* [PATCH v4 BlueZ 1/4] gatt: Add support for find included services
@ 2012-10-09 0:17 Vinicius Costa Gomes
2012-10-09 0:17 ` [PATCH v4 BlueZ 2/4] gatttool: Add "included" command Vinicius Costa Gomes
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Vinicius Costa Gomes @ 2012-10-09 0:17 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
Some services like HID over LE can reference another service using
included services.
See Vol 3, Part G, section 2.6.3 of Core specification for more
details.
---
attrib/gatt.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
attrib/gatt.h | 9 +++
2 files changed, 201 insertions(+)
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 882f3c1..d55e7fe 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -45,6 +45,22 @@ struct discover_primary {
void *user_data;
};
+/* Used for the Included Services Discovery (ISD) procedure */
+struct included_discovery {
+ GAttrib *attrib;
+ int refs;
+ int err;
+ uint16_t end_handle;
+ GSList *includes;
+ gatt_cb_t cb;
+ void *user_data;
+};
+
+struct included_uuid_query {
+ struct included_discovery *isd;
+ struct gatt_included *included;
+};
+
struct discover_char {
GAttrib *attrib;
bt_uuid_t *uuid;
@@ -61,6 +77,25 @@ static void discover_primary_free(struct discover_primary *dp)
g_free(dp);
}
+static struct included_discovery *isd_ref(struct included_discovery *isd)
+{
+ g_atomic_int_inc(&isd->refs);
+
+ return isd;
+}
+
+static void isd_unref(struct included_discovery *isd)
+{
+ if (g_atomic_int_dec_and_test(&isd->refs) == FALSE)
+ return;
+
+ isd->cb(isd->includes, isd->err, isd->user_data);
+
+ g_slist_free_full(isd->includes, g_free);
+ g_attrib_unref(isd->attrib);
+ g_free(isd);
+}
+
static void discover_char_free(struct discover_char *dc)
{
g_slist_free_full(dc->characteristics, g_free);
@@ -248,6 +283,163 @@ guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
return g_attrib_send(attrib, 0, buf[0], buf, plen, cb, dp, NULL);
}
+static void resolve_included_uuid_cb(uint8_t status, const uint8_t *pdu,
+ uint16_t len, gpointer user_data)
+{
+ struct included_uuid_query *query = user_data;
+ struct included_discovery *isd = query->isd;
+ struct gatt_included *incl = query->included;
+ unsigned int err = status;
+ bt_uuid_t uuid;
+ size_t buflen;
+ uint8_t *buf;
+
+ if (err)
+ goto done;
+
+ buf = g_attrib_get_buffer(isd->attrib, &buflen);
+ if (dec_read_resp(pdu, len, buf, buflen) != 16) {
+ err = ATT_ECODE_IO;
+ goto done;
+ }
+
+ uuid = att_get_uuid128(buf);
+ bt_uuid_to_string(&uuid, incl->uuid, sizeof(incl->uuid));
+ isd->includes = g_slist_append(isd->includes, incl);
+
+done:
+ if (err)
+ g_free(incl);
+
+ if (isd->err == 0)
+ isd->err = err;
+
+ isd_unref(isd);
+
+ g_free(query);
+}
+
+static guint resolve_included_uuid(struct included_discovery *isd,
+ struct gatt_included *incl)
+{
+ struct included_uuid_query *query;
+ size_t buflen;
+ uint8_t *buf = g_attrib_get_buffer(isd->attrib, &buflen);
+ guint16 oplen = enc_read_req(incl->range.start, buf, buflen);
+
+ query = g_new0(struct included_uuid_query, 1);
+ query->isd = isd_ref(isd);
+ query->included = incl;
+
+ return g_attrib_send(isd->attrib, 0, buf[0], buf, oplen,
+ resolve_included_uuid_cb, query, NULL);
+}
+
+static struct gatt_included *included_from_buf(const uint8_t *buf, gsize len)
+{
+ struct gatt_included *incl = g_new0(struct gatt_included, 1);
+
+ incl->handle = att_get_u16(&buf[0]);
+ incl->range.start = att_get_u16(&buf[2]);
+ incl->range.end = att_get_u16(&buf[4]);
+
+ if (len == 8) {
+ bt_uuid_t uuid128;
+ bt_uuid_t uuid16 = att_get_uuid16(&buf[6]);
+
+ bt_uuid_to_uuid128(&uuid16, &uuid128);
+ bt_uuid_to_string(&uuid128, incl->uuid, sizeof(incl->uuid));
+ }
+
+ return incl;
+}
+
+static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
+ gpointer user_data);
+
+static guint find_included(struct included_discovery *isd, uint16_t start)
+{
+ bt_uuid_t uuid;
+ size_t buflen;
+ uint8_t *buf = g_attrib_get_buffer(isd->attrib, &buflen);
+ guint16 oplen;
+
+ bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
+ oplen = enc_read_by_type_req(start, isd->end_handle, &uuid,
+ buf, buflen);
+
+ return g_attrib_send(isd->attrib, 0, buf[0], buf, oplen,
+ find_included_cb, isd_ref(isd), NULL);
+}
+
+static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
+ gpointer user_data)
+{
+ struct included_discovery *isd = user_data;
+ uint16_t last_handle = isd->end_handle;
+ unsigned int err = status;
+ struct att_data_list *list;
+ int i;
+
+ if (err == ATT_ECODE_ATTR_NOT_FOUND)
+ err = 0;
+
+ if (status)
+ goto done;
+
+ list = dec_read_by_type_resp(pdu, len);
+ if (list == NULL) {
+ err = ATT_ECODE_IO;
+ goto done;
+ }
+
+ if (list->len != 6 && list->len != 8) {
+ err = ATT_ECODE_IO;
+ att_data_list_free(list);
+ goto done;
+ }
+
+ for (i = 0; i < list->num; i++) {
+ struct gatt_included *incl;
+
+ incl = included_from_buf(list->data[i], list->len);
+ last_handle = incl->handle;
+
+ /* 128 bit UUID, needs resolving */
+ if (list->len == 6) {
+ resolve_included_uuid(isd, incl);
+ continue;
+ }
+
+ isd->includes = g_slist_append(isd->includes, incl);
+ }
+
+ att_data_list_free(list);
+
+ if (last_handle < isd->end_handle)
+ find_included(isd, last_handle + 1);
+
+done:
+ if (isd->err == 0)
+ isd->err = err;
+
+ isd_unref(isd);
+}
+
+unsigned int gatt_find_included(GAttrib *attrib, uint16_t start, uint16_t end,
+ gatt_cb_t func, gpointer user_data)
+{
+ struct included_discovery *isd;
+
+ isd = g_new0(struct included_discovery, 1);
+ isd->attrib = g_attrib_ref(attrib);
+ isd->end_handle = end;
+ isd->cb = func;
+ isd->user_data = user_data;
+
+ return find_included(isd, start);
+}
+
static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
gpointer user_data)
{
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 3862011..305b4c6 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -61,6 +61,12 @@ struct gatt_primary {
struct att_range range;
};
+struct gatt_included {
+ char uuid[MAX_LEN_UUID_STR + 1];
+ uint16_t handle;
+ struct att_range range;
+};
+
struct gatt_char {
char uuid[MAX_LEN_UUID_STR + 1];
uint16_t handle;
@@ -71,6 +77,9 @@ struct gatt_char {
guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
+unsigned int gatt_find_included(GAttrib *attrib, uint16_t start, uint16_t end,
+ gatt_cb_t func, gpointer user_data);
+
guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
--
1.7.12.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v4 BlueZ 2/4] gatttool: Add "included" command 2012-10-09 0:17 [PATCH v4 BlueZ 1/4] gatt: Add support for find included services Vinicius Costa Gomes @ 2012-10-09 0:17 ` Vinicius Costa Gomes 2012-10-09 0:17 ` [PATCH v4 BlueZ 3/4] core: Add support for included services Vinicius Costa Gomes ` (2 subsequent siblings) 3 siblings, 0 replies; 5+ messages in thread From: Vinicius Costa Gomes @ 2012-10-09 0:17 UTC (permalink / raw) To: linux-bluetooth; +Cc: Jefferson Delfes From: Jefferson Delfes <jefferson.delfes@openbossa.org> New command to find included services in interactive mode. --- This produces a warning when applying, but the warning can be ignored for that particular string. WARNING:SPLIT_STRING: quoted string split across lines #36: FILE: attrib/interactive.c:233: + printf("handle: 0x%04x, start handle: 0x%04x, " + "end handle: 0x%04x uuid: %s\n", attrib/interactive.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/attrib/interactive.c b/attrib/interactive.c index 8d9531f..85f72ad 100644 --- a/attrib/interactive.c +++ b/attrib/interactive.c @@ -211,6 +211,34 @@ static void primary_by_uuid_cb(GSList *ranges, guint8 status, rl_forced_update_display(); } +static void included_cb(GSList *includes, guint8 status, gpointer user_data) +{ + GSList *l; + + if (status) { + printf("Find included services failed: %s\n", + att_ecode2str(status)); + goto done; + } + + if (includes == NULL) { + printf("No included services found for this range\n"); + goto done; + } + + printf("\n"); + for (l = includes; l; l = l->next) { + struct gatt_included *incl = l->data; + printf("handle: 0x%04x, start handle: 0x%04x, " + "end handle: 0x%04x uuid: %s\n", + incl->handle, incl->range.start, + incl->range.end, incl->uuid); + } + +done: + rl_forced_update_display(); +} + static void char_cb(GSList *characteristics, guint8 status, gpointer user_data) { GSList *l; @@ -431,6 +459,36 @@ static int strtohandle(const char *src) return dst; } +static void cmd_included(int argcp, char **argvp) +{ + int start = 0x0001; + int end = 0xffff; + + if (conn_state != STATE_CONNECTED) { + printf("Command failed: disconnected\n"); + return; + } + + if (argcp > 1) { + start = strtohandle(argvp[1]); + if (start < 0) { + printf("Invalid start handle: %s\n", argvp[1]); + return; + } + end = start; + } + + if (argcp > 2) { + end = strtohandle(argvp[2]); + if (end < 0) { + printf("Invalid end handle: %s\n", argvp[2]); + return; + } + } + + gatt_find_included(attrib, start, end, included_cb, NULL); +} + static void cmd_char(int argcp, char **argvp) { int start = 0x0001; @@ -743,6 +801,8 @@ static struct { "Disconnect from a remote device" }, { "primary", cmd_primary, "[UUID]", "Primary Service Discovery" }, + { "included", cmd_included, "[start hnd [end hnd]]", + "Find Included Services" }, { "characteristics", cmd_char, "[start hnd [end hnd [UUID]]]", "Characteristics Discovery" }, { "char-desc", cmd_char_desc, "[start hnd] [end hnd]", -- 1.7.12.2 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 BlueZ 3/4] core: Add support for included services 2012-10-09 0:17 [PATCH v4 BlueZ 1/4] gatt: Add support for find included services Vinicius Costa Gomes 2012-10-09 0:17 ` [PATCH v4 BlueZ 2/4] gatttool: Add "included" command Vinicius Costa Gomes @ 2012-10-09 0:17 ` Vinicius Costa Gomes 2012-10-09 0:17 ` [PATCH v4 BlueZ 4/4] attrib: Remove opcode parameter from g_attrib_send() Vinicius Costa Gomes 2012-10-09 8:57 ` [PATCH v4 BlueZ 1/4] gatt: Add support for find included services Johan Hedberg 3 siblings, 0 replies; 5+ messages in thread From: Vinicius Costa Gomes @ 2012-10-09 0:17 UTC (permalink / raw) To: linux-bluetooth; +Cc: Vinicius Costa Gomes Soon after the primary service discovery is complete, we do a included services discovery for all found services and add each included service to the 'services' list so they can be probe()'d as a normal profile. This will also make these services to appear on the D-Bus object tree. --- src/device.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 96 insertions(+), 13 deletions(-) diff --git a/src/device.c b/src/device.c index d356631..e94b222 100644 --- a/src/device.c +++ b/src/device.c @@ -112,6 +112,12 @@ struct browse_req { guint listener_id; }; +struct included_search { + struct browse_req *req; + GSList *services; + GSList *current; +}; + struct attio_data { guint id; attio_connect_cb cfunc; @@ -2192,21 +2198,10 @@ static void device_unregister_services(struct btd_device *device) device->services = NULL; } -static void primary_cb(GSList *services, guint8 status, gpointer user_data) +static void register_all_services(struct browse_req *req, GSList *services) { - struct browse_req *req = user_data; struct btd_device *device = req->device; - if (status) { - if (req->msg) { - DBusMessage *reply; - reply = btd_error_failed(req->msg, - att_ecode2str(status)); - g_dbus_send_message(btd_get_dbus_connection(), reply); - } - goto done; - } - device_set_temporary(device, FALSE); if (device->services) @@ -2231,11 +2226,99 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data) store_services(device); -done: device->browse = NULL; browse_request_free(req); } +static int service_by_range_cmp(gconstpointer a, gconstpointer b) +{ + const struct gatt_primary *prim = a; + const struct att_range *range = b; + + return memcmp(&prim->range, range, sizeof(*range)); +} + +static void find_included_cb(GSList *includes, uint8_t status, + gpointer user_data) +{ + struct included_search *search = user_data; + struct btd_device *device = search->req->device; + struct gatt_primary *prim; + GSList *l; + + if (includes == NULL) + goto done; + + for (l = includes; l; l = l->next) { + struct gatt_included *incl = l->data; + + if (g_slist_find_custom(search->services, &incl->range, + service_by_range_cmp)) + continue; + + prim = g_new0(struct gatt_primary, 1); + memcpy(prim->uuid, incl->uuid, sizeof(prim->uuid)); + memcpy(&prim->range, &incl->range, sizeof(prim->range)); + + search->services = g_slist_append(search->services, prim); + } + +done: + search->current = search->current->next; + if (search->current == NULL) { + register_all_services(search->req, search->services); + g_slist_free(search->services); + g_free(search); + return; + } + + prim = search->current->data; + gatt_find_included(device->attrib, prim->range.start, prim->range.end, + find_included_cb, search); +} + +static void find_included_services(struct browse_req *req, GSList *services) +{ + struct btd_device *device = req->device; + struct included_search *search; + struct gatt_primary *prim; + + if (services == NULL) + return; + + search = g_new0(struct included_search, 1); + search->req = req; + search->services = g_slist_copy(services); + search->current = search->services; + + prim = search->current->data; + gatt_find_included(device->attrib, prim->range.start, prim->range.end, + find_included_cb, search); + +} + +static void primary_cb(GSList *services, guint8 status, gpointer user_data) +{ + struct browse_req *req = user_data; + + if (status) { + struct btd_device *device = req->device; + + if (req->msg) { + DBusMessage *reply; + reply = btd_error_failed(req->msg, + att_ecode2str(status)); + g_dbus_send_message(btd_get_dbus_connection(), reply); + } + + device->browse = NULL; + browse_request_free(req); + return; + } + + find_included_services(req, services); +} + static void bonding_request_free(struct bonding_req *bonding) { struct btd_device *device; -- 1.7.12.2 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 BlueZ 4/4] attrib: Remove opcode parameter from g_attrib_send() 2012-10-09 0:17 [PATCH v4 BlueZ 1/4] gatt: Add support for find included services Vinicius Costa Gomes 2012-10-09 0:17 ` [PATCH v4 BlueZ 2/4] gatttool: Add "included" command Vinicius Costa Gomes 2012-10-09 0:17 ` [PATCH v4 BlueZ 3/4] core: Add support for included services Vinicius Costa Gomes @ 2012-10-09 0:17 ` Vinicius Costa Gomes 2012-10-09 8:57 ` [PATCH v4 BlueZ 1/4] gatt: Add support for find included services Johan Hedberg 3 siblings, 0 replies; 5+ messages in thread From: Vinicius Costa Gomes @ 2012-10-09 0:17 UTC (permalink / raw) To: linux-bluetooth; +Cc: Vinicius Costa Gomes In all uses of g_attrib_send() the opcode of the command/event is already clear because of the att.h functions used to build the ATT PDU. --- attrib/client.c | 3 +-- attrib/gatt.c | 51 ++++++++++++++++---------------------- attrib/gattrib.c | 9 ++++--- attrib/gattrib.h | 6 ++--- attrib/gatttool.c | 2 +- attrib/interactive.c | 2 +- profiles/alert/server.c | 3 +-- profiles/gatt/gas.c | 2 +- profiles/thermometer/thermometer.c | 3 +-- src/attrib-server.c | 3 +-- 10 files changed, 37 insertions(+), 47 deletions(-) diff --git a/attrib/client.c b/attrib/client.c index 30513d1..8b29cbb 100644 --- a/attrib/client.c +++ b/attrib/client.c @@ -354,8 +354,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, case ATT_OP_HANDLE_IND: opdu = g_attrib_get_buffer(gatt->attrib, &plen); olen = enc_confirmation(opdu, plen); - g_attrib_send(gatt->attrib, 0, opdu[0], opdu, olen, - NULL, NULL, NULL); + g_attrib_send(gatt->attrib, 0, opdu, olen, NULL, NULL, NULL); case ATT_OP_HANDLE_NOTIFY: if (characteristic_set_value(chr, &pdu[3], len - 3) < 0) DBG("Can't change Characteristic 0x%02x", handle); diff --git a/attrib/gatt.c b/attrib/gatt.c index d55e7fe..963fa20 100644 --- a/attrib/gatt.c +++ b/attrib/gatt.c @@ -176,8 +176,7 @@ static void primary_by_uuid_cb(guint8 status, const guint8 *ipdu, if (oplen == 0) goto done; - g_attrib_send(dp->attrib, 0, buf[0], buf, oplen, primary_by_uuid_cb, - dp, NULL); + g_attrib_send(dp->attrib, 0, buf, oplen, primary_by_uuid_cb, dp, NULL); return; done: @@ -242,7 +241,7 @@ static void primary_all_cb(guint8 status, const guint8 *ipdu, guint16 iplen, guint16 oplen = encode_discover_primary(end + 1, 0xffff, NULL, buf, buflen); - g_attrib_send(dp->attrib, 0, buf[0], buf, oplen, primary_all_cb, + g_attrib_send(dp->attrib, 0, buf, oplen, primary_all_cb, dp, NULL); return; @@ -280,7 +279,7 @@ guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func, } else cb = primary_all_cb; - return g_attrib_send(attrib, 0, buf[0], buf, plen, cb, dp, NULL); + return g_attrib_send(attrib, 0, buf, plen, cb, dp, NULL); } static void resolve_included_uuid_cb(uint8_t status, const uint8_t *pdu, @@ -331,7 +330,7 @@ static guint resolve_included_uuid(struct included_discovery *isd, query->isd = isd_ref(isd); query->included = incl; - return g_attrib_send(isd->attrib, 0, buf[0], buf, oplen, + return g_attrib_send(isd->attrib, 0, buf, oplen, resolve_included_uuid_cb, query, NULL); } @@ -368,8 +367,8 @@ static guint find_included(struct included_discovery *isd, uint16_t start) oplen = enc_read_by_type_req(start, isd->end_handle, &uuid, buf, buflen); - return g_attrib_send(isd->attrib, 0, buf[0], buf, oplen, - find_included_cb, isd_ref(isd), NULL); + return g_attrib_send(isd->attrib, 0, buf, oplen, find_included_cb, + isd_ref(isd), NULL); } static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len, @@ -506,8 +505,8 @@ static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen, if (oplen == 0) return; - g_attrib_send(dc->attrib, 0, buf[0], buf, oplen, - char_discovered_cb, dc, NULL); + g_attrib_send(dc->attrib, 0, buf, oplen, char_discovered_cb, + dc, NULL); return; } @@ -545,7 +544,7 @@ guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end, dc->end = end; dc->uuid = g_memdup(uuid, sizeof(bt_uuid_t)); - return g_attrib_send(attrib, 0, buf[0], buf, plen, char_discovered_cb, + return g_attrib_send(attrib, 0, buf, plen, char_discovered_cb, dc, NULL); } @@ -561,8 +560,7 @@ guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end, if (plen == 0) return 0; - return g_attrib_send(attrib, 0, ATT_OP_READ_BY_TYPE_REQ, - buf, plen, func, user_data, NULL); + return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL); } struct read_long_data { @@ -621,8 +619,7 @@ static void read_blob_helper(guint8 status, const guint8 *rpdu, guint16 rlen, plen = enc_read_blob_req(long_read->handle, long_read->size - 1, buf, buflen); - id = g_attrib_send(long_read->attrib, long_read->id, - ATT_OP_READ_BLOB_REQ, buf, plen, + id = g_attrib_send(long_read->attrib, long_read->id, buf, plen, read_blob_helper, long_read, read_long_destroy); if (id != 0) { @@ -658,9 +655,8 @@ static void read_char_helper(guint8 status, const guint8 *rpdu, long_read->size = rlen; plen = enc_read_blob_req(long_read->handle, rlen - 1, buf, buflen); - id = g_attrib_send(long_read->attrib, long_read->id, - ATT_OP_READ_BLOB_REQ, buf, plen, read_blob_helper, - long_read, read_long_destroy); + id = g_attrib_send(long_read->attrib, long_read->id, buf, plen, + read_blob_helper, long_read, read_long_destroy); if (id != 0) { g_atomic_int_inc(&long_read->ref); @@ -694,9 +690,8 @@ guint gatt_read_char(GAttrib *attrib, uint16_t handle, GAttribResultFunc func, buf = g_attrib_get_buffer(attrib, &buflen); plen = enc_read_req(handle, buf, buflen); - id = g_attrib_send(attrib, 0, ATT_OP_READ_REQ, buf, plen, - read_char_helper, long_read, read_long_destroy); - + id = g_attrib_send(attrib, 0, buf, plen, read_char_helper, + long_read, read_long_destroy); if (id == 0) g_free(long_read); else { @@ -729,8 +724,7 @@ static guint execute_write(GAttrib *attrib, uint8_t flags, if (plen == 0) return 0; - return g_attrib_send(attrib, 0, buf[0], buf, plen, func, user_data, - NULL); + return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL); } static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset, @@ -779,7 +773,7 @@ static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset, if (plen == 0) return 0; - return g_attrib_send(attrib, 0, buf[0], buf, plen, prepare_write_cb, + return g_attrib_send(attrib, 0, buf, plen, prepare_write_cb, user_data, NULL); } @@ -803,7 +797,7 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value, plen = enc_write_cmd(handle, value, vlen, buf, buflen); - return g_attrib_send(attrib, 0, buf[0], buf, plen, func, + return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL); } @@ -832,8 +826,7 @@ guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func, buf = g_attrib_get_buffer(attrib, &buflen); plen = enc_mtu_req(mtu, buf, buflen); - return g_attrib_send(attrib, 0, ATT_OP_MTU_REQ, buf, plen, func, - user_data, NULL); + return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL); } guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end, @@ -848,8 +841,7 @@ guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end, if (plen == 0) return 0; - return g_attrib_send(attrib, 0, ATT_OP_FIND_INFO_REQ, buf, plen, func, - user_data, NULL); + return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL); } guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen, @@ -861,8 +853,7 @@ guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen, buf = g_attrib_get_buffer(attrib, &buflen); plen = enc_write_cmd(handle, value, vlen, buf, buflen); - return g_attrib_send(attrib, 0, ATT_OP_WRITE_CMD, buf, plen, NULL, - user_data, notify); + return g_attrib_send(attrib, 0, buf, plen, NULL, user_data, notify); } static sdp_data_t *proto_seq_find(sdp_list_t *proto_list) diff --git a/attrib/gattrib.c b/attrib/gattrib.c index 108d1d3..6f6942f 100644 --- a/attrib/gattrib.c +++ b/attrib/gattrib.c @@ -472,12 +472,13 @@ GAttrib *g_attrib_new(GIOChannel *io) return g_attrib_ref(attrib); } -guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode, - const guint8 *pdu, guint16 len, GAttribResultFunc func, - gpointer user_data, GDestroyNotify notify) +guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len, + GAttribResultFunc func, gpointer user_data, + GDestroyNotify notify) { struct command *c; GQueue *queue; + uint8_t opcode; if (attrib->stale) return 0; @@ -486,6 +487,8 @@ guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode, if (c == NULL) return 0; + opcode = pdu[0]; + c->opcode = opcode; c->expected = opcode2expected(opcode); c->pdu = g_malloc(len); diff --git a/attrib/gattrib.h b/attrib/gattrib.h index bcff039..bca966f 100644 --- a/attrib/gattrib.h +++ b/attrib/gattrib.h @@ -50,9 +50,9 @@ GIOChannel *g_attrib_get_channel(GAttrib *attrib); gboolean g_attrib_set_destroy_function(GAttrib *attrib, GDestroyNotify destroy, gpointer user_data); -guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode, - const guint8 *pdu, guint16 len, GAttribResultFunc func, - gpointer user_data, GDestroyNotify notify); +guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len, + GAttribResultFunc func, gpointer user_data, + GDestroyNotify notify); gboolean g_attrib_cancel(GAttrib *attrib, guint id); gboolean g_attrib_cancel_all(GAttrib *attrib); diff --git a/attrib/gatttool.c b/attrib/gatttool.c index 3b0ebbc..16cce0c 100644 --- a/attrib/gatttool.c +++ b/attrib/gatttool.c @@ -104,7 +104,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data) olen = enc_confirmation(opdu, plen); if (olen > 0) - g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL); + g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL); } static gboolean listen_start(gpointer user_data) diff --git a/attrib/interactive.c b/attrib/interactive.c index 85f72ad..b41a7bb 100644 --- a/attrib/interactive.c +++ b/attrib/interactive.c @@ -135,7 +135,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data) olen = enc_confirmation(opdu, plen); if (olen > 0) - g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL); + g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL); } static void connect_cb(GIOChannel *io, GError *err, gpointer user_data) diff --git a/profiles/alert/server.c b/profiles/alert/server.c index b8ea141..77de704 100644 --- a/profiles/alert/server.c +++ b/profiles/alert/server.c @@ -381,8 +381,7 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data) al_adapter->hnd_value[type], al_adapter->hnd_ccc[type]); - g_attrib_send(attrib, 0, ATT_OP_HANDLE_NOTIFY, pdu, len, - NULL, NULL, NULL); + g_attrib_send(attrib, 0, pdu, len, NULL, NULL, NULL); end: btd_device_remove_attio_callback(cb->device, cb->id); diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c index 82c2ef0..74ca9ce 100644 --- a/profiles/gatt/gas.c +++ b/profiles/gatt/gas.c @@ -224,7 +224,7 @@ static void indication_cb(const uint8_t *pdu, uint16_t len, gpointer user_data) /* Confirming indication received */ opdu = g_attrib_get_buffer(gas->attrib, &plen); olen = enc_confirmation(opdu, plen); - g_attrib_send(gas->attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL); + g_attrib_send(gas->attrib, 0, opdu, olen, NULL, NULL, NULL); btd_device_gatt_set_service_changed(gas->device, start, end); } diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c index 3506ba7..98cfb34 100644 --- a/profiles/thermometer/thermometer.c +++ b/profiles/thermometer/thermometer.c @@ -1167,8 +1167,7 @@ static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data) olen = enc_confirmation(opdu, plen); if (olen > 0) - g_attrib_send(t->attrib, 0, opdu[0], opdu, olen, NULL, NULL, - NULL); + g_attrib_send(t->attrib, 0, opdu, olen, NULL, NULL, NULL); } static void notif_handler(const uint8_t *pdu, uint16_t len, gpointer user_data) diff --git a/src/attrib-server.c b/src/attrib-server.c index 9155ab2..76a32af 100644 --- a/src/attrib-server.c +++ b/src/attrib-server.c @@ -1027,8 +1027,7 @@ done: length = enc_error_resp(ipdu[0], 0x0000, status, opdu, channel->mtu); - g_attrib_send(channel->attrib, 0, opdu[0], opdu, length, - NULL, NULL, NULL); + g_attrib_send(channel->attrib, 0, opdu, length, NULL, NULL, NULL); } guint attrib_channel_attach(GAttrib *attrib) -- 1.7.12.2 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v4 BlueZ 1/4] gatt: Add support for find included services 2012-10-09 0:17 [PATCH v4 BlueZ 1/4] gatt: Add support for find included services Vinicius Costa Gomes ` (2 preceding siblings ...) 2012-10-09 0:17 ` [PATCH v4 BlueZ 4/4] attrib: Remove opcode parameter from g_attrib_send() Vinicius Costa Gomes @ 2012-10-09 8:57 ` Johan Hedberg 3 siblings, 0 replies; 5+ messages in thread From: Johan Hedberg @ 2012-10-09 8:57 UTC (permalink / raw) To: Vinicius Costa Gomes; +Cc: linux-bluetooth Hi Vinicius, On Mon, Oct 08, 2012, Vinicius Costa Gomes wrote: > Some services like HID over LE can reference another service using > included services. > > See Vol 3, Part G, section 2.6.3 of Core specification for more > details. > --- > attrib/gatt.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > attrib/gatt.h | 9 +++ > 2 files changed, 201 insertions(+) All patches in this set have been applied. Thanks. Johan ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-10-09 8:57 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-10-09 0:17 [PATCH v4 BlueZ 1/4] gatt: Add support for find included services Vinicius Costa Gomes 2012-10-09 0:17 ` [PATCH v4 BlueZ 2/4] gatttool: Add "included" command Vinicius Costa Gomes 2012-10-09 0:17 ` [PATCH v4 BlueZ 3/4] core: Add support for included services Vinicius Costa Gomes 2012-10-09 0:17 ` [PATCH v4 BlueZ 4/4] attrib: Remove opcode parameter from g_attrib_send() Vinicius Costa Gomes 2012-10-09 8:57 ` [PATCH v4 BlueZ 1/4] gatt: Add support for find included services Johan Hedberg
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox