gatt: Add support for Notify Multiple
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 6 Sep 2019 11:09:37 +0000 (14:09 +0300)
committerAyush Garg <ayush.garg@samsung.com>
Mon, 12 Apr 2021 09:00:48 +0000 (14:30 +0530)
This adds support for Notify Multiple procedure marking its bit as
supported in the Client Features.

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

index bd51f50..d66d743 100644 (file)
@@ -1169,7 +1169,7 @@ static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib,
        if (ccc_cb->callback) {
                struct pending_op *op;
 
-               op = pending_ccc_new(att, attrib, get_le16(value),
+               op = pending_ccc_new(att, attrib, val,
                                        bt_att_get_link_type(att));
                if (!op) {
                        ecode = BT_ATT_ERROR_UNLIKELY;
@@ -1309,7 +1309,8 @@ static void cli_feat_write_cb(struct gatt_db_attribute *attrib,
        struct btd_gatt_database *database = user_data;
        struct device_state *state;
        uint8_t bits[] = { BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING,
-                               BT_GATT_CHRC_CLI_FEAT_EATT };
+                               BT_GATT_CHRC_CLI_FEAT_EATT,
+                               BT_GATT_CHRC_CLI_FEAT_NFY_MULTI };
        uint8_t ecode = 0;
        unsigned int i;
 
@@ -1615,7 +1616,8 @@ static void send_notification_indication_to_device(void *data, void *user_data)
                bt_gatt_server_send_notification(
                                        btd_device_get_gatt_server(device),
                                        notify_indicate->handle, notify_indicate->value,
-                                       notify_indicate->len);
+                                       notify_indicate->len,device_state->cli_feat[0] &
+                                       BT_GATT_CHRC_CLI_FEAT_NFY_MULTI);
                /* In case of Notification, send response to application
                 * as remote device do not respond for notification */
                conf_cb_tizen(confirm);
@@ -1730,7 +1732,8 @@ static void send_notification_to_device(void *data, void *user_data)
                DBG("GATT server sending notification");
                bt_gatt_server_send_notification(server,
                                        notify->handle, notify->value,
-                                       notify->len);
+                                       notify->len, device_state->cli_feat[0] &
+                                       BT_GATT_CHRC_CLI_FEAT_NFY_MULTI);
                return;
        }
 
index adcd7ad..072da6f 100755 (executable)
@@ -152,6 +152,7 @@ static const struct {
        { BT_ATT_OP_EXEC_WRITE_REQ,             ATT_OP_TYPE_REQ },
        { BT_ATT_OP_EXEC_WRITE_RSP,             ATT_OP_TYPE_RSP },
        { BT_ATT_OP_HANDLE_NFY,                 ATT_OP_TYPE_NFY },
+       { BT_ATT_OP_HANDLE_NFY_MULT,            ATT_OP_TYPE_NFY },
        { BT_ATT_OP_HANDLE_IND,                 ATT_OP_TYPE_IND },
        { BT_ATT_OP_HANDLE_CONF,                ATT_OP_TYPE_CONF },
        { }
@@ -867,7 +868,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_NFY, NULL, 0, op->user_data);
+               op->callback(BT_ATT_OP_HANDLE_CONF, NULL, 0, op->user_data);
 
        destroy_att_send_op(op);
        chan->pending_ind = NULL;
index 95fb30a..9989726 100644 (file)
@@ -2171,6 +2171,8 @@ static void write_client_features(struct bt_gatt_client *client)
                        client->features |= BT_GATT_CHRC_CLI_FEAT_EATT;
        }
 
+       client->features |= BT_GATT_CHRC_CLI_FEAT_NFY_MULTI;
+
        util_debug(client->debug_callback, client->debug_data,
                        "Writing Client Features 0x%02x", client->features);
 
index 048b28e..07b2080 100644 (file)
@@ -36,6 +36,7 @@
 #include "src/shared/gatt-server.h"
 #include "src/shared/gatt-helpers.h"
 #include "src/shared/util.h"
+#include "src/shared/timeout.h"
 
 #ifndef MAX
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -51,6 +52,8 @@
  */
 #define DEFAULT_MAX_PREP_QUEUE_LEN 30
 
+#define NFY_MULT_TIMEOUT 10
+
 struct async_read_op {
        struct bt_att_chan *chan;
        struct bt_gatt_server *server;
@@ -86,6 +89,13 @@ static void prep_write_data_destroy(void *user_data)
        free(data);
 }
 
