This patch adds gatt_discover_desc() function which performs descriptor
discovery in a manner similar to gatt_discover_char(), i.e. it does
complete discovery procedure and returns list of descriptors found when
finished. For 16-bit UUIDs in addition to string UUID, short UUID is
provided.
It's also possible to specify single descriptor UUID to look for and
discovery procedure is interrupted as soon as UUID is found. This way
no more than one descriptor is returned which is useful when searching
for common descriptors like CCC.
---
attrib/gatt.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
attrib/gatt.h | 10 ++++
2 files changed, 156 insertions(+)
diff --git a/attrib/gatt.c b/attrib/gatt.c
index f5917db..f766617 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -73,6 +73,16 @@ struct discover_char {
void *user_data;
};
+struct discover_desc {
+ int ref;
+ GAttrib *attrib;
+ bt_uuid_t *uuid;
+ uint16_t end;
+ GSList *descriptors;
+ gatt_cb_t cb;
+ void *user_data;
+};
+
static void discover_primary_unref(void *data)
{
struct discover_primary *dp = data;
@@ -139,6 +149,28 @@ static struct discover_char *discover_char_ref(struct discover_char *dc)
return dc;
}
+static void discover_desc_unref(void *data)
+{
+ struct discover_desc *dd = data;
+
+ dd->ref--;
+
+ if (dd->ref > 0)
+ return;
+
+ g_slist_free_full(dd->descriptors, g_free);
+ g_attrib_unref(dd->attrib);
+ g_free(dd->uuid);
+ g_free(dd);
+}
+
+static struct discover_desc *discover_desc_ref(struct discover_desc *dd)
+{
+ dd->ref++;
+
+ return dd;
+}
+
static void put_uuid_le(const bt_uuid_t *uuid, void *dst)
{
if (uuid->type == BT_UUID16)
@@ -907,6 +939,120 @@ guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func,
return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
+
+static void desc_discovered_cb(guint8 status, const guint8 *ipdu,
+ guint16 iplen, gpointer user_data)
+{
+ struct discover_desc *dd = user_data;
+ struct att_data_list *list;
+ unsigned int i, err = ATT_ECODE_ATTR_NOT_FOUND;
+ guint8 format;
+ uint16_t last = 0xffff;
+ uint8_t type;
+ gboolean uuid_found = FALSE;
+
+ if (status) {
+ err = status;
+ goto done;
+ }
+
+ list = dec_find_info_resp(ipdu, iplen, &format);
+ if (!list) {
+ err = ATT_ECODE_IO;
+ goto done;
+ }
+
+ if (format == ATT_FIND_INFO_RESP_FMT_16BIT)
+ type = BT_UUID16;
+ else
+ type = BT_UUID128;
+
+ for (i = 0; i < list->num; i++) {
+ uint8_t *value = list->data[i];
+ struct gatt_desc *desc;
+ bt_uuid_t uuid128;
+
+ last = get_le16(value);
+
+ get_uuid128(type, &value[2], &uuid128);
+
+ if (dd->uuid) {
+ if (bt_uuid_cmp(dd->uuid, &uuid128))
+ continue;
+ else
+ uuid_found = TRUE;
+ }
+
+ desc = g_try_new0(struct gatt_desc, 1);
+ if (!desc) {
+ att_data_list_free(list);
+ err = ATT_ECODE_INSUFF_RESOURCES;
+ goto done;
+ }
+
+ bt_uuid_to_string(&uuid128, desc->uuid, sizeof(desc->uuid));
+ desc->handle = last;
+
+ if (type == BT_UUID16)
+ desc->uuid16 = get_le16(&value[2]);
+
+ dd->descriptors = g_slist_append(dd->descriptors, desc);
+
+ if (uuid_found)
+ break;
+ }
+
+ att_data_list_free(list);
+
+ if (last + 1 < dd->end && !uuid_found) {
+ guint16 oplen;
+ size_t buflen;
+ uint8_t *buf;
+
+ buf = g_attrib_get_buffer(dd->attrib, &buflen);
+
+ oplen = enc_find_info_req(last + 1, dd->end, buf, buflen);
+ if (oplen == 0)
+ return;
+
+ g_attrib_send(dd->attrib, 0, buf, oplen, desc_discovered_cb,
+ discover_desc_ref(dd), discover_desc_unref);
+
+ return;
+ }
+
+done:
+ err = (dd->descriptors ? 0 : err);
+ dd->cb(err, dd->descriptors, dd->user_data);
+}
+
+guint gatt_discover_desc(GAttrib *attrib, uint16_t start, uint16_t end,
+ bt_uuid_t *uuid, gatt_cb_t func,
+ gpointer user_data)
+{
+ size_t buflen;
+ uint8_t *buf = g_attrib_get_buffer(attrib, &buflen);
+ struct discover_desc *dd;
+ guint16 plen;
+
+ plen = enc_find_info_req(start, end, buf, buflen);
+ if (plen == 0)
+ return 0;
+
+ dd = g_try_new0(struct discover_desc, 1);
+ if (dd == NULL)
+ return 0;
+
+ dd->attrib = g_attrib_ref(attrib);
+ dd->cb = func;
+ dd->user_data = user_data;
+ dd->end = end;
+ dd->uuid = g_memdup(uuid, sizeof(bt_uuid_t));
+
+ return g_attrib_send(attrib, 0, buf, plen, desc_discovered_cb,
+ discover_desc_ref(dd), discover_desc_unref);
+}
+
guint gatt_discover_char_desc(GAttrib *attrib, uint16_t start, uint16_t end,
GAttribResultFunc func, gpointer user_data)
{
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 3fe6041..533bfd7 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -67,6 +67,12 @@ struct gatt_char {
uint16_t value_handle;
};
+struct gatt_desc {
+ char uuid[MAX_LEN_UUID_STR + 1];
+ uint16_t handle;
+ uint16_t uuid16;
+};
+
guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
@@ -84,6 +90,10 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, const uint8_t *value,
size_t vlen, GAttribResultFunc func,
gpointer user_data);
+guint gatt_discover_desc(GAttrib *attrib, uint16_t start, uint16_t end,
+ bt_uuid_t *uuid, gatt_cb_t func,
+ gpointer user_data);
+
guint gatt_reliable_write_char(GAttrib *attrib, uint16_t handle,
const uint8_t *value, size_t vlen,
GAttribResultFunc func,
--
1.9.2
Hi Andrzej,
On Fri, May 02, 2014, Andrzej Kaczmarek wrote:
> This patch adds gatt_discover_desc() function which performs descriptor
> discovery in a manner similar to gatt_discover_char(), i.e. it does
> complete discovery procedure and returns list of descriptors found when
> finished. For 16-bit UUIDs in addition to string UUID, short UUID is
> provided.
>
> It's also possible to specify single descriptor UUID to look for and
> discovery procedure is interrupted as soon as UUID is found. This way
> no more than one descriptor is returned which is useful when searching
> for common descriptors like CCC.
> ---
> attrib/gatt.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> attrib/gatt.h | 10 ++++
> 2 files changed, 156 insertions(+)
All patches in this set have been applied. Thanks.
Johan
---
profiles/thermometer/thermometer.c | 28 +++++-----------------------
1 file changed, 5 insertions(+), 23 deletions(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 20575c0..e3ab923 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -574,13 +574,9 @@ static void process_thermometer_desc(struct characteristic *ch, uint16_t uuid,
write_ccc_cb, msg);
}
-static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
+static void discover_desc_cb(guint8 status, GSList *descs, gpointer user_data)
{
struct characteristic *ch = user_data;
- struct att_data_list *list = NULL;
- uint8_t format;
- int i;
if (status != 0) {
error("Discover all characteristic descriptors failed [%s]: %s",
@@ -588,27 +584,13 @@ static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
goto done;
}
- list = dec_find_info_resp(pdu, len, &format);
- if (list == NULL)
- goto done;
-
- if (format != ATT_FIND_INFO_RESP_FMT_16BIT)
- goto done;
-
- for (i = 0; i < list->num; i++) {
- uint8_t *value;
- uint16_t handle, uuid;
-
- value = list->data[i];
- handle = get_le16(value);
- uuid = get_le16(value + 2);
+ for ( ; descs; descs = descs->next) {
+ struct gatt_desc *desc = descs->data;
- process_thermometer_desc(ch, uuid, handle);
+ process_thermometer_desc(ch, desc->uuid16, desc->handle);
}
done:
- if (list != NULL)
- att_data_list_free(list);
g_free(ch);
}
@@ -634,7 +616,7 @@ static void discover_desc(struct thermometer *t, struct gatt_char *c,
ch->t = t;
memcpy(ch->uuid, c->uuid, sizeof(c->uuid));
- gatt_discover_char_desc(t->attrib, start, end, discover_desc_cb, ch);
+ gatt_discover_desc(t->attrib, start, end, NULL, discover_desc_cb, ch);
}
static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
--
1.9.2
---
android/gatt.c | 101 +++++++++++++--------------------------------------------
1 file changed, 22 insertions(+), 79 deletions(-)
diff --git a/android/gatt.c b/android/gatt.c
index 47a7ecf..e768856 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -2008,67 +2008,13 @@ static void send_client_descr_notify(int32_t status, int32_t conn_id,
HAL_EV_GATT_CLIENT_GET_DESCRIPTOR, sizeof(ev), &ev);
}
-static uint16_t parse_descrs(const uint8_t *pdu, guint16 len,
- struct queue *cache)
-{
- struct att_data_list *list;
- guint8 format;
- uint16_t handle = 0xffff;
- int i;
-
- list = dec_find_info_resp(pdu, len, &format);
- if (!list)
- return handle;
-
- for (i = 0; i < list->num; i++) {
- char uuidstr[MAX_LEN_UUID_STR];
- struct descriptor *descr;
- bt_uuid_t uuid128;
- uint8_t *value;
- bt_uuid_t uuid;
-
- value = list->data[i];
- handle = get_le16(value);
-
- if (format == ATT_FIND_INFO_RESP_FMT_16BIT) {
- bt_uuid16_create(&uuid, get_le16(&value[2]));
- bt_uuid_to_uuid128(&uuid, &uuid128);
- } else {
- uint128_t u128;
-
- bswap_128(&value[2], &u128);
- bt_uuid128_create(&uuid128, u128);
- }
-
- bt_uuid_to_string(&uuid128, uuidstr, MAX_LEN_UUID_STR);
- DBG("handle 0x%04x uuid %s", handle, uuidstr);
-
- descr = new0(struct descriptor, 1);
- if (!descr)
- continue;
-
- descr->id.instance = i;
- descr->handle = handle;
- descr->id.uuid = uuid128;
-
- if (!queue_push_tail(cache, descr))
- free(descr);
- }
-
- att_data_list_free(list);
-
- return handle;
-}
-
struct discover_desc_data {
struct app_connection *conn;
struct service *srvc;
struct characteristic *ch;
-
- struct queue *result;
};
-static void gatt_discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
+static void gatt_discover_desc_cb(guint8 status, GSList *descs,
gpointer user_data)
{
struct discover_desc_data *data = user_data;
@@ -2076,29 +2022,33 @@ static void gatt_discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
struct service *srvc = data->srvc;
struct characteristic *ch = data->ch;
struct descriptor *descr;
+ int i = 0;
- if (!status) {
- uint16_t last_handle = parse_descrs(pdu, len, data->result);
+ if (status != 0) {
+ error("Discover all characteristic descriptors failed [%s]: %s",
+ ch->ch.uuid, att_ecode2str(status));
+ goto reply;
+ }
- if (last_handle >= ch->end_handle)
- goto reply;
+ for ( ; descs; descs = descs->next) {
+ struct gatt_desc *desc = descs->data;
+ bt_uuid_t uuid;
- if (!gatt_discover_char_desc(conn->device->attrib,
- last_handle + 1, ch->end_handle,
- gatt_discover_desc_cb, data))
- goto reply;
+ descr = new0(struct descriptor, 1);
+ if (!descr)
+ continue;
- /* Do not reply yet, wait for next piece */
- return;
- } else if (status != ATT_ECODE_ATTR_NOT_FOUND) {
- error("gatt: Discover all char descriptors failed: %s",
- att_ecode2str(status));
+ bt_string_to_uuid(&uuid, desc->uuid);
+ bt_uuid_to_uuid128(&uuid, &descr->id.uuid);
+
+ descr->id.instance = i++;
+ descr->handle = desc->handle;
+
+ if (!queue_push_tail(ch->descriptors, descr))
+ free(descr);
}
reply:
- queue_destroy(ch->descriptors, free);
- ch->descriptors = data->result;
-
descr = queue_peek_head(ch->descriptors);
send_client_descr_notify(status, conn->id, srvc->primary, &srvc->id,
@@ -2130,16 +2080,9 @@ static bool build_descr_cache(struct app_connection *connection,
cb_data->conn = connection;
cb_data->srvc = srvc;
cb_data->ch = ch;
- cb_data->result = queue_new();
-
- if (!cb_data->result) {
- free(cb_data);
- return false;
- }
- if (!gatt_discover_char_desc(connection->device->attrib, start, end,
+ if (!gatt_discover_desc(connection->device->attrib, start, end, NULL,
gatt_discover_desc_cb, cb_data)) {
- queue_destroy(cb_data->result, NULL);
free(cb_data);
return false;
}
--
1.9.2
---
profiles/cyclingspeed/cyclingspeed.c | 73 +++++++++++++-----------------------
1 file changed, 26 insertions(+), 47 deletions(-)
diff --git a/profiles/cyclingspeed/cyclingspeed.c b/profiles/cyclingspeed/cyclingspeed.c
index 2f80bca..6b00da7 100644
--- a/profiles/cyclingspeed/cyclingspeed.c
+++ b/profiles/cyclingspeed/cyclingspeed.c
@@ -419,13 +419,12 @@ static void read_location_cb(guint8 status, const guint8 *pdu,
CYCLINGSPEED_INTERFACE, "Location");
}
-static void discover_desc_cb(guint8 status, const guint8 *pdu,
- guint16 len, gpointer user_data)
+static void discover_desc_cb(guint8 status, GSList *descs, gpointer user_data)
{
struct characteristic *ch = user_data;
- struct att_data_list *list = NULL;
- uint8_t format;
- int i;
+ struct gatt_desc *desc;
+ uint8_t attr_val[2];
+ char *msg = NULL;
if (status != 0) {
error("Discover %s descriptors failed: %s", ch->uuid,
@@ -433,55 +432,31 @@ static void discover_desc_cb(guint8 status, const guint8 *pdu,
goto done;
}
- list = dec_find_info_resp(pdu, len, &format);
- if (list == NULL)
- goto done;
+ /* There will be only one descriptor on list and it will be CCC */
+ desc = descs->data;
- if (format != ATT_FIND_INFO_RESP_FMT_16BIT)
- goto done;
+ if (g_strcmp0(ch->uuid, CSC_MEASUREMENT_UUID) == 0) {
+ ch->csc->measurement_ccc_handle = desc->handle;
- for (i = 0; i < list->num; i++) {
- uint8_t *value;
- uint16_t handle, uuid;
- uint8_t attr_val[2];
- char *msg;
-
- value = list->data[i];
- handle = get_le16(value);
- uuid = get_le16(value + 2);
-
- if (uuid != GATT_CLIENT_CHARAC_CFG_UUID)
- continue;
-
- if (g_strcmp0(ch->uuid, CSC_MEASUREMENT_UUID) == 0) {
- ch->csc->measurement_ccc_handle = handle;
-
- if (g_slist_length(ch->csc->cadapter->watchers) == 0) {
- put_le16(0x0000, attr_val);
- msg = g_strdup("Disable measurement");
- } else {
- put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT,
- attr_val);
- msg = g_strdup("Enable measurement");
- }
-
- } else if (g_strcmp0(ch->uuid, SC_CONTROL_POINT_UUID) == 0) {
- put_le16(GATT_CLIENT_CHARAC_CFG_IND_BIT, attr_val);
- msg = g_strdup("Enable SC Control Point indications");
+ if (g_slist_length(ch->csc->cadapter->watchers) == 0) {
+ put_le16(0x0000, attr_val);
+ msg = g_strdup("Disable measurement");
} else {
- break;
+ put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT,
+ attr_val);
+ msg = g_strdup("Enable measurement");
}
+ } else if (g_strcmp0(ch->uuid, SC_CONTROL_POINT_UUID) == 0) {
+ put_le16(GATT_CLIENT_CHARAC_CFG_IND_BIT, attr_val);
+ msg = g_strdup("Enable SC Control Point indications");
+ } else {
+ goto done;
+ }
- gatt_write_char(ch->csc->attrib, handle, attr_val,
+ gatt_write_char(ch->csc->attrib, desc->handle, attr_val,
sizeof(attr_val), char_write_cb, msg);
- /* We only want CCC, can break here */
- break;
- }
-
done:
- if (list)
- att_data_list_free(list);
g_free(ch);
}
@@ -490,6 +465,7 @@ static void discover_desc(struct csc *csc, struct gatt_char *c,
{
struct characteristic *ch;
uint16_t start, end;
+ bt_uuid_t uuid;
start = c->value_handle + 1;
@@ -507,7 +483,10 @@ static void discover_desc(struct csc *csc, struct gatt_char *c,
ch->csc = csc;
memcpy(ch->uuid, c->uuid, sizeof(c->uuid));
- gatt_discover_char_desc(csc->attrib, start, end, discover_desc_cb, ch);
+ bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+
+ gatt_discover_desc(csc->attrib, start, end, &uuid, discover_desc_cb,
+ ch);
}
static void update_watcher(gpointer data, gpointer user_data)
--
1.9.2
---
profiles/heartrate/heartrate.c | 59 ++++++++++++++----------------------------
1 file changed, 19 insertions(+), 40 deletions(-)
diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index 1dcbdf4..287ea72 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -391,13 +391,12 @@ static void notify_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
process_measurement(hr, pdu + 3, len - 3);
}
-static void discover_ccc_cb(guint8 status, const guint8 *pdu,
- guint16 len, gpointer user_data)
+static void discover_ccc_cb(uint8_t status, GSList *descs, void *user_data)
{
struct heartrate *hr = user_data;
- struct att_data_list *list;
- uint8_t format;
- int i;
+ struct gatt_desc *desc;
+ uint8_t attr_val[2];
+ char *msg;
if (status != 0) {
error("Discover Heart Rate Measurement descriptors failed: %s",
@@ -405,50 +404,28 @@ static void discover_ccc_cb(guint8 status, const guint8 *pdu,
return;
}
- list = dec_find_info_resp(pdu, len, &format);
- if (list == NULL)
- return;
-
- if (format != ATT_FIND_INFO_RESP_FMT_16BIT)
- goto done;
-
- for (i = 0; i < list->num; i++) {
- uint8_t *value;
- uint16_t handle, uuid;
- char *msg;
- uint8_t attr_val[2];
-
- value = list->data[i];
- handle = get_le16(value);
- uuid = get_le16(value + 2);
-
- if (uuid != GATT_CLIENT_CHARAC_CFG_UUID)
- continue;
+ /* There will be only one descriptor on list and it will be CCC */
+ desc = descs->data;
- hr->measurement_ccc_handle = handle;
+ hr->measurement_ccc_handle = desc->handle;
- if (g_slist_length(hr->hradapter->watchers) == 0) {
- put_le16(0x0000, attr_val);
- msg = g_strdup("Disable measurement");
- } else {
- put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, attr_val);
- msg = g_strdup("Enable measurement");
- }
-
- gatt_write_char(hr->attrib, handle, attr_val,
- sizeof(attr_val), char_write_cb, msg);
-
- break;
+ if (g_slist_length(hr->hradapter->watchers) == 0) {
+ put_le16(0x0000, attr_val);
+ msg = g_strdup("Disable measurement");
+ } else {
+ put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, attr_val);
+ msg = g_strdup("Enable measurement");
}
-done:
- att_data_list_free(list);
+ gatt_write_char(hr->attrib, desc->handle, attr_val, sizeof(attr_val),
+ char_write_cb, msg);
}
static void discover_measurement_ccc(struct heartrate *hr,
struct gatt_char *c, struct gatt_char *c_next)
{
uint16_t start, end;
+ bt_uuid_t uuid;
start = c->value_handle + 1;
@@ -462,7 +439,9 @@ static void discover_measurement_ccc(struct heartrate *hr,
return;
}
- gatt_discover_char_desc(hr->attrib, start, end, discover_ccc_cb, hr);
+ bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+
+ gatt_discover_desc(hr->attrib, start, end, &uuid, discover_ccc_cb, hr);
}
static void discover_char_cb(uint8_t status, GSList *chars, void *user_data)
--
1.9.2
---
profiles/scanparam/scan.c | 34 +++++++++++++---------------------
1 file changed, 13 insertions(+), 21 deletions(-)
diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index 156682f..25c906e 100644
--- a/profiles/scanparam/scan.c
+++ b/profiles/scanparam/scan.c
@@ -102,35 +102,24 @@ static void ccc_written_cb(guint8 status, const guint8 *pdu,
refresh_value_cb, scan, NULL);
}
-static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
- guint16 len, gpointer user_data)
+static void discover_descriptor_cb(uint8_t status, GSList *descs,
+ void *user_data)
{
struct scan *scan = user_data;
- struct att_data_list *list;
- uint8_t *ptr;
- uint16_t uuid16, handle;
+ struct gatt_desc *desc;
uint8_t value[2];
- uint8_t format;
- list = dec_find_info_resp(pdu, len, &format);
- if (list == NULL)
+ if (status != 0) {
+ error("Discover descriptors failed: %s", att_ecode2str(status));
return;
+ }
- if (format != ATT_FIND_INFO_RESP_FMT_16BIT)
- goto done;
-
- ptr = list->data[0];
- handle = get_le16(ptr);
- uuid16 = get_le16(&ptr[2]);
-
- if (uuid16 != GATT_CLIENT_CHARAC_CFG_UUID)
- goto done;
+ /* There will be only one descriptor on list and it will be CCC */
+ desc = descs->data;
put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
- gatt_write_char(scan->attrib, handle, value, sizeof(value),
+ gatt_write_char(scan->attrib, desc->handle, value, sizeof(value),
ccc_written_cb, user_data);
-done:
- att_data_list_free(list);
}
static void refresh_discovered_cb(uint8_t status, GSList *chars,
@@ -139,6 +128,7 @@ static void refresh_discovered_cb(uint8_t status, GSList *chars,
struct scan *scan = user_data;
struct gatt_char *chr;
uint16_t start, end;
+ bt_uuid_t uuid;
if (status) {
error("Scan Refresh %s", att_ecode2str(status));
@@ -162,7 +152,9 @@ static void refresh_discovered_cb(uint8_t status, GSList *chars,
scan->refresh_handle = chr->value_handle;
- gatt_discover_char_desc(scan->attrib, start, end,
+ bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+
+ gatt_discover_desc(scan->attrib, start, end, &uuid,
discover_descriptor_cb, user_data);
}
--
1.9.2
---
profiles/input/hog.c | 52 ++++++++++++----------------------------------------
1 file changed, 12 insertions(+), 40 deletions(-)
diff --git a/profiles/input/hog.c b/profiles/input/hog.c
index ae2affd..f79f977 100644
--- a/profiles/input/hog.c
+++ b/profiles/input/hog.c
@@ -199,74 +199,46 @@ static void external_report_reference_cb(guint8 status, const guint8 *pdu,
guint16 plen, gpointer user_data);
-static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
- guint16 len, gpointer user_data)
+static void discover_descriptor_cb(uint8_t status, GSList *descs,
+ void *user_data)
{
struct disc_desc_cb_data *ddcb_data = user_data;
struct report *report;
struct hog_device *hogdev;
- struct att_data_list *list = NULL;
GAttrib *attrib = NULL;
- uint8_t format;
- uint16_t handle = 0xffff;
- uint16_t end = ddcb_data->end;
- int i;
-
- if (status == ATT_ECODE_ATTR_NOT_FOUND) {
- DBG("Discover all characteristic descriptors finished");
- goto done;
- }
if (status != 0) {
- error("Discover all characteristic descriptors failed: %s",
+ error("Discover all descriptors failed: %s",
att_ecode2str(status));
goto done;
}
- list = dec_find_info_resp(pdu, len, &format);
- if (list == NULL)
- return;
-
- if (format != ATT_FIND_INFO_RESP_FMT_16BIT)
- goto done;
-
- for (i = 0; i < list->num; i++) {
- uint16_t uuid16;
- uint8_t *value;
+ for ( ; descs; descs = descs->next) {
+ struct gatt_desc *desc = descs->data;
- value = list->data[i];
- handle = get_le16(value);
- uuid16 = get_le16(&value[2]);
-
- switch (uuid16) {
+ switch (desc->uuid16) {
case GATT_CLIENT_CHARAC_CFG_UUID:
report = ddcb_data->data;
attrib = report->hogdev->attrib;
- write_ccc(handle, report);
+ write_ccc(desc->handle, report);
break;
case GATT_REPORT_REFERENCE:
report = ddcb_data->data;
attrib = report->hogdev->attrib;
- gatt_read_char(attrib, handle,
+ gatt_read_char(attrib, desc->handle,
report_reference_cb, report);
break;
case GATT_EXTERNAL_REPORT_REFERENCE:
hogdev = ddcb_data->data;
attrib = hogdev->attrib;
- gatt_read_char(attrib, handle,
+ gatt_read_char(attrib, desc->handle,
external_report_reference_cb, hogdev);
break;
}
}
done:
- att_data_list_free(list);
-
- if (handle != 0xffff && handle < end)
- gatt_discover_char_desc(attrib, handle + 1, end,
- discover_descriptor_cb, ddcb_data);
- else
- g_free(ddcb_data);
+ g_free(ddcb_data);
}
static void discover_descriptor(GAttrib *attrib, uint16_t start, uint16_t end,
@@ -281,8 +253,8 @@ static void discover_descriptor(GAttrib *attrib, uint16_t start, uint16_t end,
ddcb_data->end = end;
ddcb_data->data = user_data;
- gatt_discover_char_desc(attrib, start, end, discover_descriptor_cb,
- ddcb_data);
+ gatt_discover_desc(attrib, start, end, NULL,
+ discover_descriptor_cb, ddcb_data);
}
static void external_service_char_cb(uint8_t status, GSList *chars,
--
1.9.2
---
attrib/gatttool.c | 49 ++++++++++++-------------------------------------
attrib/interactive.c | 49 ++++++++++---------------------------------------
2 files changed, 22 insertions(+), 76 deletions(-)
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 5e0f820..bca7f69 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -400,49 +400,23 @@ error:
return FALSE;
}
-static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
- gpointer user_data)
+static void char_desc_cb(uint8_t status, GSList *descriptors, void *user_data)
{
- struct att_data_list *list;
- guint8 format;
- int i;
+ GSList *l;
- if (status != 0) {
- g_printerr("Discover all characteristic descriptors failed: "
- "%s\n", att_ecode2str(status));
- goto done;
+ if (status) {
+ g_printerr("Discover descriptors failed: %s\n",
+ att_ecode2str(status));
+ return;
}
- list = dec_find_info_resp(pdu, plen, &format);
- if (list == NULL)
- goto done;
+ for (l = descriptors; l; l = l->next) {
+ struct gatt_desc *desc = l->data;
- for (i = 0; i < list->num; i++) {
- char uuidstr[MAX_LEN_UUID_STR];
- uint16_t handle;
- uint8_t *value;
- bt_uuid_t uuid;
-
- value = list->data[i];
- handle = get_le16(value);
-
- if (format == ATT_FIND_INFO_RESP_FMT_16BIT)
- bt_uuid16_create(&uuid, get_le16(&value[2]));
- else {
- uint128_t u128;
-
- /* Converts from LE to BE byte order */
- bswap_128(&value[2], &u128);
- bt_uuid128_create(&uuid, u128);
- }
-
- bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR);
- g_print("handle = 0x%04x, uuid = %s\n", handle, uuidstr);
+ g_print("handle = 0x%04x, uuid = %s\n", desc->handle,
+ desc->uuid);
}
- att_data_list_free(list);
-
-done:
if (!opt_listen)
g_main_loop_quit(event_loop);
}
@@ -451,7 +425,8 @@ static gboolean characteristics_desc(gpointer user_data)
{
GAttrib *attrib = user_data;
- gatt_discover_char_desc(attrib, opt_start, opt_end, char_desc_cb, NULL);
+ gatt_discover_desc(attrib, opt_start, opt_end, NULL, char_desc_cb,
+ NULL);
return FALSE;
}
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 4865944..08f39f7 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -269,51 +269,22 @@ static void char_cb(uint8_t status, GSList *characteristics, void *user_data)
}
}
-static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
- gpointer user_data)
+static void char_desc_cb(uint8_t status, GSList *descriptors, void *user_data)
{
- struct att_data_list *list;
- guint8 format;
- uint16_t handle = 0xffff;
- int i;
+ GSList *l;
- if (status != 0) {
- rl_printf("Discover descriptors finished: %s\n",
- att_ecode2str(status));
+ if (status) {
+ error("Discover descriptors failed: %s\n",
+ att_ecode2str(status));
return;
}
- list = dec_find_info_resp(pdu, plen, &format);
- if (list == NULL)
- return;
+ for (l = descriptors; l; l = l->next) {
+ struct gatt_desc *desc = l->data;
- for (i = 0; i < list->num; i++) {
- char uuidstr[MAX_LEN_UUID_STR];
- uint8_t *value;
- bt_uuid_t uuid;
-
- value = list->data[i];
- handle = get_le16(value);
-
- if (format == 0x01)
- bt_uuid16_create(&uuid, get_le16(&value[2]));
- else {
- uint128_t u128;
-
- /* Converts from LE to BE byte order */
- bswap_128(&value[2], &u128);
- bt_uuid128_create(&uuid, u128);
- }
-
- bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR);
- rl_printf("handle: 0x%04x, uuid: %s\n", handle, uuidstr);
+ rl_printf("handle: 0x%04x, uuid: %s\n", desc->handle,
+ desc->uuid);
}
-
- att_data_list_free(list);
-
- if (handle != 0xffff && handle < end)
- gatt_discover_char_desc(attrib, handle + 1, end, char_desc_cb,
- NULL);
}
static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
@@ -564,7 +535,7 @@ static void cmd_char_desc(int argcp, char **argvp)
} else
end = 0xffff;
- gatt_discover_char_desc(attrib, start, end, char_desc_cb, NULL);
+ gatt_discover_desc(attrib, start, end, NULL, char_desc_cb, NULL);
}
static void cmd_read_hnd(int argcp, char **argvp)
--
1.9.2
---
profiles/gatt/gas.c | 40 +++++++++++++---------------------------
1 file changed, 13 insertions(+), 27 deletions(-)
diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index 7a9d34e..d240450 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -238,40 +238,22 @@ static void write_ccc(GAttrib *attrib, uint16_t handle, gpointer user_data)
user_data);
}
-static void gatt_descriptors_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
+static void discover_ccc_cb(uint8_t status, GSList *descs, void *user_data)
{
struct gas *gas = user_data;
- struct att_data_list *list;
- int i;
- uint8_t format;
+ struct gatt_desc *desc;
- if (status) {
- error("Discover all GATT characteristic descriptors: %s",
+ if (status != 0) {
+ error("Discover Service Changed CCC failed: %s",
att_ecode2str(status));
return;
}
- list = dec_find_info_resp(pdu, len, &format);
- if (list == NULL)
- return;
-
- if (format != ATT_FIND_INFO_RESP_FMT_16BIT)
- goto done;
-
- for (i = 0; i < list->num; i++) {
- uint16_t uuid16, ccc;
- uint8_t *value;
-
- value = list->data[i];
- ccc = get_le16(value);
- uuid16 = get_le16(&value[2]);
- DBG("CCC: 0x%04x UUID: 0x%04x", ccc, uuid16);
- write_ccc(gas->attrib, ccc, user_data);
- }
+ /* There will be only one descriptor on list and it will be CCC */
+ desc = descs->data;
-done:
- att_data_list_free(list);
+ DBG("CCC: 0x%04x", desc->handle);
+ write_ccc(gas->attrib, desc->handle, user_data);
}
static void gatt_characteristic_cb(uint8_t status, GSList *characteristics,
@@ -280,6 +262,7 @@ static void gatt_characteristic_cb(uint8_t status, GSList *characteristics,
struct gas *gas = user_data;
struct gatt_char *chr;
uint16_t start, end;
+ bt_uuid_t uuid;
if (status) {
error("Discover Service Changed handle: %s", att_ecode2str(status));
@@ -297,7 +280,10 @@ static void gatt_characteristic_cb(uint8_t status, GSList *characteristics,
}
gas->changed_handle = chr->value_handle;
- gatt_discover_char_desc(gas->attrib, start, end, gatt_descriptors_cb,
+
+ bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+
+ gatt_discover_desc(gas->attrib, start, end, &uuid, discover_ccc_cb,
gas);
}
--
1.9.2
Since complete descriptor discovery is now performed inside gatt code,
there's no need to store end handle for characteristics and thus we can
remove disc_desc_cb_data.
---
profiles/input/hog.c | 25 +++++--------------------
1 file changed, 5 insertions(+), 20 deletions(-)
diff --git a/profiles/input/hog.c b/profiles/input/hog.c
index f79f977..12bc19a 100644
--- a/profiles/input/hog.c
+++ b/profiles/input/hog.c
@@ -102,11 +102,6 @@ struct report {
struct hog_device *hogdev;
};
-struct disc_desc_cb_data {
- uint16_t end;
- gpointer data;
-};
-
static gboolean suspend_supported = FALSE;
static GSList *devices = NULL;
@@ -202,7 +197,6 @@ static void external_report_reference_cb(guint8 status, const guint8 *pdu,
static void discover_descriptor_cb(uint8_t status, GSList *descs,
void *user_data)
{
- struct disc_desc_cb_data *ddcb_data = user_data;
struct report *report;
struct hog_device *hogdev;
GAttrib *attrib = NULL;
@@ -210,7 +204,7 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
if (status != 0) {
error("Discover all descriptors failed: %s",
att_ecode2str(status));
- goto done;
+ return;
}
for ( ; descs; descs = descs->next) {
@@ -218,43 +212,34 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
switch (desc->uuid16) {
case GATT_CLIENT_CHARAC_CFG_UUID:
- report = ddcb_data->data;
+ report = user_data;
attrib = report->hogdev->attrib;
write_ccc(desc->handle, report);
break;
case GATT_REPORT_REFERENCE:
- report = ddcb_data->data;
+ report = user_data;
attrib = report->hogdev->attrib;
gatt_read_char(attrib, desc->handle,
report_reference_cb, report);
break;
case GATT_EXTERNAL_REPORT_REFERENCE:
- hogdev = ddcb_data->data;
+ hogdev = user_data;
attrib = hogdev->attrib;
gatt_read_char(attrib, desc->handle,
external_report_reference_cb, hogdev);
break;
}
}
-
-done:
- g_free(ddcb_data);
}
static void discover_descriptor(GAttrib *attrib, uint16_t start, uint16_t end,
gpointer user_data)
{
- struct disc_desc_cb_data *ddcb_data;
-
if (start > end)
return;
- ddcb_data = g_new0(struct disc_desc_cb_data, 1);
- ddcb_data->end = end;
- ddcb_data->data = user_data;
-
gatt_discover_desc(attrib, start, end, NULL,
- discover_descriptor_cb, ddcb_data);
+ discover_descriptor_cb, user_data);
}
static void external_service_char_cb(uint8_t status, GSList *chars,
--
1.9.2
This function is no longer used since all code is changed to use
gatt_discover_desc instead.
---
attrib/gatt.c | 15 ---------------
attrib/gatt.h | 3 ---
2 files changed, 18 deletions(-)
diff --git a/attrib/gatt.c b/attrib/gatt.c
index f766617..73eaf7a 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -1053,21 +1053,6 @@ guint gatt_discover_desc(GAttrib *attrib, uint16_t start, uint16_t end,
discover_desc_ref(dd), discover_desc_unref);
}
-guint gatt_discover_char_desc(GAttrib *attrib, uint16_t start, uint16_t end,
- GAttribResultFunc func, gpointer user_data)
-{
- uint8_t *buf;
- size_t buflen;
- guint16 plen;
-
- buf = g_attrib_get_buffer(attrib, &buflen);
- plen = enc_find_info_req(start, end, buf, buflen);
- if (plen == 0)
- return 0;
-
- return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
-}
-
guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, const uint8_t *value,
int vlen, GDestroyNotify notify, gpointer user_data)
{
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 533bfd7..7d055f0 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -102,9 +102,6 @@ guint gatt_reliable_write_char(GAttrib *attrib, uint16_t handle,
guint gatt_execute_write(GAttrib *attrib, uint8_t flags,
GAttribResultFunc func, gpointer user_data);
-guint gatt_discover_char_desc(GAttrib *attrib, uint16_t start, uint16_t end,
- GAttribResultFunc func, gpointer user_data);
-
guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, const uint8_t *value,
int vlen, GDestroyNotify notify, gpointer user_data);
--
1.9.2