| /* |
| * Copyright (c) 2018-2019 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| #if defined(CONFIG_BT_CTLR_RX_PDU_META) |
| #include "lll_meta.h" |
| #endif /* CONFIG_BT_CTLR_RX_PDU_META */ |
| |
| #define TICKER_INSTANCE_ID_CTLR 0 |
| #define TICKER_USER_ID_LLL MAYFLY_CALL_ID_0 |
| #define TICKER_USER_ID_ULL_HIGH MAYFLY_CALL_ID_1 |
| #define TICKER_USER_ID_ULL_LOW MAYFLY_CALL_ID_2 |
| #define TICKER_USER_ID_THREAD MAYFLY_CALL_ID_PROGRAM |
| |
| #define EVENT_PIPELINE_MAX 7 |
| #define EVENT_DONE_MAX 3 |
| |
| #define HDR_ULL(p) ((void *)((u8_t *)(p) + sizeof(struct evt_hdr))) |
| #define HDR_ULL2LLL(p) ((struct lll_hdr *)((u8_t *)(p) + \ |
| sizeof(struct ull_hdr))) |
| #define HDR_LLL2EVT(p) ((struct evt_hdr *)((struct lll_hdr *)(p))->parent) |
| |
| #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) |
| #define XON_BITMASK BIT(31) /* XTAL has been retained from previous prepare */ |
| #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */ |
| |
| #if defined(CONFIG_BT_BROADCASTER) && defined(CONFIG_BT_ADV_SET) |
| #define BT_CTLR_ADV_MAX (CONFIG_BT_ADV_SET + 1) |
| #else |
| #define BT_CTLR_ADV_MAX 1 |
| #endif |
| |
| enum { |
| TICKER_ID_LLL_PREEMPT = 0, |
| |
| #if defined(CONFIG_BT_BROADCASTER) |
| TICKER_ID_ADV_STOP, |
| TICKER_ID_ADV_BASE, |
| #if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT) |
| TICKER_ID_ADV_LAST = ((TICKER_ID_ADV_BASE) + (BT_CTLR_ADV_MAX) - 1), |
| #endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */ |
| #endif /* CONFIG_BT_BROADCASTER */ |
| |
| #if defined(CONFIG_BT_OBSERVER) |
| TICKER_ID_SCAN_STOP, |
| TICKER_ID_SCAN_BASE, |
| TICKER_ID_SCAN_LAST = TICKER_ID_SCAN_BASE, |
| #endif /* CONFIG_BT_OBSERVER */ |
| |
| #if defined(CONFIG_BT_CONN) |
| TICKER_ID_CONN_BASE, |
| TICKER_ID_CONN_LAST = ((TICKER_ID_CONN_BASE) + (CONFIG_BT_MAX_CONN) - |
| 1), |
| #endif /* CONFIG_BT_CONN */ |
| |
| TICKER_ID_MAX, |
| }; |
| |
| #if defined(CONFIG_BT_BROADCASTER) && !defined(CONFIG_BT_CTLR_ADV_EXT) && \ |
| !defined(CONFIG_BT_HCI_MESH_EXT) |
| #define TICKER_ID_ADV_LAST TICKER_ID_ADV_BASE |
| #endif |
| |
| #define TICKER_ID_ULL_BASE ((TICKER_ID_LLL_PREEMPT) + 1) |
| |
| enum ull_status { |
| ULL_STATUS_SUCCESS, |
| ULL_STATUS_FAILURE, |
| ULL_STATUS_BUSY, |
| }; |
| |
| struct evt_hdr { |
| u32_t ticks_xtal_to_start; |
| u32_t ticks_active_to_start; |
| u32_t ticks_preempt_to_start; |
| u32_t ticks_slot; |
| }; |
| |
| struct ull_hdr { |
| u8_t ref; /* Number of ongoing (between Prepare and Done) events */ |
| void (*disabled_cb)(void *param); |
| void *disabled_param; |
| }; |
| |
| struct lll_hdr { |
| void *parent; |
| u8_t is_stop:1; |
| }; |
| |
| struct lll_prepare_param { |
| u32_t ticks_at_expire; |
| u32_t remainder; |
| u16_t lazy; |
| void *param; |
| }; |
| |
| typedef int (*lll_prepare_cb_t)(struct lll_prepare_param *prepare_param); |
| typedef int (*lll_is_abort_cb_t)(void *next, int prio, void *curr, |
| lll_prepare_cb_t *resume_cb, int *resume_prio); |
| typedef void (*lll_abort_cb_t)(struct lll_prepare_param *prepare_param, |
| void *param); |
| |
| struct lll_event { |
| struct lll_prepare_param prepare_param; |
| lll_prepare_cb_t prepare_cb; |
| lll_is_abort_cb_t is_abort_cb; |
| lll_abort_cb_t abort_cb; |
| int prio; |
| u8_t is_resume:1; |
| u8_t is_aborted:1; |
| }; |
| |
| enum node_rx_type { |
| /* Unused */ |
| NODE_RX_TYPE_NONE = 0x00, |
| /* Signals completion of RX event */ |
| NODE_RX_TYPE_EVENT_DONE = 0x01, |
| /* Signals arrival of RX Data Channel payload */ |
| NODE_RX_TYPE_DC_PDU = 0x02, |
| /* Signals release of RX Data Channel payload */ |
| NODE_RX_TYPE_DC_PDU_RELEASE = 0x03, |
| |
| #if defined(CONFIG_BT_OBSERVER) |
| /* Advertisement report from scanning */ |
| NODE_RX_TYPE_REPORT = 0x04, |
| #endif /* CONFIG_BT_OBSERVER */ |
| |
| #if defined(CONFIG_BT_CTLR_ADV_EXT) |
| NODE_RX_TYPE_EXT_1M_REPORT = 0x05, |
| NODE_RX_TYPE_EXT_CODED_REPORT = 0x06, |
| #endif /* CONFIG_BT_CTLR_ADV_EXT */ |
| |
| #if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY) |
| NODE_RX_TYPE_SCAN_REQ = 0x07, |
| #endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */ |
| |
| #if defined(CONFIG_BT_CONN) |
| NODE_RX_TYPE_CONNECTION = 0x08, |
| NODE_RX_TYPE_TERMINATE = 0x09, |
| NODE_RX_TYPE_CONN_UPDATE = 0x0A, |
| NODE_RX_TYPE_ENC_REFRESH = 0x0B, |
| |
| #if defined(CONFIG_BT_CTLR_LE_PING) |
| NODE_RX_TYPE_APTO = 0x0C, |
| #endif /* CONFIG_BT_CTLR_LE_PING */ |
| |
| NODE_RX_TYPE_CHAN_SEL_ALGO = 0x0D, |
| |
| #if defined(CONFIG_BT_CTLR_PHY) |
| NODE_RX_TYPE_PHY_UPDATE = 0x0E, |
| #endif /* CONFIG_BT_CTLR_PHY */ |
| |
| #if defined(CONFIG_BT_CTLR_CONN_RSSI) |
| NODE_RX_TYPE_RSSI = 0x0F, |
| #endif /* CONFIG_BT_CTLR_CONN_RSSI */ |
| #endif /* CONFIG_BT_CONN */ |
| |
| #if defined(CONFIG_BT_CTLR_PROFILE_ISR) |
| NODE_RX_TYPE_PROFILE = 0x10, |
| #endif /* CONFIG_BT_CTLR_PROFILE_ISR */ |
| |
| #if defined(CONFIG_BT_CTLR_ADV_INDICATION) |
| NODE_RX_TYPE_ADV_INDICATION = 0x11, |
| #endif /* CONFIG_BT_CTLR_ADV_INDICATION */ |
| |
| #if defined(CONFIG_BT_CTLR_SCAN_INDICATION) |
| NODE_RX_TYPE_SCAN_INDICATION = 0x12, |
| #endif /* CONFIG_BT_CTLR_SCAN_INDICATION */ |
| |
| #if defined(CONFIG_BT_HCI_MESH_EXT) |
| NODE_RX_TYPE_MESH_ADV_CPLT = 0x13, |
| NODE_RX_TYPE_MESH_REPORT = 0x14, |
| #endif /* CONFIG_BT_HCI_MESH_EXT */ |
| |
| /* Following proprietary defines must be at end of enum range */ |
| #if defined(CONFIG_BT_CTLR_USER_EXT) |
| NODE_RX_TYPE_USER_START = 0x15, |
| NODE_RX_TYPE_USER_END = NODE_RX_TYPE_USER_START + |
| CONFIG_BT_CTLR_USER_EVT_RANGE, |
| #endif /* CONFIG_BT_CTLR_USER_EXT */ |
| |
| }; |
| |
| /* Footer of node_rx_hdr */ |
| struct node_rx_ftr { |
| void *param; |
| void *extra; |
| u32_t ticks_anchor; |
| u32_t us_radio_end; |
| u32_t us_radio_rdy; |
| u8_t rssi; |
| #if defined(CONFIG_BT_CTLR_PRIVACY) |
| u8_t rl_idx; |
| #endif /* CONFIG_BT_CTLR_PRIVACY */ |
| #if defined(CONFIG_BT_CTLR_EXT_SCAN_FP) |
| u8_t direct; |
| #endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */ |
| #if defined(CONFIG_BT_HCI_MESH_EXT) |
| u8_t chan_idx; |
| #endif /* CONFIG_BT_HCI_MESH_EXT */ |
| }; |
| |
| |
| /* Header of node_rx_pdu */ |
| struct node_rx_hdr { |
| union { |
| void *next; |
| memq_link_t *link; |
| u8_t ack_last; |
| }; |
| |
| enum node_rx_type type; |
| u8_t user_meta; /* User metadata */ |
| u16_t handle; |
| |
| union { |
| #if defined(CONFIG_BT_CTLR_RX_PDU_META) |
| lll_rx_pdu_meta_t rx_pdu_meta; |
| #endif /* CONFIG_BT_CTLR_RX_PDU_META */ |
| struct node_rx_ftr rx_ftr; |
| }; |
| }; |
| |
| struct node_rx_pdu { |
| struct node_rx_hdr hdr; |
| u8_t pdu[0]; |
| }; |
| |
| enum { |
| EVENT_DONE_EXTRA_TYPE_NONE, |
| EVENT_DONE_EXTRA_TYPE_CONN, |
| /* Following proprietary defines must be at end of enum range */ |
| #if defined(CONFIG_BT_CTLR_USER_EXT) |
| EVENT_DONE_EXTRA_TYPE_USER_START, |
| EVENT_DONE_EXTRA_TYPE_USER_END = EVENT_DONE_EXTRA_TYPE_USER_START + |
| CONFIG_BT_CTLR_USER_EVT_RANGE, |
| #endif /* CONFIG_BT_CTLR_USER_EXT */ |
| |
| }; |
| |
| struct event_done_extra_slave { |
| u32_t start_to_address_actual_us; |
| u32_t window_widening_event_us; |
| u32_t preamble_to_addr_us; |
| }; |
| |
| struct event_done_extra { |
| u8_t type; |
| union { |
| struct { |
| u16_t trx_cnt; |
| u8_t crc_valid; |
| #if defined(CONFIG_BT_CTLR_LE_ENC) |
| u8_t mic_state; |
| #endif /* CONFIG_BT_CTLR_LE_ENC */ |
| union { |
| struct event_done_extra_slave slave; |
| }; |
| }; |
| }; |
| }; |
| |
| struct node_rx_event_done { |
| struct node_rx_hdr hdr; |
| void *param; |
| struct event_done_extra extra; |
| }; |
| |
| static inline void lll_hdr_init(void *lll, void *parent) |
| { |
| struct lll_hdr *hdr = lll; |
| |
| hdr->parent = parent; |
| hdr->is_stop = 0U; |
| } |
| |
| static inline int lll_stop(void *lll) |
| { |
| struct lll_hdr *hdr = lll; |
| int ret = !!hdr->is_stop; |
| |
| hdr->is_stop = 1U; |
| |
| return ret; |
| } |
| |
| static inline int lll_is_stop(void *lll) |
| { |
| struct lll_hdr *hdr = lll; |
| |
| return !!hdr->is_stop; |
| } |
| |
| int lll_init(void); |
| int lll_reset(void); |
| int lll_prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, |
| lll_prepare_cb_t prepare_cb, int prio, |
| struct lll_prepare_param *prepare_param); |
| void lll_resume(void *param); |
| void lll_disable(void *param); |
| u32_t lll_radio_is_idle(void); |
| s8_t lll_radio_tx_pwr_min_get(void); |
| s8_t lll_radio_tx_pwr_max_get(void); |
| s8_t lll_radio_tx_pwr_floor(s8_t tx_pwr_lvl); |
| |
| int ull_prepare_enqueue(lll_is_abort_cb_t is_abort_cb, |
| lll_abort_cb_t abort_cb, |
| struct lll_prepare_param *prepare_param, |
| lll_prepare_cb_t prepare_cb, int prio, |
| u8_t is_resume); |
| void *ull_prepare_dequeue_get(void); |
| void *ull_prepare_dequeue_iter(u8_t *idx); |
| void *ull_pdu_rx_alloc_peek(u8_t count); |
| void *ull_pdu_rx_alloc_peek_iter(u8_t *idx); |
| void *ull_pdu_rx_alloc(void); |
| void ull_rx_put(memq_link_t *link, void *rx); |
| void ull_rx_sched(void); |
| void *ull_event_done_extra_get(void); |
| void *ull_event_done(void *param); |