1 /*
2 * Copyright (c) 2017-2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define ULL_ADV_RANDOM_DELAY HAL_TICKER_US_TO_TICKS(10000)
8
9 /* Bitmask value returned by ull_adv_is_enabled() */
10 #define ULL_ADV_ENABLED_BITMASK_ENABLED BIT(0)
11
12 /* Helper defined to check if Extended Advertising HCI commands used */
13 #define LL_ADV_CMDS_ANY 0 /* Any advertising cmd/evt allowed */
14 #define LL_ADV_CMDS_LEGACY 1 /* Only legacy advertising cmd/evt allowed */
15 #define LL_ADV_CMDS_EXT 2 /* Only extended advertising cmd/evt allowed */
16
17 /* Helper function to check if Extended Advertising HCI commands used */
18 int ll_adv_cmds_is_ext(void);
19
20 /* Helper functions to initialise and reset ull_adv module */
21 int ull_adv_init(void);
22 int ull_adv_reset(void);
23 int ull_adv_reset_finalize(void);
24
25 /* Return ll_adv_set context (unconditional) */
26 struct ll_adv_set *ull_adv_set_get(uint8_t handle);
27
28 /* Return the adv set handle given the adv set instance */
29 uint16_t ull_adv_handle_get(struct ll_adv_set *adv);
30
31 /* Return ll_adv_set context if enabled */
32 struct ll_adv_set *ull_adv_is_enabled_get(uint8_t handle);
33
34 /* Return enabled status of a set */
35 int ull_adv_is_enabled(uint8_t handle);
36
37 /* Return filter policy used */
38 uint32_t ull_adv_filter_pol_get(uint8_t handle);
39
40 /* Return ll_adv_set context if created */
41 struct ll_adv_set *ull_adv_is_created_get(uint8_t handle);
42
43 /* Helper function to construct AD data */
44 uint8_t ull_adv_data_set(struct ll_adv_set *adv, uint8_t len,
45 uint8_t const *const data);
46
47 /* Helper function to construct SR data */
48 uint8_t ull_scan_rsp_set(struct ll_adv_set *adv, uint8_t len,
49 uint8_t const *const data);
50
51 /* Update AdvA and TgtA (if application) in advertising PDU */
52 const uint8_t *ull_adv_pdu_update_addrs(struct ll_adv_set *adv,
53 struct pdu_adv *pdu);
54
55 /* Helper to update primary channel advertising event time reservation */
56 uint8_t ull_adv_time_update(struct ll_adv_set *adv, struct pdu_adv *pdu,
57 struct pdu_adv *pdu_scan);
58
59 #if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_CTLR_JIT_SCHEDULING)
60 /* helper function to handle adv done events */
61 void ull_adv_done(struct node_rx_event_done *done);
62 #endif /* CONFIG_BT_CTLR_ADV_EXT || CONFIG_BT_CTLR_JIT_SCHEDULING */
63
64 /* Enumeration provides flags for management of memory for extra_data
65 * related with advertising PDUs.
66 */
67 enum ull_adv_pdu_extra_data_flag {
68 /* Allocate extra_data memory if it was available in former PDU */
69 ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
70 /* Allocate extra_data memory no matter if it was available */
71 ULL_ADV_PDU_EXTRA_DATA_ALLOC_ALWAYS,
72 /* Never allocate new memory for extra_data */
73 ULL_ADV_PDU_EXTRA_DATA_ALLOC_NEVER
74 };
75
76 /* Helper functions to initialise and reset ull_adv_aux module */
77 int ull_adv_aux_init(void);
78 int ull_adv_aux_reset_finalize(void);
79
80 /* Return the aux set handle given the aux set instance */
81 uint8_t ull_adv_aux_handle_get(struct ll_adv_aux_set *aux);
82
83 /* Helper function to apply Channel Map Update for auxiliary PDUs */
84 uint8_t ull_adv_aux_chm_update(void);
85
86 /* helper function to initialize event timings */
87 uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux,
88 uint32_t *ticks_anchor);
89
90 /* helper function to start auxiliary advertising */
91 uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
92 uint32_t ticks_slot_overhead);
93
94 /* helper function to stop auxiliary advertising */
95 int ull_adv_aux_stop(struct ll_adv_aux_set *aux);
96
97 /* helper function to acquire and initialize auxiliary advertising instance */
98 struct ll_adv_aux_set *ull_adv_aux_acquire(struct lll_adv *lll);
99
100 /* helper function to release auxiliary advertising instance */
101 void ull_adv_aux_release(struct ll_adv_aux_set *aux);
102
103 /* helper function to give the auxiliary context */
104 struct ll_adv_aux_set *ull_adv_aux_get(uint8_t handle);
105
106 /* helper function to return time reservation for auxiliary PDU */
107 uint32_t ull_adv_aux_time_get(const struct ll_adv_aux_set *aux, uint8_t pdu_len,
108 uint8_t pdu_scan_len);
109
110 /* helper function to schedule a mayfly to get aux offset */
111 void ull_adv_aux_offset_get(struct ll_adv_set *adv);
112
113 /* Below are BT Spec v5.2, Vol 6, Part B Section 2.3.4 Table 2.12 defined */
114 #define ULL_ADV_PDU_HDR_FIELD_NONE 0
115 #define ULL_ADV_PDU_HDR_FIELD_ADVA BIT(0)
116 #define ULL_ADV_PDU_HDR_FIELD_TARGETA BIT(1)
117 #define ULL_ADV_PDU_HDR_FIELD_CTE_INFO BIT(2)
118 #define ULL_ADV_PDU_HDR_FIELD_ADI BIT(3)
119 #define ULL_ADV_PDU_HDR_FIELD_AUX_PTR BIT(4)
120 #define ULL_ADV_PDU_HDR_FIELD_SYNC_INFO BIT(5)
121 #define ULL_ADV_PDU_HDR_FIELD_TX_POWER BIT(6)
122 #define ULL_ADV_PDU_HDR_FIELD_RFU BIT(7)
123 /* Below are implementation defined bit fields */
124 #define ULL_ADV_PDU_HDR_FIELD_ACAD BIT(8)
125 #define ULL_ADV_PDU_HDR_FIELD_AD_DATA BIT(9)
126 #define ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND BIT(10)
127
128 /* helper defined for field offsets in the hdr_set_clear interfaces */
129 #define ULL_ADV_HDR_DATA_LEN_OFFSET 0
130 #define ULL_ADV_HDR_DATA_LEN_SIZE 1
131 #define ULL_ADV_HDR_DATA_CTE_INFO_OFFSET 0
132 #define ULL_ADV_HDR_DATA_CTE_INFO_SIZE (sizeof(struct pdu_cte_info))
133 #define ULL_ADV_HDR_DATA_ADI_PTR_OFFSET 1
134 #define ULL_ADV_HDR_DATA_ADI_PTR_SIZE (sizeof(uint8_t *))
135 #define ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET 1
136 #define ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE (sizeof(uint8_t *))
137 #define ULL_ADV_HDR_DATA_ACAD_PTR_OFFSET 1
138 #define ULL_ADV_HDR_DATA_ACAD_PTR_SIZE (sizeof(uint8_t *))
139 #define ULL_ADV_HDR_DATA_DATA_PTR_OFFSET 1
140 #define ULL_ADV_HDR_DATA_DATA_PTR_SIZE (sizeof(uint8_t *))
141
142 /* helper function to set/clear common extended header format fields */
143 uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
144 uint16_t sec_hdr_add_fields,
145 uint16_t sec_hdr_rem_fields,
146 void *value,
147 uint8_t *pri_idx, uint8_t *sec_idx);
148
149 /* helper function to set/clear common extended header format fields for
150 * auxiliary PDU
151 */
152 uint8_t ull_adv_aux_pdu_set_clear(struct ll_adv_set *adv,
153 struct pdu_adv *pdu_prev,
154 struct pdu_adv *pdu,
155 uint16_t hdr_add_fields,
156 uint16_t hdr_rem_fields,
157 void *hdr_data);
158
159 /* helper to initialize extended advertising PDU */
160 void ull_adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags,
161 uint8_t phy_s, uint8_t phy_flags,
162 struct pdu_cte_info *cte_info);
163
164 /* helper to add cte_info field to extended advertising header */
165 uint8_t ull_adv_sync_pdu_cte_info_set(struct pdu_adv *pdu, const struct pdu_cte_info *cte_info);
166
167 #if defined(CONFIG_BT_CTLR_ADV_EXT)
168 /* notify adv_set that an aux instance has been created for it */
169 void ull_adv_aux_created(struct ll_adv_set *adv);
170
171 /* helper to get information whether ADI field is avaialbe in extended advertising PDU */
ull_adv_sync_pdu_had_adi(const struct pdu_adv * pdu)172 static inline bool ull_adv_sync_pdu_had_adi(const struct pdu_adv *pdu)
173 {
174 return pdu->adv_ext_ind.ext_hdr.adi;
175 }
176 /* helper function to calculate common ext adv payload header length and
177 * adjust the data pointer.
178 * NOTE: This function reverts the header data pointer if there is no
179 * header fields flags set, and hence no header fields have been
180 * populated.
181 */
182 static inline uint8_t
ull_adv_aux_hdr_len_calc(struct pdu_adv_com_ext_adv * com_hdr,uint8_t ** dptr)183 ull_adv_aux_hdr_len_calc(struct pdu_adv_com_ext_adv *com_hdr, uint8_t **dptr)
184 {
185 uint8_t len;
186
187 len = *dptr - (uint8_t *)com_hdr;
188 if (len <= (PDU_AC_EXT_HEADER_SIZE_MIN +
189 sizeof(struct pdu_adv_ext_hdr))) {
190 len = PDU_AC_EXT_HEADER_SIZE_MIN;
191 *dptr = (uint8_t *)com_hdr + len;
192 }
193
194 return len;
195 }
196
197 /* helper function to fill common ext adv payload header length */
198 static inline void
ull_adv_aux_hdr_len_fill(struct pdu_adv_com_ext_adv * com_hdr,uint8_t len)199 ull_adv_aux_hdr_len_fill(struct pdu_adv_com_ext_adv *com_hdr, uint8_t len)
200 {
201 com_hdr->ext_hdr_len = len - PDU_AC_EXT_HEADER_SIZE_MIN;
202 }
203
204 /* notify adv_aux_set that a sync instance has been started/stopped for it */
205 void ull_adv_sync_started_stopped(struct ll_adv_aux_set *aux);
206
207 /* notify adv_sync_set that an iso instance has been created for it */
208 void ull_adv_iso_created(struct ll_adv_sync_set *sync);
209
210 #endif /* CONFIG_BT_CTLR_ADV_EXT */
211
212 /* helper function to get next unique DID value */
213 uint16_t ull_adv_aux_did_next_unique_get(uint8_t sid);
214
215 /* helper function to fill the aux ptr structure in common ext adv payload */
216 void ull_adv_aux_ptr_fill(struct pdu_adv_aux_ptr *aux_ptr, uint32_t offs_us,
217 uint8_t phy_s);
218
219 /* helper function to handle adv aux done events */
220 void ull_adv_aux_done(struct node_rx_event_done *done);
221
222 /* helper function to duplicate chain PDUs */
223 void ull_adv_aux_chain_pdu_duplicate(struct pdu_adv *pdu_prev,
224 struct pdu_adv *pdu,
225 struct pdu_adv_aux_ptr *aux_ptr,
226 uint8_t phy_s, uint8_t phy_flags,
227 uint32_t mafs_us);
228 int ull_adv_sync_init(void);
229 int ull_adv_sync_reset(void);
230 int ull_adv_sync_reset_finalize(void);
231
232 /* Return ll_adv_sync_set context (unconditional) */
233 struct ll_adv_sync_set *ull_adv_sync_get(uint8_t handle);
234
235 /* Return the aux set handle given the sync set instance */
236 uint16_t ull_adv_sync_handle_get(const struct ll_adv_sync_set *sync);
237
238 /* helper function to release periodic advertising instance */
239 void ull_adv_sync_release(struct ll_adv_sync_set *sync);
240
241 /* helper function to return event time reservation */
242 uint32_t ull_adv_sync_time_get(const struct ll_adv_sync_set *sync,
243 uint8_t pdu_len);
244
245 /* helper function to calculate ticks_slot and return slot overhead */
246 uint32_t ull_adv_sync_evt_init(struct ll_adv_set *adv,
247 struct ll_adv_sync_set *sync,
248 struct pdu_adv *pdu);
249
250 /* helper function to start periodic advertising */
251 uint32_t ull_adv_sync_start(struct ll_adv_set *adv,
252 struct ll_adv_sync_set *sync,
253 uint32_t ticks_anchor,
254 uint32_t ticks_slot_overhead);
255
256 /* helper function to update periodic advertising event time reservation */
257 uint8_t ull_adv_sync_time_update(struct ll_adv_sync_set *sync,
258 struct pdu_adv *pdu);
259
260 /* helper function to initial channel map update indications */
261 uint8_t ull_adv_sync_chm_update(void);
262
263 /* helper function to cleanup after channel map update indications complete */
264 void ull_adv_sync_chm_complete(struct node_rx_hdr *rx);
265
266 /* helper function to fill initial value of sync_info structure */
267 void ull_adv_sync_info_fill(struct ll_adv_sync_set *sync,
268 struct pdu_adv_sync_info *si);
269
270 /* helper function to allocate new PDU data for AUX_SYNC_IND and return
271 * previous and new PDU for further processing.
272 */
273 uint8_t ull_adv_sync_pdu_alloc(struct ll_adv_set *adv,
274 enum ull_adv_pdu_extra_data_flag extra_data_flags,
275 struct pdu_adv **ter_pdu_prev, struct pdu_adv **ter_pdu_new,
276 void **extra_data_prev, void **extra_data_new, uint8_t *ter_idx);
277
278 /* helper function to set/clear common extended header format fields
279 * for AUX_SYNC_IND PDU.
280 */
281 uint8_t ull_adv_sync_pdu_set_clear(struct lll_adv_sync *lll_sync, struct pdu_adv *ter_pdu_prev,
282 struct pdu_adv *ter_pdu, uint16_t hdr_add_fields,
283 uint16_t hdr_rem_fields, void *hdr_data);
284
285 /* helper function to update extra_data field */
286 void ull_adv_sync_extra_data_set_clear(void *extra_data_prev,
287 void *extra_data_new,
288 uint16_t hdr_add_fields,
289 uint16_t hdr_rem_fields,
290 void *data);
291
292 /* helper function to schedule a mayfly to get sync offset */
293 void ull_adv_sync_offset_get(struct ll_adv_set *adv);
294
295 int ull_adv_iso_init(void);
296 int ull_adv_iso_reset(void);
297
298 /* Return ll_adv_iso_set context (unconditional) */
299 struct ll_adv_iso_set *ull_adv_iso_get(uint8_t handle);
300
301 /* helper function to initial channel map update indications */
302 uint8_t ull_adv_iso_chm_update(void);
303
304 /* helper function to cleanup after channel map update complete */
305 void ull_adv_iso_chm_complete(struct node_rx_hdr *rx);
306
307 /* helper function to schedule a mayfly to get BIG offset */
308 void ull_adv_iso_offset_get(struct ll_adv_sync_set *sync);
309
310 /* helper function to handle adv ISO done BIG complete events */
311 void ull_adv_iso_done_complete(struct node_rx_event_done *done);
312
313 /* helper function to handle adv ISO done BIG terminate events */
314 void ull_adv_iso_done_terminate(struct node_rx_event_done *done);
315
316 /* helper function to return adv_iso instance */
317 struct ll_adv_iso_set *ull_adv_iso_by_stream_get(uint16_t handle);
318
319 /* helper function to return adv_iso stream instance */
320 struct lll_adv_iso_stream *ull_adv_iso_stream_get(uint16_t handle);
321
322 /* helper function to release stream instances */
323 void ull_adv_iso_stream_release(struct ll_adv_iso_set *adv_iso);
324
325 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
326 /* helper function to release unused DF configuration memory */
327 void ull_df_adv_cfg_release(struct lll_df_adv_cfg *df_adv_cfg);
328 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
329