+struct nfy_mult_data {
+       unsigned int id;
+       uint8_t *pdu;
+       uint16_t offset;
+       uint16_t len;
+};
+
 struct bt_gatt_server {
        struct gatt_db *db;
        struct bt_att *att;
@@ -121,6 +131,8 @@ struct bt_gatt_server {
        bt_gatt_server_authorize_cb_t authorize;
        void *authorize_data;
 
+       struct nfy_mult_data *nfy_mult;
+
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
        bt_gatt_server_mtu_changed_callback_t mtu_chngd_callback;
        bt_gatt_server_destroy_func_t mtu_chngd_destroy;
@@ -1779,28 +1791,68 @@ bool bt_gatt_server_set_debug(struct bt_gatt_server *server,
        return true;
 }
 
+static bool notify_multiple(void *user_data)
+{
+       struct bt_gatt_server *server = user_data;
+
+       bt_att_send(server->att, BT_ATT_OP_HANDLE_NFY_MULT,
+                       server->nfy_mult->pdu, server->nfy_mult->offset, NULL,
+                       NULL, NULL);
+
+       free(server->nfy_mult->pdu);
+       free(server->nfy_mult);
+       server->nfy_mult = NULL;
+
+       return false;
+}
+
 bool bt_gatt_server_send_notification(struct bt_gatt_server *server,
                                        uint16_t handle, const uint8_t *value,
-                                       uint16_t length)
+                                       uint16_t length, bool multiple)
 {
-       uint16_t pdu_len;
-       uint8_t *pdu;
+       struct nfy_mult_data *data = NULL;
        bool result;
 
        if (!server || (length && !value))
                return false;
 
-       pdu_len = MIN(bt_att_get_mtu(server->att) - 1, length + 2);
-       pdu = malloc(pdu_len);
-       if (!pdu)
-               return false;
+       if (multiple)
+               data = server->nfy_mult;
+       if (!data) {
+               data = new0(struct nfy_mult_data, 1);
+               data->len = bt_att_get_mtu(server->att) - 1;
+               data->pdu = malloc(data->len);
+       }
 
-       put_le16(handle, pdu);
-       memcpy(pdu + 2, value, pdu_len - 2);
+       put_le16(handle, data->pdu + data->offset);
+       data->offset += 2;
 
-       result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_NFY, pdu,
-                                               pdu_len, NULL, NULL, NULL);
-       free(pdu);
+       length = MIN(data->len - data->offset, length);
+
+       if (multiple) {
+               put_le16(length, data->pdu + data->offset);
+               data->offset += 2;
+       }
+
+       memcpy(data->pdu + data->offset, value, length);
+       data->offset += length;
+
+       if (multiple) {
+               if (!server->nfy_mult)
+                       server->nfy_mult = data;
+
+               if (!server->nfy_mult->id)
+                       server->nfy_mult->id = timeout_add(NFY_MULT_TIMEOUT,
+                                                  notify_multiple, server,
+                                                  NULL);
+
+               return true;
+       }
+
+       result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_NFY,
+                               data->pdu, data->offset, NULL, NULL, NULL);
+       free(data->pdu);
+       free(data);
 
        return result;
 }
index 7d83669..401ab09 100755 (executable)
@@ -57,7 +57,7 @@ bool bt_gatt_server_set_authorize(struct bt_gatt_server *server,
 
 bool bt_gatt_server_send_notification(struct bt_gatt_server *server,
                                        uint16_t handle, const uint8_t *value,
-                                       uint16_t length);
+                                       uint16_t length, bool multiple);
 
 bool bt_gatt_server_send_indication(struct bt_gatt_server *server,
                                        uint16_t handle, const uint8_t *value,
index bc32789..4a70a04 100755 (executable)
@@ -304,7 +304,7 @@ static bool hr_msrmt_cb(void *user_data)
 
        bt_gatt_server_send_notification(server->gatt,
                                                server->hr_msrmt_handle,
-                                               pdu, len);
+                                               pdu, len, false);
 
 
        cur_ee = server->hr_energy_expended;
@@ -830,7 +830,7 @@ static void cmd_notify(struct server *server, char *cmd_str)
                                                        conf_cb, NULL, NULL))
                        printf("Failed to initiate indication\n");
        } else if (!bt_gatt_server_send_notification(server->gatt, handle,
-                                                               value, length))
+                                                               value, length, false))
                printf("Failed to initiate notification\n");
 
 done:
index 440ea03..da5acc9 100755 (executable)
@@ -2435,7 +2435,7 @@ static void test_server_notification(struct context *context)
        const struct test_step *step = context->data->step;
 
        bt_gatt_server_send_notification(context->server, step->handle,
-                                               step->value, step->length);
+                                               step->value, step->length, false);
 }
 
 static const struct test_step test_notification_server_1 = {