2014-12-09 23:08:32

by Marie Janssen

[permalink] [raw]
Subject: [PATCH BlueZ v2 0/8] Define TS-approved "small database"

This patch set's main goal is to add the small source database as defined
by page 24 of the GATT Test Spec.

It also adds improvements to bt_string_to_uuid to ease defined service UUID
strings, and some minor simplification of the existing test data.

Finally it allows the test database used by the IUT to be switched.

v1 -> v2:
* Refactor UUID compaction patch
* Add some tests for compaction
* Add Service Discovery by UUID
* Add /TP/GAD/SR/BV-02-C test

Michael Janssen (8):
lib/uuid: Simplify BT base UUIDs when possible
unit/gatt: Define repeated MTU PDUs.
unit/gatt: Use source db for server_tests
unit/gatt: Add test spec "small test database"
unit/gatt: minor fix for test PDUs
shared/gatt-db: Add gatt_db_find_by_type_value
shared/gatt-server: support Discover by UUID
unit/gatt: Add /TP/GAD/SR/BV-02-C test

lib/uuid.c | 17 ++-
src/shared/gatt-db.c | 27 +++++
src/shared/gatt-db.h | 7 ++
src/shared/gatt-server.c | 107 +++++++++++++++++
unit/test-gatt.c | 295 +++++++++++++++++++++++++++++++++--------------
unit/test-uuid.c | 52 ++++++++-
6 files changed, 410 insertions(+), 95 deletions(-)

--
2.2.0.rc0.207.ga3a616c



2014-12-10 08:08:16

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ v2 0/8] Define TS-approved "small database"

Hi Michael,

On Wed, Dec 10, 2014 at 1:08 AM, Michael Janssen <[email protected]> wrote:
> This patch set's main goal is to add the small source database as defined
> by page 24 of the GATT Test Spec.
>
> It also adds improvements to bt_string_to_uuid to ease defined service UUID
> strings, and some minor simplification of the existing test data.
>
> Finally it allows the test database used by the IUT to be switched.
>
> v1 -> v2:
> * Refactor UUID compaction patch
> * Add some tests for compaction
> * Add Service Discovery by UUID
> * Add /TP/GAD/SR/BV-02-C test
>
> Michael Janssen (8):
> lib/uuid: Simplify BT base UUIDs when possible
> unit/gatt: Define repeated MTU PDUs.
> unit/gatt: Use source db for server_tests
> unit/gatt: Add test spec "small test database"
> unit/gatt: minor fix for test PDUs
> shared/gatt-db: Add gatt_db_find_by_type_value
> shared/gatt-server: support Discover by UUID
> unit/gatt: Add /TP/GAD/SR/BV-02-C test
>
> lib/uuid.c | 17 ++-
> src/shared/gatt-db.c | 27 +++++
> src/shared/gatt-db.h | 7 ++
> src/shared/gatt-server.c | 107 +++++++++++++++++
> unit/test-gatt.c | 295 +++++++++++++++++++++++++++++++++--------------
> unit/test-uuid.c | 52 ++++++++-
> 6 files changed, 410 insertions(+), 95 deletions(-)
>
> --
> 2.2.0.rc0.207.ga3a616c

Patches 1-5 are applied, please not that I have to fix the following
in the first patch:

WARNING:LINE_SPACING: Missing a blank line after declarations
#13: FILE: lib/uuid.c:197:
+ char dummy;
+ if (!is_uuid128(string))

