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