* [PATCHv6 12/14] shared/gatt: Add gatt-client include service iterator
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
It will allow user to take value, handle, start and end handle
of included service.
---
src/shared/gatt-client.c | 30 ++++++++++++++++++++++++++++++
src/shared/gatt-client.h | 10 ++++++++++
2 files changed, 40 insertions(+)
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index b2c33e3..1c50d82 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -1666,6 +1666,36 @@ bool bt_gatt_characteristic_iter_next(struct bt_gatt_characteristic_iter *iter,
return true;
}
+bool bt_gatt_include_service_iter_init(struct bt_gatt_incl_service_iter *iter,
+ const bt_gatt_service_t *service)
+{
+ if (!iter || !service)
+ return false;
+
+ memset(iter, 0, sizeof(*iter));
+ iter->service = (struct service_list *) service;
+
+ return true;
+}
+
+bool bt_gatt_include_service_iter_next(struct bt_gatt_incl_service_iter *iter,
+ const bt_gatt_included_service_t **incl)
+{
+ struct service_list *service;
+
+ if (!iter || !incl)
+ return false;
+
+ service = iter->service;
+
+ if (iter->pos >= service->num_includes)
+ return false;
+
+ *incl = &service->includes[iter->pos++];
+
+ return true;
+}
+
struct read_op {
bt_gatt_client_read_callback_t callback;
void *user_data;
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index 05b4838..bf4e7bb 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -113,6 +113,11 @@ struct bt_gatt_characteristic_iter {
size_t pos;
};
+struct bt_gatt_incl_service_iter {
+ void *service;
+ size_t pos;
+};
+
bool bt_gatt_service_iter_init(struct bt_gatt_service_iter *iter,
struct bt_gatt_client *client);
bool bt_gatt_service_iter_next(struct bt_gatt_service_iter *iter,
@@ -129,6 +134,11 @@ bool bt_gatt_characteristic_iter_init(struct bt_gatt_characteristic_iter *iter,
bool bt_gatt_characteristic_iter_next(struct bt_gatt_characteristic_iter *iter,
const bt_gatt_characteristic_t **chrc);
+bool bt_gatt_include_service_iter_init(struct bt_gatt_incl_service_iter *iter,
+ const bt_gatt_service_t *service);
+bool bt_gatt_include_service_iter_next(struct bt_gatt_incl_service_iter *iter,
+ const bt_gatt_included_service_t **inc);
+
typedef void (*bt_gatt_client_read_callback_t)(bool success, uint8_t att_ecode,
const uint8_t *value, uint16_t length,
void *user_data);
--
1.9.3
^ permalink raw reply related
* [PATCHv6 11/14] shared/gatt: Discover included services
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
---
src/shared/gatt-client.c | 106 +++++++++++++++++++++++++++++++++++++++++++++--
src/shared/gatt-client.h | 7 ++++
2 files changed, 109 insertions(+), 4 deletions(-)
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index e04724c..b2c33e3 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -69,6 +69,8 @@ struct service_list {
bt_gatt_service_t service;
struct chrc_data *chrcs;
size_t num_chrcs;
+ bt_gatt_included_service_t *includes;
+ size_t num_includes;
struct service_list *next;
};
@@ -253,6 +255,14 @@ static void service_destroy_characteristics(struct service_list *service)
free(service->chrcs);
}
+static void service_destroy_includes(struct service_list *service)
+{
+ free(service->includes);
+
+ service->includes = NULL;
+ service->num_includes = 0;
+}
+
static void service_list_clear(struct service_list **head,
struct service_list **tail)
{
@@ -265,6 +275,7 @@ static void service_list_clear(struct service_list **head,
while (l) {
service_destroy_characteristics(l);
+ service_destroy_includes(l);
tmp = l;
l = tmp->next;
free(tmp);
@@ -293,6 +304,7 @@ static void service_list_clear_range(struct service_list **head,
}
service_destroy_characteristics(cur);
+ service_destroy_includes(cur);
if (!prev)
*head = cur->next;
@@ -428,6 +440,91 @@ static int uuid_cmp(const uint8_t uuid128[16], uint16_t uuid16)
return memcmp(uuid128, rhs_uuid, sizeof(rhs_uuid));
}
+static void discover_incl_cb(bool success, uint8_t att_ecode,
+ struct bt_gatt_result *result, void *user_data)
+{
+ struct discovery_op *op = user_data;
+ struct bt_gatt_client *client = op->client;
+ struct bt_gatt_iter iter;
+ char uuid_str[MAX_LEN_UUID_STR];
+ bt_gatt_included_service_t *includes;
+ unsigned int includes_count, i;
+
+ if (!success) {
+ if (att_ecode == BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND)
+ goto next;
+
+ goto failed;
+ }
+
+ if (!result || !bt_gatt_iter_init(&iter, result))
+ goto failed;
+
+ includes_count = bt_gatt_result_included_count(result);
+ if (includes_count == 0)
+ goto failed;
+
+ includes = new0(bt_gatt_included_service_t, includes_count);
+ if (!includes)
+ goto failed;
+
+ util_debug(client->debug_callback, client->debug_data,
+ "Included services found: %u",
+ includes_count);
+
+ for (i = 0; i < includes_count; i++) {
+ if (!bt_gatt_iter_next_included_service(&iter,
+ &includes[i].handle,
+ &includes[i].start_handle,
+ &includes[i].end_handle,
+ includes[i].uuid))
+ break;
+
+ uuid_to_string(includes[i].uuid, uuid_str);
+ util_debug(client->debug_callback, client->debug_data,
+ "handle: 0x%04x, start: 0x%04x, end: 0x%04x,"
+ "uuid: %s", includes[i].handle,
+ includes[i].start_handle,
+ includes[i].end_handle, uuid_str);
+ }
+
+ op->cur_service->includes = includes;
+ op->cur_service->num_includes = includes_count;
+
+next:
+ if (!op->cur_service->next) {
+ op->cur_service = op->result_head;
+ if (bt_gatt_discover_characteristics(client->att,
+ op->cur_service->service.start_handle,
+ op->cur_service->service.end_handle,
+ discover_chrcs_cb,
+ discovery_op_ref(op),
+ discovery_op_unref))
+ return;
+
+ util_debug(client->debug_callback, client->debug_data,
+ "Failed to start characteristic discovery");
+ discovery_op_unref(op);
+ goto failed;
+ }
+
+ op->cur_service = op->cur_service->next;
+ if (bt_gatt_discover_included_services(client->att,
+ op->cur_service->service.start_handle,
+ op->cur_service->service.end_handle,
+ discover_incl_cb,
+ discovery_op_ref(op),
+ discovery_op_unref))
+ return;
+
+ util_debug(client->debug_callback, client->debug_data,
+ "Failed to start included discovery");
+ discovery_op_unref(op);
+
+failed:
+ op->complete_func(op, false, att_ecode);
+}
+
static void discover_descs_cb(bool success, uint8_t att_ecode,
struct bt_gatt_result *result,
void *user_data)
@@ -532,6 +629,7 @@ done:
op->complete_func(op, success, att_ecode);
}
+
static void discover_chrcs_cb(bool success, uint8_t att_ecode,
struct bt_gatt_result *result,
void *user_data)
@@ -703,18 +801,18 @@ static void discover_secondary_cb(bool success, uint8_t att_ecode,
}
next:
- /* Sequentially discover the characteristics of all services */
+ /* Sequentially discover included services */
op->cur_service = op->result_head;
- if (bt_gatt_discover_characteristics(client->att,
+ if (bt_gatt_discover_included_services(client->att,
op->cur_service->service.start_handle,
op->cur_service->service.end_handle,
- discover_chrcs_cb,
+ discover_incl_cb,
discovery_op_ref(op),
discovery_op_unref))
return;
util_debug(client->debug_callback, client->debug_data,
- "Failed to start characteristic discovery");
+ "Failed to start included services discovery");
discovery_op_unref(op);
success = false;
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index 22d4dc0..05b4838 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -96,6 +96,13 @@ typedef struct {
size_t num_descs;
} bt_gatt_characteristic_t;
+typedef struct {
+ uint16_t handle;
+ uint16_t start_handle;
+ uint16_t end_handle;
+ uint8_t uuid[BT_GATT_UUID_SIZE];
+} bt_gatt_included_service_t;
+
struct bt_gatt_service_iter {
struct bt_gatt_client *client;
void *ptr;
--
1.9.3
^ permalink raw reply related
* [PATCHv6 10/14] shared/gatt: Discover secondary services
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
Add searching of secondary services in gatt-client.
---
src/shared/gatt-client.c | 117 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 104 insertions(+), 13 deletions(-)
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 724fde2..e04724c 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -200,23 +200,36 @@ static void mark_notify_data_invalid_if_in_range(void *data, void *user_data)
notify_data->invalid = true;
}
-static bool service_list_add_service(struct service_list **head,
- struct service_list **tail,
- bool primary, uint16_t start,
- uint16_t end,
+static struct service_list *new_service_list(uint16_t start, uint16_t end,
+ bool primary,
uint8_t uuid[BT_GATT_UUID_SIZE])
{
struct service_list *list;
list = new0(struct service_list, 1);
if (!list)
- return false;
+ return NULL;
list->service.primary = primary;
list->service.start_handle = start;
list->service.end_handle = end;
memcpy(list->service.uuid, uuid, UUID_BYTES);
+ return list;
+}
+
+static bool service_list_add_service(struct service_list **head,
+ struct service_list **tail,
+ bool primary, uint16_t start,
+ uint16_t end,
+ uint8_t uuid[BT_GATT_UUID_SIZE])
+{
+ struct service_list *list;
+
+ list = new_service_list(start, end, primary, uuid);
+ if (!list)
+ return false;
+
if (!(*head))
*head = *tail = list;
else {
@@ -364,6 +377,8 @@ struct discovery_op {
struct bt_gatt_client *client;
struct service_list *result_head, *result_tail, *cur_service;
struct chrc_data *cur_chrc;
+ uint16_t start;
+ uint16_t end;
int cur_chrc_index;
int ref_count;
void (*complete_func)(struct discovery_op *op, bool success,
@@ -634,6 +649,79 @@ done:
op->complete_func(op, success, att_ecode);
}
+static void discover_secondary_cb(bool success, uint8_t att_ecode,
+ struct bt_gatt_result *result,
+ void *user_data)
+{
+ struct discovery_op *op = user_data;
+ struct bt_gatt_client *client = op->client;
+ struct bt_gatt_iter iter;
+ uint16_t start, end;
+ uint8_t uuid[BT_GATT_UUID_SIZE];
+ char uuid_str[MAX_LEN_UUID_STR];
+ struct service_list *service;
+
+ if (!success) {
+ util_debug(client->debug_callback, client->debug_data,
+ "Secondary service discovery failed."
+ " ATT ECODE: 0x%02x", att_ecode);
+ switch (att_ecode) {
+ case BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND:
+ case BT_ATT_ERROR_UNSUPPORTED_GROUP_TYPE:
+ goto next;
+ default:
+ goto done;
+ }
+ }
+
+ if (!result || !bt_gatt_iter_init(&iter, result)) {
+ success = false;
+ goto done;
+ }
+
+ util_debug(client->debug_callback, client->debug_data,
+ "Secondary services found: %u",
+ bt_gatt_result_service_count(result));
+
+ while (bt_gatt_iter_next_service(&iter, &start, &end, uuid)) {
+ uuid_to_string(uuid, uuid_str);
+ util_debug(client->debug_callback, client->debug_data,
+ "start: 0x%04x, end: 0x%04x, uuid: %s",
+ start, end, uuid_str);
+
+ /* Store the service */
+ service = new_service_list(start, end, false, uuid);
+ if (!service) {
+ util_debug(client->debug_callback, client->debug_data,
+ "Failed to create service");
+ success = false;
+ goto done;
+ }
+
+ service_list_insert_services(&op->result_head, &op->result_tail,
+ service, service);
+ }
+
+next:
+ /* Sequentially discover the characteristics of all services */
+ op->cur_service = op->result_head;
+ if (bt_gatt_discover_characteristics(client->att,
+ op->cur_service->service.start_handle,
+ op->cur_service->service.end_handle,
+ discover_chrcs_cb,
+ discovery_op_ref(op),
+ discovery_op_unref))
+ return;
+
+ util_debug(client->debug_callback, client->debug_data,
+ "Failed to start characteristic discovery");
+ discovery_op_unref(op);
+ success = false;
+
+done:
+ op->complete_func(op, success, att_ecode);
+}
+
static void discover_primary_cb(bool success, uint8_t att_ecode,
struct bt_gatt_result *result,
void *user_data)
@@ -686,18 +774,17 @@ static void discover_primary_cb(bool success, uint8_t att_ecode,
if (!op->result_head)
goto done;
- /* Sequentially discover the characteristics of all services */
+ /* Discover secondary services */
op->cur_service = op->result_head;
- if (bt_gatt_discover_characteristics(client->att,
- op->cur_service->service.start_handle,
- op->cur_service->service.end_handle,
- discover_chrcs_cb,
- discovery_op_ref(op),
- discovery_op_unref))
+ if (bt_gatt_discover_secondary_services(client->att, NULL,
+ op->start, op->end,
+ discover_secondary_cb,
+ discovery_op_ref(op),
+ discovery_op_unref))
return;
util_debug(client->debug_callback, client->debug_data,
- "Failed to start characteristic discovery");
+ "Failed to start secondary service discovery");
discovery_op_unref(op);
success = false;
@@ -870,6 +957,8 @@ static void process_service_changed(struct bt_gatt_client *client,
op->client = client;
op->complete_func = service_changed_complete;
+ op->start = start_handle;
+ op->end = end_handle;
if (!bt_gatt_discover_primary_services(client->att, NULL,
start_handle, end_handle,
@@ -1002,6 +1091,8 @@ static bool gatt_client_init(struct bt_gatt_client *client, uint16_t mtu)
op->client = client;
op->complete_func = init_complete;
+ op->start = 0x0001;
+ op->end = 0xffff;
/* Configure the MTU */
if (!bt_gatt_exchange_mtu(client->att, MAX(BT_ATT_DEFAULT_LE_MTU, mtu),
--
1.9.3
^ permalink raw reply related
* [PATCHv6 09/14] tools/btgatt-client: Print type of service
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
---
tools/btgatt-client.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c
index d900e08..d21bc34 100644
--- a/tools/btgatt-client.c
+++ b/tools/btgatt-client.c
@@ -183,8 +183,9 @@ static void print_service(const bt_gatt_service_t *service)
}
printf(COLOR_RED "service" COLOR_OFF " - start: 0x%04x, "
- "end: 0x%04x, uuid: ",
- service->start_handle, service->end_handle);
+ "end: 0x%04x, type: %s, uuid: ",
+ service->start_handle, service->end_handle,
+ service->primary ? "primary" : "secondary");
print_uuid(service->uuid);
while (bt_gatt_characteristic_iter_next(&iter, &chrc)) {
--
1.9.3
^ permalink raw reply related
* [PATCHv6 08/14] shared/gatt: Distinguish Primary from Secondary services
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
Add flag primary to distinguish service as primary or secondary.
---
src/shared/gatt-client.c | 7 +++++--
src/shared/gatt-client.h | 1 +
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 03d722f..724fde2 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -202,7 +202,8 @@ static void mark_notify_data_invalid_if_in_range(void *data, void *user_data)
static bool service_list_add_service(struct service_list **head,
struct service_list **tail,
- uint16_t start, uint16_t end,
+ bool primary, uint16_t start,
+ uint16_t end,
uint8_t uuid[BT_GATT_UUID_SIZE])
{
struct service_list *list;
@@ -211,6 +212,7 @@ static bool service_list_add_service(struct service_list **head,
if (!list)
return false;
+ list->service.primary = primary;
list->service.start_handle = start;
list->service.end_handle = end;
memcpy(list->service.uuid, uuid, UUID_BYTES);
@@ -668,7 +670,8 @@ static void discover_primary_cb(bool success, uint8_t att_ecode,
/* Store the service */
if (!service_list_add_service(&op->result_head,
- &op->result_tail, start, end, uuid)) {
+ &op->result_tail, true, start, end,
+ uuid)) {
util_debug(client->debug_callback, client->debug_data,
"Failed to store service");
success = false;
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index 6807f6b..22d4dc0 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -75,6 +75,7 @@ bool bt_gatt_client_set_debug(struct bt_gatt_client *client,
bt_gatt_client_destroy_func_t destroy);
typedef struct {
+ bool primary;
uint16_t start_handle;
uint16_t end_handle;
uint8_t uuid[BT_GATT_UUID_SIZE];
--
1.9.3
^ permalink raw reply related
* [PATCHv6 07/14] shared/gatt: Remove not needed function parameter
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
According to SPEC 4.1 4.5.1 "Find Included Services" there is no need
to pass UUID to discover_included_services() function.
---
src/shared/gatt-helpers.c | 1 -
src/shared/gatt-helpers.h | 1 -
2 files changed, 2 deletions(-)
diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index f993243..d751d5a 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -1067,7 +1067,6 @@ failed:
bool bt_gatt_discover_included_services(struct bt_att *att,
uint16_t start, uint16_t end,
- bt_uuid_t *uuid,
bt_gatt_discovery_callback_t callback,
void *user_data,
bt_gatt_destroy_func_t destroy)
diff --git a/src/shared/gatt-helpers.h b/src/shared/gatt-helpers.h
index df003ac..07c145d 100644
--- a/src/shared/gatt-helpers.h
+++ b/src/shared/gatt-helpers.h
@@ -83,7 +83,6 @@ bool bt_gatt_discover_secondary_services(struct bt_att *att, bt_uuid_t *uuid,
bt_gatt_destroy_func_t destroy);
bool bt_gatt_discover_included_services(struct bt_att *att,
uint16_t start, uint16_t end,
- bt_uuid_t *uuid,
bt_gatt_discovery_callback_t callback,
void *user_data,
bt_gatt_destroy_func_t destroy);
--
1.9.3
^ permalink raw reply related
* [PATCHv6 06/14] shared/gatt: Add function bt_gatt_result_included_count()
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
It will return number of included services in result.
---
src/shared/gatt-helpers.c | 28 ++++++++++++++++++++++++++++
src/shared/gatt-helpers.h | 1 +
2 files changed, 29 insertions(+)
diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 1516e79..f993243 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -147,6 +147,34 @@ unsigned int bt_gatt_result_descriptor_count(struct bt_gatt_result *result)
return result_element_count(result);
}
+unsigned int bt_gatt_result_included_count(struct bt_gatt_result *result)
+{
+ struct bt_gatt_result *cur;
+ unsigned int count = 0;
+
+ if (!result)
+ return 0;
+
+ if (result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
+ return 0;
+
+ /*
+ * Data length can be of length 6 or 8 octets:
+ * 2 octets - include service handle
+ * 2 octets - start handle of included service
+ * 2 octets - end handle of included service
+ * 2 octets (optionally) - 16 bit Bluetooth UUID
+ */
+ if (result->data_len != 6 && result->data_len != 8)
+ return 0;
+
+ for (cur = result; cur; cur = cur->next)
+ if (cur->opcode == BT_ATT_OP_READ_BY_TYPE_RSP)
+ count += cur->pdu_len / cur->data_len;
+
+ return count;
+}
+
bool bt_gatt_iter_init(struct bt_gatt_iter *iter, struct bt_gatt_result *result)
{
if (!iter || !result)
diff --git a/src/shared/gatt-helpers.h b/src/shared/gatt-helpers.h
index 8c434c1..df003ac 100644
--- a/src/shared/gatt-helpers.h
+++ b/src/shared/gatt-helpers.h
@@ -38,6 +38,7 @@ struct bt_gatt_iter {
unsigned int bt_gatt_result_service_count(struct bt_gatt_result *result);
unsigned int bt_gatt_result_characteristic_count(struct bt_gatt_result *result);
unsigned int bt_gatt_result_descriptor_count(struct bt_gatt_result *result);
+unsigned int bt_gatt_result_included_count(struct bt_gatt_result *result);
bool bt_gatt_iter_init(struct bt_gatt_iter *iter, struct bt_gatt_result *result);
bool bt_gatt_iter_next_service(struct bt_gatt_iter *iter,
--
1.9.3
^ permalink raw reply related
* [PATCHv6 05/14] shared/gatt: Add included service iterator
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
It will fetch included services from result.
---
src/shared/gatt-helpers.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++
src/shared/gatt-helpers.h | 3 ++
2 files changed, 77 insertions(+)
diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 0dbd999..1516e79 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -193,6 +193,80 @@ struct discovery_op {
bt_gatt_destroy_func_t destroy;
};
+bool bt_gatt_iter_next_included_service(struct bt_gatt_iter *iter,
+ uint16_t *handle, uint16_t *start_handle,
+ uint16_t *end_handle, uint8_t uuid[16])
+{
+ struct bt_gatt_result *read_result;
+ const void *pdu_ptr;
+ int i = 0;
+
+ if (!iter || !iter->result || !handle || !start_handle || !end_handle
+ || !uuid)
+ return false;
+
+ if (iter->result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
+ return false;
+
+ /*
+ * iter->result points to READ_BY_TYPE_RSP with data length containing:
+ * 2 octets - include service handle
+ * 2 octets - start handle of included service
+ * 2 octets - end handle of included service
+ * optional 2 octets - Bluetooth UUID
+ */
+ if (iter->result->data_len != 8 && iter->result->data_len != 6)
+ return false;
+
+ pdu_ptr = iter->result->pdu + iter->pos;
+
+ /* This result contains 16 bit UUID */
+ if (iter->result->data_len == 8) {
+ *handle = get_le16(pdu_ptr);
+ *start_handle = get_le16(pdu_ptr + 2);
+ *end_handle = get_le16(pdu_ptr + 4);
+ convert_uuid_le(pdu_ptr + 6, 2, uuid);
+
+ iter->pos += iter->result->data_len;
+
+ if (iter->pos == iter->result->pdu_len) {
+ iter->result = iter->result->next;
+ iter->pos = 0;
+ }
+
+ return true;
+ }
+
+ *handle = get_le16(pdu_ptr);
+ *start_handle = get_le16(pdu_ptr + 2);
+ *end_handle = get_le16(pdu_ptr + 4);
+ read_result = iter->result;
+
+ /*
+ * Find READ_RSP with include service UUID.
+ * If number of current data set in READ_BY_TYPE_RSP is n, then we must
+ * go to n'th PDU next to current item->result
+ */
+ for (read_result = read_result->next; read_result; i++) {
+ if (i >= (iter->pos / iter->result->data_len))
+ break;
+
+ read_result = read_result->next;
+ }
+
+ if (!read_result)
+ return false;
+
+ convert_uuid_le(read_result->pdu, read_result->data_len, uuid);
+ iter->pos += iter->result->data_len;
+ if (iter->pos == iter->result->pdu_len) {
+ iter->result = read_result->next;
+ iter->pos = 0;
+ }
+
+ return true;
+}
+
bool bt_gatt_iter_next_service(struct bt_gatt_iter *iter,
uint16_t *start_handle, uint16_t *end_handle,
uint8_t uuid[16])
diff --git a/src/shared/gatt-helpers.h b/src/shared/gatt-helpers.h
index 8a25dea..8c434c1 100644
--- a/src/shared/gatt-helpers.h
+++ b/src/shared/gatt-helpers.h
@@ -49,6 +49,9 @@ bool bt_gatt_iter_next_characteristic(struct bt_gatt_iter *iter,
uint8_t uuid[16]);
bool bt_gatt_iter_next_descriptor(struct bt_gatt_iter *iter, uint16_t *handle,
uint8_t uuid[16]);
+bool bt_gatt_iter_next_included_service(struct bt_gatt_iter *iter,
+ uint16_t *handle, uint16_t *start_handle,
+ uint16_t *end_handle, uint8_t uuid[16]);
typedef void (*bt_gatt_destroy_func_t)(void *user_data);
--
1.9.3
^ permalink raw reply related
* [PATCHv6 04/14] shared/gatt: Add extra check in characteristic iterator
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
Avoid incorrect reading of included service discovery results.
---
src/shared/gatt-helpers.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index d689c56..0dbd999 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -123,6 +123,16 @@ unsigned int bt_gatt_result_characteristic_count(struct bt_gatt_result *result)
if (result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
return 0;
+ /*
+ * Data length contains 7 or 21 octets:
+ * 2 octets: Attribute handle
+ * 1 octet: Characteristic properties
+ * 2 octets: Characteristic value handle
+ * 2 or 16 octets: characteristic UUID
+ */
+ if (result->data_len != 21 && result->data_len != 7)
+ return 0;
+
return result_element_count(result);
}
@@ -239,6 +249,16 @@ bool bt_gatt_iter_next_characteristic(struct bt_gatt_iter *iter,
if (iter->result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
return false;
+ /*
+ * Data length contains 7 or 21 octets:
+ * 2 octets: Attribute handle
+ * 1 octet: Characteristic properties
+ * 2 octets: Characteristic value handle
+ * 2 or 16 octets: characteristic UUID
+ */
+ if (iter->result->data_len != 21 && iter->result->data_len != 7)
+ return false;
+
op = iter->result->op;
pdu_ptr = iter->result->pdu + iter->pos;
--
1.9.3
^ permalink raw reply related
* [PATCHv6 03/14] shared/gatt: Discover included services 128 bit UUIDS
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
If included services has 128 bit UUID, it won't be returned in
READ_BY_TYPE_RSP. To get UUID READ_REQUEST is used.
This procedure is described in CORE SPEC 4.5.1 "Find Included Services".
---
src/shared/gatt-helpers.c | 167 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 166 insertions(+), 1 deletion(-)
diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 4cc483a..d689c56 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -692,6 +692,157 @@ bool bt_gatt_discover_secondary_services(struct bt_att *att, bt_uuid_t *uuid,
destroy, false);
}
+struct read_incl_data {
+ struct discovery_op *op;
+ struct bt_gatt_result *result;
+ int pos;
+ int ref_count;
+};
+
+static struct read_incl_data *new_read_included(struct bt_gatt_result *res)
+{
+ struct read_incl_data *data;
+
+ data = new0(struct read_incl_data, 1);
+ if (!data)
+ return NULL;
+
+ data->op = discovery_op_ref(res->op);
+ data->result = res;
+
+ return data;
+};
+
+static struct read_incl_data *read_included_ref(struct read_incl_data *data)
+{
+ __sync_fetch_and_add(&data->ref_count, 1);
+
+ return data;
+}
+
+static void read_included_unref(void *data)
+{
+ struct read_incl_data *read_data = data;
+
+ if (__sync_sub_and_fetch(&read_data->ref_count, 1))
+ return;
+
+ discovery_op_unref(read_data->op);
+
+ free(read_data);
+}
+
+static void discover_included_cb(uint8_t opcode, const void *pdu,
+ uint16_t length, void *user_data);
+
+static void read_included_cb(uint8_t opcode, const void *pdu,
+ uint16_t length, void *user_data)
+{
+ struct read_incl_data *data = user_data;
+ struct bt_gatt_result *final_result = NULL;
+ struct discovery_op *op = data->op;
+ struct bt_gatt_result *cur_result;
+ uint8_t att_ecode = 0;
+ uint8_t read_pdu[2];
+ bool success;
+
+ if (opcode == BT_ATT_OP_ERROR_RSP) {
+ success = false;
+ att_ecode = process_error(pdu, length);
+ goto done;
+ }
+
+ if (opcode != BT_ATT_OP_READ_RSP || (!pdu && length)) {
+ success = false;
+ goto done;
+ }
+
+ /*
+ * UUID should be in 128 bit format, as it couldn't be read in
+ * READ_BY_TYPE request
+ */
+ if (length != 16) {
+ success = false;
+ goto done;
+ }
+
+ cur_result = result_create(opcode, pdu, length, length, op);
+ if (!cur_result) {
+ success = false;
+ goto done;
+ }
+
+ if (!op->result_head) {
+ op->result_head = op->result_tail = cur_result;
+ } else {
+ op->result_tail->next = cur_result;
+ op->result_tail = cur_result;
+ }
+
+ if (data->pos == data->result->pdu_len) {
+ uint16_t last_handle;
+ uint8_t pdu[6];
+
+ last_handle = get_le16(data->result->pdu + data->pos -
+ data->result->data_len);
+ if (last_handle == op->end_handle) {
+ final_result = op->result_head;
+ success = true;
+ goto done;
+ }
+
+ put_le16(last_handle + 1, pdu);
+ put_le16(op->end_handle, pdu + 2);
+ put_le16(GATT_INCLUDE_UUID, pdu + 4);
+
+ if (bt_att_send(op->att, BT_ATT_OP_READ_BY_TYPE_REQ,
+ pdu, sizeof(pdu), discover_included_cb,
+ discovery_op_ref(op), discovery_op_unref))
+ return;
+
+ discovery_op_unref(op);
+ success = false;
+ goto done;
+ }
+
+ memcpy(read_pdu, data->result->pdu + data->pos + 2, sizeof(uint16_t));
+
+ data->pos += data->result->data_len;
+
+ if (bt_att_send(op->att, BT_ATT_OP_READ_REQ, read_pdu, sizeof(read_pdu),
+ read_included_cb, read_included_ref(data),
+ read_included_unref))
+ return;
+
+ read_included_unref(data);
+ success = false;
+
+done:
+ if (op->callback)
+ op->callback(success, att_ecode, final_result, op->user_data);
+}
+
+static void read_included(struct read_incl_data *data)
+{
+ struct discovery_op *op = data->op;
+ uint8_t pdu[2];
+
+ memcpy(pdu, data->result->pdu + 2, sizeof(uint16_t));
+
+ data->pos += data->result->data_len;
+
+ if (bt_att_send(op->att, BT_ATT_OP_READ_REQ, pdu, sizeof(pdu),
+ read_included_cb,
+ read_included_ref(data),
+ read_included_unref))
+ return;
+
+ read_included_unref(data);
+
+ if (op->callback)
+ op->callback(false, 0, NULL, data->op->user_data);
+}
+
static void discover_included_cb(uint8_t opcode, const void *pdu,
uint16_t length, void *user_data)
{
@@ -730,7 +881,8 @@ static void discover_included_cb(uint8_t opcode, const void *pdu,
* 2 octets - end handle of included service
* optional 2 octets - Bluetooth UUID of included service
*/
- if (data_length != 8 || (length - 1) % data_length) {
+ if ((data_length != 8 && data_length != 6) ||
+ (length - 1) % data_length) {
success = false;
goto failed;
}
@@ -749,6 +901,19 @@ static void discover_included_cb(uint8_t opcode, const void *pdu,
op->result_tail = cur_result;
}
+ if (data_length == 6) {
+ struct read_incl_data *data;
+
+ data = new_read_included(cur_result);
+ if (!data) {
+ success = false;
+ goto done;
+ }
+
+ read_included(data);
+ return;
+ }
+
last_handle = get_le16(pdu + length - data_length);
if (last_handle != op->end_handle) {
uint8_t pdu[6];
--
1.9.3
^ permalink raw reply related
* [PATCHv6 02/14] shared/gatt: Add initial implementation of discover_included_services
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
Current implementation allow to discover included services with
16 bit UUID only.
---
src/shared/gatt-helpers.c | 118 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 116 insertions(+), 2 deletions(-)
diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 4dc787f..4cc483a 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -692,6 +692,92 @@ bool bt_gatt_discover_secondary_services(struct bt_att *att, bt_uuid_t *uuid,
destroy, false);
}
+static void discover_included_cb(uint8_t opcode, const void *pdu,
+ uint16_t length, void *user_data)
+{
+ struct bt_gatt_result *final_result = NULL;
+ struct discovery_op *op = user_data;
+ struct bt_gatt_result *cur_result;
+ uint8_t att_ecode = 0;
+ uint16_t last_handle;
+ size_t data_length;
+ bool success;
+
+ if (opcode == BT_ATT_OP_ERROR_RSP) {
+ att_ecode = process_error(pdu, length);
+
+ if (att_ecode == BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND &&
+ op->result_head)
+ goto done;
+
+ success = false;
+ goto failed;
+ }
+
+ if (opcode != BT_ATT_OP_READ_BY_TYPE_RSP || !pdu || length < 6) {
+ success = false;
+ goto failed;
+ }
+
+ data_length = ((const uint8_t *) pdu)[0];
+
+ /*
+ * Check if PDU contains data sets with length declared in the beginning
+ * of frame and if this length is correct.
+ * Data set length may be 6 or 8 octets:
+ * 2 octets - include service handle
+ * 2 octets - start handle of included service
+ * 2 octets - end handle of included service
+ * optional 2 octets - Bluetooth UUID of included service
+ */
+ if (data_length != 8 || (length - 1) % data_length) {
+ success = false;
+ goto failed;
+ }
+
+ cur_result = result_create(opcode, pdu + 1, length - 1,
+ data_length, op);
+ if (!cur_result) {
+ success = false;
+ goto failed;
+ }
+
+ if (!op->result_head) {
+ op->result_head = op->result_tail = cur_result;
+ } else {
+ op->result_tail->next = cur_result;
+ op->result_tail = cur_result;
+ }
+
+ last_handle = get_le16(pdu + length - data_length);
+ if (last_handle != op->end_handle) {
+ uint8_t pdu[6];
+
+ put_le16(last_handle + 1, pdu);
+ put_le16(op->end_handle, pdu + 2);
+ put_le16(GATT_INCLUDE_UUID, pdu + 4);
+
+ if (bt_att_send(op->att, BT_ATT_OP_READ_BY_TYPE_REQ,
+ pdu, sizeof(pdu),
+ discover_included_cb,
+ discovery_op_ref(op),
+ discovery_op_unref))
+ return;
+
+ discovery_op_unref(op);
+ success = false;
+ goto failed;
+ }
+
+done:
+ success = true;
+ final_result = op->result_head;
+
+failed:
+ if (op->callback)
+ op->callback(success, att_ecode, final_result, op->user_data);
+}
+
bool bt_gatt_discover_included_services(struct bt_att *att,
uint16_t start, uint16_t end,
bt_uuid_t *uuid,
@@ -699,8 +785,36 @@ bool bt_gatt_discover_included_services(struct bt_att *att,
void *user_data,
bt_gatt_destroy_func_t destroy)
{
- /* TODO */
- return false;
+ struct discovery_op *op;
+ uint8_t pdu[6];
+
+ if (!att)
+ return false;
+
+ op = new0(struct discovery_op, 1);
+ if (!op)
+ return false;
+
+ op->att = att;
+ op->callback = callback;
+ op->user_data = user_data;
+ op->destroy = destroy;
+ op->end_handle = end;
+
+ put_le16(start, pdu);
+ put_le16(end, pdu + 2);
+ put_le16(GATT_INCLUDE_UUID, pdu + 4);
+
+ if (!bt_att_send(att, BT_ATT_OP_READ_BY_TYPE_REQ,
+ pdu, sizeof(pdu),
+ discover_included_cb,
+ discovery_op_ref(op),
+ discovery_op_unref)) {
+ free(op);
+ return false;
+ }
+
+ return true;
}
static void discover_chrcs_cb(uint8_t opcode, const void *pdu,
--
1.9.3
^ permalink raw reply related
* [PATCHv6 01/14] shared/gatt: Add discover_secondary_services()
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>
This pacth implements searching Secondary Services in given range.
---
src/shared/gatt-helpers.c | 56 +++++++++++++++++++++++++++++++++--------------
src/shared/gatt-helpers.h | 5 +++++
2 files changed, 45 insertions(+), 16 deletions(-)
diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 55e6992..4dc787f 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -175,6 +175,7 @@ struct discovery_op {
uint16_t end_handle;
int ref_count;
bt_uuid_t uuid;
+ uint16_t service_type;
struct bt_gatt_result *result_head;
struct bt_gatt_result *result_tail;
bt_gatt_discovery_callback_t callback;
@@ -487,7 +488,7 @@ static void read_by_grp_type_cb(uint8_t opcode, const void *pdu,
put_le16(last_end + 1, pdu);
put_le16(op->end_handle, pdu + 2);
- put_le16(GATT_PRIM_SVC_UUID, pdu + 4);
+ put_le16(op->service_type, pdu + 4);
if (bt_att_send(op->att, BT_ATT_OP_READ_BY_GRP_TYPE_REQ,
pdu, sizeof(pdu),
@@ -569,7 +570,7 @@ static void find_by_type_val_cb(uint8_t opcode, const void *pdu,
put_le16(last_end + 1, pdu);
put_le16(op->end_handle, pdu + 2);
- put_le16(GATT_PRIM_SVC_UUID, pdu + 4);
+ put_le16(op->service_type, pdu + 4);
put_uuid_le(&op->uuid, pdu + 6);
if (bt_att_send(op->att, BT_ATT_OP_FIND_BY_TYPE_VAL_REQ,
@@ -594,21 +595,12 @@ done:
op->callback(success, att_ecode, final_result, op->user_data);
}
-bool bt_gatt_discover_all_primary_services(struct bt_att *att, bt_uuid_t *uuid,
- bt_gatt_discovery_callback_t callback,
- void *user_data,
- bt_gatt_destroy_func_t destroy)
-{
- return bt_gatt_discover_primary_services(att, uuid, 0x0001, 0xffff,
- callback, user_data,
- destroy);
-}
-
-bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
+static bool discover_services(struct bt_att *att, bt_uuid_t *uuid,
uint16_t start, uint16_t end,
bt_gatt_discovery_callback_t callback,
void *user_data,
- bt_gatt_destroy_func_t destroy)
+ bt_gatt_destroy_func_t destroy,
+ bool primary)
{
struct discovery_op *op;
bool result;
@@ -625,6 +617,8 @@ bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
op->callback = callback;
op->user_data = user_data;
op->destroy = destroy;
+ /* set service uuid to primary or secondary */
+ op->service_type = primary ? GATT_PRIM_SVC_UUID : GATT_SND_SVC_UUID;
/* If UUID is NULL, then discover all primary services */
if (!uuid) {
@@ -632,7 +626,7 @@ bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
put_le16(start, pdu);
put_le16(end, pdu + 2);
- put_le16(GATT_PRIM_SVC_UUID, pdu + 4);
+ put_le16(op->service_type, pdu + 4);
result = bt_att_send(att, BT_ATT_OP_READ_BY_GRP_TYPE_REQ,
pdu, sizeof(pdu),
@@ -652,7 +646,7 @@ bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
put_le16(start, pdu);
put_le16(end, pdu + 2);
- put_le16(GATT_PRIM_SVC_UUID, pdu + 4);
+ put_le16(op->service_type, pdu + 4);
put_uuid_le(&op->uuid, pdu + 6);
result = bt_att_send(att, BT_ATT_OP_FIND_BY_TYPE_VAL_REQ,
@@ -668,6 +662,36 @@ bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
return result;
}
+bool bt_gatt_discover_all_primary_services(struct bt_att *att, bt_uuid_t *uuid,
+ bt_gatt_discovery_callback_t callback,
+ void *user_data,
+ bt_gatt_destroy_func_t destroy)
+{
+ return bt_gatt_discover_primary_services(att, uuid, 0x0001, 0xffff,
+ callback, user_data,
+ destroy);
+}
+
+bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
+ uint16_t start, uint16_t end,
+ bt_gatt_discovery_callback_t callback,
+ void *user_data,
+ bt_gatt_destroy_func_t destroy)
+{
+ return discover_services(att, uuid, start, end, callback, user_data,
+ destroy, true);
+}
+
+bool bt_gatt_discover_secondary_services(struct bt_att *att, bt_uuid_t *uuid,
+ uint16_t start, uint16_t end,
+ bt_gatt_discovery_callback_t callback,
+ void *user_data,
+ bt_gatt_destroy_func_t destroy)
+{
+ return discover_services(att, uuid, start, end, callback, user_data,
+ destroy, false);
+}
+
bool bt_gatt_discover_included_services(struct bt_att *att,
uint16_t start, uint16_t end,
bt_uuid_t *uuid,
diff --git a/src/shared/gatt-helpers.h b/src/shared/gatt-helpers.h
index f6f4b62..8a25dea 100644
--- a/src/shared/gatt-helpers.h
+++ b/src/shared/gatt-helpers.h
@@ -72,6 +72,11 @@ bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
bt_gatt_discovery_callback_t callback,
void *user_data,
bt_gatt_destroy_func_t destroy);
+bool bt_gatt_discover_secondary_services(struct bt_att *att, bt_uuid_t *uuid,
+ uint16_t start, uint16_t end,
+ bt_gatt_discovery_callback_t callback,
+ void *user_data,
+ bt_gatt_destroy_func_t destroy);
bool bt_gatt_discover_included_services(struct bt_att *att,
uint16_t start, uint16_t end,
bt_uuid_t *uuid,
--
1.9.3
^ permalink raw reply related
* [PATCHv6 00/14] Included service discovery
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
To: linux-bluetooth
v3:
In this version after primary service discovery,
secondary services are discovered. Next included
services are resolved. With this approach we
don't have recursively search for included service,
like it was TODO in previous proposal.
There is also small coding style fix suggested by Arman.
v4:
If no secondary services found, continue include services search (fixed
in gatt-client.c).
Fixed wrong debug logs (primary->secondary).
Fixed searching descriptors
v5:
Ignore Unsupported Group Type Error in response to secondary service
discovery and continue included services discovery.
v6
* Added comments to specific calculations and numbers.
* Fixed goto labels as suggested by Szymon
* Changed printing type of service.
* Typo fixes pointed by Szymon
Marcin Kraglak (14):
shared/gatt: Add discover_secondary_services()
shared/gatt: Add initial implementation of discover_included_services
shared/gatt: Discover included services 128 bit UUIDS
shared/gatt: Add extra check in characteristic iterator
shared/gatt: Add included service iterator
shared/gatt: Add function bt_gatt_result_included_count()
shared/gatt: Remove not needed function parameter
shared/gatt: Distinguish Primary from Secondary services
tools/btgatt-client: Print type of service
shared/gatt: Discover secondary services
shared/gatt: Discover included services
shared/gatt: Add gatt-client include service iterator
tools/btgatt-client: Print found include services
shared/gatt: Fix searching descriptors
src/shared/gatt-client.c | 252 +++++++++++++++++++++++--
src/shared/gatt-client.h | 18 ++
src/shared/gatt-helpers.c | 462 ++++++++++++++++++++++++++++++++++++++++++++--
src/shared/gatt-helpers.h | 10 +-
tools/btgatt-client.c | 20 +-
5 files changed, 725 insertions(+), 37 deletions(-)
--
1.9.3
^ permalink raw reply
* Re: [PATCH v3 bluetooth-next 0/4] 6lowpan: Move skb delivery out of IPHC
From: Martin Townsend @ 2014-10-23 9:51 UTC (permalink / raw)
To: Alexander Aring, Martin Townsend
Cc: linux-bluetooth, linux-wpan, marcel, jukka.rissanen
In-Reply-To: <20141023094355.GA11768@x61s.guest.pengutronix.de>
Hi Alex,
Looks like the SKB is now non-linear which causes the skb_put to assert. Maybe skb_linearlize will help[0]
I'll also take a look.
- Martin.
[0] http://lxr.free-electrons.com/source/include/linux/skbuff.h#L2399
On 23/10/14 10:43, Alexander Aring wrote:
> Hi Martin,
>
> On Wed, Oct 22, 2014 at 09:39:46AM +0100, Martin Townsend wrote:
>> This series moves skb delivery out of IPHC and into the receive routines of
>> both bluetooth and 802.15.4. The reason is that we need to support more
>> (de)compression schemes in the future. It also means that calling
>> lowpan_process_data now only returns error codes or 0 for success so
>> this has been cleaned up. The final patch then renames occurences of
>> lowpan_process_data and process_data to something more meaningful.
>>
> With this series and running fragmented 6LoWPAN packet on 802.15.4 a BUG()
> occurs.
>
> I can't bisect this issue and take a deeper look into this now. I have at
> weekend more time for this. Can you try a simple fragmented ping like "ping6
> $IP -s 127"? Do you get a similar issue?
>
> [ 73.250963] ------------[ cut here ]------------
> [ 73.255840] kernel BUG at net/core/skbuff.c:1275!
> [ 73.260770] Internal error: Oops - BUG: 0 [#1] ARM
> [ 73.265791] Modules linked in: autofs4
> [ 73.269753] CPU: 0 PID: 39 Comm: kworker/u2:1 Tainted: G W 3.17.0-rc1-118898-g89f5047 #5
> [ 73.279347] Workqueue: wpan-phy0 mac802154_rx_worker
> [ 73.284557] task: cf20e2c0 ti: cf2d8000 task.ti: cf2d8000
> [ 73.290223] PC is at skb_put+0x18/0x50
> [ 73.294153] LR is at 0x7fffff00
> [ 73.297448] pc : [<c041000c>] lr : [<7fffff00>] psr: 20000013
> [ 73.297448] sp : cf2d9c48 ip : cf50e71a fp : cf5aba00
> [ 73.309467] r10: cf2d9c84 r9 : cf2d9c83 r8 : cf4ab000
> [ 73.314939] r7 : 80000000 r6 : cf5aba00 r5 : cf5aba00 r4 : cf5aba00
> [ 73.321774] r3 : 00000000 r2 : c0410700 r1 : 80000000 r0 : cf5aba00
> [ 73.328612] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
> [ 73.336267] Control: 10c5387d Table: 8f408019 DAC: 00000015
> [ 73.342283] Process kworker/u2:1 (pid: 39, stack limit = 0xcf2d8240)
> [ 73.348937] Stack: (0xcf2d9c48 to 0xcf2da000)
> [ 73.353510] 9c40: 00000000 cf5aba00 cf5aba00 c0410700 cf2d9c84 cf5aba00
> [ 73.362081] 9c60: cf596bd0 cf5aba00 00000000 cf4ab000 cf5aba00 c0000dc0 cf5aba00 c058bc78
> [ 73.370651] 9c80: 0020e2c0 00000000 cf2d9c90 cf2d9ca0 abcdf303 000000f3 aaaaaaaa aaaaaaaa
> [ 73.379222] 9ca0: abcd0003 00000000 aaaaaabb aaaaaaaa cf5aba00 cf5aba00 cf4ab000 cf5aba00
> [ 73.387792] 9cc0: 00000000 0000f600 cf4ab000 c0821ba8 00000000 c058b208 00000000 c005eb18
> [ 73.396363] 9ce0: c08645fc 60000013 00000000 cf2d8000 c0f8cc61 00000002 abcd0003 00000000
> [ 73.404932] 9d00: aaaaaaaa aaaaaaaa abcd0003 00000000 aaaaaabb aaaaaaaa 00000000 00000000
> [ 73.413503] 9d20: c0865c40 cf5abb80 c0821b68 c08646e0 c08644fc cf5abb80 00000000 c041ac5c
> [ 73.422074] 9d40: 00000000 00000000 c041a86c 00000002 00000003 00000040 c0865c40 cf5abb80
> [ 73.430644] 9d60: cf20e2c0 c0864510 00000001 c0865c40 cf5abb80 00000000 c0865c14 c0865bd4
> [ 73.439215] 9d80: 00000040 c0865c40 c0865bc8 c041c1dc cf20e2c0 c0865bc0 0000012c 00000040
> [ 73.447787] 9da0: c0865bc0 c0865bc8 ffffa76e c041bb20 c086714c ffffa76e c041ba6c 00000008
> [ 73.456357] 9dc0: cf2d8020 cf2d8000 c0867140 00000100 c0867100 c086714c 00000004 c00366b0
> [ 73.464927] 9de0: cf20e2c0 cf2d8038 00000003 40000003 0000000a 04208060 00000000 ffffa76d
> [ 73.473497] 9e00: 20000013 60000013 aaaaaaaa cf5abb80 cf4ab520 cf4ab538 cf2d8030 00000001
> [ 73.482067] 9e20: 00000000 c00368a0 00000000 c041b518 00000000 c058e14c 00000000 00000000
> [ 73.490638] 9e40: c058df74 c005eb18 cf320a9c cf4ab520 cff8cc61 cf320a9c abcdf303 000000f3
> [ 73.499208] 9e60: aaaaaaaa aaaaaaaa abcd0003 00000000 aaaaaabb aaaaaaaa 00000001 cf320a9c
> [ 73.507780] 9e80: 00000000 cf5abb80 cf5abb80 cf320a60 cd9e1200 cf2d9ec8 cf03ea00 c058c7ec
> [ 73.516351] 9ea0: cf2d4d40 cd9e1204 cf036400 c0045fc4 00000001 00000000 c0045f4c 60000093
> [ 73.524921] 9ec0: 00000000 00000000 c1082b28 c0bb9980 00000000 c0765727 cf20e2c0 cf2d4d40
> [ 73.533492] 9ee0: cf036400 cf036400 c0832920 cf036430 cf2d8000 cf2d4d58 00000000 c0046b64
> [ 73.542063] 9f00: cf2d4d40 cf20e2c0 00000000 cf2d2400 00000000 cf2d4d40 c004688c 00000000
> [ 73.550633] 9f20: 00000000 00000000 00000000 c004a0a0 c0831550 00000000 cf20e2c0 cf2d4d40
> [ 73.559202] 9f40: 00000000 00000001 dead4ead ffffffff ffffffff c086769c 00000000 00000000
> [ 73.567772] 9f60: c07038f4 cf2d9f64 cf2d9f64 00000000 00000001 dead4ead ffffffff ffffffff
> [ 73.576342] 9f80: c086769c 00000000 00000000 c07038f4 cf2d9f90 cf2d9f90 cf2d9fac cf2d2400
> [ 73.584910] 9fa0: c0049fcc 00000000 00000000 c000db88 00000000 00000000 00000000 00000000
> [ 73.593479] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [ 73.602048] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 fefffbae bf3baaae
> [ 73.610626] [<c041000c>] (skb_put) from [<c0410700>] (skb_try_coalesce+0x6c/0x32c)
> [ 73.618564] [<c0410700>] (skb_try_coalesce) from [<c058bc78>] (lowpan_frag_rcv+0x668/0x7a8)
> [ 73.627318] [<c058bc78>] (lowpan_frag_rcv) from [<c058b208>] (lowpan_rcv+0xc8/0x1f0)
> [ 73.635441] [<c058b208>] (lowpan_rcv) from [<c041ac5c>] (__netif_receive_skb_core+0x43c/0x56c)
> [ 73.644470] [<c041ac5c>] (__netif_receive_skb_core) from [<c041c1dc>] (process_backlog+0x78/0x110)
> [ 73.653860] [<c041c1dc>] (process_backlog) from [<c041bb20>] (net_rx_action+0xb4/0x18c)
> [ 73.662267] [<c041bb20>] (net_rx_action) from [<c00366b0>] (__do_softirq+0x104/0x264)
> [ 73.670478] [<c00366b0>] (__do_softirq) from [<c00368a0>] (do_softirq+0x44/0x6c)
> [ 73.678233] [<c00368a0>] (do_softirq) from [<c041b518>] (netif_rx_ni+0x20/0x2c)
> [ 73.685900] [<c041b518>] (netif_rx_ni) from [<c058e14c>] (mac802154_wpans_rx+0x208/0x260)
> [ 73.694472] [<c058e14c>] (mac802154_wpans_rx) from [<c058c7ec>] (mac802154_rx_worker+0x7c/0x94)
> [ 73.703594] [<c058c7ec>] (mac802154_rx_worker) from [<c0045fc4>] (process_one_work+0x23c/0x3cc)
> [ 73.712712] [<c0045fc4>] (process_one_work) from [<c0046b64>] (worker_thread+0x2d8/0x438)
>
> - Alex
^ permalink raw reply
* Re: [PATCH v3 bluetooth-next 0/4] 6lowpan: Move skb delivery out of IPHC
From: Alexander Aring @ 2014-10-23 9:43 UTC (permalink / raw)
To: Martin Townsend
Cc: linux-bluetooth, linux-wpan, marcel, jukka.rissanen,
Martin Townsend
In-Reply-To: <1413967190-28890-1-git-send-email-martin.townsend@xsilon.com>
Hi Martin,
On Wed, Oct 22, 2014 at 09:39:46AM +0100, Martin Townsend wrote:
> This series moves skb delivery out of IPHC and into the receive routines of
> both bluetooth and 802.15.4. The reason is that we need to support more
> (de)compression schemes in the future. It also means that calling
> lowpan_process_data now only returns error codes or 0 for success so
> this has been cleaned up. The final patch then renames occurences of
> lowpan_process_data and process_data to something more meaningful.
>
With this series and running fragmented 6LoWPAN packet on 802.15.4 a BUG()
occurs.
I can't bisect this issue and take a deeper look into this now. I have at
weekend more time for this. Can you try a simple fragmented ping like "ping6
$IP -s 127"? Do you get a similar issue?
[ 73.250963] ------------[ cut here ]------------
[ 73.255840] kernel BUG at net/core/skbuff.c:1275!
[ 73.260770] Internal error: Oops - BUG: 0 [#1] ARM
[ 73.265791] Modules linked in: autofs4
[ 73.269753] CPU: 0 PID: 39 Comm: kworker/u2:1 Tainted: G W 3.17.0-rc1-118898-g89f5047 #5
[ 73.279347] Workqueue: wpan-phy0 mac802154_rx_worker
[ 73.284557] task: cf20e2c0 ti: cf2d8000 task.ti: cf2d8000
[ 73.290223] PC is at skb_put+0x18/0x50
[ 73.294153] LR is at 0x7fffff00
[ 73.297448] pc : [<c041000c>] lr : [<7fffff00>] psr: 20000013
[ 73.297448] sp : cf2d9c48 ip : cf50e71a fp : cf5aba00
[ 73.309467] r10: cf2d9c84 r9 : cf2d9c83 r8 : cf4ab000
[ 73.314939] r7 : 80000000 r6 : cf5aba00 r5 : cf5aba00 r4 : cf5aba00
[ 73.321774] r3 : 00000000 r2 : c0410700 r1 : 80000000 r0 : cf5aba00
[ 73.328612] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
[ 73.336267] Control: 10c5387d Table: 8f408019 DAC: 00000015
[ 73.342283] Process kworker/u2:1 (pid: 39, stack limit = 0xcf2d8240)
[ 73.348937] Stack: (0xcf2d9c48 to 0xcf2da000)
[ 73.353510] 9c40: 00000000 cf5aba00 cf5aba00 c0410700 cf2d9c84 cf5aba00
[ 73.362081] 9c60: cf596bd0 cf5aba00 00000000 cf4ab000 cf5aba00 c0000dc0 cf5aba00 c058bc78
[ 73.370651] 9c80: 0020e2c0 00000000 cf2d9c90 cf2d9ca0 abcdf303 000000f3 aaaaaaaa aaaaaaaa
[ 73.379222] 9ca0: abcd0003 00000000 aaaaaabb aaaaaaaa cf5aba00 cf5aba00 cf4ab000 cf5aba00
[ 73.387792] 9cc0: 00000000 0000f600 cf4ab000 c0821ba8 00000000 c058b208 00000000 c005eb18
[ 73.396363] 9ce0: c08645fc 60000013 00000000 cf2d8000 c0f8cc61 00000002 abcd0003 00000000
[ 73.404932] 9d00: aaaaaaaa aaaaaaaa abcd0003 00000000 aaaaaabb aaaaaaaa 00000000 00000000
[ 73.413503] 9d20: c0865c40 cf5abb80 c0821b68 c08646e0 c08644fc cf5abb80 00000000 c041ac5c
[ 73.422074] 9d40: 00000000 00000000 c041a86c 00000002 00000003 00000040 c0865c40 cf5abb80
[ 73.430644] 9d60: cf20e2c0 c0864510 00000001 c0865c40 cf5abb80 00000000 c0865c14 c0865bd4
[ 73.439215] 9d80: 00000040 c0865c40 c0865bc8 c041c1dc cf20e2c0 c0865bc0 0000012c 00000040
[ 73.447787] 9da0: c0865bc0 c0865bc8 ffffa76e c041bb20 c086714c ffffa76e c041ba6c 00000008
[ 73.456357] 9dc0: cf2d8020 cf2d8000 c0867140 00000100 c0867100 c086714c 00000004 c00366b0
[ 73.464927] 9de0: cf20e2c0 cf2d8038 00000003 40000003 0000000a 04208060 00000000 ffffa76d
[ 73.473497] 9e00: 20000013 60000013 aaaaaaaa cf5abb80 cf4ab520 cf4ab538 cf2d8030 00000001
[ 73.482067] 9e20: 00000000 c00368a0 00000000 c041b518 00000000 c058e14c 00000000 00000000
[ 73.490638] 9e40: c058df74 c005eb18 cf320a9c cf4ab520 cff8cc61 cf320a9c abcdf303 000000f3
[ 73.499208] 9e60: aaaaaaaa aaaaaaaa abcd0003 00000000 aaaaaabb aaaaaaaa 00000001 cf320a9c
[ 73.507780] 9e80: 00000000 cf5abb80 cf5abb80 cf320a60 cd9e1200 cf2d9ec8 cf03ea00 c058c7ec
[ 73.516351] 9ea0: cf2d4d40 cd9e1204 cf036400 c0045fc4 00000001 00000000 c0045f4c 60000093
[ 73.524921] 9ec0: 00000000 00000000 c1082b28 c0bb9980 00000000 c0765727 cf20e2c0 cf2d4d40
[ 73.533492] 9ee0: cf036400 cf036400 c0832920 cf036430 cf2d8000 cf2d4d58 00000000 c0046b64
[ 73.542063] 9f00: cf2d4d40 cf20e2c0 00000000 cf2d2400 00000000 cf2d4d40 c004688c 00000000
[ 73.550633] 9f20: 00000000 00000000 00000000 c004a0a0 c0831550 00000000 cf20e2c0 cf2d4d40
[ 73.559202] 9f40: 00000000 00000001 dead4ead ffffffff ffffffff c086769c 00000000 00000000
[ 73.567772] 9f60: c07038f4 cf2d9f64 cf2d9f64 00000000 00000001 dead4ead ffffffff ffffffff
[ 73.576342] 9f80: c086769c 00000000 00000000 c07038f4 cf2d9f90 cf2d9f90 cf2d9fac cf2d2400
[ 73.584910] 9fa0: c0049fcc 00000000 00000000 c000db88 00000000 00000000 00000000 00000000
[ 73.593479] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 73.602048] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 fefffbae bf3baaae
[ 73.610626] [<c041000c>] (skb_put) from [<c0410700>] (skb_try_coalesce+0x6c/0x32c)
[ 73.618564] [<c0410700>] (skb_try_coalesce) from [<c058bc78>] (lowpan_frag_rcv+0x668/0x7a8)
[ 73.627318] [<c058bc78>] (lowpan_frag_rcv) from [<c058b208>] (lowpan_rcv+0xc8/0x1f0)
[ 73.635441] [<c058b208>] (lowpan_rcv) from [<c041ac5c>] (__netif_receive_skb_core+0x43c/0x56c)
[ 73.644470] [<c041ac5c>] (__netif_receive_skb_core) from [<c041c1dc>] (process_backlog+0x78/0x110)
[ 73.653860] [<c041c1dc>] (process_backlog) from [<c041bb20>] (net_rx_action+0xb4/0x18c)
[ 73.662267] [<c041bb20>] (net_rx_action) from [<c00366b0>] (__do_softirq+0x104/0x264)
[ 73.670478] [<c00366b0>] (__do_softirq) from [<c00368a0>] (do_softirq+0x44/0x6c)
[ 73.678233] [<c00368a0>] (do_softirq) from [<c041b518>] (netif_rx_ni+0x20/0x2c)
[ 73.685900] [<c041b518>] (netif_rx_ni) from [<c058e14c>] (mac802154_wpans_rx+0x208/0x260)
[ 73.694472] [<c058e14c>] (mac802154_wpans_rx) from [<c058c7ec>] (mac802154_rx_worker+0x7c/0x94)
[ 73.703594] [<c058c7ec>] (mac802154_rx_worker) from [<c0045fc4>] (process_one_work+0x23c/0x3cc)
[ 73.712712] [<c0045fc4>] (process_one_work) from [<c0046b64>] (worker_thread+0x2d8/0x438)
- Alex
^ permalink raw reply
* [bluetooth] btusb issues
From: Patrick Shirkey @ 2014-10-23 8:59 UTC (permalink / raw)
To: linux-bluetooth
Hi,
I have now got backports to run with bluez instead of bluedroid and the
btusb driver instead of rtk_btusb.
However the android bluetooth system does not want to run for me.
/proc/kmsg:
<6>[ 19.428823] Loading modules backported from Linux version
next-20140905-0-g92d88cb
<6>[ 19.437576] Backport generated by backports.git
backports-20140905-0-ged7bd06
<6>[ 19.813396] Bluetooth: Core ver 2.19
<6>[ 19.818542] NET: Registered protocol family 31
<6>[ 19.823621] Bluetooth: HCI device and connection manager initialized
<6>[ 19.831138] Bluetooth: HCI socket layer initialized
<6>[ 19.837130] Bluetooth: L2CAP socket layer initialized
<6>[ 19.842883] Bluetooth: SCO socket layer initialized
<6>[ 19.948096] usbcore: registered new interface driver btusb
<4>[ 19.955936] [rfkill]: rfkill set power 1
<4>[ 19.975853] [rtl8723au]: rtl8723au is powered down by bt
logcat:
D/BluetoothManagerService( 1613): Message: 201
D/BluetoothManagerService( 1613): MESSAGE_SAVE_NAME_AND_ADDRESS
D/BluetoothAdapterState( 2109): CURRENT_STATE=OFF, MESSAGE = USER_TURN_ON
D/BluetoothAdapterProperties( 2109): Setting state to 11
I/BluetoothAdapterState( 2109): Bluetooth adapter state changed: 10-> 11
D/BluetoothAdapterService( 2109): Broadcasting updateAdapterState() to 0
receivers.
D/BluetoothBondStateMachine( 2109): make
I/BluetoothAdapterState( 2109): Entering PendingCommandState State:
isTurningOn()=true, isTurningOff()=false
D/BluetoothAdapterState( 2109): CURRENT_STATE=PENDING, MESSAGE = STARTED,
isTurningOn=true, isTurningOff=false
E/BluetoothAdapterState( 2109): Error while turning Bluetooth On
D/BluetoothAdapterProperties( 2109): Setting state to 10
I/BluetoothAdapterState( 2109): Bluetooth adapter state changed: 11-> 10
D/BluetoothAdapterService( 2109): Broadcasting updateAdapterState() to 0
receivers.
I/BluetoothAdapterState( 2109): Entering OffState
I/BluetoothBondStateMachine( 2109): StableState(): Entering Off State
Start bluetooth with UI:
D/BluetoothManagerService( 1613): enable(): mBluetooth =null mBinding =
false
D/BluetoothManagerService( 1613): Message: 1
D/BluetoothManagerService( 1613): MESSAGE_ENABLE: mBluetooth = null
D/BluetoothAdapterService( 2109): REFCOUNT: CREATED. INSTANCE_COUNT2
D/BluetoothAdapterState( 2109): make
I/BluetoothAdapterState( 2109): Entering OffState
D/BluetoothManagerService( 1613): BluetoothServiceConnection:
com.android.bluetooth.btservice.AdapterService
D/BluetoothManagerService( 1613): Message: 40
D/BluetoothManagerService( 1613): MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 1
E/BluetoothManagerService( 1613): IBluetooth.configHciSnoopLog return false
D/BluetoothManagerService( 1613): Calling onBluetoothServiceUp callbacks
D/BluetoothManagerService( 1613): Broadcasting onBluetoothServiceUp() to 4
receivers.
D/BluetoothAdapterState( 2109): CURRENT_STATE=OFF, MESSAGE = USER_TURN_ON
D/BluetoothAdapterProperties( 2109): Setting state to 11
I/BluetoothAdapterState( 2109): Bluetooth adapter state changed: 10-> 11
D/BluetoothAdapterService( 2109): Broadcasting updateAdapterState() to 1
receivers.
D/BluetoothManagerService( 1613): Message: 60
D/BluetoothManagerService( 1613): MESSAGE_BLUETOOTH_STATE_CHANGE:
prevState = 10, newState=11
D/BluetoothManagerService( 1613): Bluetooth State Change Intent: 10 -> 11
D/BluetoothBondStateMachine( 2109): make
D/BluetoothMapService( 2109): onReceive
D/HeadsetService( 2109): Received start request. Starting profile...
D/HeadsetStateMachine( 2109): make
I/BluetoothAdapterState( 2109): Entering PendingCommandState State:
isTurningOn()=true, isTurningOff()=false
I/BluetoothBondStateMachine( 2109): StableState(): Entering Off State
E/HeadsetStateMachine( 2109): Could not bind to Bluetooth Headset Phone
Service
E/BluetoothHeadsetServiceJni( 2109): Bluetooth module is not loaded
D/A2dpService( 2109): Received start request. Starting profile...
D/A2dpStateMachine( 2109): make
E/BluetoothA2dpServiceJni( 2109): Bluetooth module is not loaded
V/Avrcp ( 2109): make
E/BluetoothAvrcpServiceJni( 2109): Bluetooth module is not loaded
D/A2dpStateMachine( 2109): Enter Disconnected: -2
D/HidService( 2109): Received start request. Starting profile...
E/BluetoothHidServiceJni( 2109): Bluetooth module is not loaded
D/HealthService( 2109): Received start request. Starting profile...
E/BluetoothHealthServiceJni( 2109): Bluetooth module is not loaded
D/PanService( 2109): Received start request. Starting profile...
D/BluetoothPanServiceJni( 2109): initializeNative(L110): pan
E/BluetoothPanServiceJni( 2109): ## ERROR : initializeNative(L115):
Bluetooth module is not loaded##
D/BtGatt.DebugUtils( 2109): handleDebugAction() action=null
D/BtGatt.GattService( 2109): Received start request. Starting profile...
D/BtGatt.GattService( 2109): start()
E/BtGatt.JNI( 2109): ERROR: initializeNative(L695): Bluetooth module is
not loaded##
D/BluetoothMapService( 2109): Received start request. Starting profile...
D/BluetoothMapService( 2109): start()
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.hdp.HealthService
D/HeadsetPhoneState( 2109): sendDeviceStateChanged. mService=0 mSignal=0
mRoam=0 mBatteryCharge=5
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.hdp.HealthService
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.hdp.HealthService
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.map.BluetoothMapService
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.map.BluetoothMapService
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.map.BluetoothMapService
D/BluetoothAdapterState( 2109): CURRENT_STATE=PENDING, MESSAGE = STARTED,
isTurningOn=true, isTurningOff=false
E/BluetoothAdapterState( 2109): Error while turning Bluetooth On
D/BluetoothAdapterProperties( 2109): Setting state to 10
I/BluetoothAdapterState( 2109): Bluetooth adapter state changed: 11-> 10
D/BluetoothAdapterService( 2109): Broadcasting updateAdapterState() to 1
receivers.
D/BluetoothManagerService( 1613): Message: 60
D/BluetoothManagerService( 1613): MESSAGE_BLUETOOTH_STATE_CHANGE:
prevState = 11, newState=10
D/BluetoothManagerService( 1613): Broadcasting
onBluetoothStateChange(false) to 6 receivers.
I/BluetoothAdapterState( 2109): Entering OffState
D/BluetoothMap( 1837): onBluetoothStateChange: up=false
D/BluetoothInputDevice( 1837): onBluetoothStateChange: up=false
D/BluetoothHeadset( 1613): onBluetoothStateChange: up=false
D/BluetoothA2dp( 1613): onBluetoothStateChange: up=false
D/BluetoothPbap( 1837): onBluetoothStateChange: up=false
D/BluetoothManagerService( 1613): Bluetooth State Change Intent: 11 -> 10
D/BluetoothMapService( 2109): onReceive
E/BluetoothManagerService( 1613): recoverBluetoothServiceFromError
W/ContextImpl( 1837): Calling a method in the system process without a
qualified user: android.app.ContextImpl.startService:1479
android.content.ContextWrapper.startService:494
android.content.ContextWrapper.startService:494
com.android.settings.bluetooth.DockEventReceiver.beginStartingService:134
com.android.settings.bluetooth.DockEventReceiver.onReceive:115
D/DockEventReceiver( 1837): finishStartingService: stopping service
D/BluetoothManagerService( 1613): Sending off request.
D/BluetoothAdapterState( 2109): CURRENT_STATE=OFF, MESSAGE = USER_TURN_OFF
D/BluetoothManagerService( 1613): Calling onBluetoothServiceDown callbacks
D/BluetoothManagerService( 1613): Broadcasting onBluetoothServiceDown() to
4 receivers.
D/BluetoothAdapterService( 2109): Cleaning up adapter native....
D/BluetoothAdapterService( 2109): Done cleaning up adapter native....
D/BluetoothAdapterService(1102208296)( 2109): ****onDestroy()********
D/BluetoothManagerService( 1613): Message: 42
D/BluetoothManagerService( 1613): MESSAGE_RESTART_BLUETOOTH_SERVICE:
Restart IBluetooth service
D/BluetoothAdapterService( 2109): REFCOUNT: CREATED. INSTANCE_COUNT3
D/BluetoothAdapterState( 2109): make
D/BluetoothManagerService( 1613): BluetoothServiceConnection:
com.android.bluetooth.btservice.AdapterService
D/BluetoothManagerService( 1613): Message: 40
D/BluetoothManagerService( 1613): MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 1
E/BluetoothManagerService( 1613): IBluetooth.configHciSnoopLog return false
D/BluetoothManagerService( 1613): Calling onBluetoothServiceUp callbacks
I/BluetoothAdapterState( 2109): Entering OffState
D/BluetoothManagerService( 1613): Broadcasting onBluetoothServiceUp() to 4
receivers.
D/BluetoothAdapterState( 2109): CURRENT_STATE=OFF, MESSAGE = USER_TURN_ON
D/BluetoothAdapterProperties( 2109): Setting state to 11
I/BluetoothAdapterState( 2109): Bluetooth adapter state changed: 10-> 11
D/BluetoothAdapterService( 2109): Broadcasting updateAdapterState() to 1
receivers.
D/BluetoothBondStateMachine( 2109): make
D/BluetoothManagerService( 1613): Message: 60
D/BluetoothManagerService( 1613): MESSAGE_BLUETOOTH_STATE_CHANGE:
prevState = 10, newState=11
D/BluetoothManagerService( 1613): Bluetooth State Change Intent: 10 -> 11
D/BluetoothMapService( 2109): onReceive
D/HeadsetService( 2109): Received start request. Starting profile...
D/HeadsetStateMachine( 2109): make
I/BluetoothBondStateMachine( 2109): StableState(): Entering Off State
I/BluetoothAdapterState( 2109): Entering PendingCommandState State:
isTurningOn()=true, isTurningOff()=false
E/HeadsetStateMachine( 2109): Could not bind to Bluetooth Headset Phone
Service
E/BluetoothHeadsetServiceJni( 2109): Bluetooth module is not loaded
D/A2dpService( 2109): Received start request. Starting profile...
D/A2dpStateMachine( 2109): make
E/BluetoothA2dpServiceJni( 2109): Bluetooth module is not loaded
V/Avrcp ( 2109): make
E/BluetoothAvrcpServiceJni( 2109): Bluetooth module is not loaded
D/A2dpStateMachine( 2109): Enter Disconnected: -2
D/HidService( 2109): Received start request. Starting profile...
E/BluetoothHidServiceJni( 2109): Bluetooth module is not loaded
D/HealthService( 2109): Received start request. Starting profile...
E/BluetoothHealthServiceJni( 2109): Bluetooth module is not loaded
D/PanService( 2109): Received start request. Starting profile...
D/BluetoothPanServiceJni( 2109): initializeNative(L110): pan
E/BluetoothPanServiceJni( 2109): ## ERROR : initializeNative(L115):
Bluetooth module is not loaded##
D/BtGatt.DebugUtils( 2109): handleDebugAction() action=null
D/BtGatt.GattService( 2109): Received start request. Starting profile...
D/BtGatt.GattService( 2109): start()
E/BtGatt.JNI( 2109): ERROR: initializeNative(L695): Bluetooth module is
not loaded##
D/BluetoothMapService( 2109): Received start request. Starting profile...
D/BluetoothMapService( 2109): start()
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.hdp.HealthService
D/HeadsetPhoneState( 2109): sendDeviceStateChanged. mService=0 mSignal=0
mRoam=0 mBatteryCharge=5
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.hdp.HealthService
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.hdp.HealthService
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.map.BluetoothMapService
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.map.BluetoothMapService
D/BluetoothAdapterService( 2109): Profile still not
running:com.android.bluetooth.map.BluetoothMapService
D/BluetoothAdapterState( 2109): CURRENT_STATE=PENDING, MESSAGE = STARTED,
isTurningOn=true, isTurningOff=false
E/BluetoothAdapterState( 2109): Error while turning Bluetooth On
D/BluetoothAdapterProperties( 2109): Setting state to 10
I/BluetoothAdapterState( 2109): Bluetooth adapter state changed: 11-> 10
D/BluetoothAdapterService( 2109): Broadcasting updateAdapterState() to 1
receivers.
D/BluetoothManagerService( 1613): Message: 60
D/BluetoothManagerService( 1613): MESSAGE_BLUETOOTH_STATE_CHANGE:
prevState = 11, newState=10
D/BluetoothManagerService( 1613): Broadcasting
onBluetoothStateChange(false) to 6 receivers.
E/BluetoothPan( 1837):
E/BluetoothPan( 1837): java.lang.IllegalArgumentException: Service not
registered: android.bluetooth.BluetoothPan$2@41b0dd10
E/BluetoothPan( 1837): at
android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:931)
E/BluetoothPan( 1837): at
android.app.ContextImpl.unbindService(ContextImpl.java:1595)
E/BluetoothPan( 1837): at
android.content.ContextWrapper.unbindService(ContextWrapper.java:529)
E/BluetoothPan( 1837): at
android.bluetooth.BluetoothPan$1.onBluetoothStateChange(BluetoothPan.java:199)
E/BluetoothPan( 1837): at
android.bluetooth.IBluetoothStateChangeCallback$Stub.onTransact(IBluetoothStateChangeCallback.java:55)
E/BluetoothPan( 1837): at android.os.Binder.execTransact(Binder.java:404)
E/BluetoothPan( 1837): at dalvik.system.NativeStart.run(Native Method)
I/BluetoothAdapterState( 2109): Entering OffState
D/BluetoothMap( 1837): onBluetoothStateChange: up=false
E/BluetoothMap( 1837):
E/BluetoothMap( 1837): java.lang.IllegalArgumentException: Service not
registered: android.bluetooth.BluetoothMap$2@41b13478
E/BluetoothMap( 1837): at
android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:931)
E/BluetoothMap( 1837): at
android.app.ContextImpl.unbindService(ContextImpl.java:1595)
E/BluetoothMap( 1837): at
android.content.ContextWrapper.unbindService(ContextWrapper.java:529)
E/BluetoothMap( 1837): at
android.bluetooth.BluetoothMap$1.onBluetoothStateChange(BluetoothMap.java:66)
E/BluetoothMap( 1837): at
android.bluetooth.IBluetoothStateChangeCallback$Stub.onTransact(IBluetoothStateChangeCallback.java:55)
E/BluetoothMap( 1837): at android.os.Binder.execTransact(Binder.java:404)
E/BluetoothMap( 1837): at dalvik.system.NativeStart.run(Native Method)
D/BluetoothInputDevice( 1837): onBluetoothStateChange: up=false
E/BluetoothInputDevice( 1837):
E/BluetoothInputDevice( 1837): java.lang.IllegalArgumentException: Service
not registered: android.bluetooth.BluetoothInputDevice$2@41b08180
E/BluetoothInputDevice( 1837): at
android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:931)
E/BluetoothInputDevice( 1837): at
android.app.ContextImpl.unbindService(ContextImpl.java:1595)
E/BluetoothInputDevice( 1837): at
android.content.ContextWrapper.unbindService(ContextWrapper.java:529)
E/BluetoothInputDevice( 1837): at
android.bluetooth.BluetoothInputDevice$1.onBluetoothStateChange(BluetoothInputDevice.java:199)
E/BluetoothInputDevice( 1837): at
android.bluetooth.IBluetoothStateChangeCallback$Stub.onTransact(IBluetoothStateChangeCallback.java:55)
E/BluetoothInputDevice( 1837): at
android.os.Binder.execTransact(Binder.java:404)
E/BluetoothInputDevice( 1837): at dalvik.system.NativeStart.run(Native
Method)
D/BluetoothHeadset( 1613): onBluetoothStateChange: up=false
E/BluetoothHeadset( 1613):
E/BluetoothHeadset( 1613): java.lang.IllegalArgumentException: Service not
registered: android.bluetooth.BluetoothHeadset$2@41e17290
E/BluetoothHeadset( 1613): at
android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:931)
E/BluetoothHeadset( 1613): at
android.app.ContextImpl.unbindService(ContextImpl.java:1595)
E/BluetoothHeadset( 1613): at
android.bluetooth.BluetoothHeadset$1.onBluetoothStateChange(BluetoothHeadset.java:239)
E/BluetoothHeadset( 1613): at
com.android.server.BluetoothManagerService.sendBluetoothStateCallback(BluetoothManagerService.java:484)
E/BluetoothHeadset( 1613): at
com.android.server.BluetoothManagerService.bluetoothStateChangeHandler(BluetoothManagerService.java:1129)
E/BluetoothHeadset( 1613): at
com.android.server.BluetoothManagerService.access$2800(BluetoothManagerService.java:47)
E/BluetoothHeadset( 1613): at
com.android.server.BluetoothManagerService$BluetoothHandler.handleMessage(BluetoothManagerService.java:864)
E/BluetoothHeadset( 1613): at
android.os.Handler.dispatchMessage(Handler.java:102)
E/BluetoothHeadset( 1613): at android.os.Looper.loop(Looper.java:137)
E/BluetoothHeadset( 1613): at
android.os.HandlerThread.run(HandlerThread.java:61)
D/BluetoothA2dp( 1613): onBluetoothStateChange: up=false
E/BluetoothA2dp( 1613):
E/BluetoothA2dp( 1613): java.lang.IllegalArgumentException: Service not
registered: android.bluetooth.BluetoothA2dp$2@41e4c018
E/BluetoothA2dp( 1613): at
android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:931)
E/BluetoothA2dp( 1613): at
android.app.ContextImpl.unbindService(ContextImpl.java:1595)
E/BluetoothA2dp( 1613): at
android.bluetooth.BluetoothA2dp$1.onBluetoothStateChange(BluetoothA2dp.java:121)
E/BluetoothA2dp( 1613): at
com.android.server.BluetoothManagerService.sendBluetoothStateCallback(BluetoothManagerService.java:484)
E/BluetoothA2dp( 1613): at
com.android.server.BluetoothManagerService.bluetoothStateChangeHandler(BluetoothManagerService.java:1129)
E/BluetoothA2dp( 1613): at
com.android.server.BluetoothManagerService.access$2800(BluetoothManagerService.java:47)
E/BluetoothA2dp( 1613): at
com.android.server.BluetoothManagerService$BluetoothHandler.handleMessage(BluetoothManagerService.java:864)
E/BluetoothA2dp( 1613): at
android.os.Handler.dispatchMessage(Handler.java:102)
E/BluetoothA2dp( 1613): at android.os.Looper.loop(Looper.java:137)
E/BluetoothA2dp( 1613): at
android.os.HandlerThread.run(HandlerThread.java:61)
D/BluetoothPbap( 1837): onBluetoothStateChange: up=false
E/BluetoothPbap( 1837):
E/BluetoothPbap( 1837): java.lang.IllegalArgumentException: Service not
registered: android.bluetooth.BluetoothPbap$2@41b18c50
E/BluetoothPbap( 1837): at
android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:931)
E/BluetoothPbap( 1837): at
android.app.ContextImpl.unbindService(ContextImpl.java:1595)
E/BluetoothPbap( 1837): at
android.content.ContextWrapper.unbindService(ContextWrapper.java:529)
E/BluetoothPbap( 1837): at
android.bluetooth.BluetoothPbap$1.onBluetoothStateChange(BluetoothPbap.java:122)
E/BluetoothPbap( 1837): at
android.bluetooth.IBluetoothStateChangeCallback$Stub.onTransact(IBluetoothStateChangeCallback.java:55)
E/BluetoothPbap( 1837): at android.os.Binder.execTransact(Binder.java:404)
E/BluetoothPbap( 1837): at dalvik.system.NativeStart.run(Native Method)
D/BluetoothManagerService( 1613): Bluetooth State Change Intent: 11 -> 10
D/BluetoothMapService( 2109): onReceive
E/BluetoothManagerService( 1613): recoverBluetoothServiceFromError
W/ContextImpl( 1837): Calling a method in the system process without a
qualified user: android.app.ContextImpl.startService:1479
android.content.ContextWrapper.startService:494
android.content.ContextWrapper.startService:494
com.android.settings.bluetooth.DockEventReceiver.beginStartingService:134
com.android.settings.bluetooth.DockEventReceiver.onReceive:115
D/DockEventReceiver( 1837): finishStartingService: stopping service
D/BluetoothManagerService( 1613): Sending off request.
D/BluetoothAdapterState( 2109): CURRENT_STATE=OFF, MESSAGE = USER_TURN_OFF
D/BluetoothManagerService( 1613): Calling onBluetoothServiceDown callbacks
D/BluetoothManagerService( 1613): Broadcasting onBluetoothServiceDown() to
4 receivers.
D/BluetoothAdapterService( 2109): Cleaning up adapter native....
D/BluetoothAdapterService( 2109): Done cleaning up adapter native....
D/BluetoothAdapterService(1102260480)( 2109): ****onDestroy()********
D/BluetoothManagerService( 1613): Message: 42
D/BluetoothManagerService( 1613): MESSAGE_RESTART_BLUETOOTH_SERVICE:
Restart IBluetooth service
D/BluetoothAdapterService( 2109): REFCOUNT: CREATED. INSTANCE_COUNT4
Testing with bluez cli tools:
# haltest
audio_hw_device_open returned -98
hw_get_module_by_class returned -2
if_bluetooth->init: BT_STATUS_FAIL
get_profile_interface(handsfree) : 0x0
get_profile_interface(a2dp) : 0x0
get_profile_interface(avrcp) : 0x0
get_profile_interface(health) : 0x0
get_profile_interface(hidhost) : 0x0
get_profile_interface(pan) : 0x0
get_profile_interface(gatt) : 0x0
get_profile_interface(socket) : 0x0
if_bluetooth->init: BT_STATUS_FAIL
if_av is NULL
if_rc is NULL
if_gatt is NULL
if_hf is NULL
if_hh is NULL
if_pan is NULL
if_hl is NULL
>
logcat output from haltest
D/BlueZ ( 2567): external/bluetooth/bluez/android/hal-audio.c:audio_open()
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-audio.c:audio_ipc_init()
E/BlueZ ( 2567): audio: Failed to bind socket: 98 (Address already in use)
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:open_bluetooth()
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:get_bluetooth_interface()
D/BlueZ ( 2567): external/bluetooth/bluez/android/hal-bluetooth.c:init()
I/bluetoothd( 2568): bluetoothd[2569]: Bluetooth daemon 5.23
I/bluetoothd( 2568): bluetoothd[2569]: Starting SDP server
I/bluetoothd( 2568): bluetoothd[2569]: Bluetooth management interface 1.7
initialized
I/bluetoothd( 2568): bluetoothd[2569]: Kernel connection control will be used
I/bluetoothd( 2568): bluetoothd[2569]: Stopping SDP server
I/bluetoothd( 2568): bluetoothd[2569]: Exit
E/BlueZ ( 2567): bluetoothd connect timeout
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:get_profile_interface()
handsfree
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:get_profile_interface()
a2dp
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:get_profile_interface()
avrcp
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:get_profile_interface()
health
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:get_profile_interface()
hidhost
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:get_profile_interface()
pan
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:get_profile_interface()
gatt
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:get_profile_interface()
socket
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:open_bluetooth()
D/BlueZ ( 2567):
external/bluetooth/bluez/android/hal-bluetooth.c:get_bluetooth_interface()
D/BlueZ ( 2567): external/bluetooth/bluez/android/hal-bluetooth.c:init()
I/bluetoothd( 2570): bluetoothd[2571]: Bluetooth daemon 5.23
I/bluetoothd( 2570): bluetoothd[2571]: Starting SDP server
I/bluetoothd( 2570): bluetoothd[2571]: Bluetooth management interface 1.7
initialized
I/bluetoothd( 2570): bluetoothd[2571]: Kernel connection control will be used
I/bluetoothd( 2570): bluetoothd[2571]: Stopping SDP server
I/bluetoothd( 2570): bluetoothd[2571]: Exit
E/BlueZ ( 2567): bluetoothd connect timeout
# l2test
l2test[2591]: Waiting for connection on psm 4113 ...
# rctest
rctest[2593]: Can't create socket: Protocol not supported (93)
# btmgmt le on
Set Low Energy for hci0 failed with status 0x11 (Invalid Index)
# btmgmt info
# btmgmt power on
Set Powered for hci0 failed with status 0x11 (Invalid Index)
--
Patrick Shirkey
Boost Hardware Ltd
^ permalink raw reply
* Re: [PATCHv5 00/14] Included service discovery
From: Luiz Augusto von Dentz @ 2014-10-23 7:55 UTC (permalink / raw)
To: Szymon Janc
Cc: Arman Uguray, Marcin Kraglak,
linux-bluetooth@vger.kernel.org development
In-Reply-To: <2326994.RrINgRSL6X@athlon>
Hi Szymon,
On Wed, Oct 22, 2014 at 9:39 PM, Szymon Janc <szymon.janc@gmail.com> wrote:
> Hi,
>
> On Wednesday 22 October 2014 08:35:05 Arman Uguray wrote:
>> Hi Luiz,
>>
>> On Wed, Oct 22, 2014 at 7:54 AM, Luiz Augusto von Dentz
>>
>> <luiz.dentz@gmail.com> wrote:
>> > Hi Marcin,
>> >
>> > On Wed, Oct 22, 2014 at 9:25 AM, Marcin Kraglak
>> >
>> > <marcin.kraglak@tieto.com> wrote:
>> >> On 16 October 2014 12:17, Marcin Kraglak <marcin.kraglak@tieto.com>
> wrote:
>> >>> v3:
>> >>> In this version after primary service discovery,
>> >>> secondary services are discovered. Next included
>> >>> services are resolved. With this approach we
>> >>> don't have recursively search for included service,
>> >>> like it was TODO in previous proposal.
>> >>> There is also small coding style fix suggested by Arman.
>> >>>
>> >>> v4:
>> >>> If no secondary services found, continue include services search (fixed
>> >>> in gatt-client.c).
>> >>> Fixed wrong debug logs (primary->secondary).
>> >>> Fixed searching descriptors
>> >>>
>> >>> v5:
>> >>> Ignore Unsupported Group Type Error in response to secondary service
>> >>> discovery and continue included services discovery.
>> >>>
>> >>> Marcin Kraglak (14):
>> >>> shared/gatt: Add discover_secondary_services()
>> >>> shared/gatt: Add initial implementation of discover_included_services
>> >>> shared/gatt: Discover included services 128 bit UUIDS
>> >>> shared/gatt: Add extra check in characteristic iterator
>> >>> shared/gatt: Add included service iterator
>> >>> shared/gatt: Remove not needed function parameter
>> >>> shared/gatt: Distinguish Primary from Secondary services
>> >>> tools/btgatt-client: Print type of service
>> >>> shared/gatt: Discover secondary services
>> >>> shared/gatt: Discover included services
>> >>> shared/gatt: Add gatt-client include service iterator
>> >>> tools/btgatt-client: Print found include services
>> >>> shared/gatt: Fix searching descriptors
>> >>> shared/gatt: Add function bt_gatt_result_included_count()
>> >>>
>> >>> src/shared/gatt-client.c | 263 +++++++++++++++++++++++++++--
>> >>> src/shared/gatt-client.h | 18 ++
>> >>> src/shared/gatt-helpers.c | 418
>> >>> +++++++++++++++++++++++++++++++++++++++++++---
>> >>> src/shared/gatt-helpers.h | 10 +-
>> >>> tools/btgatt-client.c | 17 +-
>> >>> 5 files changed, 690 insertions(+), 36 deletions(-)
>> >>>
>> >>> --
>> >>> 1.9.3
>> >
>> > Patches looks fine to me, but I would like Arman to ack before applying.
>>
>> I'm fine with the patches as they are, though I saw that Szymon has
>> left comments on some of them (I'm guessing he's a doing a pass of the
>> patch set now). I'm good with it as long as his comments are
>> addressed.
>
> I really think we should have more comments and less magic numbers there.
> Otherwise this code will be hard to maintain in long term.
Yep, we could actually start creating packed structs for PDU as it was
done for AVRCP so we could do sizeof etc, it makes the code much
easier to understand and maintain.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: Attribute security permissions and CCC descriptors in shared/gatt-server.
From: Luiz Augusto von Dentz @ 2014-10-23 7:51 UTC (permalink / raw)
To: Arman Uguray; +Cc: BlueZ development, Marcin Kraglak, Marcel Holtmann
In-Reply-To: <CAHrH25S3h=LjaXSFkJiz5X41JD9-1zNJiD1R7hQNfA3aSbO0sg@mail.gmail.com>
Hi Arman,
On Wed, Oct 22, 2014 at 11:12 PM, Arman Uguray <armansito@chromium.org> wrote:
> Hi all,
>
> I have some unresolved questions about two aspects of
> shared/gatt-server and I thought it might be better to discuss them
> before moving on with the related parts of the implementation.
>
> *** 1. Who will be responsible for Attribute Permission checks? ***
>
> These mainly come in play when the remote end wants to read or write
> the value of a characteristic/descriptor. We currently have read &
> write callbacks that get assigned by the upper-layer to a
> characteristic/descriptor definition in shared/gatt-db. Since these
> callbacks already handle the read/write it initially made sense to me
> that this is where encryption/authentication/authorization permission
> checks can be performed. I then realized that there are cases where we
> may want to perform this check before we invoke the read/write
> callback. For instance, the Prepare Write request requires attribute
> permission checks to be performed, however (in the current design) we
> wouldn't actually call the write callback until a subsequent Execute
> Write request is received.
I believe this should be handle by the db, perhaps with a dedicated
prepare function that should probably call a callback so the
implementation can really tell when a write is about to happen. The
weird thing here is that the gatt_db_add_characteristic take
permissions but never really use it for anything except in
gatt_db_get_attribute_permissions, I thought the idea would be to do
the permission checks with it or Im missing something.
> The main problem here is the fact that shared/att is designed to be
> transport agnostic: it doesn't know whether the underlying connection
> is AF_BLUETOOTH or something else, so it can't make assumptions on the
> nature of the connection to obtain security level information. We
> could add some sort of delegate callback to this end, perhaps
> something like:
Then we should probably have some functions to set and get the
security level, but Im sure it needs to be a callback as it does not
looks like it gonna change without us noticing it, then we can
automatically check with security level against the permissions
provided by the profile when registering the characteristic.
> static uint8_t my_sec_handler(void *user_data)
> {
> ....
> return sec;
> }
> ...
> bt_att_register_security_handler(att, my_sec_handler);
>
> And then bt_gatt_server can obtain the current security level like this:
>
> uint8_t sec = bt_att_get_security_level(att);
>
> where bt_att_get_security_level is implemented as:
>
> static uint8_t bt_att_get_security_level(struct bt_att *att)
> {
> if (!att || !att->security_callback)
> return 0;
>
> return att->security_callback(att->security_data);
> }
>
>
> I'm mostly thinking out loud here; would something like this make sense?
>
>
> *** 2. Is shared/gatt-server responsible for keeping track of Client
> Characteristic Configuration descriptor states for each bonded client?
> ***
>
> Currently, the descriptor read/write operations need to be handled by
> the upper layer via the read/write callbacks anyway, since the
> side-effects of a writing to a particular CCC descriptor need to be
> implemented by the related profile. In the bonding case, the
> read/write callbacks could determine what value to return and how to
> cache the value on a per-device basis without shared/gatt-db having a
> notion of "per-client CCC descriptors".
Well making gatt_db have the notion of CCC would make things a little
bit simpler for storing and reloading but it would probably force us
to rethink how the db access the values, perhaps the db could cache
CCC values per client so it could detect changes and send
notifications automatically whenever the profiles tell it values has
changed or when a write succeeds.
> Does this make sense? If so, is there a point of keeping the "bdaddr_t
> *bdaddr" arguments of gatt_db_read_t, gatt_db_write_t, gatt_db_read,
> and gatt_db_write? Note that I'm currently passing NULL to all of
> these calls for this parameter in shared/gatt-server, since bt_att
> doesn't have a notion of a BD_ADDR.
I guess this was inspired by Android, I would agree that if you
register a characteristic and set the permission properly then it does
not matter who is attempting to read/write as long as they are fulfill
the requirements it should be okay but perhaps Android have pushed the
notion of CCC up in the stack which force it to expose the remote
address. Anyway for unit test I will have to address it since that
will be using a socket pair, perhaps passing NULL is fine if we have
CCC caching but in case of Android I don't think we can do much about
it.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Attribute security permissions and CCC descriptors in shared/gatt-server.
From: Arman Uguray @ 2014-10-22 20:12 UTC (permalink / raw)
To: BlueZ development, Marcin Kraglak, Luiz Augusto von Dentz,
Marcel Holtmann
Hi all,
I have some unresolved questions about two aspects of
shared/gatt-server and I thought it might be better to discuss them
before moving on with the related parts of the implementation.
*** 1. Who will be responsible for Attribute Permission checks? ***
These mainly come in play when the remote end wants to read or write
the value of a characteristic/descriptor. We currently have read &
write callbacks that get assigned by the upper-layer to a
characteristic/descriptor definition in shared/gatt-db. Since these
callbacks already handle the read/write it initially made sense to me
that this is where encryption/authentication/authorization permission
checks can be performed. I then realized that there are cases where we
may want to perform this check before we invoke the read/write
callback. For instance, the Prepare Write request requires attribute
permission checks to be performed, however (in the current design) we
wouldn't actually call the write callback until a subsequent Execute
Write request is received.
The main problem here is the fact that shared/att is designed to be
transport agnostic: it doesn't know whether the underlying connection
is AF_BLUETOOTH or something else, so it can't make assumptions on the
nature of the connection to obtain security level information. We
could add some sort of delegate callback to this end, perhaps
something like:
static uint8_t my_sec_handler(void *user_data)
{
....
return sec;
}
...
bt_att_register_security_handler(att, my_sec_handler);
And then bt_gatt_server can obtain the current security level like this:
uint8_t sec = bt_att_get_security_level(att);
where bt_att_get_security_level is implemented as:
static uint8_t bt_att_get_security_level(struct bt_att *att)
{
if (!att || !att->security_callback)
return 0;
return att->security_callback(att->security_data);
}
I'm mostly thinking out loud here; would something like this make sense?
*** 2. Is shared/gatt-server responsible for keeping track of Client
Characteristic Configuration descriptor states for each bonded client?
***
Currently, the descriptor read/write operations need to be handled by
the upper layer via the read/write callbacks anyway, since the
side-effects of a writing to a particular CCC descriptor need to be
implemented by the related profile. In the bonding case, the
read/write callbacks could determine what value to return and how to
cache the value on a per-device basis without shared/gatt-db having a
notion of "per-client CCC descriptors".
Does this make sense? If so, is there a point of keeping the "bdaddr_t
*bdaddr" arguments of gatt_db_read_t, gatt_db_write_t, gatt_db_read,
and gatt_db_write? Note that I'm currently passing NULL to all of
these calls for this parameter in shared/gatt-server, since bt_att
doesn't have a notion of a BD_ADDR.
Thanks,
Arman
^ permalink raw reply
* Re: [PATCHv5 05/14] shared/gatt: Add included service iterator
From: Szymon Janc @ 2014-10-22 18:43 UTC (permalink / raw)
To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1413454646-23076-6-git-send-email-marcin.kraglak@tieto.com>
Hi Marcin,
On Thursday 16 October 2014 12:17:17 Marcin Kraglak wrote:
> It will fetch included services from result.
> ---
> src/shared/gatt-helpers.c | 58
> +++++++++++++++++++++++++++++++++++++++++++++++ src/shared/gatt-helpers.h |
> 3 +++
> 2 files changed, 61 insertions(+)
>
> diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
> index 58104d9..fd8d06c 100644
> --- a/src/shared/gatt-helpers.c
> +++ b/src/shared/gatt-helpers.c
> @@ -186,6 +186,64 @@ struct discovery_op {
> bt_gatt_destroy_func_t destroy;
> };
>
> +bool bt_gatt_iter_next_included_service(struct bt_gatt_iter *iter,
> + uint16_t *handle, uint16_t *start_handle,
> + uint16_t *end_handle, uint8_t uuid[16])
> +{
> + struct bt_gatt_result *read_result;
> + const void *pdu_ptr;
> + int i = 0;
> +
> + if (!iter || !iter->result || !handle || !start_handle || !end_handle
> + || !uuid)
> + return false;
> +
> + if (iter->result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
> + return false;
> +
> + if (iter->result->data_len != 8 && iter->result->data_len != 6)
> + return false;
> +
> + pdu_ptr = iter->result->pdu + iter->pos;
> +
> + if (iter->result->data_len == 8) {
> + *handle = get_le16(pdu_ptr);
> + *start_handle = get_le16(pdu_ptr + 2);
> + *end_handle = get_le16(pdu_ptr + 4);
> + convert_uuid_le(pdu_ptr + 6, 2, uuid);
> +
> + iter->pos += iter->result->data_len;
> +
> + if (iter->pos == iter->result->pdu_len) {
> + iter->result = iter->result->next;
> + iter->pos = 0;
> + }
> +
> + return true;
> + }
> +
> + *handle = get_le16(pdu_ptr);
> + *start_handle = get_le16(pdu_ptr + 2);
> + *end_handle = get_le16(pdu_ptr + 4);
> + read_result = iter->result;
> +
> + do {
> + read_result = read_result->next;
> + } while (read_result && i++ < (iter->pos / iter->result->data_len));
This loop looks quite unusual. Maybe use for and break inside?
Also please put some comment about those calculations.
> +
> + if (!read_result)
> + return false;
> +
> + convert_uuid_le(read_result->pdu, read_result->data_len, uuid);
> + iter->pos += iter->result->data_len;
> + if (iter->pos == iter->result->pdu_len) {
> + iter->result = read_result->next;
> + iter->pos = 0;
> + }
> +
> + return true;
> +}
> +
> bool bt_gatt_iter_next_service(struct bt_gatt_iter *iter,
> uint16_t *start_handle, uint16_t *end_handle,
> uint8_t uuid[16])
> diff --git a/src/shared/gatt-helpers.h b/src/shared/gatt-helpers.h
> index 8a25dea..8c434c1 100644
> --- a/src/shared/gatt-helpers.h
> +++ b/src/shared/gatt-helpers.h
> @@ -49,6 +49,9 @@ bool bt_gatt_iter_next_characteristic(struct bt_gatt_iter
> *iter, uint8_t uuid[16]);
> bool bt_gatt_iter_next_descriptor(struct bt_gatt_iter *iter, uint16_t
> *handle, uint8_t uuid[16]);
> +bool bt_gatt_iter_next_included_service(struct bt_gatt_iter *iter,
> + uint16_t *handle, uint16_t *start_handle,
> + uint16_t *end_handle, uint8_t uuid[16]);
>
> typedef void (*bt_gatt_destroy_func_t)(void *user_data);
--
Szymon K. Janc
szymon.janc@gmail.com
^ permalink raw reply
* Re: [PATCHv5 03/14] shared/gatt: Discover included services 128 bit UUIDS
From: Szymon Janc @ 2014-10-22 18:43 UTC (permalink / raw)
To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1413454646-23076-4-git-send-email-marcin.kraglak@tieto.com>
Hi Marcin,
On Thursday 16 October 2014 12:17:15 Marcin Kraglak wrote:
> If included services has 128 bit UUID, it won't be returned in
> READ_BY_TYPE_RSP. To get UUID READ_REQUEST is used.
> This procedure is described in CORE SPEC 4.5.1 "Find Included Services".
> ---
> src/shared/gatt-helpers.c | 170
> +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 169
> insertions(+), 1 deletion(-)
>
> diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
> index dcb2a2f..c18f738 100644
> --- a/src/shared/gatt-helpers.c
> +++ b/src/shared/gatt-helpers.c
> @@ -692,6 +692,160 @@ bool bt_gatt_discover_secondary_services(struct bt_att
> *att, bt_uuid_t *uuid, destroy, false);
> }
>
> +struct read_incl_data {
> + struct discovery_op *op;
> + struct bt_gatt_result *result;
> + int pos;
> + int ref_count;
> +};
> +
> +static struct read_incl_data *new_read_included(struct bt_gatt_result *res)
> +{
> + struct read_incl_data *data;
> +
> + data = new0(struct read_incl_data, 1);
> + if (!data)
> + return NULL;
> +
> + data->op = discovery_op_ref(res->op);
> + data->result = res;
> +
> + return data;
> +};
> +
> +static struct read_incl_data *read_included_ref(struct read_incl_data
> *data) +{
> + __sync_fetch_and_add(&data->ref_count, 1);
> +
> + return data;
> +}
> +
> +static void read_included_unref(void *data)
> +{
> + struct read_incl_data *read_data = data;
> +
> + if (__sync_sub_and_fetch(&read_data->ref_count, 1))
> + return;
> +
> + discovery_op_unref(read_data->op);
> +
> + free(read_data);
> +}
> +
> +static void discover_included_cb(uint8_t opcode, const void *pdu,
> + uint16_t length, void *user_data);
> +
> +static void read_included_cb(uint8_t opcode, const void *pdu,
> + uint16_t length, void *user_data)
> +{
> + struct read_incl_data *data = user_data;
> + struct bt_gatt_result *final_result = NULL;
> + struct discovery_op *op = data->op;
> + struct bt_gatt_result *cur_result;
> + uint8_t att_ecode = 0;
> + uint16_t handle;
> + uint8_t read_pdu[2];
> + bool success;
> +
> + if (opcode == BT_ATT_OP_ERROR_RSP) {
> + success = false;
> + att_ecode = process_error(pdu, length);
> + goto done;
> + }
> +
> + if (opcode != BT_ATT_OP_READ_RSP || (!pdu && length)) {
> + success = false;
> + goto done;
> + }
> +
> + if (length != 16) {
I think we should have those magic numbers defined (this is more general
comment since more code here uses magic values). It might be clear for you now
why this must be 16 but won't be in 2 months :)
> + success = false;
> + goto done;
> + }
Empty line here.
> + cur_result = result_create(opcode, pdu, length, length, op);
> + if (!cur_result) {
> + success = false;
> + goto done;
> + }
> +
> + if (!op->result_head)
> + op->result_head = op->result_tail = cur_result;
Braces on both branches.
> + else {
> + op->result_tail->next = cur_result;
> + op->result_tail = cur_result;
> + }
> +
> + if (data->pos == data->result->pdu_len) {
> + uint16_t last_handle, data_len;
> + uint8_t pdu[6];
> +
> + data_len = data->result->data_len;
> + last_handle = get_le16(data->result->pdu + data->pos -
> + data_len);
This data_len variable doesn't make code clearer.
> + if (last_handle == op->end_handle) {
> + final_result = op->result_head;
> + success = true;
> + goto done;
> + }
> +
> + put_le16(last_handle + 1, pdu);
> + put_le16(op->end_handle, pdu + 2);
> + put_le16(GATT_INCLUDE_UUID, pdu + 4);
> +
> + if (bt_att_send(op->att, BT_ATT_OP_READ_BY_TYPE_REQ,
> + pdu, sizeof(pdu),
> + discover_included_cb,
> + discovery_op_ref(op),
> + discovery_op_unref))
This should fit just in 2 lines, instead of 4.
> + return;
> +
> + discovery_op_unref(op);
> + success = false;
> + goto done;
> + }
> +
> + handle = get_le16(data->result->pdu + data->pos + 2);
> + put_le16(handle, read_pdu);
So if both are LE value why not just memcpy() here?
> +
> + data->pos += data->result->data_len;
> +
> + if (bt_att_send(op->att, BT_ATT_OP_READ_REQ, read_pdu, sizeof(read_pdu),
> + read_included_cb,
> + read_included_ref(data),
> + read_included_unref))
Ditto.
> + return;
> +
> + read_included_unref(data);
> + success = false;
> +
> +done:
> + if (op->callback)
> + op->callback(success, att_ecode, final_result, op->user_data);
> +}
> +
> +static void read_included(struct read_incl_data *data)
> +{
> + struct discovery_op *op = data->op;
> + uint16_t handle;
> + uint8_t pdu[2];
> +
> + handle = get_le16(data->result->pdu + 2);
> + put_le16(handle, pdu);
memcpy
> +
> + data->pos += data->result->data_len;
> +
> + if (bt_att_send(op->att, BT_ATT_OP_READ_REQ, pdu, sizeof(pdu),
> + read_included_cb,
> + read_included_ref(data),
> + read_included_unref))
> + return;
> +
> + read_included_unref(data);
> +
> + if (op->callback)
> + op->callback(false, 0, NULL, data->op->user_data);
> +}
> +
> static void discover_included_cb(uint8_t opcode, const void *pdu,
> uint16_t length, void *user_data)
> {
> @@ -721,7 +875,8 @@ static void discover_included_cb(uint8_t opcode, const
> void *pdu,
>
> data_length = ((uint8_t *) pdu)[0];
>
> - if ((length - 1) % data_length || data_length != 8) {
> + if (((length - 1) % data_length) ||
> + (data_length != 8 && data_length != 6)) {
> success = false;
> goto done;
> }
> @@ -740,6 +895,19 @@ static void discover_included_cb(uint8_t opcode, const
> void *pdu, op->result_tail = cur_result;
> }
>
> + if (data_length == 6) {
> + struct read_incl_data *data;
> +
> + data = new_read_included(cur_result);
> + if (!data) {
> + success = false;
> + goto done;
> + }
> +
> + read_included(data);
> + return;
> + }
> +
> last_handle = get_le16(pdu + length - data_length);
> if (last_handle != op->end_handle) {
> uint8_t pdu[6];
--
Szymon K. Janc
szymon.janc@gmail.com
^ permalink raw reply
* Re: [PATCHv5 00/14] Included service discovery
From: Szymon Janc @ 2014-10-22 18:39 UTC (permalink / raw)
To: Arman Uguray
Cc: Luiz Augusto von Dentz, Marcin Kraglak,
linux-bluetooth@vger.kernel.org development
In-Reply-To: <CAHrH25T_OGAuC2aS3FvV2ZNffv0Ep2PxxOk4+HDn7YXuvfJqbQ@mail.gmail.com>
Hi,
On Wednesday 22 October 2014 08:35:05 Arman Uguray wrote:
> Hi Luiz,
>
> On Wed, Oct 22, 2014 at 7:54 AM, Luiz Augusto von Dentz
>
> <luiz.dentz@gmail.com> wrote:
> > Hi Marcin,
> >
> > On Wed, Oct 22, 2014 at 9:25 AM, Marcin Kraglak
> >
> > <marcin.kraglak@tieto.com> wrote:
> >> On 16 October 2014 12:17, Marcin Kraglak <marcin.kraglak@tieto.com>
wrote:
> >>> v3:
> >>> In this version after primary service discovery,
> >>> secondary services are discovered. Next included
> >>> services are resolved. With this approach we
> >>> don't have recursively search for included service,
> >>> like it was TODO in previous proposal.
> >>> There is also small coding style fix suggested by Arman.
> >>>
> >>> v4:
> >>> If no secondary services found, continue include services search (fixed
> >>> in gatt-client.c).
> >>> Fixed wrong debug logs (primary->secondary).
> >>> Fixed searching descriptors
> >>>
> >>> v5:
> >>> Ignore Unsupported Group Type Error in response to secondary service
> >>> discovery and continue included services discovery.
> >>>
> >>> Marcin Kraglak (14):
> >>> shared/gatt: Add discover_secondary_services()
> >>> shared/gatt: Add initial implementation of discover_included_services
> >>> shared/gatt: Discover included services 128 bit UUIDS
> >>> shared/gatt: Add extra check in characteristic iterator
> >>> shared/gatt: Add included service iterator
> >>> shared/gatt: Remove not needed function parameter
> >>> shared/gatt: Distinguish Primary from Secondary services
> >>> tools/btgatt-client: Print type of service
> >>> shared/gatt: Discover secondary services
> >>> shared/gatt: Discover included services
> >>> shared/gatt: Add gatt-client include service iterator
> >>> tools/btgatt-client: Print found include services
> >>> shared/gatt: Fix searching descriptors
> >>> shared/gatt: Add function bt_gatt_result_included_count()
> >>>
> >>> src/shared/gatt-client.c | 263 +++++++++++++++++++++++++++--
> >>> src/shared/gatt-client.h | 18 ++
> >>> src/shared/gatt-helpers.c | 418
> >>> +++++++++++++++++++++++++++++++++++++++++++---
> >>> src/shared/gatt-helpers.h | 10 +-
> >>> tools/btgatt-client.c | 17 +-
> >>> 5 files changed, 690 insertions(+), 36 deletions(-)
> >>>
> >>> --
> >>> 1.9.3
> >
> > Patches looks fine to me, but I would like Arman to ack before applying.
>
> I'm fine with the patches as they are, though I saw that Szymon has
> left comments on some of them (I'm guessing he's a doing a pass of the
> patch set now). I'm good with it as long as his comments are
> addressed.
I really think we should have more comments and less magic numbers there.
Otherwise this code will be hard to maintain in long term.
>
> > Btw, there is one thing I would like to see addressed, right now
> > whenever we disconnect the cache is lost which doesn't use the CCC
> > ability to persist across connections, this can cause us to loose
> > notifications when reconnecting because the code don't remember any
> > handles and this is specially bad for profiles such as HoG since we
> > may loose some input events while rediscovering, in fact we should
> > probably store the cache whenever the remote supports service changed
> > and be able to reload them so we only have to do the discover again if
> > something has changed.
>
> There's an item in the top-level TODO for long-term caching of
> attributes, so I guess this falls under that?
>
> > --
> > Luiz Augusto von Dentz
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth"
> > in the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
>
> Cheers,
> -Arman
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth"
> in the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Szymon K. Janc
szymon.janc@gmail.com
^ permalink raw reply
* Re: [PATCHv5 11/14] shared/gatt: Add gatt-client include service iterator
From: Szymon Janc @ 2014-10-22 18:29 UTC (permalink / raw)
To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1413454646-23076-12-git-send-email-marcin.kraglak@tieto.com>
Hi Marcin,
On Thursday 16 October 2014 12:17:23 Marcin Kraglak wrote:
> It will allow user to take value, handle, start and end handle
> of included service.
> ---
> src/shared/gatt-client.c | 30 ++++++++++++++++++++++++++++++
> src/shared/gatt-client.h | 10 ++++++++++
> 2 files changed, 40 insertions(+)
>
> diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
> index 971788c..28865da 100644
> --- a/src/shared/gatt-client.c
> +++ b/src/shared/gatt-client.c
> @@ -1674,6 +1674,36 @@ bool bt_gatt_characteristic_iter_next(struct
> bt_gatt_characteristic_iter *iter, return true;
> }
>
> +bool bt_gatt_include_service_iter_init(struct bt_gatt_incl_service_iter
> *iter, + const bt_gatt_service_t *service)
> +{
> + if (!iter || !service)
> + return false;
> +
> + memset(iter, 0, sizeof(*iter));
> + iter->service = (struct service_list *) service;
I know that this is based on existing code but I'll comment on it here :)
This cast is really confusing. Either it should be casted to void* as service
field inside iter or service should be const in iter if we are passing const
data there. Or it should be of type service_list and named services?
This list interface is kinda hard to read and I don't really like it without
proper macros (like in kernel code)...
> +
> + return true;
> +}
> +
> +bool bt_gatt_include_service_iter_next(struct bt_gatt_incl_service_iter
> *iter, + const bt_gatt_included_service_t **incl)
> +{
> + struct service_list *service;
> +
> + if (!iter || !incl)
> + return false;
> +
> + service = iter->service;
> +
> + if (iter->pos >= service->num_includes)
> + return false;
> +
> + *incl = &service->includes[iter->pos++];
> +
> + return true;
> +}
> +
> struct read_op {
> bt_gatt_client_read_callback_t callback;
> void *user_data;
> diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
> index 05b4838..bf4e7bb 100644
> --- a/src/shared/gatt-client.h
> +++ b/src/shared/gatt-client.h
> @@ -113,6 +113,11 @@ struct bt_gatt_characteristic_iter {
> size_t pos;
> };
>
> +struct bt_gatt_incl_service_iter {
> + void *service;
> + size_t pos;
> +};
> +
> bool bt_gatt_service_iter_init(struct bt_gatt_service_iter *iter,
> struct bt_gatt_client *client);
> bool bt_gatt_service_iter_next(struct bt_gatt_service_iter *iter,
> @@ -129,6 +134,11 @@ bool bt_gatt_characteristic_iter_init(struct
> bt_gatt_characteristic_iter *iter, bool
> bt_gatt_characteristic_iter_next(struct bt_gatt_characteristic_iter *iter,
> const bt_gatt_characteristic_t **chrc);
>
> +bool bt_gatt_include_service_iter_init(struct bt_gatt_incl_service_iter
> *iter, + const bt_gatt_service_t *service);
> +bool bt_gatt_include_service_iter_next(struct bt_gatt_incl_service_iter
> *iter, + const bt_gatt_included_service_t **inc);
> +
> typedef void (*bt_gatt_client_read_callback_t)(bool success, uint8_t
> att_ecode, const uint8_t *value, uint16_t length,
> void *user_data);
--
Szymon K. Janc
szymon.janc@gmail.com
^ permalink raw reply
* Re: [PATCHv5 10/14] shared/gatt: Discover included services
From: Szymon Janc @ 2014-10-22 18:20 UTC (permalink / raw)
To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1413454646-23076-11-git-send-email-marcin.kraglak@tieto.com>
Hi Marcin,
On Thursday 16 October 2014 12:17:22 Marcin Kraglak wrote:
> ---
> src/shared/gatt-client.c | 114
> +++++++++++++++++++++++++++++++++++++++++++++-- src/shared/gatt-client.h |
> 7 +++
> 2 files changed, 117 insertions(+), 4 deletions(-)
>
> diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
> index e04724c..971788c 100644
> --- a/src/shared/gatt-client.c
> +++ b/src/shared/gatt-client.c
> @@ -69,6 +69,8 @@ struct service_list {
> bt_gatt_service_t service;
> struct chrc_data *chrcs;
> size_t num_chrcs;
> + bt_gatt_included_service_t *includes;
> + size_t num_includes;
> struct service_list *next;
> };
>
> @@ -253,6 +255,14 @@ static void service_destroy_characteristics(struct
> service_list *service) free(service->chrcs);
> }
>
> +static void service_destroy_includes(struct service_list *service)
> +{
> + free(service->includes);
> +
> + service->includes = NULL;
> + service->num_includes = 0;
> +}
> +
> static void service_list_clear(struct service_list **head,
> struct service_list **tail)
> {
> @@ -265,6 +275,7 @@ static void service_list_clear(struct service_list
> **head,
>
> while (l) {
> service_destroy_characteristics(l);
> + service_destroy_includes(l);
> tmp = l;
> l = tmp->next;
> free(tmp);
> @@ -293,6 +304,7 @@ static void service_list_clear_range(struct service_list
> **head, }
>
> service_destroy_characteristics(cur);
> + service_destroy_includes(cur);
>
> if (!prev)
> *head = cur->next;
> @@ -428,6 +440,99 @@ static int uuid_cmp(const uint8_t uuid128[16], uint16_t
> uuid16) return memcmp(uuid128, rhs_uuid, sizeof(rhs_uuid));
> }
>
> +static void discover_incl_cb(bool success, uint8_t att_ecode,
> + struct bt_gatt_result *result,
> + void *user_data)
Indentation is broken here and those likely fit in single line.
> +{
> + struct discovery_op *op = user_data;
> + struct bt_gatt_client *client = op->client;
> + struct bt_gatt_iter iter;
> + char uuid_str[MAX_LEN_UUID_STR];
> + bt_gatt_included_service_t *includes;
> + unsigned int includes_count, i;
> +
> + if (!success) {
> + if (att_ecode == BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND) {
> + success = true;
> + goto next;
> + }
> +
> + goto done;
> + }
> +
> + if (!result || !bt_gatt_iter_init(&iter, result)) {
> + success = false;
> + goto done;
> + }
> +
> + includes_count = bt_gatt_result_included_count(result);
> + if (includes_count == 0) {
> + success = false;
> + goto done;
> + }
> +
> + includes = new0(bt_gatt_included_service_t, includes_count);
> + if (!includes) {
> + success = false;
> + goto done;
> + }
> +
> + util_debug(client->debug_callback, client->debug_data,
> + "Included services found: %u",
> + includes_count);
> +
> + i = 0;
> + while (bt_gatt_iter_next_included_service(&iter, &includes[i].handle,
> + &includes[i].start_handle,
> + &includes[i].end_handle,
> + includes[i].uuid)) {
> + uuid_to_string(includes[i].uuid, uuid_str);
> + util_debug(client->debug_callback, client->debug_data,
> + "handle: 0x%04x, start: 0x%04x, end: 0x%04x,"
> + "uuid: %s", includes[i].handle,
> + includes[i].start_handle,
> + includes[i].end_handle, uuid_str);
> + i++;
> + }
I'd use for(;;) + break here. Also should we verify if this loop iterated
includes_count times?
> +
> + op->cur_service->includes = includes;
> + op->cur_service->num_includes = includes_count;
> +
> +next:
> + if (!op->cur_service->next) {
> + op->cur_service = op->result_head;
> + if (bt_gatt_discover_characteristics(client->att,
> + op->cur_service->service.start_handle,
> + op->cur_service->service.end_handle,
> + discover_chrcs_cb,
> + discovery_op_ref(op),
> + discovery_op_unref))
> + return;
> +
> + util_debug(client->debug_callback, client->debug_data,
> + "Failed to start characteristic discovery");
> + discovery_op_unref(op);
> + success = false;
> + goto done;
> + }
> +
> + op->cur_service = op->cur_service->next;
> + if (bt_gatt_discover_included_services(client->att,
> + op->cur_service->service.start_handle,
> + op->cur_service->service.end_handle,
> + discover_incl_cb,
> + discovery_op_ref(op),
> + discovery_op_unref))
> + return;
Empty line here.
> + util_debug(client->debug_callback, client->debug_data,
> + "Failed to start included discovery");
> + discovery_op_unref(op);
> + success = false;
> +
> +done:
> + op->complete_func(op, success, att_ecode);
This is always called with success == false so maybe label should be called
failed and called with hardcoded false? Or there is some codepath missing for
success case?
> +}
> +
> static void discover_descs_cb(bool success, uint8_t att_ecode,
> struct bt_gatt_result *result,
> void *user_data)
> @@ -532,6 +637,7 @@ done:
> op->complete_func(op, success, att_ecode);
> }
>
> +
> static void discover_chrcs_cb(bool success, uint8_t att_ecode,
> struct bt_gatt_result *result,
> void *user_data)
> @@ -703,18 +809,18 @@ static void discover_secondary_cb(bool success,
> uint8_t att_ecode, }
>
> next:
> - /* Sequentially discover the characteristics of all services */
> + /* Sequentially discover included services */
> op->cur_service = op->result_head;
> - if (bt_gatt_discover_characteristics(client->att,
> + if (bt_gatt_discover_included_services(client->att,
> op->cur_service->service.start_handle,
> op->cur_service->service.end_handle,
> - discover_chrcs_cb,
> + discover_incl_cb,
> discovery_op_ref(op),
> discovery_op_unref))
> return;
>
> util_debug(client->debug_callback, client->debug_data,
> - "Failed to start characteristic discovery");
> + "Failed to start included services discovery");
> discovery_op_unref(op);
> success = false;
>
> diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
> index 22d4dc0..05b4838 100644
> --- a/src/shared/gatt-client.h
> +++ b/src/shared/gatt-client.h
> @@ -96,6 +96,13 @@ typedef struct {
> size_t num_descs;
> } bt_gatt_characteristic_t;
>
> +typedef struct {
> + uint16_t handle;
> + uint16_t start_handle;
> + uint16_t end_handle;
> + uint8_t uuid[BT_GATT_UUID_SIZE];
> +} bt_gatt_included_service_t;
> +
> struct bt_gatt_service_iter {
> struct bt_gatt_client *client;
> void *ptr;
--
Szymon K. Janc
szymon.janc@gmail.com
^ permalink raw reply
* Re: [PATCHv5 08/14] tools/btgatt-client: Print type of service
From: Szymon Janc @ 2014-10-22 18:00 UTC (permalink / raw)
To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1413454646-23076-9-git-send-email-marcin.kraglak@tieto.com>
Hi Marcin,
On Thursday 16 October 2014 12:17:20 Marcin Kraglak wrote:
> ---
> tools/btgatt-client.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c
> index d900e08..5c692ff 100644
> --- a/tools/btgatt-client.c
> +++ b/tools/btgatt-client.c
> @@ -182,8 +182,9 @@ static void print_service(const bt_gatt_service_t
> *service) return;
> }
>
> - printf(COLOR_RED "service" COLOR_OFF " - start: 0x%04x, "
> + printf(COLOR_RED "service %s" COLOR_OFF " - start: 0x%04x, "
> "end: 0x%04x, uuid: ",
> + service->primary ? "primary" : "second.",
> service->start_handle, service->end_handle);
As we discussed offline, maybe having "type: foo" would be nicer instead of
"serivce second." ?
> print_uuid(service->uuid);
--
Szymon K. Janc
szymon.janc@gmail.com
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox