This is an automated email from the ASF dual-hosted git repository.

andk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit ca043593a9e85b7ccb281abee51df2148c22672d
Author: Andrzej Kaczmarek <[email protected]>
AuthorDate: Fri Mar 18 21:06:55 2022 +0100

    nimble/transport: Add ISO support
    
    This adds support for HCI ISO Data packets to UART H4, nRF5340 IPC and
    native transport.
    
    The default ISO buffers count is set to 0 as it will disable ISO support
    by default.
---
 .../hci_h4/include/nimble/transport/hci_h4.h       |  2 +
 nimble/transport/common/hci_h4/src/hci_h4.c        | 14 +++++
 .../hci_ipc/include/nimble/transport/hci_ipc.h     |  1 +
 nimble/transport/common/hci_ipc/src/hci_ipc.c      | 15 +++++
 nimble/transport/include/nimble/transport.h        |  4 ++
 .../transport/include/nimble/transport/monitor.h   | 12 ++++
 nimble/transport/include/nimble/transport_impl.h   |  2 +
 nimble/transport/nrf5340/src/nrf5340_ble_hci.c     | 35 +++++++++++
 nimble/transport/src/monitor.c                     | 16 +++++
 nimble/transport/src/monitor_priv.h                |  2 +
 nimble/transport/src/transport.c                   | 69 ++++++++++++++++++++++
 nimble/transport/syscfg.yml                        | 21 +++++++
 nimble/transport/uart/src/hci_uart.c               | 30 ++++++++++
 13 files changed, 223 insertions(+)

diff --git a/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h 
b/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h
index 139160a5..6ad083a0 100644
--- a/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h
+++ b/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h
@@ -31,11 +31,13 @@
 typedef void *(hci_h4_alloc_cmd)(void);
 typedef void *(hci_h4_alloc_evt)(int);
 typedef struct os_mbuf *(hci_h4_alloc_acl)(void);
+typedef struct os_mbuf *(hci_h4_alloc_iso)(void);
 
 struct hci_h4_allocators {
     hci_h4_alloc_cmd *cmd;
     hci_h4_alloc_acl *acl;
     hci_h4_alloc_evt *evt;
+    hci_h4_alloc_iso *iso;
 };
 
 extern const struct hci_h4_allocators hci_h4_allocs_from_ll;
diff --git a/nimble/transport/common/hci_h4/src/hci_h4.c 
b/nimble/transport/common/hci_h4/src/hci_h4.c
index cb091342..ea30f429 100644
--- a/nimble/transport/common/hci_h4/src/hci_h4.c
+++ b/nimble/transport/common/hci_h4/src/hci_h4.c
@@ -39,6 +39,7 @@ const struct hci_h4_allocators hci_h4_allocs_from_ll = {
 const struct hci_h4_allocators hci_h4_allocs_from_hs = {
     .cmd = ble_transport_alloc_cmd,
     .acl = ble_transport_alloc_acl_from_hs,
+    .iso = ble_transport_alloc_iso_from_hs,
 };
 
 struct hci_h4_input_buffer {
@@ -58,6 +59,7 @@ hci_h4_frame_start(struct hci_h4_sm *rxs, uint8_t pkt_type)
         rxs->min_len = 3;
         break;
     case HCI_H4_ACL:
+    case HCI_H4_ISO:
         rxs->min_len = 4;
         break;
     case HCI_H4_EVT:
@@ -159,6 +161,16 @@ hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct 
hci_h4_input_buffer *ib)
 
         h4sm->exp_len = h4sm->hdr[1] + 2;
         break;
+    case HCI_H4_ISO:
+        assert(h4sm->allocs && h4sm->allocs->iso);
+        h4sm->om = h4sm->allocs->iso();
+        if (!h4sm->om) {
+            return -1;
+        }
+
+        os_mbuf_append(h4sm->om, h4sm->hdr, h4sm->len);
+        h4sm->exp_len = (get_le16(&h4sm->hdr[2]) & 0x7fff) + 4;
+        break;
     default:
         assert(0);
         break;
@@ -185,6 +197,7 @@ hci_h4_sm_w4_payload(struct hci_h4_sm *h4sm,
         }
         break;
     case HCI_H4_ACL:
+    case HCI_H4_ISO:
         assert(h4sm->om);
 
         mbuf_len = OS_MBUF_PKTLEN(h4sm->om);
@@ -230,6 +243,7 @@ hci_h4_sm_completed(struct hci_h4_sm *h4sm)
         }
         break;
     case HCI_H4_ACL:
