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) {