WARNING:LONG_LINE: line over 80 characters
#16: FILE: lib/uuid.c:200:
+ return sscanf(string,
"0000%04hx-0000-1000-8000-00805%1[fF]9%1[bB]34%1[fF]%1[bB]",

WARNING:LINE_SPACING: Missing a blank line after declarations
#132: FILE: unit/test-uuid.c:266:
+ char *testpath;
+ testpath = g_strdup_printf("/uuid/compress/%s",

In case you are wondering this is the output of checkpatch.pl that you
can find in the kernel tree.



--
Luiz Augusto von Dentz

2014-12-10 08:03:16

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ v2 6/8] shared/gatt-db: Add gatt_db_find_by_type_value

Hi Michael,

On Wed, Dec 10, 2014 at 1:08 AM, Michael Janssen <[email protected]> wrote:
> Added to support the GATT discovery of services by UUID.
> Currently only works for values which are stored within the attribute
> structure (not callback-based).
> ---
> src/shared/gatt-db.c | 27 +++++++++++++++++++++++++++
> src/shared/gatt-db.h | 7 +++++++
> 2 files changed, 34 insertions(+)
>
> diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
> index 98fb8a0..b261ca4 100644
> --- a/src/shared/gatt-db.c
> +++ b/src/shared/gatt-db.c
> @@ -853,6 +853,8 @@ struct find_by_type_value_data {
> bt_uuid_t uuid;
> uint16_t start_handle;
> uint16_t end_handle;
> + const void *value;
> + size_t value_len;
> };
>
> static void find_by_type(void *data, void *user_data)
> @@ -878,6 +880,12 @@ static void find_by_type(void *data, void *user_data)
> if (bt_uuid_cmp(&search_data->uuid, &attribute->uuid))
> continue;
>
> + /* TODO: fix for read-callback based attributes */
> + if (search_data->value && memcmp(attribute->value,
> + search_data->value,
> + search_data->value_len))
> + continue;
> +
> queue_push_tail(search_data->queue, attribute);
> }
> }
> @@ -897,6 +905,25 @@ void gatt_db_find_by_type(struct gatt_db *db, uint16_t start_handle,
> queue_foreach(db->services, find_by_type, &data);
> }
>
> +void gatt_db_find_by_type_value(struct gatt_db *db, uint16_t start_handle,
> + uint16_t end_handle,
> + const bt_uuid_t *type,
> + const void *value,
> + size_t value_len,
> + struct queue *queue)
> +{
> + struct find_by_type_value_data data;
> +
> + data.uuid = *type;
> + data.start_handle = start_handle;
> + data.end_handle = end_handle;
> + data.queue = queue;
> + data.value = value;
> + data.value_len = value_len;
> +
> + queue_foreach(db->services, find_by_type, &data);
> +}
> +
> struct read_by_type_data {
> struct queue *queue;
> bt_uuid_t uuid;
> diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
> index e5fe6bb..22e60d5 100644
> --- a/src/shared/gatt-db.h
> +++ b/src/shared/gatt-db.h
> @@ -92,6 +92,13 @@ void gatt_db_find_by_type(struct gatt_db *db, uint16_t start_handle,
> const bt_uuid_t *type,
> struct queue *queue);
>
> +void gatt_db_find_by_type_value(struct gatt_db *db, uint16_t start_handle,
> + uint16_t end_handle,
> + const bt_uuid_t *type,
> + const void *value,
> + size_t value_len,
> + struct queue *queue);
> +

We actually have plans to replace this API that expose queues with
callback based thus avoid having to iterate twice.

> void gatt_db_read_by_type(struct gatt_db *db, uint16_t start_handle,
> uint16_t end_handle,
> const bt_uuid_t type,
> --
> 2.2.0.rc0.207.ga3a616c
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html



--
Luiz Augusto von Dentz

2014-12-09 23:08:37

by Marie Janssen

[permalink] [raw]
Subject: [PATCH BlueZ v2 5/8] unit/gatt: minor fix for test PDUs

---
unit/test-gatt.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 505e41e..5f5ad1b 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
@@ -1136,12 +1136,12 @@ int main(int argc, char *argv[])
define_test_att("/TP/GAD/CL/BV-02-C-2", test_search_primary, &uuid_128,
NULL,
MTU_EXCHANGE_CLIENT_PDUS,
- raw_pdu(06, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28, 0xfb,
+ raw_pdu(0x06, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28, 0xfb,
0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00,
0x80, 0x00, 0x10, 0x00, 0x00, 0x0d,
0x18, 0x00, 0x00),
raw_pdu(0x07, 0x10, 0x00, 0x17, 0x00),
- raw_pdu(06, 0x18, 0x00, 0xff, 0xff, 0x00, 0x28, 0xfb,
+ raw_pdu(0x06, 0x18, 0x00, 0xff, 0xff, 0x00, 0x28, 0xfb,
0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00,
0x80, 0x00, 0x10, 0x00, 0x00, 0x0d,
0x18, 0x00, 0x00),
--
2.2.0.rc0.207.ga3a616c


2014-12-09 23:08:39

by Marie Janssen

[permalink] [raw]
Subject: [PATCH BlueZ v2 7/8] shared/gatt-server: support Discover by UUID

Implements Find By Type Value parsing and response, supporting the
"Discovery Primary Service by UUID" of GATT.
---
src/shared/gatt-server.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 107 insertions(+)

diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index 00f36fd..985cca1 100644
--- a/src/shared/gatt-server.c
+++ b/src/shared/gatt-server.c
@@ -87,6 +87,7 @@ struct bt_gatt_server {
unsigned int read_by_grp_type_id;
unsigned int read_by_type_id;
unsigned int find_info_id;
+ unsigned int find_by_type_value_id;
unsigned int write_id;
unsigned int write_cmd_id;
unsigned int read_id;
@@ -114,6 +115,7 @@ static void bt_gatt_server_free(struct bt_gatt_server *server)
bt_att_unregister(server->att, server->read_by_grp_type_id);
bt_att_unregister(server->att, server->read_by_type_id);
bt_att_unregister(server->att, server->find_info_id);
+ bt_att_unregister(server->att, server->find_by_type_value_id);
bt_att_unregister(server->att, server->write_id);
bt_att_unregister(server->att, server->write_cmd_id);
bt_att_unregister(server->att, server->read_id);
@@ -639,6 +641,102 @@ error:

}

+static bool encode_find_by_type_value_rsp(struct queue *q, uint16_t mtu,
+ uint8_t *pdu, uint16_t *len)
+{
+ struct gatt_db_attribute *attr;
+ uint16_t handle, end_handle;
+ uint16_t iter = 0;
+
+ *len = 0;
+ while (queue_peek_head(q)) {
+ /*
+ * This OP is only valid for Primary Service per the spec
+ * page 562, so this should work.
+ */
+ attr = queue_pop_head(q);
+ gatt_db_attribute_get_service_data(attr, &handle, &end_handle,
+ NULL, NULL);
+ if (!handle || !end_handle)
+ return false;
+
+ if (iter + 4 > mtu - 1)
+ break;
+
+ put_le16(handle, pdu + iter);
+ put_le16(end_handle, pdu + iter + 2);
+
+ iter += 4;
+ }
+
+ *len = iter;
+
+ return true;
+}
+
+static void find_by_type_val_cb(uint8_t opcode, const void *pdu,
+ uint16_t length, void *user_data)
+{
+ struct bt_gatt_server *server = user_data;
+ uint16_t start, end, uuid16;
+ uint16_t mtu = bt_att_get_mtu(server->att);
+ uint8_t rsp_pdu[mtu];
+ uint16_t rsp_len;
+ uint8_t ecode = 0;
+ uint16_t ehandle = 0;
+ bt_uuid_t uuid;
+ struct queue *q = NULL;
+
+ if (length < 6) {
+ ecode = BT_ATT_ERROR_INVALID_PDU;
+ goto error;
+ }
+
+ q = queue_new();
+ if (!q) {
+ ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
+ goto error;
+ }
+
+ start = get_le16(pdu);
+ end = get_le16(pdu + 2);
+ uuid16 = get_le16(pdu + 4);
+
+ util_debug(server->debug_callback, server->debug_data,
+ "Find By Type Value - start: 0x%04x end: 0x%04x uuid: 0x%04x",
+ start, end, uuid16);
+ ehandle = start;
+ if (start > end) {
+ ecode = BT_ATT_ERROR_INVALID_HANDLE;
+ goto error;
+ }
+
+ bt_uuid16_create(&uuid, uuid16);
+ gatt_db_find_by_type_value(server->db, start, end, &uuid, pdu + 6,
+ length - 6, q);
+
+ if (queue_isempty(q)) {
+ ecode = BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND;
+ goto error;
+ }
+
+ if (!encode_find_by_type_value_rsp(q, mtu, rsp_pdu, &rsp_len)) {
+ ecode = BT_ATT_ERROR_UNLIKELY;
+ goto error;
+ }
+
+ bt_att_send(server->att, BT_ATT_OP_FIND_BY_TYPE_VAL_RSP, rsp_pdu,
+ rsp_len, NULL, NULL, NULL);
+
+ queue_destroy(q, NULL);
+
+ return;
+
+error:
+ bt_att_send_error_rsp(server->att, opcode, ehandle, ecode);
+ queue_destroy(q, NULL);
+}
+
static void async_write_op_destroy(struct async_write_op *op)
{
if (op->server)
@@ -1128,6 +1226,15 @@ static bool gatt_server_register_att_handlers(struct bt_gatt_server *server)
if (!server->find_info_id)
return false;

+ /* Find By Type Value */
+ server->find_by_type_value_id = bt_att_register(server->att,
+ BT_ATT_OP_FIND_BY_TYPE_VAL_REQ,
+ find_by_type_val_cb,
+ server, NULL);
+
+ if (!server->find_by_type_value_id)
+ return false;
+
/* Write Request */
server->write_id = bt_att_register(server->att, BT_ATT_OP_WRITE_REQ,
write_cb,
--
2.2.0.rc0.207.ga3a616c


2014-12-09 23:08:40

by Marie Janssen

[permalink] [raw]
Subject: [PATCH BlueZ v2 8/8] unit/gatt: Add /TP/GAD/SR/BV-02-C test

Verify that a Generic Attribute Profile server can support discovery of
all particular Primary Services selected by service UUID, using 16-bit
UUIDs, and using 128-bit UUIDs where supported.

128-bit tests will be added once the larger databases with 128-bit UUIDs
are added.
---
unit/test-gatt.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 5f5ad1b..6f29647 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
@@ -1147,6 +1147,23 @@ int main(int argc, char *argv[])
0x18, 0x00, 0x00),
raw_pdu(0x01, 0x06, 0x08, 0x00, 0x0a));

+ define_test_server("/TP/GAD/SR/BV-02-C/exists-16/small", test_server,
+ ts_small_db, NULL,
+ raw_pdu(0x03, 0x00, 0x02),
+ raw_pdu(0x06, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28, 0x00,
+ 0x18),
+ raw_pdu(0x07, 0x10, 0xf0, 0x15, 0xf0),
+ raw_pdu(0x06, 0x16, 0xf0, 0xff, 0xff, 0x00, 0x28, 0x00,
+ 0x18),
+ raw_pdu(0x01, 0x06, 0x16, 0xf0, 0x0a));
+
+ define_test_server("/TP/GAD/SR/BV-02-C/missing-16/small", test_server,
+ ts_small_db, NULL,
+ raw_pdu(0x03, 0x00, 0x02),
+ raw_pdu(0x06, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28, 0x01,
+ 0x18),
+ raw_pdu(0x01, 0x06, 0x01, 0x00, 0x0a));
+
define_test_att("/TP/GAD/CL/BV-03-C", test_search_included, NULL,
NULL,
MTU_EXCHANGE_CLIENT_PDUS,
--
2.2.0.rc0.207.ga3a616c


2014-12-09 23:08:35

by Marie Janssen

[permalink] [raw]
Subject: [PATCH BlueZ v2 3/8] unit/gatt: Use source db for server_tests

Use the passed-in gatt_db for server tests instead of populating
with the same db every time.
---
unit/test-gatt.c | 70 +++++++++++++-------------------------------------------
1 file changed, 16 insertions(+), 54 deletions(-)

diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index c23b4c4..336bd6e 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
@@ -450,42 +450,6 @@ static void client_ready_cb(bool success, uint8_t att_ecode, void *user_data)
context_quit(context);
}

-static void populate_db(struct context *context)
-{
- struct gatt_db *db = context->server_db;
- struct gatt_db_attribute *attr;
- bt_uuid_t uuid;
- uint128_t u128 = {
- .data = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }
- };
-
- /* Service 1 */
- bt_uuid16_create(&uuid, 0x1800);
- attr = gatt_db_add_service(db, &uuid, true, 5);
- gatt_db_service_set_active(attr, true);
-
- /* Service 2 */
- bt_uuid16_create(&uuid, 0x1801);
- attr = gatt_db_add_service(db, &uuid, true, 3);
- gatt_db_service_set_active(attr, true);
-
- /* Service 3 */
- bt_uuid16_create(&uuid, 0x180f);
- attr = gatt_db_add_service(db, &uuid, false, 5);
- gatt_db_service_set_active(attr, true);
-
- /* Service 4 */
- bt_uuid16_create(&uuid, 0x180d);
- attr = gatt_db_add_service(db, &uuid, true, 8);
- gatt_db_service_set_active(attr, true);
-
- /* Service 5 */
- bt_uuid128_create(&uuid, u128);
- attr = gatt_db_add_service(db, &uuid, true, 1);
- gatt_db_service_set_active(attr, true);
-}
-
static struct context *create_context(uint16_t mtu, gconstpointer data)
{
struct context *context = g_new0(struct context, 1);
@@ -514,15 +478,13 @@ static struct context *create_context(uint16_t mtu, gconstpointer data)
bt_gatt_exchange_mtu(context->att, mtu, NULL, NULL, NULL);
break;
case SERVER:
- context->server_db = gatt_db_new();
+ context->server_db = gatt_db_ref(test_data->source_db);
g_assert(context->server_db);

context->server = bt_gatt_server_new(context->server_db, att,
mtu);
g_assert(context->server);

- populate_db(context);
-
if (g_test_verbose())
bt_gatt_server_set_debug(context->server, print_debug,
"bt_gatt_server:", NULL);
@@ -718,7 +680,7 @@ static struct gatt_db *make_service_data_1_db(void)
struct gatt_db_attribute *serv_att, *chrc_att;
bt_uuid_t uuid;

- bt_string_to_uuid(&uuid, GATT_UUID);
+ bt_uuid16_create(&uuid, 0x1801);
serv_att = gatt_db_insert_service(db, 0x0001, &uuid, true, 4);

bt_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
@@ -727,7 +689,9 @@ static struct gatt_db *make_service_data_1_db(void)

add_user_description(chrc_att, "Device Name", false);

- bt_string_to_uuid(&uuid, HEART_RATE_UUID);
+ gatt_db_service_set_active(serv_att, true);
+
+ bt_uuid16_create(&uuid, 0x180d);
serv_att = gatt_db_insert_service(db, 0x0005, &uuid, true, 4);

bt_uuid16_create(&uuid, GATT_CHARAC_MANUFACTURER_NAME_STRING);
@@ -738,6 +702,8 @@ static struct gatt_db *make_service_data_1_db(void)

add_user_description(chrc_att, "Manufacturer Name", false);

+ gatt_db_service_set_active(serv_att, true);
+
return db;
}

@@ -978,8 +944,9 @@ int main(int argc, char *argv[])
define_test_client("/TP/GAC/CL/BV-01-C", test_client, NULL, NULL,
raw_pdu(0x02, 0x00, 0x02));

- define_test_server("/TP/GAC/SR/BV-01-C", test_server, NULL, NULL,
- raw_pdu(0x03, 0x00, 0x02));
+ define_test_server("/TP/GAC/SR/BV-01-C", test_server, service_db_1,
+ NULL,
+ raw_pdu(0x03, 0x00, 0x02));

/*
* Discovery
@@ -1002,19 +969,14 @@ int main(int argc, char *argv[])
raw_pdu(0x10, 0x97, 0x00, 0xff, 0xff, 0x00, 0x28),
raw_pdu(0x01, 0x10, 0x97, 0x00, 0x0a));

- define_test_server("/TP/GAD/SR/BV-01-C", test_server, NULL, NULL,
+ define_test_server("/TP/GAD/SR/BV-01-C", test_server, service_db_1,
+ NULL,
raw_pdu(0x03, 0x00, 0x02),
raw_pdu(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28),
- raw_pdu(0x11, 0x06, 0x01, 0x00, 0x05, 0x00, 0x00, 0x18,
- 0x06, 0x00, 0x08, 0x00, 0x01, 0x18,
- 0x0e, 0x00, 0x15, 0x00, 0x0d, 0x18),
- raw_pdu(0x10, 0x16, 0x00, 0xff, 0xff, 0x00, 0x28),
- raw_pdu(0x11, 0x14, 0x16, 0x00, 0x16, 0x00, 0x0f,
- 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09,
- 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
- 0x02, 0x01, 0x00),
- raw_pdu(0x10, 0x17, 0x00, 0xff, 0xff, 0x00, 0x28),
- raw_pdu(0x01, 0x10, 0x17, 0x00, 0x0a));
+ raw_pdu(0x11, 0x06, 0x01, 0x00, 0x04, 0x00, 0x01, 0x18,
+ 0x05, 0x00, 0x08, 0x00, 0x0d, 0x18),
+ raw_pdu(0x10, 0x06, 0x00, 0xff, 0xff, 0x00, 0x28),
+ raw_pdu(0x01, 0x10, 0x06, 0x00, 0x0a));

define_test_att("/TP/GAD/CL/BV-02-C-1", test_search_primary, &uuid_16,
NULL,
--
2.2.0.rc0.207.ga3a616c


2014-12-09 23:08:33

by Marie Janssen

[permalink] [raw]
Subject: [PATCH BlueZ v2 1/8] lib/uuid: Simplify BT base UUIDs when possible

When converting a UUID from string to bt_uuid_t, prefer using
the 16-bit version when possible, which should generate shorter
sequences by increasing the number of 16-bit types.
---
lib/uuid.c | 17 +++++++++++++++--
unit/test-uuid.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/lib/uuid.c b/lib/uuid.c
index 186a7e6..29d4239 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -190,6 +190,17 @@ static inline int is_uuid128(const char *string)
string[23] == '-');
}

+static inline int is_base_uuid128(const char *string)
+{
+ uint16_t uuid;
+ char dummy;
+ if (!is_uuid128(string))
+ return 0;
+
+ return sscanf(string, "0000%04hx-0000-1000-8000-00805%1[fF]9%1[bB]34%1[fF]%1[bB]",
+ &uuid, &dummy, &dummy, &dummy, &dummy) == 5;
+}
+
static inline int is_uuid32(const char *string)
{
return (strlen(string) == 8 || strlen(string) == 10);
@@ -206,7 +217,7 @@ static int bt_string_to_uuid16(bt_uuid_t *uuid, const char *string)
char *endptr = NULL;

u16 = strtol(string, &endptr, 16);
- if (endptr && *endptr == '\0') {
+ if (endptr && (*endptr == '\0' || *endptr == '-')) {
bt_uuid16_create(uuid, u16);
return 0;
}
@@ -261,7 +272,9 @@ static int bt_string_to_uuid128(bt_uuid_t *uuid, const char *string)

int bt_string_to_uuid(bt_uuid_t *uuid, const char *string)
{
- if (is_uuid128(string))
+ if (is_base_uuid128(string))
+ return bt_string_to_uuid16(uuid, string + 4);
+ else if (is_uuid128(string))
return bt_string_to_uuid128(uuid, string);
else if (is_uuid32(string))
return bt_string_to_uuid32(uuid, string);
diff --git a/unit/test-uuid.c b/unit/test-uuid.c
index 49ea031..d7ee54d 100644
--- a/unit/test-uuid.c
+++ b/unit/test-uuid.c
@@ -46,9 +46,9 @@ static unsigned char uuid_base_binary[] = {
0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb };

static struct uuid_test_data uuid_base = {
- .str = "00000000-0000-1000-8000-00805f9b34fb",
- .binary = uuid_base_binary,
- .type = BT_UUID128,
+ .str = "0000",
+ .val16 = 0x0000,
+ .type = BT_UUID16,
.str128 = "00000000-0000-1000-8000-00805f9b34fb",
.binary128 = uuid_base_binary,
};
@@ -93,6 +93,18 @@ static struct uuid_test_data uuid_32_2 = {
.binary128 = uuid_32_binary,
};

+static unsigned char uuid_128_binary[] = {
+ 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb };
+
+static struct uuid_test_data uuid_128 = {
+ .str = "F0000000-0000-1000-8000-00805f9b34fb",
+ .binary = uuid_128_binary,
+ .type = BT_UUID128,
+ .str128 = "F0000000-0000-1000-8000-00805f9b34fb",
+ .binary128 = uuid_128_binary,
+};
+
static void test_uuid(gconstpointer data)
{
const struct uuid_test_data *test_data = data;
@@ -164,6 +176,26 @@ static void test_cmp(gconstpointer data)
g_assert(bt_uuid_cmp(&uuid1, &uuid2) == 0);
}

+static const struct uuid_test_data compress[] = {
+ {
+ .str = "00001234-0000-1000-8000-00805f9b34fb",
+ .type = BT_UUID16,
+ .val16 = 0x1234,
+ }, {
+ .str = "0000FFFF-0000-1000-8000-00805f9b34fb",
+ .type = BT_UUID16,
+ .val16 = 0xFFFF,
+ }, {
+ .str = "0000FFFF-0000-1000-8000-00805F9B34FB",
+ .type = BT_UUID16,
+ .val16 = 0xFFFF,
+ }, {
+ .str = "F0000000-0000-1000-8000-00805f9b34fb",
+ .type = BT_UUID128,
+ .binary = uuid_128_binary,
+ },
+};
+
static const char *malformed[] = {
"0",
"01",
@@ -193,7 +225,7 @@ static void test_malformed(gconstpointer data)

int main(int argc, char *argv[])
{
- int i;
+ size_t i;

g_test_init(&argc, &argv, NULL);

@@ -217,6 +249,10 @@ int main(int argc, char *argv[])
g_test_add_data_func("/uuid/thritytwo2/str", &uuid_32_2, test_str);
g_test_add_data_func("/uuid/thirtytwo2/cmp", &uuid_32_2, test_cmp);

+ g_test_add_data_func("/uuid/onetwentyeight", &uuid_128, test_uuid);
+ g_test_add_data_func("/uuid/onetwentyeight/str", &uuid_128, test_str);
+ g_test_add_data_func("/uuid/onetwentyeight/cmp", &uuid_128, test_cmp);
+
for (i = 0; malformed[i]; i++) {
char *testpath;

@@ -225,5 +261,13 @@ int main(int argc, char *argv[])
g_free(testpath);
}

+ for (i = 0; i < (sizeof(compress) / sizeof(compress[0])); i++) {
+ char *testpath;
+ testpath = g_strdup_printf("/uuid/compress/%s",
+ compress[i].str);
+ g_test_add_data_func(testpath, compress + i, test_uuid);
+ g_free(testpath);
+ }
+
return g_test_run();
}
--
2.2.0.rc0.207.ga3a616c


2014-12-09 23:08:36

by Marie Janssen

[permalink] [raw]
Subject: [PATCH BlueZ v2 4/8] unit/gatt: Add test spec "small test database"

This patch adds the first of a set of databases which are specified by
the Bluetooth GATT Test Specification document.

It is specifically the "small test database" constructed carefully to
fit the first requirement.

It satisfies the following requirements in section 3.3.2 of the GATT TS:
1. One small test database whose services fit into a single minimum
sized PDU, with only 16-biy UUIDs
3. At least one of those has a Primary Service at the MAX handle
8. All have some services that are simple, and some that include other
services
9. Each has at last one instance where the handle of an included service
is before the handle of the including service
11. Each has instances of simple characteristics (no descriptors) and
complex characteristics (multiple descriptors)
12. Each has instances of complex characteristics with 16-bit and
128-bit characteristic descriptor UUIDs, and these are in no
particular order.
---
unit/test-gatt.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 146 insertions(+), 1 deletion(-)

diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 336bd6e..505e41e 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
@@ -147,6 +147,17 @@ struct context {
raw_pdu(0x04, 0x08, 0x00, 0x08, 0x00), \
raw_pdu(0x05, 0x01, 0x08, 0x00, 0x01, 0x29)

+#define PRIMARY_DISC_SMALL_DB \
+ raw_pdu(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28), \
+ raw_pdu(0x11, 0x06, 0x10, 0xF0, 0x15, 0xF0, 0x00, 0x18, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x0a, 0x18)
+
+#define SECONDARY_DISC_SMALL_DB \
+ raw_pdu(0x10, 0x01, 0x00, 0xff, 0xff, 0x01, 0x28), \
+ raw_pdu(0x11, 0x06, 0x01, 0x00, 0x0F, 0x00, 0x0a, 0x18),\
+ raw_pdu(0x10, 0x10, 0x00, 0xff, 0xff, 0x01, 0x28), \
+ raw_pdu(0x01, 0x10, 0x10, 0x00, 0x0a)
+
#define SERVER_MTU_EXCHANGE_PDU raw_pdu(0x02, 0x17, 0x00)

static bt_uuid_t uuid_16 = {
@@ -647,6 +658,28 @@ static struct gatt_db_attribute *add_char_with_value(struct gatt_db *db,
return attrib;
}

+static struct gatt_db_attribute *add_ccc(struct gatt_db_attribute *chrc_att,
+ bool writable)
+{
+ struct gatt_db_attribute *desc_att;
+ bt_uuid_t uuid;
+ uint32_t permissions = BT_ATT_PERM_READ;
+ uint16_t tmp;
+
+ if (writable)
+ permissions |= BT_ATT_PERM_WRITE;
+
+ bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+ desc_att = gatt_db_service_add_descriptor(chrc_att, &uuid, permissions,
+ NULL, NULL, NULL);
+
+ tmp = 0x0000;
+ gatt_db_attribute_write(desc_att, 0, (uint8_t *)&tmp, sizeof(uint16_t),
+ 0x00, NULL, att_write_cb, NULL);
+
+ return desc_att;
+}
+
static struct gatt_db_attribute *
add_user_description(struct gatt_db_attribute *chrc_att, const char *desc,
bool writable)
@@ -674,6 +707,34 @@ typedef struct gatt_db_attribute (*add_service_func) (struct gatt_db *db,
bool primary,
uint16_t extra_handles);

+static struct gatt_db_attribute *
+add_device_information_service(struct gatt_db *db, uint16_t handle,
+ bool primary, uint16_t extra_handles)
+{
+ bt_uuid_t uuid;
+ struct gatt_db_attribute *serv_att;
+
+ bt_string_to_uuid(&uuid, DEVICE_INFORMATION_UUID);
+ serv_att = gatt_db_insert_service(db, handle, &uuid, primary,
+ 1 + extra_handles);
+
+ return serv_att;
+}
+
+static struct gatt_db_attribute *add_gap(struct gatt_db *db, uint16_t handle,
+ bool primary,
+ uint16_t extra_handles)
+{
+ bt_uuid_t uuid;
+ struct gatt_db_attribute *serv_att;
+
+ bt_string_to_uuid(&uuid, GAP_UUID);
+ serv_att = gatt_db_insert_service(db, handle, &uuid, primary,
+ 1 + extra_handles);
+
+ return serv_att;
+}
+
static struct gatt_db *make_service_data_1_db(void)
{
struct gatt_db *db = gatt_db_new();
@@ -707,6 +768,79 @@ static struct gatt_db *make_service_data_1_db(void)
return db;
}

+/*
+ * Defined Test database 1:
+ * Tiny database fits into a single minimum sized-pdu.
+ * Satisfies:
+ * 3. At least one primary seervice at the MAX handle
+ * For each / all databases:
+ * X 7. at least one service uuid with multiple instances
+ * X 8. Some simple services, some with included services
+ * X 9. an instance where handle of included service comes before the including
+ * service
+ * X 11. Simple characteristics (no desc) and complex characteristics
+ * (multiple descriptors)
+ * X 12. Instances of complex chars with 16-bit and 128-bit uuids
+ * (although not in scrambled order)
+ */
+
+static struct gatt_db *make_test_spec_small_db(void)
+{
+ struct gatt_db *db;
+ struct gatt_db_attribute *serv_att, *dis_att;
+ bt_uuid_t uuid;
+ const char *manuf_device_string = "BlueZ";
+ const char *device_name_string = "BlueZ Unit Tester";
+ const char *user_desc_manuf_name = "Manufacturer Name";
+ uint16_t u16_value;
+ uint8_t u8_value;
+
+ db = gatt_db_new();
+
+ dis_att = add_device_information_service(db, 0x0001, false, 15);
+
+ bt_uuid16_create(&uuid, GATT_CHARAC_MANUFACTURER_NAME_STRING);
+ add_char_with_value(db, dis_att, &uuid, BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ,
+ manuf_device_string,
+ strlen(manuf_device_string));
+ add_ccc(dis_att, false);
+ add_user_description(dis_att, user_desc_manuf_name, false);
+
+ gatt_db_service_set_active(dis_att, true);
+
+ serv_att = add_gap(db, 0xF010, true, 5);
+
+ gatt_db_service_add_included(serv_att, dis_att);
+
+ bt_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
+ add_char_with_value(db, serv_att, &uuid, BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ,
+ device_name_string,
+ strlen(device_name_string));
+
+ bt_string_to_uuid(&uuid, "0000B009-0000-0000-0123-456789abcdef");
+ u8_value = 0x09;
+ add_char_with_value(db, serv_att, &uuid, BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ,
+ &u8_value, sizeof(uint8_t));
+
+ gatt_db_service_set_active(serv_att, true);
+
+ u16_value = 0x0000; /* "Unknown" Appearance */
+ bt_uuid16_create(&uuid, GATT_CHARAC_APPEARANCE);
+ add_char_with_value(db, serv_att, &uuid, BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ, &u16_value,
+ sizeof(uint16_t));
+
+
+ serv_att = add_device_information_service(db, 0xFFFF, true, 0);
+
+ gatt_db_service_set_active(serv_att, true);
+
+ return db;
+}
+
static void test_client(gconstpointer data)
{
struct context *context = create_context(512, data);
@@ -928,11 +1062,12 @@ static void test_read_by_type(gconstpointer data)

int main(int argc, char *argv[])
{
- struct gatt_db *service_db_1;
+ struct gatt_db *service_db_1, *ts_small_db;

g_test_init(&argc, &argv, NULL);

service_db_1 = make_service_data_1_db();
+ ts_small_db = make_test_spec_small_db();

/*
* Server Configuration
@@ -969,6 +1104,11 @@ int main(int argc, char *argv[])
raw_pdu(0x10, 0x97, 0x00, 0xff, 0xff, 0x00, 0x28),
raw_pdu(0x01, 0x10, 0x97, 0x00, 0x0a));

+ define_test_att("/TP/GAD/CL/BV-01-C-small", test_search_primary, NULL,
+ NULL,
+ MTU_EXCHANGE_CLIENT_PDUS,
+ PRIMARY_DISC_SMALL_DB);
+
define_test_server("/TP/GAD/SR/BV-01-C", test_server, service_db_1,
NULL,
raw_pdu(0x03, 0x00, 0x02),
@@ -978,6 +1118,11 @@ int main(int argc, char *argv[])
raw_pdu(0x10, 0x06, 0x00, 0xff, 0xff, 0x00, 0x28),
raw_pdu(0x01, 0x10, 0x06, 0x00, 0x0a));

+ define_test_server("/TP/GAD/SR/BV-01-C-small", test_server, ts_small_db,
+ NULL,
+ raw_pdu(0x03, 0x00, 0x02),
+ PRIMARY_DISC_SMALL_DB);
+
define_test_att("/TP/GAD/CL/BV-02-C-1", test_search_primary, &uuid_16,
NULL,
MTU_EXCHANGE_CLIENT_PDUS,
--
2.2.0.rc0.207.ga3a616c


2014-12-09 23:08:34

by Marie Janssen

[permalink] [raw]
Subject: [PATCH BlueZ v2 2/8] unit/gatt: Define repeated MTU PDUs.

The MTU PDUs are repeated many times in the code, add a define for them.
Also use "PDUS" instead of "PDU" because these macros contain multiples.
---
unit/test-gatt.c | 57 +++++++++++++++++++++++++-------------------------------
1 file changed, 25 insertions(+), 32 deletions(-)

diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 2f3f26a..c23b4c4 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
@@ -114,9 +114,12 @@ struct context {
#define define_test_server(name, function, source_db, test_step, args...)\
define_test(name, function, SERVER, NULL, source_db, test_step, args)

-#define SERVICE_DATA_1_PDU \
+#define MTU_EXCHANGE_CLIENT_PDUS \
raw_pdu(0x02, 0x00, 0x02), \
- raw_pdu(0x03, 0x00, 0x02), \
+ raw_pdu(0x03, 0x00, 0x02)
+
+#define SERVICE_DATA_1_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), \
@@ -1015,8 +1018,7 @@ int main(int argc, char *argv[])

define_test_att("/TP/GAD/CL/BV-02-C-1", test_search_primary, &uuid_16,
NULL,
- raw_pdu(0x02, 0x00, 0x02),
- raw_pdu(0x03, 0x00, 0x02),
+ MTU_EXCHANGE_CLIENT_PDUS,
raw_pdu(0x06, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28, 0x00,
0x18),
raw_pdu(0x07, 0x01, 0x00, 0x07, 0x00),
@@ -1026,8 +1028,7 @@ int main(int argc, char *argv[])

define_test_att("/TP/GAD/CL/BV-02-C-2", test_search_primary, &uuid_128,
NULL,
- raw_pdu(0x02, 0x00, 0x02),
- raw_pdu(0x03, 0x00, 0x02),
+ MTU_EXCHANGE_CLIENT_PDUS,
raw_pdu(06, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28, 0xfb,
0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00,
0x80, 0x00, 0x10, 0x00, 0x00, 0x0d,
@@ -1041,8 +1042,7 @@ int main(int argc, char *argv[])

define_test_att("/TP/GAD/CL/BV-03-C", test_search_included, NULL,
NULL,
- raw_pdu(0x02, 0x00, 0x02),
- raw_pdu(0x03, 0x00, 0x02),
+ MTU_EXCHANGE_CLIENT_PDUS,
raw_pdu(0x08, 0x01, 0x00, 0xff, 0xff, 0x02, 0x28),
raw_pdu(0x09, 0x08, 0x02, 0x00, 0x10, 0x00, 0x1f, 0x00,
0x0f, 0x18),
@@ -1065,8 +1065,7 @@ int main(int argc, char *argv[])

define_test_att("/TP/GAD/CL/BV-04-C", test_search_chars, NULL,
NULL,
- raw_pdu(0x02, 0x00, 0x02),
- raw_pdu(0x03, 0x00, 0x02),
+ MTU_EXCHANGE_CLIENT_PDUS,
raw_pdu(0x08, 0x10, 0x00, 0x20, 0x00, 0x03, 0x28),
raw_pdu(0x09, 0x07, 0x11, 0x00, 02, 0x12, 0x00, 0x25,
0x2a),
@@ -1079,8 +1078,7 @@ int main(int argc, char *argv[])
raw_pdu(0x01, 0x08, 0x12, 0x00, 0x0a));

define_test_att("/TP/GAD/CL/BV-06-C", test_search_descs, NULL, NULL,
- raw_pdu(0x02, 0x00, 0x02),
- raw_pdu(0x03, 0x00, 0x02),
+ MTU_EXCHANGE_CLIENT_PDUS,
raw_pdu(0x04, 0x13, 0x00, 0x16, 0x00),
raw_pdu(0x05, 0x01, 0x13, 0x00, 0x02, 0x29, 0x14, 0x00,
0x03, 0x29),
@@ -1090,25 +1088,25 @@ int main(int argc, char *argv[])

define_test_client("/TP/GAR/CL/BV-01-C", test_client, service_db_1,
&test_read_1,
- SERVICE_DATA_1_PDU,
+ SERVICE_DATA_1_PDUS,
raw_pdu(0x0a, 0x03, 0x00),
raw_pdu(0x0b, 0x01, 0x02, 0x03));

define_test_client("/TP/GAR/CL/BI-01-C", test_client, service_db_1,
&test_read_2,
- SERVICE_DATA_1_PDU,
+ SERVICE_DATA_1_PDUS,
raw_pdu(0x0a, 0x00, 0x00),
raw_pdu(0x01, 0x0a, 0x00, 0x00, 0x01));

define_test_client("/TP/GAR/CL/BI-02-C", test_client, service_db_1,
&test_read_3,
- SERVICE_DATA_1_PDU,
+ SERVICE_DATA_1_PDUS,
raw_pdu(0x0a, 0x03, 0x00),
raw_pdu(0x01, 0x0a, 0x03, 0x00, 0x02));

define_test_client("/TP/GAR/CL/BI-03-C", test_client, service_db_1,
&test_read_4,
- SERVICE_DATA_1_PDU,
+ SERVICE_DATA_1_PDUS,
raw_pdu(0x0a, 0x03, 0x00),
raw_pdu(0x01, 0x0a, 0x03, 0x00, 0x08));

@@ -1138,72 +1136,67 @@ int main(int argc, char *argv[])

define_test_att("/TP/GAR/CL/BI-06-C", test_read_by_type, &uuid_char_16,
&test_read_by_type_2,
- raw_pdu(0x02, 0x00, 0x02),
- raw_pdu(0x03, 0x00, 0x02),
+ MTU_EXCHANGE_CLIENT_PDUS,
raw_pdu(0x08, 0x01, 0x00, 0xff, 0xff, 0x0d, 0x2a),
raw_pdu(0x01, 0x08, 0x0b, 0x00, 0x02));

define_test_att("/TP/GAR/CL/BI-07-C", test_read_by_type, &uuid_char_16,
&test_read_by_type_3,
- raw_pdu(0x02, 0x00, 0x02),
- raw_pdu(0x03, 0x00, 0x02),
+ MTU_EXCHANGE_CLIENT_PDUS,
raw_pdu(0x08, 0x01, 0x00, 0xff, 0xff, 0x0d, 0x2a),
raw_pdu(0x01, 0x08, 0x0b, 0x00, 0x0a));

define_test_att("/TP/GAR/CL/BI-09-C", test_read_by_type, &uuid_char_16,
&test_read_by_type_4,
- raw_pdu(0x02, 0x00, 0x02),
- raw_pdu(0x03, 0x00, 0x02),
+ MTU_EXCHANGE_CLIENT_PDUS,
raw_pdu(0x08, 0x01, 0x00, 0xff, 0xff, 0x0d, 0x2a),
raw_pdu(0x01, 0x08, 0x0b, 0x00, 0x08));

define_test_att("/TP/GAR/CL/BI-10-C", test_read_by_type, &uuid_char_16,
&test_read_by_type_5,
- raw_pdu(0x02, 0x00, 0x02),
- raw_pdu(0x03, 0x00, 0x02),
+ MTU_EXCHANGE_CLIENT_PDUS,
raw_pdu(0x08, 0x01, 0x00, 0xff, 0xff, 0x0d, 0x2a),
raw_pdu(0x01, 0x08, 0x0b, 0x00, 0x05));

define_test_att("/TP/GAR/CL/BI-11-C", test_read_by_type, &uuid_char_16,
&test_read_by_type_6,
- raw_pdu(0x02, 0x00, 0x02),
- raw_pdu(0x03, 0x00, 0x02),
+ MTU_EXCHANGE_CLIENT_PDUS,
raw_pdu(0x08, 0x01, 0x00, 0xff, 0xff, 0x0d, 0x2a),
raw_pdu(0x01, 0x08, 0x0b, 0x00, 0x0c));

define_test_client("/TP/GAR/CL/BV-05-C", test_client, service_db_1,
&test_multiple_read_1,
- SERVICE_DATA_1_PDU,
+ SERVICE_DATA_1_PDUS,
raw_pdu(0x0e, 0x03, 0x00, 0x07, 0x00),
raw_pdu(0x0f, 0x01, 0x02, 0x03));

define_test_client("/TP/GAR/CL/BI-18-C", test_client, service_db_1,
&test_multiple_read_2,
- SERVICE_DATA_1_PDU,
+ SERVICE_DATA_1_PDUS,
raw_pdu(0x0e, 0x03, 0x00, 0x07, 0x00),
raw_pdu(0x01, 0x0e, 0x03, 0x00, 0x02));

define_test_client("/TP/GAR/CL/BI-19-C", test_client, service_db_1,
&test_multiple_read_3,
- SERVICE_DATA_1_PDU,
+ SERVICE_DATA_1_PDUS,
raw_pdu(0x0e, 0x03, 0x00, 0x07, 0x00),
raw_pdu(0x01, 0x0e, 0x03, 0x00, 0x01));

define_test_client("/TP/GAR/CL/BI-20-C", test_client, service_db_1,
&test_multiple_read_4,
- SERVICE_DATA_1_PDU,
+ SERVICE_DATA_1_PDUS,
raw_pdu(0x0e, 0x03, 0x00, 0x07, 0x00),
raw_pdu(0x01, 0x0e, 0x03, 0x00, 0x08));

define_test_client("/TP/GAR/CL/BI-21-C", test_client, service_db_1,
&test_multiple_read_5,
- SERVICE_DATA_1_PDU,
+ SERVICE_DATA_1_PDUS,
raw_pdu(0x0e, 0x03, 0x00, 0x07, 0x00),
raw_pdu(0x01, 0x0e, 0x03, 0x00, 0x05));

define_test_client("/TP/GAR/CL/BI-21-C", test_client, service_db_1,
&test_multiple_read_6,
- SERVICE_DATA_1_PDU,
+ SERVICE_DATA_1_PDUS,
raw_pdu(0x0e, 0x03, 0x00, 0x07, 0x00),
raw_pdu(0x01, 0x0e, 0x03, 0x00, 0x0c));

--
2.2.0.rc0.207.ga3a616c


2014-12-09 23:08:38

by Marie Janssen

[permalink] [raw]
Subject: [PATCH BlueZ v2 6/8] shared/gatt-db: Add gatt_db_find_by_type_value

Added to support the GATT discovery of services by UUID.
Currently only works for values which are stored within the attribute
structure (not callback-based).
---
src/shared/gatt-db.c | 27 +++++++++++++++++++++++++++
src/shared/gatt-db.h | 7 +++++++
2 files changed, 34 insertions(+)

diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index 98fb8a0..b261ca4 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -853,6 +853,8 @@ struct find_by_type_value_data {
bt_uuid_t uuid;
uint16_t start_handle;
uint16_t end_handle;
+ const void *value;
+ size_t value_len;
};

static void find_by_type(void *data, void *user_data)
@@ -878,6 +880,12 @@ static void find_by_type(void *data, void *user_data)
if (bt_uuid_cmp(&search_data->uuid, &attribute->uuid))
continue;

+ /* TODO: fix for read-callback based attributes */
+ if (search_data->value && memcmp(attribute->value,
+ search_data->value,
+ search_data->value_len))
+ continue;
+
queue_push_tail(search_data->queue, attribute);
}
}
@@ -897,6 +905,25 @@ void gatt_db_find_by_type(struct gatt_db *db, uint16_t start_handle,
queue_foreach(db->services, find_by_type, &data);
}

+void gatt_db_find_by_type_value(struct gatt_db *db, uint16_t start_handle,
+ uint16_t end_handle,
+ const bt_uuid_t *type,
+ const void *value,
+ size_t value_len,
+ struct queue *queue)
+{
+ struct find_by_type_value_data data;
+
+ data.uuid = *type;
+ data.start_handle = start_handle;
+ data.end_handle = end_handle;
+ data.queue = queue;
+ data.value = value;
+ data.value_len = value_len;
+
+ queue_foreach(db->services, find_by_type, &data);
+}
+
struct read_by_type_data {
struct queue *queue;
bt_uuid_t uuid;
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index e5fe6bb..22e60d5 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -92,6 +92,13 @@ void gatt_db_find_by_type(struct gatt_db *db, uint16_t start_handle,
const bt_uuid_t *type,
struct queue *queue);

+void gatt_db_find_by_type_value(struct gatt_db *db, uint16_t start_handle,
+ uint16_t end_handle,
+ const bt_uuid_t *type,
+ const void *value,
+ size_t value_len,
+ struct queue *queue);
+
void gatt_db_read_by_type(struct gatt_db *db, uint16_t start_handle,
uint16_t end_handle,
const bt_uuid_t type,
--
2.2.0.rc0.207.ga3a616c