From 6b3f0f3ab935e192db9cf73b68a27271d4febd74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 13 Apr 2016 23:09:57 +0200 Subject: [PATCH] gatt-client: Read extended props on service discovery Now once extended props can be taken with characteristic data we need to makes sure that after discovery correct value is in database. With this patch, value of all the extended properties descriptors are read during discovery just after discover of descriptors --- src/shared/gatt-client.c | 114 +++++++++++++++++++++++++++++++++++++++ unit/test-gatt.c | 2 + 2 files changed, 116 insertions(+) diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c index ff49be1a7..84689f62f 100644 --- a/src/shared/gatt-client.c +++ b/src/shared/gatt-client.c @@ -316,6 +316,7 @@ struct discovery_op { struct queue *pending_svcs; struct queue *pending_chrcs; struct queue *svcs; + struct queue *ext_prop_desc; struct gatt_db_attribute *cur_svc; bool success; uint16_t start; @@ -331,6 +332,7 @@ static void discovery_op_free(struct discovery_op *op) queue_destroy(op->pending_svcs, NULL); queue_destroy(op->pending_chrcs, free); queue_destroy(op->svcs, NULL); + queue_destroy(op->ext_prop_desc, NULL); free(op); } @@ -360,6 +362,7 @@ static struct discovery_op *discovery_op_create(struct bt_gatt_client *client, op->pending_svcs = queue_new(); op->pending_chrcs = queue_new(); op->svcs = queue_new(); + op->ext_prop_desc = queue_new(); op->client = client; op->complete_func = complete_func; op->failure_func = failure_func; @@ -604,6 +607,107 @@ failed: return false; } +static void ext_prop_write_cb(struct gatt_db_attribute *attrib, + int err, void *user_data) +{ + struct bt_gatt_client *client = user_data; + + util_debug(client->debug_callback, client->debug_data, + "Value set status: %d", err); +} + +static void ext_prop_read_cb(bool success, uint8_t att_ecode, + const uint8_t *value, uint16_t length, + void *user_data); + +static bool read_ext_prop_desc(struct discovery_op *op) +{ + struct bt_gatt_client *client = op->client; + uint16_t handle; + struct gatt_db_attribute *attr; + + attr = queue_peek_head(op->ext_prop_desc); + if (!attr) + return false; + + handle = gatt_db_attribute_get_handle(attr); + bt_gatt_client_read_value(client, handle, ext_prop_read_cb, + discovery_op_ref(op), + discovery_op_unref); + + return true; +} + +static void ext_prop_read_cb(bool success, uint8_t att_ecode, + const uint8_t *value, uint16_t length, + void *user_data) +{ + struct discovery_op *op = user_data; + struct bt_gatt_client *client = op->client; + bool discovering; + struct gatt_db_attribute *desc_attr = NULL; + struct gatt_db_attribute *next_srv; + uint16_t start, end; + + util_debug(client->debug_callback, client->debug_data, + "Ext. prop value: 0x%04x", (uint16_t)value[0]); + + desc_attr = queue_pop_head(op->ext_prop_desc); + if (!desc_attr) + goto failed; + + if (!gatt_db_attribute_write(desc_attr, 0, value, length, 0, NULL, + ext_prop_write_cb, client)) + goto failed; + + /* Any other descriptor to read? */ + if (read_ext_prop_desc(op)) + return; + + /* Continue with discovery */ + do { + if (!discover_descs(op, &discovering)) + goto failed; + + if (discovering) + return; + + /* Done with the current service */ + gatt_db_service_set_active(op->cur_svc, true); + + next_srv = queue_pop_head(op->svcs); + if (!next_srv) + goto done; + + if (!gatt_db_attribute_get_service_handles(next_srv, &start, + &end)) + goto failed; + + } while (start == end); + + /* Move on to the next service */ + op->cur_svc = next_srv; + + client->discovery_req = bt_gatt_discover_characteristics(client->att, + start, end, + discover_chrcs_cb, + discovery_op_ref(op), + discovery_op_unref); + if (client->discovery_req) + return; + + util_debug(client->debug_callback, client->debug_data, + "Failed to start characteristic discovery"); + + discovery_op_unref(op); + +failed: + success = false; + +done: + discovery_op_complete(op, success, att_ecode); +} + static void discover_descs_cb(bool success, uint8_t att_ecode, struct bt_gatt_result *result, void *user_data) @@ -618,6 +722,7 @@ static void discover_descs_cb(bool success, uint8_t att_ecode, char uuid_str[MAX_LEN_UUID_STR]; unsigned int desc_count; bool discovering; + bt_uuid_t ext_prop_uuid; discovery_req_clear(client); @@ -640,6 +745,8 @@ static void discover_descs_cb(bool success, uint8_t att_ecode, util_debug(client->debug_callback, client->debug_data, "Descriptors found: %u", desc_count); + bt_uuid16_create(&ext_prop_uuid, GATT_CHARAC_EXT_PROPER_UUID); + while (bt_gatt_iter_next_descriptor(&iter, &handle, u128.data)) { bt_uuid128_create(&uuid, u128); @@ -657,8 +764,15 @@ static void discover_descs_cb(bool success, uint8_t att_ecode, if (gatt_db_attribute_get_handle(attr) != handle) goto failed; + + if (!bt_uuid_cmp(&ext_prop_uuid, &uuid)) + queue_push_tail(op->ext_prop_desc, attr); } + /* If we got extended prop descriptor, lets read it right away */ + if (read_ext_prop_desc(op)) + return; + next: if (!discover_descs(op, &discovering)) goto failed; diff --git a/unit/test-gatt.c b/unit/test-gatt.c index 6e4dceea2..81297197e 100644 --- a/unit/test-gatt.c +++ b/unit/test-gatt.c @@ -267,6 +267,8 @@ struct context { raw_pdu(0x01, 0x08, 0x18, 0xf0, 0x0a), \ raw_pdu(0x04, 0x16, 0xf0, 0x16, 0xf0), \ raw_pdu(0x05, 0x01, 0x16, 0xf0, 0x00, 0x29), \ + raw_pdu(0x0a, 0x16, 0xf0), \ + raw_pdu(0x0b, 0x01, 0x00), \ raw_pdu(0x08, 0x01, 0x00, 0x10, 0x00, 0x03, 0x28), \ raw_pdu(0x09, 0x07, 0x02, 0x00, 0xb2, 0x03, 0x00, 0x29, \ 0x2a), \ -- 2.47.3