shared/gatt: Add support for Handle Value Multiple Notifications
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Thu, 6 Jun 2019 06:22:56 +0000 (09:22 +0300)
committerAyush Garg <ayush.garg@samsung.com>
Mon, 12 Apr 2021 09:00:48 +0000 (14:30 +0530)
Handle Value Multiple Notification can be used to notify multiple
values at once.

Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
src/shared/att-types.h
src/shared/att.c
src/shared/gatt-client.c
src/shared/gatt-server.c

index fce3d81..48d2985 100755 (executable)
 #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 */
index 9a05c98..adcd7ad 100755 (executable)
@@ -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:
index 14e6a6a..95fb30a 100644 (file)
@@ -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;
index 04ac455..048b28e 100644 (file)
@@ -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)