+    case HCI_H4_ISO:
         if (h4sm->om) {
             assert(h4sm->frame_cb);
             rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->om);
diff --git a/nimble/transport/common/hci_ipc/include/nimble/transport/hci_ipc.h 
b/nimble/transport/common/hci_ipc/include/nimble/transport/hci_ipc.h
index 2f84f68f..551fb93d 100644
--- a/nimble/transport/common/hci_ipc/include/nimble/transport/hci_ipc.h
+++ b/nimble/transport/common/hci_ipc/include/nimble/transport/hci_ipc.h
@@ -27,6 +27,7 @@
 #define HCI_IPC_TYPE_EVT                0x04
 #define HCI_IPC_TYPE_EVT_DISCARDABLE    0x05
 #define HCI_IPC_TYPE_EVT_IN_CMD         0x06
+#define HCI_IPC_TYPE_ISO                0x07
 
 struct __attribute__((packed)) hci_ipc_hdr {
     uint8_t type;
diff --git a/nimble/transport/common/hci_ipc/src/hci_ipc.c 
b/nimble/transport/common/hci_ipc/src/hci_ipc.c
index fafbacc3..613c9ce1 100644
--- a/nimble/transport/common/hci_ipc/src/hci_ipc.c
+++ b/nimble/transport/common/hci_ipc/src/hci_ipc.c
@@ -58,6 +58,13 @@ hci_ipc_alloc(struct hci_ipc_sm *sm)
         sm->buf = ble_transport_alloc_cmd();
         break;
 #endif
+    case HCI_IPC_TYPE_ISO:
+#if MYNEWT_VAL(BLE_CONTROLLER)
+        sm->om = ble_transport_alloc_iso_from_hs();
+#else
+        sm->om = ble_transport_alloc_iso_from_ll();
+#endif
+        break;
     default:
         assert(0);
         break;
@@ -102,6 +109,13 @@ hci_ipc_frame(struct hci_ipc_sm *sm)
         ble_transport_to_hs_evt(sm->buf);
         break;
 #endif
+    case HCI_IPC_TYPE_ISO:
+#if MYNEWT_VAL(BLE_CONTROLLER)
+        ble_transport_to_ll_iso(sm->om);
+#else
+        ble_transport_to_hs_iso(sm->om);
+#endif
+        break;
     default:
         assert(0);
         break;
@@ -161,6 +175,7 @@ hci_ipc_copy_to_buf(struct hci_ipc_sm *sm, const uint8_t 
*buf, uint16_t len)
         memcpy(sm->buf + sm->buf_len, buf, len);
         break;
     case HCI_IPC_TYPE_ACL:
+    case HCI_IPC_TYPE_ISO:
         rc = os_mbuf_append(sm->om, buf, len);
         assert(rc == 0);
         break;
diff --git a/nimble/transport/include/nimble/transport.h 
b/nimble/transport/include/nimble/transport.h
index d18ff560..fcb3297c 100644
--- a/nimble/transport/include/nimble/transport.h
+++ b/nimble/transport/include/nimble/transport.h
@@ -39,7 +39,9 @@ void ble_transport_init(void);
 void *ble_transport_alloc_cmd(void);
 void *ble_transport_alloc_evt(int discardable);
 struct os_mbuf *ble_transport_alloc_acl_from_hs(void);
+struct os_mbuf *ble_transport_alloc_iso_from_hs(void);
 struct os_mbuf *ble_transport_alloc_acl_from_ll(void);
+struct os_mbuf *ble_transport_alloc_iso_from_ll(void);
 
 /* Generic deallocator for cmd/evt buffers */
 void ble_transport_free(void *buf);
@@ -50,8 +52,10 @@ int 
ble_transport_register_put_acl_from_ll_cb(os_mempool_put_fn *cb);
 /* Send data to hs/ll side */
 int ble_transport_to_ll_cmd(void *buf);
 int ble_transport_to_ll_acl(struct os_mbuf *om);
+int ble_transport_to_ll_iso(struct os_mbuf *om);
 int ble_transport_to_hs_evt(void *buf);
 int ble_transport_to_hs_acl(struct os_mbuf *om);
+int ble_transport_to_hs_iso(struct os_mbuf *om);
 
 #ifdef __cplusplus
 }
