summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2017-06-30 15:42:29 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2017-07-04 12:30:05 +0300
commit0f3f40bab5c746e8a06c7b2a4d4a4a7fdb99f6d8 (patch)
treed6c789b999c48cc20f903533cd62be9f232edcaf
parentf59f3dedb2c79a75e51a3a0d27e2ae06fefc603e (diff)
downloadbluez-0f3f40bab5c746e8a06c7b2a4d4a4a7fdb99f6d8.tar.gz
shared/gatt-client: Allow multiple ready callbacks
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.
-rw-r--r--peripheral/gatt.c4
-rw-r--r--src/device.c10
-rw-r--r--src/shared/gatt-client.c60
-rw-r--r--src/shared/gatt-client.h4
-rw-r--r--tools/btgatt-client.c2
-rw-r--r--unit/test-gatt.c4
6 files changed, 59 insertions, 25 deletions
diff --git a/peripheral/gatt.c b/peripheral/gatt.c
index 4c5531d81..5ae19a8e5 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 def192f1e..8cb79df28 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 fbf90ff85..a34b00188 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 aceb570e6..6d8bf8043 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 f97963ecc..51bc3629d 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 15638dc89..5d79e94c0 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;