1 /*
2  * Copyright (c) 2017-2019 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  *  User CPR Interval
9  */
10 #if !defined(CONFIG_BT_CTLR_USER_CPR_INTERVAL_MIN)
11 #if defined(CONFIG_BT_CTLR_CONN_INTERVAL_LOW_LATENCY)
12 #define CONN_INTERVAL_MIN(x) (0U)
13 #else /* !CONFIG_BT_CTLR_CONN_INTERVAL_LOW_LATENCY */
14 /* Bluetooth defined CPR Interval Minimum (7.5ms) */
15 #define CONN_INTERVAL_MIN(x) (6U)
16 #endif /* !CONFIG_BT_CTLR_CONN_INTERVAL_LOW_LATENCY */
17 #else /* CONFIG_BT_CTLR_USER_CPR_INTERVAL_MIN */
18 /* Proprietary user defined CPR Interval Minimum */
19 #define CONN_INTERVAL_MIN(x) (MAX(ull_conn_interval_min_get(x), 1U))
20 #endif /* CONFIG_BT_CTLR_USER_CPR_INTERVAL_MIN */
21 
22 /**
23  *  User deference of CPR Anchor Point Move
24  */
25 #if !defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
26 #define DEFER_APM_CHECK(x, y, z) (false)
27 #else
28 /* Proprietary handling of peripheral CPR Anchor Point Movement Response
29  *
30  * When returning TRUE the LLCP system changes to a
31  * USER_WAIT state and an EXTERNAL trigger must kick the LLCP system
32  * to continue to either accept (with possibly changed offsets) or reject CPR
33  *
34  * When returning FALSE the LLCP system will automatically
35  * continue and thus respond immediately
36  *
37  * Possibly modified LLCP internal status/error state will determine the type of 'response'
38  *   0U                             - Accept CPR (possibly with changed offsets)
39  *   BT_HCI_ERR_UNSUPP_LL_PARAM_VAL - Reject CPR
40  */
41 struct ll_conn;
42 extern bool ull_handle_cpr_anchor_point_move(struct ll_conn *conn, uint16_t *offsets,
43 					     uint8_t *status);
44 #define DEFER_APM_CHECK(x, y, z) (ull_handle_cpr_anchor_point_move(x, y, z))
45 #endif /* CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE */
46 /* Macro to convert time in us to connection interval units */
47 #define RADIO_CONN_EVENTS(x, y) ((uint16_t)DIV_ROUND_UP(x, y))
48 
49 /* Macro to convert time in us to periodic advertising interval units */
50 #define RADIO_SYNC_EVENTS(x, y) ((uint16_t)DIV_ROUND_UP(x, y))
51 
52 /* Macro to mark address type as identity address from RPA (0x02, 0x03) */
53 #define MARK_AS_IDENTITY_ADDR(addr_type) ((addr_type) += 2U)
54 
ull_ref_get(struct ull_hdr * hdr)55 static inline uint8_t ull_ref_get(struct ull_hdr *hdr)
56 {
57 	return hdr->ref;
58 }
59 
ull_ref_inc(struct ull_hdr * hdr)60 static inline uint8_t ull_ref_inc(struct ull_hdr *hdr)
61 {
62 	return ++hdr->ref;
63 }
64 
ull_ref_dec(struct ull_hdr * hdr)65 static inline uint8_t ull_ref_dec(struct ull_hdr *hdr)
66 {
67 	return hdr->ref--;
68 }
69 
ull_hdr_init(struct ull_hdr * hdr)70 static inline void ull_hdr_init(struct ull_hdr *hdr)
71 {
72 	hdr->ref = 0U;
73 	hdr->disabled_cb = hdr->disabled_param = NULL;
74 }
75 
76 void *ll_rx_link_alloc(void);
77 void ll_rx_link_release(memq_link_t *link);
78 void *ll_rx_alloc(void);
79 void ll_rx_release(void *node_rx);
80 void *ll_pdu_rx_alloc_peek(uint8_t count);
81 void *ll_pdu_rx_alloc(void);
82 void ll_rx_put_sched(memq_link_t *link, void *rx);
83 void ll_rx_put(memq_link_t *link, void *rx);
84 void ll_rx_sched(void);
85 void ull_ticker_status_give(uint32_t status, void *param);
86 uint32_t ull_ticker_status_take(uint32_t ret, uint32_t volatile *ret_cb);
87 void *ull_disable_mark(void *param);
88 void *ull_disable_unmark(void *param);
89 void *ull_disable_mark_get(void);
90 int ull_ticker_stop_with_mark(uint8_t ticker_handle, void *param,
91 			      void *lll_disable);
92 void *ull_update_mark(void *param);
93 void *ull_update_unmark(void *param);
94 void *ull_update_mark_get(void);
95 int ull_disable(void *param);
96 void ull_drift_ticks_get(struct node_rx_event_done *done,
97 			 uint32_t *ticks_drift_plus,
98 			 uint32_t *ticks_drift_minus);
99 
100 /**
101  * @brief   RX FIFO macro frontend
102  * @details The RXFIFO data composite consists of an MFIFO with pointers to
103  *          data elements backed by a memory pool and memq link elements.
104  *          Link memq elements have a separate pool of (_count + _extra_links)
105  *          elements. Extra links may be used for initializing one or more
106  *          external memq instances. The following data structures are created
107  *          with RXFIFO_DEFINE():
108  *          - mfifo_<_name>:    FIFO with pointers to RX node elements.
109  *          - mem_<_name>:      Backing data pool of <_count> RX node elements
110  *                              of size <_size>.
111  *          - mem_link_<_name>: Pool of <_count + _extra_links> memq_link_t
112  *                              elements.
113  */
114 #define RXFIFO_DEFINE(_name, _size, _count, _extra_links) \
115 	MFIFO_DEFINE(_name, sizeof(void *), _count); \
116 	\
117 	static const struct { \
118 		uint16_t size; \
119 		uint8_t count; \
120 		uint8_t extra_links; \
121 	} mem_##_name = { .size = MROUND(_size), .count = _count, \
122 			  .extra_links = _extra_links }; \
123 	\
124 	static struct { \
125 		void *free; \
126 		uint8_t pool[MROUND(_size) * (_count)]; \
127 	} mem_pool_##_name; \
128 	\
129 	static struct { \
130 		void *free; \
131 		uint8_t pool[sizeof(memq_link_t) * (_count + _extra_links)]; \
132 	} mem_link_##_name
133 
134 /**
135  * @brief   Initializes MFIFO and pools
136  * @details This makes the MFIFO empty and will subsequently need
137  *          RXFIFO_ALLOC. Memory pools are initialized.
138  */
139 #define RXFIFO_INIT(_name) \
140 	MFIFO_INIT(_name); \
141 	mem_init(mem_pool_##_name.pool, mem_##_name.size, \
142 		 mem_##_name.count, &mem_pool_##_name.free); \
143 	\
144 	mem_init(mem_link_##_name.pool, sizeof(memq_link_t), \
145 		 (mem_##_name.count + mem_##_name.extra_links), \
146 		 &mem_link_##_name.free)
147 
148 /**
149  * @brief   Allocate FIFO elements with backing
150  * @details This function allocates up to <_count> number of MFIFO elements by
151  *          enqueuing pointers to memory elements with associated memq links.
152  */
153 #define RXFIFO_ALLOC(_name, _count) \
154 	ull_rxfifo_alloc(mfifo_##_name.s, mfifo_##_name.n, \
155 			 mfifo_fifo_##_name.f, &mfifo_fifo_##_name.l, \
156 			 mfifo_fifo_##_name.m, &mem_pool_##_name.free, \
157 			 &mem_link_##_name.free, _count)
158 
159 /**
160  * @brief Initialize and allocate MFIFO and pools
161  */
162 #define RXFIFO_INIT_ALLOC(_name) \
163 	RXFIFO_INIT(_name); \
164 	RXFIFO_ALLOC(_name, mem_##_name.count)
165 
166 /**
167  * @brief   Release RX node
168  * @details Enqueues an RX node back into the FIFO.
169  */
170 #define RXFIFO_RELEASE(_name, _link, _rx) \
171 	ull_rxfifo_release(mfifo_##_name.s, mfifo_##_name.n, \
172 			   mfifo_fifo_##_name.f, &mfifo_fifo_##_name.l, \
173 			   mfifo_fifo_##_name.m, _link, \
174 			   (struct node_rx_hdr *)_rx)
175 
176 void ull_rxfifo_alloc(uint8_t s, uint8_t n, uint8_t f, uint8_t *l, uint8_t *m,
177 		      void *mem_free, void *link_free, uint8_t max);
178 void *ull_rxfifo_release(uint8_t s, uint8_t n, uint8_t f, uint8_t *l, uint8_t *m,
179 			 memq_link_t *link, struct node_rx_hdr *rx);
180 uint32_t ull_get_wrapped_time_us(uint32_t time_now_us, int32_t time_diff_us);
181