diff --git a/nimble/transport/include/nimble/transport/monitor.h 
b/nimble/transport/include/nimble/transport/monitor.h
index 349f49d7..dc12c69c 100644
--- a/nimble/transport/include/nimble/transport/monitor.h
+++ b/nimble/transport/include/nimble/transport/monitor.h
@@ -59,6 +59,12 @@ ble_transport_to_ll_acl(struct os_mbuf *om)
     return ble_transport_to_ll_acl_impl(om);
 }
 
+static inline int
+ble_transport_to_ll_iso(struct os_mbuf *om)
+{
+    return ble_transport_to_ll_iso_impl(om);
+}
+
 static inline int
 ble_transport_to_hs_evt(void *buf)
 {
@@ -70,6 +76,12 @@ ble_transport_to_hs_acl(struct os_mbuf *om)
 {
     return ble_transport_to_hs_acl_impl(om);
 }
+
+static inline int
+ble_transport_to_hs_iso(struct os_mbuf *om)
+{
+    return ble_transport_to_hs_iso_impl(om);
+}
 #endif /* BLE_MONITOR */
 
 #ifdef __cplusplus
diff --git a/nimble/transport/include/nimble/transport_impl.h 
b/nimble/transport/include/nimble/transport_impl.h
index d99a8d95..8d95c892 100644
--- a/nimble/transport/include/nimble/transport_impl.h
+++ b/nimble/transport/include/nimble/transport_impl.h
@@ -31,8 +31,10 @@ extern void ble_transport_hs_init(void);
 /* APIs to be implemented by HS/LL side of transports */
 extern int ble_transport_to_ll_cmd_impl(void *buf);
 extern int ble_transport_to_ll_acl_impl(struct os_mbuf *om);
+extern int ble_transport_to_ll_iso_impl(struct os_mbuf *om);
 extern int ble_transport_to_hs_evt_impl(void *buf);
 extern int ble_transport_to_hs_acl_impl(struct os_mbuf *om);
+extern int ble_transport_to_hs_iso_impl(struct os_mbuf *om);
 
 #ifdef __cplusplus
 }
diff --git a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c 
b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c
index 9ee36178..7f3c5efe 100644
--- a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c
+++ b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c
@@ -63,6 +63,35 @@ nrf5340_ble_hci_acl_tx(struct os_mbuf *om)
     return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0;
 }
 
+#if !MYNEWT_VAL(BLE_CONTROLLER)
+static int
+nrf5340_ble_hci_iso_tx(struct os_mbuf *om)
+{
+    struct hci_ipc_hdr hdr;
+    struct os_mbuf *x;
+    int rc;
+
+    hdr.type = HCI_IPC_TYPE_ISO;
+    hdr.length = 4 + get_le16(&om->om_data[2]);
+
+    rc = ipc_nrf5340_write(IPC_TX_CHANNEL, &hdr, sizeof(hdr), false);
+    if (rc == 0) {
+        x = om;
+        while (x) {
+            rc = ipc_nrf5340_write(IPC_TX_CHANNEL, x->om_data, x->om_len, 
true);
+            if (rc < 0) {
+                break;
+            }
+            x = SLIST_NEXT(x, om_next);
+        }
+    }
+
+    os_mbuf_free_chain(om);
+
+    return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0;
+}
+#endif
+
 static void
 nrf5340_ble_hci_trans_rx(int channel, void *user_data)
 {
@@ -149,6 +178,12 @@ ble_transport_to_ll_acl_impl(struct os_mbuf *om)
     return nrf5340_ble_hci_acl_tx(om);
 }
 
