service->attributes has an assumption that it should look like: |char_uuid|char_1|desc_1_1|desc_1_2|char_uuid|char_2|desc_2_1|char_uuid|... where desc_x_y means a descriptor of char_x. In monitor, an attribute is inserted as soon as it is found. It is not guranteed that all the descriptors of a characteristic would be found before another characteristic is found. This adds a function to insert the descriptor with the given handle to an appropriate place in its service attribute list and make monitor to use this function when a descripter is found. Reviewed-by: Archie Pusaka <apusaka@xxxxxxxxxxxx> --- monitor/att.c | 2 +- src/shared/gatt-db.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ src/shared/gatt-db.h | 9 ++++++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/monitor/att.c b/monitor/att.c index ddeb54d9e..503099745 100644 --- a/monitor/att.c +++ b/monitor/att.c @@ -4153,7 +4153,7 @@ static struct gatt_db_attribute *insert_desc(const struct l2cap_frame *frame, if (!db) return NULL; - return gatt_db_append_descriptor(db, handle, uuid, 0, NULL, NULL, NULL); + return gatt_db_insert_descriptor(db, handle, uuid, 0, NULL, NULL, NULL); } static void att_find_info_rsp_16(const struct l2cap_frame *frame) diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c index 39bba9b54..f08c5afaa 100644 --- a/src/shared/gatt-db.c +++ b/src/shared/gatt-db.c @@ -1002,6 +1002,72 @@ service_append_descriptor(struct gatt_db_service *service, return service->attributes[i]; } +struct gatt_db_attribute * +gatt_db_insert_descriptor(struct gatt_db *db, + 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) +{ + struct gatt_db_attribute *attrib, *iter_attr, *char_attr = NULL; + struct gatt_db_service *service; + int i, j, num_index, char_index; + + attrib = gatt_db_get_service(db, handle); + if (!attrib) + return NULL; + + service = attrib->service; + num_index = get_attribute_index(service, 0); + if (!num_index) + return NULL; + + // Find the characteristic the descriptor belongs to. + for (i = 0; i < num_index; i++) { + iter_attr = service->attributes[i]; + if (bt_uuid_cmp(&characteristic_uuid, &iter_attr->uuid)) + continue; + + if (iter_attr->handle > handle) + continue; + + // Find the characteristic with the largest handle among those + // with handles less than the descriptor's handle. + if (!char_attr || iter_attr->handle > char_attr->handle) { + char_attr = iter_attr; + char_index = i; + } + } + + // There is no characteristic contain this descriptor. Something went + // wrong + if (!char_attr) + return NULL; + + // Find the end of this characteristic + for (i = char_index + 1; i < num_index; i++) { + iter_attr = service->attributes[i]; + + if (!bt_uuid_cmp(&characteristic_uuid, &iter_attr->uuid) || + !bt_uuid_cmp(&included_service_uuid, &iter_attr->uuid)) + break; + } + + // Move all of the attributes after the end of this characteristic to + // its next index. + for (j = num_index; j > i; j--) + service->attributes[j] = service->attributes[j - 1]; + + service->attributes[i] = new_attribute(service, handle, uuid, NULL, 0); + + set_attribute_data(service->attributes[i], read_func, write_func, + permissions, user_data); + + return service->attributes[i]; +} + struct gatt_db_attribute * gatt_db_append_descriptor(struct gatt_db *db, uint16_t handle, diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h index ec0eccdfc..4c4e88d87 100644 --- a/src/shared/gatt-db.h +++ b/src/shared/gatt-db.h @@ -80,6 +80,15 @@ gatt_db_append_characteristic(struct gatt_db *db, gatt_db_write_t write_func, void *user_data); +struct gatt_db_attribute * +gatt_db_insert_descriptor(struct gatt_db *db, + 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); + struct gatt_db_attribute * gatt_db_append_descriptor(struct gatt_db *db, uint16_t handle, -- 2.44.0.478.gd926399ef9-goog