summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2023-02-28 16:05:47 -0800
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2023-03-02 12:19:40 -0800
commitd6f790f82de117fc16f5a6a8879be90599f85c8f (patch)
tree51975c4fd71e26adaecfb56c01bc0f725ad70ae2 /src/shared
parent36c234625bda881bc9d5bd99305706b86d117716 (diff)
downloadbluez-d6f790f82de117fc16f5a6a8879be90599f85c8f.tar.gz
share/gatt-client: Introduce idle callback
This introduces the concept of idle callback which can be used to get notified when there is no more pending requests by the client.
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/gatt-client.c78
-rw-r--r--src/shared/gatt-client.h8
2 files changed, 84 insertions, 2 deletions
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index baff68f28..f88507691 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -47,6 +47,12 @@ struct ready_cb {
void *data;
};
+struct idle_cb {
+ bt_gatt_client_idle_callback_t callback;
+ bt_gatt_client_destroy_func_t destroy;
+ void *data;
+};
+
struct bt_gatt_client {
struct bt_att *att;
int ref_count;
@@ -56,6 +62,7 @@ struct bt_gatt_client {
struct queue *clones;
struct queue *ready_cbs;
+ struct queue *idle_cbs;
bt_gatt_client_service_changed_callback_t svc_chngd_callback;
bt_gatt_client_destroy_func_t svc_chngd_destroy;
@@ -147,9 +154,38 @@ static struct request *request_create(struct bt_gatt_client *client)
return request_ref(req);
}
+static void idle_destroy(void *data)
+{
+ struct idle_cb *idle = data;
+
+ if (idle->destroy)
+ idle->destroy(idle->data);
+
+ free(idle);
+}
+
+static bool idle_notify(const void *data, const void *user_data)
+{
+ const struct idle_cb *idle = data;
+
+ idle->callback(idle->data);
+
+ return true;
+}
+
+static void notify_client_idle(struct bt_gatt_client *client)
+{
+ bt_gatt_client_ref(client);
+
+ queue_remove_all(client->idle_cbs, idle_notify, NULL, idle_destroy);
+
+ bt_gatt_client_unref(client);
+}
+
static void request_unref(void *data)
{
struct request *req = data;
+ struct bt_gatt_client *client = req->client;
if (__sync_sub_and_fetch(&req->ref_count, 1))
return;
@@ -157,8 +193,11 @@ static void request_unref(void *data)
if (req->destroy)
req->destroy(req->data);
- if (!req->removed)
- queue_remove(req->client->pending_requests, req);
+ if (!req->removed) {
+ queue_remove(client->pending_requests, req);
+ if (queue_isempty(client->pending_requests))
+ notify_client_idle(client);
+ }
free(req);
}
@@ -2234,6 +2273,7 @@ static void bt_gatt_client_free(struct bt_gatt_client *client)
queue_destroy(client->notify_list, notify_data_cleanup);
queue_destroy(client->ready_cbs, ready_destroy);
+ queue_destroy(client->idle_cbs, idle_destroy);
if (client->debug_destroy)
client->debug_destroy(client->debug_data);
@@ -2292,6 +2332,7 @@ static struct bt_gatt_client *gatt_client_new(struct gatt_db *db,
client->clones = queue_new();
client->ready_cbs = queue_new();
+ client->idle_cbs = queue_new();
client->long_write_queue = queue_new();
client->svc_chngd_queue = queue_new();
client->notify_list = queue_new();
@@ -3727,3 +3768,36 @@ int bt_gatt_client_get_security(struct bt_gatt_client *client)
return bt_att_get_security(client->att, NULL);
}
+
+unsigned int bt_gatt_client_idle_register(struct bt_gatt_client *client,
+ bt_gatt_client_idle_callback_t callback,
+ void *user_data,
+ bt_gatt_client_destroy_func_t destroy)
+{
+ struct idle_cb *idle;
+
+ if (!client)
+ return 0;
+
+ idle = new0(struct idle_cb, 1);
+ idle->callback = callback;
+ idle->destroy = destroy;
+ idle->data = user_data;
+
+ queue_push_tail(client->idle_cbs, idle);
+
+ return PTR_TO_UINT(idle);
+}
+
+bool bt_gatt_client_idle_unregister(struct bt_gatt_client *client,
+ unsigned int id)
+{
+ struct idle_cb *idle = UINT_TO_PTR(id);
+
+ if (queue_remove(client->idle_cbs, idle)) {
+ idle_destroy(idle);
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index dc5102394..bccd04a62 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -26,6 +26,7 @@ struct bt_gatt_client *bt_gatt_client_ref(struct bt_gatt_client *client);
void bt_gatt_client_unref(struct bt_gatt_client *client);
typedef void (*bt_gatt_client_destroy_func_t)(void *user_data);
+typedef void (*bt_gatt_client_idle_callback_t)(void *user_data);
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);
@@ -126,3 +127,10 @@ bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client,
bool bt_gatt_client_set_security(struct bt_gatt_client *client, int level);
int bt_gatt_client_get_security(struct bt_gatt_client *client);
+
+unsigned int bt_gatt_client_idle_register(struct bt_gatt_client *client,
+ bt_gatt_client_idle_callback_t callback,
+ void *user_data,
+ bt_gatt_client_destroy_func_t destroy);
+bool bt_gatt_client_idle_unregister(struct bt_gatt_client *client,
+ unsigned int id);