+int
+ble_transport_to_ll_iso_impl(struct os_mbuf *om)
+{
+    return nrf5340_ble_hci_iso_tx(om);
+}
+
 void
 ble_transport_ll_init(void)
 {
diff --git a/nimble/transport/src/monitor.c b/nimble/transport/src/monitor.c
index 88309149..b21dd930 100644
--- a/nimble/transport/src/monitor.c
+++ b/nimble/transport/src/monitor.c
@@ -509,6 +509,14 @@ ble_transport_to_ll_acl(struct os_mbuf *om)
     return ble_transport_to_ll_acl_impl(om);
 }
 
+int
+ble_transport_to_ll_iso(struct os_mbuf *om)
+{
+    ble_monitor_send_om(BLE_MONITOR_OPCODE_ISO_TX_PKT, om);
+
+    return ble_transport_to_ll_iso_impl(om);
+}
+
 int
 ble_transport_to_hs_acl(struct os_mbuf *om)
 {
@@ -528,4 +536,12 @@ ble_transport_to_hs_evt(void *buf)
     return ble_transport_to_hs_evt_impl(buf);
 }
 
+int
+ble_transport_to_hs_iso(struct os_mbuf *om)
+{
+    ble_monitor_send_om(BLE_MONITOR_OPCODE_ISO_RX_PKT, om);
+
+    return ble_transport_to_hs_iso_impl(om);
+}
+
 #endif /* MYNEWT_VAL(BLE_MONITOR_RTT) || MYNEWT_VAL(BLE_MONITOR_UART) */
diff --git a/nimble/transport/src/monitor_priv.h 
b/nimble/transport/src/monitor_priv.h
index 0fb96509..938da8f5 100644
--- a/nimble/transport/src/monitor_priv.h
+++ b/nimble/transport/src/monitor_priv.h
@@ -38,6 +38,8 @@ extern "C" {
 #define BLE_MONITOR_OPCODE_VENDOR_DIAG  11
 #define BLE_MONITOR_OPCODE_SYSTEM_NOTE  12
 #define BLE_MONITOR_OPCODE_USER_LOGGING 13
+#define BLE_MONITOR_OPCODE_ISO_TX_PKT   18
+#define BLE_MONITOR_OPCODE_ISO_RX_PKT   19
 
 #define BLE_MONITOR_EXTHDR_COMMAND_DROPS    1
 #define BLE_MONITOR_EXTHDR_EVENT_DROPS      2
diff --git a/nimble/transport/src/transport.c b/nimble/transport/src/transport.c
index 7e5601d1..c9b37a7e 100644
--- a/nimble/transport/src/transport.c
+++ b/nimble/transport/src/transport.c
@@ -49,18 +49,26 @@
 #if MYNEWT_VAL_CHOICE(BLE_TRANSPORT_LL, native) && \
    MYNEWT_VAL_CHOICE(BLE_TRANSPORT_HS, native)
 #define POOL_ACL_COUNT      (0)
+#define POOL_ISO_COUNT      (0)
 #elif !MYNEWT_VAL_CHOICE(BLE_TRANSPORT_LL, native) && \
       !MYNEWT_VAL_CHOICE(BLE_TRANSPORT_HS, native)
 #define POOL_ACL_COUNT      ((MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_HS_COUNT)) + \
                              (MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT)))
