1 /*
2  * Copyright (c) 2017-2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <soc.h>
9 #include <zephyr/bluetooth/hci_types.h>
10 #include <zephyr/sys/byteorder.h>
11 
12 #include "hal/cpu.h"
13 #include "hal/ccm.h"
14 #include "hal/ticker.h"
15 
16 #include "util/util.h"
17 #include "util/mem.h"
18 #include "util/memq.h"
19 #include "util/mayfly.h"
20 #include "util/dbuf.h"
21 
22 #include "ticker/ticker.h"
23 
24 #include "pdu_df.h"
25 #include "lll/pdu_vendor.h"
26 #include "pdu.h"
27 
28 #include "lll.h"
29 #include "lll_clock.h"
30 #include "lll/lll_vendor.h"
31 #include "lll/lll_adv_types.h"
32 #include "lll_adv.h"
33 #include "lll/lll_adv_pdu.h"
34 #include "lll_adv_sync.h"
35 #include "lll/lll_df_types.h"
36 #include "lll_conn.h"
37 #include "lll_chan.h"
38 
39 #include "ull_adv_types.h"
40 
41 #include "ull_internal.h"
42 #include "ull_chan_internal.h"
43 #include "ull_sched_internal.h"
44 #include "ull_adv_internal.h"
45 
46 #include "ll.h"
47 
48 #include "hal/debug.h"
49 
50 static int init_reset(void);
51 static uint8_t adv_type_check(struct ll_adv_set *adv);
52 static inline struct ll_adv_sync_set *sync_acquire(void);
53 static inline void sync_release(struct ll_adv_sync_set *sync);
54 static inline uint16_t sync_handle_get(const struct ll_adv_sync_set *sync);
55 static uint32_t sync_time_get(const struct ll_adv_sync_set *sync,
56 			      const struct pdu_adv *pdu);
57 static inline uint8_t sync_remove(struct ll_adv_sync_set *sync,
58 				  struct ll_adv_set *adv, uint8_t enable);
59 static uint8_t sync_chm_update(uint8_t handle);
60 
61 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
62 static void sync_info_offset_fill(struct pdu_adv_sync_info *si, uint32_t offs);
63 
64 #else /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
65 static void mfy_sync_offset_get(void *param);
66 static void sync_info_offset_fill(struct pdu_adv_sync_info *si,
67 				  uint32_t ticks_offset,
68 				  uint32_t remainder_us,
69 				  uint32_t start_us);
70 static void ticker_op_cb(uint32_t status, void *param);
71 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
72 
73 static struct pdu_adv_sync_info *sync_info_get(struct pdu_adv *pdu);
74 static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
75 		      uint32_t remainder, uint16_t lazy, uint8_t force,
76 		      void *param);
77 
78 #if defined(CONFIG_BT_CTLR_ADV_ISO) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
79 static void ticker_update_op_cb(uint32_t status, void *param);
80 
81 static struct ticker_ext ll_adv_sync_ticker_ext[CONFIG_BT_CTLR_ADV_SYNC_SET];
82 #endif /* !CONFIG_BT_CTLR_ADV_ISO  && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
83 
84 static struct ll_adv_sync_set ll_adv_sync_pool[CONFIG_BT_CTLR_ADV_SYNC_SET];
85 static void *adv_sync_free;
86 
ll_adv_sync_param_set(uint8_t handle,uint16_t interval,uint16_t flags)87 uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
88 {
89 	void *extra_data_prev, *extra_data;
90 	struct pdu_adv *pdu_prev, *pdu;
91 	struct lll_adv_sync *lll_sync;
92 	struct ll_adv_sync_set *sync;
93 	struct ll_adv_set *adv;
94 	uint8_t err, ter_idx;
95 
96 	adv = ull_adv_is_created_get(handle);
97 	if (!adv) {
98 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
99 	}
100 
101 	if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
102 		uint8_t err;
103 
104 		err = adv_type_check(adv);
105 		if (err) {
106 			return err;
107 		}
108 	}
109 
110 	lll_sync = adv->lll.sync;
111 	if (!lll_sync) {
112 		struct pdu_adv *ter_pdu;
113 		struct lll_adv *lll;
114 		uint8_t chm_last;
115 		int err;
116 
117 		sync = sync_acquire();
118 		if (!sync) {
119 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
120 		}
121 
122 		lll = &adv->lll;
123 		lll_sync = &sync->lll;
124 		lll->sync = lll_sync;
125 		lll_sync->adv = lll;
126 
127 		lll_adv_data_reset(&lll_sync->data);
128 		err = lll_adv_sync_data_init(&lll_sync->data);
129 		if (err) {
130 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
131 		}
132 
133 		/* NOTE: ull_hdr_init(&sync->ull); is done on start */
134 		lll_hdr_init(lll_sync, sync);
135 
136 		err = util_aa_le32(lll_sync->access_addr);
137 		LL_ASSERT(!err);
138 
139 		lll_sync->data_chan_id = lll_chan_id(lll_sync->access_addr);
140 		chm_last = lll_sync->chm_first;
141 		lll_sync->chm_last = chm_last;
142 		lll_sync->chm[chm_last].data_chan_count =
143 			ull_chan_map_get(lll_sync->chm[chm_last].data_chan_map);
144 
145 		lll_csrand_get(lll_sync->crc_init, sizeof(lll_sync->crc_init));
146 
147 		lll_sync->latency_prepare = 0;
148 		lll_sync->latency_event = 0;
149 		lll_sync->event_counter = 0;
150 
151 		sync->is_enabled = 0U;
152 		sync->is_started = 0U;
153 
154 		ter_pdu = lll_adv_sync_data_peek(lll_sync, NULL);
155 		ull_adv_sync_pdu_init(ter_pdu, 0U, 0U, 0U, NULL);
156 	} else {
157 		sync = HDR_LLL2ULL(lll_sync);
158 	}
159 
160 	/* Periodic Advertising is already started */
161 	if (sync->is_started) {
162 		return BT_HCI_ERR_CMD_DISALLOWED;
163 	}
164 
165 	sync->interval = interval;
166 
167 	err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST, &pdu_prev, &pdu,
168 				     &extra_data_prev, &extra_data, &ter_idx);
169 	if (err) {
170 		return err;
171 	}
172 
173 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
174 	if (extra_data) {
175 		ull_adv_sync_extra_data_set_clear(extra_data_prev, extra_data,
176 						  0U, 0U, NULL);
177 	}
178 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
179 
180 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
181 	/* Duplicate chain PDUs */
182 	do {
183 		struct pdu_adv *pdu_chain;
184 
185 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
186 		err = ull_adv_sync_pdu_set_clear(lll_sync, pdu_prev, pdu,
187 						 0U, 0U, NULL);
188 		if (err) {
189 			return err;
190 		}
191 
192 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
193 		pdu_prev = lll_adv_pdu_linked_next_get(pdu_prev);
194 		pdu_chain = lll_adv_pdu_linked_next_get(pdu);
195 
196 		/* Allocate new chain PDU if required */
197 		if (pdu_prev) {
198 			/* Prior PDU chain allocation valid */
199 			if (pdu_chain) {
200 				pdu = pdu_chain;
201 
202 				continue;
203 			}
204 
205 			/* Get a new chain PDU */
206 			pdu_chain = lll_adv_pdu_alloc_pdu_adv();
207 			if (!pdu_chain) {
208 				return BT_HCI_ERR_INSUFFICIENT_RESOURCES;
209 			}
210 
211 			/* Link the chain PDU to parent PDU */
212 			lll_adv_pdu_linked_append(pdu_chain, pdu);
213 
214 			/* continue back to update the new PDU */
215 			pdu = pdu_chain;
216 		}
217 	} while (pdu_prev);
218 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
219 
220 	lll_adv_sync_data_enqueue(lll_sync, ter_idx);
221 
222 	sync->is_data_cmplt = 1U;
223 
224 	return 0;
225 }
226 
227 #if defined(CONFIG_BT_CTLR_ADV_ISO) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ull_adv_iso_created(struct ll_adv_sync_set * sync)228 void ull_adv_iso_created(struct ll_adv_sync_set *sync)
229 {
230 	if (sync->lll.iso && sync->is_started) {
231 		uint8_t iso_handle = sync->lll.iso->handle;
232 		uint8_t handle = sync_handle_get(sync);
233 
234 		ticker_update_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
235 			   (TICKER_ID_ADV_SYNC_BASE + handle), 0, 0, 0, 0, 0, 0,
236 			   ticker_update_op_cb, sync, 0, TICKER_ID_ADV_ISO_BASE + iso_handle);
237 	}
238 }
239 #endif /* CONFIG_BT_CTLR_ADV_ISO && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
240 
ll_adv_sync_ad_data_set(uint8_t handle,uint8_t op,uint8_t len,uint8_t const * const data)241 uint8_t ll_adv_sync_ad_data_set(uint8_t handle, uint8_t op, uint8_t len,
242 				uint8_t const *const data)
243 {
244 	uint8_t hdr_data[ULL_ADV_HDR_DATA_LEN_SIZE +
245 			 ULL_ADV_HDR_DATA_DATA_PTR_SIZE +
246 			 ULL_ADV_HDR_DATA_LEN_SIZE +
247 			 ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE +
248 			 ULL_ADV_HDR_DATA_LEN_SIZE];
249 	void *extra_data_prev, *extra_data;
250 	struct pdu_adv *pdu_prev, *pdu;
251 	struct lll_adv_sync *lll_sync;
252 	struct ll_adv_sync_set *sync;
253 	struct ll_adv_set *adv;
254 	uint8_t *val_ptr;
255 	uint8_t ter_idx;
256 	uint8_t err;
257 
258 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
259 	uint8_t ad_len_overflow;
260 	uint8_t ad_len_chain;
261 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
262 
263 	/* Check for valid advertising set */
264 	adv =  ull_adv_is_created_get(handle);
265 	if (!adv) {
266 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
267 	}
268 
269 	/* Check for advertising set type */
270 	if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
271 		uint8_t err;
272 
273 		err = adv_type_check(adv);
274 		if (err) {
275 			return err;
276 		}
277 	}
278 
279 	/* Check if periodic advertising is associated with advertising set */
280 	lll_sync = adv->lll.sync;
281 	if (!lll_sync) {
282 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
283 	}
284 
285 	sync = HDR_LLL2ULL(lll_sync);
286 
287 	/* Reject setting fragment when periodic advertising is enabled */
288 	if (sync->is_enabled && (op <= BT_HCI_LE_EXT_ADV_OP_LAST_FRAG)) {
289 		return BT_HCI_ERR_CMD_DISALLOWED;
290 	}
291 
292 	/* Reject intermediate op before first op */
293 	if (sync->is_data_cmplt &&
294 	    ((op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG) ||
295 	     (op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG))) {
296 		return BT_HCI_ERR_CMD_DISALLOWED;
297 	}
298 
299 	/* Reject unchanged op before complete status */
300 	if (!sync->is_data_cmplt &&
301 	    (op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA)) {
302 		return BT_HCI_ERR_CMD_DISALLOWED;
303 	}
304 
305 	/* Reject first, intermediate, last operation and len > 191 bytes if
306 	 * chain PDUs unsupported.
307 	 */
308 	if (!IS_ENABLED(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK) &&
309 	    ((op < BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA) ||
310 	     (len > PDU_AC_EXT_AD_DATA_LEN_MAX))) {
311 		return BT_HCI_ERR_CMD_DISALLOWED;
312 	}
313 
314 	/* Allocate new PDU buffer at latest double buffer index */
315 	err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
316 				     &pdu_prev, &pdu, &extra_data_prev,
317 				     &extra_data, &ter_idx);
318 	if (err) {
319 		return err;
320 	}
321 
322 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
323 	if (extra_data) {
324 		ull_adv_sync_extra_data_set_clear(extra_data_prev, extra_data,
325 						  0U, 0U, NULL);
326 	}
327 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
328 
329 	/* Prepare the AD data as parameter to update in PDU */
330 	/* Use length = 0 and NULL pointer to retain old data in the PDU.
331 	 * Use length = 0 and valid pointer of `data` (auto/local variable) to
332 	 * remove old data.
333 	 * User length > 0 and valid pointer of `data` (auto/local variable) to
334 	 * set new data.
335 	 */
336 	val_ptr = hdr_data;
337 	if (op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG ||
338 	    op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG ||
339 	    op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA) {
340 		*val_ptr++ = 0U;
341 		(void)memset((void *)val_ptr, 0U,
342 			     ULL_ADV_HDR_DATA_DATA_PTR_SIZE);
343 	} else {
344 		*val_ptr++ = len;
345 		(void)memcpy(val_ptr, &data, sizeof(data));
346 	}
347 
348 	if (!IS_ENABLED(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK) ||
349 	    (op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA)) {
350 		err = ull_adv_sync_pdu_set_clear(lll_sync, pdu_prev, pdu,
351 						 ULL_ADV_PDU_HDR_FIELD_AD_DATA,
352 						 0U, hdr_data);
353 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
354 		/* No AD data overflow */
355 		ad_len_overflow = 0U;
356 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
357 	} else if (!IS_ENABLED(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK) ||
358 		   (op == BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG ||
359 		    op == BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA)) {
360 		/* Add AD Data and remove any prior presence of Aux Ptr */
361 		err = ull_adv_sync_pdu_set_clear(lll_sync, pdu_prev, pdu,
362 						 ULL_ADV_PDU_HDR_FIELD_AD_DATA,
363 						 ULL_ADV_PDU_HDR_FIELD_AUX_PTR,
364 						 hdr_data);
365 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
366 		if (!err) {
367 			/* Fragment into chain PDU if len > 191 bytes */
368 			if (len > PDU_AC_EXT_AD_DATA_LEN_MAX) {
369 				/* Prepare the AD data as parameter to update in
370 				 * PDU
371 				 */
372 				val_ptr = hdr_data;
373 				*val_ptr++ = PDU_AC_EXT_AD_DATA_LEN_MAX;
374 				(void)memcpy(val_ptr, &data, sizeof(data));
375 
376 				/* Traverse to next set clear hdr data
377 				 * parameter, as aux ptr reference to be
378 				 * returned, hence second parameter will be for
379 				 * AD data field.
380 				 */
381 				val_ptr += sizeof(data);
382 
383 				*val_ptr = PDU_AC_EXT_AD_DATA_LEN_MAX;
384 				(void)memcpy(&val_ptr[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET],
385 					     &data, sizeof(data));
386 
387 				/* Calculate the overflow chain PDU's AD data
388 				 * length
389 				 */
390 				ad_len_overflow =
391 					len - PDU_AC_EXT_AD_DATA_LEN_MAX;
392 
393 				/* No AD data in chain PDU besides the
394 				 * overflow
395 				 */
396 				ad_len_chain = 0U;
397 			} else {
398 				struct pdu_adv *pdu_chain;
399 
400 				/* Remove/Release any previous chain PDU
401 				 * allocations
402 				 */
403 				pdu_chain = lll_adv_pdu_linked_next_get(pdu);
404 				if (pdu_chain) {
405 					lll_adv_pdu_linked_append(NULL, pdu);
406 					lll_adv_pdu_linked_release_all(pdu_chain);
407 				}
408 
409 				/* No AD data overflow */
410 				ad_len_overflow = 0U;
411 			}
412 		}
413 	} else {
414 		struct pdu_adv *pdu_chain_prev;
415 		struct pdu_adv *pdu_chain;
416 		uint16_t ad_len_total;
417 		uint8_t ad_len_prev;
418 
419 		/* Traverse to next set clear hdr data parameter */
420 		val_ptr += sizeof(data);
421 
422 		/* Traverse to the last chain PDU */
423 		ad_len_total = 0U;
424 		pdu_chain_prev = pdu_prev;
425 		pdu_chain = pdu;
426 		do {
427 			/* Prepare for aux ptr field reference to be returned, hence
428 			 * second parameter will be for AD data field.
429 			 */
430 			*val_ptr = 0U;
431 			(void)memset((void *)&val_ptr[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET],
432 				     0U, ULL_ADV_HDR_DATA_DATA_PTR_SIZE);
433 
434 			pdu_prev = pdu_chain_prev;
435 			pdu = pdu_chain;
436 
437 			/* Add Aux Ptr field if not already present */
438 			err = ull_adv_sync_pdu_set_clear(lll_sync, pdu_prev,
439 					pdu, (ULL_ADV_PDU_HDR_FIELD_AD_DATA |
440 					      ULL_ADV_PDU_HDR_FIELD_AUX_PTR),
441 					0, hdr_data);
442 			LL_ASSERT(!err || (err == BT_HCI_ERR_PACKET_TOO_LONG));
443 
444 			/* Get PDUs previous AD data length */
445 			ad_len_prev =
446 				hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET +
447 					 ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE];
448 
449 			/* Check of max supported AD data len */
450 			ad_len_total += ad_len_prev;
451 			if ((ad_len_total + len) >
452 			    CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) {
453 				/* NOTE: latest PDU was not consumed by LLL and
454 				 * as ull_adv_sync_pdu_alloc() has reverted back
455 				 * the double buffer with the first PDU, and
456 				 * returned the latest PDU as the new PDU, we
457 				 * need to enqueue back the new PDU which is
458 				 * infact the latest PDU.
459 				 */
460 				if (pdu_prev == pdu) {
461 					lll_adv_sync_data_enqueue(lll_sync, ter_idx);
462 				}
463 
464 				return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
465 			}
466 
467 			pdu_chain_prev = lll_adv_pdu_linked_next_get(pdu_prev);
468 			pdu_chain = lll_adv_pdu_linked_next_get(pdu);
469 			LL_ASSERT((pdu_chain_prev && pdu_chain) ||
470 				  (!pdu_chain_prev && !pdu_chain));
471 		} while (pdu_chain_prev);
472 
473 		if (err == BT_HCI_ERR_PACKET_TOO_LONG) {
474 			ad_len_overflow =
475 				hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET +
476 					 ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE +
477 					 ULL_ADV_HDR_DATA_DATA_PTR_OFFSET +
478 					 ULL_ADV_HDR_DATA_DATA_PTR_SIZE];
479 
480 			/* Prepare for aux ptr field reference to be returned,
481 			 * hence second parameter will be for AD data field.
482 			 * Fill it with reduced AD data length.
483 			 */
484 			*val_ptr = ad_len_prev - ad_len_overflow;
485 
486 			/* AD data len in chain PDU */
487 			ad_len_chain = len;
488 
489 			/* Proceed to add chain PDU */
490 			err = 0U;
491 		} else {
492 			ad_len_overflow = 0U;
493 		}
494 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
495 	}
496 	if (err) {
497 		return err;
498 	}
499 
500 	/* Parameter validation, if operation is 0x04 (unchanged data)
501 	 * - periodic advertising is disabled, or
502 	 * - periodic advertising contains no data, or
503 	 * - Advertising Data Length is not zero
504 	 */
505 	if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK) &&
506 	    (op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA) &&
507 	    ((!sync->is_enabled) ||
508 	     (hdr_data[ULL_ADV_HDR_DATA_LEN_OFFSET] == 0U) ||
509 	     (len != 0U))) {
510 		/* NOTE: latest PDU was not consumed by LLL and as
511 		 * ull_adv_sync_pdu_alloc() has reverted back the double buffer
512 		 * with the first PDU, and returned the latest PDU as the new
513 		 * PDU, we need to enqueue back the new PDU which is infact
514 		 * the latest PDU.
515 		 */
516 		if (pdu_prev == pdu) {
517 			lll_adv_sync_data_enqueue(lll_sync, ter_idx);
518 		}
519 
520 		return BT_HCI_ERR_INVALID_PARAM;
521 	}
522 
523 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
524 	if ((op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG) ||
525 	    (op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG) ||
526 	    ad_len_overflow) {
527 		struct pdu_adv_com_ext_adv *com_hdr_chain;
528 		struct pdu_adv_com_ext_adv *com_hdr;
529 		struct pdu_adv_ext_hdr *hdr_chain;
530 		struct pdu_adv_aux_ptr *aux_ptr;
531 		struct pdu_adv *pdu_chain_prev;
532 		struct pdu_adv_ext_hdr hdr;
533 		struct pdu_adv *pdu_chain;
534 		uint8_t *dptr_chain;
535 		uint32_t offs_us;
536 		uint16_t ter_len;
537 		uint8_t *dptr;
538 
539 		/* Get reference to flags in superior PDU */
540 		com_hdr = &pdu->adv_ext_ind;
541 		if (com_hdr->ext_hdr_len) {
542 			hdr = com_hdr->ext_hdr;
543 		} else {
544 			*(uint8_t *)&hdr = 0U;
545 		}
546 		dptr = com_hdr->ext_hdr.data;
547 
548 		/* Allocate new PDU */
549 		pdu_chain = lll_adv_pdu_alloc_pdu_adv();
550 		LL_ASSERT(pdu_chain);
551 
552 		/* Populate the appended chain PDU */
553 		pdu_chain->type = PDU_ADV_TYPE_AUX_CHAIN_IND;
554 		pdu_chain->rfu = 0U;
555 		pdu_chain->chan_sel = 0U;
556 		pdu_chain->tx_addr = 0U;
557 		pdu_chain->rx_addr = 0U;
558 		pdu_chain->len = 0U;
559 
560 		com_hdr_chain = &pdu_chain->adv_ext_ind;
561 		hdr_chain = (void *)&com_hdr_chain->ext_hdr_adv_data[0];
562 		dptr_chain = (void *)hdr_chain;
563 
564 		/* Initialize Flags */
565 		*dptr_chain = 0U;
566 
567 		/* No CTE Info.
568 		 * CTE count is given by HCI LE Set Connectionless CTE Transmit
569 		 * Parameters, hence it is not altered due to change on PDUs
570 		 * count in Periodic Advertising chain.
571 		 */
572 
573 		/* ADI flag, mandatory if superior PDU has it */
574 		if (hdr.adi) {
575 			hdr_chain->adi = 1U;
576 		}
577 
578 		/* Proceed to next byte if any flags present */
579 		if (*dptr_chain) {
580 			dptr_chain++;
581 		}
582 
583 		/* Start adding fields corresponding to flags here, if any */
584 
585 		/* No AdvA */
586 		/* No TgtA */
587 		/* No CTEInfo */
588 
589 		/* ADI flag */
590 		if (hdr_chain->adi) {
591 			(void)memcpy(dptr_chain, dptr,
592 				     sizeof(struct pdu_adv_adi));
593 
594 			dptr += sizeof(struct pdu_adv_adi);
595 			dptr_chain += sizeof(struct pdu_adv_adi);
596 		}
597 
598 		/* non-connectable non-scannable chain pdu */
599 		com_hdr_chain->adv_mode = 0;
600 
601 		/* Calc current chain PDU len */
602 		ter_len = ull_adv_aux_hdr_len_calc(com_hdr_chain, &dptr_chain);
603 
604 		/* Prefix overflowed data to chain PDU and reduce the AD data in
605 		 * in the current PDU.
606 		 */
607 		if (ad_len_overflow) {
608 			uint8_t *ad_overflow;
609 
610 			/* Copy overflowed AD data from previous PDU into
611 			 * new chain PDU
612 			 */
613 			(void)memcpy(&ad_overflow,
614 				     &val_ptr[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET],
615 				     sizeof(ad_overflow));
616 			ad_overflow += *val_ptr;
617 			(void)memcpy(dptr_chain, ad_overflow, ad_len_overflow);
618 			dptr_chain += ad_len_overflow;
619 
620 			/* Reduce the AD data in the current PDU that will
621 			 * become the current parent PDU for the new chain PDU.
622 			 */
623 			err = ull_adv_sync_pdu_set_clear(lll_sync, pdu_prev, pdu,
624 							 (ULL_ADV_PDU_HDR_FIELD_AD_DATA |
625 							  ULL_ADV_PDU_HDR_FIELD_AUX_PTR),
626 							 0, hdr_data);
627 			if (err) {
628 				/* NOTE: latest PDU was not consumed by LLL and
629 				 * as ull_adv_sync_pdu_alloc() has reverted back
630 				 * the double buffer with the first PDU, and
631 				 * returned the latest PDU as the new PDU, we
632 				 * need to enqueue back the new PDU which is
633 				 * infact the latest PDU.
634 				 */
635 				if (pdu_prev == pdu) {
636 					lll_adv_sync_data_enqueue(lll_sync, ter_idx);
637 				}
638 
639 				return err;
640 			}
641 
642 			/* AD data len in chain PDU besides the overflow */
643 			len = ad_len_chain;
644 		}
645 
646 		/* Check AdvData overflow */
647 		if ((ter_len + ad_len_overflow + len) >
648 		    PDU_AC_PAYLOAD_SIZE_MAX) {
649 			/* NOTE: latest PDU was not consumed by LLL and
650 			 * as ull_adv_sync_pdu_alloc() has reverted back
651 			 * the double buffer with the first PDU, and
652 			 * returned the latest PDU as the new PDU, we
653 			 * need to enqueue back the new PDU which is
654 			 * infact the latest PDU.
655 			 */
656 			if (pdu_prev == pdu) {
657 				lll_adv_sync_data_enqueue(lll_sync, ter_idx);
658 			}
659 
660 			return BT_HCI_ERR_PACKET_TOO_LONG;
661 		}
662 
663 		/* Fill the chain PDU length */
664 		ull_adv_aux_hdr_len_fill(com_hdr_chain, ter_len);
665 		pdu_chain->len = ter_len + ad_len_overflow + len;
666 
667 		/* Fill AD Data in chain PDU */
668 		(void)memcpy(dptr_chain, data, len);
669 
670 		/* Get reference to aux ptr in superior PDU */
671 		(void)memcpy(&aux_ptr,
672 			     &hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET],
673 			     sizeof(aux_ptr));
674 
675 		/* Fill the aux offset in the previous AUX_SYNC_IND PDU */
676 		offs_us = PDU_AC_US(pdu->len, adv->lll.phy_s,
677 				    adv->lll.phy_flags) +
678 			  EVENT_SYNC_B2B_MAFS_US;
679 		ull_adv_aux_ptr_fill(aux_ptr, offs_us, adv->lll.phy_s);
680 
681 		/* Remove/Release any previous chain PDUs */
682 		pdu_chain_prev = lll_adv_pdu_linked_next_get(pdu);
683 		if (pdu_chain_prev) {
684 			lll_adv_pdu_linked_append(NULL, pdu);
685 			lll_adv_pdu_linked_release_all(pdu_chain_prev);
686 		}
687 
688 		/* Chain the PDU */
689 		lll_adv_pdu_linked_append(pdu_chain, pdu);
690 	}
691 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
692 
693 	/* Update time reservation if Periodic Advertising events are active */
694 	if (sync->is_started) {
695 		err = ull_adv_sync_time_update(sync, pdu);
696 		if (err) {
697 			return err;
698 		}
699 	}
700 
701 	/* Commit the updated Periodic Advertising Data */
702 	lll_adv_sync_data_enqueue(lll_sync, ter_idx);
703 
704 	/* Check if Periodic Advertising Data is complete */
705 	sync->is_data_cmplt = (op >= BT_HCI_LE_EXT_ADV_OP_LAST_FRAG);
706 
707 	return 0;
708 }
709 
ll_adv_sync_enable(uint8_t handle,uint8_t enable)710 uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
711 {
712 	struct pdu_adv *ter_pdu = NULL;
713 	struct lll_adv_sync *lll_sync;
714 	struct ll_adv_sync_set *sync;
715 	uint8_t sync_got_enabled;
716 	struct ll_adv_set *adv;
717 	uint8_t ter_idx;
718 	uint8_t err;
719 
720 	/* Check for valid advertising set */
721 	adv = ull_adv_is_created_get(handle);
722 	if (!adv) {
723 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
724 	}
725 
726 	/* Check if periodic advertising is associated with advertising set */
727 	lll_sync = adv->lll.sync;
728 	if (!lll_sync) {
729 		return BT_HCI_ERR_CMD_DISALLOWED;
730 	}
731 
732 	/* Check for invalid enable bit fields */
733 	if ((enable > (BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE |
734 		       BT_HCI_LE_SET_PER_ADV_ENABLE_ADI)) ||
735 	    (!IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT) &&
736 	     (enable > BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE))) {
737 		return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
738 	}
739 
740 	sync = HDR_LLL2ULL(lll_sync);
741 
742 	/* Handle periodic advertising being disable */
743 	if (!(enable & BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE)) {
744 		if (!sync->is_enabled) {
745 			return BT_HCI_ERR_CMD_DISALLOWED;
746 		}
747 
748 		if (!sync->is_started) {
749 			sync->is_enabled = 0U;
750 
751 			return 0;
752 		}
753 
754 		err = sync_remove(sync, adv, 0U);
755 		return err;
756 	}
757 
758 	/* Check for advertising set type */
759 	if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
760 		uint8_t err;
761 
762 		err = adv_type_check(adv);
763 		if (err) {
764 			return BT_HCI_ERR_CMD_DISALLOWED;
765 		}
766 	}
767 
768 	/* Check for periodic data being complete */
769 	if (!sync->is_data_cmplt) {
770 		return BT_HCI_ERR_CMD_DISALLOWED;
771 	}
772 
773 	/* TODO: Check packet too long */
774 
775 	/* Check for already enabled periodic advertising set */
776 	sync_got_enabled = 0U;
777 	if (sync->is_enabled) {
778 		/* TODO: Enabling an already enabled advertising changes its
779 		 * random address.
780 		 */
781 	} else {
782 		sync_got_enabled = 1U;
783 	}
784 
785 	/* Add/Remove ADI */
786 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)) {
787 		uint8_t hdr_data[ULL_ADV_HDR_DATA_LEN_SIZE +
788 				 ULL_ADV_HDR_DATA_ADI_PTR_SIZE] = {0, };
789 		void *extra_data_prev, *extra_data;
790 		struct pdu_adv *pdu_prev, *pdu;
791 		uint16_t hdr_add_fields;
792 		uint16_t hdr_rem_fields;
793 
794 		if (enable & BT_HCI_LE_SET_PER_ADV_ENABLE_ADI) {
795 			hdr_add_fields = ULL_ADV_PDU_HDR_FIELD_ADI;
796 			hdr_rem_fields = 0U;
797 		} else {
798 			hdr_add_fields = 0U;
799 			hdr_rem_fields = ULL_ADV_PDU_HDR_FIELD_ADI;
800 		}
801 
802 		err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
803 					     &pdu_prev, &pdu, &extra_data_prev,
804 					     &extra_data, &ter_idx);
805 		if (err) {
806 			return err;
807 		}
808 
809 		/* Use PDU to calculate time reservation */
810 		ter_pdu = pdu;
811 
812 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
813 		if (extra_data) {
814 			ull_adv_sync_extra_data_set_clear(extra_data_prev,
815 							  extra_data, 0U, 0U,
816 							  NULL);
817 		}
818 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
819 
820 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
821 		/* Update ADI while duplicating chain PDUs */
822 		do {
823 			struct pdu_adv *pdu_chain;
824 
825 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
826 			err = ull_adv_sync_pdu_set_clear(lll_sync, pdu_prev,
827 							 pdu, hdr_add_fields,
828 							 hdr_rem_fields,
829 							 hdr_data);
830 			if (err) {
831 				return err;
832 			}
833 
834 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
835 			pdu_prev = lll_adv_pdu_linked_next_get(pdu_prev);
836 			pdu_chain = lll_adv_pdu_linked_next_get(pdu);
837 
838 			/* Allocate new chain PDU if required */
839 			if (pdu_prev) {
840 				/* Prior PDU chain allocation valid */
841 				if (pdu_chain) {
842 					pdu = pdu_chain;
843 
844 					continue;
845 				}
846 
847 				/* Get a new chain PDU */
848 				pdu_chain = lll_adv_pdu_alloc_pdu_adv();
849 				if (!pdu_chain) {
850 					return BT_HCI_ERR_INSUFFICIENT_RESOURCES;
851 				}
852 
853 				/* Link the chain PDU to parent PDU */
854 				lll_adv_pdu_linked_append(pdu_chain, pdu);
855 
856 				/* continue back to update the new PDU */
857 				pdu = pdu_chain;
858 			}
859 		} while (pdu_prev);
860 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
861 	}
862 
863 	/* Start Periodic Advertising events if Extended Advertising events are
864 	 * active.
865 	 */
866 	if (adv->is_enabled && !sync->is_started) {
867 		struct pdu_adv_sync_info *sync_info;
868 		uint8_t value[1 + sizeof(sync_info)];
869 		uint32_t ticks_slot_overhead_aux;
870 		uint32_t ticks_slot_overhead;
871 		struct lll_adv_aux *lll_aux;
872 		struct ll_adv_aux_set *aux;
873 		uint32_t ticks_anchor_sync;
874 		uint32_t ticks_anchor_aux;
875 		uint8_t pri_idx, sec_idx;
876 		uint32_t ret;
877 
878 		lll_aux = adv->lll.aux;
879 
880 		/* Add sync_info into auxiliary PDU */
881 		err = ull_adv_aux_hdr_set_clear(adv,
882 						ULL_ADV_PDU_HDR_FIELD_SYNC_INFO,
883 						0U, value, &pri_idx, &sec_idx);
884 		if (err) {
885 			return err;
886 		}
887 
888 		/* First byte in the length-value encoded parameter is size of
889 		 * sync_info structure, followed by pointer to sync_info in the
890 		 * PDU.
891 		 */
892 		(void)memcpy(&sync_info, &value[1], sizeof(sync_info));
893 		ull_adv_sync_info_fill(sync, sync_info);
894 
895 		/* Calculate the ticks_slot and return slot overhead */
896 		ticks_slot_overhead = ull_adv_sync_evt_init(adv, sync, ter_pdu);
897 
898 		/* If Auxiliary PDU already active, find and schedule Periodic
899 		 * advertising follow it.
900 		 */
901 		if (lll_aux) {
902 			/* Auxiliary set already active (due to other fields
903 			 * being already present or being started prior).
904 			 */
905 			aux = NULL;
906 			ticks_anchor_aux = 0U; /* unused in this path */
907 			ticks_slot_overhead_aux = 0U; /* unused in this path */
908 
909 			/* Find the anchor after the group of active auxiliary
910 			 * sets such that Periodic Advertising events are placed
911 			 * in non-overlapping timeline when auxiliary and
912 			 * Periodic Advertising have similar event interval.
913 			 */
914 			ticks_anchor_sync = ticker_ticks_now_get() +
915 				HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
916 
917 #if defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
918 			err = ull_sched_adv_aux_sync_free_anchor_get(sync->ull.ticks_slot,
919 								     &ticks_anchor_sync);
920 			if (!err) {
921 				ticks_anchor_sync += HAL_TICKER_US_TO_TICKS(
922 					MAX(EVENT_MAFS_US,
923 					    EVENT_OVERHEAD_START_US) -
924 					EVENT_OVERHEAD_START_US +
925 					(EVENT_TICKER_RES_MARGIN_US << 1));
926 			}
927 #endif /* CONFIG_BT_CTLR_SCHED_ADVANCED */
928 
929 		} else {
930 			/* Auxiliary set will be started due to inclusion of
931 			 * sync info field.
932 			 */
933 			lll_aux = adv->lll.aux;
934 			aux = HDR_LLL2ULL(lll_aux);
935 			ticks_anchor_aux = ticker_ticks_now_get() +
936 				HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
937 			ticks_slot_overhead_aux =
938 				ull_adv_aux_evt_init(aux, &ticks_anchor_aux);
939 
940 #if !defined(CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET) || \
941 	(CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET == 0)
942 			ticks_anchor_sync = ticks_anchor_aux +
943 				ticks_slot_overhead_aux + aux->ull.ticks_slot +
944 				HAL_TICKER_US_TO_TICKS(
945 					MAX(EVENT_MAFS_US,
946 					    EVENT_OVERHEAD_START_US) -
947 					EVENT_OVERHEAD_START_US +
948 					(EVENT_TICKER_RES_MARGIN_US << 1));
949 
950 #else /* CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET */
951 			ticks_anchor_sync = ticks_anchor_aux +
952 				HAL_TICKER_US_TO_TICKS(
953 					CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET);
954 
955 #endif /* CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET */
956 		}
957 
958 		ret = ull_adv_sync_start(adv, sync, ticks_anchor_sync,
959 					 ticks_slot_overhead);
960 		if (ret) {
961 			sync_remove(sync, adv, 1U);
962 
963 			return BT_HCI_ERR_INSUFFICIENT_RESOURCES;
964 		}
965 
966 		sync->is_started = 1U;
967 
968 		lll_adv_aux_data_enqueue(lll_aux, sec_idx);
969 		lll_adv_data_enqueue(&adv->lll, pri_idx);
970 
971 		if (aux) {
972 			/* Keep aux interval equal or higher than primary PDU
973 			 * interval.
974 			 */
975 			aux->interval = adv->interval +
976 					(HAL_TICKER_TICKS_TO_US(
977 						ULL_ADV_RANDOM_DELAY) /
978 						ADV_INT_UNIT_US);
979 
980 			ret = ull_adv_aux_start(aux, ticks_anchor_aux,
981 						ticks_slot_overhead_aux);
982 			if (ret) {
983 				sync_remove(sync, adv, 1U);
984 
985 				return BT_HCI_ERR_INSUFFICIENT_RESOURCES;
986 			}
987 
988 			aux->is_started = 1U;
989 
990 		} else if (IS_ENABLED(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)) {
991 			/* notify the auxiliary set */
992 			ull_adv_sync_started_stopped(HDR_LLL2ULL(lll_aux));
993 		}
994 	}
995 
996 	/* Commit the Periodic Advertising data if ADI supported and has been
997 	 * updated.
998 	 */
999 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)) {
1000 		lll_adv_sync_data_enqueue(lll_sync, ter_idx);
1001 	}
1002 
1003 	if (sync_got_enabled) {
1004 		sync->is_enabled = sync_got_enabled;
1005 	}
1006 
1007 	return 0;
1008 }
1009 
ull_adv_sync_init(void)1010 int ull_adv_sync_init(void)
1011 {
1012 	int err;
1013 
1014 	err = init_reset();
1015 	if (err) {
1016 		return err;
1017 	}
1018 
1019 	return 0;
1020 }
1021 
ull_adv_sync_reset(void)1022 int ull_adv_sync_reset(void)
1023 {
1024 	struct lll_adv_sync *lll_sync;
1025 	struct ll_adv_sync_set *sync;
1026 	struct ll_adv_set *adv;
1027 	uint8_t handle;
1028 	int err;
1029 
1030 	for (handle = 0U; handle < BT_CTLR_ADV_SET; handle++) {
1031 		adv = ull_adv_is_created_get(handle);
1032 		if (!adv) {
1033 			continue;
1034 		}
1035 
1036 		lll_sync = adv->lll.sync;
1037 		if (!lll_sync) {
1038 			continue;
1039 		}
1040 
1041 		sync = HDR_LLL2ULL(lll_sync);
1042 
1043 		if (!sync->is_started) {
1044 			sync->is_enabled = 0U;
1045 
1046 			continue;
1047 		}
1048 
1049 		err = sync_remove(sync, adv, 0U);
1050 		if (err) {
1051 			return err;
1052 		}
1053 	}
1054 
1055 	return 0;
1056 }
1057 
ull_adv_sync_reset_finalize(void)1058 int ull_adv_sync_reset_finalize(void)
1059 {
1060 	int err;
1061 
1062 	err = init_reset();
1063 	if (err) {
1064 		return err;
1065 	}
1066 
1067 	return 0;
1068 }
1069 
ull_adv_sync_get(uint8_t handle)1070 struct ll_adv_sync_set *ull_adv_sync_get(uint8_t handle)
1071 {
1072 	if (handle >= CONFIG_BT_CTLR_ADV_SYNC_SET) {
1073 		return NULL;
1074 	}
1075 
1076 	return &ll_adv_sync_pool[handle];
1077 }
1078 
ull_adv_sync_handle_get(const struct ll_adv_sync_set * sync)1079 uint16_t ull_adv_sync_handle_get(const struct ll_adv_sync_set *sync)
1080 {
1081 	return sync_handle_get(sync);
1082 }
1083 
ull_adv_sync_lll_handle_get(const struct lll_adv_sync * lll)1084 uint16_t ull_adv_sync_lll_handle_get(const struct lll_adv_sync *lll)
1085 {
1086 	return sync_handle_get((void *)lll->hdr.parent);
1087 }
1088 
ull_adv_sync_release(struct ll_adv_sync_set * sync)1089 void ull_adv_sync_release(struct ll_adv_sync_set *sync)
1090 {
1091 	lll_adv_sync_data_release(&sync->lll);
1092 	sync_release(sync);
1093 }
1094 
ull_adv_sync_time_get(const struct ll_adv_sync_set * sync,uint8_t pdu_len)1095 uint32_t ull_adv_sync_time_get(const struct ll_adv_sync_set *sync,
1096 			       uint8_t pdu_len)
1097 {
1098 	const struct lll_adv_sync *lll_sync = &sync->lll;
1099 	const struct lll_adv *lll = lll_sync->adv;
1100 	uint32_t time_us;
1101 
1102 	/* NOTE: 16-bit values are sufficient for minimum radio event time
1103 	 *       reservation, 32-bit are used here so that reservations for
1104 	 *       whole back-to-back chaining of PDUs can be accommodated where
1105 	 *       the required microseconds could overflow 16-bits, example,
1106 	 *       back-to-back chained Coded PHY PDUs.
1107 	 */
1108 
1109 	time_us = PDU_AC_US(pdu_len, lll->phy_s, lll->phy_flags) +
1110 		  EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
1111 
1112 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1113 	struct ll_adv_set *adv = HDR_LLL2ULL(lll);
1114 	struct lll_df_adv_cfg *df_cfg = adv->df_cfg;
1115 
1116 	if (df_cfg && df_cfg->is_enabled) {
1117 		time_us += CTE_LEN_US(df_cfg->cte_length);
1118 	}
1119 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1120 
1121 	return time_us;
1122 }
1123 
ull_adv_sync_evt_init(struct ll_adv_set * adv,struct ll_adv_sync_set * sync,struct pdu_adv * pdu)1124 uint32_t ull_adv_sync_evt_init(struct ll_adv_set *adv,
1125 			       struct ll_adv_sync_set *sync,
1126 			       struct pdu_adv *pdu)
1127 {
1128 	uint32_t ticks_slot_overhead;
1129 	uint32_t ticks_slot_offset;
1130 	uint32_t time_us;
1131 
1132 	ull_hdr_init(&sync->ull);
1133 
1134 	if (!pdu) {
1135 		pdu = lll_adv_sync_data_peek(&sync->lll, NULL);
1136 	}
1137 
1138 	time_us = sync_time_get(sync, pdu);
1139 
1140 	/* TODO: active_to_start feature port */
1141 	sync->ull.ticks_active_to_start = 0U;
1142 	sync->ull.ticks_prepare_to_start =
1143 		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
1144 	sync->ull.ticks_preempt_to_start =
1145 		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
1146 	sync->ull.ticks_slot = HAL_TICKER_US_TO_TICKS(time_us);
1147 
1148 	ticks_slot_offset = MAX(sync->ull.ticks_active_to_start,
1149 				sync->ull.ticks_prepare_to_start);
1150 	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
1151 		ticks_slot_overhead = ticks_slot_offset;
1152 	} else {
1153 		ticks_slot_overhead = 0U;
1154 	}
1155 
1156 	return ticks_slot_overhead;
1157 }
1158 
ull_adv_sync_start(struct ll_adv_set * adv,struct ll_adv_sync_set * sync,uint32_t ticks_anchor,uint32_t ticks_slot_overhead)1159 uint32_t ull_adv_sync_start(struct ll_adv_set *adv,
1160 			    struct ll_adv_sync_set *sync,
1161 			    uint32_t ticks_anchor,
1162 			    uint32_t ticks_slot_overhead)
1163 {
1164 	uint32_t volatile ret_cb;
1165 	uint32_t interval_us;
1166 	uint8_t sync_handle;
1167 	uint32_t ret;
1168 
1169 	interval_us = (uint32_t)sync->interval * PERIODIC_INT_UNIT_US;
1170 
1171 	sync_handle = sync_handle_get(sync);
1172 
1173 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
1174 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
1175 	if (sync->lll.iso) {
1176 		ll_adv_sync_ticker_ext[sync_handle].expire_info_id =
1177 			TICKER_ID_ADV_ISO_BASE + sync->lll.iso->handle;
1178 	} else {
1179 		ll_adv_sync_ticker_ext[sync_handle].expire_info_id = TICKER_NULL;
1180 	}
1181 
1182 	ll_adv_sync_ticker_ext[sync_handle].ext_timeout_func = ticker_cb;
1183 
1184 	ret_cb = TICKER_STATUS_BUSY;
1185 	ret = ticker_start_ext(
1186 #else /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
1187 
1188 	ret_cb = TICKER_STATUS_BUSY;
1189 	ret = ticker_start(
1190 #endif /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
1191 			   TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
1192 			   (TICKER_ID_ADV_SYNC_BASE + sync_handle),
1193 			   ticks_anchor, 0U,
1194 			   HAL_TICKER_US_TO_TICKS(interval_us),
1195 			   HAL_TICKER_REMAINDER(interval_us), TICKER_NULL_LAZY,
1196 			   (sync->ull.ticks_slot + ticks_slot_overhead),
1197 			   ticker_cb, sync,
1198 			   ull_ticker_status_give, (void *)&ret_cb
1199 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
1200 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
1201 			   ,
1202 			   &ll_adv_sync_ticker_ext[sync_handle]
1203 #endif /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
1204 			   );
1205 	ret = ull_ticker_status_take(ret, &ret_cb);
1206 
1207 	return ret;
1208 }
1209 
ull_adv_sync_time_update(struct ll_adv_sync_set * sync,struct pdu_adv * pdu)1210 uint8_t ull_adv_sync_time_update(struct ll_adv_sync_set *sync,
1211 				 struct pdu_adv *pdu)
1212 {
1213 	uint32_t volatile ret_cb;
1214 	uint32_t ticks_minus;
1215 	uint32_t ticks_plus;
1216 	uint32_t time_ticks;
1217 	uint32_t time_us;
1218 	uint32_t ret;
1219 
1220 	time_us = sync_time_get(sync, pdu);
1221 	time_ticks = HAL_TICKER_US_TO_TICKS(time_us);
1222 	if (sync->ull.ticks_slot > time_ticks) {
1223 		ticks_minus = sync->ull.ticks_slot - time_ticks;
1224 		ticks_plus = 0U;
1225 	} else if (sync->ull.ticks_slot < time_ticks) {
1226 		ticks_minus = 0U;
1227 		ticks_plus = time_ticks - sync->ull.ticks_slot;
1228 	} else {
1229 		return BT_HCI_ERR_SUCCESS;
1230 	}
1231 
1232 	ret_cb = TICKER_STATUS_BUSY;
1233 	ret = ticker_update(TICKER_INSTANCE_ID_CTLR,
1234 			    TICKER_USER_ID_THREAD,
1235 			    (TICKER_ID_ADV_SYNC_BASE + sync_handle_get(sync)),
1236 			    0, 0, ticks_plus, ticks_minus, 0, 0,
1237 			    ull_ticker_status_give, (void *)&ret_cb);
1238 	ret = ull_ticker_status_take(ret, &ret_cb);
1239 	if (ret != TICKER_STATUS_SUCCESS) {
1240 		return BT_HCI_ERR_CMD_DISALLOWED;
1241 	}
1242 
1243 	sync->ull.ticks_slot = time_ticks;
1244 
1245 	return BT_HCI_ERR_SUCCESS;
1246 }
1247 
ull_adv_sync_chm_update(void)1248 uint8_t ull_adv_sync_chm_update(void)
1249 {
1250 	uint8_t handle;
1251 
1252 	handle = CONFIG_BT_CTLR_ADV_SYNC_SET;
1253 	while (handle--) {
1254 		(void)sync_chm_update(handle);
1255 	}
1256 
1257 	/* TODO: Should failure due to Channel Map Update being already in
1258 	 *       progress be returned to caller?
1259 	 */
1260 	return 0;
1261 }
1262 
ull_adv_sync_chm_complete(struct node_rx_hdr * rx)1263 void ull_adv_sync_chm_complete(struct node_rx_hdr *rx)
1264 {
1265 	uint8_t hdr_data[ULL_ADV_HDR_DATA_LEN_SIZE +
1266 			 ULL_ADV_HDR_DATA_ACAD_PTR_SIZE];
1267 	struct lll_adv_sync *lll_sync;
1268 	struct pdu_adv *pdu_prev;
1269 	struct ll_adv_set *adv;
1270 	struct pdu_adv *pdu;
1271 	uint8_t acad_len;
1272 	uint8_t *others;
1273 	uint8_t ter_idx;
1274 	uint8_t ad_len;
1275 	uint8_t *acad;
1276 	uint8_t *ad;
1277 	uint8_t len;
1278 	uint8_t err;
1279 
1280 	/* Allocate next Sync PDU */
1281 	pdu_prev = NULL;
1282 	pdu = NULL;
1283 	lll_sync = rx->rx_ftr.param;
1284 	adv = HDR_LLL2ULL(lll_sync->adv);
1285 	err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
1286 				     &pdu_prev, &pdu, NULL, NULL, &ter_idx);
1287 	LL_ASSERT(!err);
1288 
1289 	/* Get the size of current ACAD, first octet returns the old length and
1290 	 * followed by pointer to previous offset to ACAD in the PDU.
1291 	 */
1292 	hdr_data[ULL_ADV_HDR_DATA_LEN_OFFSET] = 0U;
1293 	err = ull_adv_sync_pdu_set_clear(lll_sync, pdu_prev, pdu,
1294 					 ULL_ADV_PDU_HDR_FIELD_ACAD, 0U,
1295 					 &hdr_data);
1296 	LL_ASSERT(!err);
1297 
1298 	/* Dev assert if ACAD empty */
1299 	LL_ASSERT(hdr_data[ULL_ADV_HDR_DATA_LEN_OFFSET]);
1300 
1301 	/* Find the Channel Map Update Indication */
1302 	acad_len = hdr_data[ULL_ADV_HDR_DATA_LEN_OFFSET];
1303 	len = acad_len;
1304 	(void)memcpy(&acad, &hdr_data[ULL_ADV_HDR_DATA_ACAD_PTR_OFFSET],
1305 		     sizeof(acad));
1306 	ad = acad;
1307 	do {
1308 		ad_len = ad[PDU_ADV_DATA_HEADER_LEN_OFFSET];
1309 		if (ad_len &&
1310 		    (ad[PDU_ADV_DATA_HEADER_TYPE_OFFSET] ==
1311 		     PDU_ADV_DATA_TYPE_CHANNEL_MAP_UPDATE_IND)) {
1312 			break;
1313 		}
1314 
1315 		ad_len += 1U;
1316 
1317 		LL_ASSERT(ad_len <= len);
1318 
1319 		ad += ad_len;
1320 		len -= ad_len;
1321 	} while (len);
1322 	LL_ASSERT(len);
1323 
1324 	/* Remove Channel Map Update Indication by moving other AD types that
1325 	 * are after it.
1326 	 */
1327 	ad_len += 1U;
1328 	others = ad + ad_len;
1329 	acad_len -= ad_len;
1330 	(void)memmove(ad, others, acad_len);
1331 
1332 	/* Adjust the next PDU for ACAD length, this is done by using the next
1333 	 * PDU to copy ACAD into same next PDU.
1334 	 */
1335 	hdr_data[ULL_ADV_HDR_DATA_LEN_OFFSET] = acad_len;
1336 	err = ull_adv_sync_pdu_set_clear(lll_sync, pdu, pdu,
1337 					 ULL_ADV_PDU_HDR_FIELD_ACAD, 0U,
1338 					 &hdr_data);
1339 	LL_ASSERT(!err);
1340 
1341 	lll_adv_sync_data_enqueue(lll_sync, ter_idx);
1342 }
1343 
ull_adv_sync_info_fill(struct ll_adv_sync_set * sync,struct pdu_adv_sync_info * si)1344 void ull_adv_sync_info_fill(struct ll_adv_sync_set *sync,
1345 			    struct pdu_adv_sync_info *si)
1346 {
1347 	struct lll_adv_sync *lll_sync;
1348 
1349 	/* NOTE: sync offset and offset unit filled by secondary prepare.
1350 	 *
1351 	 * If sync_info is part of ADV PDU the offs_adjust field
1352 	 * is always set to 0.
1353 	 */
1354 	si->offs_units = OFFS_UNIT_VALUE_30_US;
1355 	si->offs_adjust = 0U;
1356 	si->offs = 0U;
1357 
1358 	/* Fill the interval, access address and CRC init */
1359 	si->interval = sys_cpu_to_le16(sync->interval);
1360 	lll_sync = &sync->lll;
1361 	(void)memcpy(&si->aa, lll_sync->access_addr, sizeof(si->aa));
1362 	(void)memcpy(si->crc_init, lll_sync->crc_init, sizeof(si->crc_init));
1363 
1364 	/* NOTE: Filled by secondary prepare */
1365 	si->evt_cntr = 0U;
1366 }
1367 
1368 #if !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ull_adv_sync_offset_get(struct ll_adv_set * adv)1369 void ull_adv_sync_offset_get(struct ll_adv_set *adv)
1370 {
1371 	static memq_link_t link;
1372 	static struct mayfly mfy = {0, 0, &link, NULL, mfy_sync_offset_get};
1373 	uint32_t ret;
1374 
1375 	mfy.param = adv;
1376 	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
1377 			     &mfy);
1378 	LL_ASSERT(!ret);
1379 }
1380 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
1381 
ull_adv_sync_pdu_init(struct pdu_adv * pdu,uint8_t ext_hdr_flags,uint8_t phy_s,uint8_t phy_flags,struct pdu_cte_info * cte_info)1382 void ull_adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags,
1383 			   uint8_t phy_s, uint8_t phy_flags,
1384 			   struct pdu_cte_info *cte_info)
1385 {
1386 	struct pdu_adv_com_ext_adv *com_hdr;
1387 	struct pdu_adv_ext_hdr *ext_hdr;
1388 	struct pdu_adv_aux_ptr *aux_ptr;
1389 	uint32_t cte_len_us;
1390 	uint8_t *dptr;
1391 	uint8_t len;
1392 
1393 	pdu->type = PDU_ADV_TYPE_AUX_SYNC_IND;
1394 	pdu->rfu = 0U;
1395 	pdu->chan_sel = 0U;
1396 
1397 	pdu->tx_addr = 0U;
1398 	pdu->rx_addr = 0U;
1399 
1400 	com_hdr = &pdu->adv_ext_ind;
1401 	/* Non-connectable and Non-scannable adv mode */
1402 	com_hdr->adv_mode = 0U;
1403 
1404 	ext_hdr = &com_hdr->ext_hdr;
1405 	*(uint8_t *)ext_hdr = ext_hdr_flags;
1406 	dptr = ext_hdr->data;
1407 
1408 	LL_ASSERT(!(ext_hdr_flags & (ULL_ADV_PDU_HDR_FIELD_ADVA | ULL_ADV_PDU_HDR_FIELD_TARGETA |
1409 #if !defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1410 				     ULL_ADV_PDU_HDR_FIELD_ADI |
1411 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1412 				     ULL_ADV_PDU_HDR_FIELD_SYNC_INFO)));
1413 
1414 	if (IS_ENABLED(CONFIG_BT_CTLR_DF_ADV_CTE_TX) &&
1415 	    (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_CTE_INFO)) {
1416 		(void)memcpy(dptr, cte_info, sizeof(*cte_info));
1417 		cte_len_us = CTE_LEN_US(cte_info->time);
1418 		dptr += sizeof(struct pdu_cte_info);
1419 	} else {
1420 		cte_len_us = 0U;
1421 	}
1422 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT) &&
1423 	    (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_ADI)) {
1424 		dptr += sizeof(struct pdu_adv_adi);
1425 	}
1426 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK) &&
1427 	    (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_AUX_PTR)) {
1428 		aux_ptr = (void *)dptr;
1429 		dptr += sizeof(struct pdu_adv_aux_ptr);
1430 	}
1431 	if (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_TX_POWER) {
1432 		dptr += sizeof(uint8_t);
1433 	}
1434 
1435 	/* Calc tertiary PDU len */
1436 	len = ull_adv_aux_hdr_len_calc(com_hdr, &dptr);
1437 	ull_adv_aux_hdr_len_fill(com_hdr, len);
1438 
1439 	pdu->len = len;
1440 
1441 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
1442 	/* Fill aux offset in aux pointer field */
1443 	if (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) {
1444 		uint32_t offs_us;
1445 
1446 		offs_us = PDU_AC_US(pdu->len, phy_s, phy_flags) +
1447 			  EVENT_SYNC_B2B_MAFS_US;
1448 		offs_us += cte_len_us;
1449 		ull_adv_aux_ptr_fill(aux_ptr, offs_us, phy_s);
1450 	}
1451 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
1452 }
1453 
ull_adv_sync_pdu_alloc(struct ll_adv_set * adv,enum ull_adv_pdu_extra_data_flag extra_data_flag,struct pdu_adv ** ter_pdu_prev,struct pdu_adv ** ter_pdu_new,void ** extra_data_prev,void ** extra_data_new,uint8_t * ter_idx)1454 uint8_t ull_adv_sync_pdu_alloc(struct ll_adv_set *adv,
1455 			       enum ull_adv_pdu_extra_data_flag extra_data_flag,
1456 			       struct pdu_adv **ter_pdu_prev, struct pdu_adv **ter_pdu_new,
1457 			       void **extra_data_prev, void **extra_data_new, uint8_t *ter_idx)
1458 {
1459 	struct pdu_adv *pdu_prev, *pdu_new;
1460 	struct lll_adv_sync *lll_sync;
1461 	void *ed_prev;
1462 #if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
1463 	void *ed_new;
1464 #endif
1465 
1466 	lll_sync = adv->lll.sync;
1467 	if (!lll_sync) {
1468 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
1469 	}
1470 
1471 	/* Get reference to previous periodic advertising PDU data */
1472 	pdu_prev = lll_adv_sync_data_peek(lll_sync, &ed_prev);
1473 
1474 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1475 	/* Get reference to new periodic advertising PDU data buffer */
1476 	if (extra_data_flag == ULL_ADV_PDU_EXTRA_DATA_ALLOC_ALWAYS ||
1477 	    (extra_data_flag == ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST && ed_prev)) {
1478 		/* If there was an extra data in past PDU data or it is required
1479 		 * by the hdr_add_fields then allocate memmory for it.
1480 		 */
1481 		pdu_new = lll_adv_sync_data_alloc(lll_sync, &ed_new,
1482 						  ter_idx);
1483 		if (!pdu_new) {
1484 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1485 		}
1486 	} else {
1487 		ed_new = NULL;
1488 #else
1489 	{
1490 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1491 		pdu_new = lll_adv_sync_data_alloc(lll_sync, NULL, ter_idx);
1492 		if (!pdu_new) {
1493 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1494 		}
1495 	}
1496 
1497 #if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
1498 	if (extra_data_prev) {
1499 		*extra_data_prev = ed_prev;
1500 	}
1501 	if (extra_data_new) {
1502 		*extra_data_new = ed_new;
1503 	}
1504 #endif /* CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY */
1505 
1506 	*ter_pdu_prev = pdu_prev;
1507 	*ter_pdu_new = pdu_new;
1508 
1509 	return 0;
1510 }
1511 
1512 /* @brief Set or clear fields in extended advertising header and store
1513  *        extra_data if requested.
1514  *
1515  * @param[in]  lll_sync         Reference to periodic advertising sync.
1516  * @param[in]  ter_pdu_prev     Pointer to previous PDU.
1517  * @param[in]  ter_pdu_         Pointer to PDU to fill fields.
1518  * @param[in]  hdr_add_fields   Flag with information which fields add.
1519  * @param[in]  hdr_rem_fields   Flag with information which fields remove.
1520  * @param[in]  hdr_data         Pointer to data to be added to header. Content
1521  *                              depends on the value of @p hdr_add_fields.
1522  *
1523  * @Note
1524  * @p hdr_data content depends on the flag provided by @p hdr_add_fields:
1525  * - ULL_ADV_PDU_HDR_FIELD_CTE_INFO:
1526  *   # @p hdr_data points to single byte with CTEInfo field
1527  * - ULL_ADV_PDU_HDR_FIELD_ADI:
1528  *   # @p hdr_data points to memory where first byte is size of ADI structure,
1529  *     following bytes are the pointer reference to the new ADI structure to be
1530  *     updated in the PDU.
1531  *     In return, the first byte returns the size of ADI structure, following
1532  *     bytes returns the pointer reference to ADI structure offset inside the
1533  *     updated current PDU.
1534  * - ULL_ADV_PDU_HDR_FIELD_AD_DATA:
1535  *   # @p hdr_data points to memory where first byte
1536  *     is size of advertising data, following byte is a pointer to actual
1537  *     advertising data.
1538  * - ULL_ADV_PDU_HDR_FIELD_AUX_PTR:
1539  *   # @p hdr_data points to memory where first byte is size of aux ptr
1540  *     structure, following bytes are the pointer reference to the new aux ptr
1541  *     structure to be updated in the PDU.
1542  *     In return, the first byte returns the size of aux ptr structure,
1543  *     following bytes returns the pointer reference to aux ptr structure offset
1544  *     inside the updated current PDU.
1545  * - ULL_ADV_PDU_HDR_FIELD_ACAD:
1546  *   # @p hdr_data points to memory where first byte is size of ACAD, second
1547  *     byte is used to return offset to ACAD field.
1548  *   # @p hdr_data memory returns previous ACAD length back in the first byte
1549  *     and offset to new ACAD in the next PDU.
1550  *
1551  * @return Zero in case of success, other value in case of failure.
1552  */
1553 uint8_t ull_adv_sync_pdu_set_clear(struct lll_adv_sync *lll_sync,
1554 				   struct pdu_adv *ter_pdu_prev,
1555 				   struct pdu_adv *ter_pdu,
1556 				   uint16_t hdr_add_fields,
1557 				   uint16_t hdr_rem_fields,
1558 				   void *hdr_data)
1559 {
1560 	struct pdu_adv_com_ext_adv *ter_com_hdr, *ter_com_hdr_prev;
1561 	struct pdu_adv_ext_hdr ter_hdr = { 0 }, ter_hdr_prev = { 0 };
1562 	struct pdu_adv_aux_ptr *aux_ptr, *aux_ptr_prev;
1563 	uint8_t *ter_dptr, *ter_dptr_prev;
1564 	struct pdu_adv_adi *adi;
1565 	uint8_t acad_len_prev;
1566 	uint8_t ter_len_prev;
1567 	uint8_t hdr_buf_len;
1568 	uint16_t ter_len;
1569 	uint8_t *ad_data;
1570 	uint8_t acad_len;
1571 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1572 	uint8_t cte_info;
1573 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1574 	uint8_t ad_len;
1575 
1576 	/* Get common pointers from reference to previous tertiary PDU data */
1577 	ter_com_hdr_prev = (void *)&ter_pdu_prev->adv_ext_ind;
1578 	if (ter_com_hdr_prev->ext_hdr_len != 0) {
1579 		ter_hdr_prev = ter_com_hdr_prev->ext_hdr;
1580 	}
1581 	ter_dptr_prev = ter_com_hdr_prev->ext_hdr.data;
1582 
1583 	/* Set common fields in reference to new tertiary PDU data buffer */
1584 	ter_pdu->type = ter_pdu_prev->type;
1585 	ter_pdu->rfu = 0U;
1586 	ter_pdu->chan_sel = 0U;
1587 
1588 	ter_pdu->tx_addr = ter_pdu_prev->tx_addr;
1589 	ter_pdu->rx_addr = ter_pdu_prev->rx_addr;
1590 
1591 	/* Get common pointers from current tertiary PDU data.
1592 	 * It is possible that the current tertiary is the same as
1593 	 * previous one. It may happen if update periodic advertising
1594 	 * chain in place.
1595 	 */
1596 	ter_com_hdr = (void *)&ter_pdu->adv_ext_ind;
1597 	ter_com_hdr->adv_mode = ter_com_hdr_prev->adv_mode;
1598 	ter_dptr = ter_com_hdr->ext_hdr.data;
1599 
1600 	/* No AdvA in AUX_SYNC_IND */
1601 	/* No TargetA in AUX_SYNC_IND */
1602 
1603 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1604 	/* If requested add or update CTEInfo */
1605 	if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) {
1606 		ter_hdr.cte_info = 1;
1607 		cte_info = *(uint8_t *)hdr_data;
1608 		hdr_data = (uint8_t *)hdr_data + 1;
1609 		ter_dptr += sizeof(struct pdu_cte_info);
1610 	/* If CTEInfo exists in prev and is not requested to be removed */
1611 	} else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) &&
1612 		   ter_hdr_prev.cte_info) {
1613 		ter_hdr.cte_info = 1;
1614 		cte_info = 0U; /* value not used, will be read from prev PDU */
1615 		ter_dptr += sizeof(struct pdu_cte_info);
1616 	} else {
1617 		cte_info = 0U; /* value not used */
1618 	}
1619 
1620 	/* If CTEInfo exists in prev PDU */
1621 	if (ter_hdr_prev.cte_info) {
1622 		ter_dptr_prev += sizeof(struct pdu_cte_info);
1623 	}
1624 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1625 
1626 	/* ADI */
1627 	if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADI) {
1628 		ter_hdr.adi = 1U;
1629 		/* return the size of ADI structure */
1630 		*(uint8_t *)hdr_data = sizeof(struct pdu_adv_adi);
1631 		hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
1632 		/* pick the reference to ADI param */
1633 		(void)memcpy(&adi, hdr_data, sizeof(struct pdu_adv_adi *));
1634 		/* return the pointer to ADI struct inside the PDU */
1635 		(void)memcpy(hdr_data, &ter_dptr, sizeof(ter_dptr));
1636 		hdr_data = (uint8_t *)hdr_data + sizeof(ter_dptr);
1637 		ter_dptr += sizeof(struct pdu_adv_adi);
1638 	} else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_ADI) &&
1639 		   ter_hdr_prev.adi) {
1640 		ter_hdr.adi = 1U;
1641 		adi = NULL;
1642 		ter_dptr += sizeof(struct pdu_adv_adi);
1643 	} else {
1644 		adi = NULL;
1645 	}
1646 	if (ter_hdr_prev.adi) {
1647 		ter_dptr_prev += sizeof(struct pdu_adv_adi);
1648 	}
1649 
1650 	/* AuxPtr - will be added if AUX_CHAIN_IND is required */
1651 	if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) {
1652 		ter_hdr.aux_ptr = 1;
1653 		aux_ptr_prev = NULL;
1654 		aux_ptr = (void *)ter_dptr;
1655 
1656 		/* return the size of aux pointer structure */
1657 		*(uint8_t *)hdr_data = sizeof(struct pdu_adv_aux_ptr);
1658 		hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
1659 
1660 		/* return the pointer to aux pointer struct inside the PDU
1661 		 * buffer
1662 		 */
1663 		(void)memcpy(hdr_data, &ter_dptr, sizeof(ter_dptr));
1664 		hdr_data = (uint8_t *)hdr_data + sizeof(ter_dptr);
1665 	} else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) &&
1666 		   ter_hdr_prev.aux_ptr) {
1667 		ter_hdr.aux_ptr = 1;
1668 		aux_ptr_prev = (void *)ter_dptr_prev;
1669 		aux_ptr = (void *)ter_dptr;
1670 	} else {
1671 		aux_ptr_prev = NULL;
1672 		aux_ptr = NULL;
1673 	}
1674 	if (ter_hdr_prev.aux_ptr) {
1675 		ter_dptr_prev += sizeof(struct pdu_adv_aux_ptr);
1676 	}
1677 	if (ter_hdr.aux_ptr) {
1678 		ter_dptr += sizeof(struct pdu_adv_aux_ptr);
1679 	}
1680 
1681 	/* No SyncInfo in AUX_SYNC_IND */
1682 
1683 	/* Tx Power flag */
1684 	if (ter_hdr_prev.tx_pwr) {
1685 		ter_dptr_prev++;
1686 
1687 		ter_hdr.tx_pwr = 1;
1688 		ter_dptr++;
1689 	}
1690 
1691 	/* Calc previous ACAD len and update PDU len */
1692 	ter_len_prev = ter_dptr_prev - (uint8_t *)ter_com_hdr_prev;
1693 	hdr_buf_len = ter_com_hdr_prev->ext_hdr_len +
1694 		      PDU_AC_EXT_HEADER_SIZE_MIN;
1695 	if (ter_len_prev <= hdr_buf_len) {
1696 		/* There are some data, except ACAD, in extended header if ter_len_prev
1697 		 * equals to hdr_buf_len. There is ACAD if the size of ter_len_prev
1698 		 * is smaller than hdr_buf_len.
1699 		 */
1700 		acad_len_prev = hdr_buf_len - ter_len_prev;
1701 		ter_len_prev += acad_len_prev;
1702 		ter_dptr_prev += acad_len_prev;
1703 	} else {
1704 		/* There are no data in extended header, all flags are zeros. */
1705 		acad_len_prev = 0;
1706 		/* NOTE: If no flags are set then extended header length will be
1707 		 *       zero. Under this condition the current ter_len_prev
1708 		 *       value will be greater than extended header length,
1709 		 *       hence set ter_len_prev to size of the length/mode
1710 		 *       field.
1711 		 */
1712 		ter_len_prev = PDU_AC_EXT_HEADER_SIZE_MIN;
1713 		ter_dptr_prev = (uint8_t *)ter_com_hdr_prev + ter_len_prev;
1714 	}
1715 
1716 	/* Did we parse beyond PDU length? */
1717 	if (ter_len_prev > ter_pdu_prev->len) {
1718 		/* we should not encounter invalid length */
1719 		return BT_HCI_ERR_UNSPECIFIED;
1720 	}
1721 
1722 	/* Add/Retain/Remove ACAD */
1723 	if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ACAD) {
1724 		/* remember the new acad data len */
1725 		acad_len = *(uint8_t *)hdr_data;
1726 
1727 		/* return prev ACAD length */
1728 		*(uint8_t *)hdr_data = acad_len_prev;
1729 		hdr_data = (uint8_t *)hdr_data + sizeof(acad_len);
1730 
1731 		/* return the pointer to ACAD offset */
1732 		(void)memcpy(hdr_data, &ter_dptr, sizeof(ter_dptr));
1733 		hdr_data = (uint8_t *)hdr_data + sizeof(ter_dptr);
1734 
1735 		/* unchanged acad */
1736 		if (!acad_len) {
1737 			acad_len = acad_len_prev;
1738 		}
1739 
1740 		ter_dptr += acad_len;
1741 	} else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_ACAD)) {
1742 		acad_len = acad_len_prev;
1743 		ter_dptr += acad_len_prev;
1744 	} else {
1745 		acad_len = 0U;
1746 	}
1747 
1748 	/* Calc current tertiary PDU len so far without AD data added */
1749 	ter_len = ull_adv_aux_hdr_len_calc(ter_com_hdr, &ter_dptr);
1750 
1751 	/* Get Adv data from function parameters */
1752 	if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) {
1753 		uint8_t ad_len_prev;
1754 
1755 		/* remember the new ad data len */
1756 		ad_len = *(uint8_t *)hdr_data;
1757 
1758 		/* return prev ad data length */
1759 		ad_len_prev = ter_pdu_prev->len - ter_len_prev;
1760 		*(uint8_t *)hdr_data = ad_len_prev;
1761 		hdr_data = (uint8_t *)hdr_data + sizeof(ad_len);
1762 
1763 		/* remember the reference to new ad data */
1764 		(void)memcpy(&ad_data, hdr_data, sizeof(ad_data));
1765 
1766 		/* return the reference to prev ad data */
1767 		(void)memcpy(hdr_data, &ter_dptr_prev, sizeof(ter_dptr_prev));
1768 		hdr_data = (uint8_t *)hdr_data + sizeof(ter_dptr_prev);
1769 
1770 		/* unchanged data */
1771 		if (!ad_len && !ad_data) {
1772 			ad_len = ad_len_prev;
1773 			ad_data = ter_dptr_prev;
1774 		}
1775 	} else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA)) {
1776 		ad_len = ter_pdu_prev->len - ter_len_prev;
1777 		ad_data = ter_dptr_prev;
1778 	} else {
1779 		ad_len = 0;
1780 		ad_data = NULL;
1781 	}
1782 
1783 	/* Check Max Advertising Data Length */
1784 	if (ad_len > CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) {
1785 		return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1786 	}
1787 
1788 	/* Check AdvData overflow */
1789 	if ((ter_len + ad_len) > PDU_AC_PAYLOAD_SIZE_MAX) {
1790 		/* return excess length */
1791 		*(uint8_t *)hdr_data = ter_len + ad_len -
1792 				       PDU_AC_PAYLOAD_SIZE_MAX;
1793 
1794 		/* Will use packet too long error to determine fragmenting
1795 		 * long data
1796 		 */
1797 		return BT_HCI_ERR_PACKET_TOO_LONG;
1798 	}
1799 
1800 	LL_ASSERT(ter_len <= (PDU_AC_EXT_HEADER_SIZE_MIN + PDU_AC_EXT_HEADER_SIZE_MAX));
1801 
1802 	/* set the tertiary extended header and PDU length */
1803 	ull_adv_aux_hdr_len_fill(ter_com_hdr, ter_len);
1804 	ter_pdu->len = ter_len + ad_len;
1805 
1806 	/* Start filling tertiary PDU payload based on flags from here
1807 	 * ==============================================================
1808 	 */
1809 
1810 	/* Fill AdvData in tertiary PDU */
1811 	(void)memmove(ter_dptr, ad_data, ad_len);
1812 
1813 	/* Early exit if no flags set */
1814 	if (!ter_com_hdr->ext_hdr_len) {
1815 		return 0;
1816 	}
1817 
1818 	/* Retain ACAD in tertiary PDU */
1819 	ter_dptr_prev -= acad_len_prev;
1820 	if (acad_len) {
1821 		ter_dptr -= acad_len;
1822 		(void)memmove(ter_dptr, ter_dptr_prev, acad_len_prev);
1823 	}
1824 
1825 	/* Tx Power */
1826 	if (ter_hdr.tx_pwr) {
1827 		*--ter_dptr = *--ter_dptr_prev;
1828 	}
1829 
1830 	/* No SyncInfo in AUX_SYNC_IND */
1831 
1832 	/* AuxPtr */
1833 	if (ter_hdr_prev.aux_ptr) {
1834 		ter_dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
1835 	}
1836 	if (ter_hdr.aux_ptr) {
1837 		ter_dptr -= sizeof(struct pdu_adv_aux_ptr);
1838 	}
1839 	if (aux_ptr_prev) {
1840 		(void)memmove(ter_dptr, aux_ptr_prev, sizeof(*aux_ptr_prev));
1841 	}
1842 
1843 	/* ADI */
1844 	if (ter_hdr_prev.adi) {
1845 		ter_dptr_prev -= sizeof(struct pdu_adv_adi);
1846 	}
1847 	if (ter_hdr.adi) {
1848 		struct pdu_adv_adi *adi_pdu;
1849 
1850 		ter_dptr -= sizeof(struct pdu_adv_adi);
1851 		adi_pdu = (void *)ter_dptr;
1852 
1853 		if (!adi) {
1854 			struct ll_adv_set *adv;
1855 
1856 			adv = HDR_LLL2ULL(lll_sync->adv);
1857 
1858 			/* The DID for a specific SID shall be unique.
1859 			 */
1860 			const uint16_t did =
1861 				sys_cpu_to_le16(ull_adv_aux_did_next_unique_get(adv->sid));
1862 			PDU_ADV_ADI_DID_SID_SET(adi_pdu, did, adv->sid);
1863 		} else {
1864 			adi_pdu->did_sid_packed[0] = adi->did_sid_packed[0];
1865 			adi_pdu->did_sid_packed[1] = adi->did_sid_packed[1];
1866 		}
1867 	}
1868 
1869 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1870 	if (ter_hdr.cte_info) {
1871 		if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) {
1872 			*--ter_dptr = cte_info;
1873 		} else {
1874 			*--ter_dptr = *--ter_dptr_prev;
1875 		}
1876 	}
1877 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1878 
1879 	/* No TargetA in AUX_SYNC_IND */
1880 	/* No AdvA in AUX_SYNC_IND */
1881 
1882 	if (ter_com_hdr->ext_hdr_len != 0) {
1883 		ter_com_hdr->ext_hdr = ter_hdr;
1884 	}
1885 
1886 	return 0;
1887 }
1888 
1889 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1890 /* @brief Set or clear fields in extended advertising header and store
1891  *        extra_data if requested.
1892  *
1893  * @param[in]  extra_data_prev  Pointer to previous content of extra_data.
1894  * @param[in]  hdr_add_fields   Flag with information which fields add.
1895  * @param[in]  hdr_rem_fields   Flag with information which fields remove.
1896  * @param[in]  data             Pointer to data to be stored in extra_data.
1897  *                              Content depends on the data depends on
1898  *                              @p hdr_add_fields.
1899  *
1900  * @Note
1901  * @p data depends on the flag provided by @p hdr_add_fields.
1902  * Information about content of value may be found in description of
1903  * @ref ull_adv_sync_pdu_set_clear.
1904  *
1905  * @return Zero in case of success, other value in case of failure.
1906  */
1907 void ull_adv_sync_extra_data_set_clear(void *extra_data_prev,
1908 				       void *extra_data_new,
1909 				       uint16_t hdr_add_fields,
1910 				       uint16_t hdr_rem_fields,
1911 				       void *data)
1912 {
1913 	/* Currently only CTE enable requires extra_data. Due to that fact
1914 	 * CTE additional data are just copied to extra_data memory.
1915 	 */
1916 	if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) {
1917 		(void)memcpy(extra_data_new, data, sizeof(struct lll_df_adv_cfg));
1918 	} else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) ||
1919 		   extra_data_prev) {
1920 		(void)memmove(extra_data_new, extra_data_prev,
1921 			      sizeof(struct lll_df_adv_cfg));
1922 	}
1923 }
1924 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1925 
1926 static int init_reset(void)
1927 {
1928 	/* Initialize adv sync pool. */
1929 	mem_init(ll_adv_sync_pool, sizeof(struct ll_adv_sync_set),
1930 		 sizeof(ll_adv_sync_pool) / sizeof(struct ll_adv_sync_set),
1931 		 &adv_sync_free);
1932 
1933 	return 0;
1934 }
1935 
1936 static uint8_t adv_type_check(struct ll_adv_set *adv)
1937 {
1938 	struct pdu_adv_com_ext_adv *pri_com_hdr;
1939 	struct pdu_adv_ext_hdr *pri_hdr;
1940 	struct pdu_adv *pri_pdu;
1941 
1942 	pri_pdu = lll_adv_data_latest_peek(&adv->lll);
1943 	if (pri_pdu->type != PDU_ADV_TYPE_EXT_IND) {
1944 		return BT_HCI_ERR_INVALID_PARAM;
1945 	}
1946 
1947 	pri_com_hdr = (void *)&pri_pdu->adv_ext_ind;
1948 	if (pri_com_hdr->adv_mode != 0U) {
1949 		return BT_HCI_ERR_INVALID_PARAM;
1950 	}
1951 
1952 	pri_hdr = (void *)pri_com_hdr->ext_hdr_adv_data;
1953 	if (pri_hdr->aux_ptr) {
1954 		struct pdu_adv_com_ext_adv *sec_com_hdr;
1955 		struct pdu_adv_ext_hdr *sec_hdr;
1956 		struct pdu_adv *sec_pdu;
1957 
1958 		sec_pdu = lll_adv_aux_data_latest_peek(adv->lll.aux);
1959 		sec_com_hdr = (void *)&sec_pdu->adv_ext_ind;
1960 		sec_hdr = (void *)sec_com_hdr->ext_hdr_adv_data;
1961 		if (!pri_hdr->adv_addr && !sec_hdr->adv_addr) {
1962 			return BT_HCI_ERR_INVALID_PARAM;
1963 		}
1964 	} else if (!pri_hdr->adv_addr) {
1965 		return BT_HCI_ERR_INVALID_PARAM;
1966 	}
1967 
1968 	return 0;
1969 }
1970 
1971 static inline struct ll_adv_sync_set *sync_acquire(void)
1972 {
1973 	return mem_acquire(&adv_sync_free);
1974 }
1975 
1976 static inline void sync_release(struct ll_adv_sync_set *sync)
1977 {
1978 	mem_release(sync, &adv_sync_free);
1979 }
1980 
1981 static inline uint16_t sync_handle_get(const struct ll_adv_sync_set *sync)
1982 {
1983 	return mem_index_get(sync, ll_adv_sync_pool,
1984 			     sizeof(struct ll_adv_sync_set));
1985 }
1986 
1987 static uint32_t sync_time_get(const struct ll_adv_sync_set *sync,
1988 			      const struct pdu_adv *pdu)
1989 {
1990 	uint8_t len;
1991 
1992 	/* Calculate the PDU Tx Time and hence the radio event length,
1993 	 * Always use maximum length for common extended header format so that
1994 	 * ACAD could be update when periodic advertising is active and the
1995 	 * time reservation need not be updated everytime avoiding overlapping
1996 	 * with other active states/roles.
1997 	 */
1998 	len = pdu->len - pdu->adv_ext_ind.ext_hdr_len -
1999 	      PDU_AC_EXT_HEADER_SIZE_MIN + PDU_AC_EXT_HEADER_SIZE_MAX;
2000 
2001 	return ull_adv_sync_time_get(sync, len);
2002 }
2003 
2004 static uint8_t sync_stop(struct ll_adv_sync_set *sync)
2005 {
2006 	uint8_t sync_handle;
2007 	int err;
2008 
2009 	sync_handle = sync_handle_get(sync);
2010 
2011 	err = ull_ticker_stop_with_mark(TICKER_ID_ADV_SYNC_BASE + sync_handle,
2012 					sync, &sync->lll);
2013 	LL_ASSERT(err == 0 || err == -EALREADY);
2014 	if (err) {
2015 		return BT_HCI_ERR_CMD_DISALLOWED;
2016 	}
2017 
2018 	return 0;
2019 }
2020 
2021 static inline uint8_t sync_remove(struct ll_adv_sync_set *sync,
2022 				  struct ll_adv_set *adv, uint8_t enable)
2023 {
2024 	uint8_t pri_idx;
2025 	uint8_t sec_idx;
2026 	uint8_t err;
2027 
2028 	/* Remove sync_info from auxiliary PDU */
2029 	err = ull_adv_aux_hdr_set_clear(adv, 0U,
2030 					ULL_ADV_PDU_HDR_FIELD_SYNC_INFO, NULL,
2031 					&pri_idx, &sec_idx);
2032 	if (err) {
2033 		return err;
2034 	}
2035 
2036 	lll_adv_aux_data_enqueue(adv->lll.aux, sec_idx);
2037 	lll_adv_data_enqueue(&adv->lll, pri_idx);
2038 
2039 	if (sync->is_started) {
2040 		/* TODO: we removed sync info, but if sync_stop() fails, what do
2041 		 * we do?
2042 		 */
2043 		err = sync_stop(sync);
2044 		if (err) {
2045 			return err;
2046 		}
2047 
2048 		sync->is_started = 0U;
2049 
2050 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2051 		if (adv->lll.aux) {
2052 			/* notify the auxiliary set */
2053 			ull_adv_sync_started_stopped(HDR_LLL2ULL(adv->lll.aux));
2054 		}
2055 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2056 	}
2057 
2058 	if (!enable) {
2059 		sync->is_enabled = 0U;
2060 	}
2061 
2062 	return 0U;
2063 }
2064 
2065 static uint8_t sync_chm_update(uint8_t handle)
2066 {
2067 	uint8_t hdr_data[ULL_ADV_HDR_DATA_LEN_SIZE +
2068 			 ULL_ADV_HDR_DATA_ACAD_PTR_SIZE];
2069 	struct pdu_adv_sync_chm_upd_ind *chm_upd_ind;
2070 	struct lll_adv_sync *lll_sync;
2071 	struct pdu_adv *pdu_prev;
2072 	struct ll_adv_set *adv;
2073 	uint8_t acad_len_prev;
2074 	struct pdu_adv *pdu;
2075 	uint16_t instant;
2076 	uint8_t chm_last;
2077 	uint8_t ter_idx;
2078 	uint8_t *acad;
2079 	uint8_t err;
2080 
2081 	/* Check for valid advertising instance */
2082 	adv = ull_adv_is_created_get(handle);
2083 	if (!adv) {
2084 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
2085 	}
2086 
2087 	/* Check for valid periodic advertising */
2088 	lll_sync = adv->lll.sync;
2089 	if (!lll_sync) {
2090 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
2091 	}
2092 
2093 	/* Fail if already in progress */
2094 	if (lll_sync->chm_last != lll_sync->chm_first) {
2095 		return BT_HCI_ERR_CMD_DISALLOWED;
2096 	}
2097 
2098 	/* Allocate next Sync PDU */
2099 	err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
2100 				     &pdu_prev, &pdu, NULL, NULL, &ter_idx);
2101 	if (err) {
2102 		return err;
2103 	}
2104 
2105 	/* Try to allocate ACAD for channel map update indication, previous
2106 	 * ACAD length with be returned back.
2107 	 */
2108 	hdr_data[ULL_ADV_HDR_DATA_LEN_OFFSET] = 0U;
2109 	err = ull_adv_sync_pdu_set_clear(lll_sync, pdu_prev, pdu,
2110 					 ULL_ADV_PDU_HDR_FIELD_ACAD, 0U,
2111 					 &hdr_data);
2112 	if (err) {
2113 		return err;
2114 	}
2115 
2116 	/* Check if there are other ACAD data previously and append to end of
2117 	 * other ACAD already present.
2118 	 */
2119 	acad_len_prev = hdr_data[ULL_ADV_HDR_DATA_LEN_OFFSET];
2120 	hdr_data[ULL_ADV_HDR_DATA_LEN_OFFSET] = acad_len_prev +
2121 						sizeof(*chm_upd_ind) +
2122 						2U;
2123 	err = ull_adv_sync_pdu_set_clear(lll_sync, pdu_prev, pdu,
2124 					 ULL_ADV_PDU_HDR_FIELD_ACAD, 0U,
2125 					 &hdr_data);
2126 	if (err) {
2127 		return err;
2128 	}
2129 
2130 	/* Populate the AD data length and opcode */
2131 	(void)memcpy(&acad, &hdr_data[ULL_ADV_HDR_DATA_ACAD_PTR_OFFSET],
2132 		     sizeof(acad));
2133 	acad += acad_len_prev;
2134 	acad[PDU_ADV_DATA_HEADER_LEN_OFFSET] = sizeof(*chm_upd_ind) + 1U;
2135 	acad[PDU_ADV_DATA_HEADER_TYPE_OFFSET] =
2136 		PDU_ADV_DATA_TYPE_CHANNEL_MAP_UPDATE_IND;
2137 
2138 	/* Populate the Channel Map Indication structure */
2139 	chm_upd_ind = (void *)&acad[PDU_ADV_DATA_HEADER_DATA_OFFSET];
2140 	(void)ull_chan_map_get(chm_upd_ind->chm);
2141 	instant = lll_sync->event_counter + 6U;
2142 	chm_upd_ind->instant = sys_cpu_to_le16(instant);
2143 
2144 	/* Update the LLL to reflect the Channel Map and Instant to use */
2145 	chm_last = lll_sync->chm_last + 1;
2146 	if (chm_last == DOUBLE_BUFFER_SIZE) {
2147 		chm_last = 0U;
2148 	}
2149 	lll_sync->chm[chm_last].data_chan_count =
2150 		ull_chan_map_get(lll_sync->chm[chm_last].data_chan_map);
2151 	lll_sync->chm_instant = instant;
2152 
2153 	/* Commit the Channel Map Indication in the ACAD field of Periodic
2154 	 * Advertising
2155 	 */
2156 	lll_adv_sync_data_enqueue(lll_sync, ter_idx);
2157 
2158 	/* Initiate the Channel Map Indication */
2159 	lll_sync->chm_last = chm_last;
2160 
2161 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2162 	struct ll_adv_sync_set *sync = HDR_LLL2ULL(lll_sync);
2163 
2164 	if (!sync->is_started) {
2165 		/* Sync not started yet, apply new channel map now */
2166 		lll_sync->chm_first = lll_sync->chm_last;
2167 	}
2168 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2169 
2170 	return 0;
2171 }
2172 
2173 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2174 void ull_adv_sync_lll_syncinfo_fill(struct pdu_adv *pdu, struct lll_adv_aux *lll_aux)
2175 {
2176 	struct lll_adv_sync *lll_sync;
2177 	struct pdu_adv_sync_info *si;
2178 	uint8_t chm_first;
2179 
2180 	lll_sync = lll_aux->adv->sync;
2181 
2182 	si = sync_info_get(pdu);
2183 	sync_info_offset_fill(si, lll_sync->us_adv_sync_pdu_offset);
2184 	si->evt_cntr = lll_sync->event_counter + lll_sync->latency_prepare +
2185 		       lll_sync->sync_lazy;
2186 
2187 	/* Fill the correct channel map to use if at or past the instant */
2188 	if (lll_sync->chm_first != lll_sync->chm_last) {
2189 		uint16_t instant_latency;
2190 
2191 		instant_latency = (si->evt_cntr - lll_sync->chm_instant) &
2192 				  EVENT_INSTANT_MAX;
2193 		if (instant_latency <= EVENT_INSTANT_LATENCY_MAX) {
2194 			chm_first = lll_sync->chm_last;
2195 		} else {
2196 			chm_first = lll_sync->chm_first;
2197 		}
2198 	} else {
2199 		chm_first = lll_sync->chm_first;
2200 	}
2201 	(void)memcpy(si->sca_chm, lll_sync->chm[chm_first].data_chan_map,
2202 		     sizeof(si->sca_chm));
2203 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] &=
2204 		~PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK;
2205 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] |=
2206 		((lll_clock_sca_local_get() <<
2207 		  PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS) &
2208 		 PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK);
2209 }
2210 
2211 static void sync_info_offset_fill(struct pdu_adv_sync_info *si, uint32_t offs)
2212 {
2213 	if (offs >= OFFS_ADJUST_US) {
2214 		offs -= OFFS_ADJUST_US;
2215 		si->offs_adjust = 1U;
2216 	}
2217 
2218 	offs = offs / OFFS_UNIT_30_US;
2219 	if (!!(offs >> OFFS_UNIT_BITS)) {
2220 		si->offs = sys_cpu_to_le16(offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US));
2221 		si->offs_units = OFFS_UNIT_VALUE_300_US;
2222 	} else {
2223 		si->offs = sys_cpu_to_le16(offs);
2224 		si->offs_units = OFFS_UNIT_VALUE_30_US;
2225 	}
2226 }
2227 
2228 #else /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2229 static void mfy_sync_offset_get(void *param)
2230 {
2231 	struct ll_adv_set *adv = param;
2232 	struct lll_adv_sync *lll_sync;
2233 	struct ll_adv_sync_set *sync;
2234 	struct pdu_adv_sync_info *si;
2235 	uint32_t sync_remainder_us;
2236 	uint32_t aux_remainder_us;
2237 	uint32_t ticks_to_expire;
2238 	uint32_t ticks_current;
2239 	struct pdu_adv *pdu;
2240 	uint32_t remainder;
2241 	uint8_t chm_first;
2242 	uint8_t ticker_id;
2243 	uint16_t lazy;
2244 	uint8_t retry;
2245 	uint8_t id;
2246 
2247 	lll_sync = adv->lll.sync;
2248 	sync = HDR_LLL2ULL(lll_sync);
2249 	ticker_id = TICKER_ID_ADV_SYNC_BASE + sync_handle_get(sync);
2250 
2251 	id = TICKER_NULL;
2252 	ticks_to_expire = 0U;
2253 	ticks_current = 0U;
2254 	retry = 4U;
2255 	do {
2256 		uint32_t volatile ret_cb;
2257 		uint32_t ticks_previous;
2258 		uint32_t ret;
2259 		bool success;
2260 
2261 		ticks_previous = ticks_current;
2262 
2263 		ret_cb = TICKER_STATUS_BUSY;
2264 		ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR,
2265 					       TICKER_USER_ID_ULL_LOW,
2266 					       &id, &ticks_current,
2267 					       &ticks_to_expire, &remainder,
2268 					       &lazy, NULL, NULL,
2269 					       ticker_op_cb, (void *)&ret_cb);
2270 		if (ret == TICKER_STATUS_BUSY) {
2271 			while (ret_cb == TICKER_STATUS_BUSY) {
2272 				ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
2273 						 TICKER_USER_ID_ULL_LOW);
2274 			}
2275 		}
2276 
2277 		success = (ret_cb == TICKER_STATUS_SUCCESS);
2278 		LL_ASSERT(success);
2279 
2280 		LL_ASSERT((ticks_current == ticks_previous) || retry--);
2281 
2282 		LL_ASSERT(id != TICKER_NULL);
2283 	} while (id != ticker_id);
2284 
2285 	/* Reduced a tick for negative remainder and return positive remainder
2286 	 * value.
2287 	 */
2288 	hal_ticker_remove_jitter(&ticks_to_expire, &remainder);
2289 	sync_remainder_us = remainder;
2290 
2291 	/* Add a tick for negative remainder and return positive remainder
2292 	 * value.
2293 	 */
2294 	remainder = sync->aux_remainder;
2295 	hal_ticker_add_jitter(&ticks_to_expire, &remainder);
2296 	aux_remainder_us = remainder;
2297 
2298 	pdu = lll_adv_aux_data_latest_peek(adv->lll.aux);
2299 	si = sync_info_get(pdu);
2300 	sync_info_offset_fill(si, ticks_to_expire, sync_remainder_us,
2301 			      aux_remainder_us);
2302 	si->evt_cntr = lll_sync->event_counter + lll_sync->latency_prepare +
2303 		       lazy;
2304 
2305 	/* Fill the correct channel map to use if at or past the instant */
2306 	if (lll_sync->chm_first != lll_sync->chm_last) {
2307 		uint16_t instant_latency;
2308 
2309 		instant_latency = (si->evt_cntr - lll_sync->chm_instant) &
2310 				  EVENT_INSTANT_MAX;
2311 		if (instant_latency <= EVENT_INSTANT_LATENCY_MAX) {
2312 			chm_first = lll_sync->chm_last;
2313 		} else {
2314 			chm_first = lll_sync->chm_first;
2315 		}
2316 	} else {
2317 		chm_first = lll_sync->chm_first;
2318 	}
2319 	(void)memcpy(si->sca_chm, lll_sync->chm[chm_first].data_chan_map,
2320 		     sizeof(si->sca_chm));
2321 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] &=
2322 		~PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK;
2323 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] |=
2324 		((lll_clock_sca_local_get() <<
2325 		  PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS) &
2326 		 PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK);
2327 }
2328 
2329 static void sync_info_offset_fill(struct pdu_adv_sync_info *si,
2330 				  uint32_t ticks_offset,
2331 				  uint32_t remainder_us,
2332 				  uint32_t start_us)
2333 {
2334 	uint32_t offs;
2335 
2336 	offs = HAL_TICKER_TICKS_TO_US(ticks_offset) + remainder_us - start_us;
2337 
2338 	if (offs >= OFFS_ADJUST_US) {
2339 		offs -= OFFS_ADJUST_US;
2340 		si->offs_adjust = 1U;
2341 	}
2342 
2343 	offs = offs / OFFS_UNIT_30_US;
2344 	if (!!(offs >> OFFS_UNIT_BITS)) {
2345 		si->offs = sys_cpu_to_le16(offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US));
2346 		si->offs_units = OFFS_UNIT_VALUE_300_US;
2347 	} else {
2348 		si->offs = sys_cpu_to_le16(offs);
2349 		si->offs_units = OFFS_UNIT_VALUE_30_US;
2350 	}
2351 }
2352 
2353 static void ticker_op_cb(uint32_t status, void *param)
2354 {
2355 	*((uint32_t volatile *)param) = status;
2356 }
2357 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2358 
2359 static struct pdu_adv_sync_info *sync_info_get(struct pdu_adv *pdu)
2360 {
2361 	struct pdu_adv_com_ext_adv *p;
2362 	struct pdu_adv_ext_hdr *h;
2363 	uint8_t *ptr;
2364 
2365 	p = (void *)&pdu->adv_ext_ind;
2366 	h = (void *)p->ext_hdr_adv_data;
2367 	ptr = h->data;
2368 
2369 	/* traverse through adv_addr, if present */
2370 	if (h->adv_addr) {
2371 		ptr += BDADDR_SIZE;
2372 	}
2373 
2374 	/* traverse through tgt_addr, if present */
2375 	if (h->tgt_addr) {
2376 		ptr += BDADDR_SIZE;
2377 	}
2378 
2379 	/* No CTEInfo flag in primary and secondary channel PDU */
2380 
2381 	/* traverse through adi, if present */
2382 	if (h->adi) {
2383 		ptr += sizeof(struct pdu_adv_adi);
2384 	}
2385 
2386 	/* traverse through aux ptr, if present */
2387 	if (h->aux_ptr) {
2388 		ptr += sizeof(struct pdu_adv_aux_ptr);
2389 	}
2390 
2391 	/* return pointer offset to sync_info */
2392 	return (void *)ptr;
2393 }
2394 
2395 static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
2396 		      uint32_t remainder, uint16_t lazy, uint8_t force,
2397 		      void *param)
2398 {
2399 	static memq_link_t link;
2400 	static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_sync_prepare};
2401 	static struct lll_prepare_param p;
2402 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2403 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2404 	struct ticker_ext_context *context = param;
2405 	struct ll_adv_sync_set *sync = context->context;
2406 #else /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2407 	struct ll_adv_sync_set *sync = param;
2408 #endif /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2409 	struct lll_adv_sync *lll;
2410 	uint32_t ret;
2411 	uint8_t ref;
2412 
2413 	DEBUG_RADIO_PREPARE_A(1);
2414 
2415 	lll = &sync->lll;
2416 
2417 	/* Increment prepare reference count */
2418 	ref = ull_ref_inc(&sync->ull);
2419 	LL_ASSERT(ref);
2420 
2421 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2422 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2423 	if (lll->iso) {
2424 		struct lll_adv_iso *lll_iso = lll->iso;
2425 
2426 		LL_ASSERT(context->other_expire_info);
2427 
2428 		/* Check: No need for remainder in this case? */
2429 		lll_iso->ticks_sync_pdu_offset = context->other_expire_info->ticks_to_expire;
2430 		lll_iso->iso_lazy = context->other_expire_info->lazy;
2431 	}
2432 #endif /* CONFIG_BT_CTLR_ADV_ISO && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2433 
2434 	/* Append timing parameters */
2435 	p.ticks_at_expire = ticks_at_expire;
2436 	p.remainder = remainder;
2437 	p.lazy = lazy;
2438 	p.force = force;
2439 	p.param = lll;
2440 	mfy.param = &p;
2441 
2442 	/* Kick LLL prepare */
2443 	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
2444 			     TICKER_USER_ID_LLL, 0, &mfy);
2445 	LL_ASSERT(!ret);
2446 
2447 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2448 	!defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2449 	if (lll->iso) {
2450 		ull_adv_iso_offset_get(sync);
2451 	}
2452 #endif /* CONFIG_BT_CTLR_ADV_ISO && !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2453 
2454 	DEBUG_RADIO_PREPARE_A(1);
2455 }
2456 
2457 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2458 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2459 static void ticker_update_op_cb(uint32_t status, void *param)
2460 {
2461 	LL_ASSERT(status == TICKER_STATUS_SUCCESS ||
2462 		  param == ull_disable_mark_get());
2463 }
2464 #endif /* !CONFIG_BT_CTLR_ADV_ISO && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2465