ble_gatt_client
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
gatt-client.c
Go to the documentation of this file.
1 
10 /*
11  *
12  * BlueZ - Bluetooth protocol stack for Linux
13  *
14  * Copyright (C) 2014 Google Inc.
15  *
16  *
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  *
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25  * Lesser General Public License for more details.
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30  *
31  */
32 
33 #include "att.h"
34 #include "bluetooth.h"
35 #include "uuid.h"
36 #include "gatt-helpers.h"
37 #include "util.h"
38 #include "queue.h"
39 #include "gatt-db.h"
40 #include "gatt-client.h"
41 
42 #include <assert.h>
43 #include <limits.h>
44 #include <sys/uio.h>
45 
46 #ifndef MAX
47 #define MAX(a, b) ((a) > (b) ? (a) : (b))
48 #endif
49 
50 #ifndef MIN
51 #define MIN(a, b) ((a) < (b) ? (a) : (b))
52 #endif
53 
54 #define UUID_BYTES (BT_GATT_UUID_SIZE * sizeof(uint8_t))
55 
56 #define GATT_SVC_UUID 0x1801
57 #define SVC_CHNGD_UUID 0x2a05
58 
65  struct bt_att *att;
67  int ref_count;
71  void *ready_data;
72 
76 
79  void *debug_data;
80 
81  struct gatt_db *db;
82  bool in_init;
83  bool ready;
92 
94  struct queue *notify_list;
98  unsigned int disc_id;
102  unsigned int notify_id;
107  unsigned int ind_id;
112  unsigned int svc_chngd_ind_id;
122  unsigned int next_request_id;
124  unsigned int mtu_req_id;
125 };
126 
132 struct request {
139  bool removed;
143  unsigned int id;
145  unsigned int att_id;
147  void *data;
149  void (*destroy)(void *);
151 };
152 
153 static struct request *request_ref(struct request *req)
154 {
155  __sync_fetch_and_add(&req->ref_count, 1);
156 
157  return req;
158 }
159 
161 {
162  struct request *req;
163 
164  req = new0(struct request, 1);
165  if (!req)
166  return NULL;
167 
168  if (client->next_request_id < 1)
169  client->next_request_id = 1;
170 
171  queue_push_tail(client->pending_requests, req);
172  req->client = client;
173  req->id = client->next_request_id++;
174 
175  return request_ref(req);
176 }
177 
178 static void request_unref(void *data)
179 {
180  struct request *req = data;
181 
182  if (__sync_sub_and_fetch(&req->ref_count, 1))
183  return;
184 
185  if (req->destroy)
186  req->destroy(req->data);
187 
188  if (!req->removed)
190 
191  free(req);
192 }
193 
194 struct notify_chrc {
195  uint16_t value_handle;
196  uint16_t ccc_handle;
197  uint16_t properties;
198  int notify_count; /* Reference count of registered notify callbacks */
199 
200  /* Pending calls to register_notify are queued here so that they can be
201  * processed after a write that modifies the CCC descriptor.
202  */
204  unsigned int ccc_write_id;
205 };
206 
207 struct notify_data {
209  unsigned int id;
210  unsigned int att_id;
212  struct notify_chrc *chrc;
215  void *user_data;
217 };
218 
220 {
221  __sync_fetch_and_add(&notify_data->ref_count, 1);
222 
223  return notify_data;
224 }
225 
226 static void notify_data_unref(void *data)
227 {
228  struct notify_data *notify_data = data;
229 
230  if (__sync_sub_and_fetch(&notify_data->ref_count, 1))
231  return;
232 
233  if (notify_data->destroy)
234  notify_data->destroy(notify_data->user_data);
235 
236  free(notify_data);
237 }
238 
239 static void find_ccc(struct gatt_db_attribute *attr, void *user_data)
240 {
241  struct gatt_db_attribute **ccc_ptr = user_data;
242  bt_uuid_t uuid;
243 
244  if (*ccc_ptr)
245  return;
246 
248 
249  if (bt_uuid_cmp(&uuid, gatt_db_attribute_get_type(attr)))
250  return;
251 
252  *ccc_ptr = attr;
253 }
254 
256  uint16_t value_handle)
257 {
258  struct gatt_db_attribute *attr, *ccc;
259  struct notify_chrc *chrc;
260  bt_uuid_t uuid;
261  uint8_t properties;
262 
263  /* Check that chrc_value_handle belongs to a known characteristic */
264  attr = gatt_db_get_attribute(client->db, value_handle - 1);
265  if (!attr)
266  return NULL;
267 
269  if (bt_uuid_cmp(&uuid, gatt_db_attribute_get_type(attr)))
270  return NULL;
271 
272  if (!gatt_db_attribute_get_char_data(attr, NULL, NULL,
273  &properties, NULL))
274  return NULL;
275 
276  chrc = new0(struct notify_chrc, 1);
277  if (!chrc)
278  return NULL;
279 
280  chrc->reg_notify_queue = queue_new();
281  if (!chrc->reg_notify_queue) {
282  free(chrc);
283  return NULL;
284  }
285 
286  /*
287  * Find the CCC characteristic. Some characteristics that allow
288  * notifications may not have a CCC descriptor. We treat these as
289  * automatically successful.
290  */
291  ccc = NULL;
293  if (ccc)
295 
296  chrc->value_handle = value_handle;
297  chrc->properties = properties;
298 
299  queue_push_tail(client->notify_chrcs, chrc);
300 
301  return chrc;
302 }
303 
304 static void notify_chrc_free(void *data)
305 {
306  struct notify_chrc *chrc = data;
307 
309  free(chrc);
310 }
311 
312 static bool match_notify_data_id(const void *a, const void *b)
313 {
314  const struct notify_data *notify_data = a;
315  unsigned int id = PTR_TO_UINT(b);
316 
317  return notify_data->id == id;
318 }
319 
320 struct handle_range {
321  uint16_t start;
322  uint16_t end;
323 };
324 
325 static bool match_notify_data_handle_range(const void *a, const void *b)
326 {
327  const struct notify_data *notify_data = a;
328  struct notify_chrc *chrc = notify_data->chrc;
329  const struct handle_range *range = b;
330 
331  return chrc->value_handle >= range->start &&
332  chrc->value_handle <= range->end;
333 }
334 
335 static bool match_notify_chrc_handle_range(const void *a, const void *b)
336 {
337  const struct notify_chrc *chrc = a;
338  const struct handle_range *range = b;
339 
340  return chrc->value_handle >= range->start &&
341  chrc->value_handle <= range->end;
342 }
343 
345  struct bt_gatt_client *client,
346  uint16_t start_handle, uint16_t end_handle)
347 {
348  struct handle_range range;
349 
350  range.start = start_handle;
351  range.end = end_handle;
352 
354  &range, notify_data_unref);
355 }
356 
358  struct bt_gatt_client *client,
359  uint16_t start_handle, uint16_t end_handle)
360 {
361  struct handle_range range;
362 
363  range.start = start_handle;
364  range.end = end_handle;
365 
367  &range, notify_chrc_free);
368 }
369 
370 struct discovery_op;
371 
372 typedef void (*discovery_op_complete_func_t)(struct discovery_op *op,
373  bool success,
374  uint8_t att_ecode);
375 typedef void (*discovery_op_fail_func_t)(struct discovery_op *op);
376 
377 struct discovery_op {
381  struct queue *tmp_queue;
383  bool success;
384  uint16_t start;
385  uint16_t end;
389 };
390 
391 static void discovery_op_free(struct discovery_op *op)
392 {
393  queue_destroy(op->pending_svcs, NULL);
394  queue_destroy(op->pending_chrcs, free);
395  queue_destroy(op->tmp_queue, NULL);
396  free(op);
397 }
398 
400  uint16_t start, uint16_t end,
403 {
404  struct discovery_op *op;
405 
406  op = new0(struct discovery_op, 1);
407  if (!op)
408  return NULL;
409 
410  op->pending_svcs = queue_new();
411  if (!op->pending_svcs)
412  goto fail;
413 
414  op->pending_chrcs = queue_new();
415  if (!op->pending_chrcs)
416  goto fail;
417 
418  op->tmp_queue = queue_new();
419  if (!op->tmp_queue)
420  goto fail;
421 
422  op->client = client;
425  op->start = start;
426  op->end = end;
427 
428  return op;
429 
430 fail:
431  discovery_op_free(op);
432  return NULL;
433 }
434 
435 static struct discovery_op *discovery_op_ref(struct discovery_op *op)
436 {
437  __sync_fetch_and_add(&op->ref_count, 1);
438 
439  return op;
440 }
441 
442 static void discovery_op_unref(void *data)
443 {
444  struct discovery_op *op = data;
445 
446  if (__sync_sub_and_fetch(&op->ref_count, 1))
447  return;
448 
449  if (!op->success)
450  op->failure_func(op);
451 
452  discovery_op_free(op);
453 }
454 
456 {
457  if (!client->discovery_req)
458  return;
459 
461  client->discovery_req = NULL;
462 }
463 
464 static void discover_chrcs_cb(bool success, uint8_t att_ecode,
465  struct bt_gatt_result *result,
466  void *user_data);
467 
468 static void discover_incl_cb(bool success, uint8_t att_ecode,
469  struct bt_gatt_result *result, void *user_data)
470 {
471  struct discovery_op *op = user_data;
472  struct bt_gatt_client *client = op->client;
473  struct bt_gatt_iter iter;
474  struct gatt_db_attribute *attr, *tmp;
475  uint16_t handle, start, end;
476  uint128_t u128;
477  bt_uuid_t uuid;
478  char uuid_str[MAX_LEN_UUID_STR];
479  unsigned int includes_count, i;
480 
481  discovery_req_clear(client);
482 
483  if (!success) {
484  if (att_ecode == BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND)
485  goto next;
486 
487  goto failed;
488  }
489 
490  /* Get the currently processed service */
491  attr = op->cur_svc;
492  if (!attr)
493  goto failed;
494 
495  if (!result || !bt_gatt_iter_init(&iter, result))
496  goto failed;
497 
498  includes_count = bt_gatt_result_included_count(result);
499  if (includes_count == 0)
500  goto failed;
501 
502  util_debug(client->debug_callback, client->debug_data,
503  "Included services found: %u",
504  includes_count);
505 
506  for (i = 0; i < includes_count; i++) {
507  if (!bt_gatt_iter_next_included_service(&iter, &handle, &start,
508  &end, u128.data))
509  break;
510 
511  bt_uuid128_create(&uuid, u128);
512 
513  /* Log debug message */
514  bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
515  util_debug(client->debug_callback, client->debug_data,
516  "handle: 0x%04x, start: 0x%04x, end: 0x%04x,"
517  "uuid: %s", handle, start, end, uuid_str);
518 
519  tmp = gatt_db_get_attribute(client->db, start);
520  if (!tmp)
521  goto failed;
522 
523  tmp = gatt_db_service_add_included(attr, tmp);
524  if (!tmp)
525  goto failed;
526 
527  /*
528  * GATT requires that all include definitions precede
529  * characteristic declarations. Based on the order we're adding
530  * these entries, the correct handle must be assigned to the new
531  * attribute.
532  */
533  if (gatt_db_attribute_get_handle(tmp) != handle)
534  goto failed;
535  }
536 
537 next:
538  /* Move on to the next service */
539  attr = queue_pop_head(op->pending_svcs);
540  if (!attr) {
541  struct queue *tmp_queue;
542 
543  tmp_queue = op->pending_svcs;
544  op->pending_svcs = op->tmp_queue;
545  op->tmp_queue = tmp_queue;
546 
547  /*
548  * We have processed all include definitions. Move on to
549  * characteristics.
550  */
551  attr = queue_pop_head(op->pending_svcs);
552  if (!attr)
553  goto failed;
554 
555  if (!gatt_db_attribute_get_service_handles(attr, &start, &end))
556  goto failed;
557 
558  op->cur_svc = attr;
559 
561  client->att,
562  start, end,
564  discovery_op_ref(op),
566  if (client->discovery_req)
567  return;
568 
569  util_debug(client->debug_callback, client->debug_data,
570  "Failed to start characteristic discovery");
571  discovery_op_unref(op);
572  goto failed;
573  }
574 
575  queue_push_tail(op->tmp_queue, attr);
576  op->cur_svc = attr;
577  if (!gatt_db_attribute_get_service_handles(attr, &start, &end))
578  goto failed;
579 
580  if (start == end)
581  goto next;
582 
584  start, end,
586  discovery_op_ref(op),
588  if (client->discovery_req)
589  return;
590 
591  util_debug(client->debug_callback, client->debug_data,
592  "Failed to start included discovery");
593  discovery_op_unref(op);
594 
595 failed:
596  op->success = false;
597  op->complete_func(op, false, att_ecode);
598 }
599 
600 struct chrc {
601  uint16_t start_handle;
602  uint16_t end_handle;
603  uint16_t value_handle;
604  uint8_t properties;
606 };
607 
608 static void discover_descs_cb(bool success, uint8_t att_ecode,
609  struct bt_gatt_result *result,
610  void *user_data);
611 
612 static bool discover_descs(struct discovery_op *op, bool *discovering)
613 {
614  struct bt_gatt_client *client = op->client;
615  struct gatt_db_attribute *attr;
616  struct chrc *chrc_data;
617  uint16_t desc_start;
618 
619  *discovering = false;
620 
621  while ((chrc_data = queue_pop_head(op->pending_chrcs))) {
623  chrc_data->value_handle,
624  &chrc_data->uuid, 0,
625  chrc_data->properties,
626  NULL, NULL, NULL);
627 
628  if (!attr)
629  goto failed;
630 
631  if (gatt_db_attribute_get_handle(attr) !=
632  chrc_data->value_handle)
633  goto failed;
634 
635  /*
636  * check for descriptors presence, before initializing the
637  * desc_handle and avoid integer overflow during desc_handle
638  * intialization.
639  */
640  if (chrc_data->value_handle >= chrc_data->end_handle) {
641  free(chrc_data);
642  continue;
643  }
644  desc_start = chrc_data->value_handle + 1;
645 
647  client->att, desc_start,
648  chrc_data->end_handle,
650  discovery_op_ref(op),
652  if (client->discovery_req) {
653  *discovering = true;
654  goto done;
655  }
656 
657  util_debug(client->debug_callback, client->debug_data,
658  "Failed to start descriptor discovery");
659  discovery_op_unref(op);
660 
661  goto failed;
662  }
663 
664 done:
665  free(chrc_data);
666  return true;
667 
668 failed:
669  free(chrc_data);
670  return false;
671 }
672 
673 static void discover_descs_cb(bool success, uint8_t att_ecode,
674  struct bt_gatt_result *result,
675  void *user_data)
676 {
677  struct discovery_op *op = user_data;
678  struct bt_gatt_client *client = op->client;
679  struct bt_gatt_iter iter;
680  struct gatt_db_attribute *attr;
681  uint16_t handle, start, end;
682  uint128_t u128;
683  bt_uuid_t uuid;
684  char uuid_str[MAX_LEN_UUID_STR];
685  unsigned int desc_count;
686  bool discovering;
687 
688  discovery_req_clear(client);
689 
690  if (!success) {
691  if (att_ecode == BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND) {
692  success = true;
693  goto next;
694  }
695 
696  goto done;
697  }
698 
699  if (!result || !bt_gatt_iter_init(&iter, result))
700  goto failed;
701 
702  desc_count = bt_gatt_result_descriptor_count(result);
703  if (desc_count == 0)
704  goto failed;
705 
706  util_debug(client->debug_callback, client->debug_data,
707  "Descriptors found: %u", desc_count);
708 
709  while (bt_gatt_iter_next_descriptor(&iter, &handle, u128.data)) {
710  bt_uuid128_create(&uuid, u128);
711 
712  /* Log debug message */
713  bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
714  util_debug(client->debug_callback, client->debug_data,
715  "handle: 0x%04x, uuid: %s",
716  handle, uuid_str);
717 
718  attr = gatt_db_service_insert_descriptor(op->cur_svc, handle,
719  &uuid, 0, NULL, NULL,
720  NULL);
721  if (!attr)
722  goto failed;
723 
724  if (gatt_db_attribute_get_handle(attr) != handle)
725  goto failed;
726  }
727 
728 next:
729  if (!discover_descs(op, &discovering))
730  goto failed;
731 
732  if (discovering)
733  return;
734 
735  /* Done with the current service */
737 
738  attr = queue_pop_head(op->pending_svcs);
739  if (!attr)
740  goto done;
741 
742  if (!gatt_db_attribute_get_service_handles(attr, &start, &end))
743  goto failed;
744 
745  if (start == end)
746  goto next;
747 
748  /* Move on to the next service */
749  op->cur_svc = attr;
750 
752  start, end,
754  discovery_op_ref(op),
756  if (client->discovery_req)
757  return;
758 
759  util_debug(client->debug_callback, client->debug_data,
760  "Failed to start characteristic discovery");
761  discovery_op_unref(op);
762 
763 failed:
764  success = false;
765 
766 done:
767  op->success = success;
768  op->complete_func(op, success, att_ecode);
769 }
770 
771 static void discover_chrcs_cb(bool success, uint8_t att_ecode,
772  struct bt_gatt_result *result,
773  void *user_data)
774 {
775  struct discovery_op *op = user_data;
776  struct bt_gatt_client *client = op->client;
777  struct bt_gatt_iter iter;
778  struct gatt_db_attribute *attr;
779  struct chrc *chrc_data;
780  uint16_t start, end, value;
781  uint8_t properties;
782  uint128_t u128;
783  bt_uuid_t uuid;
784  char uuid_str[MAX_LEN_UUID_STR];
785  unsigned int chrc_count;
786  bool discovering;
787 
788  discovery_req_clear(client);
789 
790  if (!success) {
791  if (att_ecode == BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND) {
792  success = true;
793  goto next;
794  }
795 
796  goto done;
797  }
798 
799  if (!op->cur_svc || !result || !bt_gatt_iter_init(&iter, result))
800  goto failed;
801 
802  chrc_count = bt_gatt_result_characteristic_count(result);
803  util_debug(client->debug_callback, client->debug_data,
804  "Characteristics found: %u", chrc_count);
805 
806  if (chrc_count == 0)
807  goto failed;
808 
809  while (bt_gatt_iter_next_characteristic(&iter, &start, &end, &value,
810  &properties, u128.data)) {
811  bt_uuid128_create(&uuid, u128);
812 
813  /* Log debug message */
814  bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
815  util_debug(client->debug_callback, client->debug_data,
816  "start: 0x%04x, end: 0x%04x, value: 0x%04x, "
817  "props: 0x%02x, uuid: %s",
818  start, end, value, properties, uuid_str);
819 
820  chrc_data = new0(struct chrc, 1);
821  if (!chrc_data)
822  goto failed;
823 
824  chrc_data->start_handle = start;
825  chrc_data->end_handle = end;
826  chrc_data->value_handle = value;
827  chrc_data->properties = properties;
828  chrc_data->uuid = uuid;
829 
830  queue_push_tail(op->pending_chrcs, chrc_data);
831  }
832 
833  /*
834  * Sequentially discover descriptors for each characteristic and insert
835  * the characteristics into the database as we proceed.
836  */
837  if (!discover_descs(op, &discovering))
838  goto failed;
839 
840  if (discovering)
841  return;
842 
843 next:
844  /* Done with the current service */
846 
847  attr = queue_pop_head(op->pending_svcs);
848  if (!attr)
849  goto done;
850 
851  if (!gatt_db_attribute_get_service_handles(attr, &start, &end))
852  goto failed;
853 
854  if (start == end)
855  goto next;
856 
857  /* Move on to the next service */
858  op->cur_svc = attr;
859 
861  start, end,
863  discovery_op_ref(op),
865  if (client->discovery_req)
866  return;
867 
868  util_debug(client->debug_callback, client->debug_data,
869  "Failed to start characteristic discovery");
870  discovery_op_unref(op);
871 
872 failed:
873  success = false;
874 
875 done:
876  op->success = success;
877  op->complete_func(op, success, att_ecode);
878 }
879 
880 static void discover_secondary_cb(bool success, uint8_t att_ecode,
881  struct bt_gatt_result *result,
882  void *user_data)
883 {
884  struct discovery_op *op = user_data;
885  struct bt_gatt_client *client = op->client;
886  struct bt_gatt_iter iter;
887  struct gatt_db_attribute *attr;
888  uint16_t start, end;
889  uint128_t u128;
890  bt_uuid_t uuid;
891  char uuid_str[MAX_LEN_UUID_STR];
892 
893  discovery_req_clear(client);
894 
895  if (!success) {
896  util_debug(client->debug_callback, client->debug_data,
897  "Secondary service discovery failed."
898  " ATT ECODE: 0x%02x", att_ecode);
899  switch (att_ecode) {
902  goto next;
903  default:
904  goto done;
905  }
906  }
907 
908  if (!result || !bt_gatt_iter_init(&iter, result)) {
909  success = false;
910  goto done;
911  }
912 
913  util_debug(client->debug_callback, client->debug_data,
914  "Secondary services found: %u",
916 
917  while (bt_gatt_iter_next_service(&iter, &start, &end, u128.data)) {
918  bt_uuid128_create(&uuid, u128);
919 
920  /* Log debug message */
921  bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
922  util_debug(client->debug_callback, client->debug_data,
923  "start: 0x%04x, end: 0x%04x, uuid: %s",
924  start, end, uuid_str);
925 
926  /* Store the service */
927  attr = gatt_db_insert_service(client->db, start, &uuid, false,
928  end - start + 1);
929  if (!attr) {
930  gatt_db_clear_range(client->db, start, end);
931  attr = gatt_db_insert_service(client->db, start, &uuid,
932  false, end - start + 1);
933  if (!attr) {
934  util_debug(client->debug_callback,
935  client->debug_data,
936  "Failed to store service");
937  success = false;
938  goto done;
939  }
940  }
941 
942  /* Skip if service already active */
943  if (!gatt_db_service_get_active(attr))
944  queue_push_tail(op->pending_svcs, attr);
945  }
946 
947 next:
948  /* Sequentially discover included services */
949  attr = queue_pop_head(op->pending_svcs);
950 
951  /* Complete with success if queue is empty */
952  if (!attr) {
953  success = true;
954  goto done;
955  }
956 
957  /*
958  * Store the service in the tmp queue to be reused during
959  * characteristics discovery later.
960  */
961  queue_push_tail(op->tmp_queue, attr);
962  op->cur_svc = attr;
963 
964  if (!gatt_db_attribute_get_service_handles(attr, &start, &end)) {
965  success = false;
966  goto done;
967  }
968 
970  start, end,
972  discovery_op_ref(op),
974  if (client->discovery_req)
975  return;
976 
977  util_debug(client->debug_callback, client->debug_data,
978  "Failed to start included services discovery");
979  discovery_op_unref(op);
980 
981 done:
982  op->success = success;
983  op->complete_func(op, success, att_ecode);
984 }
985 
986 static void discover_primary_cb(bool success, uint8_t att_ecode,
987  struct bt_gatt_result *result,
988  void *user_data)
989 {
990  struct discovery_op *op = user_data;
991  struct bt_gatt_client *client = op->client;
992  struct bt_gatt_iter iter;
993  struct gatt_db_attribute *attr;
994  uint16_t start, end;
995  uint128_t u128;
996  bt_uuid_t uuid;
997  char uuid_str[MAX_LEN_UUID_STR];
998 
999  discovery_req_clear(client);
1000 
1001  if (!success) {
1002  util_debug(client->debug_callback, client->debug_data,
1003  "Primary service discovery failed."
1004  " ATT ECODE: 0x%02x", att_ecode);
1005  goto secondary;
1006  }
1007 
1008  if (!result || !bt_gatt_iter_init(&iter, result)) {
1009  success = false;
1010  goto done;
1011  }
1012 
1013  util_debug(client->debug_callback, client->debug_data,
1014  "Primary services found: %u",
1016 
1017  while (bt_gatt_iter_next_service(&iter, &start, &end, u128.data)) {
1018  bt_uuid128_create(&uuid, u128);
1019 
1020  /* Log debug message. */
1021  bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
1022  util_debug(client->debug_callback, client->debug_data,
1023  "start: 0x%04x, end: 0x%04x, uuid: %s",
1024  start, end, uuid_str);
1025 
1026  attr = gatt_db_insert_service(client->db, start, &uuid, true,
1027  end - start + 1);
1028  if (!attr) {
1029  gatt_db_clear_range(client->db, start, end);
1030  attr = gatt_db_insert_service(client->db, start, &uuid,
1031  true, end - start + 1);
1032  if (!attr) {
1033  util_debug(client->debug_callback,
1034  client->debug_data,
1035  "Failed to store service");
1036  success = false;
1037  goto done;
1038  }
1039  }
1040 
1041  /* Skip if service already active */
1042  if (!gatt_db_service_get_active(attr))
1043  queue_push_tail(op->pending_svcs, attr);
1044  }
1045 
1046 secondary:
1047  /*
1048  * Version 4.2 [Vol 1, Part A] page 101:
1049  * A secondary service is a service that provides auxiliary
1050  * functionality of a device and is referenced from at least one
1051  * primary service on the device.
1052  */
1053  if (queue_isempty(op->pending_svcs))
1054  goto done;
1055 
1056  /* Discover secondary services */
1058  NULL, op->start, op->end,
1060  discovery_op_ref(op),
1062  if (client->discovery_req)
1063  return;
1064 
1065  util_debug(client->debug_callback, client->debug_data,
1066  "Failed to start secondary service discovery");
1067  discovery_op_unref(op);
1068  success = false;
1069 
1070 done:
1071  op->success = success;
1072  op->complete_func(op, success, att_ecode);
1073 }
1074 
1075 static void notify_client_ready(struct bt_gatt_client *client, bool success,
1076  uint8_t att_ecode)
1077 {
1078  if (!client->ready_callback || client->ready)
1079  return;
1080 
1081  bt_gatt_client_ref(client);
1082  client->ready = success;
1083  client->ready_callback(success, att_ecode, client->ready_data);
1084  bt_gatt_client_unref(client);
1085 }
1086 
1087 static void exchange_mtu_cb(bool success, uint8_t att_ecode, void *user_data)
1088 {
1089  struct discovery_op *op = user_data;
1090  struct bt_gatt_client *client = op->client;
1091 
1092  op->success = success;
1093  client->mtu_req_id = 0;
1094 
1095  if (!success) {
1096  util_debug(client->debug_callback, client->debug_data,
1097  "MTU Exchange failed. ATT ECODE: 0x%02x",
1098  att_ecode);
1099 
1100  /*
1101  * BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] page 546
1102  * If the Error Response is sent by the server with the Error
1103  * Code set to RequestNot Supported , the Attribute Opcode is
1104  * not supported and the default MTU shall be used.
1105  */
1106  if (att_ecode == BT_ATT_ERROR_REQUEST_NOT_SUPPORTED)
1107  goto discover;
1108 
1109  client->in_init = false;
1110  notify_client_ready(client, success, att_ecode);
1111 
1112  return;
1113  }
1114 
1115  util_debug(client->debug_callback, client->debug_data,
1116  "MTU exchange complete, with MTU: %u",
1117  bt_att_get_mtu(client->att));
1118 
1119 discover:
1121  client->att, NULL,
1123  discovery_op_ref(op),
1125  if (client->discovery_req)
1126  return;
1127 
1128  util_debug(client->debug_callback, client->debug_data,
1129  "Failed to initiate primary service discovery");
1130 
1131  client->in_init = false;
1132  notify_client_ready(client, false, att_ecode);
1133 
1134  discovery_op_unref(op);
1135 }
1136 
1139  uint16_t start_handle;
1140  uint16_t end_handle;
1141 };
1142 
1143 static void process_service_changed(struct bt_gatt_client *client,
1144  uint16_t start_handle,
1145  uint16_t end_handle);
1146 static void service_changed_cb(uint16_t value_handle, const uint8_t *value,
1147  uint16_t length, void *user_data);
1148 
1149 static void complete_notify_request(void *data)
1150 {
1151  struct notify_data *notify_data = data;
1152 
1153  /* Increment the per-characteristic ref count of notify handlers */
1154  __sync_fetch_and_add(&notify_data->chrc->notify_count, 1);
1155 
1156  notify_data->att_id = 0;
1157  notify_data->callback(0, notify_data->user_data);
1158 }
1159 
1160 static bool notify_data_write_ccc(struct notify_data *notify_data, bool enable,
1162 {
1163  uint8_t pdu[4];
1164  unsigned int att_id;
1165 
1166  assert(notify_data->chrc->ccc_handle);
1167  memset(pdu, 0, sizeof(pdu));
1168  put_le16(notify_data->chrc->ccc_handle, pdu);
1169 
1170  if (enable) {
1171  /* Try to enable notifications and/or indications based on
1172  * whatever the characteristic supports.
1173  */
1174  if (notify_data->chrc->properties & BT_GATT_CHRC_PROP_NOTIFY)
1175  pdu[2] = 0x01;
1176 
1177  if (notify_data->chrc->properties & BT_GATT_CHRC_PROP_INDICATE)
1178  pdu[2] |= 0x02;
1179 
1180  if (!pdu[2])
1181  return false;
1182  }
1183 
1184  att_id = bt_att_send(notify_data->client->att, BT_ATT_OP_WRITE_REQ,
1185  pdu, sizeof(pdu), callback,
1186  notify_data_ref(notify_data),
1188  notify_data->chrc->ccc_write_id = notify_data->att_id = att_id;
1189 
1190  return !!att_id;
1191 }
1192 
1193 static uint8_t process_error(const void *pdu, uint16_t length)
1194 {
1195  const struct bt_att_pdu_error_rsp *error_pdu;
1196 
1197  if (!pdu || length != sizeof(struct bt_att_pdu_error_rsp))
1198  return 0;
1199 
1200  error_pdu = pdu;
1201 
1202  return error_pdu->ecode;
1203 }
1204 
1205 static void enable_ccc_callback(uint8_t opcode, const void *pdu,
1206  uint16_t length, void *user_data)
1207 {
1208  struct notify_data *notify_data = user_data;
1209  uint16_t att_ecode;
1210 
1211  assert(!notify_data->chrc->notify_count);
1212  assert(notify_data->chrc->ccc_write_id);
1213 
1214  notify_data->chrc->ccc_write_id = 0;
1215 
1216  if (opcode == BT_ATT_OP_ERROR_RSP) {
1217  att_ecode = process_error(pdu, length);
1218 
1219  /* Failed to enable. Complete the current request and move on to
1220  * the next one in the queue. If there was an error sending the
1221  * write request, then just move on to the next queued entry.
1222  */
1223  queue_remove(notify_data->client->notify_list, notify_data);
1224  notify_data->callback(att_ecode, notify_data->user_data);
1225 
1226  while ((notify_data = queue_pop_head(
1227  notify_data->chrc->reg_notify_queue))) {
1228 
1229  if (notify_data_write_ccc(notify_data, true,
1231  return;
1232  }
1233 
1234  return;
1235  }
1236 
1237  /* Success! Report success for all remaining requests. */
1238  bt_gatt_client_ref(notify_data->client);
1239 
1240  complete_notify_request(notify_data);
1241  queue_remove_all(notify_data->chrc->reg_notify_queue, NULL, NULL,
1243 
1244  bt_gatt_client_unref(notify_data->client);
1245 }
1246 
1247 static bool match_notify_chrc_value_handle(const void *a, const void *b)
1248 {
1249  const struct notify_chrc *chrc = a;
1250  uint16_t value_handle = PTR_TO_UINT(b);
1251 
1252  return chrc->value_handle == value_handle;
1253 }
1254 
1255 static unsigned int register_notify(struct bt_gatt_client *client,
1256  uint16_t handle,
1259  void *user_data,
1261 {
1262  struct notify_data *notify_data;
1263  struct notify_chrc *chrc = NULL;
1264 
1265  /* Check if a characteristic ref count has been started already */
1267  UINT_TO_PTR(handle));
1268 
1269  if (!chrc) {
1270  /*
1271  * Create an entry if the characteristic is known and has a CCC
1272  * descriptor.
1273  */
1274  chrc = notify_chrc_create(client, handle);
1275  if (!chrc)
1276  return 0;
1277  }
1278 
1279  /* Fail if we've hit the maximum allowed notify sessions */
1280  if (chrc->notify_count == INT_MAX)
1281  return 0;
1282 
1283  notify_data = new0(struct notify_data, 1);
1284  if (!notify_data)
1285  return 0;
1286 
1287  notify_data->client = client;
1288  notify_data->ref_count = 1;
1289  notify_data->chrc = chrc;
1290  notify_data->callback = callback;
1291  notify_data->notify = notify;
1292  notify_data->user_data = user_data;
1293  notify_data->destroy = destroy;
1294 
1295  /* Add the handler to the bt_gatt_client's general list */
1296  queue_push_tail(client->notify_list, notify_data);
1297 
1298  /* Assign an ID to the handler. */
1299  if (client->next_reg_id < 1)
1300  client->next_reg_id = 1;
1301 
1302  notify_data->id = client->next_reg_id++;
1303 
1304  /*
1305  * If a write to the CCC descriptor is in progress, then queue this
1306  * request.
1307  */
1308  if (chrc->ccc_write_id) {
1309  queue_push_tail(chrc->reg_notify_queue, notify_data);
1310  return notify_data->id;
1311  }
1312 
1313  /*
1314  * If the ref count is not zero, then notifications are already enabled.
1315  */
1316  if (chrc->notify_count > 0 || !chrc->ccc_handle) {
1317  complete_notify_request(notify_data);
1318  return notify_data->id;
1319  }
1320 
1321  /* Write to the CCC descriptor */
1322  if (!notify_data_write_ccc(notify_data, true, enable_ccc_callback)) {
1323  queue_remove(client->notify_list, notify_data);
1324  free(notify_data);
1325  return 0;
1326  }
1327 
1328  return notify_data->id;
1329 }
1330 
1331 static void get_first_attribute(struct gatt_db_attribute *attrib,
1332  void *user_data)
1333 {
1334  struct gatt_db_attribute **stored = user_data;
1335 
1336  if (*stored)
1337  return;
1338 
1339  *stored = attrib;
1340 }
1341 
1342 static void service_changed_register_cb(uint16_t att_ecode, void *user_data)
1343 {
1344  bool success;
1345  struct bt_gatt_client *client = user_data;
1346 
1347  if (att_ecode) {
1348  util_debug(client->debug_callback, client->debug_data,
1349  "Failed to register handler for \"Service Changed\"");
1350  success = false;
1351  client->svc_chngd_ind_id = 0;
1352  goto done;
1353  }
1354 
1355  client->svc_chngd_registered = true;
1356  success = true;
1357  util_debug(client->debug_callback, client->debug_data,
1358  "Registered handler for \"Service Changed\": %u",
1359  client->svc_chngd_ind_id);
1360 
1361 done:
1362  notify_client_ready(client, success, att_ecode);
1363 }
1364 
1366 {
1367  bt_uuid_t uuid;
1368  struct gatt_db_attribute *attr = NULL;
1369 
1371 
1372  if (client->svc_chngd_ind_id)
1373  return true;
1374 
1375  gatt_db_find_by_type(client->db, 0x0001, 0xffff, &uuid,
1376  get_first_attribute, &attr);
1377  if (!attr)
1378  return true;
1379 
1380  /*
1381  * Register an indication handler for the "Service Changed"
1382  * characteristic and report ready only if the handler is registered
1383  * successfully.
1384  */
1385  client->svc_chngd_ind_id = register_notify(client,
1389  client, NULL);
1390 
1391  return client->svc_chngd_ind_id ? true : false;
1392 }
1393 
1394 static void service_changed_complete(struct discovery_op *op, bool success,
1395  uint8_t att_ecode)
1396 {
1397  struct bt_gatt_client *client = op->client;
1398  struct service_changed_op *next_sc_op;
1399  uint16_t start_handle = op->start;
1400  uint16_t end_handle = op->end;
1401 
1402  client->in_svc_chngd = false;
1403 
1404  if (!success && att_ecode != BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND) {
1405  util_debug(client->debug_callback, client->debug_data,
1406  "Failed to discover services within changed range - "
1407  "error: 0x%02x", att_ecode);
1408 
1409  gatt_db_clear_range(client->db, start_handle, end_handle);
1410  }
1411 
1412  /* Notify the upper layer of changed services */
1413  if (client->svc_chngd_callback)
1414  client->svc_chngd_callback(start_handle, end_handle,
1415  client->svc_chngd_data);
1416 
1417  /* Process any queued events */
1418  next_sc_op = queue_pop_head(client->svc_chngd_queue);
1419  if (next_sc_op) {
1420  process_service_changed(client, next_sc_op->start_handle,
1421  next_sc_op->end_handle);
1422  free(next_sc_op);
1423  return;
1424  }
1425 
1426  if (register_service_changed(client))
1427  return;
1428 
1429  util_debug(client->debug_callback, client->debug_data,
1430  "Failed to re-register handler for \"Service Changed\"");
1431 }
1432 
1433 static void service_changed_failure(struct discovery_op *op)
1434 {
1435  struct bt_gatt_client *client = op->client;
1436 
1437  gatt_db_clear_range(client->db, op->start, op->end);
1438 }
1439 
1441  uint16_t start_handle,
1442  uint16_t end_handle)
1443 {
1444  struct discovery_op *op;
1445 
1446  /* Invalidate and remove all effected notify callbacks */
1447  gatt_client_remove_all_notify_in_range(client, start_handle,
1448  end_handle);
1449  gatt_client_remove_notify_chrcs_in_range(client, start_handle,
1450  end_handle);
1451 
1452  /* Remove all services that overlap the modified range since we'll
1453  * rediscover them
1454  */
1455  gatt_db_clear_range(client->db, start_handle, end_handle);
1456 
1457  op = discovery_op_create(client, start_handle, end_handle,
1460  if (!op)
1461  goto fail;
1462 
1464  NULL, start_handle, end_handle,
1466  discovery_op_ref(op),
1468  if (client->discovery_req) {
1469  client->in_svc_chngd = true;
1470  return;
1471  }
1472 
1473  discovery_op_free(op);
1474 
1475 fail:
1476  util_debug(client->debug_callback, client->debug_data,
1477  "Failed to initiate service discovery"
1478  " after Service Changed");
1479 }
1480 
1481 static void service_changed_cb(uint16_t value_handle, const uint8_t *value,
1482  uint16_t length, void *user_data)
1483 {
1484  struct bt_gatt_client *client = user_data;
1485  struct service_changed_op *op;
1486  uint16_t start, end;
1487 
1488  if (length != 4)
1489  return;
1490 
1491  start = get_le16(value);
1492  end = get_le16(value + 2);
1493 
1494  if (start > end) {
1495  util_debug(client->debug_callback, client->debug_data,
1496  "Service Changed received with invalid handles");
1497  return;
1498  }
1499 
1500  util_debug(client->debug_callback, client->debug_data,
1501  "Service Changed received - start: 0x%04x end: 0x%04x",
1502  start, end);
1503 
1504  if (!client->in_svc_chngd) {
1505  process_service_changed(client, start, end);
1506  return;
1507  }
1508 
1509  op = new0(struct service_changed_op, 1);
1510  if (!op)
1511  return;
1512 
1513  op->start_handle = start;
1514  op->end_handle = end;
1515 
1516  queue_push_tail(client->svc_chngd_queue, op);
1517 }
1518 
1519 static void init_complete(struct discovery_op *op, bool success,
1520  uint8_t att_ecode)
1521 {
1522  struct bt_gatt_client *client = op->client;
1523 
1524  client->in_init = false;
1525 
1526  if (!success)
1527  goto fail;
1528 
1529  if (register_service_changed(client))
1530  goto done;
1531 
1532  util_debug(client->debug_callback, client->debug_data,
1533  "Failed to register handler for \"Service Changed\"");
1534  success = false;
1535 
1536 fail:
1537  util_debug(client->debug_callback, client->debug_data,
1538  "Failed to initialize gatt-client");
1539 
1540  op->success = false;
1541 
1542 done:
1543  notify_client_ready(client, success, att_ecode);
1544 }
1545 
1546 static void init_fail(struct discovery_op *op)
1547 {
1548  struct bt_gatt_client *client = op->client;
1549 
1550  gatt_db_clear(client->db);
1551 }
1552 
1553 static bool gatt_client_init(struct bt_gatt_client *client, uint16_t mtu)
1554 {
1555  struct discovery_op *op;
1556 
1557  if (client->in_init || client->ready)
1558  return false;
1559 
1560  op = discovery_op_create(client, 0x0001, 0xffff, init_complete,
1561  init_fail);
1562  if (!op)
1563  return false;
1564 
1565  /* Configure the MTU */
1566  client->mtu_req_id = bt_gatt_exchange_mtu(client->att,
1567  MAX(BT_ATT_DEFAULT_LE_MTU, mtu),
1569  discovery_op_ref(op),
1571  if (!client->mtu_req_id) {
1572  discovery_op_free(op);
1573  return false;
1574  }
1575 
1576  client->in_init = true;
1577 
1578  return true;
1579 }
1580 
1581 struct pdu_data {
1582  const void *pdu;
1583  uint16_t length;
1584 };
1585 
1586 static void disable_ccc_callback(uint8_t opcode, const void *pdu,
1587  uint16_t length, void *user_data)
1588 {
1589  struct notify_data *notify_data = user_data;
1590  struct notify_data *next_data;
1591 
1592  assert(!notify_data->chrc->notify_count);
1593  assert(notify_data->chrc->ccc_write_id);
1594 
1595  notify_data->chrc->ccc_write_id = 0;
1596 
1597  /* This is a best effort procedure, so ignore errors and process any
1598  * queued requests.
1599  */
1600  while (1) {
1601  next_data = queue_pop_head(notify_data->chrc->reg_notify_queue);
1602  if (!next_data || notify_data_write_ccc(notify_data, true,
1604  return;
1605  }
1606 }
1607 
1608 static void complete_unregister_notify(void *data)
1609 {
1610  struct notify_data *notify_data = data;
1611 
1612  /*
1613  * If a procedure to enable the CCC is still pending, then cancel it and
1614  * return.
1615  */
1616  if (notify_data->att_id) {
1617  bt_att_cancel(notify_data->client->att, notify_data->att_id);
1618  goto done;
1619  }
1620 
1621  if (__sync_sub_and_fetch(&notify_data->chrc->notify_count, 1) ||
1622  !notify_data->chrc->ccc_handle)
1623  goto done;
1624 
1625  if (notify_data_write_ccc(notify_data, false, disable_ccc_callback))
1626  return;
1627 
1628 done:
1629  notify_data_unref(notify_data);
1630 }
1631 
1632 static void notify_handler(void *data, void *user_data)
1633 {
1634  struct notify_data *notify_data = data;
1635  struct pdu_data *pdu_data = user_data;
1636  uint16_t value_handle;
1637  const uint8_t *value = NULL;
1638 
1639  value_handle = get_le16(pdu_data->pdu);
1640 
1641  if (notify_data->chrc->value_handle != value_handle)
1642  return;
1643 
1644  if (pdu_data->length > 2)
1645  value = pdu_data->pdu + 2;
1646 
1647  /*
1648  * Even if the notify data has a pending ATT request to write to the
1649  * CCC, there is really no reason not to notify the handlers.
1650  */
1651  if (notify_data->notify)
1652  notify_data->notify(value_handle, value, pdu_data->length - 2,
1653  notify_data->user_data);
1654 }
1655 
1656 static void notify_cb(uint8_t opcode, const void *pdu, uint16_t length,
1657  void *user_data)
1658 {
1659  struct bt_gatt_client *client = user_data;
1660  struct pdu_data pdu_data;
1661 
1662  bt_gatt_client_ref(client);
1663 
1664  memset(&pdu_data, 0, sizeof(pdu_data));
1665  pdu_data.pdu = pdu;
1666  pdu_data.length = length;
1667 
1668  queue_foreach(client->notify_list, notify_handler, &pdu_data);
1669 
1670  if (opcode == BT_ATT_OP_HANDLE_VAL_IND)
1671  bt_att_send(client->att, BT_ATT_OP_HANDLE_VAL_CONF, NULL, 0,
1672  NULL, NULL, NULL);
1673 
1674  bt_gatt_client_unref(client);
1675 }
1676 
1677 static void notify_data_cleanup(void *data)
1678 {
1679  struct notify_data *notify_data = data;
1680 
1681  if (notify_data->att_id)
1682  bt_att_cancel(notify_data->client->att, notify_data->att_id);
1683 
1684  notify_data_unref(notify_data);
1685 }
1686 
1688 {
1689  bt_gatt_client_cancel_all(client);
1690 
1692 
1693  if (client->ready_destroy)
1694  client->ready_destroy(client->ready_data);
1695 
1696  if (client->debug_destroy)
1697  client->debug_destroy(client->debug_data);
1698 
1699  if (client->att) {
1700  bt_att_unregister_disconnect(client->att, client->disc_id);
1701  bt_att_unregister(client->att, client->notify_id);
1702  bt_att_unregister(client->att, client->ind_id);
1703  bt_att_unref(client->att);
1704  }
1705 
1706  gatt_db_unref(client->db);
1707 
1708  queue_destroy(client->svc_chngd_queue, free);
1712 
1713  free(client);
1714 }
1715 
1716 static void att_disconnect_cb(int err, void *user_data)
1717 {
1718  struct bt_gatt_client *client = user_data;
1719  bool in_init = client->in_init;
1720 
1721  client->disc_id = 0;
1722 
1723  bt_att_unref(client->att);
1724  client->att = NULL;
1725 
1726  client->in_init = false;
1727  client->ready = false;
1728 
1729  if (in_init)
1730  notify_client_ready(client, false, 0);
1731 }
1732 
1734  struct bt_att *att,
1735  uint16_t mtu)
1736 {
1737  struct bt_gatt_client *client;
1738 
1739  if (!att || !db)
1740  return NULL;
1741 
1742  client = new0(struct bt_gatt_client, 1);
1743  if (!client)
1744  return NULL;
1745 
1747  client, NULL);
1748  if (!client->disc_id)
1749  goto fail;
1750 
1751  client->long_write_queue = queue_new();
1752  if (!client->long_write_queue)
1753  goto fail;
1754 
1755  client->svc_chngd_queue = queue_new();
1756  if (!client->svc_chngd_queue)
1757  goto fail;
1758 
1759  client->notify_list = queue_new();
1760  if (!client->notify_list)
1761  goto fail;
1762 
1763  client->notify_chrcs = queue_new();
1764  if (!client->notify_chrcs)
1765  goto fail;
1766 
1767  client->pending_requests = queue_new();
1768  if (!client->pending_requests)
1769  goto fail;
1770 
1772  notify_cb, client, NULL);
1773  if (!client->notify_id)
1774  goto fail;
1775 
1777  notify_cb, client, NULL);
1778  if (!client->ind_id)
1779  goto fail;
1780 
1781  client->att = bt_att_ref(att);
1782  client->db = gatt_db_ref(db);
1783 
1784  if (!gatt_client_init(client, mtu))
1785  goto fail;
1786 
1787  return bt_gatt_client_ref(client);
1788 
1789 fail:
1790  bt_gatt_client_free(client);
1791  return NULL;
1792 }
1793 
1795 {
1796  if (!client)
1797  return NULL;
1798 
1799  __sync_fetch_and_add(&client->ref_count, 1);
1800 
1801  return client;
1802 }
1803 
1805 {
1806  if (!client)
1807  return;
1808 
1809  if (__sync_sub_and_fetch(&client->ref_count, 1))
1810  return;
1811 
1812  bt_gatt_client_free(client);
1813 }
1814 
1816 {
1817  return (client && client->ready);
1818 }
1819 
1821  bt_gatt_client_callback_t callback,
1822  void *user_data,
1824 {
1825  if (!client)
1826  return false;
1827 
1828  if (client->ready_destroy)
1829  client->ready_destroy(client->ready_data);
1830 
1831  client->ready_callback = callback;
1832  client->ready_destroy = destroy;
1833  client->ready_data = user_data;
1834 
1835  return true;
1836 }
1837 
1840  void *user_data,
1842 {
1843  if (!client)
1844  return false;
1845 
1846  if (client->svc_chngd_destroy)
1847  client->svc_chngd_destroy(client->svc_chngd_data);
1848 
1849  client->svc_chngd_callback = callback;
1850  client->svc_chngd_destroy = destroy;
1851  client->svc_chngd_data = user_data;
1852 
1853  return true;
1854 }
1855 
1857  bt_gatt_client_debug_func_t callback,
1858  void *user_data,
1860  if (!client)
1861  return false;
1862 
1863  if (client->debug_destroy)
1864  client->debug_destroy(client->debug_data);
1865 
1866  client->debug_callback = callback;
1867  client->debug_destroy = destroy;
1868  client->debug_data = user_data;
1869 
1870  return true;
1871 }
1872 
1874 {
1875  if (!client || !client->att)
1876  return 0;
1877 
1878  return bt_att_get_mtu(client->att);
1879 }
1880 
1882 {
1883  if (!client || !client->db)
1884  return NULL;
1885 
1886  return client->db;
1887 }
1888 
1889 static bool match_req_id(const void *a, const void *b)
1890 {
1891  const struct request *req = a;
1892  unsigned int id = PTR_TO_UINT(b);
1893 
1894  return req->id == id;
1895 }
1896 
1897 static void cancel_long_write_cb(uint8_t opcode, const void *pdu, uint16_t len,
1898  void *user_data)
1899 {
1900  struct bt_gatt_client *client = user_data;
1901 
1902  if (queue_isempty(client->long_write_queue))
1903  client->in_long_write = false;
1904 }
1905 
1907  struct request *req)
1908 {
1909  uint8_t pdu = 0x00;
1910 
1911  /*
1912  * att_id == 0 means that request has been queued and no prepare write
1913  * has been sent so far.Let's just remove if from the queue.
1914  * Otherwise execute write needs to be send.
1915  */
1916  if (!req->att_id)
1917  return queue_remove(client->long_write_queue, req);
1918 
1919  return !!bt_att_send(client->att, BT_ATT_OP_EXEC_WRITE_REQ, &pdu,
1920  sizeof(pdu),
1922  client, NULL);
1923 
1924 }
1925 
1926 static void cancel_prep_write_cb(uint8_t opcode, const void *pdu, uint16_t len,
1927  void *user_data)
1928 {
1929  struct request *req = user_data;
1930  struct bt_gatt_client *client = req->client;
1931 
1932  client->reliable_write_session_id = 0;
1933 }
1934 
1936  struct request *req)
1937 {
1938  uint8_t pdu = 0x00;
1939 
1940  return !!bt_att_send(client->att, BT_ATT_OP_EXEC_WRITE_REQ, &pdu,
1941  sizeof(pdu),
1943  req, request_unref);
1944 }
1945 
1946 static bool cancel_request(struct request *req)
1947 {
1948  req->removed = true;
1949 
1950  if (req->long_write)
1951  return cancel_long_write_req(req->client, req);
1952 
1953  if (req->prep_write)
1954  return cancel_prep_write_session(req->client, req);
1955 
1956  return bt_att_cancel(req->client->att, req->att_id);
1957 }
1958 
1959 bool bt_gatt_client_cancel(struct bt_gatt_client *client, unsigned int id)
1960 {
1961  struct request *req;
1962 
1963  if (!client || !id || !client->att)
1964  return false;
1965 
1967  UINT_TO_PTR(id));
1968  if (!req)
1969  return false;
1970 
1971  return cancel_request(req);
1972 }
1973 
1975 {
1976  if (!client || !client->att)
1977  return false;
1978 
1979  queue_remove_all(client->pending_requests, NULL, NULL,
1981 
1982  if (client->discovery_req) {
1985  client->discovery_req = NULL;
1986  }
1987 
1988  if (client->mtu_req_id)
1989  bt_att_cancel(client->att, client->mtu_req_id);
1990 
1991  return true;
1992 }
1993 
1994 struct read_op {
1996  void *user_data;
1998 };
1999 
2000 static void destroy_read_op(void *data)
2001 {
2002  struct read_op *op = data;
2003 
2004  if (op->destroy)
2005  op->destroy(op->user_data);
2006 
2007  free(op);
2008 }
2009 
2010 static void read_cb(uint8_t opcode, const void *pdu, uint16_t length,
2011  void *user_data)
2012 {
2013  struct request *req = user_data;
2014  struct read_op *op = req->data;
2015  bool success;
2016  uint8_t att_ecode = 0;
2017  const uint8_t *value = NULL;
2018  uint16_t value_len = 0;
2019 
2020  if (opcode == BT_ATT_OP_ERROR_RSP) {
2021  success = false;
2022  att_ecode = process_error(pdu, length);
2023  goto done;
2024  }
2025 
2026  if (opcode != BT_ATT_OP_READ_RSP || (!pdu && length)) {
2027  success = false;
2028  goto done;
2029  }
2030 
2031  success = true;
2032  value_len = length;
2033  if (value_len)
2034  value = pdu;
2035 
2036 done:
2037  if (op->callback)
2038  op->callback(success, att_ecode, value, length, op->user_data);
2039 }
2040 
2051  uint16_t value_handle,
2053  void *user_data,
2055 {
2056  struct request *req;
2057  struct read_op *op;
2058  uint8_t pdu[2];
2059 
2060  if (!client)
2061  return 0;
2062 
2063  op = new0(struct read_op, 1);
2064  if (!op)
2065  return 0;
2066 
2067  req = request_create(client);
2068  if (!req) {
2069  free(op);
2070  return 0;
2071  }
2072 
2073  op->callback = callback;
2074  op->user_data = user_data;
2075  op->destroy = destroy;
2076 
2077  req->data = op;
2078  req->destroy = destroy_read_op;
2079 
2080  put_le16(value_handle, pdu);
2081 
2082  req->att_id = bt_att_send(client->att, BT_ATT_OP_READ_REQ,
2083  pdu, sizeof(pdu),
2084  read_cb, req,
2085  request_unref);
2086  if (!req->att_id) {
2087  op->destroy = NULL;
2088  request_unref(req);
2089  return 0;
2090  }
2091 
2092  return req->id;
2093 }
2094 
2095 static void read_multiple_cb(uint8_t opcode, const void *pdu, uint16_t length,
2096  void *user_data)
2097 {
2098  struct request *req = user_data;
2099  struct read_op *op = req->data;
2100  uint8_t att_ecode;
2101  bool success;
2102 
2103  if (opcode != BT_ATT_OP_READ_MULT_RSP || (!pdu && length)) {
2104  success = false;
2105 
2106  if (opcode == BT_ATT_OP_ERROR_RSP)
2107  att_ecode = process_error(pdu, length);
2108  else
2109  att_ecode = 0;
2110 
2111  pdu = NULL;
2112  length = 0;
2113  } else {
2114  success = true;
2115  att_ecode = 0;
2116  }
2117 
2118  if (op->callback)
2119  op->callback(success, att_ecode, pdu, length, op->user_data);
2120 }
2121 
2123  uint16_t *handles, uint8_t num_handles,
2125  void *user_data,
2127 {
2128  uint8_t pdu[num_handles * 2];
2129  struct request *req;
2130  struct read_op *op;
2131  int i;
2132 
2133  if (!client)
2134  return 0;
2135 
2136  if (num_handles < 2)
2137  return 0;
2138 
2139  if (num_handles * 2 > bt_att_get_mtu(client->att) - 1)
2140  return 0;
2141 
2142  op = new0(struct read_op, 1);
2143  if (!op)
2144  return 0;
2145 
2146  req = request_create(client);
2147  if (!req) {
2148  free(op);
2149  return 0;
2150  }
2151 
2152  op->callback = callback;
2153  op->user_data = user_data;
2154  op->destroy = destroy;
2155 
2156  req->data = op;
2157  req->destroy = destroy_read_op;
2158 
2159  for (i = 0; i < num_handles; i++)
2160  put_le16(handles[i], pdu + (2 * i));
2161 
2163  pdu, sizeof(pdu),
2164  read_multiple_cb, req,
2165  request_unref);
2166  if (!req->att_id) {
2167  op->destroy = NULL;
2168  request_unref(req);
2169  return 0;
2170  }
2171 
2172  return req->id;
2173 }
2174 
2178  uint16_t value_handle;
2179  uint16_t offset;
2180  struct iovec iov;
2182  void *user_data;
2184 };
2185 
2186 static void destroy_read_long_op(void *data)
2187 {
2188  struct read_long_op *op = data;
2189 
2190  if (op->destroy)
2191  op->destroy(op->user_data);
2192 
2193  free(op->iov.iov_base);
2194  free(op);
2195 }
2196 
2197 static bool append_chunk(struct read_long_op *op, const uint8_t *data,
2198  uint16_t len)
2199 {
2200  void *buf;
2201 
2202  /* Truncate if the data would exceed maximum length */
2203  if (op->offset + len > BT_ATT_MAX_VALUE_LEN)
2204  len = BT_ATT_MAX_VALUE_LEN - op->offset;
2205 
2206  buf = realloc(op->iov.iov_base, op->iov.iov_len + len);
2207  if (!buf)
2208  return false;
2209 
2210  op->iov.iov_base = buf;
2211 
2212  memcpy(op->iov.iov_base + op->iov.iov_len, data, len);
2213 
2214  op->iov.iov_len += len;
2215  op->offset += len;
2216 
2217  return true;
2218 }
2219 
2220 static void read_long_cb(uint8_t opcode, const void *pdu,
2221  uint16_t length, void *user_data)
2222 {
2223  struct request *req = user_data;
2224  struct read_long_op *op = req->data;
2225  bool success;
2226  uint8_t att_ecode = 0;
2227 
2228  if (opcode == BT_ATT_OP_ERROR_RSP) {
2229  success = false;
2230  att_ecode = process_error(pdu, length);
2231  goto done;
2232  }
2233 
2234  if (opcode != BT_ATT_OP_READ_BLOB_RSP || (!pdu && length)) {
2235  success = false;
2236  goto done;
2237  }
2238 
2239  if (!length)
2240  goto success;
2241 
2242  if (!append_chunk(op, pdu, length)) {
2243  success = false;
2244  goto done;
2245  }
2246 
2247  if (op->offset >= BT_ATT_MAX_VALUE_LEN)
2248  goto success;
2249 
2250  if (length >= bt_att_get_mtu(op->client->att) - 1) {
2251  uint8_t pdu[4];
2252 
2253  put_le16(op->value_handle, pdu);
2254  put_le16(op->offset, pdu + 2);
2255 
2256  req->att_id = bt_att_send(op->client->att,
2258  pdu, sizeof(pdu),
2259  read_long_cb,
2260  request_ref(req),
2261  request_unref);
2262  if (req->att_id)
2263  return;
2264 
2265  request_unref(req);
2266  success = false;
2267  goto done;
2268  }
2269 
2270 success:
2271  success = true;
2272 
2273 done:
2274  if (op->callback)
2275  op->callback(success, att_ecode, op->iov.iov_base,
2276  op->iov.iov_len, op->user_data);
2277 }
2278 
2280  uint16_t value_handle, uint16_t offset,
2282  void *user_data,
2284 {
2285  struct request *req;
2286  struct read_long_op *op;
2287  uint8_t pdu[4];
2288 
2289  if (!client)
2290  return 0;
2291 
2292  op = new0(struct read_long_op, 1);
2293  if (!op)
2294  return 0;
2295 
2296  req = request_create(client);
2297  if (!req) {
2298  free(op);
2299  return 0;
2300  }
2301 
2302  op->client = client;
2303  op->value_handle = value_handle;
2304  op->offset = offset;
2305  op->callback = callback;
2306  op->user_data = user_data;
2307  op->destroy = destroy;
2308 
2309  req->data = op;
2311 
2312  put_le16(value_handle, pdu);
2313  put_le16(offset, pdu + 2);
2314 
2316  pdu, sizeof(pdu),
2317  read_long_cb, req,
2318  request_unref);
2319  if (!req->att_id) {
2320  op->destroy = NULL;
2321  request_unref(req);
2322  return 0;
2323  }
2324 
2325  return req->id;
2326 }
2327 
2329  struct bt_gatt_client *client,
2330  uint16_t value_handle,
2331  bool signed_write,
2332  const uint8_t *value, uint16_t length) {
2333  uint8_t pdu[2 + length];
2334  struct request *req;
2335  int security;
2336  uint8_t op;
2337 
2338  if (!client)
2339  return 0;
2340 
2341  req = request_create(client);
2342  if (!req)
2343  return 0;
2344 
2345  /* Only use signed write if unencrypted */
2346  if (signed_write) {
2347  security = bt_att_get_security(client->att);
2348  op = security > BT_SECURITY_LOW ? BT_ATT_OP_WRITE_CMD :
2350  } else
2351  op = BT_ATT_OP_WRITE_CMD;
2352 
2353  put_le16(value_handle, pdu);
2354  memcpy(pdu + 2, value, length);
2355 
2356  req->att_id = bt_att_send(client->att, op, pdu, sizeof(pdu), NULL, req,
2357  request_unref);
2358  if (!req->att_id) {
2359  request_unref(req);
2360  return 0;
2361  }
2362 
2363  return req->id;
2364 }
2365 
2366 struct write_op {
2369  void *user_data;
2371 };
2372 
2373 static void destroy_write_op(void *data)
2374 {
2375  struct write_op *op = data;
2376 
2377  if (op->destroy)
2378  op->destroy(op->user_data);
2379 
2380  free(op);
2381 }
2382 
2383 static void write_cb(uint8_t opcode, const void *pdu, uint16_t length,
2384  void *user_data)
2385 {
2386  struct request *req = user_data;
2387  struct write_op *op = req->data;
2388  bool success = true;
2389  uint8_t att_ecode = 0;
2390 
2391  if (opcode == BT_ATT_OP_ERROR_RSP) {
2392  success = false;
2393  att_ecode = process_error(pdu, length);
2394  goto done;
2395  }
2396 
2397  if (opcode != BT_ATT_OP_WRITE_RSP || pdu || length)
2398  success = false;
2399 
2400 done:
2401  if (op->callback)
2402  op->callback(success, att_ecode, op->user_data);
2403 }
2404 
2406  uint16_t value_handle,
2407  const uint8_t *value, uint16_t length,
2409  void *user_data,
2411 {
2412  struct request *req;
2413  struct write_op *op;
2414  uint8_t pdu[2 + length];
2415 
2416  if (!client)
2417  return 0;
2418 
2419  op = new0(struct write_op, 1);
2420  if (!op)
2421  return 0;
2422 
2423  req = request_create(client);
2424  if (!req) {
2425  free(op);
2426  return 0;
2427  }
2428 
2429  op->callback = callback;
2430  op->user_data = user_data;
2431  op->destroy = destroy;
2432 
2433  req->data = op;
2434  req->destroy = destroy_write_op;
2435 
2436  put_le16(value_handle, pdu);
2437  memcpy(pdu + 2, value, length);
2438 
2439  req->att_id = bt_att_send(client->att, BT_ATT_OP_WRITE_REQ,
2440  pdu, sizeof(pdu),
2441  write_cb, req,
2442  request_unref);
2443  if (!req->att_id) {
2444  op->destroy = NULL;
2445  request_unref(req);
2446  return 0;
2447  }
2448 
2449  return req->id;
2450 }
2451 
2454  bool reliable;
2455  bool success;
2456  uint8_t att_ecode;
2458  uint16_t value_handle;
2459  uint8_t *value;
2460  uint16_t length;
2461  uint16_t offset;
2462  uint16_t index;
2463  uint16_t cur_length;
2465  void *user_data;
2467 };
2468 
2469 static void long_write_op_free(void *data)
2470 {
2471  struct long_write_op *op = data;
2472 
2473  if (op->destroy)
2474  op->destroy(op->user_data);
2475 
2476  free(op->value);
2477  free(op);
2478 }
2479 
2480 static void prepare_write_cb(uint8_t opcode, const void *pdu, uint16_t length,
2481  void *user_data);
2482 static void complete_write_long_op(struct request *req, bool success,
2483  uint8_t att_ecode, bool reliable_error);
2484 
2485 static void handle_next_prep_write(struct request *req)
2486 {
2487  struct long_write_op *op = req->data;
2488  bool success = true;
2489  uint8_t *pdu;
2490 
2491  pdu = malloc(op->cur_length + 4);
2492  if (!pdu) {
2493  success = false;
2494  goto done;
2495  }
2496 
2497  put_le16(op->value_handle, pdu);
2498  put_le16(op->offset + op->index, pdu + 2);
2499  memcpy(pdu + 4, op->value + op->index, op->cur_length);
2500 
2502  pdu, op->cur_length + 4,
2504  request_ref(req),
2505  request_unref);
2506  if (!req->att_id) {
2507  request_unref(req);
2508  success = false;
2509  }
2510 
2511  free(pdu);
2512 
2513  /* If so far successful, then the operation should continue.
2514  * Otherwise, there was an error and the procedure should be
2515  * completed.
2516  */
2517  if (success)
2518  return;
2519 
2520 done:
2521  complete_write_long_op(req, success, 0, false);
2522 }
2523 
2525 {
2526  struct request *req;
2527 
2528  if (queue_isempty(client->long_write_queue)) {
2529  client->in_long_write = false;
2530  return;
2531  }
2532 
2533  req = queue_pop_head(client->long_write_queue);
2534  if (!req)
2535  return;
2536 
2538 
2539  /*
2540  * send_next_prep_write adds an extra ref. Unref here to clean up if
2541  * necessary, since we also added a ref before pushing to the queue.
2542  */
2543  request_unref(req);
2544 }
2545 
2546 static void execute_write_cb(uint8_t opcode, const void *pdu, uint16_t length,
2547  void *user_data)
2548 {
2549  struct request *req = user_data;
2550  struct long_write_op *op = req->data;
2551  bool success = op->success;
2552  uint8_t att_ecode = op->att_ecode;
2553 
2554  if (opcode == BT_ATT_OP_ERROR_RSP) {
2555  success = false;
2556  att_ecode = process_error(pdu, length);
2557  } else if (opcode != BT_ATT_OP_EXEC_WRITE_RSP || pdu || length)
2558  success = false;
2559 
2561 
2562  if (op->callback)
2563  op->callback(success, op->reliable_error, att_ecode,
2564  op->user_data);
2565 
2567 
2569 }
2570 
2571 static void complete_write_long_op(struct request *req, bool success,
2572  uint8_t att_ecode, bool reliable_error)
2573 {
2574  struct long_write_op *op = req->data;
2575  uint8_t pdu;
2576 
2577  op->success = success;
2578  op->att_ecode = att_ecode;
2580 
2581  if (success)
2582  pdu = 0x01; /* Write */
2583  else
2584  pdu = 0x00; /* Cancel */
2585 
2587  &pdu, sizeof(pdu),
2589  request_ref(req),
2590  request_unref);
2591  if (req->att_id)
2592  return;
2593 
2594  request_unref(req);
2595  success = false;
2596 
2598 
2599  if (op->callback)
2600  op->callback(success, reliable_error, att_ecode, op->user_data);
2601 
2603 
2605 }
2606 
2607 static void prepare_write_cb(uint8_t opcode, const void *pdu, uint16_t length,
2608  void *user_data)
2609 {
2610  struct request *req = user_data;
2611  struct long_write_op *op = req->data;
2612  bool success = true;
2613  bool reliable_error = false;
2614  uint8_t att_ecode = 0;
2615  uint16_t next_index;
2616 
2617  if (opcode == BT_ATT_OP_ERROR_RSP) {
2618  success = false;
2619  att_ecode = process_error(pdu, length);
2620  goto done;
2621  }
2622 
2623  if (opcode != BT_ATT_OP_PREP_WRITE_RSP) {
2624  success = false;
2625  goto done;
2626  }
2627 
2628  if (op->reliable) {
2629  if (!pdu || length != (op->cur_length + 4)) {
2630  success = false;
2631  reliable_error = true;
2632  goto done;
2633  }
2634 
2635  if (get_le16(pdu) != op->value_handle ||
2636  get_le16(pdu + 2) != (op->offset + op->index)) {
2637  success = false;
2638  reliable_error = true;
2639  goto done;
2640  }
2641 
2642  if (memcmp(pdu + 4, op->value + op->index, op->cur_length)) {
2643  success = false;
2644  reliable_error = true;
2645  goto done;
2646  }
2647  }
2648 
2649  next_index = op->index + op->cur_length;
2650  if (next_index == op->length) {
2651  /* All bytes written */
2652  goto done;
2653  }
2654 
2655  /* If the last written length was greater than or equal to what can fit
2656  * inside a PDU, then there is more data to send.
2657  */
2658  if (op->cur_length >= bt_att_get_mtu(op->client->att) - 5) {
2659  op->index = next_index;
2660  op->cur_length = MIN(op->length - op->index,
2661  bt_att_get_mtu(op->client->att) - 5);
2663  return;
2664  }
2665 
2666 done:
2667  complete_write_long_op(req, success, att_ecode, reliable_error);
2668 }
2669 
2671  bool reliable,
2672  uint16_t value_handle, uint16_t offset,
2673  const uint8_t *value, uint16_t length,
2675  void *user_data,
2677 {
2678  struct request *req;
2679  struct long_write_op *op;
2680  uint8_t *pdu;
2681 
2682  if (!client)
2683  return 0;
2684 
2685  if ((size_t)(length + offset) > UINT16_MAX)
2686  return 0;
2687 
2688  /* Don't allow writing a 0-length value using this procedure. The
2689  * upper-layer should use bt_gatt_write_value for that instead.
2690  */
2691  if (!length || !value)
2692  return 0;
2693 
2694  op = new0(struct long_write_op, 1);
2695  if (!op)
2696  return 0;
2697 
2698  op->value = malloc(length);
2699  if (!op->value) {
2700  free(op);
2701  return 0;
2702  }
2703 
2704  req = request_create(client);
2705  if (!req) {
2706  free(op->value);
2707  free(op);
2708  return 0;
2709  }
2710 
2711  memcpy(op->value, value, length);
2712 
2713  op->client = client;
2714  op->reliable = reliable;
2715  op->value_handle = value_handle;
2716  op->length = length;
2717  op->offset = offset;
2718  op->cur_length = MIN(length, bt_att_get_mtu(client->att) - 5);
2719  op->callback = callback;
2720  op->user_data = user_data;
2721  op->destroy = destroy;
2722 
2723  req->data = op;
2724  req->destroy = long_write_op_free;
2725  req->long_write = true;
2726 
2727  if (client->in_long_write || client->reliable_write_session_id > 0) {
2728  queue_push_tail(client->long_write_queue, req);
2729  return req->id;
2730  }
2731 
2732  pdu = malloc(op->cur_length + 4);
2733  if (!pdu) {
2734  free(op->value);
2735  free(op);
2736  return 0;
2737  }
2738 
2739  put_le16(value_handle, pdu);
2740  put_le16(offset, pdu + 2);
2741  memcpy(pdu + 4, op->value, op->cur_length);
2742 
2744  pdu, op->cur_length + 4,
2745  prepare_write_cb, req,
2746  request_unref);
2747  free(pdu);
2748 
2749  if (!req->att_id) {
2750  op->destroy = NULL;
2751  request_unref(req);
2752  return 0;
2753  }
2754 
2755  client->in_long_write = true;
2756 
2757  return req->id;
2758 }
2759 
2762  void *user_data;
2764  uint8_t *pdu;
2765  uint16_t pdu_len;
2766 };
2767 
2768 static void destroy_prep_write_op(void *data)
2769 {
2770  struct prep_write_op *op = data;
2771 
2772  if (op->destroy)
2773  op->destroy(op->user_data);
2774 
2775  free(op->pdu);
2776  free(op);
2777 }
2778 
2779 static void prep_write_cb(uint8_t opcode, const void *pdu, uint16_t length,
2780  void *user_data)
2781 {
2782  struct request *req = user_data;
2783  struct prep_write_op *op = req->data;
2784  bool success;
2785  uint8_t att_ecode;
2786  bool reliable_error;
2787 
2788  if (opcode == BT_ATT_OP_ERROR_RSP) {
2789  success = false;
2790  reliable_error = false;
2791  att_ecode = process_error(pdu, length);
2792  goto done;
2793  }
2794 
2795  if (opcode != BT_ATT_OP_PREP_WRITE_RSP) {
2796  success = false;
2797  reliable_error = false;
2798  att_ecode = 0;
2799  goto done;
2800  }
2801 
2802  if (!pdu || length != op->pdu_len ||
2803  memcmp(pdu, op->pdu, op->pdu_len)) {
2804  success = false;
2805  reliable_error = true;
2806  att_ecode = 0;
2807  goto done;
2808  }
2809 
2810  success = true;
2811  reliable_error = false;
2812  att_ecode = 0;
2813 
2814 done:
2815  if (op->callback)
2816  op->callback(success, reliable_error, att_ecode, op->user_data);
2817 }
2818 
2820  unsigned int id)
2821 {
2822  struct request *req;
2823  struct prep_write_op *op;
2824 
2825  op = new0(struct prep_write_op, 1);
2826  if (!op)
2827  return NULL;
2828 
2829  /* Following prepare writes */
2830  if (id != 0)
2831  req = queue_find(client->pending_requests, match_req_id,
2832  UINT_TO_PTR(id));
2833  else
2834  req = request_create(client);
2835 
2836  if (!req) {
2837  free(op);
2838  return NULL;
2839  }
2840 
2841  req->data = op;
2842 
2843  return req;
2844 }
2845 
2847  unsigned int id, uint16_t value_handle,
2848  uint16_t offset, const uint8_t *value,
2849  uint16_t length,
2851  void *user_data,
2853 {
2854  struct request *req;
2855  struct prep_write_op *op;
2856  uint8_t pdu[4 + length];
2857 
2858  if (!client)
2859  return 0;
2860 
2861  if (client->in_long_write)
2862  return 0;
2863 
2864  /*
2865  * Make sure that client who owns reliable session continues with
2866  * prepare writes or this is brand new reliable session (id == 0)
2867  */
2868  if (id != client->reliable_write_session_id) {
2869  util_debug(client->debug_callback, client->debug_data,
2870  "There is other reliable write session ongoing %u",
2871  client->reliable_write_session_id);
2872 
2873  return 0;
2874  }
2875 
2876  req = get_reliable_request(client, id);
2877  if (!req)
2878  return 0;
2879 
2880  op = (struct prep_write_op *)req->data;
2881 
2882  op->callback = callback;
2883  op->user_data = user_data;
2884  op->destroy = destroy;
2885 
2887  req->prep_write = true;
2888 
2889  put_le16(value_handle, pdu);
2890  put_le16(offset, pdu + 2);
2891  memcpy(pdu + 4, value, length);
2892 
2893  /*
2894  * Before sending command we need to remember pdu as we need to validate
2895  * it in the response. Store handle, offset and value. Therefore
2896  * increase length by 4 (handle + offset) as we need it in couple places
2897  * below
2898  */
2899  length += 4;
2900 
2901  op->pdu = malloc(length);
2902  if (!op->pdu) {
2903  op->destroy = NULL;
2904  request_unref(req);
2905  return 0;
2906  }
2907 
2908  memcpy(op->pdu, pdu, length);
2909  op->pdu_len = length;
2910 
2911  /*
2912  * Now we are ready to send command
2913  * Note that request_unref will be done on write execute
2914  */
2915  req->att_id = bt_att_send(client->att, BT_ATT_OP_PREP_WRITE_REQ, pdu,
2916  sizeof(pdu), prep_write_cb, req,
2917  NULL);
2918  if (!req->att_id) {
2919  op->destroy = NULL;
2920  request_unref(req);
2921  return 0;
2922  }
2923 
2924  /*
2925  * Store first request id for prepare write and treat it as a session id
2926  * valid until write execute is done
2927  */
2928  if (client->reliable_write_session_id == 0)
2929  client->reliable_write_session_id = req->id;
2930 
2931  return client->reliable_write_session_id;
2932 }
2933 
2934 static void exec_write_cb(uint8_t opcode, const void *pdu, uint16_t length,
2935  void *user_data)
2936 {
2937  struct request *req = user_data;
2938  struct write_op *op = req->data;
2939  bool success;
2940  uint8_t att_ecode;
2941 
2942  if (opcode == BT_ATT_OP_ERROR_RSP) {
2943  success = false;
2944  att_ecode = process_error(pdu, length);
2945  goto done;
2946  }
2947 
2948  if (opcode != BT_ATT_OP_EXEC_WRITE_RSP || pdu || length) {
2949  success = false;
2950  att_ecode = 0;
2951  goto done;
2952  }
2953 
2954  success = true;
2955  att_ecode = 0;
2956 
2957 done:
2958  if (op->callback)
2959  op->callback(success, att_ecode, op->user_data);
2960 
2962 
2964 }
2965 
2967  unsigned int id,
2969  void *user_data,
2971 {
2972  struct request *req;
2973  struct write_op *op;
2974  uint8_t pdu;
2975 
2976  if (!client)
2977  return 0;
2978 
2979  if (client->in_long_write)
2980  return 0;
2981 
2982  if (client->reliable_write_session_id != id)
2983  return 0;
2984 
2985  op = new0(struct write_op, 1);
2986  if (!op)
2987  return 0;
2988 
2989  req = queue_find(client->pending_requests, match_req_id,
2990  UINT_TO_PTR(id));
2991  if (!req) {
2992  free(op);
2993  return 0;
2994  }
2995 
2996  op->client = client;
2997  op->callback = callback;
2998  op->user_data = user_data;
2999  op->destroy = destroy;
3000 
3001  pdu = 0x01;
3002 
3003  req->data = op;
3004  req->destroy = destroy_write_op;
3005 
3006  req->att_id = bt_att_send(client->att, BT_ATT_OP_EXEC_WRITE_REQ, &pdu,
3007  sizeof(pdu), exec_write_cb,
3008  req, request_unref);
3009  if (!req->att_id) {
3010  op->destroy = NULL;
3011  request_unref(req);
3012  return 0;
3013  }
3014 
3015  return id;
3016 }
3017 
3019  uint16_t chrc_value_handle,
3022  void *user_data,
3024 {
3025  if (!client || !client->db || !chrc_value_handle || !callback)
3026  return 0;
3027 
3028  if (!bt_gatt_client_is_ready(client) || client->in_svc_chngd)
3029  return 0;
3030 
3031  return register_notify(client, chrc_value_handle, callback, notify,
3032  user_data, destroy);
3033 }
3034 
3036  unsigned int id)
3037 {
3038  struct notify_data *notify_data;
3039 
3040  if (!client || !id)
3041  return false;
3042 
3043  notify_data = queue_remove_if(client->notify_list, match_notify_data_id,
3044  UINT_TO_PTR(id));
3045  if (!notify_data)
3046  return false;
3047 
3048  assert(notify_data->chrc->notify_count > 0);
3049  assert(!notify_data->chrc->ccc_write_id);
3050 
3051  complete_unregister_notify(notify_data);
3052  return true;
3053 }
3054 
3056 {
3057  if (!client)
3058  return false;
3059 
3060  return bt_att_set_security(client->att, level);
3061 }
3062 
3064 {
3065  if (!client)
3066  return -1;
3067 
3068  return bt_att_get_security(client->att);
3069 }
static void service_changed_complete(struct discovery_op *op, bool success, uint8_t att_ecode)
Definition: gatt-client.c:1394
static void disable_ccc_callback(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: gatt-client.c:1586
bool gatt_db_attribute_get_char_data(const struct gatt_db_attribute *attrib, uint16_t *handle, uint16_t *value_handle, uint8_t *properties, bt_uuid_t *uuid)
Definition: gatt-db.c:1495
static bool cancel_request(struct request *req)
Definition: gatt-client.c:1946
#define BT_ATT_OP_HANDLE_VAL_CONF
Definition: att-types.h:67
bt_gatt_client_destroy_func_t destroy
Definition: gatt-client.c:2466
void * queue_find(struct queue *queue, queue_match_func_t function, const void *match_data)
Definition: queue.c:376
static void request_unref(void *data)
Definition: gatt-client.c:178
void queue_foreach(struct queue *queue, queue_foreach_func_t function, void *user_data)
Definition: queue.c:325
unsigned int ind_id
Definition: gatt-client.c:107
static void complete_unregister_notify(void *data)
Definition: gatt-client.c:1608
void bt_gatt_request_unref(struct bt_gatt_request *req)
Definition: gatt-helpers.c:632
static uint8_t process_error(const void *pdu, uint16_t length)
Definition: gatt-client.c:1193
static void att_disconnect_cb(int err, void *user_data)
Definition: gatt-client.c:1716
void bt_gatt_client_unref(struct bt_gatt_client *client)
Definition: gatt-client.c:1804
uint16_t value_handle
Definition: gatt-client.c:2458
static struct discovery_op * discovery_op_create(struct bt_gatt_client *client, uint16_t start, uint16_t end, discovery_op_complete_func_t complete_func, discovery_op_fail_func_t failure_func)
Definition: gatt-client.c:399
#define BT_ATT_OP_READ_RSP
Definition: att-types.h:50
static void gatt_client_remove_notify_chrcs_in_range(struct bt_gatt_client *client, uint16_t start_handle, uint16_t end_handle)
Definition: gatt-client.c:357
static bool append_chunk(struct read_long_op *op, const uint8_t *data, uint16_t len)
Definition: gatt-client.c:2197
static bool cancel_long_write_req(struct bt_gatt_client *client, struct request *req)
Definition: gatt-client.c:1906
static struct request * get_reliable_request(struct bt_gatt_client *client, unsigned int id)
Definition: gatt-client.c:2819
#define GATT_CLIENT_CHARAC_CFG_UUID
Definition: uuid.h:134
uint16_t bt_gatt_client_get_mtu(struct bt_gatt_client *client)
Definition: gatt-client.c:1873
bt_gatt_client_destroy_func_t debug_destroy
Definition: gatt-client.c:78
struct queue * notify_list
Definition: gatt-client.c:94
bt_gatt_client_destroy_func_t destroy
Definition: gatt-client.c:1997
static void discovery_req_clear(struct bt_gatt_client *client)
Definition: gatt-client.c:455
uint16_t cur_length
Definition: gatt-client.c:2463
#define BT_ATT_OP_SIGNED_WRITE_CMD
Definition: att-types.h:60
void gatt_db_unref(struct gatt_db *db)
Definition: gatt-db.c:328
void(* queue_destroy_func_t)(void *data)
Definition: queue.h:26
struct bt_gatt_client * client
Definition: gatt-client.c:2453
static void gatt_client_remove_all_notify_in_range(struct bt_gatt_client *client, uint16_t start_handle, uint16_t end_handle)
Definition: gatt-client.c:344
struct gatt_db_attribute * attr
Definition: gatt-db.c:263
uint16_t offset
Definition: gatt-client.c:2179
static void read_long_cb(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: gatt-client.c:2220
bt_gatt_client_callback_t callback
Definition: gatt-client.c:2368
bt_gatt_client_service_changed_callback_t svc_chngd_callback
Definition: gatt-client.c:73
struct queue * pending_chrcs
Definition: gatt-client.c:380
unsigned int ccc_write_id
Definition: gatt-client.c:204
static bool match_req_id(const void *a, const void *b)
Definition: gatt-client.c:1889
uint16_t end_handle
Definition: gatt-client.c:602
bool bt_att_unregister_disconnect(struct bt_att *att, unsigned int id)
Definition: att.c:1189
uint16_t end
Definition: gatt-client.c:385
static void init_fail(struct discovery_op *op)
Definition: gatt-client.c:1546
bool bt_gatt_client_set_security(struct bt_gatt_client *client, int level)
Definition: gatt-client.c:3055
unsigned int bt_gatt_client_write_value(struct bt_gatt_client *client, uint16_t value_handle, const uint8_t *value, uint16_t length, bt_gatt_client_callback_t callback, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:2405
bluetooth GATT client structure
Definition: gatt-client.c:64
static void destroy_read_long_op(void *data)
Definition: gatt-client.c:2186
uint16_t gatt_db_attribute_get_handle(const struct gatt_db_attribute *attrib)
Definition: gatt-db.c:1409
void(* bt_gatt_client_service_changed_callback_t)(uint16_t start_handle, uint16_t end_handle, void *user_data)
Definition: gatt-client.h:54
bool bt_gatt_client_is_ready(struct bt_gatt_client *client)
Definition: gatt-client.c:1815
static void destroy_read_op(void *data)
Definition: gatt-client.c:2000
bt_gatt_client_notify_callback_t notify
Definition: gatt-client.c:214
static void notify_chrc_free(void *data)
Definition: gatt-client.c:304
struct gatt_db_attribute * cur_svc
Definition: gatt-client.c:382
static void cancel_prep_write_cb(uint8_t opcode, const void *pdu, uint16_t len, void *user_data)
Definition: gatt-client.c:1926
static void find_ccc(struct gatt_db_attribute *attr, void *user_data)
Definition: gatt-client.c:239
const bt_uuid_t * gatt_db_attribute_get_type(const struct gatt_db_attribute *attrib)
Definition: gatt-db.c:1400
unsigned int bt_gatt_client_register_notify(struct bt_gatt_client *client, uint16_t chrc_value_handle, bt_gatt_client_register_callback_t callback, bt_gatt_client_notify_callback_t notify, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:3018
#define BT_ATT_OP_HANDLE_VAL_IND
Definition: att-types.h:66
void * queue_pop_head(struct queue *queue)
Definition: queue.c:268
static void destroy_write_op(void *data)
Definition: gatt-client.c:2373
bt_gatt_destroy_func_t destroy
Definition: gatt-client.c:2370
struct queue * tmp_queue
Definition: gatt-client.c:381
Definition: gatt-db.c:70
static void long_write_op_free(void *data)
Definition: gatt-client.c:2469
uint16_t index
Definition: gatt-client.c:2462
void * user_data
Definition: gatt-client.c:2762
uint16_t value_handle
Definition: gatt-client.c:2178
uint8_t data[16]
Definition: bluetooth.h:343
struct gatt_db_attribute * gatt_db_service_add_included(struct gatt_db_attribute *attrib, struct gatt_db_attribute *include)
Definition: gatt-db.c:868
uint8_t * pdu
Definition: gatt-client.c:2764
uint16_t start
Definition: gatt-client.c:384
uint16_t length
Definition: gatt-client.c:1583
void(* discovery_op_fail_func_t)(struct discovery_op *op)
Definition: gatt-client.c:375
discovery_op_fail_func_t failure_func
Definition: gatt-client.c:388
static void service_changed_failure(struct discovery_op *op)
Definition: gatt-client.c:1433
static void cancel_long_write_cb(uint8_t opcode, const void *pdu, uint16_t len, void *user_data)
Definition: gatt-client.c:1897
void(* discovery_op_complete_func_t)(struct discovery_op *op, bool success, uint8_t att_ecode)
Definition: gatt-client.c:372
#define BT_ATT_OP_READ_BLOB_REQ
Definition: att-types.h:51
const void * pdu
Definition: gatt-client.c:1582
static bool register_service_changed(struct bt_gatt_client *client)
Definition: gatt-client.c:1365
uint16_t value_handle
Definition: gatt-client.c:603
#define BT_ATT_OP_PREP_WRITE_REQ
Definition: att-types.h:61
struct bt_gatt_request * bt_gatt_discover_characteristics(struct bt_att *att, uint16_t start, uint16_t end, bt_gatt_request_callback_t callback, void *user_data, bt_gatt_destroy_func_t destroy)
void * svc_chngd_data
Definition: gatt-client.c:75
#define BT_ATT_OP_PREP_WRITE_RSP
Definition: att-types.h:62
struct gatt_db_attribute * gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib, uint16_t handle, const bt_uuid_t *uuid, uint32_t permissions, uint8_t properties, gatt_db_read_t read_func, gatt_db_write_t write_func, void *user_data)
Definition: gatt-db.c:766
struct bt_gatt_request * bt_gatt_discover_included_services(struct bt_att *att, uint16_t start, uint16_t end, bt_gatt_request_callback_t callback, void *user_data, bt_gatt_destroy_func_t destroy)
struct queue * notify_chrcs
Definition: gatt-client.c:96
static struct discovery_op * discovery_op_ref(struct discovery_op *op)
Definition: gatt-client.c:435
static void notify_client_ready(struct bt_gatt_client *client, bool success, uint8_t att_ecode)
Definition: gatt-client.c:1075
bool gatt_db_service_set_active(struct gatt_db_attribute *attrib, bool active)
Definition: gatt-db.c:922
bool bt_gatt_client_set_service_changed(struct bt_gatt_client *client, bt_gatt_client_service_changed_callback_t callback, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:1838
uint16_t pdu_len
Definition: gatt-client.c:2765
bool bt_gatt_iter_next_characteristic(struct bt_gatt_iter *iter, uint16_t *start_handle, uint16_t *end_handle, uint16_t *value_handle, uint8_t *properties, uint8_t uuid[16])
Definition: gatt-helpers.c:378
struct gatt_db_attribute * gatt_db_service_insert_descriptor(struct gatt_db_attribute *attrib, uint16_t handle, const bt_uuid_t *uuid, uint32_t permissions, gatt_db_read_t read_func, gatt_db_write_t write_func, void *user_data)
Definition: gatt-db.c:835
static void discover_primary_cb(bool success, uint8_t att_ecode, struct bt_gatt_result *result, void *user_data)
Definition: gatt-client.c:986
unsigned int att_id
Definition: gatt-client.c:145
bt_gatt_client_destroy_func_t ready_destroy
Definition: gatt-client.c:70
unsigned int gatt_db_find_by_type(struct gatt_db *db, uint16_t start_handle, uint16_t end_handle, const bt_uuid_t *type, gatt_db_attribute_cb_t func, void *user_data)
Definition: gatt-db.c:1056
bool bt_att_unregister(struct bt_att *att, unsigned int id)
Definition: att.c:1421
uint16_t length
Definition: gatt-client.c:2460
#define BT_ATT_OP_WRITE_REQ
Definition: att-types.h:57
Definition: queue.c:40
static bool match_notify_data_handle_range(const void *a, const void *b)
Definition: gatt-client.c:325
void(* bt_gatt_client_write_long_callback_t)(bool success, bool reliable_error, uint8_t att_ecode, void *user_data)
Definition: gatt-client.h:46
bt_gatt_client_debug_func_t debug_callback
Definition: gatt-client.c:77
#define BT_SECURITY_LOW
Definition: bluetooth.h:69
struct queue * reg_notify_queue
Definition: gatt-client.c:203
static void put_le16(uint16_t val, void *dst)
Definition: util.h:130
void(* bt_gatt_destroy_func_t)(void *user_data)
Definition: gatt-helpers.h:60
bt_uuid_t uuid
Definition: gatt-client.c:605
static unsigned int register_notify(struct bt_gatt_client *client, uint16_t handle, bt_gatt_client_register_callback_t callback, bt_gatt_client_notify_callback_t notify, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:1255
static void exchange_mtu_cb(bool success, uint8_t att_ecode, void *user_data)
Definition: gatt-client.c:1087
bool queue_isempty(struct queue *queue)
Definition: queue.c:569
#define BT_ATT_OP_READ_BLOB_RSP
Definition: att-types.h:52
void * user_data
Definition: gatt-db.c:104
static void exec_write_cb(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: gatt-client.c:2934
struct bt_gatt_client * client
Definition: gatt-client.c:2367
struct bt_gatt_request * bt_gatt_discover_descriptors(struct bt_att *att, uint16_t start, uint16_t end, bt_gatt_request_callback_t callback, void *user_data, bt_gatt_destroy_func_t destroy)
bt_gatt_client_write_long_callback_t callback
Definition: gatt-client.c:2464
int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2)
Definition: uuid.c:135
bool bt_gatt_client_cancel_all(struct bt_gatt_client *client)
Definition: gatt-client.c:1974
#define BT_ATT_OP_WRITE_RSP
Definition: att-types.h:58
void(* bt_gatt_client_debug_func_t)(const char *str, void *user_data)
Definition: gatt-client.h:42
unsigned int disc_id
Definition: gatt-client.c:98
uint16_t properties
Definition: gatt-client.c:197
#define BT_ATT_OP_READ_MULT_RSP
Definition: att-types.h:54
bt_gatt_destroy_func_t destroy
Definition: gatt-client.c:2763
bt_gatt_client_destroy_func_t destroy
Definition: gatt-client.c:2183
bt_gatt_client_write_long_callback_t callback
Definition: gatt-client.c:2761
void queue_destroy(struct queue *queue, queue_destroy_func_t destroy)
Definition: queue.c:102
bool bt_att_set_security(struct bt_att *att, int level)
Definition: att.c:1467
bool in_long_write
Definition: gatt-client.c:91
struct bt_gatt_client * bt_gatt_client_new(struct gatt_db *db, struct bt_att *att, uint16_t mtu)
Definition: gatt-client.c:1733
discovery_op_complete_func_t complete_func
Definition: gatt-client.c:387
struct bt_gatt_client * client
Definition: gatt-client.c:133
bool prep_write
Definition: gatt-client.c:137
static void notify_data_unref(void *data)
Definition: gatt-client.c:226
bt_gatt_client_destroy_func_t svc_chngd_destroy
Definition: gatt-client.c:74
void * user_data
Definition: gatt-client.c:2182
void(* bt_gatt_client_register_callback_t)(uint16_t att_ecode, void *user_data)
Definition: gatt-client.h:52
unsigned int mtu_req_id
Definition: gatt-client.c:124
bt_gatt_client_read_callback_t callback
Definition: gatt-client.c:2181
#define PTR_TO_UINT(p)
Definition: util.h:76
bt_gatt_client_read_callback_t callback
Definition: gatt-client.c:1995
#define MAX(a, b)
Definition: gatt-client.c:47
bool bt_att_cancel(struct bt_att *att, unsigned int id)
Definition: att.c:1278
bool gatt_db_clear_range(struct gatt_db *db, uint16_t start_handle, uint16_t end_handle)
Definition: gatt-db.c:481
bool bt_gatt_client_set_debug(struct bt_gatt_client *client, bt_gatt_client_debug_func_t callback, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:1856
struct bt_gatt_client * bt_gatt_client_ref(struct bt_gatt_client *client)
Definition: gatt-client.c:1794
static void bt_gatt_client_free(struct bt_gatt_client *client)
Definition: gatt-client.c:1687
struct notify_chrc * chrc
Definition: gatt-client.c:212
static struct notify_data * notify_data_ref(struct notify_data *notify_data)
Definition: gatt-client.c:219
void(* destroy)(void *)
Definition: gatt-client.c:149
uint16_t bt_att_get_mtu(struct bt_att *att)
Definition: att.c:1111
bool queue_push_tail(struct queue *queue, void *data)
Definition: queue.c:167
static void destroy_prep_write_op(void *data)
Definition: gatt-client.c:2768
struct gatt_db * db
Definition: gatt-client.c:81
struct queue * queue_new(void)
Definition: queue.c:81
#define BT_ATT_OP_EXEC_WRITE_REQ
Definition: att-types.h:63
static void get_first_attribute(struct gatt_db_attribute *attrib, void *user_data)
Definition: gatt-client.c:1331
bool bt_gatt_iter_next_included_service(struct bt_gatt_iter *iter, uint16_t *handle, uint16_t *start_handle, uint16_t *end_handle, uint8_t uuid[16])
Definition: gatt-helpers.c:257
struct bt_att * att
Definition: gatt-client.c:65
uint8_t * value
Definition: gatt-client.c:2459
uint8_t properties
Definition: gatt-client.c:604
static struct notify_chrc * notify_chrc_create(struct bt_gatt_client *client, uint16_t value_handle)
Definition: gatt-client.c:255
uint8_t att_ecode
Definition: gatt-client.c:2456
static void discover_incl_cb(bool success, uint8_t att_ecode, struct bt_gatt_result *result, void *user_data)
Definition: gatt-client.c:468
uint16_t handle
Definition: gatt-db.c:96
bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client, unsigned int id)
Definition: gatt-client.c:3035
bool queue_remove(struct queue *queue, void *data)
Definition: queue.c:402
static void process_service_changed(struct bt_gatt_client *client, uint16_t start_handle, uint16_t end_handle)
Definition: gatt-client.c:1440
struct bt_gatt_client * client
Definition: gatt-client.c:2176
static bool match_notify_data_id(const void *a, const void *b)
Definition: gatt-client.c:312
bt_gatt_client_register_callback_t callback
Definition: gatt-client.c:213
#define BT_ATT_OP_ERROR_RSP
Definition: att-types.h:40
unsigned int queue_remove_all(struct queue *queue, queue_match_func_t function, void *user_data, queue_destroy_func_t destroy)
Definition: queue.c:487
unsigned int svc_chngd_ind_id
Definition: gatt-client.c:112
uint16_t ccc_handle
Definition: gatt-client.c:196
#define BT_ATT_OP_WRITE_CMD
Definition: att-types.h:59
bool bt_gatt_iter_init(struct bt_gatt_iter *iter, struct bt_gatt_result *result)
Definition: gatt-helpers.c:188
unsigned int bt_gatt_client_read_multiple(struct bt_gatt_client *client, uint16_t *handles, uint8_t num_handles, bt_gatt_client_read_callback_t callback, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:2122
static void service_changed_cb(uint16_t value_handle, const uint8_t *value, uint16_t length, void *user_data)
Definition: gatt-client.c:1481
#define BT_ATT_ERROR_UNSUPPORTED_GROUP_TYPE
Definition: att-types.h:96
int bt_uuid16_create(bt_uuid_t *btuuid, uint16_t value)
Definition: uuid.c:108
#define BT_ATT_OP_HANDLE_VAL_NOT
Definition: att-types.h:65
static void discover_chrcs_cb(bool success, uint8_t att_ecode, struct bt_gatt_result *result, void *user_data)
Definition: gatt-client.c:771
void util_debug(util_debug_func_t function, void *user_data, const char *format,...)
Definition: util.c:56
#define BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND
Definition: att-types.h:90
unsigned int bt_gatt_client_write_long_value(struct bt_gatt_client *client, bool reliable, uint16_t value_handle, uint16_t offset, const uint8_t *value, uint16_t length, bt_gatt_client_write_long_callback_t callback, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:2670
unsigned int id
Definition: gatt-client.c:143
struct bt_gatt_request * bt_gatt_discover_secondary_services(struct bt_att *att, bt_uuid_t *uuid, uint16_t start, uint16_t end, bt_gatt_request_callback_t callback, void *user_data, bt_gatt_destroy_func_t destroy)
Definition: gatt-helpers.c:947
static void discovery_op_unref(void *data)
Definition: gatt-client.c:442
bool gatt_db_attribute_get_service_handles(const struct gatt_db_attribute *attrib, uint16_t *start_handle, uint16_t *end_handle)
Definition: gatt-db.c:1448
void(* bt_gatt_client_read_callback_t)(bool success, uint8_t att_ecode, const uint8_t *value, uint16_t length, void *user_data)
Definition: gatt-client.h:43
#define UINT_TO_PTR(u)
Definition: util.h:77
static void enable_ccc_callback(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: gatt-client.c:1205
unsigned int bt_gatt_result_descriptor_count(struct bt_gatt_result *result)
Definition: gatt-helpers.c:149
bool long_write
Definition: gatt-client.c:135
void * user_data
Definition: gatt-client.c:215
#define BT_ATT_OP_READ_MULT_REQ
Definition: att-types.h:53
bool bt_gatt_client_set_ready_handler(struct bt_gatt_client *client, bt_gatt_client_callback_t callback, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:1820
void * debug_data
Definition: gatt-client.c:79
static void prepare_write_cb(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: gatt-client.c:2607
bool removed
Definition: gatt-client.c:139
void * queue_remove_if(struct queue *queue, queue_match_func_t function, void *user_data)
Definition: queue.c:440
static void handle_next_prep_write(struct request *req)
Definition: gatt-client.c:2485
bool gatt_db_clear(struct gatt_db *db)
Definition: gatt-db.c:442
#define BT_GATT_CHRC_PROP_INDICATE
Definition: att-types.h:133
bt_uuid_t uuid
Definition: gatt-db.c:97
struct queue * pending_svcs
Definition: gatt-client.c:379
void(* bt_gatt_client_callback_t)(bool success, uint8_t att_ecode, void *user_data)
Definition: gatt-client.h:40
static void complete_write_long_op(struct request *req, bool success, uint8_t att_ecode, bool reliable_error)
Definition: gatt-client.c:2571
static struct request * request_create(struct bt_gatt_client *client)
Definition: gatt-client.c:160
struct gatt_db * bt_gatt_client_get_db(struct bt_gatt_client *client)
Definition: gatt-client.c:1881
static void notify_handler(void *data, void *user_data)
Definition: gatt-client.c:1632
struct bt_gatt_client * client
Definition: gatt-client.c:1138
int bt_gatt_client_get_security(struct bt_gatt_client *client)
Definition: gatt-client.c:3063
struct queue * pending_requests
Definition: gatt-client.c:117
static bool discover_descs(struct discovery_op *op, bool *discovering)
Definition: gatt-client.c:612
uint8_t * pdu
Definition: att.c:752
static bool match_notify_chrc_handle_range(const void *a, const void *b)
Definition: gatt-client.c:335
struct bt_gatt_client * client
Definition: gatt-client.c:378
Definition: att.c:64
struct gatt_db * gatt_db_ref(struct gatt_db *db)
Definition: gatt-db.c:208
uint16_t offset
Definition: gatt-client.c:2461
unsigned int att_id
Definition: gatt-client.c:210
uint16_t start_handle
Definition: gatt-client.c:601
static void service_changed_register_cb(uint16_t att_ecode, void *user_data)
Definition: gatt-client.c:1342
unsigned int next_request_id
Definition: gatt-client.c:122
struct queue * svc_chngd_queue
Definition: gatt-client.c:114
static void discover_secondary_cb(bool success, uint8_t att_ecode, struct bt_gatt_result *result, void *user_data)
Definition: gatt-client.c:880
#define BT_ATT_DEFAULT_LE_MTU
Definition: att-types.h:35
int bt_att_get_security(struct bt_att *att)
Definition: att.c:1448
void gatt_db_service_foreach_desc(struct gatt_db_attribute *attrib, gatt_db_attribute_cb_t func, void *user_data)
Definition: gatt-db.c:1291
#define SVC_CHNGD_UUID
Definition: gatt-client.c:57
void(* bt_att_response_func_t)(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: att.h:40
struct gatt_db_attribute * gatt_db_get_attribute(struct gatt_db *db, uint16_t handle)
Definition: gatt-db.c:1349
Definition: crypto.c:447
uint16_t end
Definition: gatt-client.c:322
static void complete_notify_request(void *data)
Definition: gatt-client.c:1149
int ref_count
Definition: gatt-client.c:141
struct bt_gatt_client * client
Definition: gatt-client.c:208
unsigned int bt_gatt_client_write_execute(struct bt_gatt_client *client, unsigned int id, bt_gatt_client_callback_t callback, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:2966
void(* bt_gatt_client_notify_callback_t)(uint16_t value_handle, const uint8_t *value, uint16_t length, void *user_data)
Definition: gatt-client.h:49
void * user_data
Definition: gatt-client.c:2369
unsigned int bt_gatt_client_write_without_response(struct bt_gatt_client *client, uint16_t value_handle, bool signed_write, const uint8_t *value, uint16_t length)
Definition: gatt-client.c:2328
uint16_t value_handle
Definition: gatt-client.c:195
#define BT_ATT_OP_EXEC_WRITE_RSP
Definition: att-types.h:64
bool svc_chngd_registered
Definition: gatt-client.c:113
Request data structure.
Definition: gatt-client.c:132
unsigned int bt_gatt_client_prepare_write(struct bt_gatt_client *client, unsigned int id, uint16_t value_handle, uint16_t offset, const uint8_t *value, uint16_t length, bt_gatt_client_write_long_callback_t callback, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:2846
static void read_multiple_cb(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: gatt-client.c:2095
void * user_data
Definition: gatt-client.c:2465
unsigned int bt_gatt_result_characteristic_count(struct bt_gatt_result *result)
Definition: gatt-helpers.c:128
static struct request * request_ref(struct request *req)
Definition: gatt-client.c:153
struct bt_gatt_request * bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid, uint16_t start, uint16_t end, bt_gatt_request_callback_t callback, void *user_data, bt_gatt_destroy_func_t destroy)
Definition: gatt-helpers.c:936
static bool gatt_client_init(struct bt_gatt_client *client, uint16_t mtu)
Definition: gatt-client.c:1553
bool bt_gatt_iter_next_descriptor(struct bt_gatt_iter *iter, uint16_t *handle, uint8_t uuid[16])
Definition: gatt-helpers.c:430
bool bt_gatt_iter_next_service(struct bt_gatt_iter *iter, uint16_t *start_handle, uint16_t *end_handle, uint8_t uuid[16])
Definition: gatt-helpers.c:337
static uint16_t get_le16(const void *ptr)
Definition: util.h:100
int notify_count
Definition: gatt-client.c:198
static bool notify_data_write_ccc(struct notify_data *notify_data, bool enable, bt_att_response_func_t callback)
Definition: gatt-client.c:1160
static void write_cb(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: gatt-client.c:2383
bt_gatt_client_callback_t ready_callback
Definition: gatt-client.c:69
#define new0(t, n)
Definition: util.h:82
static void discover_descs_cb(bool success, uint8_t att_ecode, struct bt_gatt_result *result, void *user_data)
Definition: gatt-client.c:673
static void start_next_long_write(struct bt_gatt_client *client)
Definition: gatt-client.c:2524
void(* bt_gatt_client_destroy_func_t)(void *user_data)
Definition: gatt-client.h:39
#define BT_ATT_ERROR_REQUEST_NOT_SUPPORTED
Definition: att-types.h:86
struct gatt_db_attribute * gatt_db_insert_service(struct gatt_db *db, uint16_t handle, const bt_uuid_t *uuid, bool primary, uint16_t num_handles)
Definition: gatt-db.c:531
unsigned int bt_gatt_exchange_mtu(struct bt_att *att, uint16_t client_rx_mtu, bt_gatt_result_callback_t callback, void *user_data, bt_gatt_destroy_func_t destroy)
Definition: gatt-helpers.c:582
static bool match_notify_chrc_value_handle(const void *a, const void *b)
Definition: gatt-client.c:1247
struct iovec iov
Definition: gatt-client.c:2180
#define BT_ATT_OP_READ_REQ
Definition: att-types.h:49
void * ready_data
Definition: gatt-client.c:71
static void prep_write_cb(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: gatt-client.c:2779
uint8_t opcode
Definition: att.c:140
static void notify_data_cleanup(void *data)
Definition: gatt-client.c:1677
#define BT_ATT_MAX_VALUE_LEN
Definition: att-types.h:37
struct bt_gatt_request * discovery_req
Definition: gatt-client.c:123
static void notify_cb(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: gatt-client.c:1656
unsigned int bt_att_register(struct bt_att *att, uint8_t opcode, bt_att_notify_func_t callback, void *user_data, bt_att_destroy_func_t destroy)
Definition: att.c:1389
bt_gatt_client_destroy_func_t destroy
Definition: gatt-client.c:216
unsigned int bt_gatt_client_read_long_value(struct bt_gatt_client *client, uint16_t value_handle, uint16_t offset, bt_gatt_client_read_callback_t callback, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:2279
void bt_gatt_request_cancel(struct bt_gatt_request *req)
Definition: gatt-helpers.c:650
struct queue * long_write_queue
Definition: gatt-client.c:84
unsigned int bt_gatt_result_service_count(struct bt_gatt_result *result)
Definition: gatt-helpers.c:116
void * data
Definition: gatt-client.c:147
#define MIN(a, b)
Definition: gatt-client.c:51
unsigned int bt_att_register_disconnect(struct bt_att *att, bt_att_disconnect_func_t callback, void *user_data, bt_att_destroy_func_t destroy)
Definition: att.c:1158
unsigned int bt_att_send(struct bt_att *att, uint8_t opcode, const void *pdu, uint16_t length, bt_att_response_func_t callback, void *user_data, bt_att_destroy_func_t destroy)
Definition: att.c:1220
static void read_cb(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: gatt-client.c:2010
#define MAX_LEN_UUID_STR
Definition: uuid.h:165
void bt_att_unref(struct bt_att *att)
Definition: att.c:1065
unsigned int bt_gatt_result_included_count(struct bt_gatt_result *result)
Definition: gatt-helpers.c:160
static bool cancel_prep_write_session(struct bt_gatt_client *client, struct request *req)
Definition: gatt-client.c:1935
#define BT_GATT_CHRC_PROP_NOTIFY
Definition: att-types.h:132
static void discovery_op_free(struct discovery_op *op)
Definition: gatt-client.c:391
uint16_t start
Definition: gatt-client.c:321
int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value)
Definition: uuid.c:126
#define GATT_CHARAC_UUID
Definition: uuid.h:113
unsigned int notify_id
Definition: gatt-client.c:102
unsigned int bt_gatt_client_read_value(struct bt_gatt_client *client, uint16_t value_handle, bt_gatt_client_read_callback_t callback, void *user_data, bt_gatt_client_destroy_func_t destroy)
Definition: gatt-client.c:2050
struct bt_att * bt_att_ref(struct bt_att *att)
Definition: att.c:1055
unsigned int id
Definition: gatt-client.c:209
static void init_complete(struct discovery_op *op, bool success, uint8_t att_ecode)
Definition: gatt-client.c:1519
unsigned int reliable_write_session_id
Definition: gatt-client.c:93
void * user_data
Definition: gatt-client.c:1996
static void execute_write_cb(uint8_t opcode, const void *pdu, uint16_t length, void *user_data)
Definition: gatt-client.c:2546
struct bt_gatt_request * bt_gatt_discover_all_primary_services(struct bt_att *att, bt_uuid_t *uuid, bt_gatt_request_callback_t callback, void *user_data, bt_gatt_destroy_func_t destroy)
Definition: gatt-helpers.c:925
bool gatt_db_service_get_active(struct gatt_db_attribute *attrib)
Definition: gatt-db.c:941
bool bt_gatt_client_cancel(struct bt_gatt_client *client, unsigned int id)
Definition: gatt-client.c:1959
int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n)
Definition: uuid.c:148