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_CMD_DISALLOWED;
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 	sync->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
808 
809 	ticks_slot_offset = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
810 	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
811 		ticks_slot_overhead = ticks_slot_offset;
812 	} else {
813 		ticks_slot_overhead = 0U;
814 	}
815 
816 	return ticks_slot_overhead;
817 }
818 
ull_adv_sync_start(struct ll_adv_set * adv,struct ll_adv_sync_set * sync,uint32_t ticks_anchor,uint32_t ticks_slot_overhead)819 uint32_t ull_adv_sync_start(struct ll_adv_set *adv,
820 			    struct ll_adv_sync_set *sync,
821 			    uint32_t ticks_anchor,
822 			    uint32_t ticks_slot_overhead)
823 {
824 	uint32_t volatile ret_cb;
825 	uint32_t interval_us;
826 	uint8_t sync_handle;
827 	uint32_t ret;
828 
829 	interval_us = (uint32_t)sync->interval * PERIODIC_INT_UNIT_US;
830 
831 	sync_handle = sync_handle_get(sync);
832 
833 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
834 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
835 	if (sync->lll.iso) {
836 		ll_adv_sync_ticker_ext[sync_handle].expire_info_id =
837 			TICKER_ID_ADV_ISO_BASE + sync->lll.iso->handle;
838 	} else {
839 		ll_adv_sync_ticker_ext[sync_handle].expire_info_id = TICKER_NULL;
840 	}
841 
842 	ll_adv_sync_ticker_ext[sync_handle].ext_timeout_func = ticker_cb;
843 
844 	ret_cb = TICKER_STATUS_BUSY;
845 	ret = ticker_start_ext(
846 #else /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
847 
848 	ret_cb = TICKER_STATUS_BUSY;
849 	ret = ticker_start(
850 #endif /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
851 			   TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
852 			   (TICKER_ID_ADV_SYNC_BASE + sync_handle),
853 			   ticks_anchor, 0U,
854 			   HAL_TICKER_US_TO_TICKS(interval_us),
855 			   HAL_TICKER_REMAINDER(interval_us), TICKER_NULL_LAZY,
856 			   (sync->ull.ticks_slot + ticks_slot_overhead),
857 			   ticker_cb, sync,
858 			   ull_ticker_status_give, (void *)&ret_cb
859 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
860 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
861 			   ,
862 			   &ll_adv_sync_ticker_ext[sync_handle]
863 #endif /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
864 			   );
865 	ret = ull_ticker_status_take(ret, &ret_cb);
866 
867 	return ret;
868 }
869 
ull_adv_sync_time_update(struct ll_adv_sync_set * sync,struct pdu_adv * pdu)870 uint8_t ull_adv_sync_time_update(struct ll_adv_sync_set *sync,
871 				 struct pdu_adv *pdu)
872 {
873 	uint32_t time_ticks;
874 	uint32_t time_us;
875 
876 	time_us = sync_time_get(sync, pdu);
877 	time_ticks = HAL_TICKER_US_TO_TICKS(time_us);
878 
879 #if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING)
880 	uint32_t volatile ret_cb;
881 	uint32_t ticks_minus;
882 	uint32_t ticks_plus;
883 	uint32_t ret;
884 
885 	if (sync->ull.ticks_slot > time_ticks) {
886 		ticks_minus = sync->ull.ticks_slot - time_ticks;
887 		ticks_plus = 0U;
888 	} else if (sync->ull.ticks_slot < time_ticks) {
889 		ticks_minus = 0U;
890 		ticks_plus = time_ticks - sync->ull.ticks_slot;
891 	} else {
892 		return BT_HCI_ERR_SUCCESS;
893 	}
894 
895 	ret_cb = TICKER_STATUS_BUSY;
896 	ret = ticker_update(TICKER_INSTANCE_ID_CTLR,
897 			    TICKER_USER_ID_THREAD,
898 			    (TICKER_ID_ADV_SYNC_BASE + sync_handle_get(sync)),
899 			    0, 0, ticks_plus, ticks_minus, 0, 0,
900 			    ull_ticker_status_give, (void *)&ret_cb);
901 	ret = ull_ticker_status_take(ret, &ret_cb);
902 	if (ret != TICKER_STATUS_SUCCESS) {
903 		return BT_HCI_ERR_CMD_DISALLOWED;
904 	}
905 #endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */
906 
907 	sync->ull.ticks_slot = time_ticks;
908 
909 	return BT_HCI_ERR_SUCCESS;
910 }
911 
ull_adv_sync_chm_update(void)912 uint8_t ull_adv_sync_chm_update(void)
913 {
914 	uint8_t handle;
915 
916 	handle = CONFIG_BT_CTLR_ADV_SYNC_SET;
917 	while (handle--) {
918 		(void)sync_chm_update(handle);
919 	}
920 
921 	/* TODO: Should failure due to Channel Map Update being already in
922 	 *       progress be returned to caller?
923 	 */
924 	return 0;
925 }
926 
ull_adv_sync_chm_complete(struct node_rx_pdu * rx)927 void ull_adv_sync_chm_complete(struct node_rx_pdu *rx)
928 {
929 	struct lll_adv_sync *lll_sync;
930 	struct pdu_adv *pdu_prev;
931 	struct ll_adv_set *adv;
932 	struct pdu_adv *pdu;
933 	uint8_t ter_idx;
934 	uint8_t err;
935 
936 	/* Allocate next Sync PDU */
937 	pdu_prev = NULL;
938 	pdu = NULL;
939 	lll_sync = rx->rx_ftr.param;
940 	adv = HDR_LLL2ULL(lll_sync->adv);
941 	err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
942 				     &pdu_prev, &pdu, NULL, NULL, &ter_idx);
943 	LL_ASSERT(!err);
944 
945 	err = ull_adv_sync_remove_from_acad(lll_sync, pdu_prev, pdu,
946 					    PDU_ADV_DATA_TYPE_CHANNEL_MAP_UPDATE_IND);
947 	LL_ASSERT(!err);
948 
949 	lll_adv_sync_data_enqueue(lll_sync, ter_idx);
950 }
951 
ull_adv_sync_info_fill(struct ll_adv_sync_set * sync,struct pdu_adv_sync_info * si)952 void ull_adv_sync_info_fill(struct ll_adv_sync_set *sync,
953 			    struct pdu_adv_sync_info *si)
954 {
955 	struct lll_adv_sync *lll_sync;
956 
957 	/* NOTE: sync offset and offset unit filled by secondary prepare.
958 	 *
959 	 * If sync_info is part of ADV PDU the offs_adjust field
960 	 * is always set to 0.
961 	 */
962 	PDU_ADV_SYNC_INFO_OFFS_SET(si, 0U, OFFS_UNIT_VALUE_30_US, 0U);
963 
964 	/* Fill the interval, access address and CRC init */
965 	si->interval = sys_cpu_to_le16(sync->interval);
966 	lll_sync = &sync->lll;
967 	(void)memcpy(&si->aa, lll_sync->access_addr, sizeof(si->aa));
968 	(void)memcpy(si->crc_init, lll_sync->crc_init, sizeof(si->crc_init));
969 
970 	/* NOTE: Filled by secondary prepare */
971 	si->evt_cntr = 0U;
972 }
973 
974 #if !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ull_adv_sync_offset_get(struct ll_adv_set * adv)975 void ull_adv_sync_offset_get(struct ll_adv_set *adv)
976 {
977 	static memq_link_t link;
978 	static struct mayfly mfy = {0, 0, &link, NULL, mfy_sync_offset_get};
979 	uint32_t ret;
980 
981 	mfy.param = adv;
982 	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
983 			     &mfy);
984 	LL_ASSERT(!ret);
985 }
986 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
987 
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)988 void ull_adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags,
989 			   uint8_t phy_s, uint8_t phy_flags,
990 			   struct pdu_cte_info *cte_info)
991 {
992 	struct pdu_adv_com_ext_adv *com_hdr;
993 	struct pdu_adv_ext_hdr *ext_hdr;
994 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
995 	struct pdu_adv_aux_ptr *aux_ptr;
996 	uint32_t cte_len_us;
997 #endif
998 	uint8_t *dptr;
999 	uint8_t len;
1000 
1001 	pdu->type = PDU_ADV_TYPE_AUX_SYNC_IND;
1002 	pdu->rfu = 0U;
1003 	pdu->chan_sel = 0U;
1004 
1005 	pdu->tx_addr = 0U;
1006 	pdu->rx_addr = 0U;
1007 
1008 	com_hdr = &pdu->adv_ext_ind;
1009 	/* Non-connectable and Non-scannable adv mode */
1010 	com_hdr->adv_mode = 0U;
1011 
1012 	ext_hdr = &com_hdr->ext_hdr;
1013 	*(uint8_t *)ext_hdr = ext_hdr_flags;
1014 	dptr = ext_hdr->data;
1015 
1016 	LL_ASSERT(!(ext_hdr_flags & (ULL_ADV_PDU_HDR_FIELD_ADVA | ULL_ADV_PDU_HDR_FIELD_TARGETA |
1017 #if !defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1018 				     ULL_ADV_PDU_HDR_FIELD_ADI |
1019 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1020 				     ULL_ADV_PDU_HDR_FIELD_SYNC_INFO)));
1021 
1022 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
1023 	if (IS_ENABLED(CONFIG_BT_CTLR_DF_ADV_CTE_TX) &&
1024 	    (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_CTE_INFO)) {
1025 		(void)memcpy(dptr, cte_info, sizeof(*cte_info));
1026 		cte_len_us = CTE_LEN_US(cte_info->time);
1027 		dptr += sizeof(struct pdu_cte_info);
1028 	} else {
1029 		cte_len_us = 0U;
1030 	}
1031 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
1032 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT) &&
1033 	    (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_ADI)) {
1034 		dptr += sizeof(struct pdu_adv_adi);
1035 	}
1036 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
1037 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK) &&
1038 	    (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_AUX_PTR)) {
1039 		aux_ptr = (void *)dptr;
1040 		dptr += sizeof(struct pdu_adv_aux_ptr);
1041 	}
1042 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
1043 	if (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_TX_POWER) {
1044 		dptr += sizeof(uint8_t);
1045 	}
1046 
1047 	/* Calc tertiary PDU len */
1048 	len = ull_adv_aux_hdr_len_calc(com_hdr, &dptr);
1049 	ull_adv_aux_hdr_len_fill(com_hdr, len);
1050 
1051 	pdu->len = len;
1052 
1053 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
1054 	/* Fill aux offset in aux pointer field */
1055 	if (ext_hdr_flags & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) {
1056 		uint32_t offs_us;
1057 
1058 		offs_us = PDU_AC_US(pdu->len, phy_s, phy_flags) +
1059 			  EVENT_SYNC_B2B_MAFS_US;
1060 		offs_us += cte_len_us;
1061 		ull_adv_aux_ptr_fill(aux_ptr, offs_us, phy_s);
1062 	}
1063 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
1064 }
1065 
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)1066 uint8_t ull_adv_sync_pdu_alloc(struct ll_adv_set *adv,
1067 			       enum ull_adv_pdu_extra_data_flag extra_data_flag,
1068 			       struct pdu_adv **ter_pdu_prev, struct pdu_adv **ter_pdu_new,
1069 			       void **extra_data_prev, void **extra_data_new, uint8_t *ter_idx)
1070 {
1071 	struct pdu_adv *pdu_prev, *pdu_new;
1072 	struct lll_adv_sync *lll_sync;
1073 	void *ed_prev;
1074 #if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
1075 	void *ed_new;
1076 #endif
1077 
1078 	lll_sync = adv->lll.sync;
1079 	if (!lll_sync) {
1080 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
1081 	}
1082 
1083 	/* Get reference to previous periodic advertising PDU data */
1084 	pdu_prev = lll_adv_sync_data_peek(lll_sync, &ed_prev);
1085 
1086 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1087 	/* Get reference to new periodic advertising PDU data buffer */
1088 	if (extra_data_flag == ULL_ADV_PDU_EXTRA_DATA_ALLOC_ALWAYS ||
1089 	    (extra_data_flag == ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST && ed_prev)) {
1090 		/* If there was an extra data in past PDU data or it is required
1091 		 * by the hdr_add_fields then allocate memory for it.
1092 		 */
1093 		pdu_new = lll_adv_sync_data_alloc(lll_sync, &ed_new,
1094 						  ter_idx);
1095 		if (!pdu_new) {
1096 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1097 		}
1098 	} else {
1099 		ed_new = NULL;
1100 #else
1101 	{
1102 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1103 		pdu_new = lll_adv_sync_data_alloc(lll_sync, NULL, ter_idx);
1104 		if (!pdu_new) {
1105 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1106 		}
1107 	}
1108 
1109 #if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
1110 	if (extra_data_prev) {
1111 		*extra_data_prev = ed_prev;
1112 	}
1113 	if (extra_data_new) {
1114 		*extra_data_new = ed_new;
1115 	}
1116 #endif /* CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY */
1117 
1118 	*ter_pdu_prev = pdu_prev;
1119 	*ter_pdu_new = pdu_new;
1120 
1121 	return 0;
1122 }
1123 
1124 uint8_t ull_adv_sync_duplicate(const struct pdu_adv *pdu_prev, struct pdu_adv *pdu_new)
1125 {
1126 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1127 	/* Duplicate chain PDUs */
1128 	return ull_adv_sync_duplicate_chain(pdu_prev, pdu_new);
1129 #else
1130 	ull_adv_sync_copy_pdu(pdu_prev, pdu_new);
1131 
1132 	return 0U;
1133 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1134 }
1135 
1136 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK) || defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX) || \
1137 	defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1138 static void ull_adv_sync_add_to_header(struct pdu_adv *pdu,
1139 				       const struct pdu_adv_ext_hdr *fields,
1140 				       uint8_t *ad_overflow, uint8_t *overflow_len)
1141 {
1142 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
1143 	uint8_t delta = 0U;
1144 	uint8_t *dptr;
1145 
1146 	if (overflow_len) {
1147 		*overflow_len = 0U;
1148 	}
1149 
1150 	/* AdvA, TargetA and SyncInfo is RFU for periodic advertising */
1151 	if (fields->cte_info && (hdr->ext_hdr_len == 0U || hdr->ext_hdr.cte_info == 0U)) {
1152 		delta += sizeof(struct pdu_cte_info);
1153 	}
1154 	if (fields->adi && (hdr->ext_hdr_len == 0U || hdr->ext_hdr.adi == 0U)) {
1155 		delta += sizeof(struct pdu_adv_adi);
1156 	}
1157 	if (fields->aux_ptr && (hdr->ext_hdr_len == 0U || hdr->ext_hdr.aux_ptr == 0U)) {
1158 		delta += sizeof(struct pdu_adv_aux_ptr);
1159 	}
1160 	if (fields->tx_pwr && (hdr->ext_hdr_len == 0U || hdr->ext_hdr.tx_pwr == 0U)) {
1161 		delta += 1U;
1162 	}
1163 
1164 	if (delta == 0U) {
1165 		/* No new fields to add */
1166 		return;
1167 	}
1168 
1169 	if (hdr->ext_hdr_len == 0) {
1170 		/* Add one byte for the header flags */
1171 		delta++;
1172 	}
1173 
1174 	/* Push back any adv data - overflow will be returned via ad_overflow */
1175 	if (pdu->len > hdr->ext_hdr_len + 1U) {
1176 		if (pdu->len > PDU_AC_EXT_PAYLOAD_SIZE_MAX - delta) {
1177 			LL_ASSERT(ad_overflow);
1178 			LL_ASSERT(overflow_len);
1179 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1180 			*overflow_len = delta - (PDU_AC_EXT_PAYLOAD_SIZE_MAX - pdu->len);
1181 			memcpy(ad_overflow,
1182 			       pdu->payload + PDU_AC_EXT_PAYLOAD_SIZE_MAX - *overflow_len,
1183 			       *overflow_len);
1184 			pdu->len -= *overflow_len;
1185 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1186 		}
1187 		dptr = pdu->payload + hdr->ext_hdr_len + 1U;
1188 		memmove(dptr + delta,
1189 			dptr, pdu->len - hdr->ext_hdr_len - 1U);
1190 	}
1191 
1192 	pdu->len += delta;
1193 
1194 	if (hdr->ext_hdr_len == 0U) {
1195 		/* No extended header present, adding one */
1196 		memcpy(&hdr->ext_hdr, fields, sizeof(struct pdu_adv_ext_hdr));
1197 		hdr->ext_hdr_len = delta;
1198 	} else {
1199 		/* Go to end of current extended header and push back fields/ACAD in reverse */
1200 		dptr = hdr->ext_hdr.data;
1201 
1202 		/* AdvA and TargetA is RFU for periodic advertising */
1203 
1204 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1205 		if (hdr->ext_hdr.cte_info) {
1206 			dptr += sizeof(struct pdu_cte_info);
1207 		}
1208 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1209 
1210 		if (hdr->ext_hdr.adi) {
1211 			dptr += sizeof(struct pdu_adv_adi);
1212 		}
1213 
1214 		if (hdr->ext_hdr.aux_ptr) {
1215 			dptr += sizeof(struct pdu_adv_aux_ptr);
1216 		}
1217 
1218 		/* SyncInfo is RFU for periodic advertising */
1219 
1220 		if (hdr->ext_hdr.tx_pwr) {
1221 			dptr++;
1222 		}
1223 
1224 		/* Push back ACAD if any */
1225 		if ((dptr - hdr->ext_hdr_adv_data) < hdr->ext_hdr_len) {
1226 			uint8_t acad_len = hdr->ext_hdr_len - (dptr - hdr->ext_hdr_adv_data);
1227 
1228 			memmove(dptr + delta, dptr, acad_len);
1229 		}
1230 
1231 		/* Set new header size now before starting to decrement delta */
1232 		hdr->ext_hdr_len += delta;
1233 
1234 		/* Now push back or add fields as needed */
1235 
1236 		if (hdr->ext_hdr.tx_pwr) {
1237 			dptr--;
1238 			*(dptr + delta) = *dptr;
1239 		} else if (fields->tx_pwr) {
1240 			hdr->ext_hdr.tx_pwr = 1U;
1241 			delta -= 1U;
1242 		}
1243 
1244 		if (hdr->ext_hdr.aux_ptr) {
1245 			dptr -= sizeof(struct pdu_adv_aux_ptr);
1246 			memmove(dptr + delta, dptr, sizeof(struct pdu_adv_aux_ptr));
1247 		} else if (fields->aux_ptr) {
1248 			hdr->ext_hdr.aux_ptr = 1U;
1249 			delta -= sizeof(struct pdu_adv_aux_ptr);
1250 		}
1251 
1252 		if (hdr->ext_hdr.adi) {
1253 			dptr -= sizeof(struct pdu_adv_adi);
1254 			memmove(dptr + delta, dptr, sizeof(struct pdu_adv_adi));
1255 		} else if (fields->adi) {
1256 			hdr->ext_hdr.adi = 1U;
1257 			delta -= sizeof(struct pdu_adv_adi);
1258 		}
1259 
1260 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1261 		if (hdr->ext_hdr.cte_info) {
1262 			dptr -= sizeof(struct pdu_cte_info);
1263 			memmove(dptr + delta, dptr, sizeof(struct pdu_cte_info));
1264 		} else if (fields->cte_info) {
1265 			hdr->ext_hdr.cte_info = 1U;
1266 			delta -= sizeof(struct pdu_cte_info);
1267 		}
1268 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1269 	}
1270 }
1271 
1272 static void ull_adv_sync_remove_from_header(struct pdu_adv *pdu,
1273 					    const struct pdu_adv_ext_hdr *fields,
1274 					    bool acad)
1275 {
1276 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
1277 	uint8_t orig_hdr_len = hdr->ext_hdr_len;
1278 	uint8_t *dptr;
1279 
1280 	if (orig_hdr_len == 0U) {
1281 		return;
1282 	}
1283 
1284 	dptr = hdr->ext_hdr.data;
1285 
1286 	/* AdvA and TargetA is RFU for periodic advertising */
1287 
1288 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1289 	if (hdr->ext_hdr.cte_info) {
1290 		if (fields->cte_info) {
1291 			memmove(dptr, dptr + sizeof(struct pdu_cte_info),
1292 				hdr->ext_hdr_len - (hdr->ext_hdr.data - dptr));
1293 			hdr->ext_hdr.cte_info = 0U;
1294 			hdr->ext_hdr_len -= sizeof(struct pdu_cte_info);
1295 		} else {
1296 			dptr += sizeof(struct pdu_cte_info);
1297 		}
1298 	}
1299 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1300 
1301 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1302 	if (hdr->ext_hdr.adi) {
1303 		if (fields->adi) {
1304 			memmove(dptr, dptr + sizeof(struct pdu_adv_adi),
1305 				hdr->ext_hdr_len - (hdr->ext_hdr.data - dptr));
1306 			hdr->ext_hdr.adi = 0U;
1307 			hdr->ext_hdr_len -= sizeof(struct pdu_adv_adi);
1308 		} else {
1309 			dptr += sizeof(struct pdu_adv_adi);
1310 		}
1311 	}
1312 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1313 
1314 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1315 	if (hdr->ext_hdr.aux_ptr) {
1316 		if (fields->aux_ptr) {
1317 			memmove(dptr, dptr + sizeof(struct pdu_adv_aux_ptr),
1318 				hdr->ext_hdr_len - (hdr->ext_hdr.data - dptr));
1319 			hdr->ext_hdr.aux_ptr = 0U;
1320 			hdr->ext_hdr_len -= sizeof(struct pdu_adv_aux_ptr);
1321 		} else {
1322 			dptr += sizeof(struct pdu_adv_aux_ptr);
1323 		}
1324 	}
1325 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1326 
1327 	/* SyncInfo is RFU for periodic advertising */
1328 
1329 	if (hdr->ext_hdr.tx_pwr) {
1330 		if (fields->tx_pwr) {
1331 			memmove(dptr, dptr + 1U,
1332 				hdr->ext_hdr_len - (hdr->ext_hdr.data - dptr));
1333 			hdr->ext_hdr.tx_pwr = 0U;
1334 			hdr->ext_hdr_len -= 1U;
1335 		} else {
1336 			dptr++;
1337 		}
1338 	}
1339 
1340 	/* ACAD is the remainder of the header, if any left */
1341 	if (acad) {
1342 		/* Drop any ACAD */
1343 		hdr->ext_hdr_len = dptr - hdr->ext_hdr_adv_data;
1344 	}
1345 
1346 	if (hdr->ext_hdr_len == 1U) {
1347 		/* Only flags left in header, remove it completely */
1348 		hdr->ext_hdr_len = 0U;
1349 	}
1350 
1351 	if (orig_hdr_len != hdr->ext_hdr_len) {
1352 		/* Move adv data if any */
1353 		if (pdu->len > orig_hdr_len + 1U) {
1354 			memmove(hdr->ext_hdr_adv_data + hdr->ext_hdr_len,
1355 				hdr->ext_hdr_adv_data + orig_hdr_len,
1356 				pdu->len - orig_hdr_len - 1U);
1357 		}
1358 
1359 		/* Update total PDU len */
1360 		pdu->len -= orig_hdr_len - hdr->ext_hdr_len;
1361 	}
1362 
1363 }
1364 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK || CONFIG_BT_CTLR_DF_ADV_CTE_TX || \
1365 	*  CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT
1366 	*/
1367 
1368 static void ull_adv_sync_copy_pdu_header(struct pdu_adv *target_pdu,
1369 					 const struct pdu_adv *source_pdu,
1370 					 const struct pdu_adv_ext_hdr *skip_fields,
1371 					 bool skip_acad)
1372 {
1373 	const struct pdu_adv_com_ext_adv *source_hdr = &source_pdu->adv_ext_ind;
1374 	struct pdu_adv_com_ext_adv *target_hdr = &target_pdu->adv_ext_ind;
1375 	const uint8_t *source_dptr;
1376 	uint8_t *target_dptr;
1377 
1378 	LL_ASSERT(target_pdu != source_pdu);
1379 
1380 	/* Initialize PDU header */
1381 	target_pdu->type = source_pdu->type;
1382 	target_pdu->rfu = 0U;
1383 	target_pdu->chan_sel = 0U;
1384 	target_pdu->tx_addr = 0U;
1385 	target_pdu->rx_addr = 0U;
1386 	target_hdr->adv_mode = source_hdr->adv_mode;
1387 
1388 	/* Copy extended header */
1389 	if (source_hdr->ext_hdr_len == 0U) {
1390 		/* No extended header present */
1391 		target_hdr->ext_hdr_len = 0U;
1392 	} else if (!skip_fields && !skip_acad) {
1393 		/* Copy entire extended header */
1394 		memcpy(target_hdr, source_hdr, source_hdr->ext_hdr_len + 1U);
1395 	} else {
1396 		/* Copy field by field */
1397 		source_dptr = source_hdr->ext_hdr.data;
1398 		target_dptr = target_hdr->ext_hdr.data;
1399 
1400 		/* Initialize extended header flags to all 0 */
1401 		target_hdr->ext_hdr_adv_data[0U] = 0U;
1402 
1403 		/* AdvA and TargetA is RFU for periodic advertising */
1404 
1405 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1406 		if (source_hdr->ext_hdr.cte_info) {
1407 			if (!skip_fields || !skip_fields->cte_info) {
1408 				memcpy(target_dptr, source_dptr, sizeof(struct pdu_cte_info));
1409 				target_dptr += sizeof(struct pdu_cte_info);
1410 				target_hdr->ext_hdr.cte_info = 1U;
1411 			}
1412 			source_dptr += sizeof(struct pdu_cte_info);
1413 		}
1414 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1415 
1416 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1417 		if (source_hdr->ext_hdr.adi) {
1418 			if (!skip_fields || !skip_fields->adi) {
1419 				memcpy(target_dptr, source_dptr, sizeof(struct pdu_adv_adi));
1420 				target_dptr += sizeof(struct pdu_adv_adi);
1421 				target_hdr->ext_hdr.adi = 1U;
1422 			}
1423 			source_dptr += sizeof(struct pdu_adv_adi);
1424 		}
1425 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1426 
1427 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1428 		if (source_hdr->ext_hdr.aux_ptr) {
1429 			if (!skip_fields || !skip_fields->aux_ptr) {
1430 				memcpy(target_dptr, source_dptr, sizeof(struct pdu_adv_aux_ptr));
1431 				target_dptr += sizeof(struct pdu_adv_aux_ptr);
1432 				target_hdr->ext_hdr.aux_ptr = 1U;
1433 			}
1434 			source_dptr += sizeof(struct pdu_adv_aux_ptr);
1435 		}
1436 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1437 
1438 		/* SyncInfo is RFU for periodic advertising */
1439 
1440 		if (source_hdr->ext_hdr.tx_pwr) {
1441 			if (!skip_fields || !skip_fields->tx_pwr) {
1442 				*target_dptr = *source_dptr;
1443 				target_dptr++;
1444 				target_hdr->ext_hdr.tx_pwr = 1U;
1445 			}
1446 			source_dptr++;
1447 		}
1448 
1449 		/* ACAD is the remainder of the header, if any left */
1450 		if ((source_dptr - source_hdr->ext_hdr_adv_data) < source_hdr->ext_hdr_len &&
1451 		    !skip_acad) {
1452 			uint8_t acad_len = source_hdr->ext_hdr_len -
1453 					   (source_dptr - source_hdr->ext_hdr_adv_data);
1454 
1455 			memcpy(target_dptr, source_dptr, acad_len);
1456 			target_dptr += acad_len;
1457 		}
1458 
1459 		if (target_dptr == target_hdr->ext_hdr.data) {
1460 			/* Nothing copied, do not include extended header */
1461 			target_hdr->ext_hdr_len = 0U;
1462 		} else {
1463 			target_hdr->ext_hdr_len = target_dptr - target_hdr->ext_hdr_adv_data;
1464 		}
1465 	}
1466 
1467 	target_pdu->len = target_hdr->ext_hdr_len + 1U;
1468 }
1469 
1470 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1471 static void ull_adv_sync_update_pdu_adi(struct lll_adv_sync *lll_sync, struct pdu_adv *pdu,
1472 					uint16_t did)
1473 {
1474 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
1475 	struct ll_adv_set *adv = HDR_LLL2ULL(lll_sync->adv);
1476 	struct pdu_adv_adi *adi;
1477 	uint8_t *dptr;
1478 
1479 	if (hdr->ext_hdr_len == 0U || hdr->ext_hdr.adi == 0U) {
1480 		/* No ADI field present, nothing to do */
1481 		return;
1482 	}
1483 
1484 	/* Find ADI in extended header */
1485 	dptr = hdr->ext_hdr.data;
1486 
1487 	/* AdvA and TargetA is RFU for periodic advertising */
1488 
1489 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1490 	if (hdr->ext_hdr.cte_info) {
1491 		dptr += sizeof(struct pdu_cte_info);
1492 	}
1493 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1494 
1495 	adi = (struct pdu_adv_adi *)dptr;
1496 
1497 	PDU_ADV_ADI_DID_SID_SET(adi, did, adv->sid);
1498 }
1499 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1500 
1501 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1502 static void ull_adv_sync_add_aux_ptr(struct pdu_adv *pdu, uint8_t *ad_overflow,
1503 				     uint8_t *overflow_len)
1504 {
1505 	struct pdu_adv_ext_hdr fields = { 0U };
1506 
1507 	fields.aux_ptr = 1U;
1508 	ull_adv_sync_add_to_header(pdu, &fields, ad_overflow, overflow_len);
1509 }
1510 
1511 static void ull_adv_sync_update_aux_ptr(struct lll_adv_sync *lll_sync, struct pdu_adv *pdu)
1512 {
1513 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
1514 	struct pdu_adv_aux_ptr *aux_ptr;
1515 	struct ll_adv_set *adv;
1516 	uint32_t offs_us;
1517 	uint8_t *dptr;
1518 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1519 	struct pdu_cte_info *cte_info = NULL;
1520 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1521 
1522 	if (!hdr->ext_hdr_len || !hdr->ext_hdr.aux_ptr) {
1523 		/* Nothing to update */
1524 		return;
1525 	}
1526 
1527 	/* Find AuxPtr */
1528 	dptr = hdr->ext_hdr.data;
1529 
1530 	/* AdvA and TargetA is RFU for periodic advertising */
1531 
1532 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1533 	if (hdr->ext_hdr.cte_info) {
1534 		cte_info = (struct pdu_cte_info *)dptr;
1535 		dptr += sizeof(struct pdu_cte_info);
1536 	}
1537 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1538 
1539 	if (hdr->ext_hdr.adi) {
1540 		dptr += sizeof(struct pdu_adv_adi);
1541 	}
1542 
1543 	/* Now at AuxPtr */
1544 	aux_ptr = (struct pdu_adv_aux_ptr *)dptr;
1545 
1546 	/* Calculate and set offset */
1547 	adv = HDR_LLL2ULL(lll_sync->adv);
1548 	offs_us = PDU_AC_US(pdu->len, adv->lll.phy_s, adv->lll.phy_flags) + EVENT_SYNC_B2B_MAFS_US;
1549 
1550 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1551 	/* Add CTE time if relevant */
1552 	if (cte_info) {
1553 		offs_us += CTE_LEN_US(cte_info->time);
1554 	}
1555 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1556 
1557 	ull_adv_aux_ptr_fill(aux_ptr, offs_us, adv->lll.phy_s);
1558 }
1559 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1560 
1561 static uint8_t ull_adv_sync_append_ad_data(struct lll_adv_sync *lll_sync, struct pdu_adv *pdu,
1562 					   const uint8_t *ad, uint8_t ad_len, uint8_t max_ad_len)
1563 {
1564 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1565 	uint8_t ad_overflow[sizeof(struct pdu_adv_aux_ptr) + 1U];
1566 	uint8_t overflow_len = 0U;
1567 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1568 
1569 	while (ad_len) {
1570 		uint8_t pdu_ad_len;
1571 		uint8_t *dptr;
1572 		uint8_t ext_hdr_len;
1573 		uint8_t pdu_add_len = ad_len;
1574 
1575 		ext_hdr_len = pdu->adv_ext_ind.ext_hdr_len + 1U;
1576 		pdu_ad_len = pdu->len - ext_hdr_len;
1577 
1578 		/* Check if the adv data exceeds the configured maximum */
1579 		/* FIXME - this check should include the entire chain */
1580 		if (pdu_ad_len + ad_len > CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) {
1581 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1582 		}
1583 
1584 		/* Only allow up to max_ad_len adv data per PDU */
1585 		if (pdu_ad_len + ad_len > max_ad_len ||
1586 		    PDU_AC_EXT_PAYLOAD_SIZE_MAX - pdu->len < ad_len) {
1587 #if !defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1588 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1589 #else
1590 			/* Will fragment into chain PDU */
1591 
1592 			/* Add aux_ptr to existing PDU */
1593 			ull_adv_sync_add_aux_ptr(pdu, ad_overflow, &overflow_len);
1594 
1595 			pdu_add_len = MAX(0U, MIN(max_ad_len - pdu_ad_len,
1596 					  PDU_AC_EXT_PAYLOAD_SIZE_MAX - pdu->len));
1597 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1598 		}
1599 
1600 		dptr = pdu->payload + pdu->len;
1601 
1602 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1603 		if (pdu_add_len && overflow_len) {
1604 			/* Overflow from previous PDU in chain, add this first */
1605 			memcpy(dptr, ad, overflow_len);
1606 			pdu->len += overflow_len;
1607 			dptr += overflow_len;
1608 			overflow_len = 0U;
1609 		}
1610 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1611 
1612 		if (pdu_add_len) {
1613 			memcpy(dptr, ad, pdu_add_len);
1614 			pdu->len += pdu_add_len;
1615 			ad_len -= pdu_add_len;
1616 			ad += pdu_add_len;
1617 		}
1618 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1619 		if (ad_len) {
1620 			struct pdu_adv_ext_hdr skip_fields = { 0U };
1621 			struct pdu_adv *pdu_chain;
1622 
1623 			/* Fill the aux offset in superior PDU */
1624 			ull_adv_sync_update_aux_ptr(lll_sync, pdu);
1625 
1626 			/* Allocate new PDU */
1627 			pdu_chain = lll_adv_pdu_alloc_pdu_adv();
1628 			if (!pdu_chain) {
1629 				return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1630 			}
1631 
1632 			/* Copy header, removing AuxPtr, CTEInfo and ACAD */
1633 			skip_fields.aux_ptr = 1U;
1634 			skip_fields.cte_info = 1U;
1635 			ull_adv_sync_copy_pdu_header(pdu_chain, pdu, &skip_fields, true);
1636 
1637 			/* Chain the PDU */
1638 			lll_adv_pdu_linked_append(pdu_chain, pdu);
1639 
1640 			pdu = pdu_chain;
1641 		}
1642 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1643 	}
1644 
1645 	return 0U;
1646 }
1647 
1648 static void ull_adv_sync_copy_pdu(const struct pdu_adv *pdu_prev,
1649 				  struct pdu_adv *pdu)
1650 {
1651 	if (pdu == pdu_prev) {
1652 		return;
1653 	}
1654 
1655 	/* Initialize PDU header */
1656 	pdu->type = pdu_prev->type;
1657 	pdu->rfu = 0U;
1658 	pdu->chan_sel = 0U;
1659 	pdu->tx_addr = 0U;
1660 	pdu->rx_addr = 0U;
1661 	pdu->len = pdu_prev->len;
1662 
1663 	/* Copy PDU payload */
1664 	memcpy(pdu->payload, pdu_prev->payload, pdu_prev->len);
1665 }
1666 
1667 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1668 static uint8_t ull_adv_sync_duplicate_chain(const struct pdu_adv *pdu_prev,
1669 					    struct pdu_adv *pdu)
1670 {
1671 	/* If pdu_prev == pdu we are done */
1672 	if (pdu == pdu_prev) {
1673 		return 0U;
1674 	}
1675 
1676 	/* Copy existing PDU chain */
1677 	while (pdu_prev) {
1678 		struct pdu_adv *pdu_chain;
1679 
1680 		ull_adv_sync_copy_pdu(pdu_prev, pdu);
1681 
1682 		pdu_prev = lll_adv_pdu_linked_next_get(pdu_prev);
1683 		pdu_chain = lll_adv_pdu_linked_next_get(pdu);
1684 		if (pdu_prev && !pdu_chain) {
1685 			/* Get a new chain PDU */
1686 			pdu_chain = lll_adv_pdu_alloc_pdu_adv();
1687 			if (!pdu_chain) {
1688 				return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1689 			}
1690 
1691 			/* Link the chain PDU to parent PDU */
1692 			lll_adv_pdu_linked_append(pdu_chain, pdu);
1693 			pdu = pdu_chain;
1694 		}
1695 	}
1696 
1697 	return 0U;
1698 }
1699 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1700 
1701 static uint8_t ull_adv_sync_ad_add(struct lll_adv_sync *lll_sync,
1702 				   struct pdu_adv *ter_pdu_prev,
1703 				   struct pdu_adv *ter_pdu,
1704 				   const uint8_t *ad, uint8_t ad_len)
1705 {
1706 	uint8_t pdu_ad_max_len = PDU_AC_EXT_AD_DATA_LEN_MAX;
1707 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1708 	uint8_t err;
1709 
1710 	err = ull_adv_sync_duplicate_chain(ter_pdu_prev, ter_pdu);
1711 	if (err) {
1712 		return err;
1713 	}
1714 
1715 	/* Find end of current advertising data */
1716 	while (lll_adv_pdu_linked_next_get(ter_pdu)) {
1717 		ter_pdu = lll_adv_pdu_linked_next_get(ter_pdu);
1718 		ter_pdu_prev = lll_adv_pdu_linked_next_get(ter_pdu_prev);
1719 
1720 		/* Use the full PDU payload for AUX_CHAIN_IND */
1721 		pdu_ad_max_len = PDU_AC_EXT_PAYLOAD_SIZE_MAX;
1722 
1723 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1724 		/* Detect end of current advertising data */
1725 		if (ter_pdu->len < PDU_AC_EXT_PAYLOAD_SIZE_MAX) {
1726 			break;
1727 		}
1728 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1729 	}
1730 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1731 	/* Initialize PDU header */
1732 	ter_pdu->type = ter_pdu_prev->type;
1733 	ter_pdu->rfu = 0U;
1734 	ter_pdu->chan_sel = 0U;
1735 	ter_pdu->tx_addr = 0U;
1736 	ter_pdu->rx_addr = 0U;
1737 	ter_pdu->len = ter_pdu_prev->len;
1738 
1739 	/* Copy PDU payload */
1740 	memcpy(ter_pdu->payload, ter_pdu_prev->payload, ter_pdu_prev->len);
1741 #endif /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1742 
1743 	/* At end of copied chain, append new adv data */
1744 	return ull_adv_sync_append_ad_data(lll_sync, ter_pdu, ad, ad_len, pdu_ad_max_len);
1745 }
1746 
1747 static uint8_t ull_adv_sync_ad_replace(struct lll_adv_sync *lll_sync,
1748 				       struct pdu_adv *ter_pdu_prev,
1749 				       struct pdu_adv *ter_pdu,
1750 				       const uint8_t *ad, uint8_t ad_len)
1751 {
1752 	struct pdu_adv_ext_hdr skip_fields = { 0U };
1753 
1754 	skip_fields.aux_ptr = 1U;
1755 
1756 	/* FIXME - below ignores any configured CTE count */
1757 	if (ter_pdu_prev == ter_pdu) {
1758 		/* Remove adv data and any AuxPtr */
1759 		ter_pdu->len = ter_pdu_prev->adv_ext_ind.ext_hdr_len + 1U;
1760 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1761 		ull_adv_sync_remove_from_header(ter_pdu, &skip_fields, false);
1762 		/* Delete any existing PDU chain */
1763 		if (lll_adv_pdu_linked_next_get(ter_pdu)) {
1764 			lll_adv_pdu_linked_release_all(lll_adv_pdu_linked_next_get(ter_pdu));
1765 			lll_adv_pdu_linked_append(NULL, ter_pdu);
1766 		}
1767 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1768 	} else {
1769 		/* Copy header (only), removing any prior presence of Aux Ptr */
1770 		ull_adv_sync_copy_pdu_header(ter_pdu, ter_pdu_prev, &skip_fields, false);
1771 	}
1772 
1773 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1774 	/* New adv data - update ADI if present */
1775 	if (ter_pdu->adv_ext_ind.ext_hdr_len && ter_pdu->adv_ext_ind.ext_hdr.adi) {
1776 		struct ll_adv_set *adv = HDR_LLL2ULL(lll_sync->adv);
1777 		uint16_t did;
1778 
1779 		/* The DID for a specific SID shall be unique */
1780 		did = sys_cpu_to_le16(ull_adv_aux_did_next_unique_get(adv->sid));
1781 		ull_adv_sync_update_pdu_adi(lll_sync, ter_pdu, did);
1782 	}
1783 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1784 
1785 	/* Set advertising data (without copying any existing adv data) */
1786 	return ull_adv_sync_append_ad_data(lll_sync, ter_pdu, ad, ad_len,
1787 					   PDU_AC_EXT_AD_DATA_LEN_MAX);
1788 }
1789 
1790 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1791 static uint8_t ull_adv_sync_update_adi(struct lll_adv_sync *lll_sync,
1792 				       struct pdu_adv *ter_pdu_prev,
1793 				       struct pdu_adv *ter_pdu)
1794 {
1795 	struct ll_adv_set *adv = HDR_LLL2ULL(lll_sync->adv);
1796 	uint16_t did;
1797 
1798 	/* The DID for a specific SID shall be unique */
1799 	did = sys_cpu_to_le16(ull_adv_aux_did_next_unique_get(adv->sid));
1800 
1801 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1802 	uint8_t err;
1803 
1804 	err = ull_adv_sync_duplicate_chain(ter_pdu_prev, ter_pdu);
1805 	if (err) {
1806 		return err;
1807 	}
1808 
1809 	/* Loop through chain and set new ADI for all */
1810 	while (ter_pdu) {
1811 		ull_adv_sync_update_pdu_adi(lll_sync, ter_pdu, did);
1812 		ter_pdu = lll_adv_pdu_linked_next_get(ter_pdu);
1813 	}
1814 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1815 	/* Initialize PDU header */
1816 	ter_pdu->type = ter_pdu_prev->type;
1817 	ter_pdu->rfu = 0U;
1818 	ter_pdu->chan_sel = 0U;
1819 	ter_pdu->tx_addr = 0U;
1820 	ter_pdu->rx_addr = 0U;
1821 	ter_pdu->len = ter_pdu_prev->len;
1822 
1823 	/* Copy PDU payload */
1824 	memcpy(ter_pdu->payload, ter_pdu_prev->payload, ter_pdu_prev->len);
1825 
1826 	/* Set new ADI */
1827 	ull_adv_sync_update_pdu_adi(lll_sync, ter_pdu, did);
1828 #endif /*  CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK*/
1829 	return 0U;
1830 }
1831 
1832 static uint8_t ull_adv_sync_add_adi(struct lll_adv_sync *lll_sync,
1833 				    struct pdu_adv *pdu_prev,
1834 				    struct pdu_adv *pdu)
1835 {
1836 	struct ll_adv_set *adv = HDR_LLL2ULL(lll_sync->adv);
1837 	struct pdu_adv_ext_hdr add_fields = { 0U };
1838 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1839 	uint8_t ad_overflow[sizeof(struct pdu_adv_adi)*MAX_FRAG_COUNT];
1840 	uint8_t total_overflow_len;
1841 	struct pdu_adv *last_pdu;
1842 	uint8_t overflow_len;
1843 	uint8_t err;
1844 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1845 	uint16_t did;
1846 
1847 	add_fields.adi = 1U;
1848 
1849 	/* The DID for a specific SID shall be unique */
1850 	did = sys_cpu_to_le16(ull_adv_aux_did_next_unique_get(adv->sid));
1851 
1852 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1853 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
1854 	if (err) {
1855 		return err;
1856 	}
1857 
1858 	total_overflow_len = 0U;
1859 	/* Loop through chain and add ADI for all */
1860 	while (pdu) {
1861 		last_pdu = pdu;
1862 
1863 		/* We should always have enough available overflow space to fit an ADI */
1864 		LL_ASSERT(total_overflow_len + sizeof(struct pdu_adv_adi) <= sizeof(ad_overflow));
1865 
1866 		ull_adv_sync_add_to_header(pdu, &add_fields,
1867 					   &ad_overflow[total_overflow_len], &overflow_len);
1868 		total_overflow_len += overflow_len;
1869 		ull_adv_sync_update_pdu_adi(lll_sync, pdu, did);
1870 		pdu = lll_adv_pdu_linked_next_get(pdu);
1871 		if (pdu) {
1872 			uint8_t ad_overflow_tmp[sizeof(struct pdu_adv_adi)*MAX_FRAG_COUNT];
1873 			uint8_t overflow_tmp_len = 0U;
1874 			uint8_t pdu_avail = PDU_AC_EXT_PAYLOAD_SIZE_MAX - pdu->len;
1875 			uint8_t pdu_needed = total_overflow_len;
1876 			uint8_t *dptr;
1877 
1878 			if (!pdu->adv_ext_ind.ext_hdr.adi) {
1879 				pdu_needed += sizeof(struct pdu_adv_adi);
1880 			}
1881 			if (pdu->adv_ext_ind.ext_hdr_len == 0U) {
1882 				/* Make room for flags as well */
1883 				pdu_needed++;
1884 			}
1885 
1886 			if (total_overflow_len > 0U) {
1887 				if (pdu_avail < pdu_needed) {
1888 					/* Make room by removing last part of adv data */
1889 					overflow_tmp_len = pdu_needed - pdu_avail;
1890 					memcpy(ad_overflow_tmp,
1891 					       pdu->payload + (pdu->len - overflow_tmp_len),
1892 					       overflow_tmp_len);
1893 					pdu->len -= overflow_tmp_len;
1894 				}
1895 
1896 				/* Prepend overflow from last PDU */
1897 				dptr = pdu->payload + pdu->adv_ext_ind.ext_hdr_len + 1U;
1898 				memmove(dptr + total_overflow_len, dptr,
1899 					pdu->len - pdu->adv_ext_ind.ext_hdr_len - 1U +
1900 					 total_overflow_len);
1901 				pdu->len += total_overflow_len;
1902 				memcpy(dptr, ad_overflow, total_overflow_len);
1903 
1904 				/* Carry forward overflow from this PDU */
1905 				total_overflow_len = overflow_tmp_len;
1906 				if (overflow_tmp_len) {
1907 					memcpy(ad_overflow, ad_overflow_tmp, overflow_tmp_len);
1908 				}
1909 			}
1910 		}
1911 	}
1912 
1913 	/* Push any remaining overflow on to last PDU */
1914 	ull_adv_sync_append_ad_data(lll_sync, pdu, ad_overflow, total_overflow_len,
1915 				    PDU_AC_EXT_PAYLOAD_SIZE_MAX);
1916 
1917 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1918 
1919 	if (pdu->len > PDU_AC_EXT_PAYLOAD_SIZE_MAX - sizeof(struct pdu_adv_adi)) {
1920 		/* No room for ADI */
1921 		return BT_HCI_ERR_PACKET_TOO_LONG;
1922 	}
1923 
1924 	/* Initialize PDU header */
1925 	pdu->type = pdu_prev->type;
1926 	pdu->rfu = 0U;
1927 	pdu->chan_sel = 0U;
1928 	pdu->tx_addr = 0U;
1929 	pdu->rx_addr = 0U;
1930 	pdu->len = pdu_prev->len;
1931 
1932 	/* Copy PDU payload */
1933 	memcpy(pdu->payload, pdu_prev->payload, pdu_prev->len);
1934 
1935 	/* Add and set new ADI */
1936 	ull_adv_sync_add_to_header(pdu, &add_fields, NULL, NULL);
1937 	ull_adv_sync_update_pdu_adi(lll_sync, pdu, did);
1938 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1939 	return 0U;
1940 }
1941 
1942 static uint8_t ull_adv_sync_remove_adi(struct lll_adv_sync *lll_sync,
1943 				       struct pdu_adv *pdu_prev,
1944 				       struct pdu_adv *pdu)
1945 {
1946 	struct pdu_adv_ext_hdr remove_fields = { 0U };
1947 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1948 	uint8_t err;
1949 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1950 
1951 	remove_fields.adi = 1U;
1952 
1953 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1954 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
1955 	if (err) {
1956 		return err;
1957 	}
1958 
1959 	/* Loop through chain and remove ADI for all */
1960 	while (pdu) {
1961 		ull_adv_sync_remove_from_header(pdu, &remove_fields, false);
1962 		if (pdu->adv_ext_ind.ext_hdr_len && pdu->adv_ext_ind.ext_hdr.aux_ptr) {
1963 			ull_adv_sync_update_aux_ptr(lll_sync, pdu);
1964 		}
1965 		pdu = lll_adv_pdu_linked_next_get(pdu);
1966 	}
1967 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1968 	ull_adv_sync_remove_from_header(pdu, &remove_fields, false);
1969 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
1970 
1971 	return 0U;
1972 }
1973 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1974 
1975 uint8_t *ull_adv_sync_get_acad(struct pdu_adv *pdu, uint8_t *acad_len)
1976 {
1977 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
1978 	uint8_t *dptr;
1979 
1980 	/* Skip to ACAD */
1981 	dptr = hdr->ext_hdr.data;
1982 
1983 	/* AdvA and TargetA is RFU for periodic advertising */
1984 
1985 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1986 	if (hdr->ext_hdr.cte_info) {
1987 		dptr += sizeof(struct pdu_cte_info);
1988 	}
1989 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1990 
1991 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT)
1992 	if (hdr->ext_hdr.adi) {
1993 		dptr += sizeof(struct pdu_adv_adi);
1994 	}
1995 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */
1996 
1997 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
1998 	if (hdr->ext_hdr.aux_ptr) {
1999 		dptr += sizeof(struct pdu_adv_aux_ptr);
2000 	}
2001 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2002 
2003 	/* SyncInfo is RFU for periodic advertising */
2004 
2005 	if (hdr->ext_hdr.tx_pwr) {
2006 		dptr++;
2007 	}
2008 
2009 	/* ACAD is the remainder of the header, if any left */
2010 	if ((dptr - hdr->ext_hdr_adv_data) < hdr->ext_hdr_len) {
2011 		*acad_len = hdr->ext_hdr_len - (dptr - hdr->ext_hdr_adv_data);
2012 	} else {
2013 		*acad_len = 0U;
2014 	}
2015 
2016 	return dptr;
2017 }
2018 
2019 uint8_t ull_adv_sync_remove_from_acad(struct lll_adv_sync *lll_sync,
2020 				      struct pdu_adv *pdu_prev,
2021 				      struct pdu_adv *pdu,
2022 				      uint8_t ad_type)
2023 {
2024 	uint8_t acad_len;
2025 	uint8_t ad_len;
2026 	uint8_t *acad;
2027 	uint8_t len;
2028 	uint8_t *ad;
2029 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2030 	uint8_t err;
2031 
2032 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
2033 	if (err) {
2034 		return err;
2035 	}
2036 #else
2037 	ull_adv_sync_copy_pdu(pdu_prev, pdu);
2038 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2039 
2040 	acad = ull_adv_sync_get_acad(pdu, &acad_len);
2041 
2042 	if (acad_len == 0U) {
2043 		return 0U;
2044 	}
2045 
2046 	/* Find the relevant entry */
2047 	len = acad_len;
2048 	ad = acad;
2049 	do {
2050 		ad_len = ad[PDU_ADV_DATA_HEADER_LEN_OFFSET];
2051 		if (ad_len && (ad[PDU_ADV_DATA_HEADER_TYPE_OFFSET] == ad_type)) {
2052 			break;
2053 		}
2054 
2055 		ad_len += 1U;
2056 
2057 		LL_ASSERT(ad_len <= len);
2058 
2059 		ad += ad_len;
2060 		len -= ad_len;
2061 	} while (len);
2062 
2063 	if (len == 0U) {
2064 		/* Entry is not present */
2065 		return 0U;
2066 	}
2067 
2068 	/* Remove entry by moving the rest of the PDU content forward */
2069 	ad_len += 1U;
2070 	(void)memmove(ad, ad + ad_len, pdu->len - ((ad + ad_len) - pdu->payload));
2071 
2072 	/* Adjust lengths */
2073 	pdu->len -= ad_len;
2074 	pdu->adv_ext_ind.ext_hdr_len -= ad_len;
2075 
2076 	return 0U;
2077 }
2078 
2079 uint8_t ull_adv_sync_add_to_acad(struct lll_adv_sync *lll_sync,
2080 				 struct pdu_adv *pdu_prev,
2081 				 struct pdu_adv *pdu,
2082 				 const uint8_t *new_ad,
2083 				 uint8_t new_ad_len)
2084 {
2085 	uint8_t ad_len;
2086 	uint8_t delta;
2087 	uint8_t *dptr;
2088 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2089 	uint8_t err;
2090 
2091 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
2092 	if (err) {
2093 		return err;
2094 	}
2095 #else
2096 	ull_adv_sync_copy_pdu(pdu_prev, pdu);
2097 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2098 
2099 	delta = new_ad_len;
2100 	if (pdu->adv_ext_ind.ext_hdr_len == 0U) {
2101 		/* Add one byte for the header flags */
2102 		delta++;
2103 	}
2104 
2105 	if (pdu->len > PDU_AC_EXT_PAYLOAD_SIZE_MAX - delta) {
2106 		return BT_HCI_ERR_PACKET_TOO_LONG;
2107 	}
2108 
2109 	dptr = pdu->payload + pdu->adv_ext_ind.ext_hdr_len + 1U;
2110 
2111 	/* Make room in ACAD by moving any advertising data back */
2112 	ad_len = pdu->len - pdu->adv_ext_ind.ext_hdr_len - 1U;
2113 	if (ad_len) {
2114 		(void)memmove(dptr + delta, dptr, ad_len);
2115 	}
2116 
2117 	if (pdu->adv_ext_ind.ext_hdr_len == 0U) {
2118 		/* Set all extended header flags to 0 */
2119 		*dptr = 0U;
2120 		dptr++;
2121 	}
2122 
2123 	/* Copy in ACAD data */
2124 	memcpy(dptr, new_ad, new_ad_len);
2125 
2126 	/* Adjust lengths */
2127 	pdu->len += delta;
2128 	pdu->adv_ext_ind.ext_hdr_len += delta;
2129 
2130 	return 0U;
2131 }
2132 
2133 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
2134 static void ull_adv_sync_update_pdu_cteinfo(struct lll_adv_sync *lll_sync, struct pdu_adv *pdu,
2135 					    const struct pdu_cte_info *cte_info)
2136 {
2137 	struct pdu_adv_com_ext_adv *hdr = &pdu->adv_ext_ind;
2138 	uint8_t *dptr;
2139 
2140 	if (hdr->ext_hdr_len == 0U || hdr->ext_hdr.cte_info == 0U) {
2141 		/* No CTEInfo field present, nothing to do */
2142 		return;
2143 	}
2144 
2145 	/* Find CTEInfo in extended header */
2146 	dptr = hdr->ext_hdr.data;
2147 
2148 	/* AdvA and TargetA is RFU for periodic advertising */
2149 
2150 	/* Copy supplied data into extended header */
2151 	memcpy(dptr, (uint8_t *)cte_info, sizeof(struct pdu_cte_info));
2152 }
2153 
2154 uint8_t ull_adv_sync_add_cteinfo(struct lll_adv_sync *lll_sync,
2155 				 struct pdu_adv *pdu_prev,
2156 				 struct pdu_adv *pdu,
2157 				 const struct pdu_cte_info *cte_info,
2158 				 uint8_t cte_count)
2159 {
2160 	struct pdu_adv_ext_hdr add_fields = { 0U };
2161 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2162 	uint8_t ad_overflow[sizeof(struct pdu_cte_info)*MAX_FRAG_COUNT];
2163 	uint8_t total_overflow_len;
2164 	struct pdu_adv *last_pdu = pdu;
2165 	uint8_t overflow_len;
2166 	uint8_t err;
2167 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2168 
2169 	add_fields.cte_info = 1U;
2170 
2171 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2172 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
2173 	if (err) {
2174 		return err;
2175 	}
2176 
2177 	total_overflow_len = 0U;
2178 	/* Loop through chain and add CTEInfo for PDUs up to cte_count */
2179 	while (pdu && cte_count) {
2180 		last_pdu = pdu;
2181 
2182 		/* We should always have enough available overflow space to fit CTEInfo */
2183 		LL_ASSERT(total_overflow_len + sizeof(struct pdu_cte_info) <= sizeof(ad_overflow));
2184 
2185 		ull_adv_sync_add_to_header(pdu, &add_fields,
2186 					   &ad_overflow[total_overflow_len], &overflow_len);
2187 		total_overflow_len += overflow_len;
2188 		ull_adv_sync_update_pdu_cteinfo(lll_sync, pdu, cte_info);
2189 		cte_count--;
2190 
2191 		/* Update AuxPtr if present */
2192 		ull_adv_sync_update_aux_ptr(lll_sync, pdu);
2193 
2194 		pdu = lll_adv_pdu_linked_next_get(pdu);
2195 		if (pdu) {
2196 			uint8_t ad_overflow_tmp[sizeof(struct pdu_cte_info)*MAX_FRAG_COUNT];
2197 			uint8_t overflow_tmp_len = 0U;
2198 			uint8_t pdu_avail = PDU_AC_EXT_PAYLOAD_SIZE_MAX - pdu->len;
2199 			uint8_t pdu_needed = total_overflow_len;
2200 			uint8_t *dptr;
2201 
2202 			if (!pdu->adv_ext_ind.ext_hdr.cte_info) {
2203 				pdu_needed += sizeof(struct pdu_cte_info);
2204 			}
2205 			if (pdu->adv_ext_ind.ext_hdr_len == 0U) {
2206 				/* Make room for flags as well */
2207 				pdu_needed++;
2208 			}
2209 
2210 			if (total_overflow_len > 0U) {
2211 				if (pdu_avail < pdu_needed) {
2212 					/* Make room by removing last part of adv data */
2213 					overflow_tmp_len = pdu_needed - pdu_avail;
2214 					memcpy(ad_overflow_tmp,
2215 					       pdu->payload + (pdu->len - overflow_tmp_len),
2216 					       overflow_tmp_len);
2217 					pdu->len -= overflow_tmp_len;
2218 				}
2219 
2220 				/* Prepend overflow from last PDU */
2221 				dptr = pdu->payload + pdu->adv_ext_ind.ext_hdr_len + 1U;
2222 				memmove(dptr + total_overflow_len, dptr,
2223 					pdu->len - pdu->adv_ext_ind.ext_hdr_len - 1U +
2224 					 total_overflow_len);
2225 				pdu->len += total_overflow_len;
2226 				memcpy(dptr, ad_overflow, total_overflow_len);
2227 
2228 				/* Carry forward overflow from this PDU */
2229 				total_overflow_len = overflow_tmp_len;
2230 				if (overflow_tmp_len) {
2231 					memcpy(ad_overflow, ad_overflow_tmp, overflow_tmp_len);
2232 				}
2233 			}
2234 
2235 		}
2236 	}
2237 
2238 	pdu = last_pdu;
2239 
2240 	/* Push any remaining overflow on to last PDU */
2241 	ull_adv_sync_append_ad_data(lll_sync, pdu, ad_overflow, total_overflow_len,
2242 				    PDU_AC_EXT_PAYLOAD_SIZE_MAX);
2243 
2244 #if (CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1)
2245 	/* Add PDUs up to cte_count if needed */
2246 	while (cte_count) {
2247 		struct pdu_adv_ext_hdr skip_fields = { 0U };
2248 		struct pdu_adv *pdu_chain;
2249 
2250 		skip_fields.adi = 1U;
2251 		skip_fields.aux_ptr = 1U;
2252 		skip_fields.tx_pwr = 1U;
2253 
2254 		/* Get a new chain PDU */
2255 		pdu_chain = lll_adv_pdu_alloc_pdu_adv();
2256 		if (!pdu_chain) {
2257 			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
2258 		}
2259 
2260 		/* Link the chain PDU to parent PDU */
2261 		lll_adv_pdu_linked_append(pdu_chain, pdu);
2262 
2263 		/* Copy header to new PDU, skipping all fields except CTEInfo */
2264 		ull_adv_sync_copy_pdu_header(pdu_chain, pdu, &skip_fields, true);
2265 
2266 		/* Add and set aux_ptr to existing PDU */
2267 		ull_adv_sync_add_aux_ptr(pdu, ad_overflow, &overflow_len);
2268 		ull_adv_sync_update_aux_ptr(lll_sync, pdu);
2269 
2270 		if (overflow_len) {
2271 			ull_adv_sync_append_ad_data(lll_sync, pdu_chain, ad_overflow, overflow_len,
2272 				    PDU_AC_EXT_PAYLOAD_SIZE_MAX);
2273 		}
2274 
2275 		pdu = pdu_chain;
2276 		cte_count--;
2277 	}
2278 #endif /* CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 */
2279 
2280 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2281 
2282 	if (pdu->len > PDU_AC_EXT_PAYLOAD_SIZE_MAX - sizeof(struct pdu_cte_info)) {
2283 		/* No room for CTEInfo */
2284 		return BT_HCI_ERR_PACKET_TOO_LONG;
2285 	}
2286 
2287 	/* Initialize PDU header */
2288 	pdu->type = pdu_prev->type;
2289 	pdu->rfu = 0U;
2290 	pdu->chan_sel = 0U;
2291 	pdu->tx_addr = 0U;
2292 	pdu->rx_addr = 0U;
2293 	pdu->len = pdu_prev->len;
2294 
2295 	/* Copy PDU payload */
2296 	memcpy(pdu->payload, pdu_prev->payload, pdu_prev->len);
2297 
2298 	/* Add and set CTEInfo */
2299 	ull_adv_sync_add_to_header(pdu, &add_fields, NULL, NULL);
2300 	ull_adv_sync_update_pdu_cteinfo(lll_sync, pdu, cte_info);
2301 #endif /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2302 	return 0U;
2303 }
2304 
2305 uint8_t ull_adv_sync_remove_cteinfo(struct lll_adv_sync *lll_sync,
2306 				    struct pdu_adv *pdu_prev,
2307 				    struct pdu_adv *pdu)
2308 {
2309 	struct pdu_adv_ext_hdr remove_fields = { 0U };
2310 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2311 	uint8_t err;
2312 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2313 
2314 	remove_fields.cte_info = 1U;
2315 
2316 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK)
2317 	err = ull_adv_sync_duplicate_chain(pdu_prev, pdu);
2318 	if (err) {
2319 		return err;
2320 	}
2321 
2322 	/* Loop through chain and remove CTEInfo for all */
2323 	while (pdu) {
2324 		struct pdu_adv *pdu_chain;
2325 
2326 		ull_adv_sync_remove_from_header(pdu, &remove_fields, false);
2327 
2328 		if (pdu->adv_ext_ind.ext_hdr_len && pdu->adv_ext_ind.ext_hdr.aux_ptr) {
2329 			ull_adv_sync_update_aux_ptr(lll_sync, pdu);
2330 		}
2331 
2332 		pdu_chain = lll_adv_pdu_linked_next_get(pdu);
2333 #if (CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1)
2334 		/* If the next PDU in the chain contains no adv data, any remaining PDUs
2335 		 *  in the chain are only present for CTE purposes
2336 		 */
2337 		if (pdu_chain && pdu_chain->len == pdu_chain->adv_ext_ind.ext_hdr_len + 1U) {
2338 			/* Remove AuxPtr and clean up remaining PDUs in chain */
2339 			remove_fields.aux_ptr = 1U;
2340 			ull_adv_sync_remove_from_header(pdu, &remove_fields, false);
2341 			lll_adv_pdu_linked_release_all(pdu_chain);
2342 			lll_adv_pdu_linked_append(NULL, pdu);
2343 			pdu_chain = NULL;
2344 		}
2345 #endif /* CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX > 1 */
2346 		pdu = pdu_chain;
2347 	}
2348 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2349 	ull_adv_sync_remove_from_header(pdu, &remove_fields, false);
2350 #endif /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK */
2351 
2352 	return 0U;
2353 }
2354 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
2355 
2356 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
2357 /* @brief Set or clear fields in extended advertising header and store
2358  *        extra_data if requested.
2359  *
2360  * @param[in]  extra_data_prev  Pointer to previous content of extra_data.
2361  * @param[in]  hdr_add_fields   Flag with information which fields add.
2362  * @param[in]  hdr_rem_fields   Flag with information which fields remove.
2363  * @param[in]  data             Pointer to data to be stored in extra_data.
2364  *                              Content depends on the data depends on
2365  *                              @p hdr_add_fields.
2366  *
2367  * @Note
2368  * @p hdr_data content depends on the flag provided by @p hdr_add_fields:
2369  * - ULL_ADV_PDU_HDR_FIELD_CTE_INFO:
2370  *   # @p hdr_data points to single byte with CTEInfo field
2371  *
2372  * @return Zero in case of success, other value in case of failure.
2373  * @p data depends on the flag provided by @p hdr_add_fields.
2374  *
2375  * @return Zero in case of success, other value in case of failure.
2376  */
2377 void ull_adv_sync_extra_data_set_clear(void *extra_data_prev,
2378 				       void *extra_data_new,
2379 				       uint16_t hdr_add_fields,
2380 				       uint16_t hdr_rem_fields,
2381 				       void *data)
2382 {
2383 	/* Currently only CTE enable requires extra_data. Due to that fact
2384 	 * CTE additional data are just copied to extra_data memory.
2385 	 */
2386 	if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) {
2387 		(void)memcpy(extra_data_new, data, sizeof(struct lll_df_adv_cfg));
2388 	} else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) ||
2389 		   extra_data_prev) {
2390 		(void)memmove(extra_data_new, extra_data_prev,
2391 			      sizeof(struct lll_df_adv_cfg));
2392 	}
2393 }
2394 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
2395 
2396 static int init_reset(void)
2397 {
2398 	/* Initialize adv sync pool. */
2399 	mem_init(ll_adv_sync_pool, sizeof(struct ll_adv_sync_set),
2400 		 sizeof(ll_adv_sync_pool) / sizeof(struct ll_adv_sync_set),
2401 		 &adv_sync_free);
2402 
2403 	return 0;
2404 }
2405 
2406 static uint8_t adv_type_check(struct ll_adv_set *adv)
2407 {
2408 	struct pdu_adv_com_ext_adv *pri_com_hdr;
2409 	struct pdu_adv_ext_hdr *pri_hdr;
2410 	struct pdu_adv *pri_pdu;
2411 
2412 	pri_pdu = lll_adv_data_latest_peek(&adv->lll);
2413 	if (pri_pdu->type != PDU_ADV_TYPE_EXT_IND) {
2414 		return BT_HCI_ERR_INVALID_PARAM;
2415 	}
2416 
2417 	pri_com_hdr = (void *)&pri_pdu->adv_ext_ind;
2418 	if (pri_com_hdr->adv_mode != 0U) {
2419 		return BT_HCI_ERR_INVALID_PARAM;
2420 	}
2421 
2422 	pri_hdr = (void *)pri_com_hdr->ext_hdr_adv_data;
2423 	if (pri_hdr->aux_ptr) {
2424 		struct pdu_adv_com_ext_adv *sec_com_hdr;
2425 		struct pdu_adv_ext_hdr *sec_hdr;
2426 		struct pdu_adv *sec_pdu;
2427 
2428 		sec_pdu = lll_adv_aux_data_latest_peek(adv->lll.aux);
2429 		sec_com_hdr = (void *)&sec_pdu->adv_ext_ind;
2430 		sec_hdr = (void *)sec_com_hdr->ext_hdr_adv_data;
2431 		if (!pri_hdr->adv_addr && !sec_hdr->adv_addr) {
2432 			return BT_HCI_ERR_INVALID_PARAM;
2433 		}
2434 	} else if (!pri_hdr->adv_addr) {
2435 		return BT_HCI_ERR_INVALID_PARAM;
2436 	}
2437 
2438 	return 0;
2439 }
2440 
2441 static inline struct ll_adv_sync_set *sync_acquire(void)
2442 {
2443 	return mem_acquire(&adv_sync_free);
2444 }
2445 
2446 static inline void sync_release(struct ll_adv_sync_set *sync)
2447 {
2448 	mem_release(sync, &adv_sync_free);
2449 }
2450 
2451 static inline uint16_t sync_handle_get(const struct ll_adv_sync_set *sync)
2452 {
2453 	return mem_index_get(sync, ll_adv_sync_pool,
2454 			     sizeof(struct ll_adv_sync_set));
2455 }
2456 
2457 static uint32_t sync_time_get(const struct ll_adv_sync_set *sync,
2458 			      const struct pdu_adv *pdu)
2459 {
2460 	uint8_t len;
2461 
2462 	/* Calculate the PDU Tx Time and hence the radio event length,
2463 	 * Always use maximum length for common extended header format so that
2464 	 * ACAD could be update when periodic advertising is active and the
2465 	 * time reservation need not be updated every time avoiding overlapping
2466 	 * with other active states/roles.
2467 	 */
2468 	len = pdu->len - pdu->adv_ext_ind.ext_hdr_len -
2469 	      PDU_AC_EXT_HEADER_SIZE_MIN + PDU_AC_EXT_HEADER_SIZE_MAX;
2470 
2471 	return ull_adv_sync_time_get(sync, len);
2472 }
2473 
2474 static uint8_t sync_stop(struct ll_adv_sync_set *sync)
2475 {
2476 	uint8_t sync_handle;
2477 	int err;
2478 
2479 	sync_handle = sync_handle_get(sync);
2480 
2481 	err = ull_ticker_stop_with_mark(TICKER_ID_ADV_SYNC_BASE + sync_handle,
2482 					sync, &sync->lll);
2483 	LL_ASSERT_INFO2(err == 0 || err == -EALREADY, sync_handle, err);
2484 	if (err) {
2485 		return BT_HCI_ERR_CMD_DISALLOWED;
2486 	}
2487 
2488 	return 0;
2489 }
2490 
2491 static inline uint8_t sync_remove(struct ll_adv_sync_set *sync,
2492 				  struct ll_adv_set *adv, uint8_t enable)
2493 {
2494 	uint8_t pri_idx;
2495 	uint8_t sec_idx;
2496 	uint8_t err;
2497 
2498 	/* Remove sync_info from auxiliary PDU */
2499 	err = ull_adv_aux_hdr_set_clear(adv, 0U,
2500 					ULL_ADV_PDU_HDR_FIELD_SYNC_INFO, NULL,
2501 					&pri_idx, &sec_idx);
2502 	if (err) {
2503 		return err;
2504 	}
2505 
2506 	lll_adv_aux_data_enqueue(adv->lll.aux, sec_idx);
2507 	lll_adv_data_enqueue(&adv->lll, pri_idx);
2508 
2509 	if (sync->is_started) {
2510 		/* TODO: we removed sync info, but if sync_stop() fails, what do
2511 		 * we do?
2512 		 */
2513 		err = sync_stop(sync);
2514 		if (err) {
2515 			return err;
2516 		}
2517 
2518 		sync->is_started = 0U;
2519 
2520 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2521 		if (adv->lll.aux) {
2522 			/* notify the auxiliary set */
2523 			ull_adv_sync_started_stopped(HDR_LLL2ULL(adv->lll.aux));
2524 		}
2525 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2526 	}
2527 
2528 	if (!enable) {
2529 		sync->is_enabled = 0U;
2530 	}
2531 
2532 	return 0U;
2533 }
2534 
2535 static uint8_t sync_chm_update(uint8_t handle)
2536 {
2537 	struct pdu_adv_sync_chm_upd_ind *chm_upd_ind;
2538 	uint8_t ad[sizeof(*chm_upd_ind) + 2U];
2539 	struct lll_adv_sync *lll_sync;
2540 	struct pdu_adv *pdu_prev;
2541 	struct ll_adv_set *adv;
2542 	struct pdu_adv *pdu;
2543 	uint16_t instant;
2544 	uint8_t chm_last;
2545 	uint8_t ter_idx;
2546 	uint8_t err;
2547 
2548 	/* Check for valid advertising instance */
2549 	adv = ull_adv_is_created_get(handle);
2550 	if (!adv) {
2551 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
2552 	}
2553 
2554 	/* Check for valid periodic advertising */
2555 	lll_sync = adv->lll.sync;
2556 	if (!lll_sync) {
2557 		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
2558 	}
2559 
2560 	/* Fail if already in progress */
2561 	if (lll_sync->chm_last != lll_sync->chm_first) {
2562 		return BT_HCI_ERR_CMD_DISALLOWED;
2563 	}
2564 
2565 	/* Allocate next Sync PDU */
2566 	err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
2567 				     &pdu_prev, &pdu, NULL, NULL, &ter_idx);
2568 	if (err) {
2569 		return err;
2570 	}
2571 
2572 	/* Populate the AD data length and opcode */
2573 	ad[PDU_ADV_DATA_HEADER_LEN_OFFSET] = sizeof(*chm_upd_ind) + 1U;
2574 	ad[PDU_ADV_DATA_HEADER_TYPE_OFFSET] = PDU_ADV_DATA_TYPE_CHANNEL_MAP_UPDATE_IND;
2575 
2576 	/* Populate the Channel Map Indication structure */
2577 	chm_upd_ind = (void *)&ad[PDU_ADV_DATA_HEADER_DATA_OFFSET];
2578 	(void)ull_chan_map_get(chm_upd_ind->chm);
2579 	instant = lll_sync->event_counter + 6U;
2580 	chm_upd_ind->instant = sys_cpu_to_le16(instant);
2581 
2582 	/* Try to add channel map update indication to ACAD */
2583 	err = ull_adv_sync_add_to_acad(lll_sync, pdu_prev, pdu, ad, sizeof(*chm_upd_ind) + 2U);
2584 	if (err) {
2585 		return err;
2586 	}
2587 
2588 	/* Update the LLL to reflect the Channel Map and Instant to use */
2589 	chm_last = lll_sync->chm_last + 1U;
2590 	if (chm_last == DOUBLE_BUFFER_SIZE) {
2591 		chm_last = 0U;
2592 	}
2593 	lll_sync->chm[chm_last].data_chan_count =
2594 		ull_chan_map_get(lll_sync->chm[chm_last].data_chan_map);
2595 	lll_sync->chm_instant = instant;
2596 
2597 	/* Commit the Channel Map Indication in the ACAD field of Periodic
2598 	 * Advertising
2599 	 */
2600 	lll_adv_sync_data_enqueue(lll_sync, ter_idx);
2601 
2602 	/* Initiate the Channel Map Indication */
2603 	lll_sync->chm_last = chm_last;
2604 
2605 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2606 	struct ll_adv_sync_set *sync = HDR_LLL2ULL(lll_sync);
2607 
2608 	if (!sync->is_started) {
2609 		/* Sync not started yet, apply new channel map now */
2610 		lll_sync->chm_first = lll_sync->chm_last;
2611 	}
2612 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2613 
2614 	return 0;
2615 }
2616 
2617 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2618 void ull_adv_sync_lll_syncinfo_fill(struct pdu_adv *pdu, struct lll_adv_aux *lll_aux)
2619 {
2620 	struct lll_adv_sync *lll_sync;
2621 	struct pdu_adv_sync_info *si;
2622 	uint8_t chm_first;
2623 
2624 	lll_sync = lll_aux->adv->sync;
2625 
2626 	si = sync_info_get(pdu);
2627 	sync_info_offset_fill(si, lll_sync->us_adv_sync_pdu_offset);
2628 	si->evt_cntr = lll_sync->event_counter + lll_sync->latency_prepare +
2629 		       lll_sync->sync_lazy;
2630 
2631 	/* Fill the correct channel map to use if at or past the instant */
2632 	if (lll_sync->chm_first != lll_sync->chm_last) {
2633 		uint16_t instant_latency;
2634 
2635 		instant_latency = (si->evt_cntr - lll_sync->chm_instant) &
2636 				  EVENT_INSTANT_MAX;
2637 		if (instant_latency <= EVENT_INSTANT_LATENCY_MAX) {
2638 			chm_first = lll_sync->chm_last;
2639 		} else {
2640 			chm_first = lll_sync->chm_first;
2641 		}
2642 	} else {
2643 		chm_first = lll_sync->chm_first;
2644 	}
2645 	(void)memcpy(si->sca_chm, lll_sync->chm[chm_first].data_chan_map,
2646 		     sizeof(si->sca_chm));
2647 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] &=
2648 		~PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK;
2649 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] |=
2650 		((lll_clock_sca_local_get() <<
2651 		  PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS) &
2652 		 PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK);
2653 }
2654 
2655 static void sync_info_offset_fill(struct pdu_adv_sync_info *si, uint32_t offs)
2656 {
2657 	uint8_t offs_adjust = 0U;
2658 
2659 	if (offs >= OFFS_ADJUST_US) {
2660 		offs -= OFFS_ADJUST_US;
2661 		offs_adjust = 1U;
2662 	}
2663 
2664 	offs = offs / OFFS_UNIT_30_US;
2665 	if (!!(offs >> OFFS_UNIT_BITS)) {
2666 		PDU_ADV_SYNC_INFO_OFFS_SET(si, offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US),
2667 					   OFFS_UNIT_VALUE_300_US, offs_adjust);
2668 	} else {
2669 		PDU_ADV_SYNC_INFO_OFFS_SET(si, offs, OFFS_UNIT_VALUE_30_US, offs_adjust);
2670 	}
2671 }
2672 
2673 #else /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2674 static void mfy_sync_offset_get(void *param)
2675 {
2676 	struct ll_adv_set *adv = param;
2677 	struct lll_adv_sync *lll_sync;
2678 	struct ll_adv_sync_set *sync;
2679 	struct pdu_adv_sync_info *si;
2680 	uint32_t sync_remainder_us;
2681 	uint32_t aux_remainder_us;
2682 	uint32_t ticks_to_expire;
2683 	uint32_t ticks_current;
2684 	struct pdu_adv *pdu;
2685 	uint32_t remainder = 0U;
2686 	uint8_t chm_first;
2687 	uint8_t ticker_id;
2688 	uint16_t lazy;
2689 	uint8_t retry;
2690 	uint8_t id;
2691 
2692 	lll_sync = adv->lll.sync;
2693 	sync = HDR_LLL2ULL(lll_sync);
2694 	ticker_id = TICKER_ID_ADV_SYNC_BASE + sync_handle_get(sync);
2695 
2696 	id = TICKER_NULL;
2697 	ticks_to_expire = 0U;
2698 	ticks_current = 0U;
2699 	retry = 4U;
2700 	do {
2701 		uint32_t volatile ret_cb;
2702 		uint32_t ticks_previous;
2703 		uint32_t ret;
2704 		bool success;
2705 
2706 		ticks_previous = ticks_current;
2707 
2708 		ret_cb = TICKER_STATUS_BUSY;
2709 		ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR,
2710 					       TICKER_USER_ID_ULL_LOW,
2711 					       &id, &ticks_current,
2712 					       &ticks_to_expire, &remainder,
2713 					       &lazy, NULL, NULL,
2714 					       ticker_op_cb, (void *)&ret_cb);
2715 		if (ret == TICKER_STATUS_BUSY) {
2716 			while (ret_cb == TICKER_STATUS_BUSY) {
2717 				ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
2718 						 TICKER_USER_ID_ULL_LOW);
2719 			}
2720 		}
2721 
2722 		success = (ret_cb == TICKER_STATUS_SUCCESS);
2723 		LL_ASSERT(success);
2724 
2725 		LL_ASSERT((ticks_current == ticks_previous) || retry--);
2726 
2727 		LL_ASSERT(id != TICKER_NULL);
2728 	} while (id != ticker_id);
2729 
2730 	/* Reduced a tick for negative remainder and return positive remainder
2731 	 * value.
2732 	 */
2733 	hal_ticker_remove_jitter(&ticks_to_expire, &remainder);
2734 	sync_remainder_us = remainder;
2735 
2736 	/* Add a tick for negative remainder and return positive remainder
2737 	 * value.
2738 	 */
2739 	remainder = sync->aux_remainder;
2740 	hal_ticker_add_jitter(&ticks_to_expire, &remainder);
2741 	aux_remainder_us = remainder;
2742 
2743 	pdu = lll_adv_aux_data_latest_peek(adv->lll.aux);
2744 	si = sync_info_get(pdu);
2745 	sync_info_offset_fill(si, ticks_to_expire, sync_remainder_us,
2746 			      aux_remainder_us);
2747 	si->evt_cntr = lll_sync->event_counter + lll_sync->latency_prepare +
2748 		       lazy;
2749 
2750 	/* Fill the correct channel map to use if at or past the instant */
2751 	if (lll_sync->chm_first != lll_sync->chm_last) {
2752 		uint16_t instant_latency;
2753 
2754 		instant_latency = (si->evt_cntr - lll_sync->chm_instant) &
2755 				  EVENT_INSTANT_MAX;
2756 		if (instant_latency <= EVENT_INSTANT_LATENCY_MAX) {
2757 			chm_first = lll_sync->chm_last;
2758 		} else {
2759 			chm_first = lll_sync->chm_first;
2760 		}
2761 	} else {
2762 		chm_first = lll_sync->chm_first;
2763 	}
2764 	(void)memcpy(si->sca_chm, lll_sync->chm[chm_first].data_chan_map,
2765 		     sizeof(si->sca_chm));
2766 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] &=
2767 		~PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK;
2768 	si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] |=
2769 		((lll_clock_sca_local_get() <<
2770 		  PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS) &
2771 		 PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK);
2772 }
2773 
2774 static void sync_info_offset_fill(struct pdu_adv_sync_info *si,
2775 				  uint32_t ticks_offset,
2776 				  uint32_t remainder_us,
2777 				  uint32_t start_us)
2778 {
2779 	uint8_t offs_adjust = 0U;
2780 	uint32_t offs;
2781 
2782 	offs = HAL_TICKER_TICKS_TO_US(ticks_offset) + remainder_us - start_us;
2783 
2784 	if (offs >= OFFS_ADJUST_US) {
2785 		offs -= OFFS_ADJUST_US;
2786 		offs_adjust = 1U;
2787 	}
2788 
2789 	offs = offs / OFFS_UNIT_30_US;
2790 	if (!!(offs >> OFFS_UNIT_BITS)) {
2791 		PDU_ADV_SYNC_INFO_OFFS_SET(si, offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US),
2792 					   OFFS_UNIT_VALUE_300_US, offs_adjust);
2793 	} else {
2794 		PDU_ADV_SYNC_INFO_OFFS_SET(si, offs, OFFS_UNIT_VALUE_30_US, offs_adjust);
2795 	}
2796 }
2797 
2798 static void ticker_op_cb(uint32_t status, void *param)
2799 {
2800 	*((uint32_t volatile *)param) = status;
2801 }
2802 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2803 
2804 static struct pdu_adv_sync_info *sync_info_get(struct pdu_adv *pdu)
2805 {
2806 	struct pdu_adv_com_ext_adv *p;
2807 	struct pdu_adv_ext_hdr *h;
2808 	uint8_t *ptr;
2809 
2810 	p = (void *)&pdu->adv_ext_ind;
2811 	h = (void *)p->ext_hdr_adv_data;
2812 	ptr = h->data;
2813 
2814 	/* traverse through adv_addr, if present */
2815 	if (h->adv_addr) {
2816 		ptr += BDADDR_SIZE;
2817 	}
2818 
2819 	/* traverse through tgt_addr, if present */
2820 	if (h->tgt_addr) {
2821 		ptr += BDADDR_SIZE;
2822 	}
2823 
2824 	/* No CTEInfo flag in primary and secondary channel PDU */
2825 
2826 	/* traverse through adi, if present */
2827 	if (h->adi) {
2828 		ptr += sizeof(struct pdu_adv_adi);
2829 	}
2830 
2831 	/* traverse through aux ptr, if present */
2832 	if (h->aux_ptr) {
2833 		ptr += sizeof(struct pdu_adv_aux_ptr);
2834 	}
2835 
2836 	/* return pointer offset to sync_info */
2837 	return (void *)ptr;
2838 }
2839 
2840 static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
2841 		      uint32_t remainder, uint16_t lazy, uint8_t force,
2842 		      void *param)
2843 {
2844 	static memq_link_t link;
2845 	static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_sync_prepare};
2846 	static struct lll_prepare_param p;
2847 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2848 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2849 	struct ticker_ext_context *context = param;
2850 	struct ll_adv_sync_set *sync = context->context;
2851 #else /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2852 	struct ll_adv_sync_set *sync = param;
2853 #endif /* !CONFIG_BT_CTLR_ADV_ISO || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2854 	struct lll_adv_sync *lll;
2855 	uint32_t ret;
2856 	uint8_t ref;
2857 
2858 	DEBUG_RADIO_PREPARE_A(1);
2859 
2860 	lll = &sync->lll;
2861 
2862 	/* Increment prepare reference count */
2863 	ref = ull_ref_inc(&sync->ull);
2864 	LL_ASSERT(ref);
2865 
2866 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2867 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2868 	if (lll->iso) {
2869 		struct lll_adv_iso *lll_iso = lll->iso;
2870 
2871 		LL_ASSERT(context->other_expire_info);
2872 
2873 		/* Check: No need for remainder in this case? */
2874 		lll_iso->ticks_sync_pdu_offset = context->other_expire_info->ticks_to_expire;
2875 		lll_iso->iso_lazy = context->other_expire_info->lazy;
2876 	}
2877 #endif /* CONFIG_BT_CTLR_ADV_ISO && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2878 
2879 	/* Append timing parameters */
2880 	p.ticks_at_expire = ticks_at_expire;
2881 	p.remainder = remainder;
2882 	p.lazy = lazy;
2883 	p.force = force;
2884 	p.param = lll;
2885 	mfy.param = &p;
2886 
2887 	/* Kick LLL prepare */
2888 	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
2889 			     TICKER_USER_ID_LLL, 0, &mfy);
2890 	LL_ASSERT(!ret);
2891 
2892 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2893 	!defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2894 	if (lll->iso) {
2895 		ull_adv_iso_offset_get(sync);
2896 	}
2897 #endif /* CONFIG_BT_CTLR_ADV_ISO && !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2898 
2899 	DEBUG_RADIO_PREPARE_A(1);
2900 }
2901 
2902 #if defined(CONFIG_BT_CTLR_ADV_ISO) && \
2903 	defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2904 static void ticker_update_op_cb(uint32_t status, void *param)
2905 {
2906 	LL_ASSERT(status == TICKER_STATUS_SUCCESS ||
2907 		  param == ull_disable_mark_get());
2908 }
2909 #endif /* !CONFIG_BT_CTLR_ADV_ISO && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2910