From adad7c23ee5167c0dd44fe0550d76076b88b5814 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 23 Mar 2018 11:16:03 +0200 Subject: [PATCH] gatt: Send device and link options with AcquireNotify This adds the device and link options to AcquireNotify as mentioned in the documentation. Change-Id: I65ba0bc1ecc8a4c4adf90b7bc1ba515b061ee4fd Signed-off-by: Amit Purwar --- src/gatt-database.c | 178 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 115 insertions(+), 63 deletions(-) diff --git a/src/gatt-database.c b/src/gatt-database.c index fd0e00b..1e8eadc 100644 --- a/src/gatt-database.c +++ b/src/gatt-database.c @@ -174,8 +174,7 @@ struct device_state { struct notify *pending; }; -typedef uint8_t (*btd_gatt_database_ccc_write_t) (struct bt_att *att, - uint16_t value, +typedef uint8_t (*btd_gatt_database_ccc_write_t) (struct pending_op *op, void *user_data); typedef void (*btd_gatt_database_destroy_t) (void *data); @@ -318,7 +317,7 @@ static void clear_ccc_state(void *data, void *user_data) return; if (ccc_cb->callback) - ccc_cb->callback(NULL, 0, ccc_cb->user_data); + ccc_cb->callback(NULL, ccc_cb->user_data); } static void att_disconnected(int err, void *user_data) @@ -1004,6 +1003,76 @@ done: gatt_db_attribute_read_result(attrib, id, ecode, value, len); } +static struct btd_device *att_get_device(struct bt_att *att) +{ + GIOChannel *io = NULL; + GError *gerr = NULL; + bdaddr_t src, dst; + uint8_t dst_type; + struct btd_adapter *adapter; + + io = g_io_channel_unix_new(bt_att_get_fd(att)); + if (!io) + return NULL; + + bt_io_get(io, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src, + BT_IO_OPT_DEST_BDADDR, &dst, + BT_IO_OPT_DEST_TYPE, &dst_type, + BT_IO_OPT_INVALID); + if (gerr) { + error("bt_io_get: %s", gerr->message); + g_error_free(gerr); + g_io_channel_unref(io); + return NULL; + } + + g_io_channel_unref(io); + + adapter = adapter_find(&src); + if (!adapter) { + error("Unable to find adapter object"); + return NULL; + } + + return btd_adapter_find_device(adapter, &dst, dst_type); +} + +static struct pending_op *pending_ccc_new(struct bt_att *att, + struct gatt_db_attribute *attrib, + uint16_t value, + uint8_t link_type) +{ + struct pending_op *op; + struct btd_device *device; + + device = att_get_device(att); + if (!device) { + error("Unable to find device object"); + return NULL; + } + + op = new0(struct pending_op, 1); + + op->data.iov_base = UINT_TO_PTR(value); + op->data.iov_len = sizeof(value); + + op->device = device; + op->attrib = attrib; + op->link_type = link_type; + + return op; +} + +static void pending_op_free(void *data) +{ + struct pending_op *op = data; + + if (op->owner_queue) + queue_remove(op->owner_queue, op); + + free(op); +} + static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib, unsigned int id, uint16_t offset, const uint8_t *value, size_t len, @@ -1059,9 +1128,20 @@ static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib, if (ccc->value[0] == value[0] && ccc->value[1] == value[1]) goto done; - if (ccc_cb->callback) - ecode = ccc_cb->callback(att, get_le16(value), - ccc_cb->user_data); + if (ccc_cb->callback) { + struct pending_op *op; + + op = pending_ccc_new(att, attrib, get_le16(value), + bt_att_get_link_type(att)); + if (!op) { + ecode = BT_ATT_ERROR_UNLIKELY; + goto done; + } + + ecode = ccc_cb->callback(op, ccc_cb->user_data); + if (ecode) + pending_op_free(op); + } if (!ecode) { ccc->value[0] = value[0]; @@ -2176,15 +2256,6 @@ done: gatt_db_attribute_read_result(op->attrib, op->id, ecode, value, len); } -static void pending_op_free(void *data) -{ - struct pending_op *op = data; - - if (op->owner_queue) - queue_remove(op->owner_queue, op); - - free(op); -} static struct pending_op *pending_read_new(struct btd_device *device, struct queue *owner_queue, struct gatt_db_attribute *attrib, @@ -2587,7 +2658,8 @@ static struct pending_op *acquire_write(struct external_chrc *chrc, static void acquire_notify_reply(DBusMessage *message, void *user_data) { - struct external_chrc *chrc = user_data; + struct pending_op *op = user_data; + struct external_chrc *chrc = (void *) op->data.iov_base; DBusError err; int fd; uint16_t mtu; @@ -2625,7 +2697,9 @@ retry: static void acquire_notify_setup(DBusMessageIter *iter, void *user_data) { DBusMessageIter dict; - struct external_chrc *chrc = user_data; + struct pending_op *op = user_data; + struct bt_gatt_server *server; + uint16_t mtu; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING @@ -2634,25 +2708,34 @@ static void acquire_notify_setup(DBusMessageIter *iter, void *user_data) DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - dict_append_entry(&dict, "MTU", DBUS_TYPE_UINT16, &chrc->mtu); + append_options(&dict, op); + + server = btd_device_get_gatt_server(op->device); + + mtu = bt_gatt_server_get_mtu(server); + + dict_append_entry(&dict, "MTU", DBUS_TYPE_UINT16, &mtu); dbus_message_iter_close_container(iter, &dict); } -static uint8_t ccc_write_cb(struct bt_att *att, uint16_t value, void *user_data) +static uint8_t ccc_write_cb(struct pending_op *op, void *user_data) { struct external_chrc *chrc = user_data; DBusMessageIter iter; + uint16_t value; + + value = op ? PTR_TO_UINT(op->data.iov_base) : 0; DBG("External CCC write received with value: 0x%04x", value); /* Notifications/indications disabled */ if (!value) { if (!chrc->ntfy_cnt) - return 0; + goto done; if (__sync_sub_and_fetch(&chrc->ntfy_cnt, 1)) - return 0; + goto done; if (chrc->notify_io) { io_destroy(chrc->notify_io); @@ -2660,7 +2743,7 @@ static uint8_t ccc_write_cb(struct bt_att *att, uint16_t value, void *user_data) #ifdef TIZEN_FEATURE_BLUEZ_MODIFY DBG("HUP is not getting generated so calling StopNotify"); #else - return 0; + goto done; #endif } @@ -2670,13 +2753,12 @@ static uint8_t ccc_write_cb(struct bt_att *att, uint16_t value, void *user_data) */ g_dbus_proxy_method_call(chrc->proxy, "StopNotify", NULL, NULL, NULL, NULL); - return 0; + goto done; } - if (chrc->ntfy_cnt == UINT_MAX) { + if (chrc->ntfy_cnt == UINT_MAX) /* Maximum number of per-device CCC descriptors configured */ return BT_ATT_ERROR_INSUFFICIENT_RESOURCES; - } /* Don't support undefined CCC values yet */ if (value > 2 || @@ -2686,17 +2768,17 @@ static uint8_t ccc_write_cb(struct bt_att *att, uint16_t value, void *user_data) if (chrc->notify_io) { __sync_fetch_and_add(&chrc->ntfy_cnt, 1); - return 0; + goto done; } - chrc->mtu = bt_att_get_mtu(att); - /* Make use of AcquireNotify if supported */ if (g_dbus_proxy_get_property(chrc->proxy, "NotifyAcquired", &iter)) { + op->data.iov_base = (void *) chrc; + op->data.iov_len = sizeof(chrc); if (g_dbus_proxy_method_call(chrc->proxy, "AcquireNotify", acquire_notify_setup, acquire_notify_reply, - chrc, NULL)) + op, pending_op_free)) return 0; } @@ -2710,6 +2792,10 @@ static uint8_t ccc_write_cb(struct bt_att *att, uint16_t value, void *user_data) __sync_fetch_and_add(&chrc->ntfy_cnt, 1); +done: + if (op) + pending_op_free(op); + return 0; } @@ -2897,40 +2983,6 @@ static bool database_add_cep(struct external_service *service, return true; } -static struct btd_device *att_get_device(struct bt_att *att) -{ - GIOChannel *io = NULL; - GError *gerr = NULL; - bdaddr_t src, dst; - uint8_t dst_type; - struct btd_adapter *adapter; - - io = g_io_channel_unix_new(bt_att_get_fd(att)); - if (!io) - return NULL; - - bt_io_get(io, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src, - BT_IO_OPT_DEST_BDADDR, &dst, - BT_IO_OPT_DEST_TYPE, &dst_type, - BT_IO_OPT_INVALID); - if (gerr) { - error("bt_io_get: %s", gerr->message); - g_error_free(gerr); - g_io_channel_unref(io); - return NULL; - } - - g_io_channel_unref(io); - - adapter = adapter_find(&src); - if (!adapter) { - error("Unable to find adapter object"); - return NULL; - } - - return btd_adapter_find_device(adapter, &dst, dst_type); -} - static void desc_read_cb(struct gatt_db_attribute *attrib, unsigned int id, uint16_t offset, uint8_t opcode, struct bt_att *att, -- 2.7.4