+#define POOL_ISO_COUNT      ((MYNEWT_VAL(BLE_TRANSPORT_ISO_FROM_HS_COUNT)) + \
+                             (MYNEWT_VAL(BLE_TRANSPORT_ISO_FROM_LL_COUNT)))
 #elif MYNEWT_VAL_CHOICE(BLE_TRANSPORT_LL, native)
 #define POOL_ACL_COUNT      (MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_HS_COUNT))
+#define POOL_ISO_COUNT      (MYNEWT_VAL(BLE_TRANSPORT_ISO_FROM_HS_COUNT))
 #else
 #define POOL_ACL_COUNT      (MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT))
+#define POOL_ISO_COUNT      (MYNEWT_VAL(BLE_TRANSPORT_ISO_FROM_LL_COUNT))
 #endif
 #define POOL_ACL_SIZE       (OS_ALIGN( MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE) + \
                                        BLE_MBUF_MEMBLOCK_OVERHEAD +         \
                                        BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT))
+#define POOL_ISO_SIZE       (OS_ALIGN(MYNEWT_VAL(BLE_TRANSPORT_ISO_SIZE) + \
+                                      BLE_MBUF_MEMBLOCK_OVERHEAD +         \
+                                      BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT))
 
 static uint8_t pool_cmd_buf[ OS_MEMPOOL_BYTES(POOL_CMD_COUNT, POOL_CMD_SIZE) ];
 static struct os_mempool pool_cmd;
@@ -77,6 +85,12 @@ static struct os_mempool_ext pool_acl;
 static struct os_mbuf_pool mpool_acl;
 #endif
 
+#if POOL_ISO_COUNT > 0
+static uint8_t pool_iso_buf[ OS_MEMPOOL_BYTES(POOL_ISO_COUNT, POOL_ISO_SIZE) ];
+static struct os_mempool_ext pool_iso;
+static struct os_mbuf_pool mpool_iso;
+#endif
+
 static os_mempool_put_fn *transport_put_acl_from_ll_cb;
 
 void *
@@ -159,6 +173,32 @@ ble_transport_alloc_acl_from_hs(void)
 #endif
 }
 
+struct os_mbuf *
+ble_transport_alloc_iso_from_hs(void)
+{
+#if POOL_ISO_COUNT > 0
+    struct os_mbuf *om;
+    struct os_mbuf_pkthdr *pkthdr;
+    uint16_t usrhdr_len;
+
+#if MYNEWT_VAL_CHOICE(BLE_TRANSPORT_LL, native)
+    usrhdr_len = sizeof(struct ble_mbuf_hdr);
+#else
+    usrhdr_len = 0;
+#endif
+
+    om = os_mbuf_get_pkthdr(&mpool_iso, usrhdr_len);
+    if (om) {
+        pkthdr = OS_MBUF_PKTHDR(om);
+        pkthdr->omp_flags = OMP_FLAG_FROM_HS;
+    }
+
+    return om;
+#else
+    return NULL;
+#endif
+}
+
 struct os_mbuf *
 ble_transport_alloc_acl_from_ll(void)
 {
@@ -178,6 +218,25 @@ ble_transport_alloc_acl_from_ll(void)
 #endif
 }
 
+struct os_mbuf *
+ble_transport_alloc_iso_from_ll(void)
+{
+#if POOL_ISO_COUNT > 0
+    struct os_mbuf *om;
+    struct os_mbuf_pkthdr *pkthdr;
+
+    om = os_mbuf_get_pkthdr(&mpool_iso, 0);
+    if (om) {
+        pkthdr = OS_MBUF_PKTHDR(om);
+        pkthdr->omp_flags = OMP_FLAG_FROM_LL;
+    }
+
+    return om;
+#else
+    return NULL;
+#endif
+}
+
 void
 ble_transport_free(void *buf)
 {
@@ -278,6 +337,16 @@ ble_transport_init(void)
 
     pool_acl.mpe_put_cb = ble_transport_acl_put;
 #endif
+
+#if POOL_ISO_COUNT > 0
+    rc = os_mempool_ext_init(&pool_iso, POOL_ISO_COUNT, POOL_ISO_SIZE,
+                             pool_iso_buf, "transport_pool_iso");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mbuf_pool_init(&mpool_iso, &pool_iso.mpe_mp,
+                           POOL_ISO_SIZE, POOL_ISO_COUNT);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+#endif
 }
 
 int
