@@ -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);
@@ -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)
@@ -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);
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> 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(-)