2015-03-18 21:04:46

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ] build: Add missing docs to EXTRA_DIST

From: Luiz Augusto von Dentz <[email protected]>

This adds doc/gatt-api.txt and doc/input-api.txt to EXTRA_DIST so they
get included in make dist tarball.
---
Makefile.am | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index cb8f2f5..90bb86b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -243,11 +243,13 @@ EXTRA_DIST += doc/mgmt-api.txt \
doc/adapter-api.txt doc/device-api.txt \
doc/agent-api.txt doc/profile-api.txt \
doc/network-api.txt doc/media-api.txt \
- doc/health-api.txt doc/sap-api.txt
+ doc/health-api.txt doc/sap-api.txt \
+ doc/input-api.txt

EXTRA_DIST += doc/alert-api.txt \
doc/proximity-api.txt doc/heartrate-api.txt \
- doc/thermometer-api.txt doc/cyclingspeed-api.txt
+ doc/thermometer-api.txt doc/cyclingspeed-api.txt \
+ doc/gatt-api.txt

EXTRA_DIST += doc/obex-api.txt doc/obex-agent-api.txt

--
2.1.0



2015-03-19 10:56:52

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ 5/5] shared/gatt-client: Fix service discovery

Hi Andrejs,

On Thu, Mar 19, 2015 at 12:17 PM, Luiz Augusto von Dentz
<[email protected]> wrote:
> Hi Andrejs,
>
> On Thu, Mar 19, 2015 at 9:36 AM, Andrejs Hanins <[email protected]> wrote:
>> Hi Luiz
>>
>> On 2015.03.18. 23:04, Luiz Augusto von Dentz wrote:
>>> From: Luiz Augusto von Dentz <[email protected]>
>>>
>>> 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);
>>>
>>>
>>
>> I tested this new patch-set and and results are the following:
>> 1. Three characteristics (GAP, GATT and custom) do appear on D-BUs. This was not the case before.
>> 2. CCC descriptor still does not appear on D-Bus. If I change handles on the peripheral back to sequential, then CCC appears on D-Bus also.
>> 3. Reading of any characteristic times out with 'g-io-error-quark: Timeout was reached (24)'. Logs attached. Based on HCI dumps the ATT reading is OK, but for some reason result is not propagated to the D-Bus level, so D-Dbus method times out. With sequential handles reading works fine.
>
> Strange for me it is working normally:
>
> [NEW] Service /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011
> Battery Service (Primary)
> [NEW] Characteristic
> /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012 Battery
> Level
> [NEW] Descriptor
> /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012/desc0014
> Client Characteristic Configuration
> [Arc Touch Mouse SE]# select-attribute
> /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012
> [Arc Touch Mouse SE:/service0011/char0012]# read
> Attempting to read /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012
> [CHG] Attribute
> /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012 Value: 0x5d
> 5d ]
> [Arc Touch Mouse SE:/service0011/char0012]# select-attribute
> /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012/desc0014
> [Arc Touch Mouse SE:/service0011/char0012/desc0014]# read
> Attempting to read
> /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012/desc0014
> [CHG] Attribute
> /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012/desc0014
> Value: 0x00
> [CHG] Attribute
> /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012/desc0014
> Value: 0x00
> 00 00
>
> But perhaps this is because the handles are in sequence as you said,
> can you try with the following changes:
>
> http://fpaste.org/199962/67601931/

See if the attachment works.


--
Luiz Augusto von Dentz


Attachments:
0001-core-gatt-Fix-not-replying-if-db-operation-fail.patch (1.92 kB)

2015-03-19 10:17:14

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ 5/5] shared/gatt-client: Fix service discovery

Hi Andrejs,