diff --git a/nimble/transport/syscfg.yml b/nimble/transport/syscfg.yml
index e8d83bd1..7f02f6cc 100644
--- a/nimble/transport/syscfg.yml
+++ b/nimble/transport/syscfg.yml
@@ -58,6 +58,16 @@ syscfg.defs:
     BLE_TRANSPORT_ACL_SIZE:
         description: Size of each buffer in ACL pool.
         value: 251
+    BLE_TRANSPORT_ISO_COUNT:
+        description: >
+            Number of ISO buffers available in transport. This determines
+            number of buffers used by host/controller for flow control.
+            Buffers pool is allocated for each non-native transport side
+            selected, unless overriden by BLE_TRANSPORT_ISO_FROM_[HS|LL]_COUNT.
+        value: 10
+    BLE_TRANSPORT_ISO_SIZE:
+        description: Size of each buffer in ISO pool.
+        value: 300
     BLE_TRANSPORT_EVT_COUNT:
         description: >
             Number of event buffers available in transport.
@@ -88,6 +98,17 @@ syscfg.defs:
             of ACL buffers available for controller.
         value: MYNEWT_VAL(BLE_TRANSPORT_ACL_COUNT)
 
+    BLE_TRANSPORT_ISO_FROM_HS_COUNT:
+        description: >
+            Overrides BLE_TRANSPORT_ISO_COUNT on host side, i.e. number
+            of ISO buffers available for host.
+        value: MYNEWT_VAL(BLE_TRANSPORT_ISO_COUNT)
+    BLE_TRANSPORT_ISO_FROM_LL_COUNT:
+        description: >
+            Overrides BLE_TRANSPORT_ISO_COUNT on controller side, i.e. number
+            of ISO buffers available for controller.
+        value: MYNEWT_VAL(BLE_TRANSPORT_ISO_COUNT)
+
 # import monitor and defunct settings from separate file to reduce clutter in 
main file
 $import:
     - "@apache-mynewt-nimble/nimble/transport/syscfg.monitor.yml"
diff --git a/nimble/transport/uart/src/hci_uart.c 
b/nimble/transport/uart/src/hci_uart.c
index 42206f58..af1f45ae 100644
--- a/nimble/transport/uart/src/hci_uart.c
+++ b/nimble/transport/uart/src/hci_uart.c
@@ -61,6 +61,8 @@ hci_uart_frame_cb(uint8_t pkt_type, void *data)
         return ble_transport_to_ll_cmd(data);
     case HCI_H4_ACL:
         return ble_transport_to_ll_acl(data);
+    case HCI_H4_ISO:
+        return ble_transport_to_ll_iso(data);
     default:
         assert(0);
         break;
@@ -227,6 +229,34 @@ ble_transport_to_hs_acl_impl(struct os_mbuf *om)
     return 0;
 }
 
+int
+ble_transport_to_hs_iso_impl(struct os_mbuf *om)
+{
+    struct hci_uart_tx *txe;
+    os_sr_t sr;
+
+    txe = os_memblock_get(&pool_tx_q);
+    if (!txe) {
+        assert(0);
+        return -ENOMEM;
+    }
+
+    txe->type = HCI_H4_ISO;
+    txe->sent_type = 0;
+    txe->len = OS_MBUF_PKTLEN(om);
+    txe->idx = 0;
+    txe->buf = NULL;
+    txe->om = om;
+
+    OS_ENTER_CRITICAL(sr);
+    STAILQ_INSERT_TAIL(&tx_q, txe, tx_q_next);
+    OS_EXIT_CRITICAL(sr);
+
+    hal_uart_start_tx(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT));
+
+    return 0;
+}
+
 void
 ble_transport_hs_init(void)
 {

Reply via email to