summaryrefslogtreecommitdiff
path: root/src/shared/gatt-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/gatt-server.c')
-rw-r--r--src/shared/gatt-server.c77
1 files changed, 65 insertions, 12 deletions
diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index 8e81d6e0e..7e5d652e4 100644
--- a/src/shared/gatt-server.c
+++ b/src/shared/gatt-server.c
@@ -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;
@@ -120,6 +130,8 @@ struct bt_gatt_server {
bt_gatt_server_authorize_cb_t authorize;
void *authorize_data;
+
+ struct nfy_mult_data *nfy_mult;
};
static void bt_gatt_server_free(struct bt_gatt_server *server)
@@ -1726,28 +1738,69 @@ 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;
- put_le16(handle, pdu);
- memcpy(pdu + 2, value, pdu_len - 2);
+ if (!data) {
+ data = new0(struct nfy_mult_data, 1);
+ data->len = bt_att_get_mtu(server->att) - 1;
+ data->pdu = malloc(data->len);
+ }
- result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_NFY, pdu,
- pdu_len, NULL, NULL, NULL);
- free(pdu);
+ put_le16(handle, data->pdu + data->offset);
+ data->offset += 2;
+
+ 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;
}