diff --git a/src/gatt-database.c b/src/gatt-database.c
index 25641da..dc75762 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
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 12ff5ba..53d3e12 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
.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;
};
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;
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;
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,
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;
db->ccc->read_func = read_func;
db->ccc->write_func = write_func;
+ db->ccc->notify_func = notify_func;
db->ccc->user_data = user_data;
}
return true;
}
+static void find_ccc(struct gatt_db_attribute *attrib, void *user_data)
+{
+ struct gatt_db_attribute **ccc = user_data;
+
+ if (*ccc)
+ return;
+
+ if (bt_uuid_cmp(&ccc_uuid, &attrib->uuid))
+ return;
+
+ *ccc = attrib;
+}
+
+struct gatt_db_attribute *
+gatt_db_attribute_get_ccc(struct gatt_db_attribute *attrib)
+{
+ struct gatt_db_attribute *ccc = NULL;
+
+ if (!attrib)
+ return NULL;
+
+ gatt_db_service_foreach_desc(attrib, find_ccc, &ccc);
+
+ return ccc;
+}
+
+bool gatt_db_attribute_notify(struct gatt_db_attribute *attrib,
+ const uint8_t *value, size_t len,
+ struct bt_att *att)
+{
+ struct gatt_db_attribute *ccc;
+
+ if (!attrib || !attrib->notify_func)
+ return false;
+
+ /* Return if this attribute is not a characteristic declaration */
+ if (bt_uuid_cmp(&characteristic_uuid, &attrib->uuid))
+ return false;
+
+ ccc = gatt_db_attribute_get_ccc(attrib);
+ if (!ccc)
+ 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 3de2240..41464ad 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
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,
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,
bool gatt_db_attribute_write_result(struct gatt_db_attribute *attrib,
unsigned int id, int err);
+struct gatt_db_attribute *
+gatt_db_attribute_get_ccc(struct gatt_db_attribute *attrib);
+
+bool gatt_db_attribute_notify(struct gatt_db_attribute *attrib,
+ 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);