mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-09-14 20:51:58 +00:00
The Bluetooth Specification allows for optional Controller to Host flow control based on the same credit-based mechanism as the Host to Controller one. This is particularly useful in 2-chip solutions where the Host and the Controller are connected via a physical link (UART, SPI or similar) where the Host is sometimes required to ask the Controller to throttle its data traffic while still making sure that relevant events get through the line. This implementation is based on a simple queue of pending events and data that is populated whenever the Controller detects that the Host is out of buffers and then emptied whenever the Host notifies the Controller that is ready to receive data again. Events relevant to the connections are also queued to preserve the order of arrival. At this point the Controller ignores the connection handle sent by the Host and treats all connections equally, and it also queues events even for connections that have no data pending in the queue. Both this items can be improved if necessity arises. Note that Number of Completed Packets will still flow freely from the Controller to the Host regardless of the pending ACL data packets, which might lead to inconsistencies in the sequential order of certain operations that include bi-directional data transfer. Jira: ZEP-1735 Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
307 lines
9.5 KiB
C
307 lines
9.5 KiB
C
/*
|
|
* Copyright (c) 2016 Nordic Semiconductor ASA
|
|
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifndef _CTRL_H_
|
|
#define _CTRL_H_
|
|
|
|
/*****************************************************************************
|
|
* Zephyr Kconfig defined
|
|
****************************************************************************/
|
|
#ifdef CONFIG_BLUETOOTH_MAX_CONN
|
|
#define RADIO_CONNECTION_CONTEXT_MAX CONFIG_BLUETOOTH_MAX_CONN
|
|
#else
|
|
#define RADIO_CONNECTION_CONTEXT_MAX 0
|
|
#endif
|
|
|
|
#ifdef CONFIG_BLUETOOTH_CONTROLLER_RX_BUFFERS
|
|
#define RADIO_PACKET_COUNT_RX_MAX \
|
|
CONFIG_BLUETOOTH_CONTROLLER_RX_BUFFERS
|
|
#endif
|
|
|
|
#ifdef CONFIG_BLUETOOTH_CONTROLLER_TX_BUFFERS
|
|
#define RADIO_PACKET_COUNT_TX_MAX \
|
|
CONFIG_BLUETOOTH_CONTROLLER_TX_BUFFERS
|
|
#endif
|
|
|
|
#ifdef CONFIG_BLUETOOTH_CONTROLLER_TX_BUFFER_SIZE
|
|
#define RADIO_PACKET_TX_DATA_SIZE \
|
|
CONFIG_BLUETOOTH_CONTROLLER_TX_BUFFER_SIZE
|
|
#endif
|
|
|
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_LE_PING)
|
|
#define RADIO_BLE_FEAT_BIT_PING BIT(BT_LE_FEAT_BIT_PING)
|
|
#else /* !CONFIG_BLUETOOTH_CONTROLLER_LE_PING */
|
|
#define RADIO_BLE_FEAT_BIT_PING 0
|
|
#endif /* !CONFIG_BLUETOOTH_CONTROLLER_LE_PING */
|
|
|
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH_MAX)
|
|
#define RADIO_BLE_FEAT_BIT_DLE BIT(BT_LE_FEAT_BIT_DLE)
|
|
#define RADIO_LL_LENGTH_OCTETS_RX_MAX \
|
|
CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH_MAX
|
|
#else
|
|
#define RADIO_BLE_FEAT_BIT_DLE 0
|
|
#define RADIO_LL_LENGTH_OCTETS_RX_MAX 27
|
|
#endif /* CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH_MAX */
|
|
|
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_CHAN_SEL_2)
|
|
#define RADIO_BLE_FEAT_BIT_CHAN_SEL_2 BIT(BT_LE_FEAT_BIT_CHAN_SEL_ALGO_2)
|
|
#else /* !CONFIG_BLUETOOTH_CONTROLLER_CHAN_SEL_2 */
|
|
#define RADIO_BLE_FEAT_BIT_CHAN_SEL_2 0
|
|
#endif /* !CONFIG_BLUETOOTH_CONTROLLER_CHAN_SEL_2 */
|
|
|
|
/*****************************************************************************
|
|
* Timer Resources (Controller defined)
|
|
****************************************************************************/
|
|
#define RADIO_TICKER_ID_EVENT 0
|
|
#define RADIO_TICKER_ID_MARKER_0 1
|
|
#define RADIO_TICKER_ID_PRE_EMPT 2
|
|
#define RADIO_TICKER_ID_ADV_STOP 3
|
|
#define RADIO_TICKER_ID_OBS_STOP 4
|
|
#define RADIO_TICKER_ID_ADV 5
|
|
#define RADIO_TICKER_ID_OBS 6
|
|
#define RADIO_TICKER_ID_FIRST_CONNECTION 7
|
|
|
|
#define RADIO_TICKER_INSTANCE_ID_RADIO 0
|
|
#define RADIO_TICKER_INSTANCE_ID_APP 1
|
|
|
|
#define RADIO_TICKER_USERS 3
|
|
|
|
#define RADIO_TICKER_USER_ID_WORKER MAYFLY_CALL_ID_0
|
|
#define RADIO_TICKER_USER_ID_JOB MAYFLY_CALL_ID_1
|
|
#define RADIO_TICKER_USER_ID_APP MAYFLY_CALL_ID_PROGRAM
|
|
|
|
#define RADIO_TICKER_USER_WORKER_OPS (7 + 1)
|
|
#define RADIO_TICKER_USER_JOB_OPS (2 + 1)
|
|
#define RADIO_TICKER_USER_APP_OPS (1 + 1)
|
|
#define RADIO_TICKER_USER_OPS (RADIO_TICKER_USER_WORKER_OPS \
|
|
+ RADIO_TICKER_USER_JOB_OPS \
|
|
+ RADIO_TICKER_USER_APP_OPS \
|
|
)
|
|
|
|
#define RADIO_TICKER_NODES (RADIO_TICKER_ID_FIRST_CONNECTION \
|
|
+ RADIO_CONNECTION_CONTEXT_MAX \
|
|
)
|
|
|
|
/*****************************************************************************
|
|
* Controller Interface Defines
|
|
****************************************************************************/
|
|
#define RADIO_BLE_VERSION_NUMBER BT_HCI_VERSION_5_0
|
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_COMPANY_ID)
|
|
#define RADIO_BLE_COMPANY_ID CONFIG_BLUETOOTH_CONTROLLER_COMPANY_ID
|
|
#else
|
|
#define RADIO_BLE_COMPANY_ID 0xFFFF
|
|
#endif
|
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_SUBVERSION_NUMBER)
|
|
#define RADIO_BLE_SUB_VERSION_NUMBER \
|
|
CONFIG_BLUETOOTH_CONTROLLER_SUBVERSION_NUMBER
|
|
#else
|
|
#define RADIO_BLE_SUB_VERSION_NUMBER 0xFFFF
|
|
#endif
|
|
|
|
#define RADIO_BLE_FEAT_BIT_MASK 0x1FFFF
|
|
#define RADIO_BLE_FEAT_BIT_MASK_VALID 0x1CF2F
|
|
#define RADIO_BLE_FEAT (BIT(BT_LE_FEAT_BIT_ENC) | \
|
|
BIT(BT_LE_FEAT_BIT_CONN_PARAM_REQ) | \
|
|
BIT(BT_LE_FEAT_BIT_EXT_REJ_IND) | \
|
|
BIT(BT_LE_FEAT_BIT_SLAVE_FEAT_REQ) | \
|
|
RADIO_BLE_FEAT_BIT_PING | \
|
|
RADIO_BLE_FEAT_BIT_DLE | \
|
|
RADIO_BLE_FEAT_BIT_CHAN_SEL_2)
|
|
|
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_WORKER_PRIO)
|
|
#define RADIO_TICKER_USER_ID_WORKER_PRIO CONFIG_BLUETOOTH_CONTROLLER_WORKER_PRIO
|
|
#else
|
|
#define RADIO_TICKER_USER_ID_WORKER_PRIO 0
|
|
#endif
|
|
|
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_JOB_PRIO)
|
|
#define RADIO_TICKER_USER_ID_JOB_PRIO CONFIG_BLUETOOTH_CONTROLLER_JOB_PRIO
|
|
#else
|
|
#define RADIO_TICKER_USER_ID_JOB_PRIO 0
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
* Controller Reference Defines (compile time override-able)
|
|
****************************************************************************/
|
|
/* Minimum LL Payload support (Dont change). */
|
|
#define RADIO_LL_LENGTH_OCTETS_RX_MIN 27
|
|
#define RADIO_LL_LENGTH_TIME_RX_MIN (((RADIO_LL_LENGTH_OCTETS_RX_MIN) \
|
|
+ 14) * 8 \
|
|
)
|
|
|
|
/* Maximum LL Payload support (27 to 251). */
|
|
#ifndef RADIO_LL_LENGTH_OCTETS_RX_MAX
|
|
#define RADIO_LL_LENGTH_OCTETS_RX_MAX 251
|
|
#endif
|
|
#define RADIO_LL_LENGTH_TIME_RX_MAX (((RADIO_LL_LENGTH_OCTETS_RX_MAX) \
|
|
+ 14) * 8 \
|
|
)
|
|
/* Implementation default L2CAP MTU */
|
|
#ifndef RADIO_L2CAP_MTU_MAX
|
|
#define RADIO_L2CAP_MTU_MAX (RADIO_LL_LENGTH_OCTETS_RX_MAX - 4)
|
|
#endif
|
|
|
|
/* Maximise L2CAP MTU to LL data PDU size */
|
|
#if (RADIO_L2CAP_MTU_MAX < (RADIO_LL_LENGTH_OCTETS_RX_MAX - 4))
|
|
#undef RADIO_L2CAP_MTU_MAX
|
|
#define RADIO_L2CAP_MTU_MAX (RADIO_LL_LENGTH_OCTETS_RX_MAX - 4)
|
|
#endif
|
|
|
|
/* Maximum LL PDU Receive pool size. */
|
|
#ifndef RADIO_PACKET_COUNT_RX_MAX
|
|
#define RADIO_PACKET_COUNT_RX ((RADIO_L2CAP_MTU_MAX + \
|
|
RADIO_LL_LENGTH_OCTETS_RX_MAX \
|
|
+ 3) \
|
|
/ \
|
|
RADIO_LL_LENGTH_OCTETS_RX_MAX \
|
|
)
|
|
#define RADIO_PACKET_COUNT_RX_MAX (RADIO_PACKET_COUNT_RX + \
|
|
((RADIO_CONNECTION_CONTEXT_MAX - 1) * \
|
|
(RADIO_PACKET_COUNT_RX - 1)) \
|
|
)
|
|
#endif /* RADIO_PACKET_COUNT_RX_MAX */
|
|
|
|
/* Maximum LL PDU Transmit pool size and application tx count. */
|
|
#ifndef RADIO_PACKET_COUNT_TX_MAX
|
|
#define RADIO_PACKET_COUNT_APP_TX_MAX (RADIO_CONNECTION_CONTEXT_MAX)
|
|
#define RADIO_PACKET_COUNT_TX_MAX (RADIO_PACKET_COUNT_RX_MAX + \
|
|
RADIO_PACKET_COUNT_APP_TX_MAX \
|
|
)
|
|
#else
|
|
#define RADIO_PACKET_COUNT_APP_TX_MAX (RADIO_PACKET_COUNT_TX_MAX)
|
|
#endif
|
|
|
|
/* Tx Data Size */
|
|
#if !defined(RADIO_PACKET_TX_DATA_SIZE) || \
|
|
(RADIO_PACKET_TX_DATA_SIZE < RADIO_LL_LENGTH_OCTETS_RX_MIN)
|
|
#define RADIO_PACKET_TX_DATA_SIZE RADIO_LL_LENGTH_OCTETS_RX_MIN
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
* Controller Interface Structures
|
|
****************************************************************************/
|
|
struct radio_adv_data {
|
|
u8_t data[DOUBLE_BUFFER_SIZE][PDU_AC_SIZE_MAX];
|
|
u8_t first;
|
|
u8_t last;
|
|
};
|
|
|
|
struct radio_pdu_node_tx {
|
|
void *next;
|
|
u8_t pdu_data[1];
|
|
};
|
|
|
|
enum radio_pdu_node_rx_type {
|
|
NODE_RX_TYPE_NONE,
|
|
NODE_RX_TYPE_DC_PDU,
|
|
NODE_RX_TYPE_REPORT,
|
|
NODE_RX_TYPE_CONNECTION,
|
|
NODE_RX_TYPE_TERMINATE,
|
|
NODE_RX_TYPE_CONN_UPDATE,
|
|
NODE_RX_TYPE_ENC_REFRESH,
|
|
|
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_LE_PING)
|
|
NODE_RX_TYPE_APTO,
|
|
#endif /* CONFIG_BLUETOOTH_CONTROLLER_LE_PING */
|
|
|
|
NODE_RX_TYPE_CHAN_SEL_ALGO,
|
|
|
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI)
|
|
NODE_RX_TYPE_RSSI,
|
|
#endif /* CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI */
|
|
|
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PROFILE_ISR)
|
|
NODE_RX_TYPE_PROFILE,
|
|
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PROFILE_ISR */
|
|
|
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_ADV_INDICATION)
|
|
NODE_RX_TYPE_ADV_INDICATION,
|
|
#endif /* CONFIG_BLUETOOTH_CONTROLLER_ADV_INDICATION */
|
|
};
|
|
|
|
struct radio_le_conn_cmplt {
|
|
u8_t status;
|
|
u8_t role;
|
|
u8_t peer_addr_type;
|
|
u8_t peer_addr[BDADDR_SIZE];
|
|
u8_t own_addr_type;
|
|
u8_t own_addr[BDADDR_SIZE];
|
|
u8_t peer_irk_index;
|
|
u16_t interval;
|
|
u16_t latency;
|
|
u16_t timeout;
|
|
u8_t mca;
|
|
} __packed;
|
|
|
|
struct radio_le_conn_update_cmplt {
|
|
u8_t status;
|
|
u16_t interval;
|
|
u16_t latency;
|
|
u16_t timeout;
|
|
} __packed;
|
|
|
|
struct radio_le_chan_sel_algo {
|
|
u8_t chan_sel_algo;
|
|
} __packed;
|
|
|
|
struct radio_pdu_node_rx_hdr {
|
|
union {
|
|
sys_snode_t node; /* used by slist */
|
|
void *next; /* used also by k_fifo once pulled */
|
|
void *link;
|
|
u8_t packet_release_last;
|
|
} onion;
|
|
|
|
enum radio_pdu_node_rx_type type;
|
|
u16_t handle;
|
|
};
|
|
|
|
struct radio_pdu_node_rx {
|
|
struct radio_pdu_node_rx_hdr hdr;
|
|
u8_t pdu_data[1];
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* Controller Interface Functions
|
|
****************************************************************************/
|
|
/* Downstream */
|
|
u32_t radio_init(void *hf_clock, u8_t sca, u8_t connection_count_max,
|
|
u8_t rx_count_max, u8_t tx_count_max,
|
|
u16_t packet_data_octets_max,
|
|
u16_t packet_tx_data_size, u8_t *mem_radio,
|
|
u16_t mem_size);
|
|
void radio_ticks_active_to_start_set(u32_t ticks_active_to_start);
|
|
struct radio_adv_data *radio_adv_data_get(void);
|
|
struct radio_adv_data *radio_scan_data_get(void);
|
|
u32_t radio_adv_enable(u16_t interval, u8_t chl_map,
|
|
u8_t filter_policy);
|
|
u32_t radio_adv_disable(void);
|
|
u32_t radio_scan_enable(u8_t scan_type, u8_t init_addr_type,
|
|
u8_t *init_addr, u16_t interval,
|
|
u16_t window, u8_t filter_policy);
|
|
u32_t radio_scan_disable(void);
|
|
|
|
u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr,
|
|
u16_t interval, u16_t latency,
|
|
u16_t timeout);
|
|
/* Upstream */
|
|
u8_t radio_rx_get(struct radio_pdu_node_rx **radio_pdu_node_rx,
|
|
u16_t *handle);
|
|
void radio_rx_dequeue(void);
|
|
void radio_rx_mem_release(struct radio_pdu_node_rx **radio_pdu_node_rx);
|
|
u8_t radio_rx_fc_set(u16_t handle, u8_t fc);
|
|
u8_t radio_rx_fc_get(u16_t *handle);
|
|
struct radio_pdu_node_tx *radio_tx_mem_acquire(void);
|
|
void radio_tx_mem_release(struct radio_pdu_node_tx *pdu_data_node_tx);
|
|
u32_t radio_tx_mem_enqueue(u16_t handle,
|
|
struct radio_pdu_node_tx *pdu_data_node_tx);
|
|
/* Callbacks */
|
|
extern void radio_active_callback(u8_t active);
|
|
extern void radio_event_callback(void);
|
|
|
|
#endif
|