diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index ff49be1..84689f6 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
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;
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);
}
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;
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)
char uuid_str[MAX_LEN_UUID_STR];
unsigned int desc_count;
bool discovering;
+ bt_uuid_t ext_prop_uuid;
discovery_req_clear(client);
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);
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 6e4dcee..8129719 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
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), \