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