summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;