ble_gatt_client
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
gatt-db.c
Go to the documentation of this file.
1 
10 /*
11  *
12  * BlueZ - Bluetooth protocol stack for Linux
13  *
14  * Copyright (C) 2014 Intel Corporation. All rights reserved.
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 <stdbool.h>
34 #include <errno.h>
35 
36 #include "bluetooth.h"
37 #include "uuid.h"
38 #include "util.h"
39 #include "queue.h"
40 #include "timeout.h"
41 #include "att.h"
42 #include "gatt-db.h"
43 
44 #ifndef MAX
45 #define MAX(a, b) ((a) > (b) ? (a) : (b))
46 #endif
47 
48 #define MAX_CHAR_DECL_VALUE_LEN 19
49 #define MAX_INCLUDED_VALUE_LEN 6
50 #define ATTRIBUTE_TIMEOUT 5000
51 
52 static const bt_uuid_t primary_service_uuid = { .type = BT_UUID16,
54 static const bt_uuid_t secondary_service_uuid = { .type = BT_UUID16,
56 static const bt_uuid_t characteristic_uuid = { .type = BT_UUID16,
58 static const bt_uuid_t included_service_uuid = { .type = BT_UUID16,
60 
61 struct gatt_db {
62  int ref_count;
63  uint16_t next_handle;
64  struct queue *services;
65 
66  struct queue *notify_list;
67  unsigned int next_notify_id;
68 };
69 
70 struct notify {
71  unsigned int id;
75  void *user_data;
76 };
77 
78 struct pending_read {
80  unsigned int id;
81  unsigned int timeout_id;
83  void *user_data;
84 };
85 
86 struct pending_write {
88  unsigned int id;
89  unsigned int timeout_id;
91  void *user_data;
92 };
93 
96  uint16_t handle;
98  uint32_t permissions;
99  uint16_t value_len;
100  uint8_t *value;
101 
104  void *user_data;
105 
106  unsigned int read_id;
108 
109  unsigned int write_id;
111 };
112 
114  struct gatt_db *db;
115  bool active;
116  bool claimed;
117  uint16_t num_handles;
119 };
120 
121 static void pending_read_result(struct pending_read *p, int err,
122  const uint8_t *data, size_t length)
123 {
124  if (p->timeout_id > 0)
126 
127  p->func(p->attrib, err, data, length, p->user_data);
128 
129  free(p);
130 }
131 
132 static void pending_read_free(void *data)
133 {
134  struct pending_read *p = data;
135 
136  pending_read_result(p, -ECANCELED, NULL, 0);
137 }
138 
139 static void pending_write_result(struct pending_write *p, int err)
140 {
141  if (p->timeout_id > 0)
143 
144  p->func(p->attrib, err, p->user_data);
145 
146  free(p);
147 }
148 
149 static void pending_write_free(void *data)
150 {
151  struct pending_write *p = data;
152 
153  pending_write_result(p, -ECANCELED);
154 }
155 
156 static void attribute_destroy(struct gatt_db_attribute *attribute)
157 {
158  /* Attribute was not initialized by user */
159  if (!attribute)
160  return;
161 
164 
165  free(attribute->value);
166  free(attribute);
167 }
168 
170  uint16_t handle,
171  const bt_uuid_t *type,
172  const uint8_t *val,
173  uint16_t len)
174 {
175  struct gatt_db_attribute *attribute;
176 
177  attribute = new0(struct gatt_db_attribute, 1);
178  if (!attribute)
179  return NULL;
180 
181  attribute->service = service;
182  attribute->handle = handle;
183  attribute->uuid = *type;
184  attribute->value_len = len;
185  if (len) {
186  attribute->value = malloc0(len);
187  if (!attribute->value)
188  goto failed;
189 
190  memcpy(attribute->value, val, len);
191  }
192 
193  attribute->pending_reads = queue_new();
194  if (!attribute->pending_reads)
195  goto failed;
196 
197  attribute->pending_writes = queue_new();
198  if (!attribute->pending_reads)
199  goto failed;
200 
201  return attribute;
202 
203 failed:
204  attribute_destroy(attribute);
205  return NULL;
206 }
207 
208 struct gatt_db *gatt_db_ref(struct gatt_db *db)
209 {
210  if (!db)
211  return NULL;
212 
213  __sync_fetch_and_add(&db->ref_count, 1);
214 
215  return db;
216 }
217 
218 struct gatt_db *gatt_db_new(void)
219 {
220  struct gatt_db *db;
221 
222  db = new0(struct gatt_db, 1);
223  if (!db)
224  return NULL;
225 
226  db->services = queue_new();
227  if (!db->services) {
228  free(db);
229  return NULL;
230  }
231 
232  db->notify_list = queue_new();
233  if (!db->notify_list) {
234  queue_destroy(db->services, NULL);
235  free(db);
236  return NULL;
237  }
238 
239  db->next_handle = 0x0001;
240 
241  return gatt_db_ref(db);
242 }
243 
244 static void notify_destroy(void *data)
245 {
246  struct notify *notify = data;
247 
248  if (notify->destroy)
249  notify->destroy(notify->user_data);
250 
251  free(notify);
252 }
253 
254 static bool match_notify_id(const void *a, const void *b)
255 {
256  const struct notify *notify = a;
257  unsigned int id = PTR_TO_UINT(b);
258 
259  return notify->id == id;
260 }
261 
262 struct notify_data {
264  bool added;
265 };
266 
267 static void handle_notify(void *data, void *user_data)
268 {
269  struct notify *notify = data;
271 
272  if (notify_data->added)
273  notify->service_added(notify_data->attr, notify->user_data);
274  else
275  notify->service_removed(notify_data->attr, notify->user_data);
276 }
277 
278 static void notify_service_changed(struct gatt_db *db,
279  struct gatt_db_service *service,
280  bool added)
281 {
282  struct notify_data data;
283 
284  if (queue_isempty(db->notify_list))
285  return;
286 
287  data.attr = service->attributes[0];
288  data.added = added;
289 
290  gatt_db_ref(db);
291 
293 
294  gatt_db_unref(db);
295 }
296 
297 static void gatt_db_service_destroy(void *data)
298 {
299  struct gatt_db_service *service = data;
300  int i;
301 
302  if (service->active)
303  notify_service_changed(service->db, service, false);
304 
305  for (i = 0; i < service->num_handles; i++)
306  attribute_destroy(service->attributes[i]);
307 
308  free(service->attributes);
309  free(service);
310 }
311 
312 static void gatt_db_destroy(struct gatt_db *db)
313 {
314  if (!db)
315  return;
316 
317  /*
318  * Clear the notify list before clearing the services to prevent the
319  * latter from sending service_removed events.
320  */
322  db->notify_list = NULL;
323 
325  free(db);
326 }
327 
328 void gatt_db_unref(struct gatt_db *db)
329 {
330  if (!db)
331  return;
332 
333  if (__sync_sub_and_fetch(&db->ref_count, 1))
334  return;
335 
336  gatt_db_destroy(db);
337 }
338 
340 {
341  if (!db)
342  return true;
343 
344  return queue_isempty(db->services);
345 }
346 
347 static int uuid_to_le(const bt_uuid_t *uuid, uint8_t *dst)
348 {
349  bt_uuid_t uuid128;
350 
351  if (uuid->type == BT_UUID16) {
352  put_le16(uuid->value.u16, dst);
353  return bt_uuid_len(uuid);
354  }
355 
356  bt_uuid_to_uuid128(uuid, &uuid128);
357  bswap_128(&uuid128.value.u128, dst);
358  return bt_uuid_len(&uuid128);
359 }
360 
361 static bool le_to_uuid(const uint8_t *src, size_t len, bt_uuid_t *uuid)
362 {
363  uint128_t u128;
364 
365  if (len == 2) {
366  bt_uuid16_create(uuid, get_le16(src));
367  return true;
368  }
369 
370  if (len == 4) {
371  bt_uuid32_create(uuid, get_le32(src));
372  return true;
373  }
374 
375  if (len != 16)
376  return false;
377 
378  bswap_128(src, &u128);
379  bt_uuid128_create(uuid, u128);
380 
381  return true;
382 }
383 
385  uint16_t handle,
386  bool primary,
387  uint16_t num_handles)
388 {
389  struct gatt_db_service *service;
390  const bt_uuid_t *type;
391  uint8_t value[16];
392  uint16_t len;
393 
394  if (num_handles < 1)
395  return NULL;
396 
397  service = new0(struct gatt_db_service, 1);
398  if (!service)
399  return NULL;
400 
401  service->attributes = new0(struct gatt_db_attribute *, num_handles);
402  if (!service->attributes) {
403  free(service);
404  return NULL;
405  }
406 
407  if (primary)
408  type = &primary_service_uuid;
409  else
410  type = &secondary_service_uuid;
411 
412  len = uuid_to_le(uuid, value);
413 
414  service->attributes[0] = new_attribute(service, handle, type, value,
415  len);
416  if (!service->attributes[0]) {
417  gatt_db_service_destroy(service);
418  return NULL;
419  }
420 
421  return service;
422 }
423 
424 
426  struct gatt_db_attribute *attrib)
427 {
428  struct gatt_db_service *service;
429 
430  if (!db || !attrib)
431  return false;
432 
433  service = attrib->service;
434 
435  queue_remove(db->services, service);
436 
437  gatt_db_service_destroy(service);
438 
439  return true;
440 }
441 
442 bool gatt_db_clear(struct gatt_db *db)
443 {
444  if (!db)
445  return false;
446 
448 
449  db->next_handle = 0;
450 
451  return true;
452 }
453 
454 static void gatt_db_service_get_handles(const struct gatt_db_service *service,
455  uint16_t *start_handle,
456  uint16_t *end_handle)
457 {
458  if (start_handle)
459  *start_handle = service->attributes[0]->handle;
460 
461  if (end_handle)
462  *end_handle = service->attributes[0]->handle +
463  service->num_handles - 1;
464 }
465 
466 struct clear_range {
467  uint16_t start, end;
468 };
469 
470 static bool match_range(const void *a, const void *b)
471 {
472  const struct gatt_db_service *service = a;
473  const struct clear_range *range = b;
474  uint16_t svc_start, svc_end;
475 
476  gatt_db_service_get_handles(service, &svc_start, &svc_end);
477 
478  return svc_start <= range->end && svc_end >= range->start;
479 }
480 
481 bool gatt_db_clear_range(struct gatt_db *db, uint16_t start_handle,
482  uint16_t end_handle)
483 {
484  struct clear_range range;
485 
486  if (!db || start_handle > end_handle)
487  return false;
488 
489  range.start = start_handle;
490  range.end = end_handle;
491 
494 
495  return true;
496 }
497 
498 static struct gatt_db_service *find_insert_loc(struct gatt_db *db,
499  uint16_t start, uint16_t end,
500  struct gatt_db_service **after)
501 {
502  const struct queue_entry *services_entry;
503  struct gatt_db_service *service;
504  uint16_t cur_start, cur_end;
505 
506  *after = NULL;
507 
508  services_entry = queue_get_entries(db->services);
509 
510  while (services_entry) {
511  service = services_entry->data;
512 
513  gatt_db_service_get_handles(service, &cur_start, &cur_end);
514 
515  if (start >= cur_start && start <= cur_end)
516  return service;
517 
518  if (end >= cur_start && end <= cur_end)
519  return service;
520 
521  if (end < cur_start)
522  return NULL;
523 
524  *after = service;
525  services_entry = services_entry->next;
526  }
527 
528  return NULL;
529 }
530 
532  uint16_t handle,
533  const bt_uuid_t *uuid,
534  bool primary,
535  uint16_t num_handles)
536 {
537  struct gatt_db_service *service, *after;
538 
539  after = NULL;
540 
541  if (!db || handle < 1)
542  return NULL;
543 
544  if (num_handles < 1 || (handle + num_handles - 1) > UINT16_MAX)
545  return NULL;
546 
547  service = find_insert_loc(db, handle, handle + num_handles - 1, &after);
548  if (service) {
549  const bt_uuid_t *type;
550  bt_uuid_t value;
551 
552  if (primary)
553  type = &primary_service_uuid;
554  else
555  type = &secondary_service_uuid;
556 
558  &value);
559 
560  /* Check if service match */
561  if (!bt_uuid_cmp(&service->attributes[0]->uuid, type) &&
562  !bt_uuid_cmp(&value, uuid) &&
563  service->num_handles == num_handles &&
564  service->attributes[0]->handle == handle)
565  return service->attributes[0];
566 
567  return NULL;
568  }
569 
570  service = gatt_db_service_create(uuid, handle, primary, num_handles);
571 
572  if (!service)
573  return NULL;
574 
575  if (after) {
576  if (!queue_push_after(db->services, after, service))
577  goto fail;
578  } else if (!queue_push_head(db->services, service)) {
579  goto fail;
580  }
581 
582  service->db = db;
583  service->attributes[0]->handle = handle;
584  service->num_handles = num_handles;
585 
586  /* Fast-forward next_handle if the new service was added to the end */
587  db->next_handle = MAX(handle + num_handles, db->next_handle);
588 
589  return service->attributes[0];
590 
591 fail:
592  gatt_db_service_destroy(service);
593  return NULL;
594 }
595 
597  const bt_uuid_t *uuid,
598  bool primary,
599  uint16_t num_handles)
600 {
601  return gatt_db_insert_service(db, db->next_handle, uuid, primary,
602  num_handles);
603 }
604 
605 unsigned int gatt_db_register(struct gatt_db *db,
606  gatt_db_attribute_cb_t service_added,
607  gatt_db_attribute_cb_t service_removed,
608  void *user_data,
609  gatt_db_destroy_func_t destroy)
610 {
611  struct notify *notify;
612 
613  if (!db || !(service_added || service_removed))
614  return 0;
615 
616  notify = new0(struct notify, 1);
617  if (!notify)
618  return 0;
619 
620  notify->service_added = service_added;
622  notify->destroy = destroy;
623  notify->user_data = user_data;
624 
625  if (db->next_notify_id < 1)
626  db->next_notify_id = 1;
627 
628  notify->id = db->next_notify_id++;
629 
630  if (!queue_push_tail(db->notify_list, notify)) {
631  free(notify);
632  return 0;
633  }
634 
635  return notify->id;
636 }
637 
638 bool gatt_db_unregister(struct gatt_db *db, unsigned int id)
639 {
640  struct notify *notify;
641 
642  if (!db || !id)
643  return false;
644 
646  if (!notify)
647  return false;
648 
649  queue_remove(db->notify_list, notify);
650  notify_destroy(notify);
651 
652  return true;
653 }
654 
655 static uint16_t get_attribute_index(struct gatt_db_service *service,
656  int end_offset)
657 {
658  int i = 0;
659 
660  /* Here we look for first free attribute index with given offset */
661  while (i < (service->num_handles - end_offset) &&
662  service->attributes[i])
663  i++;
664 
665  return i == (service->num_handles - end_offset) ? 0 : i;
666 }
667 
668 static uint16_t get_handle_at_index(struct gatt_db_service *service,
669  int index)
670 {
671  return service->attributes[index]->handle;
672 }
673 
674 static struct gatt_db_attribute *
676 {
677  uint16_t previous_handle;
678 
679  /* We call this function with index > 0, because index 0 is reserved
680  * for service declaration, and is set in add_service()
681  */
682  previous_handle = service->attributes[index - 1]->handle;
683  service->attributes[index]->handle = previous_handle + 1;
684 
685  return service->attributes[index];
686 }
687 
688 static void set_attribute_data(struct gatt_db_attribute *attribute,
691  uint32_t permissions,
692  void *user_data)
693 {
694  attribute->permissions = permissions;
695  attribute->read_func = read_func;
696  attribute->write_func = write_func;
697  attribute->user_data = user_data;
698 }
699 
700 static struct gatt_db_attribute *
702  uint16_t handle,
703  const bt_uuid_t *uuid,
704  uint32_t permissions,
705  uint8_t properties,
708  void *user_data)
709 {
711  uint16_t len = 0;
712  int i;
713 
714  /* Check if handle is in within service range */
715  if (handle && handle <= service->attributes[0]->handle)
716  return NULL;
717 
718  /*
719  * It is not possible to allocate last handle for a Characteristic
720  * since it would not have space for its value:
721  * 3.3.2 Characteristic Value Declaration
722  * The Characteristic Value declaration contains the value of the
723  * characteristic. It is the first Attribute after the characteristic
724  * declaration. All characteristic definitions shall have a
725  * Characteristic Value declaration.
726  */
727  if (handle == UINT16_MAX)
728  return NULL;
729 
730  i = get_attribute_index(service, 1);
731  if (!i)
732  return NULL;
733 
734  if (!handle)
735  handle = get_handle_at_index(service, i - 1) + 2;
736 
737  value[0] = properties;
738  len += sizeof(properties);
739 
740  /* We set handle of characteristic value, which will be added next */
741  put_le16(handle, &value[1]);
742  len += sizeof(uint16_t);
743  len += uuid_to_le(uuid, &value[3]);
744 
745  service->attributes[i] = new_attribute(service, handle - 1,
746  &characteristic_uuid,
747  value, len);
748  if (!service->attributes[i])
749  return NULL;
750 
751  i++;
752 
753  service->attributes[i] = new_attribute(service, handle, uuid, NULL, 0);
754  if (!service->attributes[i]) {
755  free(service->attributes[i - 1]);
756  return NULL;
757  }
758 
759  set_attribute_data(service->attributes[i], read_func, write_func,
760  permissions, user_data);
761 
762  return service->attributes[i];
763 }
764 
765 struct gatt_db_attribute *
767  uint16_t handle,
768  const bt_uuid_t *uuid,
769  uint32_t permissions,
770  uint8_t properties,
773  void *user_data)
774 {
775  if (!attrib || !handle)
776  return NULL;
777 
778  return service_insert_characteristic(attrib->service, handle, uuid,
779  permissions, properties,
780  read_func, write_func,
781  user_data);
782 }
783 
784 struct gatt_db_attribute *
786  const bt_uuid_t *uuid,
787  uint32_t permissions,
788  uint8_t properties,
791  void *user_data)
792 {
793  if (!attrib)
794  return NULL;
795 
796  return service_insert_characteristic(attrib->service, 0, uuid,
797  permissions, properties,
798  read_func, write_func,
799  user_data);
800 }
801 
802 static struct gatt_db_attribute *
804  uint16_t handle,
805  const bt_uuid_t *uuid,
806  uint32_t permissions,
809  void *user_data)
810 {
811  int i;
812 
813  i = get_attribute_index(service, 0);
814  if (!i)
815  return NULL;
816 
817  /* Check if handle is in within service range */
818  if (handle && handle <= service->attributes[0]->handle)
819  return NULL;
820 
821  if (!handle)
822  handle = get_handle_at_index(service, i - 1) + 1;
823 
824  service->attributes[i] = new_attribute(service, handle, uuid, NULL, 0);
825  if (!service->attributes[i])
826  return NULL;
827 
828  set_attribute_data(service->attributes[i], read_func, write_func,
829  permissions, user_data);
830 
831  return service->attributes[i];
832 }
833 
834 struct gatt_db_attribute *
836  uint16_t handle,
837  const bt_uuid_t *uuid,
838  uint32_t permissions,
841  void *user_data)
842 {
843  if (!attrib || !handle)
844  return NULL;
845 
846  return service_insert_descriptor(attrib->service, handle, uuid,
847  permissions, read_func, write_func,
848  user_data);
849 }
850 
851 struct gatt_db_attribute *
853  const bt_uuid_t *uuid,
854  uint32_t permissions,
857  void *user_data)
858 {
859  if (!attrib)
860  return NULL;
861 
862  return service_insert_descriptor(attrib->service, 0, uuid,
863  permissions, read_func, write_func,
864  user_data);
865 }
866 
867 struct gatt_db_attribute *
869  struct gatt_db_attribute *include)
870 {
871  struct gatt_db_service *service, *included;
872  uint8_t value[MAX_INCLUDED_VALUE_LEN];
873  uint16_t included_handle, len = 0;
874  int index;
875 
876  if (!attrib || !include)
877  return NULL;
878 
879  service = attrib->service;
880  included = include->service;
881 
882  /* Adjust include to point to the first attribute */
883  if (include != included->attributes[0])
884  include = included->attributes[0];
885 
886  included_handle = include->handle;
887 
888  put_le16(included_handle, &value[len]);
889  len += sizeof(uint16_t);
890 
891  put_le16(included_handle + included->num_handles - 1, &value[len]);
892  len += sizeof(uint16_t);
893 
894  /* The Service UUID shall only be present when the UUID is a 16-bit
895  * Bluetooth UUID. Vol 2. Part G. 3.2
896  */
897  if (include->value_len == sizeof(uint16_t)) {
898  memcpy(&value[len], include->value, include->value_len);
899  len += include->value_len;
900  }
901 
902  index = get_attribute_index(service, 0);
903  if (!index)
904  return NULL;
905 
906  service->attributes[index] = new_attribute(service, 0,
907  &included_service_uuid,
908  value, len);
909  if (!service->attributes[index])
910  return NULL;
911 
912  /* The Attribute Permissions shall be read only and not require
913  * authentication or authorization. Vol 2. Part G. 3.2
914  *
915  * TODO handle permissions
916  */
917  set_attribute_data(service->attributes[index], NULL, NULL, 0, NULL);
918 
919  return attribute_update(service, index);
920 }
921 
923 {
924  struct gatt_db_service *service;
925 
926  if (!attrib)
927  return false;
928 
929  service = attrib->service;
930 
931  if (service->active == active)
932  return true;
933 
934  service->active = active;
935 
936  notify_service_changed(service->db, service, active);
937 
938  return true;
939 }
940 
942 {
943  if (!attrib)
944  return false;
945 
946  return attrib->service->active;
947 }
948 
950  bool claimed)
951 {
952  if (!attrib)
953  return false;
954 
955  attrib->service->claimed = claimed;
956 
957  return true;
958 }
959 
961 {
962  if (!attrib)
963  return false;
964 
965  return attrib->service->claimed;
966 }
967 
968 void gatt_db_read_by_group_type(struct gatt_db *db, uint16_t start_handle,
969  uint16_t end_handle,
970  const bt_uuid_t type,
971  struct queue *queue)
972 {
973  const struct queue_entry *services_entry;
974  struct gatt_db_service *service;
975  uint16_t grp_start, grp_end, uuid_size;
976 
977  uuid_size = 0;
978 
979  services_entry = queue_get_entries(db->services);
980 
981  while (services_entry) {
982  service = services_entry->data;
983 
984  if (!service->active)
985  goto next_service;
986 
987  if (bt_uuid_cmp(&type, &service->attributes[0]->uuid))
988  goto next_service;
989 
990  grp_start = service->attributes[0]->handle;
991  grp_end = grp_start + service->num_handles - 1;
992 
993  if (grp_end < start_handle || grp_start > end_handle)
994  goto next_service;
995 
996  if (grp_start < start_handle || grp_start > end_handle)
997  goto next_service;
998 
999  if (!uuid_size)
1000  uuid_size = service->attributes[0]->value_len;
1001  else if (uuid_size != service->attributes[0]->value_len)
1002  return;
1003 
1004  queue_push_tail(queue, service->attributes[0]);
1005 
1006 next_service:
1007  services_entry = services_entry->next;
1008  }
1009 }
1010 
1013  uint16_t start_handle;
1014  uint16_t end_handle;
1016  void *user_data;
1017  const void *value;
1018  size_t value_len;
1019  unsigned int num_of_res;
1020 };
1021 
1022 static void find_by_type(void *data, void *user_data)
1023 {
1024  struct find_by_type_value_data *search_data = user_data;
1025  struct gatt_db_service *service = data;
1026  struct gatt_db_attribute *attribute;
1027  int i;
1028 
1029  if (!service->active)
1030  return;
1031 
1032  for (i = 0; i < service->num_handles; i++) {
1033  attribute = service->attributes[i];
1034 
1035  if (!attribute)
1036  continue;
1037 
1038  if ((attribute->handle < search_data->start_handle) ||
1039  (attribute->handle > search_data->end_handle))
1040  continue;
1041 
1042  if (bt_uuid_cmp(&search_data->uuid, &attribute->uuid))
1043  continue;
1044 
1045  /* TODO: fix for read-callback based attributes */
1046  if (search_data->value && memcmp(attribute->value,
1047  search_data->value,
1048  search_data->value_len))
1049  continue;
1050 
1051  search_data->num_of_res++;
1052  search_data->func(attribute, search_data->user_data);
1053  }
1054 }
1055 
1056 unsigned int gatt_db_find_by_type(struct gatt_db *db, uint16_t start_handle,
1057  uint16_t end_handle,
1058  const bt_uuid_t *type,
1060  void *user_data)
1061 {
1062  struct find_by_type_value_data data;
1063 
1064  memset(&data, 0, sizeof(data));
1065 
1066  data.uuid = *type;
1067  data.start_handle = start_handle;
1068  data.end_handle = end_handle;
1069  data.func = func;
1070  data.user_data = user_data;
1071 
1072  queue_foreach(db->services, find_by_type, &data);
1073 
1074  return data.num_of_res;
1075 }
1076 
1077 unsigned int gatt_db_find_by_type_value(struct gatt_db *db,
1078  uint16_t start_handle,
1079  uint16_t end_handle,
1080  const bt_uuid_t *type,
1081  const void *value,
1082  size_t value_len,
1084  void *user_data)
1085 {
1086  struct find_by_type_value_data data;
1087 
1088  data.uuid = *type;
1089  data.start_handle = start_handle;
1090  data.end_handle = end_handle;
1091  data.func = func;
1092  data.user_data = user_data;
1093  data.value = value;
1094  data.value_len = value_len;
1095 
1096  queue_foreach(db->services, find_by_type, &data);
1097 
1098  return data.num_of_res;
1099 }
1100 
1102  struct queue *queue;
1104  uint16_t start_handle;
1105  uint16_t end_handle;
1106 };
1107 
1108 static void read_by_type(void *data, void *user_data)
1109 {
1110  struct read_by_type_data *search_data = user_data;
1111  struct gatt_db_service *service = data;
1112  struct gatt_db_attribute *attribute;
1113  int i;
1114 
1115  if (!service->active)
1116  return;
1117 
1118  for (i = 0; i < service->num_handles; i++) {
1119  attribute = service->attributes[i];
1120  if (!attribute)
1121  continue;
1122 
1123  if (attribute->handle < search_data->start_handle)
1124  continue;
1125 
1126  if (attribute->handle > search_data->end_handle)
1127  return;
1128 
1129  if (bt_uuid_cmp(&search_data->uuid, &attribute->uuid))
1130  continue;
1131 
1132  queue_push_tail(search_data->queue, attribute);
1133  }
1134 }
1135 
1136 void gatt_db_read_by_type(struct gatt_db *db, uint16_t start_handle,
1137  uint16_t end_handle,
1138  const bt_uuid_t type,
1139  struct queue *queue)
1140 {
1141  struct read_by_type_data data;
1142  data.uuid = type;
1143  data.start_handle = start_handle;
1144  data.end_handle = end_handle;
1145  data.queue = queue;
1146 
1147  queue_foreach(db->services, read_by_type, &data);
1148 }
1149 
1150 
1152  struct queue *queue;
1153  uint16_t start_handle;
1154  uint16_t end_handle;
1155 };
1156 
1157 static void find_information(void *data, void *user_data)
1158 {
1159  struct find_information_data *search_data = user_data;
1160  struct gatt_db_service *service = data;
1161  struct gatt_db_attribute *attribute;
1162  int i;
1163 
1164  if (!service->active)
1165  return;
1166 
1167  /* Check if service is in range */
1168  if ((service->attributes[0]->handle + service->num_handles - 1) <
1169  search_data->start_handle)
1170  return;
1171 
1172  for (i = 0; i < service->num_handles; i++) {
1173  attribute = service->attributes[i];
1174  if (!attribute)
1175  continue;
1176 
1177  if (attribute->handle < search_data->start_handle)
1178  continue;
1179 
1180  if (attribute->handle > search_data->end_handle)
1181  return;
1182 
1183  queue_push_tail(search_data->queue, attribute);
1184  }
1185 }
1186 
1187 void gatt_db_find_information(struct gatt_db *db, uint16_t start_handle,
1188  uint16_t end_handle,
1189  struct queue *queue)
1190 {
1191  struct find_information_data data;
1192 
1193  data.start_handle = start_handle;
1194  data.end_handle = end_handle;
1195  data.queue = queue;
1196 
1198 }
1199 
1200 void gatt_db_foreach_service(struct gatt_db *db, const bt_uuid_t *uuid,
1202  void *user_data)
1203 {
1204  gatt_db_foreach_service_in_range(db, uuid, func, user_data, 0x0001,
1205  0xffff);
1206 }
1207 
1210  const bt_uuid_t *uuid;
1211  void *user_data;
1212  uint16_t start, end;
1213 };
1214 
1215 static void foreach_service_in_range(void *data, void *user_data)
1216 {
1217  struct gatt_db_service *service = data;
1219  uint16_t svc_start;
1220  bt_uuid_t uuid;
1221 
1222  svc_start = get_handle_at_index(service, 0);
1223 
1224  if (svc_start > foreach_data->end || svc_start < foreach_data->start)
1225  return;
1226 
1227  if (foreach_data->uuid) {
1229  &uuid);
1230  if (bt_uuid_cmp(&uuid, foreach_data->uuid))
1231  return;
1232  }
1233 
1234  foreach_data->func(service->attributes[0], foreach_data->user_data);
1235 }
1236 
1238  const bt_uuid_t *uuid,
1240  void *user_data,
1241  uint16_t start_handle,
1242  uint16_t end_handle)
1243 {
1244  struct foreach_data data;
1245 
1246  if (!db || !func || start_handle > end_handle)
1247  return;
1248 
1249  data.func = func;
1250  data.uuid = uuid;
1251  data.user_data = user_data;
1252  data.start = start_handle;
1253  data.end = end_handle;
1254 
1256 }
1257 
1259  const bt_uuid_t *uuid,
1261  void *user_data)
1262 {
1263  struct gatt_db_service *service;
1264  struct gatt_db_attribute *attr;
1265  uint16_t i;
1266 
1267  if (!attrib || !func)
1268  return;
1269 
1270  service = attrib->service;
1271 
1272  for (i = 0; i < service->num_handles; i++) {
1273  attr = service->attributes[i];
1274  if (!attr)
1275  continue;
1276 
1277  if (uuid && bt_uuid_cmp(uuid, &attr->uuid))
1278  continue;
1279 
1280  func(attr, user_data);
1281  }
1282 }
1283 
1286  void *user_data)
1287 {
1288  gatt_db_service_foreach(attrib, &characteristic_uuid, func, user_data);
1289 }
1290 
1293  void *user_data)
1294 {
1295  struct gatt_db_service *service;
1296  struct gatt_db_attribute *attr;
1297  uint16_t i;
1298 
1299  if (!attrib || !func)
1300  return;
1301 
1302  /* Return if this attribute is not a characteristic declaration */
1303  if (bt_uuid_cmp(&characteristic_uuid, &attrib->uuid))
1304  return;
1305 
1306  service = attrib->service;
1307 
1308  /* Start from the attribute following the value handle */
1309  for (i = 0; i < service->num_handles; i++) {
1310  if (service->attributes[i] == attrib) {
1311  i += 2;
1312  break;
1313  }
1314  }
1315 
1316  for (; i < service->num_handles; i++) {
1317  attr = service->attributes[i];
1318  if (!attr)
1319  continue;
1320 
1321  /* Return if we reached the end of this characteristic */
1322  if (!bt_uuid_cmp(&characteristic_uuid, &attr->uuid) ||
1323  !bt_uuid_cmp(&included_service_uuid, &attr->uuid))
1324  return;
1325 
1326  func(attr, user_data);
1327  }
1328 }
1329 
1332  void *user_data)
1333 {
1334  gatt_db_service_foreach(attrib, &included_service_uuid, func,
1335  user_data);
1336 }
1337 
1338 static bool find_service_for_handle(const void *data, const void *user_data)
1339 {
1340  const struct gatt_db_service *service = data;
1341  uint16_t handle = PTR_TO_UINT(user_data);
1342  uint16_t start, end;
1343 
1344  gatt_db_service_get_handles(service, &start, &end);
1345 
1346  return (start <= handle) && (handle <= end);
1347 }
1348 
1350  uint16_t handle)
1351 {
1352  struct gatt_db_service *service;
1353  int i;
1354 
1355  if (!db || !handle)
1356  return NULL;
1357 
1359  UINT_TO_PTR(handle));
1360  if (!service)
1361  return NULL;
1362 
1363  for (i = 0; i < service->num_handles; i++) {
1364  if (!service->attributes[i])
1365  continue;
1366 
1367  if (service->attributes[i]->handle == handle)
1368  return service->attributes[i];
1369  }
1370 
1371  return NULL;
1372 }
1373 
1374 static bool find_service_with_uuid(const void *data, const void *user_data)
1375 {
1376  const struct gatt_db_service *service = data;
1377  const bt_uuid_t *uuid = user_data;
1378  bt_uuid_t svc_uuid;
1379 
1380  gatt_db_attribute_get_service_uuid(service->attributes[0], &svc_uuid);
1381 
1382  return bt_uuid_cmp(uuid, &svc_uuid) == 0;
1383 }
1384 
1386  const bt_uuid_t *uuid)
1387 {
1388  struct gatt_db_service *service;
1389 
1390  if (!db || !uuid)
1391  return NULL;
1392 
1393  service = queue_find(db->services, find_service_with_uuid, uuid);
1394  if (!service)
1395  return NULL;
1396 
1397  return service->attributes[0];
1398 }
1399 
1401  const struct gatt_db_attribute *attrib)
1402 {
1403  if (!attrib)
1404  return NULL;
1405 
1406  return &attrib->uuid;
1407 }
1408 
1409 uint16_t gatt_db_attribute_get_handle(const struct gatt_db_attribute *attrib)
1410 {
1411  if (!attrib)
1412  return 0;
1413 
1414  return attrib->handle;
1415 }
1416 
1418  bt_uuid_t *uuid)
1419 {
1420  struct gatt_db_service *service;
1421 
1422  if (!attrib || !uuid)
1423  return false;
1424 
1425  service = attrib->service;
1426 
1427  if (service->attributes[0]->value_len == sizeof(uint16_t)) {
1428  uint16_t value;
1429 
1430  value = get_le16(service->attributes[0]->value);
1431  bt_uuid16_create(uuid, value);
1432 
1433  return true;
1434  }
1435 
1436  if (service->attributes[0]->value_len == sizeof(uint128_t)) {
1437  uint128_t value;
1438 
1439  bswap_128(service->attributes[0]->value, &value);
1440  bt_uuid128_create(uuid, value);
1441 
1442  return true;
1443  }
1444 
1445  return false;
1446 }
1447 
1449  const struct gatt_db_attribute *attrib,
1450  uint16_t *start_handle,
1451  uint16_t *end_handle)
1452 {
1453  struct gatt_db_service *service;
1454 
1455  if (!attrib)
1456  return false;
1457 
1458  service = attrib->service;
1459 
1460  gatt_db_service_get_handles(service, start_handle, end_handle);
1461 
1462  return true;
1463 }
1464 
1466  uint16_t *start_handle,
1467  uint16_t *end_handle,
1468  bool *primary,
1469  bt_uuid_t *uuid)
1470 {
1471  struct gatt_db_service *service;
1472  struct gatt_db_attribute *decl;
1473 
1474  if (!attrib)
1475  return false;
1476 
1477  service = attrib->service;
1478  decl = service->attributes[0];
1479 
1480  gatt_db_service_get_handles(service, start_handle, end_handle);
1481 
1482  if (primary)
1483  *primary = bt_uuid_cmp(&decl->uuid, &secondary_service_uuid);
1484 
1485  if (!uuid)
1486  return true;
1487 
1488  /*
1489  * The service declaration attribute value is the 16 or 128 bit service
1490  * UUID.
1491  */
1492  return le_to_uuid(decl->value, decl->value_len, uuid);
1493 }
1494 
1496  uint16_t *handle,
1497  uint16_t *value_handle,
1498  uint8_t *properties,
1499  bt_uuid_t *uuid)
1500 {
1501  if (!attrib)
1502  return false;
1503 
1504  if (bt_uuid_cmp(&characteristic_uuid, &attrib->uuid))
1505  return false;
1506 
1507  /*
1508  * Characteristic declaration value:
1509  * 1 octet: Characteristic properties
1510  * 2 octets: Characteristic value handle
1511  * 2 or 16 octets: characteristic UUID
1512  */
1513  if (!attrib->value || (attrib->value_len != 5 &&
1514  attrib->value_len != 19))
1515  return false;
1516 
1517  if (handle)
1518  *handle = attrib->handle;
1519 
1520  if (properties)
1521  *properties = attrib->value[0];
1522 
1523  if (value_handle)
1524  *value_handle = get_le16(attrib->value + 1);
1525 
1526  if (!uuid)
1527  return true;
1528 
1529  return le_to_uuid(attrib->value + 3, attrib->value_len - 3, uuid);
1530 }
1531 
1533  uint16_t *handle,
1534  uint16_t *start_handle,
1535  uint16_t *end_handle)
1536 {
1537  if (!attrib)
1538  return false;
1539 
1540  if (bt_uuid_cmp(&included_service_uuid, &attrib->uuid))
1541  return false;
1542 
1543  /*
1544  * Include definition value:
1545  * 2 octets: start handle of included service
1546  * 2 octets: end handle of included service
1547  * optional 2 octets: 16-bit Bluetooth UUID
1548  */
1549  if (!attrib->value || attrib->value_len < 4 || attrib->value_len > 6)
1550  return false;
1551 
1552  /*
1553  * We only return the handles since the UUID can be easily obtained
1554  * from the corresponding attribute.
1555  */
1556  if (handle)
1557  *handle = attrib->handle;
1558 
1559  if (start_handle)
1560  *start_handle = get_le16(attrib->value);
1561 
1562  if (end_handle)
1563  *end_handle = get_le16(attrib->value + 2);
1564 
1565  return true;
1566 }
1567 
1568 uint32_t
1570 {
1571  if (!attrib)
1572  return 0;
1573 
1574  return attrib->permissions;
1575 }
1576 
1577 static bool read_timeout(void *user_data)
1578 {
1579  struct pending_read *p = user_data;
1580 
1581  p->timeout_id = 0;
1582 
1584 
1585  pending_read_result(p, -ETIMEDOUT, NULL, 0);
1586 
1587  return false;
1588 }
1589 
1590 bool gatt_db_attribute_read(struct gatt_db_attribute *attrib, uint16_t offset,
1591  uint8_t opcode, struct bt_att *att,
1593 {
1594  uint8_t *value;
1595 
1596  if (!attrib || !func)
1597  return false;
1598 
1599  if (attrib->read_func) {
1600  struct pending_read *p;
1601 
1602  p = new0(struct pending_read, 1);
1603  if (!p)
1604  return false;
1605 
1606  p->attrib = attrib;
1607  p->id = ++attrib->read_id;
1609  p, NULL);
1610  p->func = func;
1611  p->user_data = user_data;
1612 
1613  queue_push_tail(attrib->pending_reads, p);
1614 
1615  attrib->read_func(attrib, p->id, offset, opcode, att,
1616  attrib->user_data);
1617  return true;
1618  }
1619 
1620  /* Check boundary if value is stored in the db */
1621  if (offset > attrib->value_len) {
1622  func(attrib, BT_ATT_ERROR_INVALID_OFFSET, NULL, 0, user_data);
1623  return true;
1624  }
1625 
1626  /* Guard against invalid access if offset equals to value length */
1627  value = offset == attrib->value_len ? NULL : &attrib->value[offset];
1628 
1629  func(attrib, 0, value, attrib->value_len - offset, user_data);
1630 
1631  return true;
1632 }
1633 
1634 static bool find_pending(const void *a, const void *b)
1635 {
1636  const struct pending_read *p = a;
1637  unsigned int id = PTR_TO_UINT(b);
1638 
1639  return p->id == id;
1640 }
1641 
1643  unsigned int id, int err,
1644  const uint8_t *value, size_t length)
1645 {
1646  struct pending_read *p;
1647 
1648  if (!attrib || !id)
1649  return false;
1650 
1652  UINT_TO_PTR(id));
1653  if (!p)
1654  return false;
1655 
1656  pending_read_result(p, err, value, length);
1657 
1658  return true;
1659 }
1660 
1661 static bool write_timeout(void *user_data)
1662 {
1663  struct pending_write *p = user_data;
1664 
1665  p->timeout_id = 0;
1666 
1668 
1669  pending_write_result(p, -ETIMEDOUT);
1670 
1671  return false;
1672 }
1673 
1674 bool gatt_db_attribute_write(struct gatt_db_attribute *attrib, uint16_t offset,
1675  const uint8_t *value, size_t len,
1676  uint8_t opcode, struct bt_att *att,
1678  void *user_data)
1679 {
1680  if (!attrib || !func)
1681  return false;
1682 
1683  if (attrib->write_func) {
1684  struct pending_write *p;
1685 
1686  p = new0(struct pending_write, 1);
1687  if (!p)
1688  return false;
1689 
1690  p->attrib = attrib;
1691  p->id = ++attrib->write_id;
1693  p, NULL);
1694  p->func = func;
1695  p->user_data = user_data;
1696 
1697  queue_push_tail(attrib->pending_writes, p);
1698 
1699  attrib->write_func(attrib, p->id, offset, value, len, opcode,
1700  att, attrib->user_data);
1701  return true;
1702  }
1703 
1704  /* Nothing to write just skip */
1705  if (len == 0)
1706  goto done;
1707 
1708  /* For values stored in db allocate on demand */
1709  if (!attrib->value || offset >= attrib->value_len ||
1710  len > (unsigned) (attrib->value_len - offset)) {
1711  void *buf;
1712 
1713  buf = realloc(attrib->value, len + offset);
1714  if (!buf)
1715  return false;
1716 
1717  attrib->value = buf;
1718 
1719  /* Init data in the first allocation */
1720  if (!attrib->value_len)
1721  memset(attrib->value, 0, offset);
1722 
1723  attrib->value_len = len + offset;
1724  }
1725 
1726  memcpy(&attrib->value[offset], value, len);
1727 
1728 done:
1729  func(attrib, 0, user_data);
1730 
1731  return true;
1732 }
1733 
1735  unsigned int id, int err)
1736 {
1737  struct pending_write *p;
1738 
1739  if (!attrib || !id)
1740  return false;
1741 
1743  UINT_TO_PTR(id));
1744  if (!p)
1745  return false;
1746 
1747  pending_write_result(p, err);
1748 
1749  return true;
1750 }
1751 
1753 {
1754  if (!attrib)
1755  return false;
1756 
1757  if (!attrib->value || !attrib->value_len)
1758  return true;
1759 
1760  free(attrib->value);
1761  attrib->value = NULL;
1762  attrib->value_len = 0;
1763 
1764  return true;
1765 }
uint128_t u128
Definition: uuid.h:152
bool gatt_db_attribute_write_result(struct gatt_db_attribute *attrib, unsigned int id, int err)
Definition: gatt-db.c:1734
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 le_to_uuid(const uint8_t *src, size_t len, bt_uuid_t *uuid)
Definition: gatt-db.c:361
command_func_t func
static struct gatt_db_attribute * attribute_update(struct gatt_db_service *service, int index)
Definition: gatt-db.c:675
void * queue_find(struct queue *queue, queue_match_func_t function, const void *match_data)
Definition: queue.c:376
void(* gatt_db_read_t)(struct gatt_db_attribute *attrib, unsigned int id, uint16_t offset, uint8_t opcode, struct bt_att *att, void *user_data)
Definition: gatt-db.h:51
enum att_op_type type
Definition: att.c:141
void queue_foreach(struct queue *queue, queue_foreach_func_t function, void *user_data)
Definition: queue.c:325
const struct queue_entry * queue_get_entries(struct queue *queue)
Definition: queue.c:540
static void gatt_db_service_destroy(void *data)
Definition: gatt-db.c:297
struct gatt_db_attribute * attrib
Definition: gatt-db.c:79
uint32_t gatt_db_attribute_get_permissions(const struct gatt_db_attribute *attrib)
Definition: gatt-db.c:1569
void gatt_db_service_foreach(struct gatt_db_attribute *attrib, const bt_uuid_t *uuid, gatt_db_attribute_cb_t func, void *user_data)
Definition: gatt-db.c:1258
void gatt_db_unref(struct gatt_db *db)
Definition: gatt-db.c:328
uint8_t * value
Definition: gatt-db.c:100
bool added
Definition: gatt-db.c:264
void(* gatt_db_attribute_write_t)(struct gatt_db_attribute *attrib, int err, void *user_data)
Definition: gatt-db.h:224
static bool read_timeout(void *user_data)
Definition: gatt-db.c:1577
struct gatt_db_attribute * attr
Definition: gatt-db.c:263
void * data
Definition: queue.h:32
static void pending_write_free(void *data)
Definition: gatt-db.c:149
static bool find_service_with_uuid(const void *data, const void *user_data)
Definition: gatt-db.c:1374
gatt_db_destroy_func_t destroy
Definition: gatt-db.c:74
uint16_t gatt_db_attribute_get_handle(const struct gatt_db_attribute *attrib)
Definition: gatt-db.c:1409
void(* gatt_db_attribute_cb_t)(struct gatt_db_attribute *attrib, void *user_data)
Definition: gatt-db.h:107
bool queue_push_after(struct queue *queue, void *entry, void *data)
Definition: queue.c:229
unsigned int write_id
Definition: gatt-db.c:109
const bt_uuid_t * gatt_db_attribute_get_type(const struct gatt_db_attribute *attrib)
Definition: gatt-db.c:1400
int bt_uuid32_create(bt_uuid_t *btuuid, uint32_t value)
Definition: uuid.c:117
unsigned int id
Definition: gatt-db.c:80
bool gatt_db_attribute_write(struct gatt_db_attribute *attrib, uint16_t offset, const uint8_t *value, size_t len, uint8_t opcode, struct bt_att *att, gatt_db_attribute_write_t func, void *user_data)
Definition: gatt-db.c:1674
Definition: gatt-db.c:70
#define BT_ATT_ERROR_INVALID_OFFSET
Definition: att-types.h:87
unsigned int read_id
Definition: gatt-db.c:106
bool gatt_db_attribute_get_service_uuid(const struct gatt_db_attribute *attrib, bt_uuid_t *uuid)
Definition: gatt-db.c:1417
void gatt_db_foreach_service_in_range(struct gatt_db *db, const bt_uuid_t *uuid, gatt_db_attribute_cb_t func, void *user_data, uint16_t start_handle, uint16_t end_handle)
Definition: gatt-db.c:1237
unsigned int next_notify_id
Definition: gatt-db.c:67
struct gatt_db_attribute * gatt_db_service_add_included(struct gatt_db_attribute *attrib, struct gatt_db_attribute *include)
Definition: gatt-db.c:868
struct queue * queue
Definition: gatt-db.c:1152
uint16_t u16
Definition: uuid.h:150
void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
Definition: uuid.c:85
uint16_t value_len
Definition: gatt-db.c:99
#define GATT_PRIM_SVC_UUID
Definition: uuid.h:110
static int uuid_to_le(const bt_uuid_t *uuid, uint8_t *dst)
Definition: gatt-db.c:347
static bool match_notify_id(const void *a, const void *b)
Definition: gatt-db.c:254
static bool match_range(const void *a, const void *b)
Definition: gatt-db.c:470
bool gatt_db_remove_service(struct gatt_db *db, struct gatt_db_attribute *attrib)
Definition: gatt-db.c:425
static struct gatt_db_service * gatt_db_service_create(const bt_uuid_t *uuid, uint16_t handle, bool primary, uint16_t num_handles)
Definition: gatt-db.c:384
#define GATT_INCLUDE_UUID
Definition: uuid.h:112
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
Definition: queue.h:30
gatt_db_attribute_cb_t service_removed
Definition: gatt-db.c:73
void gatt_db_service_foreach_char(struct gatt_db_attribute *attrib, gatt_db_attribute_cb_t func, void *user_data)
Definition: gatt-db.c:1284
static void pending_read_free(void *data)
Definition: gatt-db.c:132
bool gatt_db_service_set_active(struct gatt_db_attribute *attrib, bool active)
Definition: gatt-db.c:922
static struct gatt_db_service * find_insert_loc(struct gatt_db *db, uint16_t start, uint16_t end, struct gatt_db_service **after)
Definition: gatt-db.c:498
static bool find_pending(const void *a, const void *b)
Definition: gatt-db.c:1634
uint16_t start_handle
Definition: gatt-db.c:1104
struct gatt_db_attribute * gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib, 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:785
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
union bt_uuid_t::@8 value
void * user_data
Definition: gatt-db.c:75
bool gatt_db_service_get_claimed(struct gatt_db_attribute *attrib)
Definition: gatt-db.c:960
uint16_t end
Definition: gatt-db.c:467
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
void gatt_db_find_information(struct gatt_db *db, uint16_t start_handle, uint16_t end_handle, struct queue *queue)
Definition: gatt-db.c:1187
Definition: queue.c:40
unsigned int id
Definition: gatt-db.c:71
struct queue * pending_reads
Definition: gatt-db.c:107
struct queue * services
Definition: gatt-db.c:64
struct gatt_db * gatt_db_new(void)
Definition: gatt-db.c:218
static void put_le16(uint16_t val, void *dst)
Definition: util.h:130
void * user_data
Definition: gatt-db.c:83
bool queue_isempty(struct queue *queue)
Definition: queue.c:569
unsigned int gatt_db_register(struct gatt_db *db, gatt_db_attribute_cb_t service_added, gatt_db_attribute_cb_t service_removed, void *user_data, gatt_db_destroy_func_t destroy)
Definition: gatt-db.c:605
void * user_data
Definition: gatt-db.c:104
void * user_data
Definition: gatt-db.c:91
uint32_t permissions
Definition: gatt-db.c:98
bool gatt_db_attribute_reset(struct gatt_db_attribute *attrib)
Definition: gatt-db.c:1752
uint16_t next_handle
Definition: gatt-db.c:63
int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2)
Definition: uuid.c:135
static const bt_uuid_t primary_service_uuid
Definition: gatt-db.c:52
void gatt_db_service_foreach_incl(struct gatt_db_attribute *attrib, gatt_db_attribute_cb_t func, void *user_data)
Definition: gatt-db.c:1330
#define malloc0(n)
Definition: util.h:84
bool gatt_db_isempty(struct gatt_db *db)
Definition: gatt-db.c:339
static const bt_uuid_t secondary_service_uuid
Definition: gatt-db.c:54
uint16_t num_handles
Definition: gatt-db.c:117
enum bt_uuid_t::@7 type
uint16_t start_handle
Definition: gatt-db.c:1153
bool gatt_db_attribute_get_service_data(const struct gatt_db_attribute *attrib, uint16_t *start_handle, uint16_t *end_handle, bool *primary, bt_uuid_t *uuid)
Definition: gatt-db.c:1465
void queue_destroy(struct queue *queue, queue_destroy_func_t destroy)
Definition: queue.c:102
struct gatt_db_attribute * gatt_db_get_service_with_uuid(struct gatt_db *db, const bt_uuid_t *uuid)
Definition: gatt-db.c:1385
struct queue * pending_writes
Definition: gatt-db.c:110
gatt_db_attribute_read_t func
Definition: gatt-db.c:82
static uint32_t get_le32(const void *ptr)
Definition: util.h:110
static void read_by_type(void *data, void *user_data)
Definition: gatt-db.c:1108
#define MAX_CHAR_DECL_VALUE_LEN
Definition: gatt-db.c:48
unsigned int timeout_id
Definition: gatt-db.c:89
#define PTR_TO_UINT(p)
Definition: util.h:76
gatt_db_attribute_cb_t service_added
Definition: gatt-db.c:72
uint16_t start
Definition: gatt-db.c:467
bool gatt_db_clear_range(struct gatt_db *db, uint16_t start_handle, uint16_t end_handle)
Definition: gatt-db.c:481
bt_uuid_t uuid
Definition: gatt-db.c:1103
static void pending_read_result(struct pending_read *p, int err, const uint8_t *data, size_t length)
Definition: gatt-db.c:121
static int bt_uuid_len(const bt_uuid_t *uuid)
Definition: uuid.h:172
bool queue_push_tail(struct queue *queue, void *data)
Definition: queue.c:167
struct queue * queue_new(void)
Definition: queue.c:81
void gatt_db_foreach_service(struct gatt_db *db, const bt_uuid_t *uuid, gatt_db_attribute_cb_t func, void *user_data)
Definition: gatt-db.c:1200
struct gatt_db * db
Definition: gatt-db.c:114
uint16_t handle
Definition: gatt-db.c:96
static const bt_uuid_t characteristic_uuid
Definition: gatt-db.c:56
bool queue_remove(struct queue *queue, void *data)
Definition: queue.c:402
static bool write_timeout(void *user_data)
Definition: gatt-db.c:1661
bool gatt_db_attribute_get_incl_data(const struct gatt_db_attribute *attrib, uint16_t *handle, uint16_t *start_handle, uint16_t *end_handle)
Definition: gatt-db.c:1532
#define MAX(a, b)
Definition: gatt-db.c:45
static uint16_t get_attribute_index(struct gatt_db_service *service, int end_offset)
Definition: gatt-db.c:655
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
static void set_attribute_data(struct gatt_db_attribute *attribute, gatt_db_read_t read_func, gatt_db_write_t write_func, uint32_t permissions, void *user_data)
Definition: gatt-db.c:688
static void gatt_db_destroy(struct gatt_db *db)
Definition: gatt-db.c:312
static void pending_write_result(struct pending_write *p, int err)
Definition: gatt-db.c:139
gatt_db_attribute_cb_t func
Definition: gatt-db.c:1015
static void find_information(void *data, void *user_data)
Definition: gatt-db.c:1157
void(* gatt_db_destroy_func_t)(void *user_data)
Definition: gatt-db.h:164
static void bswap_128(const void *src, void *dst)
Definition: bluetooth.h:346
unsigned int num_of_res
Definition: gatt-db.c:1019
gatt_db_read_t read_func
Definition: gatt-db.c:102
int bt_uuid16_create(bt_uuid_t *btuuid, uint16_t value)
Definition: uuid.c:108
gatt_db_attribute_cb_t func
Definition: gatt-db.c:1209
struct queue * queue
Definition: gatt-db.c:1102
unsigned int gatt_db_find_by_type_value(struct gatt_db *db, uint16_t start_handle, uint16_t end_handle, const bt_uuid_t *type, const void *value, size_t value_len, gatt_db_attribute_cb_t func, void *user_data)
Definition: gatt-db.c:1077
static const bt_uuid_t included_service_uuid
Definition: gatt-db.c:58
static void attribute_destroy(struct gatt_db_attribute *attribute)
Definition: gatt-db.c:156
void gatt_db_read_by_group_type(struct gatt_db *db, uint16_t start_handle, uint16_t end_handle, const bt_uuid_t type, struct queue *queue)
Definition: gatt-db.c:968
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
uint16_t end
Definition: gatt-db.c:1212
#define UINT_TO_PTR(u)
Definition: util.h:77
gatt_db_write_t write_func
Definition: gatt-db.c:103
const bt_uuid_t * uuid
Definition: gatt-db.c:1210
gatt_db_attribute_write_t func
Definition: gatt-db.c:90
void * user_data
Definition: gatt-client.c:215
static void find_by_type(void *data, void *user_data)
Definition: gatt-db.c:1022
static struct gatt_db_attribute * service_insert_descriptor(struct gatt_db_service *service, 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:803
void * queue_remove_if(struct queue *queue, queue_match_func_t function, void *user_data)
Definition: queue.c:440
bool gatt_db_clear(struct gatt_db *db)
Definition: gatt-db.c:442
static struct gatt_db_attribute * service_insert_characteristic(struct gatt_db_service *service, 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:701
bt_uuid_t uuid
Definition: gatt-db.c:97
bool gatt_db_attribute_read_result(struct gatt_db_attribute *attrib, unsigned int id, int err, const uint8_t *value, size_t length)
Definition: gatt-db.c:1642
static uint16_t get_handle_at_index(struct gatt_db_service *service, int index)
Definition: gatt-db.c:668
static struct gatt_db_attribute * new_attribute(struct gatt_db_service *service, uint16_t handle, const bt_uuid_t *type, const uint8_t *val, uint16_t len)
Definition: gatt-db.c:169
int ref_count
Definition: gatt-db.c:62
void(* gatt_db_attribute_read_t)(struct gatt_db_attribute *attrib, int err, const uint8_t *value, size_t length, void *user_data)
Definition: gatt-db.h:212
Definition: att.c:64
static void notify_service_changed(struct gatt_db *db, struct gatt_db_service *service, bool added)
Definition: gatt-db.c:278
struct gatt_db * gatt_db_ref(struct gatt_db *db)
Definition: gatt-db.c:208
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
struct gatt_db_attribute * gatt_db_get_attribute(struct gatt_db *db, uint16_t handle)
Definition: gatt-db.c:1349
Definition: crypto.c:447
unsigned int timeout_id
Definition: gatt-db.c:81
static void handle_notify(void *data, void *user_data)
Definition: gatt-db.c:267
#define ATTRIBUTE_TIMEOUT
Definition: gatt-db.c:50
static void foreach_service_in_range(void *data, void *user_data)
Definition: gatt-db.c:1215
unsigned int timeout_add(unsigned int timeout, timeout_func_t func, void *user_data, timeout_destroy_func_t destroy)
Definition: timeout-glib.c:58
struct queue_entry * next
Definition: queue.h:33
uint16_t end_handle
Definition: gatt-db.c:1105
const void * value
Definition: gatt-db.c:1017
struct gatt_db_attribute * gatt_db_add_service(struct gatt_db *db, const bt_uuid_t *uuid, bool primary, uint16_t num_handles)
Definition: gatt-db.c:596
bool gatt_db_attribute_read(struct gatt_db_attribute *attrib, uint16_t offset, uint8_t opcode, struct bt_att *att, gatt_db_attribute_read_t func, void *user_data)
Definition: gatt-db.c:1590
static uint16_t get_le16(const void *ptr)
Definition: util.h:100
void * user_data
Definition: gatt-db.c:1211
void gatt_db_read_by_type(struct gatt_db *db, uint16_t start_handle, uint16_t end_handle, const bt_uuid_t type, struct queue *queue)
Definition: gatt-db.c:1136
static void gatt_db_service_get_handles(const struct gatt_db_service *service, uint16_t *start_handle, uint16_t *end_handle)
Definition: gatt-db.c:454
void(* gatt_db_write_t)(struct gatt_db_attribute *attrib, unsigned int id, uint16_t offset, const uint8_t *value, size_t len, uint8_t opcode, struct bt_att *att, void *user_data)
Definition: gatt-db.h:56
#define new0(t, n)
Definition: util.h:82
struct gatt_db_attribute * attrib
Definition: gatt-db.c:87
void timeout_remove(unsigned int id)
Definition: timeout-glib.c:80
struct queue * notify_list
Definition: gatt-db.c:66
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
bool gatt_db_unregister(struct gatt_db *db, unsigned int id)
Definition: gatt-db.c:638
uint8_t opcode
Definition: att.c:140
bool gatt_db_service_set_claimed(struct gatt_db_attribute *attrib, bool claimed)
Definition: gatt-db.c:949
unsigned int id
Definition: gatt-db.c:88
struct gatt_db_service * service
Definition: gatt-db.c:95
uint16_t start
Definition: gatt-db.c:1212
struct gatt_db_attribute * gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib, 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:852
static void notify_destroy(void *data)
Definition: gatt-db.c:244
struct gatt_db_attribute ** attributes
Definition: gatt-db.c:118
#define GATT_SND_SVC_UUID
Definition: uuid.h:111
int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value)
Definition: uuid.c:126
#define GATT_CHARAC_UUID
Definition: uuid.h:113
#define MAX_INCLUDED_VALUE_LEN
Definition: gatt-db.c:49
static bool find_service_for_handle(const void *data, const void *user_data)
Definition: gatt-db.c:1338
bool gatt_db_service_get_active(struct gatt_db_attribute *attrib)
Definition: gatt-db.c:941
bool queue_push_head(struct queue *queue, void *data)
Definition: queue.c:198