[PATCH BlueZ 02/10] shared/gatt-client: Allow multiple ready callbacks

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

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

This makes the ready callbacks much more convenient to track when the
client is ready since its is now possible to notify more than on client
at the same time.
---
 peripheral/gatt.c        |  4 ++--
 src/device.c             | 10 ++++----
 src/shared/gatt-client.c | 60 ++++++++++++++++++++++++++++++++++++------------
 src/shared/gatt-client.h |  4 +++-
 tools/btgatt-client.c    |  2 +-
 unit/test-gatt.c         |  4 ++--
 6 files changed, 59 insertions(+), 25 deletions(-)

diff --git a/peripheral/gatt.c b/peripheral/gatt.c
index 4c5531d..5ae19a8 100644
--- a/peripheral/gatt.c
+++ b/peripheral/gatt.c
@@ -145,8 +145,8 @@ static struct gatt_conn *gatt_conn_new(int fd)
 		return NULL;
 	}
 
-	bt_gatt_client_set_ready_handler(conn->client,
-				client_ready_callback, conn, NULL);
+	bt_gatt_client_ready_register(conn->client, client_ready_callback,
+								conn, NULL);
 	bt_gatt_client_set_service_changed(conn->client,
 				client_service_changed_callback, conn, NULL);
 
diff --git a/src/device.c b/src/device.c
index def192f..8cb79df 100644
--- a/src/device.c
+++ b/src/device.c
@@ -226,6 +226,7 @@ struct btd_device {
 	struct gatt_db *db;			/* GATT db cache */
 	struct bt_gatt_client *client;		/* GATT client instance */
 	struct bt_gatt_server *server;		/* GATT server instance */
+	unsigned int gatt_ready_id;
 
 	struct btd_gatt_client *client_dbus;
 
@@ -550,7 +551,7 @@ static void gatt_client_cleanup(struct btd_device *device)
 
 	gatt_cache_cleanup(device);
 	bt_gatt_client_set_service_changed(device->client, NULL, NULL, NULL);
-	bt_gatt_client_set_ready_handler(device->client, NULL, NULL, NULL);
+	bt_gatt_client_ready_unregister(device->client, device->gatt_ready_id);
 	bt_gatt_client_unref(device->client);
 	device->client = NULL;
 }
@@ -4718,10 +4719,11 @@ static void gatt_client_init(struct btd_device *device)
 	 */
 	device_accept_gatt_profiles(device);
 
