[PATCH BlueZ v1 10/13] shared/gatt-client: Add service iterator functions.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch introduces high-level structures and functions for iterating through,
and storing, data about the discovered services.
---
 src/shared/gatt-client.c | 148 +++++++++++++++++++++++++++++++++++++++++++++--
 src/shared/gatt-client.h |  41 +++++++++++++
 2 files changed, 185 insertions(+), 4 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 7a76234..17b2f56 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -31,6 +31,13 @@
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
 #endif
 
+#define UUID_BYTES BT_GATT_UUID_SIZE * sizeof(uint8_t)
+
+struct service_list {
+	bt_gatt_service_t service;
+	struct service_list *next;
+};
+
 struct bt_gatt_client {
 	struct bt_att *att;
 	int ref_count;
@@ -43,9 +50,61 @@ struct bt_gatt_client {
 	bt_gatt_client_destroy_func_t debug_destroy;
 	void *debug_data;
 
+	struct service_list *svc_head, *svc_tail;
 	bool in_init;
+	bool ready;
 };
 
+static bool gatt_client_add_service(struct bt_gatt_client *client,
+						uint16_t start, uint16_t end,
+						uint8_t uuid[BT_GATT_UUID_SIZE])
+{
+	struct service_list *list;
+
+	list = new0(struct service_list, 1);
+	if (!list)
+		return false;
+
+	list->service.start_handle = start;
+	list->service.end_handle = end;
+	memcpy(list->service.uuid, uuid, UUID_BYTES);
+
+	if (!client->svc_head)
+		client->svc_head = client->svc_tail = list;
+	else {
+		client->svc_tail->next = list;
+		client->svc_tail = list;
+	}
+
+	return true;
+}
+
+static void service_destroy_characteristics(bt_gatt_service_t *service)
+{
+	unsigned int i;
+
+	for (i = 0; i < service->num_chrcs; i++)
+		free((bt_gatt_descriptor_t *) service->chrcs[i].descs);
+
+	free((bt_gatt_characteristic_t *) service->chrcs);
+}
+
+static void gatt_client_clear_services(struct bt_gatt_client *client)
+{
+	struct service_list *l, *tmp;
+
+	l = client->svc_head;
+
+	while (l) {
+		service_destroy_characteristics(&l->service);
+		tmp = l;
+		l = tmp->next;
+		free(tmp);
+	}
+
+	client->svc_head = client->svc_tail = NULL;
+}
+
 struct async_op {
 	struct bt_gatt_client *client;
 	int ref_count;
@@ -76,7 +135,7 @@ static void discover_primary_cb(bool success, uint8_t att_ecode,
 	struct bt_gatt_client *client = op->client;
 	struct bt_gatt_iter iter;
 	uint16_t start, end;
-	uint8_t uuid[16];
+	uint8_t uuid[BT_GATT_UUID_SIZE];
 	char uuid_str[MAX_LEN_UUID_STR];
 	bt_uuid_t tmp;
 
@@ -98,8 +157,6 @@ static void discover_primary_cb(bool success, uint8_t att_ecode,
 					bt_gatt_result_service_count(result));
 
 	while (bt_gatt_iter_next_service(&iter, &start, &end, uuid)) {
-		/* TODO: discover characteristics and store the service. */
-
 		/* Log debug message. */
 		tmp.type = BT_UUID128;
 		memcpy(tmp.value.u128.data, uuid, sizeof(uuid));
@@ -107,11 +164,25 @@ static void discover_primary_cb(bool success, uint8_t att_ecode,
 		util_debug(client->debug_callback, client->debug_data,
 				"start: 0x%04x, end: 0x%04x, uuid: %s",
 				start, end, uuid_str);
+
+		/* Store the service */
+		if (!gatt_client_add_service(client, start, end, uuid)) {
+			util_debug(client->debug_callback, client->debug_data,
+						"Failed to store service");
+
+			gatt_client_clear_services(client);
+
+			success = false;
+			goto done;
+		}
 	}
 
 done:
 	client->in_init = false;
 
+	if (success)
+		client->ready = true;
+
 	if (client->ready_callback)
 		client->ready_callback(success, att_ecode, client->ready_data);
 }
@@ -160,7 +231,7 @@ static bool gatt_client_init(struct bt_gatt_client *client, uint16_t mtu)
 {
 	struct async_op *op;
 
-	if (client->in_init)
+	if (client->in_init || client->ready)
 		return false;
 
 	op = new0(struct async_op, 1);
@@ -231,6 +302,11 @@ void bt_gatt_client_unref(struct bt_gatt_client *client)
 	free(client);
 }
 
+bool bt_gatt_client_is_ready(struct bt_gatt_client *client)
+{
+	return (client && client->ready);
+}
+
 bool bt_gatt_client_set_ready_handler(struct bt_gatt_client *client,
 					bt_gatt_client_callback_t callback,
 					void *user_data,
@@ -265,3 +341,67 @@ bool bt_gatt_client_set_debug(struct bt_gatt_client *client,
 
 	return true;
 }
+
+bool bt_gatt_service_iter_init(struct bt_gatt_service_iter *iter,
+						struct bt_gatt_client *client)
+{
+	if (!iter || !client)
+		return false;
+
+	if (client->in_init)
+		return false;
+
+	memset(iter, 0, sizeof(*iter));
+	iter->client = client;
+	iter->ptr = NULL;
+
+	return true;
+}
+
+bool bt_gatt_service_iter_next(struct bt_gatt_service_iter *iter,
+						bt_gatt_service_t *service)
+{
+	struct service_list *l;
+
+	if (!iter || !service)
+		return false;
+
+	l = iter->ptr;
+
+	if (!l)
+		l = iter->client->svc_head;
+	else
+		l = l->next;
+
+	if (!l)
+		return false;
+
+	*service = l->service;
+	iter->ptr = l;
+
+	return true;
+}
+
+bool bt_gatt_service_iter_next_by_handle(struct bt_gatt_service_iter *iter,
+						uint16_t start_handle,
+						bt_gatt_service_t *service)
+{
+	while (bt_gatt_service_iter_next(iter, service)) {
+		if (service->start_handle == start_handle)
+			return true;
+	}
+
+	return false;
+}
+
+bool bt_gatt_service_iter_next_by_uuid(struct bt_gatt_service_iter *iter,
+					const uint8_t uuid[BT_GATT_UUID_SIZE],
+					bt_gatt_service_t *service)
+{
+	while (bt_gatt_service_iter_next(iter, service)) {
+		if (memcmp(service->uuid, uuid, UUID_BYTES) == 0)
+			return true;
+	}
+
+	return false;
+}
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index 45c6010..f724c3c 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -23,6 +23,9 @@
 
 #include <stdbool.h>
 #include <stdint.h>
+#include <stddef.h>
+
+#define BT_GATT_UUID_SIZE 16
 
 struct bt_gatt_client;
 
@@ -36,6 +39,7 @@ typedef void (*bt_gatt_client_callback_t)(bool success, uint8_t att_ecode,
 							void *user_data);
 typedef void (*bt_gatt_client_debug_func_t)(const char *str, void *user_data);
 
+bool bt_gatt_client_is_ready(struct bt_gatt_client *client);
 bool bt_gatt_client_set_ready_handler(struct bt_gatt_client *client,
 					bt_gatt_client_callback_t callback,
 					void *user_data,
@@ -46,3 +50,40 @@ bool bt_gatt_client_set_debug(struct bt_gatt_client *client,
 					void *user_data,
 					bt_gatt_client_destroy_func_t destroy);
 
+typedef struct {
+	uint16_t handle;
+	uint8_t uuid[BT_GATT_UUID_SIZE];
+} bt_gatt_descriptor_t;
+
+typedef struct {
+	uint16_t handle;
+	uint16_t value_handle;
+	uint8_t properties;
+	uint8_t uuid[BT_GATT_UUID_SIZE];
+	const bt_gatt_descriptor_t *descs;
+	size_t num_descs;
+} bt_gatt_characteristic_t;
+
+typedef struct {
+	uint16_t start_handle;
+	uint16_t end_handle;
+	uint8_t uuid[BT_GATT_UUID_SIZE];
+	const bt_gatt_characteristic_t *chrcs;
+	size_t num_chrcs;
+} bt_gatt_service_t;
+
+struct bt_gatt_service_iter {
+	struct bt_gatt_client *client;
+	void *ptr;
+};
+
+bool bt_gatt_service_iter_init(struct bt_gatt_service_iter *iter,
+						struct bt_gatt_client *client);
+bool bt_gatt_service_iter_next(struct bt_gatt_service_iter *iter,
+						bt_gatt_service_t *service);
+bool bt_gatt_service_iter_next_by_handle(struct bt_gatt_service_iter *iter,
+						uint16_t start_handle,
+						bt_gatt_service_t *service);
+bool bt_gatt_service_iter_next_by_uuid(struct bt_gatt_service_iter *iter,
+					const uint8_t uuid[BT_GATT_UUID_SIZE],
+					bt_gatt_service_t *service);
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux