From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> This introduces gatt_db_attribute_notify which can be used to trigger a notification using the callback set by gatt_db_ccc_register. --- src/gatt-database.c | 2 +- src/shared/gatt-db.c | 46 ++++++++++++++++++++++++++++++++++++++++---- src/shared/gatt-db.h | 13 ++++++++++++- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/gatt-database.c b/src/gatt-database.c index 25641da8a..dc75762f3 100644 --- a/src/gatt-database.c +++ b/src/gatt-database.c @@ -1302,7 +1302,7 @@ static void populate_devinfo_service(struct btd_gatt_database *database) static void register_core_services(struct btd_gatt_database *database) { gatt_db_ccc_register(database->db, gatt_ccc_read_cb, gatt_ccc_write_cb, - database); + NULL, database); populate_gap_service(database); populate_gatt_service(database); diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c index 12ff5badb..59d19eea3 100644 --- a/src/shared/gatt-db.c +++ b/src/shared/gatt-db.c @@ -43,10 +43,13 @@ static const bt_uuid_t included_service_uuid = { .type = BT_UUID16, .value.u16 = GATT_INCLUDE_UUID }; static const bt_uuid_t ext_desc_uuid = { .type = BT_UUID16, .value.u16 = GATT_CHARAC_EXT_PROPER_UUID }; +static const bt_uuid_t ccc_uuid = { .type = BT_UUID16, + .value.u16 = GATT_CLIENT_CHARAC_CFG_UUID }; struct gatt_db_ccc { gatt_db_read_t read_func; gatt_db_write_t write_func; + gatt_db_notify_t notify_func; void *user_data; }; @@ -109,6 +112,7 @@ struct gatt_db_attribute { gatt_db_read_t read_func; gatt_db_write_t write_func; + gatt_db_notify_t notify_func; void *user_data; unsigned int read_id; @@ -1047,12 +1051,20 @@ gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib, user_data); } +static void find_ccc_value(struct gatt_db_attribute *attrib, void *user_data) +{ + uint16_t *handle = user_data; + + gatt_db_attribute_get_char_data(attrib, NULL, handle, NULL, NULL, NULL); +} + struct gatt_db_attribute * gatt_db_service_add_ccc(struct gatt_db_attribute *attrib, uint32_t permissions) { struct gatt_db *db; struct gatt_db_attribute *ccc; - bt_uuid_t uuid; + struct gatt_db_attribute *value; + uint16_t handle = 0; if (!attrib) return NULL; @@ -1062,9 +1074,17 @@ gatt_db_service_add_ccc(struct gatt_db_attribute *attrib, uint32_t permissions) if (!db->ccc) return NULL; - bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID); + /* Locate value handle */ + gatt_db_service_foreach_char(attrib, find_ccc_value, &handle); + + if (!handle) + return NULL; + + value = gatt_db_get_attribute(db, handle); + if (!value || value->notify_func) + return NULL; - ccc = service_insert_descriptor(attrib->service, 0, &uuid, + ccc = service_insert_descriptor(attrib->service, 0, &ccc_uuid, permissions, db->ccc->read_func, db->ccc->write_func, @@ -1073,12 +1093,16 @@ gatt_db_service_add_ccc(struct gatt_db_attribute *attrib, uint32_t permissions) return ccc; gatt_db_attribute_set_fixed_length(ccc, 2); + ccc->notify_func = db->ccc->notify_func; + value->notify_func = db->ccc->notify_func; return ccc; } void gatt_db_ccc_register(struct gatt_db *db, gatt_db_read_t read_func, - gatt_db_write_t write_func, void *user_data) + gatt_db_write_t write_func, + gatt_db_notify_t notify_func, + void *user_data) { if (!db) return; @@ -1088,6 +1112,7 @@ void gatt_db_ccc_register(struct gatt_db *db, gatt_db_read_t read_func, db->ccc->read_func = read_func; db->ccc->write_func = write_func; + db->ccc->notify_func = notify_func; db->ccc->user_data = user_data; } @@ -2103,6 +2128,19 @@ bool gatt_db_attribute_write_result(struct gatt_db_attribute *attrib, return true; } +bool gatt_db_attribute_notify(struct gatt_db_attribute *attrib, + struct gatt_db_attribute *ccc, + const uint8_t *value, size_t len, + struct bt_att *att) +{ + if (!attrib || !ccc || !attrib->notify_func) + return false; + + attrib->notify_func(attrib, ccc, value, len, att, ccc->user_data); + + return true; +} + bool gatt_db_attribute_reset(struct gatt_db_attribute *attrib) { if (!attrib) diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h index 3de22403c..acd8f6a81 100644 --- a/src/shared/gatt-db.h +++ b/src/shared/gatt-db.h @@ -47,6 +47,10 @@ typedef void (*gatt_db_write_t) (struct gatt_db_attribute *attrib, const uint8_t *value, size_t len, uint8_t opcode, struct bt_att *att, void *user_data); +typedef void (*gatt_db_notify_t) (struct gatt_db_attribute *attrib, + struct gatt_db_attribute *ccc, + const uint8_t *value, size_t len, + struct bt_att *att, void *user_data); struct gatt_db_attribute * gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib, @@ -197,7 +201,9 @@ unsigned int gatt_db_register(struct gatt_db *db, bool gatt_db_unregister(struct gatt_db *db, unsigned int id); void gatt_db_ccc_register(struct gatt_db *db, gatt_db_read_t read_func, - gatt_db_write_t write_func, void *user_data); + gatt_db_write_t write_func, + gatt_db_notify_t notify_func, + void *user_data); typedef uint8_t (*gatt_db_authorize_cb_t)(struct gatt_db_attribute *attrib, uint8_t opcode, struct bt_att *att, @@ -275,6 +281,11 @@ bool gatt_db_attribute_write(struct gatt_db_attribute *attrib, uint16_t offset, bool gatt_db_attribute_write_result(struct gatt_db_attribute *attrib, unsigned int id, int err); +bool gatt_db_attribute_notify(struct gatt_db_attribute *attrib, + struct gatt_db_attribute *ccc, + const uint8_t *value, size_t len, + struct bt_att *att); + bool gatt_db_attribute_reset(struct gatt_db_attribute *attrib); void *gatt_db_attribute_get_user_data(struct gatt_db_attribute *attrib); -- 2.34.1