On Thu, Mar 19, 2015 at 9:36 AM, Andrejs Hanins <[email protected]> wrote:
> Hi Luiz
>
> On 2015.03.18. 23:04, Luiz Augusto von Dentz wrote:
>> From: Luiz Augusto von Dentz <[email protected]>
>>
>> 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);
>>
>>
>
> I tested this new patch-set and and results are the following:
> 1. Three characteristics (GAP, GATT and custom) do appear on D-BUs. This was not the case before.
> 2. CCC descriptor still does not appear on D-Bus. If I change handles on the peripheral back to sequential, then CCC appears on D-Bus also.
> 3. Reading of any characteristic times out with 'g-io-error-quark: Timeout was reached (24)'. Logs attached. Based on HCI dumps the ATT reading is OK, but for some reason result is not propagated to the D-Bus level, so D-Dbus method times out. With sequential handles reading works fine.

Strange for me it is working normally:

[NEW] Service /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011
Battery Service (Primary)
[NEW] Characteristic
/org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012 Battery
Level
[NEW] Descriptor
/org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012/desc0014
Client Characteristic Configuration
[Arc Touch Mouse SE]# select-attribute
/org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012
[Arc Touch Mouse SE:/service0011/char0012]# read
Attempting to read /org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012
[CHG] Attribute
/org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012 Value: 0x5d
5d ]
[Arc Touch Mouse SE:/service0011/char0012]# select-attribute
/org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012/desc0014
[Arc Touch Mouse SE:/service0011/char0012/desc0014]# read
Attempting to read
/org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012/desc0014
[CHG] Attribute
/org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012/desc0014
Value: 0x00
[CHG] Attribute
/org/bluez/hci0/dev_F3_43_74_B7_86_24/service0011/char0012/desc0014
Value: 0x00
00 00

But perhaps this is because the handles are in sequence as you said,
can you try with the following changes:

http://fpaste.org/199962/67601931/

--
Luiz Augusto von Dentz

2015-03-19 07:36:38

by Andrejs Hanins

[permalink] [raw]
Subject: Re: [PATCH BlueZ 5/5] shared/gatt-client: Fix service discovery

Hi Luiz

On 2015.03.18. 23:04, Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> 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);
>
>

I tested this new patch-set and and results are the following:
1. Three characteristics (GAP, GATT and custom) do appear on D-BUs. This was not the case before.
2. CCC descriptor still does not appear on D-Bus. If I change handles on the peripheral back to sequential, then CCC appears on D-Bus also.
3. Reading of any characteristic times out with 'g-io-error-quark: Timeout was reached (24)'. Logs attached. Based on HCI dumps the ATT reading is OK, but for some reason result is not propagated to the D-Bus level, so D-Dbus method times out. With sequential handles reading works fine.


Attachments:
bluez_fix2.log (12.58 kB)
noncons_handles_fix2.dump (1.57 kB)
Download all attachments

2015-03-18 21:04:48

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 2/5] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-1 test

From: Luiz Augusto von Dentz <[email protected]>

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


2015-03-18 21:04:51

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 5/5] shared/gatt-client: Fix service discovery

From: Luiz Augusto von Dentz <[email protected]>

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


2015-03-18 21:04:47

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 1/5] shared/gatt-client: Fix handling of services

From: Luiz Augusto von Dentz <[email protected]>

Remote services may contain gaps between their handles so they need to be
inserted in a proper position.
---
src/shared/gatt-client.c | 8 ++--
src/shared/gatt-db.c | 122 +++++++++++++++++++++++++++++++++++++++--------
src/shared/gatt-db.h | 17 +++++++
3 files changed, 123 insertions(+), 24 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..29361af 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])
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


2015-03-18 21:04:50

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 4/5] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-3 test

From: Luiz Augusto von Dentz <[email protected]>

This verify the code is able to parse services with different gaps
between handles.
---
unit/test-gatt.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 72 insertions(+), 1 deletion(-)

diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 7bc2d25..d510f51 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(0x01, 0x04, 0x12, 0x03, 0x0a) \
+
#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,42 @@ 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)), \
+ }
+
+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, ""),
+ { }
+ };
+
+ return make_db(specs);
+}
+
/*
* Defined Test database 1:
* Tiny database fits into a single minimum sized-pdu.
@@ -2049,13 +2115,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 +2434,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


2015-03-18 21:04:49

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 3/5] unit/test-gatt: Add /TP/GAD/CL/BV-06-C/client-2 test

From: Luiz Augusto von Dentz <[email protected]>

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