45 #define MAX(a, b) ((a) > (b) ? (a) : (b))
48 #define MAX_CHAR_DECL_VALUE_LEN 19
49 #define MAX_INCLUDED_VALUE_LEN 6
50 #define ATTRIBUTE_TIMEOUT 5000
122 const uint8_t *data,
size_t length)
165 free(attribute->
value);
187 if (!attribute->
value)
190 memcpy(attribute->
value, val, len);
259 return notify->
id ==
id;
272 if (notify_data->
added)
333 if (__sync_sub_and_fetch(&db->
ref_count, 1))
351 if (uuid->
type == BT_UUID16) {
455 uint16_t *start_handle,
456 uint16_t *end_handle)
474 uint16_t svc_start, svc_end;
478 return svc_start <= range->
end && svc_end >= range->
start;
486 if (!db || start_handle > end_handle)
489 range.
start = start_handle;
490 range.
end = end_handle;
499 uint16_t start, uint16_t end,
504 uint16_t cur_start, cur_end;
510 while (services_entry) {
511 service = services_entry->
data;
515 if (start >= cur_start && start <= cur_end)
518 if (end >= cur_start && end <= cur_end)
525 services_entry = services_entry->
next;
535 uint16_t num_handles)
541 if (!db || handle < 1)
544 if (num_handles < 1 || (handle + num_handles - 1) > UINT16_MAX)
547 service =
find_insert_loc(db, handle, handle + num_handles - 1, &after);
599 uint16_t num_handles)
613 if (!db || !(service_added || service_removed))
616 notify =
new0(
struct notify, 1);
665 return i == (service->
num_handles - end_offset) ? 0 : i;
677 uint16_t previous_handle;
715 if (handle && handle <= service->attributes[0]->handle)
727 if (handle == UINT16_MAX)
737 value[0] = properties;
738 len +=
sizeof(properties);
742 len +=
sizeof(uint16_t);
746 &characteristic_uuid,
760 permissions, user_data);
775 if (!attrib || !handle)
779 permissions, properties,
780 read_func, write_func,
797 permissions, properties,
798 read_func, write_func,
818 if (handle && handle <= service->attributes[0]->handle)
829 permissions, user_data);
843 if (!attrib || !handle)
847 permissions, read_func, write_func,
863 permissions, read_func, write_func,
873 uint16_t included_handle, len = 0;
876 if (!attrib || !include)
886 included_handle = include->
handle;
888 put_le16(included_handle, &value[len]);
889 len +=
sizeof(uint16_t);
892 len +=
sizeof(uint16_t);
897 if (include->
value_len ==
sizeof(uint16_t)) {
907 &included_service_uuid,
931 if (service->
active == active)
975 uint16_t grp_start, grp_end, uuid_size;
981 while (services_entry) {
982 service = services_entry->
data;
993 if (grp_end < start_handle || grp_start > end_handle)
996 if (grp_start < start_handle || grp_start > end_handle)
1007 services_entry = services_entry->
next;
1046 if (search_data->
value && memcmp(attribute->
value,
1057 uint16_t end_handle,
1064 memset(&data, 0,
sizeof(data));
1137 uint16_t end_handle,
1188 uint16_t end_handle,
1224 if (svc_start > foreach_data->
end || svc_start < foreach_data->
start)
1227 if (foreach_data->
uuid) {
1241 uint16_t start_handle,
1242 uint16_t end_handle)
1246 if (!db || !func || start_handle > end_handle)
1252 data.
start = start_handle;
1253 data.
end = end_handle;
1267 if (!attrib || !func)
1280 func(attr, user_data);
1299 if (!attrib || !func)
1326 func(attr, user_data);
1342 uint16_t start, end;
1346 return (start <= handle) && (handle <= end);
1406 return &attrib->
uuid;
1422 if (!attrib || !uuid)
1450 uint16_t *start_handle,
1451 uint16_t *end_handle)
1466 uint16_t *start_handle,
1467 uint16_t *end_handle,
1497 uint16_t *value_handle,
1498 uint8_t *properties,
1518 *handle = attrib->
handle;
1521 *properties = attrib->
value[0];
1534 uint16_t *start_handle,
1535 uint16_t *end_handle)
1557 *handle = attrib->
handle;
1596 if (!attrib || !func)
1615 attrib->
read_func(attrib, p->
id, offset, opcode, att,
1627 value = offset == attrib->
value_len ? NULL : &attrib->
value[offset];
1629 func(attrib, 0, value, attrib->
value_len - offset, user_data);
1643 unsigned int id,
int err,
1644 const uint8_t *value,
size_t length)
1675 const uint8_t *value,
size_t len,
1680 if (!attrib || !func)
1699 attrib->
write_func(attrib, p->
id, offset, value, len, opcode,
1710 len > (
unsigned) (attrib->
value_len - offset)) {
1713 buf = realloc(attrib->
value, len + offset);
1717 attrib->
value = buf;
1721 memset(attrib->
value, 0, offset);
1726 memcpy(&attrib->
value[offset], value, len);
1729 func(attrib, 0, user_data);
1735 unsigned int id,
int err)
1760 free(attrib->
value);
1761 attrib->
value = NULL;
bool gatt_db_attribute_write_result(struct gatt_db_attribute *attrib, unsigned int id, int err)
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)
static bool le_to_uuid(const uint8_t *src, size_t len, bt_uuid_t *uuid)
static struct gatt_db_attribute * attribute_update(struct gatt_db_service *service, int index)
void * queue_find(struct queue *queue, queue_match_func_t function, const void *match_data)
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)
void queue_foreach(struct queue *queue, queue_foreach_func_t function, void *user_data)
const struct queue_entry * queue_get_entries(struct queue *queue)
static void gatt_db_service_destroy(void *data)
struct gatt_db_attribute * attrib
uint32_t gatt_db_attribute_get_permissions(const struct gatt_db_attribute *attrib)
void gatt_db_service_foreach(struct gatt_db_attribute *attrib, const bt_uuid_t *uuid, gatt_db_attribute_cb_t func, void *user_data)
void gatt_db_unref(struct gatt_db *db)
void(* gatt_db_attribute_write_t)(struct gatt_db_attribute *attrib, int err, void *user_data)
static bool read_timeout(void *user_data)
struct gatt_db_attribute * attr
static void pending_write_free(void *data)
static bool find_service_with_uuid(const void *data, const void *user_data)
gatt_db_destroy_func_t destroy
uint16_t gatt_db_attribute_get_handle(const struct gatt_db_attribute *attrib)
void(* gatt_db_attribute_cb_t)(struct gatt_db_attribute *attrib, void *user_data)
bool queue_push_after(struct queue *queue, void *entry, void *data)
const bt_uuid_t * gatt_db_attribute_get_type(const struct gatt_db_attribute *attrib)
int bt_uuid32_create(bt_uuid_t *btuuid, uint32_t value)
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)
#define BT_ATT_ERROR_INVALID_OFFSET
bool gatt_db_attribute_get_service_uuid(const struct gatt_db_attribute *attrib, bt_uuid_t *uuid)
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)
unsigned int next_notify_id
struct gatt_db_attribute * gatt_db_service_add_included(struct gatt_db_attribute *attrib, struct gatt_db_attribute *include)
void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
#define GATT_PRIM_SVC_UUID
static int uuid_to_le(const bt_uuid_t *uuid, uint8_t *dst)
static bool match_notify_id(const void *a, const void *b)
static bool match_range(const void *a, const void *b)
bool gatt_db_remove_service(struct gatt_db *db, struct gatt_db_attribute *attrib)
static struct gatt_db_service * gatt_db_service_create(const bt_uuid_t *uuid, uint16_t handle, bool primary, uint16_t num_handles)
#define GATT_INCLUDE_UUID
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)
gatt_db_attribute_cb_t service_removed
void gatt_db_service_foreach_char(struct gatt_db_attribute *attrib, gatt_db_attribute_cb_t func, void *user_data)
static void pending_read_free(void *data)
bool gatt_db_service_set_active(struct gatt_db_attribute *attrib, bool active)
static struct gatt_db_service * find_insert_loc(struct gatt_db *db, uint16_t start, uint16_t end, struct gatt_db_service **after)
static bool find_pending(const void *a, const void *b)
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)
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)
union bt_uuid_t::@8 value
bool gatt_db_service_get_claimed(struct gatt_db_attribute *attrib)
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)
void gatt_db_find_information(struct gatt_db *db, uint16_t start_handle, uint16_t end_handle, struct queue *queue)
struct queue * pending_reads
struct gatt_db * gatt_db_new(void)
static void put_le16(uint16_t val, void *dst)
bool queue_isempty(struct queue *queue)
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)
bool gatt_db_attribute_reset(struct gatt_db_attribute *attrib)
int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2)
static const bt_uuid_t primary_service_uuid
void gatt_db_service_foreach_incl(struct gatt_db_attribute *attrib, gatt_db_attribute_cb_t func, void *user_data)
bool gatt_db_isempty(struct gatt_db *db)
static const bt_uuid_t secondary_service_uuid
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)
void queue_destroy(struct queue *queue, queue_destroy_func_t destroy)
struct gatt_db_attribute * gatt_db_get_service_with_uuid(struct gatt_db *db, const bt_uuid_t *uuid)
struct queue * pending_writes
gatt_db_attribute_read_t func
static uint32_t get_le32(const void *ptr)
static void read_by_type(void *data, void *user_data)
#define MAX_CHAR_DECL_VALUE_LEN
gatt_db_attribute_cb_t service_added
bool gatt_db_clear_range(struct gatt_db *db, uint16_t start_handle, uint16_t end_handle)
static void pending_read_result(struct pending_read *p, int err, const uint8_t *data, size_t length)
static int bt_uuid_len(const bt_uuid_t *uuid)
bool queue_push_tail(struct queue *queue, void *data)
struct queue * queue_new(void)
void gatt_db_foreach_service(struct gatt_db *db, const bt_uuid_t *uuid, gatt_db_attribute_cb_t func, void *user_data)
static const bt_uuid_t characteristic_uuid
bool queue_remove(struct queue *queue, void *data)
static bool write_timeout(void *user_data)
bool gatt_db_attribute_get_incl_data(const struct gatt_db_attribute *attrib, uint16_t *handle, uint16_t *start_handle, uint16_t *end_handle)
static uint16_t get_attribute_index(struct gatt_db_service *service, int end_offset)
unsigned int queue_remove_all(struct queue *queue, queue_match_func_t function, void *user_data, queue_destroy_func_t destroy)
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)
static void gatt_db_destroy(struct gatt_db *db)
static void pending_write_result(struct pending_write *p, int err)
gatt_db_attribute_cb_t func
static void find_information(void *data, void *user_data)
void(* gatt_db_destroy_func_t)(void *user_data)
static void bswap_128(const void *src, void *dst)
int bt_uuid16_create(bt_uuid_t *btuuid, uint16_t value)
gatt_db_attribute_cb_t func
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)
static const bt_uuid_t included_service_uuid
static void attribute_destroy(struct gatt_db_attribute *attribute)
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)
bool gatt_db_attribute_get_service_handles(const struct gatt_db_attribute *attrib, uint16_t *start_handle, uint16_t *end_handle)
gatt_db_write_t write_func
gatt_db_attribute_write_t func
static void find_by_type(void *data, void *user_data)
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)
void * queue_remove_if(struct queue *queue, queue_match_func_t function, void *user_data)
bool gatt_db_clear(struct gatt_db *db)
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)
bool gatt_db_attribute_read_result(struct gatt_db_attribute *attrib, unsigned int id, int err, const uint8_t *value, size_t length)
static uint16_t get_handle_at_index(struct gatt_db_service *service, int index)
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)
void(* gatt_db_attribute_read_t)(struct gatt_db_attribute *attrib, int err, const uint8_t *value, size_t length, void *user_data)
static void notify_service_changed(struct gatt_db *db, struct gatt_db_service *service, bool added)
struct gatt_db * gatt_db_ref(struct gatt_db *db)
void gatt_db_service_foreach_desc(struct gatt_db_attribute *attrib, gatt_db_attribute_cb_t func, void *user_data)
struct gatt_db_attribute * gatt_db_get_attribute(struct gatt_db *db, uint16_t handle)
static void handle_notify(void *data, void *user_data)
#define ATTRIBUTE_TIMEOUT
static void foreach_service_in_range(void *data, void *user_data)
unsigned int timeout_add(unsigned int timeout, timeout_func_t func, void *user_data, timeout_destroy_func_t destroy)
struct queue_entry * next
struct gatt_db_attribute * gatt_db_add_service(struct gatt_db *db, const bt_uuid_t *uuid, bool primary, uint16_t num_handles)
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)
static uint16_t get_le16(const void *ptr)
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)
static void gatt_db_service_get_handles(const struct gatt_db_service *service, uint16_t *start_handle, uint16_t *end_handle)
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)
struct gatt_db_attribute * attrib
void timeout_remove(unsigned int id)
struct queue * notify_list
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)
bool gatt_db_unregister(struct gatt_db *db, unsigned int id)
bool gatt_db_service_set_claimed(struct gatt_db_attribute *attrib, bool claimed)
struct gatt_db_service * service
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)
static void notify_destroy(void *data)
struct gatt_db_attribute ** attributes
#define GATT_SND_SVC_UUID
int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value)
#define MAX_INCLUDED_VALUE_LEN
static bool find_service_for_handle(const void *data, const void *user_data)
bool gatt_db_service_get_active(struct gatt_db_attribute *attrib)
bool queue_push_head(struct queue *queue, void *data)