-	if (!bt_gatt_client_set_ready_handler(device->client,
+	device->gatt_ready_id = bt_gatt_client_ready_register(device->client,
 							gatt_client_ready_cb,
-							device, NULL)) {
-		DBG("Failed to set ready handler");
+							device, NULL);
+	if (!device->gatt_ready_id) {
+		DBG("Failed to register GATT ready callback");
 		gatt_client_cleanup(device);
 		return;
 	}
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index fbf90ff..a34b001 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -51,6 +51,12 @@
 #define GATT_SVC_UUID	0x1801
 #define SVC_CHNGD_UUID	0x2a05
 
+struct ready_cb {
+	bt_gatt_client_callback_t callback;
+	bt_gatt_client_destroy_func_t destroy;
+	void *data;
+};
+
 struct bt_gatt_client {
 	struct bt_att *att;
 	int ref_count;
@@ -58,9 +64,7 @@ struct bt_gatt_client {
 	struct bt_gatt_client *parent;
 	struct queue *clones;
 
-	bt_gatt_client_callback_t ready_callback;
-	bt_gatt_client_destroy_func_t ready_destroy;
-	void *ready_data;
+	struct queue *ready_cbs;
 
 	bt_gatt_client_service_changed_callback_t svc_chngd_callback;
 	bt_gatt_client_destroy_func_t svc_chngd_destroy;
@@ -1097,17 +1101,35 @@ done:
 	discovery_op_complete(op, success, att_ecode);
 }
 
+static void ready_destroy(void *data)
+{
+	struct ready_cb *ready = data;
+
+	if (ready->destroy)
+		ready->destroy(ready->data);
+
+	free(ready);
+}
+
 static void notify_client_ready(struct bt_gatt_client *client, bool success,
 							uint8_t att_ecode)
 {
 	const struct queue_entry *entry;
 
-	if (!client->ready_callback || client->ready)
+	if (client->ready)
 		return;
 
 	bt_gatt_client_ref(client);
 	client->ready = success;
-	client->ready_callback(success, att_ecode, client->ready_data);
+
+	for (entry = queue_get_entries(client->ready_cbs); entry;
+							entry = entry->next) {
+		struct ready_cb *ready = entry->data;
+
+		ready->callback(success, att_ecode, ready->data);
+	}
+
+	queue_remove_all(client->ready_cbs, NULL, NULL, ready_destroy);
 
 	/* Notify clones */
 	for (entry = queue_get_entries(client->clones); entry;
@@ -1731,8 +1753,7 @@ static void bt_gatt_client_free(struct bt_gatt_client *client)
 
 	queue_destroy(client->notify_list, notify_data_cleanup);
 
-	if (client->ready_destroy)
-		client->ready_destroy(client->ready_data);
+	queue_destroy(client->ready_cbs, ready_destroy);
 
 	if (client->debug_destroy)
 		client->debug_destroy(client->debug_data);
@@ -1789,6 +1810,7 @@ static struct bt_gatt_client *gatt_client_new(struct gatt_db *db,
 		goto fail;
 
 	client->clones = queue_new();
+	client->ready_cbs = queue_new();
 	client->long_write_queue = queue_new();
 	client->svc_chngd_queue = queue_new();
 	client->notify_list = queue_new();
@@ -1886,22 +1908,30 @@ 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,
+unsigned int bt_gatt_client_ready_register(struct bt_gatt_client *client,
 					bt_gatt_client_callback_t callback,
 					void *user_data,
 					bt_gatt_client_destroy_func_t destroy)
 {
+	struct ready_cb *ready;
+
 	if (!client)
-		return false;
+		return 0;
 
-	if (client->ready_destroy)
-		client->ready_destroy(client->ready_data);
+	ready = new0(struct ready_cb, 1);
+	ready->callback = callback;
+	ready->destroy = destroy;
+	ready->data = user_data;
 
-	client->ready_callback = callback;
-	client->ready_destroy = destroy;
-	client->ready_data = user_data;
+	queue_push_tail(client->ready_cbs, ready);
 
-	return true;
+	return PTR_TO_UINT(ready);
+}
+
+bool bt_gatt_client_ready_unregister(struct bt_gatt_client *client,
+						unsigned int id)
+{
+	return queue_remove(client->ready_cbs, UINT_TO_PTR(id));
 }
 
 bool bt_gatt_client_set_service_changed(struct bt_gatt_client *client,
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index aceb570..6d8bf80 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -57,10 +57,12 @@ typedef void (*bt_gatt_client_service_changed_callback_t)(uint16_t start_handle,
 							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,
+unsigned int bt_gatt_client_ready_register(struct bt_gatt_client *client,
 					bt_gatt_client_callback_t callback,
 					void *user_data,
 					bt_gatt_client_destroy_func_t destroy);
+bool bt_gatt_client_ready_unregister(struct bt_gatt_client *client,
+						unsigned int id);
 bool bt_gatt_client_set_service_changed(struct bt_gatt_client *client,
 			bt_gatt_client_service_changed_callback_t callback,
 			void *user_data,
diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c
index f97963e..51bc362 100644
--- a/tools/btgatt-client.c
+++ b/tools/btgatt-client.c
@@ -235,7 +235,7 @@ static struct client *client_create(int fd, uint16_t mtu)
 									NULL);
 	}
 
-	bt_gatt_client_set_ready_handler(cli->gatt, ready_cb, cli, NULL);
+	bt_gatt_client_ready_register(cli->gatt, ready_cb, cli, NULL);
 	bt_gatt_client_set_service_changed(cli->gatt, service_changed_cb, cli,
 									NULL);
 
diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 15638dc..5d79e94 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
@@ -684,8 +684,8 @@ static struct context *create_context(uint16_t mtu, gconstpointer data)
 		bt_gatt_client_set_debug(context->client, print_debug,
 						"bt_gatt_client:", NULL);
 
-		bt_gatt_client_set_ready_handler(context->client,
-						client_ready_cb, context, NULL);
+		bt_gatt_client_ready_register(context->client, client_ready_cb,
+								context, NULL);
 		break;
 	default:
 		break;
-- 
2.9.4

--
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