* [PATCH BlueZ v3 2/7] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-1 test
2015-03-19 14:21 [PATCH BlueZ v3 1/7] shared/gatt-client: Fix handling of services Luiz Augusto von Dentz
@ 2015-03-19 14:21 ` Luiz Augusto von Dentz
2015-03-19 14:21 ` [PATCH BlueZ v3 3/7] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-2 test Luiz Augusto von Dentz
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-03-19 14:21 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This is similar to TP/GAD/CL/BV-06-C but using bt_gatt_client to
discover everything.
---
unit/test-gatt.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 93ee2c7..33d4b9f 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
@@ -2269,6 +2269,10 @@ int main(int argc, char *argv[])
raw_pdu(0x05, 0x01, 0x15, 0x00, 0x04, 0x29, 0x16, 0x00,
0x05, 0x29));
+ define_test_client("/TP/GAD/CL/BV-06-C/client-1", test_client,
+ service_db_1, NULL,
+ SERVICE_DATA_1_PDUS);
+
define_test_server("/TP/GAD/SR/BV-06-C/small", test_server,
ts_small_db, NULL,
raw_pdu(0x03, 0x00, 0x02),
--
2.1.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH BlueZ v3 3/7] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-2 test
2015-03-19 14:21 [PATCH BlueZ v3 1/7] shared/gatt-client: Fix handling of services Luiz Augusto von Dentz
2015-03-19 14:21 ` [PATCH BlueZ v3 2/7] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-1 test Luiz Augusto von Dentz
@ 2015-03-19 14:21 ` Luiz Augusto von Dentz
2015-03-19 14:21 ` [PATCH BlueZ v3 4/7] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-3 test Luiz Augusto von Dentz
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-03-19 14:21 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This veryfy we the code is able to parse services with gaps between
handles.
---
unit/test-gatt.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 109 insertions(+), 15 deletions(-)
diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 33d4b9f..7bc2d25 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
@@ -149,6 +149,35 @@ struct context {
raw_pdu(0x04, 0x08, 0x00, 0x08, 0x00), \
raw_pdu(0x05, 0x01, 0x08, 0x00, 0x01, 0x29)
+#define SERVICE_DATA_2_PDUS \
+ MTU_EXCHANGE_CLIENT_PDUS, \
+ raw_pdu(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28), \
+ raw_pdu(0x11, 0x06, 0x01, 0x00, 0x04, 0x00, 0x01, 0x18),\
+ raw_pdu(0x10, 0x05, 0x00, 0xff, 0xff, 0x00, 0x28), \
+ raw_pdu(0x11, 0x06, 0x05, 0x00, 0x0a, 0x00, 0x0d, 0x18),\
+ raw_pdu(0x10, 0x0b, 0x00, 0xff, 0xff, 0x00, 0x28), \
+ raw_pdu(0x01, 0x10, 0x0b, 0x00, 0x0a), \
+ raw_pdu(0x10, 0x01, 0x00, 0xff, 0xff, 0x01, 0x28), \
+ raw_pdu(0x01, 0x10, 0x01, 0x00, 0x0a), \
+ raw_pdu(0x08, 0x01, 0x00, 0x04, 0x00, 0x02, 0x28), \
+ raw_pdu(0x01, 0x08, 0x01, 0x00, 0x0a), \
+ raw_pdu(0x08, 0x05, 0x00, 0x0a, 0x00, 0x02, 0x28), \
+ raw_pdu(0x01, 0x08, 0x05, 0x00, 0x0a), \
+ raw_pdu(0x08, 0x01, 0x00, 0x04, 0x00, 0x03, 0x28), \
+ raw_pdu(0x09, 0x07, 0x02, 0x00, 0x02, 0x03, 0x00, 0x00, \
+ 0x2a), \
+ raw_pdu(0x08, 0x03, 0x00, 0x04, 0x00, 0x03, 0x28), \
+ raw_pdu(0x01, 0x08, 0x03, 0x00, 0x0a), \
+ raw_pdu(0x04, 0x04, 0x00, 0x04, 0x00), \
+ raw_pdu(0x05, 0x01, 0x04, 0x00, 0x01, 0x29), \
+ raw_pdu(0x08, 0x05, 0x00, 0x0a, 0x00, 0x03, 0x28), \
+ raw_pdu(0x09, 0x07, 0x07, 0x00, 0x0a, 0x08, 0x00, 0x29, \
+ 0x2a), \
+ raw_pdu(0x08, 0x08, 0x00, 0x0a, 0x00, 0x03, 0x28), \
+ raw_pdu(0x01, 0x08, 0x08, 0x00, 0x0a), \
+ raw_pdu(0x04, 0x09, 0x00, 0x0a, 0x00), \
+ raw_pdu(0x05, 0x01, 0x0a, 0x00, 0x01, 0x29)
+
#define PRIMARY_DISC_SMALL_DB \
raw_pdu(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28), \
raw_pdu(0x11, 0x06, 0x10, 0xF0, 0x17, 0xF0, 0x00, 0x18, \
@@ -966,16 +995,23 @@ static void att_write_cb(struct gatt_db_attribute *att, int err,
g_assert(!err);
}
-static struct gatt_db_attribute *add_char_with_value(struct gatt_db *db,
- struct gatt_db_attribute *service_att,
- bt_uuid_t *uuid,
- uint32_t att_permissions,
- uint8_t char_properties,
- const void *value, size_t len)
+static struct gatt_db_attribute *
+add_char_with_value(struct gatt_db_attribute *service_att, uint16_t handle,
+ bt_uuid_t *uuid, uint32_t att_permissions,
+ uint8_t char_properties, const void *value,
+ size_t len)
{
struct gatt_db_attribute *attrib;
- attrib = gatt_db_service_add_characteristic(service_att, uuid,
+ if (handle)
+ attrib = gatt_db_service_insert_characteristic(service_att,
+ handle, uuid,
+ att_permissions,
+ char_properties,
+ NULL, NULL,
+ NULL);
+ else
+ attrib = gatt_db_service_add_characteristic(service_att, uuid,
att_permissions,
char_properties,
NULL, NULL,
@@ -990,14 +1026,19 @@ static struct gatt_db_attribute *add_char_with_value(struct gatt_db *db,
}
static struct gatt_db_attribute *
-add_desc_with_value(struct gatt_db_attribute *att, bt_uuid_t *uuid,
- uint32_t att_perms, const uint8_t *value,
- size_t len)
+add_desc_with_value(struct gatt_db_attribute *att, uint16_t handle,
+ bt_uuid_t *uuid, uint32_t att_perms,
+ const uint8_t *value, size_t len)
{
struct gatt_db_attribute *desc_att;
- desc_att = gatt_db_service_add_descriptor(att, uuid, att_perms, NULL,
- NULL, NULL);
+ if (handle)
+ desc_att = gatt_db_service_insert_descriptor(att, handle, uuid,
+ att_perms, NULL, NULL,
+ NULL);
+ else
+ desc_att = gatt_db_service_add_descriptor(att, uuid, att_perms,
+ NULL, NULL, NULL);
gatt_db_attribute_write(desc_att, 0, value, len, 0x00, NULL,
att_write_cb, NULL);
@@ -1124,7 +1165,7 @@ static struct gatt_db *make_db(const struct att_handle_spec *spec)
case CHARACTERISTIC:
bt_string_to_uuid(&uuid, spec->uuid);
- add_char_with_value(db, att, &uuid,
+ add_char_with_value(att, spec->handle, &uuid,
spec->att_permissions,
spec->char_properties,
spec->value, spec->len);
@@ -1134,7 +1175,8 @@ static struct gatt_db *make_db(const struct att_handle_spec *spec)
case DESCRIPTOR:
bt_string_to_uuid(&uuid, spec->uuid);
- add_desc_with_value(att, &uuid, spec->att_permissions,
+ add_desc_with_value(att, spec->handle, &uuid,
+ spec->att_permissions,
spec->value, spec->len);
break;
@@ -1168,6 +1210,52 @@ static struct gatt_db *make_service_data_1_db(void)
return make_db(specs);
}
+#define CHARACTERISTIC_STR_AT(chr_handle, chr_uuid, permissions, properties, \
+ string) \
+ { \
+ .valid = true, \
+ .handle = chr_handle, \
+ .type = CHARACTERISTIC, \
+ .uuid = STR(chr_uuid), \
+ .att_permissions = permissions, \
+ .char_properties = properties, \
+ .value = (uint8_t *)string, \
+ .len = strlen(string), \
+ }
+
+#define DESCRIPTOR_STR_AT(desc_handle, desc_uuid, permissions, string) \
+ { \
+ .valid = true, \
+ .handle = desc_handle, \
+ .type = DESCRIPTOR, \
+ .uuid = STR(desc_uuid), \
+ .att_permissions = permissions, \
+ .value = (uint8_t *)string, \
+ .len = strlen(string), \
+ }
+
+static struct gatt_db *make_service_data_2_db(void)
+{
+ const struct att_handle_spec specs[] = {
+ PRIMARY_SERVICE(0x0001, GATT_UUID, 4),
+ CHARACTERISTIC_STR(GATT_CHARAC_DEVICE_NAME, BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ, "BlueZ"),
+ DESCRIPTOR_STR(GATT_CHARAC_USER_DESC_UUID, BT_ATT_PERM_READ,
+ "Device Name"),
+ PRIMARY_SERVICE(0x0005, HEART_RATE_UUID, 6),
+ CHARACTERISTIC_STR_AT(0x0008,
+ GATT_CHARAC_MANUFACTURER_NAME_STRING,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ |
+ BT_GATT_CHRC_PROP_WRITE, ""),
+ DESCRIPTOR_STR_AT(0x000a, GATT_CHARAC_USER_DESC_UUID,
+ BT_ATT_PERM_READ, "Manufacturer Name"),
+ { }
+ };
+
+ return make_db(specs);
+}
+
/*
* Defined Test database 1:
* Tiny database fits into a single minimum sized-pdu.
@@ -1961,11 +2049,13 @@ static const struct test_step test_indication_server_1 = {
int main(int argc, char *argv[])
{
- struct gatt_db *service_db_1, *ts_small_db, *ts_large_db_1;
+ struct gatt_db *service_db_1, *service_db_2;
+ struct gatt_db *ts_small_db, *ts_large_db_1;
tester_init(&argc, &argv);
service_db_1 = make_service_data_1_db();
+ service_db_2 = make_service_data_2_db();
ts_small_db = make_test_spec_small_db();
ts_large_db_1 = make_test_spec_large_db_1();
@@ -2273,6 +2363,10 @@ int main(int argc, char *argv[])
service_db_1, NULL,
SERVICE_DATA_1_PDUS);
+ define_test_client("/TP/GAD/CL/BV-06-C/client-2", test_client,
+ service_db_2, NULL,
+ SERVICE_DATA_2_PDUS);
+
define_test_server("/TP/GAD/SR/BV-06-C/small", test_server,
ts_small_db, NULL,
raw_pdu(0x03, 0x00, 0x02),
--
2.1.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH BlueZ v3 4/7] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-3 test
2015-03-19 14:21 [PATCH BlueZ v3 1/7] shared/gatt-client: Fix handling of services Luiz Augusto von Dentz
2015-03-19 14:21 ` [PATCH BlueZ v3 2/7] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-1 test Luiz Augusto von Dentz
2015-03-19 14:21 ` [PATCH BlueZ v3 3/7] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-2 test Luiz Augusto von Dentz
@ 2015-03-19 14:21 ` Luiz Augusto von Dentz
2015-03-19 14:21 ` [PATCH BlueZ v3 5/7] shared/gatt-client: Fix service discovery Luiz Augusto von Dentz
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-03-19 14:21 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This verify the code is able to parse services with different gaps
between handles.
---
unit/test-gatt.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 86 insertions(+), 1 deletion(-)
diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 7bc2d25..f1f814a 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
@@ -178,6 +178,36 @@ struct context {
raw_pdu(0x04, 0x09, 0x00, 0x0a, 0x00), \
raw_pdu(0x05, 0x01, 0x0a, 0x00, 0x01, 0x29)
+#define SERVICE_DATA_3_PDUS \
+ MTU_EXCHANGE_CLIENT_PDUS, \
+ raw_pdu(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28), \
+ raw_pdu(0x11, 0x06, 0x00, 0x01, 0x21, 0x01, 0x00, 0x18, \
+ 0x00, 0x02, 0x00, 0x02, 0x01, 0x18), \
+ raw_pdu(0x10, 0x01, 0x02, 0xff, 0xff, 0x00, 0x28), \
+ raw_pdu(0x11, 0x06, 0x00, 0x03, 0x20, 0x03, 0x0d, 0x18),\
+ raw_pdu(0x10, 0x21, 0x03, 0xff, 0xff, 0x00, 0x28), \
+ raw_pdu(0x01, 0x10, 0x21, 0x03, 0x0a), \
+ raw_pdu(0x10, 0x01, 0x00, 0xff, 0xff, 0x01, 0x28), \
+ raw_pdu(0x01, 0x10, 0x01, 0x00, 0x0a), \
+ raw_pdu(0x08, 0x00, 0x01, 0x21, 0x01, 0x02, 0x28), \
+ raw_pdu(0x01, 0x08, 0x00, 0x01, 0x0a), \
+ raw_pdu(0x08, 0x00, 0x03, 0x20, 0x03, 0x02, 0x28), \
+ raw_pdu(0x01, 0x08, 0x00, 0x03, 0x0a), \
+ raw_pdu(0x08, 0x00, 0x01, 0x21, 0x01, 0x03, 0x28), \
+ raw_pdu(0x09, 0x07, 0x10, 0x01, 0x02, 0x11, 0x01, 0x00, \
+ 0x2a, 0x20, 0x01, 0x02, 0x21, 0x01, 0x01, 0x2a),\
+ raw_pdu(0x08, 0x21, 0x01, 0x21, 0x01, 0x03, 0x28), \
+ raw_pdu(0x01, 0x08, 0x21, 0x01, 0x0a), \
+ raw_pdu(0x04, 0x12, 0x01, 0x1f, 0x01), \
+ raw_pdu(0x01, 0x04, 0x12, 0x01, 0x0a), \
+ raw_pdu(0x08, 0x00, 0x03, 0x20, 0x03, 0x03, 0x28), \
+ raw_pdu(0x09, 0x07, 0x10, 0x03, 0x0a, 0x11, 0x03, 0x29, \
+ 0x2a), \
+ raw_pdu(0x08, 0x11, 0x03, 0x20, 0x03, 0x03, 0x28), \
+ raw_pdu(0x01, 0x08, 0x11, 0x03, 0x0a), \
+ raw_pdu(0x04, 0x12, 0x03, 0x20, 0x03), \
+ raw_pdu(0x05, 0x01, 0x20, 0x03, 0x02, 0x29)
+
#define PRIMARY_DISC_SMALL_DB \
raw_pdu(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28), \
raw_pdu(0x11, 0x06, 0x10, 0xF0, 0x17, 0xF0, 0x00, 0x18, \
@@ -1256,6 +1286,56 @@ static struct gatt_db *make_service_data_2_db(void)
return make_db(specs);
}
+#define CHARACTERISTIC_AT(chr_handle, chr_uuid, permissions, properties, \
+ bytes...) \
+ { \
+ .valid = true, \
+ .handle = chr_handle, \
+ .type = CHARACTERISTIC, \
+ .uuid = STR(chr_uuid), \
+ .att_permissions = permissions, \
+ .char_properties = properties, \
+ .value = data(bytes), \
+ .len = sizeof(data(bytes)), \
+ }
+
+#define DESCRIPTOR_AT(desc_handle, desc_uuid, permissions, bytes...) \
+ { \
+ .valid = true, \
+ .handle = desc_handle, \
+ .type = DESCRIPTOR, \
+ .uuid = STR(desc_uuid), \
+ .att_permissions = permissions, \
+ .value = data(bytes), \
+ .len = sizeof(data(bytes)), \
+ }
+
+static struct gatt_db *make_service_data_3_db(void)
+{
+ const struct att_handle_spec specs[] = {
+ PRIMARY_SERVICE(0x0100, GAP_UUID, 0x0121 - 0x0100 + 1),
+ CHARACTERISTIC_STR_AT(0x0111, GATT_CHARAC_DEVICE_NAME,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ, "BlueZ"),
+ CHARACTERISTIC_AT(0x0121, GATT_CHARAC_APPEARANCE,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ, 0x00, 0x00),
+ PRIMARY_SERVICE(0x0200, GATT_UUID, 0x0200 - 0x0200 + 1),
+ PRIMARY_SERVICE(0x0300, HEART_RATE_UUID, 0x0320 - 0x0300 + 1),
+ CHARACTERISTIC_STR_AT(0x0311,
+ GATT_CHARAC_MANUFACTURER_NAME_STRING,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ |
+ BT_GATT_CHRC_PROP_WRITE, ""),
+ DESCRIPTOR_AT(0x0320, GATT_CLIENT_CHARAC_CFG_UUID,
+ BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+ 0x00, 0x00),
+ { }
+ };
+
+ return make_db(specs);
+}
+
/*
* Defined Test database 1:
* Tiny database fits into a single minimum sized-pdu.
@@ -2049,13 +2129,14 @@ static const struct test_step test_indication_server_1 = {
int main(int argc, char *argv[])
{
- struct gatt_db *service_db_1, *service_db_2;
+ struct gatt_db *service_db_1, *service_db_2, *service_db_3;
struct gatt_db *ts_small_db, *ts_large_db_1;
tester_init(&argc, &argv);
service_db_1 = make_service_data_1_db();
service_db_2 = make_service_data_2_db();
+ service_db_3 = make_service_data_3_db();
ts_small_db = make_test_spec_small_db();
ts_large_db_1 = make_test_spec_large_db_1();
@@ -2367,6 +2448,10 @@ int main(int argc, char *argv[])
service_db_2, NULL,
SERVICE_DATA_2_PDUS);
+ define_test_client("/TP/GAD/CL/BV-06-C/client-3", test_client,
+ service_db_3, NULL,
+ SERVICE_DATA_3_PDUS);
+
define_test_server("/TP/GAD/SR/BV-06-C/small", test_server,
ts_small_db, NULL,
raw_pdu(0x03, 0x00, 0x02),
--
2.1.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH BlueZ v3 5/7] shared/gatt-client: Fix service discovery
2015-03-19 14:21 [PATCH BlueZ v3 1/7] shared/gatt-client: Fix handling of services Luiz Augusto von Dentz
` (2 preceding siblings ...)
2015-03-19 14:21 ` [PATCH BlueZ v3 4/7] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-3 test Luiz Augusto von Dentz
@ 2015-03-19 14:21 ` Luiz Augusto von Dentz
2015-03-19 14:21 ` [PATCH BlueZ v3 6/7] core/gatt: Fix not replying if db operation fail Luiz Augusto von Dentz
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-03-19 14:21 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
The code should proceed to discover all descriptors before moving to
next service otherwise it may attempt to insert characteristics in the
wrong service which would probably fail.
---
src/shared/gatt-client.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 3e28c6e..729bd87 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -690,13 +690,13 @@ static void discover_descs_cb(bool success, uint8_t att_ecode,
goto failed;
}
+next:
if (!discover_descs(op, &discovering))
goto failed;
if (discovering)
return;
-next:
/* Done with the current service */
gatt_db_service_set_active(op->cur_svc, true);
--
2.1.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH BlueZ v3 6/7] core/gatt: Fix not replying if db operation fail
2015-03-19 14:21 [PATCH BlueZ v3 1/7] shared/gatt-client: Fix handling of services Luiz Augusto von Dentz
` (3 preceding siblings ...)
2015-03-19 14:21 ` [PATCH BlueZ v3 5/7] shared/gatt-client: Fix service discovery Luiz Augusto von Dentz
@ 2015-03-19 14:21 ` Luiz Augusto von Dentz
2015-03-19 14:21 ` [PATCH BlueZ v3 7/7] core/gatt: Check if attribute is valid Luiz Augusto von Dentz
2015-03-20 9:19 ` [PATCH BlueZ v3 1/7] shared/gatt-client: Fix handling of services Luiz Augusto von Dentz
6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-03-19 14:21 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
src/gatt-client.c | 61 ++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 40 insertions(+), 21 deletions(-)
diff --git a/src/gatt-client.c b/src/gatt-client.c
index a85b9d2..8f67db3 100644
--- a/src/gatt-client.c
+++ b/src/gatt-client.c
@@ -344,20 +344,19 @@ static void desc_read_cb(bool success, uint8_t att_ecode,
struct async_dbus_op *op = user_data;
struct descriptor *desc = op->data;
struct service *service = desc->chrc->service;
+ DBusMessage *reply;
- if (!success) {
- DBusMessage *reply = create_gatt_dbus_error(op->msg, att_ecode);
-
- desc->read_id = 0;
- g_dbus_send_message(btd_get_dbus_connection(), reply);
- return;
- }
+ if (!success)
+ goto fail;
if (!op->offset)
gatt_db_attribute_reset(desc->attr);
- gatt_db_attribute_write(desc->attr, op->offset, value, length, 0, NULL,
- write_descriptor_cb, desc);
+ if (gatt_db_attribute_write(desc->attr, op->offset, value, length, 0,
+ NULL, write_descriptor_cb, desc)) {
+ error("Failed to store attribute");
+ goto fail;
+ }
/*
* If the value length is exactly MTU-1, then we may not have read the
@@ -377,10 +376,21 @@ static void desc_read_cb(bool success, uint8_t att_ecode,
return;
}
+ /* Read the stored data from db */
+ if (gatt_db_attribute_read(desc->attr, 0, 0, NULL, read_op_cb, op)) {
+ error("Failed to read database");
+ goto fail;
+ }
+
desc->read_id = 0;
- /* Read the stored data from db */
- gatt_db_attribute_read(desc->attr, 0, 0, NULL, read_op_cb, op);
+ return;
+
+fail:
+ reply = create_gatt_dbus_error(op->msg, att_ecode);
+ desc->read_id = 0;
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+ return;
}
static DBusMessage *descriptor_read_value(DBusConnection *conn,
@@ -778,20 +788,19 @@ static void chrc_read_cb(bool success, uint8_t att_ecode, const uint8_t *value,
struct async_dbus_op *op = user_data;
struct characteristic *chrc = op->data;
struct service *service = chrc->service;
+ DBusMessage *reply;
- if (!success) {
- DBusMessage *reply = create_gatt_dbus_error(op->msg, att_ecode);
-
- chrc->read_id = 0;
- g_dbus_send_message(btd_get_dbus_connection(), reply);
- return ;
- }
+ if (!success)
+ goto fail;
if (!op->offset)
gatt_db_attribute_reset(chrc->attr);
- gatt_db_attribute_write(chrc->attr, op->offset, value, length, 0, NULL,
- write_characteristic_cb, chrc);
+ if (!gatt_db_attribute_write(chrc->attr, op->offset, value, length, 0,
+ NULL, write_characteristic_cb, chrc)) {
+ error("Failed to store attribute");
+ goto fail;
+ }
/*
* If the value length is exactly MTU-1, then we may not have read the
@@ -814,7 +823,17 @@ static void chrc_read_cb(bool success, uint8_t att_ecode, const uint8_t *value,
chrc->read_id = 0;
/* Read the stored data from db */
- gatt_db_attribute_read(chrc->attr, 0, 0, NULL, read_op_cb, op);
+ if (!gatt_db_attribute_read(chrc->attr, 0, 0, NULL, read_op_cb, op)) {
+ error("Failed to read database");
+ goto fail;
+ }
+
+ return;
+
+fail:
+ reply = create_gatt_dbus_error(op->msg, att_ecode);
+ chrc->read_id = 0;
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
}
static DBusMessage *characteristic_read_value(DBusConnection *conn,
--
2.1.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH BlueZ v3 7/7] core/gatt: Check if attribute is valid
2015-03-19 14:21 [PATCH BlueZ v3 1/7] shared/gatt-client: Fix handling of services Luiz Augusto von Dentz
` (4 preceding siblings ...)
2015-03-19 14:21 ` [PATCH BlueZ v3 6/7] core/gatt: Fix not replying if db operation fail Luiz Augusto von Dentz
@ 2015-03-19 14:21 ` Luiz Augusto von Dentz
2015-03-20 9:19 ` [PATCH BlueZ v3 1/7] shared/gatt-client: Fix handling of services Luiz Augusto von Dentz
6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-03-19 14:21 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This checks the return of gatt_db_get_attribute and fail if return NULL.
---
src/gatt-client.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/gatt-client.c b/src/gatt-client.c
index 8f67db3..608f96d 100644
--- a/src/gatt-client.c
+++ b/src/gatt-client.c
@@ -1339,8 +1339,15 @@ static struct characteristic *characteristic_create(
gatt_db_attribute_get_char_data(attr, &chrc->handle,
&chrc->value_handle,
&chrc->props, &uuid);
+
chrc->attr = gatt_db_get_attribute(service->client->db,
chrc->value_handle);
+ if (!chrc->attr) {
+ error("Attribute 0x%04x not found", chrc->value_handle);
+ characteristic_free(chrc);
+ return NULL;
+ }
+
bt_uuid_to_uuid128(&uuid, &chrc->uuid);
chrc->path = g_strdup_printf("%s/char%04x", service->path,
--
2.1.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH BlueZ v3 1/7] shared/gatt-client: Fix handling of services
2015-03-19 14:21 [PATCH BlueZ v3 1/7] shared/gatt-client: Fix handling of services Luiz Augusto von Dentz
` (5 preceding siblings ...)
2015-03-19 14:21 ` [PATCH BlueZ v3 7/7] core/gatt: Check if attribute is valid Luiz Augusto von Dentz
@ 2015-03-20 9:19 ` Luiz Augusto von Dentz
6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-03-20 9:19 UTC (permalink / raw)
To: linux-bluetooth
Hi,
On Thu, Mar 19, 2015 at 4:21 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> Remote services may contain gaps between their handles so they need to be
> inserted in a proper position.
> ---
> v2: Fix gatt_db_get_attribute to work with non-sequential handles
> v3: Fix gatt_db_service_foreach_desc to work with non-sequential handles
>
> src/shared/gatt-client.c | 8 ++-
> src/shared/gatt-db.c | 147 +++++++++++++++++++++++++++++++++++++----------
> src/shared/gatt-db.h | 17 ++++++
> 3 files changed, 139 insertions(+), 33 deletions(-)
>
> diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
> index f33d8c9..3e28c6e 100644
> --- a/src/shared/gatt-client.c
> +++ b/src/shared/gatt-client.c
> @@ -588,7 +588,8 @@ static bool discover_descs(struct discovery_op *op, bool *discovering)
> *discovering = false;
>
> while ((chrc_data = queue_pop_head(op->pending_chrcs))) {
> - attr = gatt_db_service_add_characteristic(op->cur_svc,
> + attr = gatt_db_service_insert_characteristic(op->cur_svc,
> + chrc_data->value_handle,
> &chrc_data->uuid, 0,
> chrc_data->properties,
> NULL, NULL, NULL);
> @@ -679,8 +680,9 @@ static void discover_descs_cb(bool success, uint8_t att_ecode,
> "handle: 0x%04x, uuid: %s",
> handle, uuid_str);
>
> - attr = gatt_db_service_add_descriptor(op->cur_svc, &uuid, 0,
> - NULL, NULL, NULL);
> + attr = gatt_db_service_insert_descriptor(op->cur_svc, handle,
> + &uuid, 0, NULL, NULL,
> + NULL);
> if (!attr)
> goto failed;
>
> diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
> index eb81372..2b2090c 100644
> --- a/src/shared/gatt-db.c
> +++ b/src/shared/gatt-db.c
> @@ -158,6 +158,7 @@ static void attribute_destroy(struct gatt_db_attribute *attribute)
> }
>
> static struct gatt_db_attribute *new_attribute(struct gatt_db_service *service,
> + uint16_t handle,
> const bt_uuid_t *type,
> const uint8_t *val,
> uint16_t len)
> @@ -169,6 +170,7 @@ static struct gatt_db_attribute *new_attribute(struct gatt_db_service *service,
> return NULL;
>
> attribute->service = service;
> + attribute->handle = handle;
> attribute->uuid = *type;
> attribute->value_len = len;
> if (len) {
> @@ -371,6 +373,7 @@ static bool le_to_uuid(const uint8_t *src, size_t len, bt_uuid_t *uuid)
> }
>
> static struct gatt_db_service *gatt_db_service_create(const bt_uuid_t *uuid,
> + uint16_t handle,
> bool primary,
> uint16_t num_handles)
> {
> @@ -399,7 +402,8 @@ static struct gatt_db_service *gatt_db_service_create(const bt_uuid_t *uuid,
>
> len = uuid_to_le(uuid, value);
>
> - service->attributes[0] = new_attribute(service, type, value, len);
> + service->attributes[0] = new_attribute(service, handle, type, value,
> + len);
> if (!service->attributes[0]) {
> gatt_db_service_destroy(service);
> return NULL;
> @@ -533,7 +537,7 @@ struct gatt_db_attribute *gatt_db_insert_service(struct gatt_db *db,
> if (!find_insert_loc(db, handle, handle + num_handles - 1, &after))
> return NULL;
>
> - service = gatt_db_service_create(uuid, primary, num_handles);
> + service = gatt_db_service_create(uuid, handle, primary, num_handles);
>
> if (!service)
> return NULL;
> @@ -663,8 +667,9 @@ static void set_attribute_data(struct gatt_db_attribute *attribute,
> attribute->user_data = user_data;
> }
>
> -struct gatt_db_attribute *
> -gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
> +static struct gatt_db_attribute *
> +service_insert_characteristic(struct gatt_db_service *service,
> + uint16_t handle,
> const bt_uuid_t *uuid,
> uint32_t permissions,
> uint8_t properties,
> @@ -672,35 +677,38 @@ gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
> gatt_db_write_t write_func,
> void *user_data)
> {
> - struct gatt_db_service *service;
> uint8_t value[MAX_CHAR_DECL_VALUE_LEN];
> uint16_t len = 0;
> int i;
>
> - if (!attrib)
> + /* Check if handle is in within service range */
> + if (handle && handle <= service->attributes[0]->handle)
> return NULL;
>
> - service = attrib->service;
> -
> i = get_attribute_index(service, 1);
> if (!i)
> return NULL;
>
> + if (!handle)
> + handle = get_handle_at_index(service, i - 1) + 2;
> +
> value[0] = properties;
> len += sizeof(properties);
> +
> /* We set handle of characteristic value, which will be added next */
> - put_le16(get_handle_at_index(service, i - 1) + 2, &value[1]);
> + put_le16(handle, &value[1]);
> len += sizeof(uint16_t);
> len += uuid_to_le(uuid, &value[3]);
>
> - service->attributes[i] = new_attribute(service, &characteristic_uuid,
> - value, len);
> + service->attributes[i] = new_attribute(service, handle - 1,
> + &characteristic_uuid,
> + value, len);
> if (!service->attributes[i])
> return NULL;
>
> - attribute_update(service, i++);
> + i++;
>
> - service->attributes[i] = new_attribute(service, uuid, NULL, 0);
> + service->attributes[i] = new_attribute(service, handle, uuid, NULL, 0);
> if (!service->attributes[i]) {
> free(service->attributes[i - 1]);
> return NULL;
> @@ -709,37 +717,109 @@ gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
> set_attribute_data(service->attributes[i], read_func, write_func,
> permissions, user_data);
>
> - return attribute_update(service, i);
> + return service->attributes[i];
> }
>
> struct gatt_db_attribute *
> -gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib,
> +gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
> + uint16_t handle,
> const bt_uuid_t *uuid,
> uint32_t permissions,
> + uint8_t properties,
> gatt_db_read_t read_func,
> gatt_db_write_t write_func,
> void *user_data)
> {
> - struct gatt_db_service *service;
> - int i;
> + if (!attrib || !handle)
> + return NULL;
>
> + return service_insert_characteristic(attrib->service, handle, uuid,
> + permissions, properties,
> + read_func, write_func,
> + user_data);
> +}
> +
> +struct gatt_db_attribute *
> +gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
> + const bt_uuid_t *uuid,
> + uint32_t permissions,
> + uint8_t properties,
> + gatt_db_read_t read_func,
> + gatt_db_write_t write_func,
> + void *user_data)
> +{
> if (!attrib)
> return NULL;
>
> - service = attrib->service;
> + return service_insert_characteristic(attrib->service, 0, uuid,
> + permissions, properties,
> + read_func, write_func,
> + user_data);
> +}
> +
> +static struct gatt_db_attribute *
> +service_insert_descriptor(struct gatt_db_service *service,
> + uint16_t handle,
> + const bt_uuid_t *uuid,
> + uint32_t permissions,
> + gatt_db_read_t read_func,
> + gatt_db_write_t write_func,
> + void *user_data)
> +{
> + int i;
>
> i = get_attribute_index(service, 0);
> if (!i)
> return NULL;
>
> - service->attributes[i] = new_attribute(service, uuid, NULL, 0);
> + /* Check if handle is in within service range */
> + if (handle && handle <= service->attributes[0]->handle)
> + return NULL;
> +
> + if (!handle)
> + handle = get_handle_at_index(service, i - 1) + 1;
> +
> + service->attributes[i] = new_attribute(service, handle, uuid, NULL, 0);
> if (!service->attributes[i])
> return NULL;
>
> set_attribute_data(service->attributes[i], read_func, write_func,
> permissions, user_data);
>
> - return attribute_update(service, i);
> + return service->attributes[i];
> +}
> +
> +struct gatt_db_attribute *
> +gatt_db_service_insert_descriptor(struct gatt_db_attribute *attrib,
> + uint16_t handle,
> + const bt_uuid_t *uuid,
> + uint32_t permissions,
> + gatt_db_read_t read_func,
> + gatt_db_write_t write_func,
> + void *user_data)
> +{
> + if (!attrib || !handle)
> + return NULL;
> +
> + return service_insert_descriptor(attrib->service, handle, uuid,
> + permissions, read_func, write_func,
> + user_data);
> +}
> +
> +struct gatt_db_attribute *
> +gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib,
> + const bt_uuid_t *uuid,
> + uint32_t permissions,
> + gatt_db_read_t read_func,
> + gatt_db_write_t write_func,
> + void *user_data)
> +{
> + if (!attrib)
> + return NULL;
> +
> + return service_insert_descriptor(attrib->service, 0, uuid,
> + permissions, read_func, write_func,
> + user_data);
> }
>
> struct gatt_db_attribute *
> @@ -781,7 +861,7 @@ gatt_db_service_add_included(struct gatt_db_attribute *attrib,
> if (!index)
> return NULL;
>
> - service->attributes[index] = new_attribute(service,
> + service->attributes[index] = new_attribute(service, 0,
> &included_service_uuid,
> value, len);
> if (!service->attributes[index])
> @@ -1184,7 +1264,13 @@ void gatt_db_service_foreach_desc(struct gatt_db_attribute *attrib,
> service = attrib->service;
>
> /* Start from the attribute following the value handle */
> - i = attrib->handle - service->attributes[0]->handle + 2;
> + for (i = 0; i < service->num_handles; i++) {
> + if (service->attributes[i] == attrib) {
> + i += 2;
> + break;
> + }
> + }
> +
> for (; i < service->num_handles; i++) {
> attr = service->attributes[i];
> if (!attr)
> @@ -1222,7 +1308,7 @@ struct gatt_db_attribute *gatt_db_get_attribute(struct gatt_db *db,
> uint16_t handle)
> {
> struct gatt_db_service *service;
> - uint16_t service_handle;
> + int i;
>
> if (!db || !handle)
> return NULL;
> @@ -1232,14 +1318,15 @@ struct gatt_db_attribute *gatt_db_get_attribute(struct gatt_db *db,
> if (!service)
> return NULL;
>
> - service_handle = service->attributes[0]->handle;
> + for (i = 0; i < service->num_handles; i++) {
> + if (!service->attributes[i])
> + continue;
>
> - /*
> - * We can safely get attribute from attributes array with offset,
> - * because find_service_for_handle() check if given handle is
> - * in service range.
> - */
> - return service->attributes[handle - service_handle];
> + if (service->attributes[i]->handle == handle)
> + return service->attributes[i];
> + }
> +
> + return NULL;
> }
>
> static bool find_service_with_uuid(const void *data, const void *user_data)
> diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
> index 74b37bc..96cceb9 100644
> --- a/src/shared/gatt-db.h
> +++ b/src/shared/gatt-db.h
> @@ -67,6 +67,15 @@ gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
> gatt_db_read_t read_func,
> gatt_db_write_t write_func,
> void *user_data);
> +struct gatt_db_attribute *
> +gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
> + uint16_t handle,
> + const bt_uuid_t *uuid,
> + uint32_t permissions,
> + uint8_t properties,
> + gatt_db_read_t read_func,
> + gatt_db_write_t write_func,
> + void *user_data);
>
> struct gatt_db_attribute *
> gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib,
> @@ -75,6 +84,14 @@ gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib,
> gatt_db_read_t read_func,
> gatt_db_write_t write_func,
> void *user_data);
> +struct gatt_db_attribute *
> +gatt_db_service_insert_descriptor(struct gatt_db_attribute *attrib,
> + uint16_t handle,
> + const bt_uuid_t *uuid,
> + uint32_t permissions,
> + gatt_db_read_t read_func,
> + gatt_db_write_t write_func,
> + void *user_data);
>
> struct gatt_db_attribute *
> gatt_db_service_add_included(struct gatt_db_attribute *attrib,
> --
> 2.1.0
Applied.
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 8+ messages in thread