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 "ull_conn_internal.h"
47 
48 #include "isoal.h"
49 #include "ull_iso_types.h"
50 #include "lll_conn_iso.h"
51 #include "ull_conn_iso_types.h"
52 #include "ull_llcp.h"
53 
54 #include "ll.h"
55 
56 #include "hal/debug.h"
57 
58 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
59 /* First PDU contains up to PDU_AC_EXT_AD_DATA_LEN_MAX, next ones PDU_AC_EXT_PAYLOAD_SIZE_MAX */
60 #define PAYLOAD_BASED_FRAG_COUNT \
61 	1U + DIV_ROUND_UP(MAX(0U, CONFIG_BT_CTLR_ADV_DATA_LEN_MAX - PDU_AC_EXT_AD_DATA_LEN_MAX), \
62 			 PDU_AC_EXT_PAYLOAD_SIZE_MAX)
63 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
64 #define MAX_FRAG_COUNT MAX(PAYLOAD_BASED_FRAG_COUNT, CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX)
65 #else
66 #define MAX_FRAG_COUNT PAYLOAD_BASED_FRAG_COUNT
67 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
68 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
69 
70 static int init_reset(void);
71 static void ull_adv_sync_copy_pdu(const struct pdu_adv *pdu_prev,
72 				  struct pdu_adv *pdu);
73 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
74 static uint8_t ull_adv_sync_duplicate_chain(const struct pdu_adv *pdu_prev,
75 					    struct pdu_adv *pdu);
76 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
77 static uint8_t ull_adv_sync_ad_add(struct lll_adv_sync *lll_sync,
78 				   struct pdu_adv *ter_pdu_prev,
79 				   struct pdu_adv *ter_pdu,
80 				   const uint8_t *ad, uint8_t ad_len);
81 static uint8_t ull_adv_sync_ad_replace(struct lll_adv_sync *lll_sync,
82 				       struct pdu_adv *ter_pdu_prev,
83 				       struct pdu_adv *ter_pdu,
84 				       const uint8_t *ad, uint8_t ad_len);
85 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
86 static uint8_t ull_adv_sync_update_adi(struct lll_adv_sync *lll_sync,
87 				       struct pdu_adv *ter_pdu_prev,
88 				       struct pdu_adv *ter_pdu);
89 static uint8_t ull_adv_sync_add_adi(struct lll_adv_sync *lll_sync,
90 				    struct pdu_adv *pdu_prev,
91 				    struct pdu_adv *pdu);
92 static uint8_t ull_adv_sync_remove_adi(struct lll_adv_sync *lll_sync,
93 				       struct pdu_adv *pdu_prev,
94 				       struct pdu_adv *pdu);
95 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
96 static uint8_t adv_type_check(struct ll_adv_set *adv);
97 static inline struct ll_adv_sync_set *sync_acquire(void);
98 static inline void sync_release(struct ll_adv_sync_set *sync);
99 static inline uint16_t sync_handle_get(const struct ll_adv_sync_set *sync);
100 static uint32_t sync_time_get(const struct ll_adv_sync_set *sync,
101 			      const struct pdu_adv *pdu);
102 static inline uint8_t sync_remove(struct ll_adv_sync_set *sync,
103 				  struct ll_adv_set *adv, uint8_t enable);
104 static uint8_t sync_chm_update(uint8_t handle);
105 
106 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
107 static void sync_info_offset_fill(struct pdu_adv_sync_info *si, uint32_t offs);
108 
109 #else /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
110 static void mfy_sync_offset_get(void *param);
111 static void sync_info_offset_fill(struct pdu_adv_sync_info *si,
112 				  uint32_t ticks_offset,
113 				  uint32_t remainder_us,
114 				  uint32_t start_us);
115 static void ticker_op_cb(uint32_t status, void *param);
116 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
117 
118 static struct pdu_adv_sync_info *sync_info_get(struct pdu_adv *pdu);
119 static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
120 		      uint32_t remainder, uint16_t lazy, uint8_t force,
121 		      void *param);
122 
123 #if defined(CONFIG_BT_CTLR_ADV_ISO) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
124 static void ticker_update_op_cb(uint32_t status, void *param);
125 
126 static struct ticker_ext ll_adv_sync_ticker_ext[CONFIG_BT_CTLR_ADV_SYNC_SET];
127 #endif /* !CONFIG_BT_CTLR_ADV_ISO  && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
128 
129 static struct ll_adv_sync_set ll_adv_sync_pool[CONFIG_BT_CTLR_ADV_SYNC_SET];
130 static void *adv_sync_free;
131 
ll_adv_sync_param_set(uint8_t handle,uint16_t interval,uint16_t flags)132 uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
133 {
134 	void *extra_data_prev, *extra_data;
135 	struct pdu_adv *pdu_prev, *pdu;
136 	struct lll_adv_sync *lll_sync;
137 	struct ll_adv_sync_set *sync;
138 	struct ll_adv_set *adv;
139 	uint8_t err, ter_idx;
140 
141 	adv = ull_adv_is_created_get(handle);
142 	if (!adv) {
143 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
144 	}
145 
146 	if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
147 		err = adv_type_check(adv);
148 		if (err) {
149 			return err;
150 		}
151 	}
152 
153 	lll_sync = adv->lll.sync;
154 	if (!lll_sync) {
155 		struct pdu_adv *ter_pdu;
156 		struct lll_adv *lll;
157 		uint8_t chm_last;
158 
159 		sync = sync_acquire();
160 		if (!sync) {
161 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
162 		}
163 
164 		lll = &adv->lll;
165 		lll_sync = &sync->lll;
166 		lll->sync = lll_sync;
167 		lll_sync->adv = lll;
168 
169 		lll_adv_data_reset(&lll_sync->data);
170 		err = lll_adv_sync_data_init(&lll_sync->data);
171 		if (err) {
172 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
173 		}
174 
175 		/* NOTE: ull_hdr_init(&sync->ull); is done on start */
176 		lll_hdr_init(lll_sync, sync);
177 
178 		err = util_aa_le32(lll_sync->access_addr);
179 		LL_ASSERT(!err);
180 
181 		lll_sync->data_chan_id = lll_chan_id(lll_sync->access_addr);
182 		chm_last = lll_sync->chm_first;
183 		lll_sync->chm_last = chm_last;
184 		lll_sync->chm[chm_last].data_chan_count =
185 			ull_chan_map_get(lll_sync->chm[chm_last].data_chan_map);
186 
187 		lll_csrand_get(lll_sync->crc_init, sizeof(lll_sync->crc_init));
188 
189 		lll_sync->latency_prepare = 0;
190 		lll_sync->latency_event = 0;
191 		lll_sync->event_counter = 0;
192 
193 #if defined(CONFIG_BT_CTLR_ADV_PDU_LINK)
194 		lll_sync->data_chan_counter = 0U;
195 #endif /* CONFIG_BT_CTLR_ADV_PDU_LINK */
196 
197 		sync->is_enabled = 0U;
198 		sync->is_started = 0U;
199 
200 		ter_pdu = lll_adv_sync_data_peek(lll_sync, NULL);
201 		ull_adv_sync_pdu_init(ter_pdu, 0U, 0U, 0U, NULL);
202 	} else {
203 		sync = HDR_LLL2ULL(lll_sync);
204 	}
205 
206 	/* Periodic Advertising is already started */
207 	if (sync->is_started) {
208 		return BT_HCI_ERR_CMD_DISALLOWED;
209 	}
210 
211 	sync->interval = interval;
212 
213 	err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST, &pdu_prev, &pdu,
214 				     &extra_data_prev, &extra_data, &ter_idx);
215 	if (err) {
216 		return err;
217 	}
218 
219 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
220 	if (extra_data) {
221 		ull_adv_sync_extra_data_set_clear(extra_data_prev, extra_data,
222 						  0U, 0U, NULL);
223 	}
224 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
225 
226 	/* FIXME - handle flags (i.e. adding TxPower if specified) */
227 	err = ull_adv_sync_duplicate(pdu_prev, pdu);
228 	if (err) {
229 		return err;
230 	}
231 
232 	lll_adv_sync_data_enqueue(lll_sync, ter_idx);
233 
234 	sync->is_data_cmplt = 1U;
235 
236 	return 0;
237 }
238 
239 #if defined(CONFIG_BT_CTLR_ADV_ISO) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ull_adv_sync_iso_created(struct ll_adv_sync_set * sync)240 void ull_adv_sync_iso_created(struct ll_adv_sync_set *sync)
241 {
242 	if (sync->lll.iso && sync->is_started) {
243 		uint8_t iso_handle = sync->lll.iso->handle;
244 		uint8_t handle = sync_handle_get(sync);
245 
246 		ticker_update_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
247 			   (TICKER_ID_ADV_SYNC_BASE + handle), 0, 0, 0, 0, 0, 0,
248 			   ticker_update_op_cb, sync, 0, TICKER_ID_ADV_ISO_BASE + iso_handle);
249 	}
250 }
251 #endif /* CONFIG_BT_CTLR_ADV_ISO && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
252 
ll_adv_sync_ad_data_set(uint8_t handle,uint8_t op,uint8_t len,uint8_t const * const data)253 uint8_t ll_adv_sync_ad_data_set(uint8_t handle, uint8_t op, uint8_t len,
254 				uint8_t const *const data)
255 {
256 	void *extra_data_prev, *extra_data;
257 	struct pdu_adv *pdu_prev, *pdu;
258 	struct lll_adv_sync *lll_sync;
259 	struct ll_adv_sync_set *sync;
260 	struct ll_adv_set *adv;
261 	uint8_t ter_idx;
262 	uint8_t err;
263 
264 	/* Check for valid advertising set */
265 	adv =  ull_adv_is_created_get(handle);
266 	if (!adv) {
267 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
268 	}
269 
270 	/* Check for advertising set type */
271 	if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
272 		err = adv_type_check(adv);
273 		if (err) {
274 			return err;
275 		}
276 	}
277 
278 	/* Check if periodic advertising is associated with advertising set */
279 	lll_sync = adv->lll.sync;
280 	if (!lll_sync) {
281 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
282 	}
283 
284 	sync = HDR_LLL2ULL(lll_sync);
285 
286 	/* Reject setting fragment when periodic advertising is enabled */
287 	if (sync->is_enabled && (op <= BT_HCI_LE_EXT_ADV_OP_LAST_FRAG)) {
288 		return BT_HCI_ERR_CMD_DISALLOWED;
289 	}
290 
291 	/* Reject intermediate op before first op */
292 	if (sync->is_data_cmplt &&
293 	    ((op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG) ||
294 	     (op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG))) {
295 		return BT_HCI_ERR_CMD_DISALLOWED;
296 	}
297 
298 	/* Reject unchanged op before complete status */
299 	if (!sync->is_data_cmplt &&
300 	    (op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA)) {
301 		return BT_HCI_ERR_CMD_DISALLOWED;
302 	}
303 
304 	/* Reject len > 191 bytes if chain PDUs unsupported */
305 	if (!IS_ENABLED(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK) &&
306 	    (len > PDU_AC_EXT_AD_DATA_LEN_MAX)) {
307 		return BT_HCI_ERR_CMD_DISALLOWED;
308 	}
309 
310 	/* Allocate new PDU buffer at latest double buffer index */
311 	err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
312 				     &pdu_prev, &pdu, &extra_data_prev,
313 				     &extra_data, &ter_idx);
314 	if (err) {
315 		return err;
316 	}
317 
318 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
319 	if (extra_data) {
320 		ull_adv_sync_extra_data_set_clear(extra_data_prev, extra_data,
321 						  0U, 0U, NULL);
322 	}
323 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
324 
325 	if (op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA) {
326 		/* Only update ADI */
327 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
328 		err = ull_adv_sync_update_adi(lll_sync, pdu_prev, pdu);
329 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
330 	} else if (op == BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG ||
331 		   op == BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA) {
332 		err = ull_adv_sync_ad_replace(lll_sync, pdu_prev, pdu, data, len);
333 	} else {
334 		err = ull_adv_sync_ad_add(lll_sync, pdu_prev, pdu, data, len);
335 	}
336 	if (err) {
337 		return err;
338 	}
339 
340 	/* Parameter validation, if operation is 0x04 (unchanged data)
341 	 * - periodic advertising is disabled, or
342 	 * - periodic advertising contains no data, or
343 	 * - Advertising Data Length is not zero
344 	 */
345 	if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK) &&
346 	    (op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA) &&
347 	    ((!sync->is_enabled) ||
348 	     (pdu->len == pdu->adv_ext_ind.ext_hdr_len + 1U) ||
349 	     (len != 0U))) {
350 		/* NOTE: latest PDU was not consumed by LLL and as
351 		 * ull_adv_sync_pdu_alloc() has reverted back the double buffer
352 		 * with the first PDU, and returned the latest PDU as the new
353 		 * PDU, we need to enqueue back the new PDU which is in fact
354 		 * the latest PDU.
355 		 */
356 		if (pdu_prev == pdu) {
357 			lll_adv_sync_data_enqueue(lll_sync, ter_idx);
358 		}
359 
360 		return BT_HCI_ERR_INVALID_PARAM;
361 	}
362 
363 	/* Update time reservation if Periodic Advertising events are active */
364 	if (sync->is_started) {
365 		err = ull_adv_sync_time_update(sync, pdu);
366 		if (err) {
367 			return err;
368 		}
369 	}
370 
371 	/* Commit the updated Periodic Advertising Data */
372 	lll_adv_sync_data_enqueue(lll_sync, ter_idx);
373 
374 	/* Check if Periodic Advertising Data is complete */
375 	sync->is_data_cmplt = (op >= BT_HCI_LE_EXT_ADV_OP_LAST_FRAG);
376 
377 	return 0;
378 }
379 
ll_adv_sync_enable(uint8_t handle,uint8_t enable)380 uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
381 {
382 	struct pdu_adv *ter_pdu = NULL;
383 	struct lll_adv_sync *lll_sync;
384 	struct ll_adv_sync_set *sync;
385 	uint8_t sync_got_enabled;
386 	struct ll_adv_set *adv;
387 	uint8_t ter_idx;
388 	uint8_t err;
389 
390 	/* Check for valid advertising set */
391 	adv = ull_adv_is_created_get(handle);
392 	if (!adv) {
393 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
394 	}
395 
396 	/* Check if periodic advertising is associated with advertising set */
397 	lll_sync = adv->lll.sync;
398 	if (!lll_sync) {
399 		return BT_HCI_ERR_CMD_DISALLOWED;
400 	}
401 
402 	/* Check for invalid enable bit fields */
403 	if ((enable > (BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE |
404 		       BT_HCI_LE_SET_PER_ADV_ENABLE_ADI)) ||
405 	    (!IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT) &&
406 	     (enable > BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE))) {
407 		return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
408 	}
409 
410 	sync = HDR_LLL2ULL(lll_sync);
411 
412 	/* Handle periodic advertising being disable */
413 	if (!(enable & BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE)) {
414 		if (!sync->is_enabled) {
415 			return BT_HCI_ERR_CMD_DISALLOWED;
416 		}
417 
418 		if (!sync->is_started) {
419 			sync->is_enabled = 0U;
420 
421 			return 0;
422 		}
423 
424 		err = sync_remove(sync, adv, 0U);
425 		return err;
426 	}
427 
428 	/* Check for advertising set type */
429 	if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) {
430 		err = adv_type_check(adv);
431 		if (err) {
432 			return BT_HCI_ERR_CMD_DISALLOWED;
433 		}
434 	}
435 
436 	/* Check for periodic data being complete */
437 	if (!sync->is_data_cmplt) {
438 		return BT_HCI_ERR_CMD_DISALLOWED;
439 	}
440 
441 	/* TODO: Check packet too long */
442 
443 	/* Check for already enabled periodic advertising set */
444 	sync_got_enabled = 0U;
445 	if (sync->is_enabled) {
446 		/* TODO: Enabling an already enabled advertising changes its
447 		 * random address.
448 		 */
449 	} else {
450 		sync_got_enabled = 1U;
451 	}
452 
453 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
454 	/* Add/Remove ADI */
455 	{
456 		void *extra_data_prev, *extra_data;
457 		struct pdu_adv *pdu_prev, *pdu;
458 
459 		err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
460 					     &pdu_prev, &pdu, &extra_data_prev,
461 					     &extra_data, &ter_idx);
462 		if (err) {
463 			return err;
464 		}
465 
466 		/* Use PDU to calculate time reservation */
467 		ter_pdu = pdu;
468 
469 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
470 		if (extra_data) {
471 			ull_adv_sync_extra_data_set_clear(extra_data_prev,
472 							  extra_data, 0U, 0U,
473 							  NULL);
474 		}
475 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
476 
477 		if (enable & BT_HCI_LE_SET_PER_ADV_ENABLE_ADI) {
478 			ull_adv_sync_add_adi(lll_sync, pdu_prev, pdu);
479 		} else {
480 			ull_adv_sync_remove_adi(lll_sync, pdu_prev, pdu);
481 		}
482 	}
483 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
484 
485 	/* Start Periodic Advertising events if Extended Advertising events are
486 	 * active.
487 	 */
488 	if (adv->is_enabled && !sync->is_started) {
489 		struct pdu_adv_sync_info *sync_info;
490 		uint8_t value[1 + sizeof(sync_info)];
491 		uint32_t ticks_slot_overhead_aux;
492 		uint32_t ticks_slot_overhead;
493 		struct lll_adv_aux *lll_aux;
494 		struct ll_adv_aux_set *aux;
495 		uint32_t ticks_anchor_sync;
496 		uint32_t ticks_anchor_aux;
497 		uint8_t pri_idx, sec_idx;
498 		uint32_t ret;
499 
500 		lll_aux = adv->lll.aux;
501 
502 		/* Add sync_info into auxiliary PDU */
503 		err = ull_adv_aux_hdr_set_clear(adv,
504 						ULL_ADV_PDU_HDR_FIELD_SYNC_INFO,
505 						0U, value, &pri_idx, &sec_idx);
506 		if (err) {
507 			return err;
508 		}
509 
510 		/* First byte in the length-value encoded parameter is size of
511 		 * sync_info structure, followed by pointer to sync_info in the
512 		 * PDU.
513 		 */
514 		(void)memcpy(&sync_info, &value[1], sizeof(sync_info));
515 		ull_adv_sync_info_fill(sync, sync_info);
516 
517 		/* Calculate the ticks_slot and return slot overhead */
518 		ticks_slot_overhead = ull_adv_sync_evt_init(adv, sync, ter_pdu);
519 
520 		/* If Auxiliary PDU already active, find and schedule Periodic
521 		 * advertising follow it.
522 		 */
523 		if (lll_aux) {
524 			/* Auxiliary set already active (due to other fields
525 			 * being already present or being started prior).
526 			 */
527 			aux = NULL;
528 			ticks_anchor_aux = 0U; /* unused in this path */
529 			ticks_slot_overhead_aux = 0U; /* unused in this path */
530 
531 			/* Find the anchor after the group of active auxiliary
532 			 * sets such that Periodic Advertising events are placed
533 			 * in non-overlapping timeline when auxiliary and
534 			 * Periodic Advertising have similar event interval.
535 			 */
536 			ticks_anchor_sync = ticker_ticks_now_get() +
537 				HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
538 
539 #if defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
540 			err = ull_sched_adv_aux_sync_free_anchor_get(sync->ull.ticks_slot,
541 								     &ticks_anchor_sync);
542 			if (!err) {
543 				ticks_anchor_sync += HAL_TICKER_US_TO_TICKS(
544 					MAX(EVENT_MAFS_US,
545 					    EVENT_OVERHEAD_START_US) -
546 					EVENT_OVERHEAD_START_US +
547 					(EVENT_TICKER_RES_MARGIN_US << 1));
548 			}
549 #endif /* CONFIG_BT_CTLR_SCHED_ADVANCED */
550 
551 		} else {
552 			/* Auxiliary set will be started due to inclusion of
553 			 * sync info field.
554 			 */
555 			lll_aux = adv->lll.aux;
556 			aux = HDR_LLL2ULL(lll_aux);
557 			ticks_anchor_aux = ticker_ticks_now_get() +
558 				HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
559 			ticks_slot_overhead_aux =
560 				ull_adv_aux_evt_init(aux, &ticks_anchor_aux);
561 
562 #if !defined(CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET) || \
563 	(CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET == 0)
564 			ticks_anchor_sync = ticks_anchor_aux +
565 				ticks_slot_overhead_aux + aux->ull.ticks_slot +
566 				HAL_TICKER_US_TO_TICKS(
567 					MAX(EVENT_MAFS_US,
568 					    EVENT_OVERHEAD_START_US) -
569 					EVENT_OVERHEAD_START_US +
570 					(EVENT_TICKER_RES_MARGIN_US << 1));
571 
572 #else /* CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET */
573 			ticks_anchor_sync = ticks_anchor_aux +
574 				HAL_TICKER_US_TO_TICKS(
575 					CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET);
576 
577 #endif /* CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET */
578 		}
579 
580 		ret = ull_adv_sync_start(adv, sync, ticks_anchor_sync,
581 					 ticks_slot_overhead);
582 		if (ret) {
583 			sync_remove(sync, adv, 1U);
584 
585 			return BT_HCI_ERR_INSUFFICIENT_RESOURCES;
586 		}
587 
588 		sync->is_started = 1U;
589 
590 		lll_adv_aux_data_enqueue(lll_aux, sec_idx);
591 		lll_adv_data_enqueue(&adv->lll, pri_idx);
592 
593 		if (aux) {
594 			/* Keep aux interval equal or higher than primary PDU
595 			 * interval.
596 			 */
597 			aux->interval = adv->interval +
598 					(HAL_TICKER_TICKS_TO_US(
599 						ULL_ADV_RANDOM_DELAY) /
600 						ADV_INT_UNIT_US);
601 
602 			ret = ull_adv_aux_start(aux, ticks_anchor_aux,
603 						ticks_slot_overhead_aux);
604 			if (ret) {
605 				sync_remove(sync, adv, 1U);
606 
607 				return BT_HCI_ERR_INSUFFICIENT_RESOURCES;
608 			}
609 
610 			aux->is_started = 1U;
611 
612 		} else if (IS_ENABLED(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)) {
613 			/* notify the auxiliary set */
614 			ull_adv_sync_started_stopped(HDR_LLL2ULL(lll_aux));
615 		}
616 	}
617 
618 	/* Commit the Periodic Advertising data if ADI supported and has been
619 	 * updated.
620 	 */
621 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)) {
622 		lll_adv_sync_data_enqueue(lll_sync, ter_idx);
623 	}
624 
625 	if (sync_got_enabled) {
626 		sync->is_enabled = sync_got_enabled;
627 	}
628 
629 	return 0;
630 }
631 
632 #if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
633 /* @brief Link Layer interface function corresponding to HCI LE Periodic
634  *        Advertising Set Info Transfer command.
635  *
636  * @param[in] conn_handle Connection_Handle identifying the connected device
637  *            Range: 0x0000 to 0x0EFF.
638  * @param[in] service_data Service_Data value provided by the Host for use by the
639  *            Host of the peer device.
640  * @param[in] adv_handle Advertising_Handle identifying the advertising
641  *            set. Range: 0x00 to 0xEF.
642  *
643  * @return HCI error codes as documented in Bluetooth Core Specification v5.4.
644  */
ll_adv_sync_set_info_transfer(uint16_t conn_handle,uint16_t service_data,uint8_t adv_handle)645 uint8_t ll_adv_sync_set_info_transfer(uint16_t conn_handle, uint16_t service_data,
646 				      uint8_t adv_handle)
647 {
648 	struct ll_adv_sync_set *sync;
649 	struct ll_adv_set *adv;
650 	struct ll_conn *conn;
651 
652 	conn = ll_connected_get(conn_handle);
653 	if (!conn) {
654 		return BT_HCI_ERR_UNKNOWN_CONN_ID;
655 	}
656 
657 	/* Verify that adv_handle is valid and periodic advertising is enabled */
658 	adv = ull_adv_is_created_get(adv_handle);
659 	if (!adv) {
660 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
661 	}
662 
663 	if (!adv->lll.sync) {
664 		return BT_HCI_ERR_CMD_DISALLOWED;
665 	}
666 
667 	sync = HDR_LLL2ULL(adv->lll.sync);
668 	if (!sync->is_enabled) {
669 		return BT_HCI_ERR_CMD_DISALLOWED;
670 	}
671 
672 	/* Call llcp to start LLCP_PERIODIC_SYNC_IND */
673 	return ull_cp_periodic_sync(conn, NULL, sync, service_data);
674 }
675 #endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */
676 
ull_adv_sync_init(void)677 int ull_adv_sync_init(void)
678 {
679 	int err;
680 
681 	err = init_reset();
682 	if (err) {
683 		return err;
684 	}
685 
686 	return 0;
687 }
688 
ull_adv_sync_reset(void)689 int ull_adv_sync_reset(void)
690 {
691 	struct lll_adv_sync *lll_sync;
692 	struct ll_adv_sync_set *sync;
693 	struct ll_adv_set *adv;
694 	uint8_t handle;
695 	int err;
696 
697 	for (handle = 0U; handle < BT_CTLR_ADV_SET; handle++) {
698 		adv = ull_adv_is_created_get(handle);
699 		if (!adv) {
700 			continue;
701 		}
702 
703 		lll_sync = adv->lll.sync;
704 		if (!lll_sync) {
705 			continue;
706 		}
707 
708 		sync = HDR_LLL2ULL(lll_sync);
709 
710 		if (!sync->is_started) {
711 			sync->is_enabled = 0U;
712 
713 			continue;
714 		}
715 
716 		err = sync_remove(sync, adv, 0U);
717 		if (err) {
718 			return err;
719 		}
720 	}
721 
722 	return 0;
723 }
724 
ull_adv_sync_reset_finalize(void)725 int ull_adv_sync_reset_finalize(void)
726 {
727 	int err;
728 
729 	err = init_reset();
730 	if (err) {
731 		return err;
732 	}
733 
734 	return 0;
735 }
736 
ull_adv_sync_get(uint8_t handle)737 struct ll_adv_sync_set *ull_adv_sync_get(uint8_t handle)
738 {
739 	if (handle >= CONFIG_BT_CTLR_ADV_SYNC_SET) {
740 		return NULL;
741 	}
742 
743 	return &ll_adv_sync_pool[handle];
744 }
745 
ull_adv_sync_handle_get(const struct ll_adv_sync_set * sync)746 uint16_t ull_adv_sync_handle_get(const struct ll_adv_sync_set *sync)
747 {
748 	return sync_handle_get(sync);
749 }
750 
ull_adv_sync_lll_handle_get(const struct lll_adv_sync * lll)751 uint16_t ull_adv_sync_lll_handle_get(const struct lll_adv_sync *lll)
752 {
753 	return sync_handle_get((void *)lll->hdr.parent);
754 }
755 
ull_adv_sync_release(struct ll_adv_sync_set * sync)756 void ull_adv_sync_release(struct ll_adv_sync_set *sync)
757 {
758 	lll_adv_sync_data_release(&sync->lll);
759 	sync_release(sync);
760 }
761 
ull_adv_sync_time_get(const struct ll_adv_sync_set * sync,uint8_t pdu_len)762 uint32_t ull_adv_sync_time_get(const struct ll_adv_sync_set *sync,
763 			       uint8_t pdu_len)
764 {
765 	const struct lll_adv_sync *lll_sync = &sync->lll;
766 	const struct lll_adv *lll = lll_sync->adv;
767 	uint32_t time_us;
768 
769 	/* NOTE: 16-bit values are sufficient for minimum radio event time
770 	 *       reservation, 32-bit are used here so that reservations for
771 	 *       whole back-to-back chaining of PDUs can be accommodated where
772 	 *       the required microseconds could overflow 16-bits, example,
773 	 *       back-to-back chained Coded PHY PDUs.
774 	 */
775 
776 	time_us = PDU_AC_US(pdu_len, lll->phy_s, lll->phy_flags) +
777 		  EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
778 
779 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
780 	struct ll_adv_set *adv = HDR_LLL2ULL(lll);
781 	struct lll_df_adv_cfg *df_cfg = adv->df_cfg;
782 
783 	if (df_cfg && df_cfg->is_enabled) {
784 		time_us += CTE_LEN_US(df_cfg->cte_length);
785 	}
786 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
787 
788 	return time_us;
789 }
790 
ull_adv_sync_evt_init(struct ll_adv_set * adv,struct ll_adv_sync_set * sync,struct pdu_adv * pdu)791 uint32_t ull_adv_sync_evt_init(struct ll_adv_set *adv,
792 			       struct ll_adv_sync_set *sync,
793 			       struct pdu_adv *pdu)
794 {
795 	uint32_t ticks_slot_overhead;
796 	uint32_t ticks_slot_offset;
797 	uint32_t time_us;
798 
799 	ull_hdr_init(&sync->ull);
800 
801 	if (!pdu) {
802 		pdu = lll_adv_sync_data_peek(&sync->lll, NULL);
803 	}
804 
805 	time_us = sync_time_get(sync, pdu);
806 
807 	/* TODO: active_to_start feature port */
808 	sync->ull.ticks_active_to_start = 0U;
809 	sync->ull.ticks_prepare_to_start =
810 		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
811 	sync->ull.ticks_preempt_to_start =
812 		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
813 	sync->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
814 
815 	ticks_slot_offset = MAX(sync->ull.ticks_active_to_start,
816 				sync->ull.ticks_prepare_to_start);
817 	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
818 		ticks_slot_overhead = ticks_slot_offset;
819 	} else {
820 		ticks_slot_overhead = 0U;
821 	}
822 
823 	return ticks_slot_overhead;
824 }
825 
ull_adv_sync_start(struct ll_adv_set * adv,struct ll_adv_sync_set * sync,uint32_t ticks_anchor,uint32_t ticks_slot_overhead)826 uint32_t ull_adv_sync_start(struct ll_adv_set *adv,
827 			    struct ll_adv_sync_set *sync,
828 			    uint32_t ticks_anchor,
829 			    uint32_t ticks_slot_overhead)
830 {
831 	uint32_t volatile ret_cb;
832 	uint32_t interval_us;
833 	uint8_t sync_handle;
834 	uint32_t ret;
835 
836 	interval_us = (uint32_t)sync->interval * PERIODIC_INT_UNIT_US;
837 
838 	sync_handle = sync_handle_get(sync);
839 
840 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
841 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
842 	if (sync->lll.iso) {
843 		ll_adv_sync_ticker_ext[sync_handle].expire_info_id =
844 			TICKER_ID_ADV_ISO_BASE + sync->lll.iso->handle;
845 	} else {
846 		ll_adv_sync_ticker_ext[sync_handle].expire_info_id = TICKER_NULL;
847 	}
848 
849 	ll_adv_sync_ticker_ext[sync_handle].ext_timeout_func = ticker_cb;
850 
851 	ret_cb = TICKER_STATUS_BUSY;
852 	ret = ticker_start_ext(
853 #else /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
854 
855 	ret_cb = TICKER_STATUS_BUSY;
856 	ret = ticker_start(
857 #endif /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
858 			   TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
859 			   (TICKER_ID_ADV_SYNC_BASE + sync_handle),
860 			   ticks_anchor, 0U,
861 			   HAL_TICKER_US_TO_TICKS(interval_us),
862 			   HAL_TICKER_REMAINDER(interval_us), TICKER_NULL_LAZY,
863 			   (sync->ull.ticks_slot + ticks_slot_overhead),
864 			   ticker_cb, sync,
865 			   ull_ticker_status_give, (void *)&ret_cb
866 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
867 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
868 			   ,
869 			   &ll_adv_sync_ticker_ext[sync_handle]
870 #endif /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
871 			   );
872 	ret = ull_ticker_status_take(ret, &ret_cb);
873 
874 	return ret;
875 }
876 
ull_adv_sync_time_update(struct ll_adv_sync_set * sync,struct pdu_adv * pdu)877 uint8_t ull_adv_sync_time_update(struct ll_adv_sync_set *sync,
878 				 struct pdu_adv *pdu)
879 {
880 	uint32_t time_ticks;
881 	uint32_t time_us;
882 
883 	time_us = sync_time_get(sync, pdu);
884 	time_ticks = HAL_TICKER_US_TO_TICKS(time_us);
885 
886 #if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING)
887 	uint32_t volatile ret_cb;
888 	uint32_t ticks_minus;
889 	uint32_t ticks_plus;
890 	uint32_t ret;
891 
892 	if (sync->ull.ticks_slot > time_ticks) {
893 		ticks_minus = sync->ull.ticks_slot - time_ticks;
894 		ticks_plus = 0U;
895 	} else if (sync->ull.ticks_slot < time_ticks) {
896 		ticks_minus = 0U;
897 		ticks_plus = time_ticks - sync->ull.ticks_slot;
898 	} else {
899 		return BT_HCI_ERR_SUCCESS;
900 	}
901 
902 	ret_cb = TICKER_STATUS_BUSY;
903 	ret = ticker_update(TICKER_INSTANCE_ID_CTLR,
904 			    TICKER_USER_ID_THREAD,
905 			    (TICKER_ID_ADV_SYNC_BASE + sync_handle_get(sync)),
906 			    0, 0, ticks_plus, ticks_minus, 0, 0,
907 			    ull_ticker_status_give, (void *)&ret_cb);
908 	ret = ull_ticker_status_take(ret, &ret_cb);
909 	if (ret != TICKER_STATUS_SUCCESS) {
910 		return BT_HCI_ERR_CMD_DISALLOWED;
911 	}
912 #endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */
913 
914 	sync->ull.ticks_slot = time_ticks;
915 
916 	return BT_HCI_ERR_SUCCESS;
917 }
918 
ull_adv_sync_chm_update(void)919 uint8_t ull_adv_sync_chm_update(void)
920 {
921 	uint8_t handle;
922 
923 	handle = CONFIG_BT_CTLR_ADV_SYNC_SET;
924 	while (handle--) {
925 		(void)sync_chm_update(handle);
926 	}
927 
928 	/* TODO: Should failure due to Channel Map Update being already in
929 	 *       progress be returned to caller?
930 	 */
931 	return 0;
932 }
933 
ull_adv_sync_chm_complete(struct node_rx_pdu * rx)934 void ull_adv_sync_chm_complete(struct node_rx_pdu *rx)
935 {
936 	struct lll_adv_sync *lll_sync;
937 	struct pdu_adv *pdu_prev;
938 	struct ll_adv_set *adv;
939 	struct pdu_adv *pdu;
940 	uint8_t ter_idx;
941 	uint8_t err;
942 
943 	/* Allocate next Sync PDU */
944 	pdu_prev = NULL;
945 	pdu = NULL;
946 	lll_sync = rx->rx_ftr.param;
947 	adv = HDR_LLL2ULL(lll_sync->adv);
948 	err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
949 				     &pdu_prev, &pdu, NULL, NULL, &ter_idx);
950 	LL_ASSERT(!err);
951 
952 	err = ull_adv_sync_remove_from_acad(lll_sync, pdu_prev, pdu,
953 					    PDU_ADV_DATA_TYPE_CHANNEL_MAP_UPDATE_IND);
954 	LL_ASSERT(!err);
955 
956 	lll_adv_sync_data_enqueue(lll_sync, ter_idx);
957 }
958 
ull_adv_sync_info_fill(struct ll_adv_sync_set * sync,struct pdu_adv_sync_info * si)959 void ull_adv_sync_info_fill(struct ll_adv_sync_set *sync,
960 			    struct pdu_adv_sync_info *si)
961 {
962 	struct lll_adv_sync *lll_sync;
963 
964 	/* NOTE: sync offset and offset unit filled by secondary prepare.
965 	 *
966 	 * If sync_info is part of ADV PDU the offs_adjust field
967 	 * is always set to 0.
968 	 */
969 	PDU_ADV_SYNC_INFO_OFFS_SET(si, 0U, OFFS_UNIT_VALUE_30_US, 0U);
970 
971 	/* Fill the interval, access address and CRC init */
972 	si->interval = sys_cpu_to_le16(sync->interval);
973 	lll_sync = &sync->lll;
974 	(void)memcpy(&si->aa, lll_sync->access_addr, sizeof(si->aa));
975 	(void)memcpy(si->crc_init, lll_sync->crc_init, sizeof(si->crc_init));
976 
977 	/* NOTE: Filled by secondary prepare */
978 	si->evt_cntr = 0U;
979 }
980 
981 #if !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ull_adv_sync_offset_get(struct ll_adv_set * adv)982 void ull_adv_sync_offset_get(struct ll_adv_set *adv)
983 {
984 	static memq_link_t link;
985 	static struct mayfly mfy = {0, 0, &link, NULL, mfy_sync_offset_get};
986 	uint32_t ret;
987 
988 	mfy.param = adv;
989 	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
990 			     &mfy);
991 	LL_ASSERT(!ret);
992 }
993 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
994 
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)995 void ull_adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags,
996 			   uint8_t phy_s, uint8_t phy_flags,
997 			   struct pdu_cte_info *cte_info)
998 {
999 	struct pdu_adv_com_ext_adv *com_hdr;
1000 	struct pdu_adv_ext_hdr *ext_hdr;
1001 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
1002 	struct pdu_adv_aux_ptr *aux_ptr;
1003 	uint32_t cte_len_us;
1004 #endif
1005 	uint8_t *dptr;
1006 	uint8_t len;
1007 
1008 	pdu->type = PDU_ADV_TYPE_AUX_SYNC_IND;
1009 	pdu->rfu = 0U;
1010 	pdu->chan_sel = 0U;
1011 
1012 	pdu->tx_addr = 0U;
1013 	pdu->rx_addr = 0U;
1014 
1015 	com_hdr = &pdu->adv_ext_ind;
1016 	/* Non-connectable and Non-scannable adv mode */
1017 	com_hdr->adv_mode = 0U;
1018 
1019 	ext_hdr = &com_hdr->ext_hdr;
1020 	*(uint8_t *)ext_hdr = ext_hdr_flags;
1021 	dptr = ext_hdr->data;
1022 
1023 	LL_ASSERT(!(ext_hdr_flags & (ULL_ADV_PDU_HDR_FIELD_ADVA | ULL_ADV_PDU_HDR_FIELD_TARGETA |
1024 #if !defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1025 				     ULL_ADV_PDU_HDR_FIELD_ADI |
1026 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1027 				     ULL_ADV_PDU_HDR_FIELD_SYNC_INFO)));
1028 
1029 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
1030 	if (IS_ENABLED(CONFIG_BT_CTLR_DF_ADV_CTE_TX) &&
1031 	    (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_CTE_INFO)) {
1032 		(void)memcpy(dptr, cte_info, sizeof(*cte_info));
1033 		cte_len_us = CTE_LEN_US(cte_info->time);
1034 		dptr += sizeof(struct pdu_cte_info);
1035 	} else {
1036 		cte_len_us = 0U;
1037 	}
1038 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
1039 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT) &&
1040 	    (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_ADI)) {
1041 		dptr += sizeof(struct pdu_adv_adi);
1042 	}
1043 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
1044 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK) &&
1045 	    (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_AUX_PTR)) {
1046 		aux_ptr = (void *)dptr;
1047 		dptr += sizeof(struct pdu_adv_aux_ptr);
1048 	}
1049 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
1050 	if (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_TX_POWER) {
1051 		dptr += sizeof(uint8_t);
1052 	}
1053 
1054 	/* Calc tertiary PDU len */
1055 	len = ull_adv_aux_hdr_len_calc(com_hdr, &dptr);
1056 	ull_adv_aux_hdr_len_fill(com_hdr, len);
1057 
1058 	pdu->len = len;
1059 
1060 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
1061 	/* Fill aux offset in aux pointer field */
1062 	if (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) {
1063 		uint32_t offs_us;
1064 
1065 		offs_us = PDU_AC_US(pdu->len, phy_s, phy_flags) +
1066 			  EVENT_SYNC_B2B_MAFS_US;
1067 		offs_us += cte_len_us;
1068 		ull_adv_aux_ptr_fill(aux_ptr, offs_us, phy_s);
1069 	}
1070 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
1071 }
1072 
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)1073 uint8_t ull_adv_sync_pdu_alloc(struct ll_adv_set *adv,
1074 			       enum ull_adv_pdu_extra_data_flag extra_data_flag,
1075 			       struct pdu_adv **ter_pdu_prev, struct pdu_adv **ter_pdu_new,
1076 			       void **extra_data_prev, void **extra_data_new, uint8_t *ter_idx)
1077 {
1078 	struct pdu_adv *pdu_prev, *pdu_new;
1079 	struct lll_adv_sync *lll_sync;
1080 	void *ed_prev;
1081 #if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
1082 	void *ed_new;
1083 #endif
1084 
1085 	lll_sync = adv->lll.sync;
1086 	if (!lll_sync) {
1087 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
1088 	}
1089 
1090 	/* Get reference to previous periodic advertising PDU data */
1091 	pdu_prev = lll_adv_sync_data_peek(lll_sync, &ed_prev);
1092 
1093 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1094 	/* Get reference to new periodic advertising PDU data buffer */
1095 	if (extra_data_flag == ULL_ADV_PDU_EXTRA_DATA_ALLOC_ALWAYS ||
1096 	    (extra_data_flag == ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST && ed_prev)) {
1097 		/* If there was an extra data in past PDU data or it is required
1098 		 * by the hdr_add_fields then allocate memory for it.
1099 		 */
1100 		pdu_new = lll_adv_sync_data_alloc(lll_sync, &ed_new,
1101 						  ter_idx);
1102 		if (!pdu_new) {
1103 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1104 		}
1105 	} else {
1106 		ed_new = NULL;
1107 #else
1108 	{
1109 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1110 		pdu_new = lll_adv_sync_data_alloc(lll_sync, NULL, ter_idx);
1111 		if (!pdu_new) {
1112 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1113 		}
1114 	}
1115 
1116 #if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
1117 	if (extra_data_prev) {
1118 		*extra_data_prev = ed_prev;
1119 	}
1120 	if (extra_data_new) {
1121 		*extra_data_new = ed_new;
1122 	}
1123 #endif /* CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY */
1124 
1125 	*ter_pdu_prev = pdu_prev;
1126 	*ter_pdu_new = pdu_new;
1127 
1128 	return 0;
1129 }
1130 
1131 uint8_t ull_adv_sync_duplicate(const struct pdu_adv *pdu_prev, struct pdu_adv *pdu_new)
1132 {
1133 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1134 	/* Duplicate chain PDUs */
1135 	return ull_adv_sync_duplicate_chain(pdu_prev, pdu_new);
1136 #else
1137 	ull_adv_sync_copy_pdu(pdu_prev, pdu_new);
1138 
1139 	return 0U;
1140 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1141 }
1142 
1143 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK) || defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX) || \
1144 	defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1145 static void ull_adv_sync_add_to_header(struct pdu_adv *pdu,
1146 				       const struct pdu_adv_ext_hdr *fields,
1147 				       uint8_t *ad_overflow, uint8_t *overflow_len)
1148 {
1149 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
1150 	uint8_t delta = 0U;
1151 	uint8_t *dptr;
1152 
1153 	if (overflow_len) {
1154 		*overflow_len = 0U;
1155 	}
1156 
1157 	/* AdvA, TargetA and SyncInfo is RFU for periodic advertising */
1158 	if (fields->cte_info && (hdr->ext_hdr_len == 0U || hdr->ext_hdr.cte_info == 0U)) {
1159 		delta += sizeof(struct pdu_cte_info);
1160 	}
1161 	if (fields->adi && (hdr->ext_hdr_len == 0U || hdr->ext_hdr.adi == 0U)) {
1162 		delta += sizeof(struct pdu_adv_adi);
1163 	}
1164 	if (fields->aux_ptr && (hdr->ext_hdr_len == 0U || hdr->ext_hdr.aux_ptr == 0U)) {
1165 		delta += sizeof(struct pdu_adv_aux_ptr);
1166 	}
1167 	if (fields->tx_pwr && (hdr->ext_hdr_len == 0U || hdr->ext_hdr.tx_pwr == 0U)) {
1168 		delta += 1U;
1169 	}
1170 
1171 	if (delta == 0U) {
1172 		/* No new fields to add */
1173 		return;
1174 	}
1175 
1176 	if (hdr->ext_hdr_len == 0) {
1177 		/* Add one byte for the header flags */
1178 		delta++;
1179 	}
1180 
1181 	/* Push back any adv data - overflow will be returned via ad_overflow */
1182 	if (pdu->len > hdr->ext_hdr_len + 1U) {
1183 		if (pdu->len > PDU_AC_EXT_PAYLOAD_SIZE_MAX - delta) {
1184 			LL_ASSERT(ad_overflow);
1185 			LL_ASSERT(overflow_len);
1186 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1187 			*overflow_len = delta - (PDU_AC_EXT_PAYLOAD_SIZE_MAX - pdu->len);
1188 			memcpy(ad_overflow,
1189 			       pdu->payload + PDU_AC_EXT_PAYLOAD_SIZE_MAX - *overflow_len,
1190 			       *overflow_len);
1191 			pdu->len -= *overflow_len;
1192 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1193 		}
1194 		dptr = pdu->payload + hdr->ext_hdr_len + 1U;
1195 		memmove(dptr + delta,
1196 			dptr, pdu->len - hdr->ext_hdr_len - 1U);
1197 	}
1198 
1199 	pdu->len += delta;
1200 
1201 	if (hdr->ext_hdr_len == 0U) {
1202 		/* No extended header present, adding one */
1203 		memcpy(&hdr->ext_hdr, fields, sizeof(struct pdu_adv_ext_hdr));
1204 		hdr->ext_hdr_len = delta;
1205 	} else {
1206 		/* Go to end of current extended header and push back fields/ACAD in reverse */
1207 		dptr = hdr->ext_hdr.data;
1208 
1209 		/* AdvA and TargetA is RFU for periodic advertising */
1210 
1211 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1212 		if (hdr->ext_hdr.cte_info) {
1213 			dptr += sizeof(struct pdu_cte_info);
1214 		}
1215 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1216 
1217 		if (hdr->ext_hdr.adi) {
1218 			dptr += sizeof(struct pdu_adv_adi);
1219 		}
1220 
1221 		if (hdr->ext_hdr.aux_ptr) {
1222 			dptr += sizeof(struct pdu_adv_aux_ptr);
1223 		}
1224 
1225 		/* SyncInfo is RFU for periodic advertising */
1226 
1227 		if (hdr->ext_hdr.tx_pwr) {
1228 			dptr++;
1229 		}
1230 
1231 		/* Push back ACAD if any */
1232 		if ((dptr - hdr->ext_hdr_adv_data) < hdr->ext_hdr_len) {
1233 			uint8_t acad_len = hdr->ext_hdr_len - (dptr - hdr->ext_hdr_adv_data);
1234 
1235 			memmove(dptr + delta, dptr, acad_len);
1236 		}
1237 
1238 		/* Set new header size now before starting to decrement delta */
1239 		hdr->ext_hdr_len += delta;
1240 
1241 		/* Now push back or add fields as needed */
1242 
1243 		if (hdr->ext_hdr.tx_pwr) {
1244 			dptr--;
1245 			*(dptr + delta) = *dptr;
1246 		} else if (fields->tx_pwr) {
1247 			hdr->ext_hdr.tx_pwr = 1U;
1248 			delta -= 1U;
1249 		}
1250 
1251 		if (hdr->ext_hdr.aux_ptr) {
1252 			dptr -= sizeof(struct pdu_adv_aux_ptr);
1253 			memmove(dptr + delta, dptr, sizeof(struct pdu_adv_aux_ptr));
1254 		} else if (fields->aux_ptr) {
1255 			hdr->ext_hdr.aux_ptr = 1U;
1256 			delta -= sizeof(struct pdu_adv_aux_ptr);
1257 		}
1258 
1259 		if (hdr->ext_hdr.adi) {
1260 			dptr -= sizeof(struct pdu_adv_adi);
1261 			memmove(dptr + delta, dptr, sizeof(struct pdu_adv_adi));
1262 		} else if (fields->adi) {
1263 			hdr->ext_hdr.adi = 1U;
1264 			delta -= sizeof(struct pdu_adv_adi);
1265 		}
1266 
1267 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1268 		if (hdr->ext_hdr.cte_info) {
1269 			dptr -= sizeof(struct pdu_cte_info);
1270 			memmove(dptr + delta, dptr, sizeof(struct pdu_cte_info));
1271 		} else if (fields->cte_info) {
1272 			hdr->ext_hdr.cte_info = 1U;
1273 			delta -= sizeof(struct pdu_cte_info);
1274 		}
1275 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1276 	}
1277 }
1278 
1279 static void ull_adv_sync_remove_from_header(struct pdu_adv *pdu,
1280 					    const struct pdu_adv_ext_hdr *fields,
1281 					    bool acad)
1282 {
1283 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
1284 	uint8_t orig_hdr_len = hdr->ext_hdr_len;
1285 	uint8_t *dptr;
1286 
1287 	if (orig_hdr_len == 0U) {
1288 		return;
1289 	}
1290 
1291 	dptr = hdr->ext_hdr.data;
1292 
1293 	/* AdvA and TargetA is RFU for periodic advertising */
1294 
1295 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1296 	if (hdr->ext_hdr.cte_info) {
1297 		if (fields->cte_info) {
1298 			memmove(dptr, dptr + sizeof(struct pdu_cte_info),
1299 				hdr->ext_hdr_len - (hdr->ext_hdr.data - dptr));
1300 			hdr->ext_hdr.cte_info = 0U;
1301 			hdr->ext_hdr_len -= sizeof(struct pdu_cte_info);
1302 		} else {
1303 			dptr += sizeof(struct pdu_cte_info);
1304 		}
1305 	}
1306 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1307 
1308 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1309 	if (hdr->ext_hdr.adi) {
1310 		if (fields->adi) {
1311 			memmove(dptr, dptr + sizeof(struct pdu_adv_adi),
1312 				hdr->ext_hdr_len - (hdr->ext_hdr.data - dptr));
1313 			hdr->ext_hdr.adi = 0U;
1314 			hdr->ext_hdr_len -= sizeof(struct pdu_adv_adi);
1315 		} else {
1316 			dptr += sizeof(struct pdu_adv_adi);
1317 		}
1318 	}
1319 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1320 
1321 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1322 	if (hdr->ext_hdr.aux_ptr) {
1323 		if (fields->aux_ptr) {
1324 			memmove(dptr, dptr + sizeof(struct pdu_adv_aux_ptr),
1325 				hdr->ext_hdr_len - (hdr->ext_hdr.data - dptr));
1326 			hdr->ext_hdr.aux_ptr = 0U;
1327 			hdr->ext_hdr_len -= sizeof(struct pdu_adv_aux_ptr);
1328 		} else {
1329 			dptr += sizeof(struct pdu_adv_aux_ptr);
1330 		}
1331 	}
1332 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1333 
1334 	/* SyncInfo is RFU for periodic advertising */
1335 
1336 	if (hdr->ext_hdr.tx_pwr) {
1337 		if (fields->tx_pwr) {
1338 			memmove(dptr, dptr + 1U,
1339 				hdr->ext_hdr_len - (hdr->ext_hdr.data - dptr));
1340 			hdr->ext_hdr.tx_pwr = 0U;
1341 			hdr->ext_hdr_len -= 1U;
1342 		} else {
1343 			dptr++;
1344 		}
1345 	}
1346 
1347 	/* ACAD is the remainder of the header, if any left */
1348 	if (acad) {
1349 		/* Drop any ACAD */
1350 		hdr->ext_hdr_len = dptr - hdr->ext_hdr_adv_data;
1351 	}
1352 
1353 	if (hdr->ext_hdr_len == 1U) {
1354 		/* Only flags left in header, remove it completely */
1355 		hdr->ext_hdr_len = 0U;
1356 	}
1357 
1358 	if (orig_hdr_len != hdr->ext_hdr_len) {
1359 		/* Move adv data if any */
1360 		if (pdu->len > orig_hdr_len + 1U) {
1361 			memmove(hdr->ext_hdr_adv_data + hdr->ext_hdr_len,
1362 				hdr->ext_hdr_adv_data + orig_hdr_len,
1363 				pdu->len - orig_hdr_len - 1U);
1364 		}
1365 
1366 		/* Update total PDU len */
1367 		pdu->len -= orig_hdr_len - hdr->ext_hdr_len;
1368 	}
1369 
1370 }
1371 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK || CONFIG_BT_CTLR_DF_ADV_CTE_TX || \
1372 	*  CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT
1373 	*/
1374 
1375 static void ull_adv_sync_copy_pdu_header(struct pdu_adv *target_pdu,
1376 					 const struct pdu_adv *source_pdu,
1377 					 const struct pdu_adv_ext_hdr *skip_fields,
1378 					 bool skip_acad)
1379 {
1380 	const struct pdu_adv_com_ext_adv *source_hdr = &source_pdu->adv_ext_ind;
1381 	struct pdu_adv_com_ext_adv *target_hdr = &target_pdu->adv_ext_ind;
1382 	const uint8_t *source_dptr;
1383 	uint8_t *target_dptr;
1384 
1385 	LL_ASSERT(target_pdu != source_pdu);
1386 
1387 	/* Initialize PDU header */
1388 	target_pdu->type = source_pdu->type;
1389 	target_pdu->rfu = 0U;
1390 	target_pdu->chan_sel = 0U;
1391 	target_pdu->tx_addr = 0U;
1392 	target_pdu->rx_addr = 0U;
1393 	target_hdr->adv_mode = source_hdr->adv_mode;
1394 
1395 	/* Copy extended header */
1396 	if (source_hdr->ext_hdr_len == 0U) {
1397 		/* No extended header present */
1398 		target_hdr->ext_hdr_len = 0U;
1399 	} else if (!skip_fields && !skip_acad) {
1400 		/* Copy entire extended header */
1401 		memcpy(target_hdr, source_hdr, source_hdr->ext_hdr_len + 1U);
1402 	} else {
1403 		/* Copy field by field */
1404 
1405 		source_dptr = source_hdr->ext_hdr.data;
1406 		target_dptr = target_hdr->ext_hdr.data;
1407 
1408 		/* Initialize extended header flags to all 0 */
1409 		target_hdr->ext_hdr_adv_data[0U] = 0U;
1410 
1411 		/* AdvA and TargetA is RFU for periodic advertising */
1412 
1413 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1414 		if (source_hdr->ext_hdr.cte_info) {
1415 			if (!skip_fields->cte_info) {
1416 				memcpy(target_dptr, source_dptr, sizeof(struct pdu_cte_info));
1417 				target_dptr += sizeof(struct pdu_cte_info);
1418 				target_hdr->ext_hdr.cte_info = 1U;
1419 			}
1420 			source_dptr += sizeof(struct pdu_cte_info);
1421 		}
1422 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1423 
1424 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1425 		if (source_hdr->ext_hdr.adi) {
1426 			if (!skip_fields->adi) {
1427 				memcpy(target_dptr, source_dptr, sizeof(struct pdu_adv_adi));
1428 				target_dptr += sizeof(struct pdu_adv_adi);
1429 				target_hdr->ext_hdr.adi = 1U;
1430 			}
1431 			source_dptr += sizeof(struct pdu_adv_adi);
1432 		}
1433 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1434 
1435 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1436 		if (source_hdr->ext_hdr.aux_ptr) {
1437 			if (!skip_fields->aux_ptr) {
1438 				memcpy(target_dptr, source_dptr, sizeof(struct pdu_adv_aux_ptr));
1439 				target_dptr += sizeof(struct pdu_adv_aux_ptr);
1440 				target_hdr->ext_hdr.aux_ptr = 1U;
1441 			}
1442 			source_dptr += sizeof(struct pdu_adv_aux_ptr);
1443 		}
1444 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1445 
1446 		/* SyncInfo is RFU for periodic advertising */
1447 
1448 		if (source_hdr->ext_hdr.tx_pwr) {
1449 			if (!skip_fields->tx_pwr) {
1450 				*target_dptr = *source_dptr;
1451 				target_dptr++;
1452 				target_hdr->ext_hdr.tx_pwr = 1U;
1453 			}
1454 			source_dptr++;
1455 		}
1456 
1457 		/* ACAD is the remainder of the header, if any left */
1458 		if ((source_dptr - source_hdr->ext_hdr_adv_data) < source_hdr->ext_hdr_len &&
1459 		    !skip_acad) {
1460 			uint8_t acad_len = source_hdr->ext_hdr_len -
1461 					   (source_dptr - source_hdr->ext_hdr_adv_data);
1462 
1463 			memcpy(target_dptr, source_dptr, acad_len);
1464 			target_dptr += acad_len;
1465 		}
1466 
1467 		if (target_dptr == target_hdr->ext_hdr.data) {
1468 			/* Nothing copied, do not include extended header */
1469 			target_hdr->ext_hdr_len = 0U;
1470 		} else {
1471 			target_hdr->ext_hdr_len = target_dptr - target_hdr->ext_hdr_adv_data;
1472 		}
1473 	}
1474 
1475 	target_pdu->len = target_hdr->ext_hdr_len + 1U;
1476 }
1477 
1478 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1479 static void ull_adv_sync_update_pdu_adi(struct lll_adv_sync *lll_sync, struct pdu_adv *pdu,
1480 					uint16_t did)
1481 {
1482 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
1483 	struct ll_adv_set *adv = HDR_LLL2ULL(lll_sync->adv);
1484 	struct pdu_adv_adi *adi;
1485 	uint8_t *dptr;
1486 
1487 	if (hdr->ext_hdr_len == 0U || hdr->ext_hdr.adi == 0U) {
1488 		/* No ADI field present, nothing to do */
1489 		return;
1490 	}
1491 
1492 	/* Find ADI in extended header */
1493 	dptr = hdr->ext_hdr.data;
1494 
1495 	/* AdvA and TargetA is RFU for periodic advertising */
1496 
1497 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1498 	if (hdr->ext_hdr.cte_info) {
1499 		dptr += sizeof(struct pdu_cte_info);
1500 	}
1501 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1502 
1503 	adi = (struct pdu_adv_adi *)dptr;
1504 
1505 	PDU_ADV_ADI_DID_SID_SET(adi, did, adv->sid);
1506 }
1507 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1508 
1509 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1510 static void ull_adv_sync_add_aux_ptr(struct pdu_adv *pdu, uint8_t *ad_overflow,
1511 				     uint8_t *overflow_len)
1512 {
1513 	struct pdu_adv_ext_hdr fields = { 0U };
1514 
1515 	fields.aux_ptr = 1U;
1516 	ull_adv_sync_add_to_header(pdu, &fields, ad_overflow, overflow_len);
1517 }
1518 
1519 static void ull_adv_sync_update_aux_ptr(struct lll_adv_sync *lll_sync, struct pdu_adv *pdu)
1520 {
1521 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
1522 	struct pdu_adv_aux_ptr *aux_ptr;
1523 	struct ll_adv_set *adv;
1524 	uint32_t offs_us;
1525 	uint8_t *dptr;
1526 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1527 	struct pdu_cte_info *cte_info = NULL;
1528 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1529 
1530 	if (!hdr->ext_hdr_len || !hdr->ext_hdr.aux_ptr) {
1531 		/* Nothing to update */
1532 		return;
1533 	}
1534 
1535 	/* Find AuxPtr */
1536 	dptr = hdr->ext_hdr.data;
1537 
1538 	/* AdvA and TargetA is RFU for periodic advertising */
1539 
1540 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1541 	if (hdr->ext_hdr.cte_info) {
1542 		cte_info = (struct pdu_cte_info *)dptr;
1543 		dptr += sizeof(struct pdu_cte_info);
1544 	}
1545 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1546 
1547 	if (hdr->ext_hdr.adi) {
1548 		dptr += sizeof(struct pdu_adv_adi);
1549 	}
1550 
1551 	/* Now at AuxPtr */
1552 	aux_ptr = (struct pdu_adv_aux_ptr *)dptr;
1553 
1554 	/* Calculate and set offset */
1555 	adv = HDR_LLL2ULL(lll_sync->adv);
1556 	offs_us = PDU_AC_US(pdu->len, adv->lll.phy_s, adv->lll.phy_flags) + EVENT_SYNC_B2B_MAFS_US;
1557 
1558 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1559 	/* Add CTE time if relevant */
1560 	if (cte_info) {
1561 		offs_us += CTE_LEN_US(cte_info->time);
1562 	}
1563 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1564 
1565 	ull_adv_aux_ptr_fill(aux_ptr, offs_us, adv->lll.phy_s);
1566 }
1567 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1568 
1569 static uint8_t ull_adv_sync_append_ad_data(struct lll_adv_sync *lll_sync, struct pdu_adv *pdu,
1570 					   const uint8_t *ad, uint8_t ad_len, uint8_t max_ad_len)
1571 {
1572 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1573 	uint8_t ad_overflow[sizeof(struct pdu_adv_aux_ptr) + 1U];
1574 	uint8_t overflow_len = 0U;
1575 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1576 
1577 	while (ad_len) {
1578 		uint8_t pdu_ad_len;
1579 		uint8_t *dptr;
1580 		uint8_t ext_hdr_len;
1581 		uint8_t pdu_add_len = ad_len;
1582 
1583 		ext_hdr_len = pdu->adv_ext_ind.ext_hdr_len + 1U;
1584 		pdu_ad_len = pdu->len - ext_hdr_len;
1585 
1586 		/* Check if the adv data exceeds the configured maximum */
1587 		/* FIXME - this check should include the entire chain */
1588 		if (pdu_ad_len + ad_len > CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) {
1589 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1590 		}
1591 
1592 		/* Only allow up to max_ad_len adv data per PDU */
1593 		if (pdu_ad_len + ad_len > max_ad_len ||
1594 		    PDU_AC_EXT_PAYLOAD_SIZE_MAX - pdu->len < ad_len) {
1595 #if !defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1596 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1597 #else
1598 			/* Will fragment into chain PDU */
1599 
1600 			/* Add aux_ptr to existing PDU */
1601 			ull_adv_sync_add_aux_ptr(pdu, ad_overflow, &overflow_len);
1602 
1603 			pdu_add_len = MAX(0U, MIN(max_ad_len - pdu_ad_len,
1604 					  PDU_AC_EXT_PAYLOAD_SIZE_MAX - pdu->len));
1605 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1606 		}
1607 
1608 		dptr = pdu->payload + pdu->len;
1609 
1610 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1611 		if (pdu_add_len && overflow_len) {
1612 			/* Overflow from previous PDU in chain, add this first */
1613 			memcpy(dptr, ad, overflow_len);
1614 			pdu->len += overflow_len;
1615 			dptr += overflow_len;
1616 			overflow_len = 0U;
1617 		}
1618 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1619 
1620 		if (pdu_add_len) {
1621 			memcpy(dptr, ad, pdu_add_len);
1622 			pdu->len += pdu_add_len;
1623 			ad_len -= pdu_add_len;
1624 			ad += pdu_add_len;
1625 		}
1626 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1627 		if (ad_len) {
1628 			struct pdu_adv_ext_hdr skip_fields = { 0U };
1629 			struct pdu_adv *pdu_chain;
1630 
1631 			/* Fill the aux offset in superior PDU */
1632 			ull_adv_sync_update_aux_ptr(lll_sync, pdu);
1633 
1634 			/* Allocate new PDU */
1635 			pdu_chain = lll_adv_pdu_alloc_pdu_adv();
1636 			if (!pdu_chain) {
1637 				return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1638 			}
1639 
1640 			/* Copy header, removing AuxPtr, CTEInfo and ACAD */
1641 			skip_fields.aux_ptr = 1U;
1642 			skip_fields.cte_info = 1U;
1643 			ull_adv_sync_copy_pdu_header(pdu_chain, pdu, &skip_fields, true);
1644 
1645 			/* Chain the PDU */
1646 			lll_adv_pdu_linked_append(pdu_chain, pdu);
1647 
1648 			pdu = pdu_chain;
1649 		}
1650 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1651 	}
1652 
1653 	return 0U;
1654 }
1655 
1656 static void ull_adv_sync_copy_pdu(const struct pdu_adv *pdu_prev,
1657 				  struct pdu_adv *pdu)
1658 {
1659 	if (pdu == pdu_prev) {
1660 		return;
1661 	}
1662 
1663 	/* Initialize PDU header */
1664 	pdu->type = pdu_prev->type;
1665 	pdu->rfu = 0U;
1666 	pdu->chan_sel = 0U;
1667 	pdu->tx_addr = 0U;
1668 	pdu->rx_addr = 0U;
1669 	pdu->len = pdu_prev->len;
1670 
1671 	/* Copy PDU payload */
1672 	memcpy(pdu->payload, pdu_prev->payload, pdu_prev->len);
1673 }
1674 
1675 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1676 static uint8_t ull_adv_sync_duplicate_chain(const struct pdu_adv *pdu_prev,
1677 					    struct pdu_adv *pdu)
1678 {
1679 	/* If pdu_prev == pdu we are done */
1680 	if (pdu == pdu_prev) {
1681 		return 0U;
1682 	}
1683 
1684 	/* Copy existing PDU chain */
1685 	while (pdu_prev) {
1686 		struct pdu_adv *pdu_chain;
1687 
1688 		ull_adv_sync_copy_pdu(pdu_prev, pdu);
1689 
1690 		pdu_prev = lll_adv_pdu_linked_next_get(pdu_prev);
1691 		pdu_chain = lll_adv_pdu_linked_next_get(pdu);
1692 		if (pdu_prev && !pdu_chain) {
1693 			/* Get a new chain PDU */
1694 			pdu_chain = lll_adv_pdu_alloc_pdu_adv();
1695 			if (!pdu_chain) {
1696 				return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1697 			}
1698 
1699 			/* Link the chain PDU to parent PDU */
1700 			lll_adv_pdu_linked_append(pdu_chain, pdu);
1701 			pdu = pdu_chain;
1702 		}
1703 	}
1704 
1705 	return 0U;
1706 }
1707 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1708 
1709 static uint8_t ull_adv_sync_ad_add(struct lll_adv_sync *lll_sync,
1710 				   struct pdu_adv *ter_pdu_prev,
1711 				   struct pdu_adv *ter_pdu,
1712 				   const uint8_t *ad, uint8_t ad_len)
1713 {
1714 	uint8_t pdu_ad_max_len = PDU_AC_EXT_AD_DATA_LEN_MAX;
1715 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1716 	uint8_t err;
1717 
1718 	err = ull_adv_sync_duplicate_chain(ter_pdu_prev, ter_pdu);
1719 	if (err) {
1720 		return err;
1721 	}
1722 
1723 	/* Find end of current advertising data */
1724 	while (lll_adv_pdu_linked_next_get(ter_pdu)) {
1725 		ter_pdu = lll_adv_pdu_linked_next_get(ter_pdu);
1726 		ter_pdu_prev = lll_adv_pdu_linked_next_get(ter_pdu_prev);
1727 
1728 		/* Use the full PDU payload for AUX_CHAIN_IND */
1729 		pdu_ad_max_len = PDU_AC_EXT_PAYLOAD_SIZE_MAX;
1730 
1731 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1732 		/* Detect end of current advertising data */
1733 		if (ter_pdu->len < PDU_AC_EXT_PAYLOAD_SIZE_MAX) {
1734 			break;
1735 		}
1736 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1737 	}
1738 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1739 	/* Initialize PDU header */
1740 	ter_pdu->type = ter_pdu_prev->type;
1741 	ter_pdu->rfu = 0U;
1742 	ter_pdu->chan_sel = 0U;
1743 	ter_pdu->tx_addr = 0U;
1744 	ter_pdu->rx_addr = 0U;
1745 	ter_pdu->len = ter_pdu_prev->len;
1746 
1747 	/* Copy PDU payload */
1748 	memcpy(ter_pdu->payload, ter_pdu_prev->payload, ter_pdu_prev->len);
1749 #endif /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1750 
1751 	/* At end of copied chain, append new adv data */
1752 	return ull_adv_sync_append_ad_data(lll_sync, ter_pdu, ad, ad_len, pdu_ad_max_len);
1753 }
1754 
1755 static uint8_t ull_adv_sync_ad_replace(struct lll_adv_sync *lll_sync,
1756 				       struct pdu_adv *ter_pdu_prev,
1757 				       struct pdu_adv *ter_pdu,
1758 				       const uint8_t *ad, uint8_t ad_len)
1759 {
1760 	struct pdu_adv_ext_hdr skip_fields = { 0U };
1761 
1762 	skip_fields.aux_ptr = 1U;
1763 
1764 	/* FIXME - below ignores any configured CTE count */
1765 	if (ter_pdu_prev == ter_pdu) {
1766 		/* Remove adv data and any AuxPtr */
1767 		ter_pdu->len = ter_pdu_prev->adv_ext_ind.ext_hdr_len + 1U;
1768 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1769 		ull_adv_sync_remove_from_header(ter_pdu, &skip_fields, false);
1770 		/* Delete any existing PDU chain */
1771 		if (lll_adv_pdu_linked_next_get(ter_pdu)) {
1772 			lll_adv_pdu_linked_release_all(lll_adv_pdu_linked_next_get(ter_pdu));
1773 			lll_adv_pdu_linked_append(NULL, ter_pdu);
1774 		}
1775 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1776 	} else {
1777 		/* Copy header (only), removing any prior presence of Aux Ptr */
1778 		ull_adv_sync_copy_pdu_header(ter_pdu, ter_pdu_prev, &skip_fields, false);
1779 	}
1780 
1781 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1782 	/* New adv data - update ADI if present */
1783 	if (ter_pdu->adv_ext_ind.ext_hdr_len && ter_pdu->adv_ext_ind.ext_hdr.adi) {
1784 		struct ll_adv_set *adv = HDR_LLL2ULL(lll_sync->adv);
1785 		uint16_t did;
1786 
1787 		/* The DID for a specific SID shall be unique */
1788 		did = sys_cpu_to_le16(ull_adv_aux_did_next_unique_get(adv->sid));
1789 		ull_adv_sync_update_pdu_adi(lll_sync, ter_pdu, did);
1790 	}
1791 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1792 
1793 	/* Set advertising data (without copying any existing adv data) */
1794 	return ull_adv_sync_append_ad_data(lll_sync, ter_pdu, ad, ad_len,
1795 					   PDU_AC_EXT_AD_DATA_LEN_MAX);
1796 }
1797 
1798 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1799 static uint8_t ull_adv_sync_update_adi(struct lll_adv_sync *lll_sync,
1800 				       struct pdu_adv *ter_pdu_prev,
1801 				       struct pdu_adv *ter_pdu)
1802 {
1803 	struct ll_adv_set *adv = HDR_LLL2ULL(lll_sync->adv);
1804 	uint16_t did;
1805 
1806 	/* The DID for a specific SID shall be unique */
1807 	did = sys_cpu_to_le16(ull_adv_aux_did_next_unique_get(adv->sid));
1808 
1809 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1810 	uint8_t err;
1811 
1812 	err = ull_adv_sync_duplicate_chain(ter_pdu_prev, ter_pdu);
1813 	if (err) {
1814 		return err;
1815 	}
1816 
1817 	/* Loop through chain and set new ADI for all */
1818 	while (ter_pdu) {
1819 		ull_adv_sync_update_pdu_adi(lll_sync, ter_pdu, did);
1820 		ter_pdu = lll_adv_pdu_linked_next_get(ter_pdu);
1821 	}
1822 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1823 	/* Initialize PDU header */
1824 	ter_pdu->type = ter_pdu_prev->type;
1825 	ter_pdu->rfu = 0U;
1826 	ter_pdu->chan_sel = 0U;
1827 	ter_pdu->tx_addr = 0U;
1828 	ter_pdu->rx_addr = 0U;
1829 	ter_pdu->len = ter_pdu_prev->len;
1830 
1831 	/* Copy PDU payload */
1832 	memcpy(ter_pdu->payload, ter_pdu_prev->payload, ter_pdu_prev->len);
1833 
1834 	/* Set new ADI */
1835 	ull_adv_sync_update_pdu_adi(lll_sync, ter_pdu, did);
1836 #endif /*  CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK*/
1837 	return 0U;
1838 }
1839 
1840 static uint8_t ull_adv_sync_add_adi(struct lll_adv_sync *lll_sync,
1841 				    struct pdu_adv *pdu_prev,
1842 				    struct pdu_adv *pdu)
1843 {
1844 	struct ll_adv_set *adv = HDR_LLL2ULL(lll_sync->adv);
1845 	struct pdu_adv_ext_hdr add_fields = { 0U };
1846 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1847 	uint8_t ad_overflow[sizeof(struct pdu_adv_adi)*MAX_FRAG_COUNT];
1848 	uint8_t total_overflow_len;
1849 	struct pdu_adv *last_pdu;
1850 	uint8_t overflow_len;
1851 	uint8_t err;
1852 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1853 	uint16_t did;
1854 
1855 	add_fields.adi = 1U;
1856 
1857 	/* The DID for a specific SID shall be unique */
1858 	did = sys_cpu_to_le16(ull_adv_aux_did_next_unique_get(adv->sid));
1859 
1860 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1861 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
1862 	if (err) {
1863 		return err;
1864 	}
1865 
1866 	total_overflow_len = 0U;
1867 	/* Loop through chain and add ADI for all */
1868 	while (pdu) {
1869 		last_pdu = pdu;
1870 
1871 		/* We should always have enough available overflow space to fit an ADI */
1872 		LL_ASSERT(total_overflow_len + sizeof(struct pdu_adv_adi) <= sizeof(ad_overflow));
1873 
1874 		ull_adv_sync_add_to_header(pdu, &add_fields,
1875 					   &ad_overflow[total_overflow_len], &overflow_len);
1876 		total_overflow_len += overflow_len;
1877 		ull_adv_sync_update_pdu_adi(lll_sync, pdu, did);
1878 		pdu = lll_adv_pdu_linked_next_get(pdu);
1879 		if (pdu) {
1880 			uint8_t ad_overflow_tmp[sizeof(struct pdu_adv_adi)*MAX_FRAG_COUNT];
1881 			uint8_t overflow_tmp_len = 0U;
1882 			uint8_t pdu_avail = PDU_AC_EXT_PAYLOAD_SIZE_MAX - pdu->len;
1883 			uint8_t pdu_needed = total_overflow_len;
1884 			uint8_t *dptr;
1885 
1886 			if (!pdu->adv_ext_ind.ext_hdr.adi) {
1887 				pdu_needed += sizeof(struct pdu_adv_adi);
1888 			}
1889 			if (pdu->adv_ext_ind.ext_hdr_len == 0U) {
1890 				/* Make room for flags as well */
1891 				pdu_needed++;
1892 			}
1893 
1894 			if (total_overflow_len > 0U) {
1895 				if (pdu_avail < pdu_needed) {
1896 					/* Make room by removing last part of adv data */
1897 					overflow_tmp_len = pdu_needed - pdu_avail;
1898 					memcpy(ad_overflow_tmp,
1899 					       pdu->payload + (pdu->len - overflow_tmp_len),
1900 					       overflow_tmp_len);
1901 					pdu->len -= overflow_tmp_len;
1902 				}
1903 
1904 				/* Prepend overflow from last PDU */
1905 				dptr = pdu->payload + pdu->adv_ext_ind.ext_hdr_len + 1U;
1906 				memmove(dptr + total_overflow_len, dptr,
1907 					pdu->len - pdu->adv_ext_ind.ext_hdr_len - 1U +
1908 					 total_overflow_len);
1909 				pdu->len += total_overflow_len;
1910 				memcpy(dptr, ad_overflow, total_overflow_len);
1911 
1912 				/* Carry forward overflow from this PDU */
1913 				total_overflow_len = overflow_tmp_len;
1914 				if (overflow_tmp_len) {
1915 					memcpy(ad_overflow, ad_overflow_tmp, overflow_tmp_len);
1916 				}
1917 			}
1918 		}
1919 	}
1920 
1921 	/* Push any remaining overflow on to last PDU */
1922 	ull_adv_sync_append_ad_data(lll_sync, pdu, ad_overflow, total_overflow_len,
1923 				    PDU_AC_EXT_PAYLOAD_SIZE_MAX);
1924 
1925 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1926 
1927 	if (pdu->len > PDU_AC_EXT_PAYLOAD_SIZE_MAX - sizeof(struct pdu_adv_adi)) {
1928 		/* No room for ADI */
1929 		return BT_HCI_ERR_PACKET_TOO_LONG;
1930 	}
1931 
1932 	/* Initialize PDU header */
1933 	pdu->type = pdu_prev->type;
1934 	pdu->rfu = 0U;
1935 	pdu->chan_sel = 0U;
1936 	pdu->tx_addr = 0U;
1937 	pdu->rx_addr = 0U;
1938 	pdu->len = pdu_prev->len;
1939 
1940 	/* Copy PDU payload */
1941 	memcpy(pdu->payload, pdu_prev->payload, pdu_prev->len);
1942 
1943 	/* Add and set new ADI */
1944 	ull_adv_sync_add_to_header(pdu, &add_fields, NULL, NULL);
1945 	ull_adv_sync_update_pdu_adi(lll_sync, pdu, did);
1946 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1947 	return 0U;
1948 }
1949 
1950 static uint8_t ull_adv_sync_remove_adi(struct lll_adv_sync *lll_sync,
1951 				       struct pdu_adv *pdu_prev,
1952 				       struct pdu_adv *pdu)
1953 {
1954 	struct pdu_adv_ext_hdr remove_fields = { 0U };
1955 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1956 	uint8_t err;
1957 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1958 
1959 	remove_fields.adi = 1U;
1960 
1961 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1962 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
1963 	if (err) {
1964 		return err;
1965 	}
1966 
1967 	/* Loop through chain and remove ADI for all */
1968 	while (pdu) {
1969 		ull_adv_sync_remove_from_header(pdu, &remove_fields, false);
1970 		if (pdu->adv_ext_ind.ext_hdr_len && pdu->adv_ext_ind.ext_hdr.aux_ptr) {
1971 			ull_adv_sync_update_aux_ptr(lll_sync, pdu);
1972 		}
1973 		pdu = lll_adv_pdu_linked_next_get(pdu);
1974 	}
1975 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1976 	ull_adv_sync_remove_from_header(pdu, &remove_fields, false);
1977 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1978 
1979 	return 0U;
1980 }
1981 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1982 
1983 uint8_t *ull_adv_sync_get_acad(struct pdu_adv *pdu, uint8_t *acad_len)
1984 {
1985 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
1986 	uint8_t *dptr;
1987 
1988 	/* Skip to ACAD */
1989 	dptr = hdr->ext_hdr.data;
1990 
1991 	/* AdvA and TargetA is RFU for periodic advertising */
1992 
1993 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1994 	if (hdr->ext_hdr.cte_info) {
1995 		dptr += sizeof(struct pdu_cte_info);
1996 	}
1997 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1998 
1999 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
2000 	if (hdr->ext_hdr.adi) {
2001 		dptr += sizeof(struct pdu_adv_adi);
2002 	}
2003 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
2004 
2005 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2006 	if (hdr->ext_hdr.aux_ptr) {
2007 		dptr += sizeof(struct pdu_adv_aux_ptr);
2008 	}
2009 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2010 
2011 	/* SyncInfo is RFU for periodic advertising */
2012 
2013 	if (hdr->ext_hdr.tx_pwr) {
2014 		dptr++;
2015 	}
2016 
2017 	/* ACAD is the remainder of the header, if any left */
2018 	if ((dptr - hdr->ext_hdr_adv_data) < hdr->ext_hdr_len) {
2019 		*acad_len = hdr->ext_hdr_len - (dptr - hdr->ext_hdr_adv_data);
2020 	} else {
2021 		*acad_len = 0U;
2022 	}
2023 
2024 	return dptr;
2025 }
2026 
2027 uint8_t ull_adv_sync_remove_from_acad(struct lll_adv_sync *lll_sync,
2028 				      struct pdu_adv *pdu_prev,
2029 				      struct pdu_adv *pdu,
2030 				      uint8_t ad_type)
2031 {
2032 	uint8_t acad_len;
2033 	uint8_t ad_len;
2034 	uint8_t *acad;
2035 	uint8_t len;
2036 	uint8_t *ad;
2037 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2038 	uint8_t err;
2039 
2040 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
2041 	if (err) {
2042 		return err;
2043 	}
2044 #else
2045 	ull_adv_sync_copy_pdu(pdu_prev, pdu);
2046 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2047 
2048 	acad = ull_adv_sync_get_acad(pdu, &acad_len);
2049 
2050 	if (acad_len == 0U) {
2051 		return 0U;
2052 	}
2053 
2054 	/* Find the relevant entry */
2055 	len = acad_len;
2056 	ad = acad;
2057 	do {
2058 		ad_len = ad[PDU_ADV_DATA_HEADER_LEN_OFFSET];
2059 		if (ad_len && (ad[PDU_ADV_DATA_HEADER_TYPE_OFFSET] == ad_type)) {
2060 			break;
2061 		}
2062 
2063 		ad_len += 1U;
2064 
2065 		LL_ASSERT(ad_len <= len);
2066 
2067 		ad += ad_len;
2068 		len -= ad_len;
2069 	} while (len);
2070 
2071 	if (len == 0U) {
2072 		/* Entry is not present */
2073 		return 0U;
2074 	}
2075 
2076 	/* Remove entry by moving the rest of the PDU content forward */
2077 	ad_len += 1U;
2078 	(void)memmove(ad, ad + ad_len, pdu->len - ((ad + ad_len) - pdu->payload));
2079 
2080 	/* Adjust lengths */
2081 	pdu->len -= ad_len;
2082 	pdu->adv_ext_ind.ext_hdr_len -= ad_len;
2083 
2084 	return 0U;
2085 }
2086 
2087 uint8_t ull_adv_sync_add_to_acad(struct lll_adv_sync *lll_sync,
2088 				 struct pdu_adv *pdu_prev,
2089 				 struct pdu_adv *pdu,
2090 				 const uint8_t *new_ad,
2091 				 uint8_t new_ad_len)
2092 {
2093 	uint8_t ad_len;
2094 	uint8_t delta;
2095 	uint8_t *dptr;
2096 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2097 	uint8_t err;
2098 
2099 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
2100 	if (err) {
2101 		return err;
2102 	}
2103 #else
2104 	ull_adv_sync_copy_pdu(pdu_prev, pdu);
2105 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2106 
2107 	delta = new_ad_len;
2108 	if (pdu->adv_ext_ind.ext_hdr_len == 0U) {
2109 		/* Add one byte for the header flags */
2110 		delta++;
2111 	}
2112 
2113 	if (pdu->len > PDU_AC_EXT_PAYLOAD_SIZE_MAX - delta) {
2114 		return BT_HCI_ERR_PACKET_TOO_LONG;
2115 	}
2116 
2117 	dptr = pdu->payload + pdu->adv_ext_ind.ext_hdr_len + 1U;
2118 
2119 	/* Make room in ACAD by moving any advertising data back */
2120 	ad_len = pdu->len - pdu->adv_ext_ind.ext_hdr_len - 1U;
2121 	if (ad_len) {
2122 		(void)memmove(dptr + delta, dptr, ad_len);
2123 	}
2124 
2125 	if (pdu->adv_ext_ind.ext_hdr_len == 0U) {
2126 		/* Set all extended header flags to 0 */
2127 		*dptr = 0U;
2128 		dptr++;
2129 	}
2130 
2131 	/* Copy in ACAD data */
2132 	memcpy(dptr, new_ad, new_ad_len);
2133 
2134 	/* Adjust lengths */
2135 	pdu->len += delta;
2136 	pdu->adv_ext_ind.ext_hdr_len += delta;
2137 
2138 	return 0U;
2139 }
2140 
2141 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
2142 static void ull_adv_sync_update_pdu_cteinfo(struct lll_adv_sync *lll_sync, struct pdu_adv *pdu,
2143 					    const struct pdu_cte_info *cte_info)
2144 {
2145 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
2146 	uint8_t *dptr;
2147 
2148 	if (hdr->ext_hdr_len == 0U || hdr->ext_hdr.cte_info == 0U) {
2149 		/* No CTEInfo field present, nothing to do */
2150 		return;
2151 	}
2152 
2153 	/* Find CTEInfo in extended header */
2154 	dptr = hdr->ext_hdr.data;
2155 
2156 	/* AdvA and TargetA is RFU for periodic advertising */
2157 
2158 	/* Copy supplied data into extended header */
2159 	memcpy(dptr, (uint8_t *)cte_info, sizeof(struct pdu_cte_info));
2160 }
2161 
2162 uint8_t ull_adv_sync_add_cteinfo(struct lll_adv_sync *lll_sync,
2163 				 struct pdu_adv *pdu_prev,
2164 				 struct pdu_adv *pdu,
2165 				 const struct pdu_cte_info *cte_info,
2166 				 uint8_t cte_count)
2167 {
2168 	struct pdu_adv_ext_hdr add_fields = { 0U };
2169 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2170 	uint8_t ad_overflow[sizeof(struct pdu_cte_info)*MAX_FRAG_COUNT];
2171 	uint8_t total_overflow_len;
2172 	struct pdu_adv *last_pdu = pdu;
2173 	uint8_t overflow_len;
2174 	uint8_t err;
2175 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2176 
2177 	add_fields.cte_info = 1U;
2178 
2179 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2180 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
2181 	if (err) {
2182 		return err;
2183 	}
2184 
2185 	total_overflow_len = 0U;
2186 	/* Loop through chain and add CTEInfo for PDUs up to cte_count */
2187 	while (pdu && cte_count) {
2188 		last_pdu = pdu;
2189 
2190 		/* We should always have enough available overflow space to fit CTEInfo */
2191 		LL_ASSERT(total_overflow_len + sizeof(struct pdu_cte_info) <= sizeof(ad_overflow));
2192 
2193 		ull_adv_sync_add_to_header(pdu, &add_fields,
2194 					   &ad_overflow[total_overflow_len], &overflow_len);
2195 		total_overflow_len += overflow_len;
2196 		ull_adv_sync_update_pdu_cteinfo(lll_sync, pdu, cte_info);
2197 		cte_count--;
2198 
2199 		/* Update AuxPtr if present */
2200 		ull_adv_sync_update_aux_ptr(lll_sync, pdu);
2201 
2202 		pdu = lll_adv_pdu_linked_next_get(pdu);
2203 		if (pdu) {
2204 			uint8_t ad_overflow_tmp[sizeof(struct pdu_cte_info)*MAX_FRAG_COUNT];
2205 			uint8_t overflow_tmp_len = 0U;
2206 			uint8_t pdu_avail = PDU_AC_EXT_PAYLOAD_SIZE_MAX - pdu->len;
2207 			uint8_t pdu_needed = total_overflow_len;
2208 			uint8_t *dptr;
2209 
2210 			if (!pdu->adv_ext_ind.ext_hdr.cte_info) {
2211 				pdu_needed += sizeof(struct pdu_cte_info);
2212 			}
2213 			if (pdu->adv_ext_ind.ext_hdr_len == 0U) {
2214 				/* Make room for flags as well */
2215 				pdu_needed++;
2216 			}
2217 
2218 			if (total_overflow_len > 0U) {
2219 				if (pdu_avail < pdu_needed) {
2220 					/* Make room by removing last part of adv data */
2221 					overflow_tmp_len = pdu_needed - pdu_avail;
2222 					memcpy(ad_overflow_tmp,
2223 					       pdu->payload + (pdu->len - overflow_tmp_len),
2224 					       overflow_tmp_len);
2225 					pdu->len -= overflow_tmp_len;
2226 				}
2227 
2228 				/* Prepend overflow from last PDU */
2229 				dptr = pdu->payload + pdu->adv_ext_ind.ext_hdr_len + 1U;
2230 				memmove(dptr + total_overflow_len, dptr,
2231 					pdu->len - pdu->adv_ext_ind.ext_hdr_len - 1U +
2232 					 total_overflow_len);
2233 				pdu->len += total_overflow_len;
2234 				memcpy(dptr, ad_overflow, total_overflow_len);
2235 
2236 				/* Carry forward overflow from this PDU */
2237 				total_overflow_len = overflow_tmp_len;
2238 				if (overflow_tmp_len) {
2239 					memcpy(ad_overflow, ad_overflow_tmp, overflow_tmp_len);
2240 				}
2241 			}
2242 
2243 		}
2244 	}
2245 
2246 	pdu = last_pdu;
2247 
2248 	/* Push any remaining overflow on to last PDU */
2249 	ull_adv_sync_append_ad_data(lll_sync, pdu, ad_overflow, total_overflow_len,
2250 				    PDU_AC_EXT_PAYLOAD_SIZE_MAX);
2251 
2252 #if (CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1)
2253 	/* Add PDUs up to cte_count if needed */
2254 	while (cte_count) {
2255 		struct pdu_adv_ext_hdr skip_fields = { 0U };
2256 		struct pdu_adv *pdu_chain;
2257 
2258 		skip_fields.adi = 1U;
2259 		skip_fields.aux_ptr = 1U;
2260 		skip_fields.tx_pwr = 1U;
2261 
2262 		/* Get a new chain PDU */
2263 		pdu_chain = lll_adv_pdu_alloc_pdu_adv();
2264 		if (!pdu_chain) {
2265 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
2266 		}
2267 
2268 		/* Link the chain PDU to parent PDU */
2269 		lll_adv_pdu_linked_append(pdu_chain, pdu);
2270 
2271 		/* Copy header to new PDU, skipping all fields except CTEInfo */
2272 		ull_adv_sync_copy_pdu_header(pdu_chain, pdu, &skip_fields, true);
2273 
2274 		/* Add and set aux_ptr to existing PDU */
2275 		ull_adv_sync_add_aux_ptr(pdu, ad_overflow, &overflow_len);
2276 		ull_adv_sync_update_aux_ptr(lll_sync, pdu);
2277 
2278 		if (overflow_len) {
2279 			ull_adv_sync_append_ad_data(lll_sync, pdu_chain, ad_overflow, overflow_len,
2280 				    PDU_AC_EXT_PAYLOAD_SIZE_MAX);
2281 		}
2282 
2283 		pdu = pdu_chain;
2284 		cte_count--;
2285 	}
2286 #endif /* CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 */
2287 
2288 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2289 
2290 	if (pdu->len > PDU_AC_EXT_PAYLOAD_SIZE_MAX - sizeof(struct pdu_cte_info)) {
2291 		/* No room for CTEInfo */
2292 		return BT_HCI_ERR_PACKET_TOO_LONG;
2293 	}
2294 
2295 	/* Initialize PDU header */
2296 	pdu->type = pdu_prev->type;
2297 	pdu->rfu = 0U;
2298 	pdu->chan_sel = 0U;
2299 	pdu->tx_addr = 0U;
2300 	pdu->rx_addr = 0U;
2301 	pdu->len = pdu_prev->len;
2302 
2303 	/* Copy PDU payload */
2304 	memcpy(pdu->payload, pdu_prev->payload, pdu_prev->len);
2305 
2306 	/* Add and set CTEInfo */
2307 	ull_adv_sync_add_to_header(pdu, &add_fields, NULL, NULL);
2308 	ull_adv_sync_update_pdu_cteinfo(lll_sync, pdu, cte_info);
2309 #endif /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2310 	return 0U;
2311 }
2312 
2313 uint8_t ull_adv_sync_remove_cteinfo(struct lll_adv_sync *lll_sync,
2314 				    struct pdu_adv *pdu_prev,
2315 				    struct pdu_adv *pdu)
2316 {
2317 	struct pdu_adv_ext_hdr remove_fields = { 0U };
2318 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2319 	uint8_t err;
2320 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2321 
2322 	remove_fields.cte_info = 1U;
2323 
2324 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2325 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
2326 	if (err) {
2327 		return err;
2328 	}
2329 
2330 	/* Loop through chain and remove CTEInfo for all */
2331 	while (pdu) {
2332 		struct pdu_adv *pdu_chain;
2333 
2334 		ull_adv_sync_remove_from_header(pdu, &remove_fields, false);
2335 
2336 		if (pdu->adv_ext_ind.ext_hdr_len && pdu->adv_ext_ind.ext_hdr.aux_ptr) {
2337 			ull_adv_sync_update_aux_ptr(lll_sync, pdu);
2338 		}
2339 
2340 		pdu_chain = lll_adv_pdu_linked_next_get(pdu);
2341 #if (CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1)
2342 		/* If the next PDU in the chain contains no adv data, any remaining PDUs
2343 		 *  in the chain are only present for CTE purposes
2344 		 */
2345 		if (pdu_chain && pdu_chain->len == pdu_chain->adv_ext_ind.ext_hdr_len + 1U) {
2346 			/* Remove AuxPtr and clean up remaining PDUs in chain */
2347 			remove_fields.aux_ptr = 1U;
2348 			ull_adv_sync_remove_from_header(pdu, &remove_fields, false);
2349 			lll_adv_pdu_linked_release_all(pdu_chain);
2350 			lll_adv_pdu_linked_append(NULL, pdu);
2351 			pdu_chain = NULL;
2352 		}
2353 #endif /* CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 */
2354 		pdu = pdu_chain;
2355 	}
2356 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2357 	ull_adv_sync_remove_from_header(pdu, &remove_fields, false);
2358 #endif /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2359 
2360 	return 0U;
2361 }
2362 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
2363 
2364 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
2365 /* @brief Set or clear fields in extended advertising header and store
2366  *        extra_data if requested.
2367  *
2368  * @param[in]  extra_data_prev  Pointer to previous content of extra_data.
2369  * @param[in]  hdr_add_fields   Flag with information which fields add.
2370  * @param[in]  hdr_rem_fields   Flag with information which fields remove.
2371  * @param[in]  data             Pointer to data to be stored in extra_data.
2372  *                              Content depends on the data depends on
2373  *                              @p hdr_add_fields.
2374  *
2375  * @Note
2376  * @p hdr_data content depends on the flag provided by @p hdr_add_fields:
2377  * - ULL_ADV_PDU_HDR_FIELD_CTE_INFO:
2378  *   # @p hdr_data points to single byte with CTEInfo field
2379  *
2380  * @return Zero in case of success, other value in case of failure.
2381  * @p data depends on the flag provided by @p hdr_add_fields.
2382  *
2383  * @return Zero in case of success, other value in case of failure.
2384  */
2385 void ull_adv_sync_extra_data_set_clear(void *extra_data_prev,
2386 				       void *extra_data_new,
2387 				       uint16_t hdr_add_fields,
2388 				       uint16_t hdr_rem_fields,
2389 				       void *data)
2390 {
2391 	/* Currently only CTE enable requires extra_data. Due to that fact
2392 	 * CTE additional data are just copied to extra_data memory.
2393 	 */
2394 	if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) {
2395 		(void)memcpy(extra_data_new, data, sizeof(struct lll_df_adv_cfg));
2396 	} else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) ||
2397 		   extra_data_prev) {
2398 		(void)memmove(extra_data_new, extra_data_prev,
2399 			      sizeof(struct lll_df_adv_cfg));
2400 	}
2401 }
2402 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
2403 
2404 static int init_reset(void)
2405 {
2406 	/* Initialize adv sync pool. */
2407 	mem_init(ll_adv_sync_pool, sizeof(struct ll_adv_sync_set),
2408 		 sizeof(ll_adv_sync_pool) / sizeof(struct ll_adv_sync_set),
2409 		 &adv_sync_free);
2410 
2411 	return 0;
2412 }
2413 
2414 static uint8_t adv_type_check(struct ll_adv_set *adv)
2415 {
2416 	struct pdu_adv_com_ext_adv *pri_com_hdr;
2417 	struct pdu_adv_ext_hdr *pri_hdr;
2418 	struct pdu_adv *pri_pdu;
2419 
2420 	pri_pdu = lll_adv_data_latest_peek(&adv->lll);
2421 	if (pri_pdu->type != PDU_ADV_TYPE_EXT_IND) {
2422 		return BT_HCI_ERR_INVALID_PARAM;
2423 	}
2424 
2425 	pri_com_hdr = (void *)&pri_pdu->adv_ext_ind;
2426 	if (pri_com_hdr->adv_mode != 0U) {
2427 		return BT_HCI_ERR_INVALID_PARAM;
2428 	}
2429 
2430 	pri_hdr = (void *)pri_com_hdr->ext_hdr_adv_data;
2431 	if (pri_hdr->aux_ptr) {
2432 		struct pdu_adv_com_ext_adv *sec_com_hdr;
2433 		struct pdu_adv_ext_hdr *sec_hdr;
2434 		struct pdu_adv *sec_pdu;
2435 
2436 		sec_pdu = lll_adv_aux_data_latest_peek(adv->lll.aux);
2437 		sec_com_hdr = (void *)&sec_pdu->adv_ext_ind;
2438 		sec_hdr = (void *)sec_com_hdr->ext_hdr_adv_data;
2439 		if (!pri_hdr->adv_addr && !sec_hdr->adv_addr) {
2440 			return BT_HCI_ERR_INVALID_PARAM;
2441 		}
2442 	} else if (!pri_hdr->adv_addr) {
2443 		return BT_HCI_ERR_INVALID_PARAM;
2444 	}
2445 
2446 	return 0;
2447 }
2448 
2449 static inline struct ll_adv_sync_set *sync_acquire(void)
2450 {
2451 	return mem_acquire(&adv_sync_free);
2452 }
2453 
2454 static inline void sync_release(struct ll_adv_sync_set *sync)
2455 {
2456 	mem_release(sync, &adv_sync_free);
2457 }
2458 
2459 static inline uint16_t sync_handle_get(const struct ll_adv_sync_set *sync)
2460 {
2461 	return mem_index_get(sync, ll_adv_sync_pool,
2462 			     sizeof(struct ll_adv_sync_set));
2463 }
2464 
2465 static uint32_t sync_time_get(const struct ll_adv_sync_set *sync,
2466 			      const struct pdu_adv *pdu)
2467 {
2468 	uint8_t len;
2469 
2470 	/* Calculate the PDU Tx Time and hence the radio event length,
2471 	 * Always use maximum length for common extended header format so that
2472 	 * ACAD could be update when periodic advertising is active and the
2473 	 * time reservation need not be updated every time avoiding overlapping
2474 	 * with other active states/roles.
2475 	 */
2476 	len = pdu->len - pdu->adv_ext_ind.ext_hdr_len -
2477 	      PDU_AC_EXT_HEADER_SIZE_MIN + PDU_AC_EXT_HEADER_SIZE_MAX;
2478 
2479 	return ull_adv_sync_time_get(sync, len);
2480 }
2481 
2482 static uint8_t sync_stop(struct ll_adv_sync_set *sync)
2483 {
2484 	uint8_t sync_handle;
2485 	int err;
2486 
2487 	sync_handle = sync_handle_get(sync);
2488 
2489 	err = ull_ticker_stop_with_mark(TICKER_ID_ADV_SYNC_BASE + sync_handle,
2490 					sync, &sync->lll);
2491 	LL_ASSERT_INFO2(err == 0 || err == -EALREADY, sync_handle, err);
2492 	if (err) {
2493 		return BT_HCI_ERR_CMD_DISALLOWED;
2494 	}
2495 
2496 	return 0;
2497 }
2498 
2499 static inline uint8_t sync_remove(struct ll_adv_sync_set *sync,
2500 				  struct ll_adv_set *adv, uint8_t enable)
2501 {
2502 	uint8_t pri_idx;
2503 	uint8_t sec_idx;
2504 	uint8_t err;
2505 
2506 	/* Remove sync_info from auxiliary PDU */
2507 	err = ull_adv_aux_hdr_set_clear(adv, 0U,
2508 					ULL_ADV_PDU_HDR_FIELD_SYNC_INFO, NULL,
2509 					&pri_idx, &sec_idx);
2510 	if (err) {
2511 		return err;
2512 	}
2513 
2514 	lll_adv_aux_data_enqueue(adv->lll.aux, sec_idx);
2515 	lll_adv_data_enqueue(&adv->lll, pri_idx);
2516 
2517 	if (sync->is_started) {
2518 		/* TODO: we removed sync info, but if sync_stop() fails, what do
2519 		 * we do?
2520 		 */
2521 		err = sync_stop(sync);
2522 		if (err) {
2523 			return err;
2524 		}
2525 
2526 		sync->is_started = 0U;
2527 
2528 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2529 		if (adv->lll.aux) {
2530 			/* notify the auxiliary set */
2531 			ull_adv_sync_started_stopped(HDR_LLL2ULL(adv->lll.aux));
2532 		}
2533 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2534 	}
2535 
2536 	if (!enable) {
2537 		sync->is_enabled = 0U;
2538 	}
2539 
2540 	return 0U;
2541 }
2542 
2543 static uint8_t sync_chm_update(uint8_t handle)
2544 {
2545 	struct pdu_adv_sync_chm_upd_ind *chm_upd_ind;
2546 	uint8_t ad[sizeof(*chm_upd_ind) + 2U];
2547 	struct lll_adv_sync *lll_sync;
2548 	struct pdu_adv *pdu_prev;
2549 	struct ll_adv_set *adv;
2550 	struct pdu_adv *pdu;
2551 	uint16_t instant;
2552 	uint8_t chm_last;
2553 	uint8_t ter_idx;
2554 	uint8_t err;
2555 
2556 	/* Check for valid advertising instance */
2557 	adv = ull_adv_is_created_get(handle);
2558 	if (!adv) {
2559 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
2560 	}
2561 
2562 	/* Check for valid periodic advertising */
2563 	lll_sync = adv->lll.sync;
2564 	if (!lll_sync) {
2565 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
2566 	}
2567 
2568 	/* Fail if already in progress */
2569 	if (lll_sync->chm_last != lll_sync->chm_first) {
2570 		return BT_HCI_ERR_CMD_DISALLOWED;
2571 	}
2572 
2573 	/* Allocate next Sync PDU */
2574 	err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
2575 				     &pdu_prev, &pdu, NULL, NULL, &ter_idx);
2576 	if (err) {
2577 		return err;
2578 	}
2579 
2580 	/* Populate the AD data length and opcode */
2581 	ad[PDU_ADV_DATA_HEADER_LEN_OFFSET] = sizeof(*chm_upd_ind) + 1U;
2582 	ad[PDU_ADV_DATA_HEADER_TYPE_OFFSET] = PDU_ADV_DATA_TYPE_CHANNEL_MAP_UPDATE_IND;
2583 
2584 	/* Populate the Channel Map Indication structure */
2585 	chm_upd_ind = (void *)&ad[PDU_ADV_DATA_HEADER_DATA_OFFSET];
2586 	(void)ull_chan_map_get(chm_upd_ind->chm);
2587 	instant = lll_sync->event_counter + 6U;
2588 	chm_upd_ind->instant = sys_cpu_to_le16(instant);
2589 
2590 	/* Try to add channel map update indication to ACAD */
2591 	err = ull_adv_sync_add_to_acad(lll_sync, pdu_prev, pdu, ad, sizeof(*chm_upd_ind) + 2U);
2592 	if (err) {
2593 		return err;
2594 	}
2595 
2596 	/* Update the LLL to reflect the Channel Map and Instant to use */
2597 	chm_last = lll_sync->chm_last + 1U;
2598 	if (chm_last == DOUBLE_BUFFER_SIZE) {
2599 		chm_last = 0U;
2600 	}
2601 	lll_sync->chm[chm_last].data_chan_count =
2602 		ull_chan_map_get(lll_sync->chm[chm_last].data_chan_map);
2603 	lll_sync->chm_instant = instant;
2604 
2605 	/* Commit the Channel Map Indication in the ACAD field of Periodic
2606 	 * Advertising
2607 	 */
2608 	lll_adv_sync_data_enqueue(lll_sync, ter_idx);
2609 
2610 	/* Initiate the Channel Map Indication */
2611 	lll_sync->chm_last = chm_last;
2612 
2613 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2614 	struct ll_adv_sync_set *sync = HDR_LLL2ULL(lll_sync);
2615 
2616 	if (!sync->is_started) {
2617 		/* Sync not started yet, apply new channel map now */
2618 		lll_sync->chm_first = lll_sync->chm_last;
2619 	}
2620 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2621 
2622 	return 0;
2623 }
2624 
2625 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2626 void ull_adv_sync_lll_syncinfo_fill(struct pdu_adv *pdu, struct lll_adv_aux *lll_aux)
2627 {
2628 	struct lll_adv_sync *lll_sync;
2629 	struct pdu_adv_sync_info *si;
2630 	uint8_t chm_first;
2631 
2632 	lll_sync = lll_aux->adv->sync;
2633 
2634 	si = sync_info_get(pdu);
2635 	sync_info_offset_fill(si, lll_sync->us_adv_sync_pdu_offset);
2636 	si->evt_cntr = lll_sync->event_counter + lll_sync->latency_prepare +
2637 		       lll_sync->sync_lazy;
2638 
2639 	/* Fill the correct channel map to use if at or past the instant */
2640 	if (lll_sync->chm_first != lll_sync->chm_last) {
2641 		uint16_t instant_latency;
2642 
2643 		instant_latency = (si->evt_cntr - lll_sync->chm_instant) &
2644 				  EVENT_INSTANT_MAX;
2645 		if (instant_latency <= EVENT_INSTANT_LATENCY_MAX) {
2646 			chm_first = lll_sync->chm_last;
2647 		} else {
2648 			chm_first = lll_sync->chm_first;
2649 		}
2650 	} else {
2651 		chm_first = lll_sync->chm_first;
2652 	}
2653 	(void)memcpy(si->sca_chm, lll_sync->chm[chm_first].data_chan_map,
2654 		     sizeof(si->sca_chm));
2655 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] &=
2656 		~PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK;
2657 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] |=
2658 		((lll_clock_sca_local_get() <<
2659 		  PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS) &
2660 		 PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK);
2661 }
2662 
2663 static void sync_info_offset_fill(struct pdu_adv_sync_info *si, uint32_t offs)
2664 {
2665 	uint8_t offs_adjust = 0U;
2666 
2667 	if (offs >= OFFS_ADJUST_US) {
2668 		offs -= OFFS_ADJUST_US;
2669 		offs_adjust = 1U;
2670 	}
2671 
2672 	offs = offs / OFFS_UNIT_30_US;
2673 	if (!!(offs >> OFFS_UNIT_BITS)) {
2674 		PDU_ADV_SYNC_INFO_OFFS_SET(si, offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US),
2675 					   OFFS_UNIT_VALUE_300_US, offs_adjust);
2676 	} else {
2677 		PDU_ADV_SYNC_INFO_OFFS_SET(si, offs, OFFS_UNIT_VALUE_30_US, offs_adjust);
2678 	}
2679 }
2680 
2681 #else /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2682 static void mfy_sync_offset_get(void *param)
2683 {
2684 	struct ll_adv_set *adv = param;
2685 	struct lll_adv_sync *lll_sync;
2686 	struct ll_adv_sync_set *sync;
2687 	struct pdu_adv_sync_info *si;
2688 	uint32_t sync_remainder_us;
2689 	uint32_t aux_remainder_us;
2690 	uint32_t ticks_to_expire;
2691 	uint32_t ticks_current;
2692 	struct pdu_adv *pdu;
2693 	uint32_t remainder;
2694 	uint8_t chm_first;
2695 	uint8_t ticker_id;
2696 	uint16_t lazy;
2697 	uint8_t retry;
2698 	uint8_t id;
2699 
2700 	lll_sync = adv->lll.sync;
2701 	sync = HDR_LLL2ULL(lll_sync);
2702 	ticker_id = TICKER_ID_ADV_SYNC_BASE + sync_handle_get(sync);
2703 
2704 	id = TICKER_NULL;
2705 	ticks_to_expire = 0U;
2706 	ticks_current = 0U;
2707 	retry = 4U;
2708 	do {
2709 		uint32_t volatile ret_cb;
2710 		uint32_t ticks_previous;
2711 		uint32_t ret;
2712 		bool success;
2713 
2714 		ticks_previous = ticks_current;
2715 
2716 		ret_cb = TICKER_STATUS_BUSY;
2717 		ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR,
2718 					       TICKER_USER_ID_ULL_LOW,
2719 					       &id, &ticks_current,
2720 					       &ticks_to_expire, &remainder,
2721 					       &lazy, NULL, NULL,
2722 					       ticker_op_cb, (void *)&ret_cb);
2723 		if (ret == TICKER_STATUS_BUSY) {
2724 			while (ret_cb == TICKER_STATUS_BUSY) {
2725 				ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
2726 						 TICKER_USER_ID_ULL_LOW);
2727 			}
2728 		}
2729 
2730 		success = (ret_cb == TICKER_STATUS_SUCCESS);
2731 		LL_ASSERT(success);
2732 
2733 		LL_ASSERT((ticks_current == ticks_previous) || retry--);
2734 
2735 		LL_ASSERT(id != TICKER_NULL);
2736 	} while (id != ticker_id);
2737 
2738 	/* Reduced a tick for negative remainder and return positive remainder
2739 	 * value.
2740 	 */
2741 	hal_ticker_remove_jitter(&ticks_to_expire, &remainder);
2742 	sync_remainder_us = remainder;
2743 
2744 	/* Add a tick for negative remainder and return positive remainder
2745 	 * value.
2746 	 */
2747 	remainder = sync->aux_remainder;
2748 	hal_ticker_add_jitter(&ticks_to_expire, &remainder);
2749 	aux_remainder_us = remainder;
2750 
2751 	pdu = lll_adv_aux_data_latest_peek(adv->lll.aux);
2752 	si = sync_info_get(pdu);
2753 	sync_info_offset_fill(si, ticks_to_expire, sync_remainder_us,
2754 			      aux_remainder_us);
2755 	si->evt_cntr = lll_sync->event_counter + lll_sync->latency_prepare +
2756 		       lazy;
2757 
2758 	/* Fill the correct channel map to use if at or past the instant */
2759 	if (lll_sync->chm_first != lll_sync->chm_last) {
2760 		uint16_t instant_latency;
2761 
2762 		instant_latency = (si->evt_cntr - lll_sync->chm_instant) &
2763 				  EVENT_INSTANT_MAX;
2764 		if (instant_latency <= EVENT_INSTANT_LATENCY_MAX) {
2765 			chm_first = lll_sync->chm_last;
2766 		} else {
2767 			chm_first = lll_sync->chm_first;
2768 		}
2769 	} else {
2770 		chm_first = lll_sync->chm_first;
2771 	}
2772 	(void)memcpy(si->sca_chm, lll_sync->chm[chm_first].data_chan_map,
2773 		     sizeof(si->sca_chm));
2774 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] &=
2775 		~PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK;
2776 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] |=
2777 		((lll_clock_sca_local_get() <<
2778 		  PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS) &
2779 		 PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK);
2780 }
2781 
2782 static void sync_info_offset_fill(struct pdu_adv_sync_info *si,
2783 				  uint32_t ticks_offset,
2784 				  uint32_t remainder_us,
2785 				  uint32_t start_us)
2786 {
2787 	uint8_t offs_adjust = 0U;
2788 	uint32_t offs;
2789 
2790 	offs = HAL_TICKER_TICKS_TO_US(ticks_offset) + remainder_us - start_us;
2791 
2792 	if (offs >= OFFS_ADJUST_US) {
2793 		offs -= OFFS_ADJUST_US;
2794 		offs_adjust = 1U;
2795 	}
2796 
2797 	offs = offs / OFFS_UNIT_30_US;
2798 	if (!!(offs >> OFFS_UNIT_BITS)) {
2799 		PDU_ADV_SYNC_INFO_OFFS_SET(si, offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US),
2800 					   OFFS_UNIT_VALUE_300_US, offs_adjust);
2801 	} else {
2802 		PDU_ADV_SYNC_INFO_OFFS_SET(si, offs, OFFS_UNIT_VALUE_30_US, offs_adjust);
2803 	}
2804 }
2805 
2806 static void ticker_op_cb(uint32_t status, void *param)
2807 {
2808 	*((uint32_t volatile *)param) = status;
2809 }
2810 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2811 
2812 static struct pdu_adv_sync_info *sync_info_get(struct pdu_adv *pdu)
2813 {
2814 	struct pdu_adv_com_ext_adv *p;
2815 	struct pdu_adv_ext_hdr *h;
2816 	uint8_t *ptr;
2817 
2818 	p = (void *)&pdu->adv_ext_ind;
2819 	h = (void *)p->ext_hdr_adv_data;
2820 	ptr = h->data;
2821 
2822 	/* traverse through adv_addr, if present */
2823 	if (h->adv_addr) {
2824 		ptr += BDADDR_SIZE;
2825 	}
2826 
2827 	/* traverse through tgt_addr, if present */
2828 	if (h->tgt_addr) {
2829 		ptr += BDADDR_SIZE;
2830 	}
2831 
2832 	/* No CTEInfo flag in primary and secondary channel PDU */
2833 
2834 	/* traverse through adi, if present */
2835 	if (h->adi) {
2836 		ptr += sizeof(struct pdu_adv_adi);
2837 	}
2838 
2839 	/* traverse through aux ptr, if present */
2840 	if (h->aux_ptr) {
2841 		ptr += sizeof(struct pdu_adv_aux_ptr);
2842 	}
2843 
2844 	/* return pointer offset to sync_info */
2845 	return (void *)ptr;
2846 }
2847 
2848 static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
2849 		      uint32_t remainder, uint16_t lazy, uint8_t force,
2850 		      void *param)
2851 {
2852 	static memq_link_t link;
2853 	static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_sync_prepare};
2854 	static struct lll_prepare_param p;
2855 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2856 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2857 	struct ticker_ext_context *context = param;
2858 	struct ll_adv_sync_set *sync = context->context;
2859 #else /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2860 	struct ll_adv_sync_set *sync = param;
2861 #endif /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2862 	struct lll_adv_sync *lll;
2863 	uint32_t ret;
2864 	uint8_t ref;
2865 
2866 	DEBUG_RADIO_PREPARE_A(1);
2867 
2868 	lll = &sync->lll;
2869 
2870 	/* Increment prepare reference count */
2871 	ref = ull_ref_inc(&sync->ull);
2872 	LL_ASSERT(ref);
2873 
2874 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2875 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2876 	if (lll->iso) {
2877 		struct lll_adv_iso *lll_iso = lll->iso;
2878 
2879 		LL_ASSERT(context->other_expire_info);
2880 
2881 		/* Check: No need for remainder in this case? */
2882 		lll_iso->ticks_sync_pdu_offset = context->other_expire_info->ticks_to_expire;
2883 		lll_iso->iso_lazy = context->other_expire_info->lazy;
2884 	}
2885 #endif /* CONFIG_BT_CTLR_ADV_ISO && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2886 
2887 	/* Append timing parameters */
2888 	p.ticks_at_expire = ticks_at_expire;
2889 	p.remainder = remainder;
2890 	p.lazy = lazy;
2891 	p.force = force;
2892 	p.param = lll;
2893 	mfy.param = &p;
2894 
2895 	/* Kick LLL prepare */
2896 	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
2897 			     TICKER_USER_ID_LLL, 0, &mfy);
2898 	LL_ASSERT(!ret);
2899 
2900 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2901 	!defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2902 	if (lll->iso) {
2903 		ull_adv_iso_offset_get(sync);
2904 	}
2905 #endif /* CONFIG_BT_CTLR_ADV_ISO && !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2906 
2907 	DEBUG_RADIO_PREPARE_A(1);
2908 }
2909 
2910 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2911 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2912 static void ticker_update_op_cb(uint32_t status, void *param)
2913 {
2914 	LL_ASSERT(status == TICKER_STATUS_SUCCESS ||
2915 		  param == ull_disable_mark_get());
2916 }
2917 #endif /* !CONFIG_BT_CTLR_ADV_ISO && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2918