KKopyscinski commented on code in PR #1426:
URL: https://github.com/apache/mynewt-nimble/pull/1426#discussion_r1283117573
##########
nimble/host/include/host/ble_gatt.h:
##########
@@ -473,6 +479,22 @@ int ble_gattc_write_reliable(uint16_t conn_handle,
int ble_gatts_notify_custom(uint16_t conn_handle, uint16_t att_handle,
struct os_mbuf *om);
+/**
+ * Sends multiple characteristic notifications on the specified
+ * attribute handles. This function consumes the mbuf of the
+ * notification value after sending notification.
+ *
+ * @param conn_handle The connection over which to execute the
+ * procedure.
+ * @param tuples The list of attribute handles and notification
+ * value tuples.
+ * @param num_tuples The number of notifications to send.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int ble_gatts_multi_notify_custom(uint16_t conn_handle,
+ struct ble_gatt_hv * tuples, uint16_t
num_tuples);
Review Comment:
adjust name after change and codestyle
```suggestion
struct ble_gatt_mult_notif_entry *tuples,
uint16_t num_tuples);
```
##########
nimble/host/include/host/ble_gatt.h:
##########
@@ -79,6 +79,12 @@ struct ble_hs_cfg;
#define BLE_GATT_SVC_TYPE_PRIMARY 1
#define BLE_GATT_SVC_TYPE_SECONDARY 2
+/*** @server. */
+struct ble_gatt_hv {
+ uint16_t handle;
+ struct os_mbuf* value;
Review Comment:
codestyle
```suggestion
struct os_mbuf *value;
```
##########
nimble/host/src/ble_gattc.c:
##########
@@ -4212,6 +4223,131 @@ ble_gatts_notify_custom(uint16_t conn_handle, uint16_t
chr_val_handle,
return rc;
}
+int
+ble_gatts_multi_notify_custom(uint16_t conn_handle,
+ struct ble_gatt_hv * tuples, uint16_t num_tuples)
+{
+#if !MYNEWT_VAL(BLE_GATT_MULTI_NOTIFY)
+ return BLE_HS_ENOTSUP;
+#endif
+
+ int i;
+ int rc;
+ uint16_t mtu;
+ uint16_t pdu_size;
+ int split_at;
+ struct os_mbuf *om = NULL;
+
+ STATS_INC(ble_gattc_stats, multi_notify);
+ ble_gattc_log_multi_notify(tuples, num_tuples);
+
+ for (i = 0; i < num_tuples; i++) {
+ if (tuples[i].value == NULL) {
+ /* No custom attribute data; read the value from the specified
+ * attribute
+ */
+ tuples[i].value = ble_hs_mbuf_att_pkt();
+ if (tuples[i].value == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE,
+ tuples[i].handle, 0, tuples[i].value,
NULL);
+ if (rc != 0) {
+ /* Fatal error; application disallowed attribute read. */
+ rc = BLE_HS_EAPP;
+ goto done;
+ }
+ }
+ }
+
+ mtu = ble_att_mtu(conn_handle);
+ pdu_size = sizeof(uint8_t); /* Opcode */
+ split_at = 0;
+
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ /* The notification will need to be split */
+ if (i == split_at) {
+ /* Single notification too large for server,
+ * cannot send notify without truncating.
+ */
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ split_at = i;
+ /* Reinitialize loop */
+ i--;
+ pdu_size = sizeof(uint8_t);
+ }
+ }
+
+ pdu_size = sizeof(uint8_t);
+ split_at = 0;
Review Comment:
```suggestion
```
not needed
##########
nimble/host/src/ble_gattc.c:
##########
@@ -4212,6 +4223,131 @@ ble_gatts_notify_custom(uint16_t conn_handle, uint16_t
chr_val_handle,
return rc;
}
+int
+ble_gatts_multi_notify_custom(uint16_t conn_handle,
+ struct ble_gatt_hv * tuples, uint16_t num_tuples)
+{
+#if !MYNEWT_VAL(BLE_GATT_MULTI_NOTIFY)
+ return BLE_HS_ENOTSUP;
+#endif
+
+ int i;
+ int rc;
+ uint16_t mtu;
+ uint16_t pdu_size;
+ int split_at;
+ struct os_mbuf *om = NULL;
+
+ STATS_INC(ble_gattc_stats, multi_notify);
+ ble_gattc_log_multi_notify(tuples, num_tuples);
+
+ for (i = 0; i < num_tuples; i++) {
+ if (tuples[i].value == NULL) {
+ /* No custom attribute data; read the value from the specified
+ * attribute
+ */
+ tuples[i].value = ble_hs_mbuf_att_pkt();
+ if (tuples[i].value == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE,
+ tuples[i].handle, 0, tuples[i].value,
NULL);
+ if (rc != 0) {
+ /* Fatal error; application disallowed attribute read. */
+ rc = BLE_HS_EAPP;
+ goto done;
+ }
+ }
+ }
+
+ mtu = ble_att_mtu(conn_handle);
+ pdu_size = sizeof(uint8_t); /* Opcode */
+ split_at = 0;
+
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ /* The notification will need to be split */
+ if (i == split_at) {
+ /* Single notification too large for server,
+ * cannot send notify without truncating.
+ */
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ split_at = i;
+ /* Reinitialize loop */
+ i--;
+ pdu_size = sizeof(uint8_t);
+ }
+ }
+
+ pdu_size = sizeof(uint8_t);
+ split_at = 0;
+ om = ble_hs_mbuf_att_pkt();
+ if(om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ rc = ble_att_clt_tx_multi_notify(conn_handle, om);
+ if (rc != 0) {
+ goto done;
+ }
+ split_at = i;
+ i--;
+ pdu_size = sizeof(uint8_t);
+ om = ble_hs_mbuf_att_pkt();
+ if(om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ continue;
+ }
+ /* Handle */
+ rc = os_mbuf_copyinto(om, OS_MBUF_PKTLEN(om),
+ &tuples[i].handle, sizeof tuples[i].handle);
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ os_mbuf_free_chain(om);
+ goto done;
+ }
+ /* Length */
+ rc = os_mbuf_copyinto(om, OS_MBUF_PKTLEN(om),
Review Comment:
ditto (`os_mbuf_append`)
##########
nimble/host/src/ble_gattc.c:
##########
@@ -4212,6 +4223,131 @@ ble_gatts_notify_custom(uint16_t conn_handle, uint16_t
chr_val_handle,
return rc;
}
+int
+ble_gatts_multi_notify_custom(uint16_t conn_handle,
+ struct ble_gatt_hv * tuples, uint16_t num_tuples)
+{
+#if !MYNEWT_VAL(BLE_GATT_MULTI_NOTIFY)
+ return BLE_HS_ENOTSUP;
+#endif
+
+ int i;
+ int rc;
+ uint16_t mtu;
+ uint16_t pdu_size;
+ int split_at;
+ struct os_mbuf *om = NULL;
+
+ STATS_INC(ble_gattc_stats, multi_notify);
+ ble_gattc_log_multi_notify(tuples, num_tuples);
+
+ for (i = 0; i < num_tuples; i++) {
+ if (tuples[i].value == NULL) {
+ /* No custom attribute data; read the value from the specified
+ * attribute
+ */
+ tuples[i].value = ble_hs_mbuf_att_pkt();
+ if (tuples[i].value == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE,
+ tuples[i].handle, 0, tuples[i].value,
NULL);
+ if (rc != 0) {
+ /* Fatal error; application disallowed attribute read. */
+ rc = BLE_HS_EAPP;
+ goto done;
+ }
+ }
+ }
+
+ mtu = ble_att_mtu(conn_handle);
+ pdu_size = sizeof(uint8_t); /* Opcode */
+ split_at = 0;
+
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ /* The notification will need to be split */
+ if (i == split_at) {
+ /* Single notification too large for server,
+ * cannot send notify without truncating.
+ */
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ split_at = i;
+ /* Reinitialize loop */
+ i--;
+ pdu_size = sizeof(uint8_t);
+ }
+ }
+
+ pdu_size = sizeof(uint8_t);
+ split_at = 0;
+ om = ble_hs_mbuf_att_pkt();
+ if(om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ rc = ble_att_clt_tx_multi_notify(conn_handle, om);
+ if (rc != 0) {
+ goto done;
+ }
+ split_at = i;
+ i--;
+ pdu_size = sizeof(uint8_t);
+ om = ble_hs_mbuf_att_pkt();
+ if(om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ continue;
+ }
+ /* Handle */
+ rc = os_mbuf_copyinto(om, OS_MBUF_PKTLEN(om),
+ &tuples[i].handle, sizeof tuples[i].handle);
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ os_mbuf_free_chain(om);
+ goto done;
+ }
+ /* Length */
+ rc = os_mbuf_copyinto(om, OS_MBUF_PKTLEN(om),
+ &(OS_MBUF_PKTLEN(tuples[i].value)),
+ sizeof(OS_MBUF_PKTLEN(tuples[i].value)));
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ os_mbuf_free_chain(om);
+ goto done;
+ }
+ /* Value */
+ rc = os_mbuf_appendfrom(om, tuples[i].value,
Review Comment:
offset is 0, so `os_mbuf_append` can be used afaik
##########
nimble/host/src/ble_gattc.c:
##########
@@ -4212,6 +4223,131 @@ ble_gatts_notify_custom(uint16_t conn_handle, uint16_t
chr_val_handle,
return rc;
}
+int
+ble_gatts_multi_notify_custom(uint16_t conn_handle,
+ struct ble_gatt_hv * tuples, uint16_t num_tuples)
+{
+#if !MYNEWT_VAL(BLE_GATT_MULTI_NOTIFY)
+ return BLE_HS_ENOTSUP;
+#endif
+
+ int i;
+ int rc;
+ uint16_t mtu;
+ uint16_t pdu_size;
+ int split_at;
+ struct os_mbuf *om = NULL;
+
+ STATS_INC(ble_gattc_stats, multi_notify);
+ ble_gattc_log_multi_notify(tuples, num_tuples);
+
+ for (i = 0; i < num_tuples; i++) {
+ if (tuples[i].value == NULL) {
+ /* No custom attribute data; read the value from the specified
+ * attribute
+ */
+ tuples[i].value = ble_hs_mbuf_att_pkt();
+ if (tuples[i].value == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE,
+ tuples[i].handle, 0, tuples[i].value,
NULL);
+ if (rc != 0) {
Review Comment:
This is neither fatal error nor only caused by missing permissions
(permissions are not checked for self-reads) Maybe just log error
```suggestion
BLE_HS_LOG(ERROR, "Attribute read failed (err=0x%02x), rc");
```
and return rc as is: for example `handle` was invalid, and `BLE_HS_EAPP`
doesn't make sense then
##########
nimble/host/src/ble_gattc.c:
##########
@@ -4212,6 +4223,131 @@ ble_gatts_notify_custom(uint16_t conn_handle, uint16_t
chr_val_handle,
return rc;
}
+int
+ble_gatts_multi_notify_custom(uint16_t conn_handle,
+ struct ble_gatt_hv * tuples, uint16_t num_tuples)
+{
+#if !MYNEWT_VAL(BLE_GATT_MULTI_NOTIFY)
+ return BLE_HS_ENOTSUP;
+#endif
+
+ int i;
+ int rc;
+ uint16_t mtu;
+ uint16_t pdu_size;
+ int split_at;
+ struct os_mbuf *om = NULL;
+
+ STATS_INC(ble_gattc_stats, multi_notify);
+ ble_gattc_log_multi_notify(tuples, num_tuples);
+
+ for (i = 0; i < num_tuples; i++) {
+ if (tuples[i].value == NULL) {
+ /* No custom attribute data; read the value from the specified
+ * attribute
+ */
+ tuples[i].value = ble_hs_mbuf_att_pkt();
+ if (tuples[i].value == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE,
+ tuples[i].handle, 0, tuples[i].value,
NULL);
+ if (rc != 0) {
+ /* Fatal error; application disallowed attribute read. */
+ rc = BLE_HS_EAPP;
+ goto done;
+ }
+ }
+ }
+
+ mtu = ble_att_mtu(conn_handle);
+ pdu_size = sizeof(uint8_t); /* Opcode */
+ split_at = 0;
+
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ /* The notification will need to be split */
+ if (i == split_at) {
+ /* Single notification too large for server,
+ * cannot send notify without truncating.
+ */
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ split_at = i;
+ /* Reinitialize loop */
+ i--;
+ pdu_size = sizeof(uint8_t);
+ }
+ }
+
+ pdu_size = sizeof(uint8_t);
+ split_at = 0;
+ om = ble_hs_mbuf_att_pkt();
+ if(om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ rc = ble_att_clt_tx_multi_notify(conn_handle, om);
+ if (rc != 0) {
+ goto done;
+ }
+ split_at = i;
+ i--;
+ pdu_size = sizeof(uint8_t);
+ om = ble_hs_mbuf_att_pkt();
+ if(om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ continue;
+ }
+ /* Handle */
+ rc = os_mbuf_copyinto(om, OS_MBUF_PKTLEN(om),
+ &tuples[i].handle, sizeof tuples[i].handle);
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ os_mbuf_free_chain(om);
+ goto done;
+ }
+ /* Length */
+ rc = os_mbuf_copyinto(om, OS_MBUF_PKTLEN(om),
+ &(OS_MBUF_PKTLEN(tuples[i].value)),
+ sizeof(OS_MBUF_PKTLEN(tuples[i].value)));
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ os_mbuf_free_chain(om);
+ goto done;
+ }
+ /* Value */
+ rc = os_mbuf_appendfrom(om, tuples[i].value,
+ 0, OS_MBUF_PKTLEN(tuples[i].value));
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ os_mbuf_free_chain(om);
+ goto done;
+ }
+ }
+ rc = ble_att_clt_tx_multi_notify(conn_handle, om);
+
+done:
+ if (rc != 0) {
+ STATS_INC(ble_gattc_stats, multi_notify_fail);
+ }
+
+ /* Tell the application that multiple notification transmissions were
attempted. */
+ for (i = 0; i < num_tuples; i++) {
+ ble_gap_notify_tx_event(rc, conn_handle, tuples[i].handle, 0);
+ os_mbuf_free_chain(tuples[i].value);
+ }
Review Comment:
```suggestion
int j; //this on top
/* Tell the application that multiple notification transmissions were
attempted. */
for (j = 0; j < i; j++) {
ble_gap_notify_tx_event(rc, conn_handle, tuples[j].handle, 0);
os_mbuf_free_chain(tuples[j].value);
}
```
`i` now holds how many tuples were actually send (it may be leftover).
##########
nimble/host/src/ble_gattc.c:
##########
@@ -4212,6 +4223,131 @@ ble_gatts_notify_custom(uint16_t conn_handle, uint16_t
chr_val_handle,
return rc;
}
+int
+ble_gatts_multi_notify_custom(uint16_t conn_handle,
+ struct ble_gatt_hv * tuples, uint16_t num_tuples)
+{
+#if !MYNEWT_VAL(BLE_GATT_MULTI_NOTIFY)
+ return BLE_HS_ENOTSUP;
+#endif
+
+ int i;
+ int rc;
+ uint16_t mtu;
+ uint16_t pdu_size;
+ int split_at;
+ struct os_mbuf *om = NULL;
+
+ STATS_INC(ble_gattc_stats, multi_notify);
+ ble_gattc_log_multi_notify(tuples, num_tuples);
+
+ for (i = 0; i < num_tuples; i++) {
+ if (tuples[i].value == NULL) {
+ /* No custom attribute data; read the value from the specified
+ * attribute
+ */
+ tuples[i].value = ble_hs_mbuf_att_pkt();
+ if (tuples[i].value == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE,
+ tuples[i].handle, 0, tuples[i].value,
NULL);
+ if (rc != 0) {
+ /* Fatal error; application disallowed attribute read. */
+ rc = BLE_HS_EAPP;
+ goto done;
+ }
+ }
+ }
+
+ mtu = ble_att_mtu(conn_handle);
+ pdu_size = sizeof(uint8_t); /* Opcode */
+ split_at = 0;
+
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ /* The notification will need to be split */
+ if (i == split_at) {
+ /* Single notification too large for server,
+ * cannot send notify without truncating.
+ */
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ split_at = i;
+ /* Reinitialize loop */
+ i--;
+ pdu_size = sizeof(uint8_t);
+ }
+ }
Review Comment:
```suggestion
```
I think these two loops can be merged (or this one removed and second
modified)
##########
nimble/host/src/ble_gattc.c:
##########
@@ -4212,6 +4223,131 @@ ble_gatts_notify_custom(uint16_t conn_handle, uint16_t
chr_val_handle,
return rc;
}
+int
+ble_gatts_multi_notify_custom(uint16_t conn_handle,
+ struct ble_gatt_hv * tuples, uint16_t num_tuples)
+{
+#if !MYNEWT_VAL(BLE_GATT_MULTI_NOTIFY)
+ return BLE_HS_ENOTSUP;
+#endif
+
+ int i;
+ int rc;
+ uint16_t mtu;
+ uint16_t pdu_size;
+ int split_at;
+ struct os_mbuf *om = NULL;
+
+ STATS_INC(ble_gattc_stats, multi_notify);
+ ble_gattc_log_multi_notify(tuples, num_tuples);
+
+ for (i = 0; i < num_tuples; i++) {
+ if (tuples[i].value == NULL) {
+ /* No custom attribute data; read the value from the specified
+ * attribute
+ */
+ tuples[i].value = ble_hs_mbuf_att_pkt();
+ if (tuples[i].value == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE,
+ tuples[i].handle, 0, tuples[i].value,
NULL);
+ if (rc != 0) {
+ /* Fatal error; application disallowed attribute read. */
+ rc = BLE_HS_EAPP;
+ goto done;
+ }
+ }
+ }
+
+ mtu = ble_att_mtu(conn_handle);
+ pdu_size = sizeof(uint8_t); /* Opcode */
+ split_at = 0;
+
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ /* The notification will need to be split */
+ if (i == split_at) {
+ /* Single notification too large for server,
+ * cannot send notify without truncating.
+ */
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ split_at = i;
+ /* Reinitialize loop */
+ i--;
+ pdu_size = sizeof(uint8_t);
+ }
+ }
+
+ pdu_size = sizeof(uint8_t);
+ split_at = 0;
+ om = ble_hs_mbuf_att_pkt();
+ if(om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ rc = ble_att_clt_tx_multi_notify(conn_handle, om);
+ if (rc != 0) {
+ goto done;
+ }
+ split_at = i;
+ i--;
+ pdu_size = sizeof(uint8_t);
+ om = ble_hs_mbuf_att_pkt();
+ if(om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ continue;
+ }
+ /* Handle */
+ rc = os_mbuf_copyinto(om, OS_MBUF_PKTLEN(om),
Review Comment:
you are copying data to buffer at same offset every time. This will just
overwrite previous data. I think you need to use `os_mbuf_append()`
##########
nimble/host/include/host/ble_gatt.h:
##########
@@ -79,6 +79,12 @@ struct ble_hs_cfg;
#define BLE_GATT_SVC_TYPE_PRIMARY 1
#define BLE_GATT_SVC_TYPE_SECONDARY 2
+/*** @server. */
+struct ble_gatt_hv {
Review Comment:
`hv` isn't very clear, maybe
```suggestion
struct ble_gatt_mult_notif_entry {
```
or `notif_value` as @sjanc suggested
##########
nimble/host/src/ble_gattc.c:
##########
@@ -4212,6 +4223,131 @@ ble_gatts_notify_custom(uint16_t conn_handle, uint16_t
chr_val_handle,
return rc;
}
+int
+ble_gatts_multi_notify_custom(uint16_t conn_handle,
+ struct ble_gatt_hv * tuples, uint16_t num_tuples)
+{
+#if !MYNEWT_VAL(BLE_GATT_MULTI_NOTIFY)
+ return BLE_HS_ENOTSUP;
+#endif
+
+ int i;
+ int rc;
+ uint16_t mtu;
+ uint16_t pdu_size;
+ int split_at;
+ struct os_mbuf *om = NULL;
+
+ STATS_INC(ble_gattc_stats, multi_notify);
+ ble_gattc_log_multi_notify(tuples, num_tuples);
+
+ for (i = 0; i < num_tuples; i++) {
+ if (tuples[i].value == NULL) {
+ /* No custom attribute data; read the value from the specified
+ * attribute
+ */
+ tuples[i].value = ble_hs_mbuf_att_pkt();
+ if (tuples[i].value == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE,
+ tuples[i].handle, 0, tuples[i].value,
NULL);
+ if (rc != 0) {
+ /* Fatal error; application disallowed attribute read. */
+ rc = BLE_HS_EAPP;
+ goto done;
+ }
+ }
+ }
+
+ mtu = ble_att_mtu(conn_handle);
+ pdu_size = sizeof(uint8_t); /* Opcode */
+ split_at = 0;
+
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ /* The notification will need to be split */
+ if (i == split_at) {
+ /* Single notification too large for server,
+ * cannot send notify without truncating.
+ */
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ split_at = i;
+ /* Reinitialize loop */
+ i--;
+ pdu_size = sizeof(uint8_t);
+ }
+ }
+
+ pdu_size = sizeof(uint8_t);
+ split_at = 0;
+ om = ble_hs_mbuf_att_pkt();
+ if(om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ for (i = 0; i < num_tuples; i++) {
+ pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
+ if (pdu_size > mtu) {
+ rc = ble_att_clt_tx_multi_notify(conn_handle, om);
+ if (rc != 0) {
+ goto done;
+ }
+ split_at = i;
+ i--;
+ pdu_size = sizeof(uint8_t);
+ om = ble_hs_mbuf_att_pkt();
+ if(om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+ continue;
+ }
+ /* Handle */
+ rc = os_mbuf_copyinto(om, OS_MBUF_PKTLEN(om),
+ &tuples[i].handle, sizeof tuples[i].handle);
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ os_mbuf_free_chain(om);
+ goto done;
+ }
+ /* Length */
+ rc = os_mbuf_copyinto(om, OS_MBUF_PKTLEN(om),
+ &(OS_MBUF_PKTLEN(tuples[i].value)),
+ sizeof(OS_MBUF_PKTLEN(tuples[i].value)));
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ os_mbuf_free_chain(om);
+ goto done;
+ }
+ /* Value */
+ rc = os_mbuf_appendfrom(om, tuples[i].value,
+ 0, OS_MBUF_PKTLEN(tuples[i].value));
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ os_mbuf_free_chain(om);
+ goto done;
+ }
+ }
+ rc = ble_att_clt_tx_multi_notify(conn_handle, om);
Review Comment:
`int attr_in_cur_pdu_cnt = 0;` should be added on top, and then
```suggestion
for (i = 0; i < num_tuples; i++) {
pdu_size += (2 * sizeof(uint16_t)) + OS_MBUF_PKTLEN(tuples[i].value);
/* Multiple handle notification can only be sent with two or more
handles */
if (pdu_size > mtu && attr_in_cur_pdu_cnt > 2) {
rc = ble_att_clt_tx_multi_notify(conn_handle, om);
if (rc != 0) {
goto done;
}
attr_in_cur_pdu_cnt = 0;
pdu_size = sizeof(uint8_t);
om = ble_hs_mbuf_att_pkt();
if(om == NULL) {
rc = BLE_HS_ENOMEM;
goto done;
}
if (num_tuples - i < 2) {
BLE_HS_LOG(DEBUG, "Notifications partially sent (%d/%d)", i,
num_tuples);
goto done;
}
}
/* Handle */
rc = os_mbuf_copyinto(om, OS_MBUF_PKTLEN(om),
&tuples[i].handle, sizeof tuples[i].handle);
if (rc != 0) {
rc = BLE_HS_ENOMEM;
os_mbuf_free_chain(om);
goto done;
}
/* Length */
rc = os_mbuf_copyinto(om, OS_MBUF_PKTLEN(om),
&(OS_MBUF_PKTLEN(tuples[i].value)),
sizeof(OS_MBUF_PKTLEN(tuples[i].value)));
if (rc != 0) {
rc = BLE_HS_ENOMEM;
os_mbuf_free_chain(om);
goto done;
}
/* Value */
rc = os_mbuf_appendfrom(om, tuples[i].value,
0, OS_MBUF_PKTLEN(tuples[i].value));
if (rc != 0) {
rc = BLE_HS_ENOMEM;
os_mbuf_free_chain(om);
goto done;
}
attr_in_pdu_cnt++;
}
rc = ble_att_clt_tx_multi_notify(conn_handle, om);
```
plus what in other comments
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]