mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-10-13 09:27:22 +00:00
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.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user