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;
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;
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;
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);
}
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);
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();
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;
+}
+
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
char *bt_gatt_client_get_gap_device_name(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);
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);
#if defined TIZEN_FEATURE_BLUEZ_MODIFY
bool bt_gatt_discover_services(struct bt_gatt_client *client);