This is an automated email from the ASF dual-hosted git repository.
sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
The following commit(s) were added to refs/heads/master by this push:
new 684406a3e nimble/host: Rework ble_gatts_notify_multiple_custom
684406a3e is described below
commit 684406a3eaf42ce634e228bf202ebd4bd8d42904
Author: Szymon Janc <[email protected]>
AuthorDate: Mon May 11 11:00:52 2026 +0200
nimble/host: Rework ble_gatts_notify_multiple_custom
Simplify ble_gatts_notify_multiple_custom implementation:
- reject if peer doesn't support it (app shall check it)
- fail if doesn't git in single ATT packet
- fix missing cleanups on error
- fix missing endianess convertions
ble_gatts_notify_multiple() is now very thin wrapper on top of
ble_gatts_notify_multiple_custom().
---
nimble/host/include/host/ble_gatt.h | 6 --
nimble/host/src/ble_att_clt.c | 3 +
nimble/host/src/ble_gattc.c | 130 ++++++++++++++----------------------
3 files changed, 53 insertions(+), 86 deletions(-)
diff --git a/nimble/host/include/host/ble_gatt.h
b/nimble/host/include/host/ble_gatt.h
index e74ba9e1a..df9c36bbe 100644
--- a/nimble/host/include/host/ble_gatt.h
+++ b/nimble/host/include/host/ble_gatt.h
@@ -692,9 +692,6 @@ int ble_gatts_notify_custom(uint16_t conn_handle, uint16_t
att_handle,
* handle-value pair fits into PDU, or only one characteristic remains in the
* list, regular characteristic notification is sent.
*
- * If GATT client doesn't support receiving multiple handle notifications,
- * this will use GATT notification for each characteristic, separately.
- *
* If value of characteristic is not specified it will be read from local
* GATT database.
*
@@ -733,9 +730,6 @@ int ble_gatts_notify(uint16_t conn_handle, uint16_t
chr_val_handle);
* handle-value pair fits into PDU, or only one characteristic remains in the
* list, regular characteristic notification is sent.
*
- * If GATT client doesn't support receiving multiple handle notifications,
- * this will use GATT notification for each characteristic, separately.
- *
* @param conn_handle The connection over which to execute the
* procedure.
* @param num_handles The number of entries in the "chr_val_handles"
diff --git a/nimble/host/src/ble_att_clt.c b/nimble/host/src/ble_att_clt.c
index ddd7fc8a9..43cb0610e 100644
--- a/nimble/host/src/ble_att_clt.c
+++ b/nimble/host/src/ble_att_clt.c
@@ -1022,6 +1022,9 @@ ble_att_clt_tx_notify_mult(uint16_t conn_handle, struct
os_mbuf *txom)
ble_eatt_release_chan(conn_handle, BLE_GATT_OP_DUMMY);
}
+ return rc;
+
err:
+ os_mbuf_free_chain(txom);
return rc;
}
diff --git a/nimble/host/src/ble_gattc.c b/nimble/host/src/ble_gattc.c
index 061c783e5..7c0e62aa4 100644
--- a/nimble/host/src/ble_gattc.c
+++ b/nimble/host/src/ble_gattc.c
@@ -4437,85 +4437,78 @@ ble_gatts_notify_multiple_custom(uint16_t conn_handle,
#endif
int rc;
- size_t i = 0;
- uint16_t cur_chr_cnt = 0;
- /* mtu = MTU - 1 octet (OP code) */
- uint16_t mtu = ble_att_mtu(conn_handle) - 1;
+ size_t i;
struct os_mbuf *txom;
- struct ble_hs_conn *conn;
+ uint16_t le16;
+ uint8_t supported;
+ uint16_t total = 1; /* opcode */
- txom = ble_hs_mbuf_att_pkt();
- if (txom == NULL) {
- return BLE_HS_ENOMEM;
+ /* validate handles sanity */
+ for (i = 0; i < chr_count; i++) {
+ if (tuples->handle == 0) {
+ rc = BLE_HS_EINVAL;
+ goto err;
+ }
}
- conn = ble_hs_conn_find(conn_handle);
- if (conn == NULL) {
- return BLE_HS_ENOTCONN;
+ if (chr_count < 2) {
+ rc = BLE_HS_EINVAL;
+ goto err;
+ }
+
+ rc = ble_gatts_peer_cl_sup_feat_get(conn_handle, &supported,
sizeof(supported));
+ if (rc) {
+ goto err;
+ }
+
+ if ((supported & 0x04) == 0) {
+ rc = BLE_HS_EREJECT;
+ goto err;
}
/* Read missing values */
for (i = 0; i < chr_count; i++) {
- if (tuples->handle == 0) {
- rc = BLE_HS_EINVAL;
- goto done;
- }
if (tuples[i].value == NULL) {
rc = ble_att_svr_read_local(tuples[i].handle, &tuples[i].value);
if (rc != 0) {
- goto done;
+ goto err;
}
}
}
- /* If peer does not support fall back to multiple single value
- * Notifications */
- if ((conn->bhc_gatt_svr.peer_cl_sup_feat[0] & 0x04) == 0) {
- for (i = 0; i < chr_count; i++) {
- rc = ble_att_clt_tx_notify(conn_handle, tuples[chr_count].handle,
- tuples[chr_count].value);
- if (rc != 0) {
- goto done;
- }
- }
+ /* check if this fits into MTU */
+ for (i = 0; i < chr_count; i++) {
+ total += sizeof(uint16_t); /* handle */
+ total += sizeof(uint16_t); /* length */
+ total += os_mbuf_len(tuples[i].value);
}
- for (i = 0; i < chr_count; i++) {
- if (txom->om_len + tuples[i].value->om_len > mtu && cur_chr_cnt < 2) {
- rc = ble_att_clt_tx_notify(conn_handle, tuples[i].handle,
- tuples[i].value);
- if (rc != 0) {
- goto done;
- }
- continue;
- } else if (txom->om_len + tuples[i].value->om_len > mtu) {
- rc = ble_att_clt_tx_notify_mult(conn_handle, txom);
- if (rc != 0) {
- goto done;
- }
- cur_chr_cnt = 0;
- /* buffer was consumed, allocate new one */
- txom = ble_hs_mbuf_att_pkt();
- if (txom == NULL) {
- return BLE_HS_ENOMEM;
- }
- }
+ if (total > ble_att_mtu(conn_handle)) {
+ rc = BLE_HS_EMSGSIZE;
+ goto err;
+ }
- os_mbuf_append(txom, &tuples[i].handle, sizeof(uint16_t));
- os_mbuf_append(txom, &tuples[i].value->om_len,
- sizeof(uint16_t));
+ txom = ble_hs_mbuf_att_pkt();
+ if (txom == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < chr_count; i++) {
+ le16 = htole16(tuples[i].handle);
+ os_mbuf_append(txom, &le16, sizeof(uint16_t));
+ le16 = htole16(tuples[i].value->om_len);
+ os_mbuf_append(txom, &le16, sizeof(uint16_t));
os_mbuf_concat(txom, tuples[i].value);
- cur_chr_cnt++;
}
- if (cur_chr_cnt == 1) {
- rc = ble_att_clt_tx_notify(conn_handle, tuples[chr_count].handle,
- tuples[chr_count].value);
- } else {
- rc = ble_att_clt_tx_notify_mult(conn_handle, txom);
+ return ble_att_clt_tx_notify_mult(conn_handle, txom);
+
+err:
+ for (i = 0; i < chr_count; i++) {
+ os_mbuf_free_chain(tuples[i].value);
}
-done:
return rc;
}
@@ -4527,38 +4520,15 @@ ble_gatts_notify_multiple(uint16_t conn_handle,
#if !MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE)
return BLE_HS_ENOTSUP;
#endif
- int rc;
size_t i;
struct ble_gatt_notif tuples[num_handles];
- struct ble_hs_conn *conn;
-
- BLE_HS_LOG_DEBUG("conn_handle %d\n", conn_handle);
- conn = ble_hs_conn_find(conn_handle);
- if (conn == NULL) {
- return BLE_HS_ENOTCONN;
- }
-
- /** Skip sending to client that doesn't support this feature */
- BLE_HS_LOG_DEBUG("ble_gatts_notify_multiple: peer_cl_sup_feat %d\n",
- conn->bhc_gatt_svr.peer_cl_sup_feat[0]);
- if ((conn->bhc_gatt_svr.peer_cl_sup_feat[0] & 0x04) == 0) {
- for (i = 0; i < num_handles; i++) {
- rc = ble_gatts_notify(conn_handle, chr_val_handles[i]);
- if (rc != 0) {
- return rc;
- }
- }
- return 0;
- }
for (i = 0; i < num_handles; i++) {
tuples[i].handle = chr_val_handles[i];
tuples[i].value = NULL;
- BLE_HS_LOG(DEBUG, "handle 0x%02x\n", tuples[i].handle);
}
- rc = ble_gatts_notify_multiple_custom(conn_handle, num_handles, tuples);
- return rc;
+ return ble_gatts_notify_multiple_custom(conn_handle, num_handles, tuples);
}
/*****************************************************************************