Bluetooth: Add bt_gatt_notify
bt_gatt_notify can be used to send ATT notifications: < ACL Data TX: Handle 3585 flags 0x00 dlen 8 ATT: Handle Value Notification (0x1b) len 3 Handle: 0x0010 Data: 64 Change-Id: I908f10f9e60dc7cef221e4b27c3b6e49e7b0cfc9 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
8508bfb2b1
commit
e4e6f4dbe9
2 changed files with 91 additions and 0 deletions
|
@ -378,4 +378,16 @@ int bt_gatt_attr_write_ccc(const bt_addr_le_t *peer,
|
|||
.user_data = _value, \
|
||||
}
|
||||
|
||||
/** @brief Notify attribute value change
|
||||
*
|
||||
* Send notification of attribute value change.
|
||||
* Note: This function should only be called if CCC is declared with
|
||||
* BT_GATT_CCC otherwise it cannot find a valid peer configuration.
|
||||
*
|
||||
* @param handle attribute handle
|
||||
* @param value attribute value
|
||||
* @param len attribute value length
|
||||
*/
|
||||
void bt_gatt_notify(uint16_t handle, const void *data, size_t len);
|
||||
|
||||
#endif /* __BT_GATT_H */
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
#include <bluetooth/gatt.h>
|
||||
|
||||
#include "hci_core.h"
|
||||
#include "conn.h"
|
||||
#include "l2cap.h"
|
||||
#include "att.h"
|
||||
|
||||
#if !defined(CONFIG_BLUETOOTH_DEBUG_GATT)
|
||||
#undef BT_DBG
|
||||
|
@ -265,3 +268,79 @@ int bt_gatt_attr_write_ccc(const bt_addr_le_t *peer,
|
|||
|
||||
return len;
|
||||
}
|
||||
|
||||
struct notify_data {
|
||||
uint8_t handle;
|
||||
const void *data;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static uint8_t notify_cb(const struct bt_gatt_attr *attr, void *user_data)
|
||||
{
|
||||
struct notify_data *data = user_data;
|
||||
struct bt_uuid uuid = { .type = BT_UUID_16, .u16 = BT_UUID_GATT_CCC };
|
||||
struct bt_uuid chrc = { .type = BT_UUID_16, .u16 = BT_UUID_GATT_CHRC };
|
||||
struct _bt_gatt_ccc *ccc;
|
||||
size_t i;
|
||||
|
||||
if (bt_uuid_cmp(attr->uuid, &uuid)) {
|
||||
/* Stop if we reach the next characteristic */
|
||||
if (!bt_uuid_cmp(attr->uuid, &chrc))
|
||||
return BT_GATT_ITER_STOP;
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
/* Check attribute user_data must be of type struct _bt_gatt_ccc */
|
||||
if (attr->write != bt_gatt_attr_write_ccc) {
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
ccc = attr->user_data;
|
||||
|
||||
/* Notify all peers configured */
|
||||
for (i = 0; i < ccc->cfg_len; i++) {
|
||||
struct bt_conn *conn;
|
||||
struct bt_buf *buf;
|
||||
struct bt_att_notify *nfy;
|
||||
|
||||
conn = bt_conn_lookup_addr_le(&ccc->cfg[i].peer);
|
||||
if (!conn) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buf = bt_att_create_pdu(conn, BT_ATT_OP_NOTIFY,
|
||||
sizeof(*nfy) + data->len);
|
||||
if (!buf) {
|
||||
BT_WARN("No buffer available to send notification");
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
/* TODO: Handle indications */
|
||||
if (ccc->value != BT_GATT_CCC_NOTIFY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BT_DBG("conn %p handle %u\n", conn, data->handle);
|
||||
|
||||
nfy = bt_buf_add(buf, sizeof(*nfy));
|
||||
nfy->handle = sys_cpu_to_le16(data->handle);
|
||||
|
||||
bt_buf_add(buf, data->len);
|
||||
memcpy(nfy->value, data->data, data->len);
|
||||
|
||||
bt_l2cap_send(conn, BT_L2CAP_CID_ATT, buf);
|
||||
}
|
||||
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
void bt_gatt_notify(uint16_t handle, const void *data, size_t len)
|
||||
{
|
||||
struct notify_data nfy;
|
||||
|
||||
nfy.handle = handle;
|
||||
nfy.data = data;
|
||||
nfy.len = len;
|
||||
|
||||
bt_gatt_foreach_attr(handle, 0xffff, notify_cb, &nfy);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue