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);
 }
 
 /*****************************************************************************

Reply via email to