From 2d5984760f635b4a834c6b953b9819dba6859419 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 6 Jun 2019 09:22:56 +0300 Subject: [PATCH] shared/gatt: Add support for Handle Value Multiple Notifications Handle Value Multiple Notification can be used to notify multiple values at once. Signed-off-by: Anuj Jain Signed-off-by: Ayush Garg --- src/shared/att-types.h | 7 ++-- src/shared/att.c | 16 +++++----- src/shared/gatt-client.c | 83 +++++++++++++++++++++++++++++++----------------- src/shared/gatt-server.c | 4 +-- 4 files changed, 67 insertions(+), 43 deletions(-) diff --git a/src/shared/att-types.h b/src/shared/att-types.h index fce3d81..48d2985 100755 --- a/src/shared/att-types.h +++ b/src/shared/att-types.h @@ -72,11 +72,12 @@ #define BT_ATT_OP_PREP_WRITE_RSP 0x17 #define BT_ATT_OP_EXEC_WRITE_REQ 0x18 #define BT_ATT_OP_EXEC_WRITE_RSP 0x19 -#define BT_ATT_OP_HANDLE_VAL_NOT 0x1B -#define BT_ATT_OP_HANDLE_VAL_IND 0x1D -#define BT_ATT_OP_HANDLE_VAL_CONF 0x1E +#define BT_ATT_OP_HANDLE_NFY 0x1B +#define BT_ATT_OP_HANDLE_IND 0x1D +#define BT_ATT_OP_HANDLE_CONF 0x1E #define BT_ATT_OP_READ_MULT_VL_REQ 0x20 #define BT_ATT_OP_READ_MULT_VL_RSP 0x21 +#define BT_ATT_OP_HANDLE_NFY_MULT 0x23 /* Packed struct definitions for ATT protocol PDUs */ /* TODO: Complete these definitions for all opcodes */ diff --git a/src/shared/att.c b/src/shared/att.c index 9a05c98..adcd7ad 100755 --- a/src/shared/att.c +++ b/src/shared/att.c @@ -117,7 +117,7 @@ enum att_op_type { ATT_OP_TYPE_RSP, ATT_OP_TYPE_CMD, ATT_OP_TYPE_IND, - ATT_OP_TYPE_NOT, + ATT_OP_TYPE_NFY, ATT_OP_TYPE_CONF, ATT_OP_TYPE_UNKNOWN, }; @@ -151,9 +151,9 @@ static const struct { { BT_ATT_OP_PREP_WRITE_RSP, ATT_OP_TYPE_RSP }, { BT_ATT_OP_EXEC_WRITE_REQ, ATT_OP_TYPE_REQ }, { BT_ATT_OP_EXEC_WRITE_RSP, ATT_OP_TYPE_RSP }, - { BT_ATT_OP_HANDLE_VAL_NOT, ATT_OP_TYPE_NOT }, - { BT_ATT_OP_HANDLE_VAL_IND, ATT_OP_TYPE_IND }, - { BT_ATT_OP_HANDLE_VAL_CONF, ATT_OP_TYPE_CONF }, + { BT_ATT_OP_HANDLE_NFY, ATT_OP_TYPE_NFY }, + { BT_ATT_OP_HANDLE_IND, ATT_OP_TYPE_IND }, + { BT_ATT_OP_HANDLE_CONF, ATT_OP_TYPE_CONF }, { } }; @@ -555,7 +555,7 @@ static bool can_write_data(struct io *io, void *user_data) #ifndef TIZEN_FEATURE_BLUEZ_MODIFY case ATT_OP_TYPE_CMD: #endif - case ATT_OP_TYPE_NOT: + case ATT_OP_TYPE_NFY: case ATT_OP_TYPE_CONF: case ATT_OP_TYPE_UNKNOWN: default: @@ -867,7 +867,7 @@ static void handle_conf(struct bt_att_chan *chan, uint8_t *pdu, ssize_t pdu_len) } if (op->callback) - op->callback(BT_ATT_OP_HANDLE_VAL_CONF, NULL, 0, op->user_data); + op->callback(BT_ATT_OP_HANDLE_NFY, NULL, 0, op->user_data); destroy_att_send_op(op); chan->pending_ind = NULL; @@ -1067,7 +1067,7 @@ static bool can_read_data(struct io *io, void *user_data) chan->in_req = true; /* fall through */ case ATT_OP_TYPE_CMD: - case ATT_OP_TYPE_NOT: + case ATT_OP_TYPE_NFY: case ATT_OP_TYPE_UNKNOWN: case ATT_OP_TYPE_IND: /* fall through */ @@ -1516,7 +1516,7 @@ unsigned int bt_att_send(struct bt_att *att, uint8_t opcode, result = queue_push_tail(att->ind_queue, op); break; case ATT_OP_TYPE_CMD: - case ATT_OP_TYPE_NOT: + case ATT_OP_TYPE_NFY: case ATT_OP_TYPE_UNKNOWN: case ATT_OP_TYPE_RSP: case ATT_OP_TYPE_CONF: diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c index 14e6a6a..95fb30a 100644 --- a/src/shared/gatt-client.c +++ b/src/shared/gatt-client.c @@ -98,7 +98,7 @@ struct bt_gatt_client { struct queue *notify_list; struct queue *notify_chrcs; int next_reg_id; - unsigned int disc_id, notify_id, ind_id; + unsigned int disc_id, nfy_id, nfy_mult_id, ind_id; /* * Handles of the GATT Service and the Service Changed characteristic @@ -2292,9 +2292,10 @@ done: return true; } -struct pdu_data { - const void *pdu; - uint16_t length; +struct value_data { + uint16_t handle; + uint16_t len; + const void *data; }; static void disable_ccc_callback(uint8_t opcode, const void *pdu, @@ -2349,25 +2350,18 @@ done: static void notify_handler(void *data, void *user_data) { struct notify_data *notify_data = data; - struct pdu_data *pdu_data = user_data; - uint16_t value_handle; - const uint8_t *value = NULL; - - value_handle = get_le16(pdu_data->pdu); + struct value_data *value_data = user_data; - if (notify_data->chrc->value_handle != value_handle) + if (notify_data->chrc->value_handle != value_data->handle) return; - if (pdu_data->length > 2) - value = pdu_data->pdu + 2; - /* * Even if the notify data has a pending ATT request to write to the * CCC, there is really no reason not to notify the handlers. */ if (notify_data->notify) - notify_data->notify(value_handle, value, pdu_data->length - 2, - notify_data->user_data); + notify_data->notify(value_data->handle, value_data->data, + value_data->len, notify_data->user_data); } static void notify_cb(struct bt_att_chan *chan, uint8_t opcode, @@ -2375,7 +2369,7 @@ static void notify_cb(struct bt_att_chan *chan, uint8_t opcode, void *user_data) { struct bt_gatt_client *client = user_data; - struct pdu_data pdu_data; + struct value_data data; #ifdef TIZEN_FEATURE_BLUEZ_MODIFY if (client->ready == false) { @@ -2383,11 +2377,11 @@ static void notify_cb(struct bt_att_chan *chan, uint8_t opcode, /* GATT caching is not supported yet. Once it supported, need to handle svc changed indication */ - if (opcode == BT_ATT_OP_HANDLE_VAL_IND && !client->parent + if (opcode == BT_ATT_OP_HANDLE_IND && !client->parent && !client->discovery_req) { util_debug(client->debug_callback, client->debug_data, "Service browsing is not started. No need handling svc changed indication before starting full scan"); - bt_att_send(client->att, BT_ATT_OP_HANDLE_VAL_CONF, NULL, 0, + bt_att_send(client->att, BT_ATT_OP_HANDLE_CONF, NULL, 0, NULL, NULL, NULL); return; } @@ -2419,23 +2413,46 @@ static void notify_cb(struct bt_att_chan *chan, uint8_t opcode, bt_gatt_client_ref(client); - memset(&pdu_data, 0, sizeof(pdu_data)); - pdu_data.pdu = pdu; - pdu_data.length = length; + memset(&data, 0, sizeof(data)); + + if (opcode == BT_ATT_OP_HANDLE_NFY_MULT) { + while (length >= 4) { + data.handle = get_le16(pdu); + length -= 2; + pdu += 2; + + data.len = get_le16(pdu); + length -= 2; + pdu += 2; - queue_foreach(client->notify_list, notify_handler, &pdu_data); + data.data = pdu; - if (opcode == BT_ATT_OP_HANDLE_VAL_IND && !client->parent){ + queue_foreach(client->notify_list, notify_handler, + &data); + + length -= data.len; + } + } else { + data.handle = get_le16(pdu); + length -= 2; + pdu += 2; + + data.len = length; + data.data = pdu; + queue_foreach(client->notify_list, notify_handler, &data); + } + + if (opcode == BT_ATT_OP_HANDLE_IND && !client->parent){ #ifdef TIZEN_FEATURE_BLUEZ_MODIFY if (!chan) - bt_att_send(client->att, BT_ATT_OP_HANDLE_VAL_CONF, NULL, 0, + bt_att_send(client->att, BT_ATT_OP_HANDLE_CONF, NULL, 0, NULL, NULL, NULL); else - bt_att_chan_send(chan, BT_ATT_OP_HANDLE_VAL_CONF, NULL, 0, + bt_att_chan_send(chan, BT_ATT_OP_HANDLE_CONF, NULL, 0, NULL, NULL, NULL); } #else - bt_att_chan_send(chan, BT_ATT_OP_HANDLE_VAL_CONF, NULL, 0, + bt_att_chan_send(chan, BT_ATT_OP_HANDLE_CONF, NULL, 0, NULL, NULL, NULL); } #endif @@ -2456,7 +2473,8 @@ static void bt_gatt_client_free(struct bt_gatt_client *client) if (client->att) { bt_att_unregister_disconnect(client->att, client->disc_id); - bt_att_unregister(client->att, client->notify_id); + bt_att_unregister(client->att, client->nfy_id); + bt_att_unregister(client->att, client->nfy_mult_id); bt_att_unregister(client->att, client->ind_id); bt_att_unref(client->att); } @@ -2534,12 +2552,17 @@ static struct bt_gatt_client *gatt_client_new(struct gatt_db *db, client->pending_noti = queue_new(); #endif - client->notify_id = bt_att_register(att, BT_ATT_OP_HANDLE_VAL_NOT, + client->nfy_id = bt_att_register(att, BT_ATT_OP_HANDLE_NFY, + notify_cb, client, NULL); + if (!client->nfy_id) + goto fail; + + client->nfy_mult_id = bt_att_register(att, BT_ATT_OP_HANDLE_NFY_MULT, notify_cb, client, NULL); - if (!client->notify_id) + if (!client->nfy_mult_id) goto fail; - client->ind_id = bt_att_register(att, BT_ATT_OP_HANDLE_VAL_IND, + client->ind_id = bt_att_register(att, BT_ATT_OP_HANDLE_IND, notify_cb, client, NULL); if (!client->ind_id) goto fail; diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c index 04ac455..048b28e 100644 --- a/src/shared/gatt-server.c +++ b/src/shared/gatt-server.c @@ -1798,7 +1798,7 @@ bool bt_gatt_server_send_notification(struct bt_gatt_server *server, put_le16(handle, pdu); memcpy(pdu + 2, value, pdu_len - 2); - result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_VAL_NOT, pdu, + result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_NFY, pdu, pdu_len, NULL, NULL, NULL); free(pdu); @@ -1859,7 +1859,7 @@ bool bt_gatt_server_send_indication(struct bt_gatt_server *server, put_le16(handle, pdu); memcpy(pdu + 2, value, pdu_len - 2); - result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_VAL_IND, pdu, + result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_IND, pdu, pdu_len, conf_cb, data, destroy_ind_data); if (!result) -- 2.7.4