1 /*
2  * Copyright (c) 2018-2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/sys/byteorder.h>
8 #include <zephyr/sys/slist.h>
9 
10 #include <zephyr/bluetooth/hci_types.h>
11 
12 #include "hal/ccm.h"
13 #include "hal/radio.h"
14 #include "hal/ticker.h"
15 
16 #include "util/util.h"
17 #include "util/memq.h"
18 #include "util/mayfly.h"
19 #include "util/dbuf.h"
20 #include "util/mem.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/lll_vendor.h"
30 #include "lll/lll_adv_types.h"
31 #include "lll_adv.h"
32 #include "lll/lll_adv_pdu.h"
33 #include "lll_adv_sync.h"
34 #include "lll_scan.h"
35 #include "lll/lll_df_types.h"
36 #include "lll_conn.h"
37 #include "lll_conn_iso.h"
38 
39 #include "ll_sw/ull_tx_queue.h"
40 
41 #include "ull_adv_types.h"
42 #include "ull_scan_types.h"
43 #include "ull_conn_types.h"
44 
45 #include "isoal.h"
46 #include "ull_iso_types.h"
47 #include "ull_conn_iso_types.h"
48 
49 #include "ull_internal.h"
50 #include "ull_adv_internal.h"
51 #include "ull_conn_internal.h"
52 #include "ull_conn_iso_internal.h"
53 
54 #include "ll_feat.h"
55 
56 #include "hal/debug.h"
57 
58 
59 #if defined(CONFIG_BT_CENTRAL)
60 static void after_cen_offset_get(uint16_t conn_interval, uint32_t ticks_slot,
61 				 uint32_t ticks_anchor,
62 				 uint32_t *win_offset_us);
63 static bool ticker_match_cen_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
64 				   uint32_t ticks_to_expire, void *op_context);
65 #endif /* CONFIG_BT_CENTRAL */
66 
67 typedef struct ull_hdr *(*ull_hdr_get_func)(uint8_t ticker_id,
68 					    uint32_t *ticks_slot);
69 static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
70 				    ticker_op_match_func ticker_match_op_cb,
71 				    ull_hdr_get_func ull_hdr_get_cb_fn,
72 				    uint32_t *ticks_anchor,
73 				    uint32_t *ticks_to_expire_match,
74 				    uint32_t *remainder_match,
75 				    uint32_t *ticks_slot_match);
76 static void ticker_op_cb(uint32_t status, void *param);
77 static struct ull_hdr *ull_hdr_get_cb(uint8_t ticker_id, uint32_t *ticks_slot);
78 
79 #if (defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)) || \
80 	defined(CONFIG_BT_CTLR_CENTRAL_ISO)
81 static int group_free_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
82 			       uint32_t *ticks_to_expire_prev,
83 			       uint32_t *ticks_slot_prev,
84 			       uint32_t *ticks_anchor);
85 static bool ticker_match_any_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
86 				   uint32_t ticks_to_expire, void *op_context);
87 #endif /* (CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER) ||
88 	* CONFIG_BT_CTLR_CENTRAL_ISO
89 	*/
90 
91 #if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
ull_sched_adv_aux_sync_free_anchor_get(uint32_t ticks_slot_abs,uint32_t * ticks_anchor)92 int ull_sched_adv_aux_sync_free_anchor_get(uint32_t ticks_slot_abs,
93 					   uint32_t *ticks_anchor)
94 {
95 	uint32_t ticks_to_expire;
96 	uint32_t ticks_slot;
97 
98 	return group_free_slot_get(TICKER_USER_ID_THREAD, ticks_slot_abs,
99 				   &ticks_to_expire, &ticks_slot, ticks_anchor);
100 }
101 #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
102 
103 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
ull_sched_conn_iso_free_offset_get(uint32_t ticks_slot_abs,uint32_t * ticks_to_expire)104 int ull_sched_conn_iso_free_offset_get(uint32_t ticks_slot_abs,
105 				       uint32_t *ticks_to_expire)
106 {
107 	uint32_t ticks_anchor;
108 	uint32_t ticks_slot;
109 	int err;
110 
111 	err = group_free_slot_get(TICKER_USER_ID_ULL_LOW, ticks_slot_abs,
112 				  ticks_to_expire, &ticks_slot, &ticks_anchor);
113 	if (err) {
114 		return err;
115 	}
116 
117 	*ticks_to_expire += ticks_slot;
118 
119 	return err;
120 }
121 #endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
122 
123 #if defined(CONFIG_BT_CONN)
124 #if defined(CONFIG_BT_CENTRAL)
ull_sched_after_cen_slot_get(uint8_t user_id,uint32_t ticks_slot_abs,uint32_t * ticks_anchor,uint32_t * us_offset)125 int ull_sched_after_cen_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
126 				 uint32_t *ticks_anchor, uint32_t *us_offset)
127 {
128 	uint32_t ticks_to_expire;
129 	uint32_t ticks_slot;
130 	uint32_t remainder;
131 	uint8_t ticker_id;
132 
133 	ticker_id = after_match_slot_get(user_id, ticks_slot_abs,
134 					 ticker_match_cen_op_cb, ull_hdr_get_cb,
135 					 ticks_anchor, &ticks_to_expire,
136 					 &remainder, &ticks_slot);
137 	if (ticker_id != TICKER_NULL) {
138 		uint32_t central_spacing_us;
139 		uint32_t remainder_us;
140 		uint32_t slot_us;
141 
142 		/* When CONFIG_BT_CTLR_CENTRAL_SPACING is used then ticks_slot
143 		 * returned converts to slot_us that is less than or equal to
144 		 * CONFIG_BT_CTLR_CENTRAL_SPACING, because floor value in ticks
145 		 * is returned as ticks_slot.
146 		 * Hence, use CONFIG_BT_CTLR_CENTRAL_SPACING without margin.
147 		 *
148 		 * If actual ticks_slot in microseconds is larger than
149 		 * CONFIG_BT_CTLR_CENTRAL_SPACING, then add margin between
150 		 * central radio events.
151 		 */
152 		slot_us = HAL_TICKER_TICKS_TO_US(ticks_slot);
153 		if (slot_us > CONFIG_BT_CTLR_CENTRAL_SPACING) {
154 			central_spacing_us = slot_us;
155 			central_spacing_us += (EVENT_TICKER_RES_MARGIN_US << 1);
156 		} else {
157 			central_spacing_us = CONFIG_BT_CTLR_CENTRAL_SPACING;
158 		}
159 
160 		remainder_us = remainder;
161 		hal_ticker_remove_jitter(&ticks_to_expire, &remainder_us);
162 
163 		*us_offset = HAL_TICKER_TICKS_TO_US(ticks_to_expire) +
164 			     remainder_us + central_spacing_us;
165 
166 		return 0;
167 	}
168 
169 	return -ECHILD;
170 }
171 
ull_sched_mfy_after_cen_offset_get(void * param)172 void ull_sched_mfy_after_cen_offset_get(void *param)
173 {
174 	struct lll_prepare_param *p = param;
175 	struct lll_scan *lll = p->param;
176 	uint32_t ticks_slot_overhead;
177 	uint32_t ticks_at_expire;
178 	uint32_t remainder_us;
179 	struct ll_conn *conn;
180 
181 	conn = HDR_LLL2ULL(lll->conn);
182 	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
183 		ticks_slot_overhead = MAX(conn->ull.ticks_active_to_start,
184 					  conn->ull.ticks_prepare_to_start);
185 	} else {
186 		ticks_slot_overhead = 0U;
187 	}
188 
189 	ticks_at_expire = p->ticks_at_expire;
190 	remainder_us = p->remainder;
191 	hal_ticker_remove_jitter(&ticks_at_expire, &remainder_us);
192 
193 	after_cen_offset_get(lll->conn->interval,
194 			     (ticks_slot_overhead + conn->ull.ticks_slot),
195 			     ticks_at_expire, &lll->conn_win_offset_us);
196 	if (lll->conn_win_offset_us) {
197 		lll->conn_win_offset_us +=
198 			HAL_TICKER_TICKS_TO_US(p->ticks_at_expire -
199 					       ticks_at_expire) -
200 			remainder_us;
201 	}
202 }
203 #endif /* CONFIG_BT_CENTRAL */
204 
ull_sched_mfy_win_offset_use(void * param)205 void ull_sched_mfy_win_offset_use(void *param)
206 {
207 	struct ll_conn *conn = param;
208 	uint32_t ticks_slot_overhead;
209 
210 	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
211 		ticks_slot_overhead = MAX(conn->ull.ticks_active_to_start,
212 					  conn->ull.ticks_prepare_to_start);
213 	} else {
214 		ticks_slot_overhead = 0U;
215 	}
216 
217 	/*
218 	 * TODO: update calculationg of the win_offset
219 	 * when updating the connection update procedure
220 	 * see the legacy code from Zephyr v3.3 for inspiration
221 	 */
222 }
223 
224 #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
ull_sched_mfy_free_win_offset_calc(void * param)225 void ull_sched_mfy_free_win_offset_calc(void *param)
226 {
227 	uint32_t ticks_to_offset_default = 0U;
228 	uint32_t *ticks_to_offset_next;
229 
230 	ticks_to_offset_next = &ticks_to_offset_default;
231 
232 	/*
233 	 * TODO: update when updating the connection update procedure
234 	 * see the legacy code from Zephyr v3.3 for inspiration
235 	 */
236 }
237 
ull_sched_mfy_win_offset_select(void * param)238 void ull_sched_mfy_win_offset_select(void *param)
239 {
240 #define OFFSET_S_MAX 6
241 #define OFFSET_M_MAX 6
242 
243 	/*
244 	 * TODO: update calculation of win_offset when
245 	 * updating the connection update procedure
246 	 * see the legacy code from Zephyr v3.3 for inspiration
247 	 */
248 
249 #undef OFFSET_S_MAX
250 #undef OFFSET_M_MAX
251 }
252 
253 /*
254  * TODO: probably we need a function for calculating the window offset
255  * see the legacy code from Zephyr v3.3 for inspiration
256  */
257 #endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
258 
259 #if defined(CONFIG_BT_CENTRAL)
after_cen_offset_get(uint16_t conn_interval,uint32_t ticks_slot,uint32_t ticks_anchor,uint32_t * win_offset_us)260 static void after_cen_offset_get(uint16_t conn_interval, uint32_t ticks_slot,
261 				 uint32_t ticks_anchor,
262 				 uint32_t *win_offset_us)
263 {
264 	uint32_t ticks_anchor_offset = ticks_anchor;
265 	int err;
266 
267 	err = ull_sched_after_cen_slot_get(TICKER_USER_ID_ULL_LOW, ticks_slot,
268 					   &ticks_anchor_offset,
269 					   win_offset_us);
270 	if (err) {
271 		return;
272 	}
273 
274 	if ((ticks_anchor_offset - ticks_anchor) & BIT(HAL_TICKER_CNTR_MSBIT)) {
275 		*win_offset_us -= HAL_TICKER_TICKS_TO_US(
276 			ticker_ticks_diff_get(ticks_anchor,
277 					      ticks_anchor_offset));
278 	} else {
279 		*win_offset_us += HAL_TICKER_TICKS_TO_US(
280 			ticker_ticks_diff_get(ticks_anchor_offset,
281 					      ticks_anchor));
282 	}
283 
284 	/* Round positive offset value in the future to within one connection
285 	 * interval value.
286 	 * Offsets in the past, value with MSBit set, are handled by caller by
287 	 * adding radio end time and connection interval as necessary to get a
288 	 * window offset in future when establishing a connection.
289 	 */
290 	if ((*win_offset_us & BIT(31)) == 0) {
291 		uint32_t conn_interval_us = conn_interval * CONN_INT_UNIT_US;
292 
293 		while (*win_offset_us > conn_interval_us) {
294 			*win_offset_us -= conn_interval_us;
295 		}
296 	}
297 }
298 #endif /* CONFIG_BT_CENTRAL */
299 #endif /* CONFIG_BT_CONN */
300 
301 #if (defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)) || \
302 	defined(CONFIG_BT_CTLR_CENTRAL_ISO)
group_free_slot_get(uint8_t user_id,uint32_t ticks_slot_abs,uint32_t * ticks_to_expire_prev,uint32_t * ticks_slot_prev,uint32_t * ticks_anchor)303 static int group_free_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
304 			       uint32_t *ticks_to_expire_prev,
305 			       uint32_t *ticks_slot_prev,
306 			       uint32_t *ticks_anchor)
307 {
308 	uint32_t remainder_prev;
309 	uint8_t ticker_id;
310 
311 	ticker_id = after_match_slot_get(user_id, ticks_slot_abs,
312 					 ticker_match_any_op_cb, ull_hdr_get_cb,
313 					 ticks_anchor, ticks_to_expire_prev,
314 					 &remainder_prev, ticks_slot_prev);
315 	if (ticker_id != TICKER_NULL) {
316 		uint32_t ticks_to_expire;
317 		uint32_t ticks_slot;
318 
319 		ticks_to_expire = *ticks_to_expire_prev;
320 		ticks_slot = *ticks_slot_prev;
321 
322 		if (false) {
323 
324 #if defined(CONFIG_BT_BROADCASTER) && CONFIG_BT_CTLR_ADV_AUX_SET > 0
325 		} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE,
326 				    TICKER_ID_ADV_AUX_LAST)) {
327 			const struct ll_adv_aux_set *aux;
328 
329 			*ticks_anchor += ticks_to_expire;
330 			*ticks_anchor += ticks_slot;
331 
332 			aux = ull_adv_aux_get(ticker_id -
333 					      TICKER_ID_ADV_AUX_BASE);
334 
335 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
336 			if (aux->lll.adv->sync) {
337 				const struct ll_adv_sync_set *sync;
338 
339 				sync = HDR_LLL2ULL(aux->lll.adv->sync);
340 				if (sync->is_started) {
341 					*ticks_anchor += sync->ull.ticks_slot;
342 					*ticks_anchor += HAL_TICKER_US_TO_TICKS(
343 						EVENT_TICKER_RES_MARGIN_US << 1);
344 				}
345 			}
346 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
347 
348 			if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
349 				*ticks_anchor +=
350 					MAX(aux->ull.ticks_active_to_start,
351 					    aux->ull.ticks_prepare_to_start);
352 			}
353 
354 			return 0;
355 
356 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
357 		} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
358 				    TICKER_ID_ADV_SYNC_LAST)) {
359 			*ticks_anchor += ticks_to_expire;
360 			*ticks_anchor += ticks_slot;
361 
362 			if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
363 				const struct ll_adv_sync_set *sync;
364 
365 				sync = ull_adv_sync_get(ticker_id -
366 							TICKER_ID_ADV_SYNC_BASE);
367 				*ticks_anchor +=
368 					MAX(sync->ull.ticks_active_to_start,
369 					    sync->ull.ticks_prepare_to_start);
370 			}
371 
372 			return 0;
373 
374 #if defined(CONFIG_BT_CTLR_ADV_ISO)
375 		} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_ISO_BASE,
376 				    TICKER_ID_ADV_ISO_LAST)) {
377 			*ticks_anchor += ticks_to_expire;
378 			*ticks_anchor += ticks_slot;
379 
380 			if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
381 				const struct ll_adv_iso_set *iso;
382 
383 				iso = ull_adv_iso_get(ticker_id -
384 						      TICKER_ID_ADV_ISO_BASE);
385 				*ticks_anchor +=
386 					MAX(iso->ull.ticks_active_to_start,
387 					    iso->ull.ticks_prepare_to_start);
388 			}
389 
390 			return 0;
391 
392 #endif /* CONFIG_BT_CTLR_ADV_ISO */
393 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
394 #endif /* CONFIG_BT_BROADCASTER && CONFIG_BT_CTLR_ADV_AUX_SET > 0 */
395 
396 #if defined(CONFIG_BT_CONN)
397 		} else if (IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
398 				    TICKER_ID_CONN_LAST)) {
399 			*ticks_anchor += ticks_to_expire;
400 			*ticks_anchor += ticks_slot;
401 
402 			return 0;
403 #endif /* CONFIG_BT_CONN */
404 
405 		}
406 	}
407 
408 	return -ECHILD;
409 }
410 #endif /* (CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER) ||
411 	* CONFIG_BT_CTLR_CENTRAL_ISO
412 	*/
413 
after_match_slot_get(uint8_t user_id,uint32_t ticks_slot_abs,ticker_op_match_func ticker_match_op_cb,ull_hdr_get_func ull_hdr_get_cb_fn,uint32_t * ticks_anchor,uint32_t * ticks_to_expire_match,uint32_t * remainder_match,uint32_t * ticks_slot_match)414 static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
415 				    ticker_op_match_func ticker_match_op_cb,
416 				    ull_hdr_get_func ull_hdr_get_cb_fn,
417 				    uint32_t *ticks_anchor,
418 				    uint32_t *ticks_to_expire_match,
419 				    uint32_t *remainder_match,
420 				    uint32_t *ticks_slot_match)
421 {
422 	uint32_t ticks_to_expire_prev;
423 	uint32_t ticks_slot_abs_prev;
424 	uint32_t ticks_anchor_prev;
425 	uint32_t ticks_to_expire;
426 	uint32_t remainder_prev;
427 	uint32_t remainder;
428 	uint8_t ticker_id_prev;
429 	uint8_t ticker_id;
430 	uint8_t retry;
431 
432 	/* As we may place the event between two other events, ensure there is
433 	 * space for 4 times +/- 16 us jitter. I.e. with 32KHz sleep clock,
434 	 * ~30.517 us after previous event, ~30.517 us before and after current
435 	 * event, and an ~30.517 us before next event. Hence 8 time of ceil
436 	 * value 16 us (30.517 / 2) or 4 times EVENT_TICKER_RES_MARGIN_US.
437 	 */
438 	ticks_slot_abs += HAL_TICKER_US_TO_TICKS(EVENT_TICKER_RES_MARGIN_US << 2);
439 
440 	/* There is a possibility that ticker nodes expire during iterations in
441 	 * this function causing the reference ticks_anchor returned for the
442 	 * found ticker to change. In this case the iterations have to be
443 	 * restarted with the new reference ticks_anchor value.
444 	 * Simultaneous continuous scanning on 1M and Coded PHY, alongwith
445 	 * directed advertising and one other state/role could expire in quick
446 	 * succession, hence have a retry count of 4.
447 	 */
448 	retry = 4U;
449 
450 	/* Initialize variable required for iterations to find a free slot */
451 	ticker_id = ticker_id_prev = TICKER_NULL;
452 	ticks_anchor_prev = 0U;
453 	ticks_to_expire = ticks_to_expire_prev = 0U;
454 	remainder = remainder_prev = 0U;
455 	ticks_slot_abs_prev = 0U;
456 	while (1) {
457 		uint32_t ticks_slot_abs_curr = 0U;
458 		uint32_t ticks_to_expire_normal;
459 		uint32_t volatile ret_cb;
460 		uint32_t ticks_slot;
461 		struct ull_hdr *hdr;
462 		uint32_t ret;
463 		bool success;
464 
465 		ret_cb = TICKER_STATUS_BUSY;
466 #if defined(CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH)
467 		ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR, user_id,
468 					       &ticker_id, ticks_anchor,
469 					       &ticks_to_expire, &remainder,
470 					       NULL, /* lazy */
471 					       ticker_match_op_cb,
472 					       NULL, /* match_op_context */
473 					       ticker_op_cb, (void *)&ret_cb);
474 #else /* !CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
475 		ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR, user_id,
476 					   &ticker_id, ticks_anchor,
477 					   &ticks_to_expire,
478 					   ticker_op_cb, (void *)&ret_cb);
479 #endif /* !CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
480 		if (ret == TICKER_STATUS_BUSY) {
481 			while (ret_cb == TICKER_STATUS_BUSY) {
482 				ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
483 						 user_id);
484 			}
485 		}
486 
487 		/* Using a local variable to address the Coverity rule:
488 		 * Incorrect expression  (ASSERT_SIDE_EFFECT)
489 		 * Argument "ret_cb" of LL_ASSERT() has a side effect
490 		 * because the variable is volatile.  The containing function
491 		 * might work differently in a non-debug build.
492 		 */
493 		success = (ret_cb == TICKER_STATUS_SUCCESS);
494 		LL_ASSERT(success);
495 
496 		/* There is a possibility that tickers expire while we
497 		 * iterate through the active list of tickers, start over with
498 		 * a fresh iteration.
499 		 */
500 		if ((ticker_id_prev != TICKER_NULL) &&
501 		    (*ticks_anchor != ticks_anchor_prev)) {
502 			LL_ASSERT(retry);
503 			retry--;
504 
505 			ticker_id = ticker_id_prev = TICKER_NULL;
506 
507 			continue;
508 		}
509 
510 		/* No more active tickers with slot */
511 		if (ticker_id == TICKER_NULL) {
512 			break;
513 		}
514 
515 #if !defined(CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH)
516 		if (!ticker_match_op_cb(ticker_id, 0, 0, NULL)) {
517 			continue;
518 		}
519 #endif /* CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
520 
521 		hdr = ull_hdr_get_cb_fn(ticker_id, &ticks_slot);
522 		if (!hdr) {
523 			continue;
524 		}
525 
526 		ticks_to_expire_normal = ticks_to_expire;
527 
528 #if defined(CONFIG_BT_CTLR_LOW_LAT)
529 #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
530 		if (hdr->ticks_prepare_to_start & XON_BITMASK) {
531 			const uint32_t ticks_prepare_to_start =
532 				MAX(hdr->ticks_active_to_start,
533 				    hdr->ticks_preempt_to_start);
534 
535 			ticks_slot_abs_curr = hdr->ticks_prepare_to_start &
536 					      ~XON_BITMASK;
537 			ticks_to_expire_normal -= ticks_slot_abs_curr -
538 						  ticks_prepare_to_start;
539 		} else
540 #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
541 		{
542 			const uint32_t ticks_prepare_to_start =
543 				MAX(hdr->ticks_active_to_start,
544 				    hdr->ticks_prepare_to_start);
545 
546 			ticks_slot_abs_curr = ticks_prepare_to_start;
547 		}
548 #endif
549 
550 		ticks_slot_abs_curr += ticks_slot;
551 
552 		if ((ticker_id_prev != TICKER_NULL) &&
553 		    (ticker_ticks_diff_get(ticks_to_expire_normal,
554 					   ticks_to_expire_prev) >
555 		     (ticks_slot_abs_prev + ticks_slot_abs))) {
556 			break;
557 		}
558 
559 		ticks_anchor_prev = *ticks_anchor;
560 		ticker_id_prev = ticker_id;
561 		ticks_to_expire_prev = ticks_to_expire_normal;
562 		remainder_prev = remainder;
563 		ticks_slot_abs_prev = ticks_slot_abs_curr;
564 	}
565 
566 	if (ticker_id_prev != TICKER_NULL) {
567 		*ticks_to_expire_match = ticks_to_expire_prev;
568 		*remainder_match = remainder_prev;
569 		*ticks_slot_match = ticks_slot_abs_prev;
570 	}
571 
572 	return ticker_id_prev;
573 }
574 
ticker_op_cb(uint32_t status,void * param)575 static void ticker_op_cb(uint32_t status, void *param)
576 {
577 	*((uint32_t volatile *)param) = status;
578 }
579 
580 #if (defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)) || \
581 	defined(CONFIG_BT_CTLR_CENTRAL_ISO)
ticker_match_any_op_cb(uint8_t ticker_id,uint32_t ticks_slot,uint32_t ticks_to_expire,void * op_context)582 static bool ticker_match_any_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
583 				   uint32_t ticks_to_expire, void *op_context)
584 {
585 	ARG_UNUSED(ticks_slot);
586 	ARG_UNUSED(ticks_to_expire);
587 	ARG_UNUSED(op_context);
588 
589 	return false ||
590 
591 #if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
592 	       IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE,
593 			TICKER_ID_ADV_AUX_LAST) ||
594 
595 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
596 	       IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
597 			TICKER_ID_ADV_SYNC_LAST) ||
598 
599 #if defined(CONFIG_BT_CTLR_ADV_ISO)
600 	       IN_RANGE(ticker_id, TICKER_ID_ADV_ISO_BASE,
601 			TICKER_ID_ADV_ISO_LAST) ||
602 #endif /* CONFIG_BT_CTLR_ADV_ISO */
603 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
604 #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
605 
606 #if defined(CONFIG_BT_CONN)
607 	       IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
608 			TICKER_ID_CONN_LAST) ||
609 
610 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
611 	       IN_RANGE(ticker_id, TICKER_ID_CONN_ISO_BASE,
612 			TICKER_ID_CONN_ISO_LAST) ||
613 #endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
614 #endif /* CONFIG_BT_CONN */
615 
616 	       false;
617 }
618 #endif /* (CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER) ||
619 	* CONFIG_BT_CTLR_CENTRAL_ISO
620 	*/
621 
622 #if defined(CONFIG_BT_CENTRAL)
ticker_match_cen_op_cb(uint8_t ticker_id,uint32_t ticks_slot,uint32_t ticks_to_expire,void * op_context)623 static bool ticker_match_cen_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
624 				   uint32_t ticks_to_expire, void *op_context)
625 {
626 	ARG_UNUSED(ticks_slot);
627 	ARG_UNUSED(ticks_to_expire);
628 	ARG_UNUSED(op_context);
629 
630 	return IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
631 			TICKER_ID_CONN_LAST) ||
632 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO) && \
633 		(CONFIG_BT_CTLR_CENTRAL_SPACING == 0)
634 	       IN_RANGE(ticker_id, TICKER_ID_CONN_ISO_BASE,
635 			TICKER_ID_CONN_ISO_LAST) ||
636 #endif /* CONFIG_BT_CTLR_CENTRAL_ISO &&
637 	*  (CONFIG_BT_CTLR_CENTRAL_SPACING == 0)
638 	*/
639 	       false;
640 }
641 #endif /* CONFIG_BT_CENTRAL */
642 
ull_hdr_get_cb(uint8_t ticker_id,uint32_t * ticks_slot)643 static struct ull_hdr *ull_hdr_get_cb(uint8_t ticker_id, uint32_t *ticks_slot)
644 {
645 	if (false) {
646 
647 #if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
648 	} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE,
649 		     TICKER_ID_ADV_AUX_LAST)) {
650 		struct ll_adv_aux_set *aux;
651 
652 		aux = ull_adv_aux_get(ticker_id - TICKER_ID_ADV_AUX_BASE);
653 		if (aux) {
654 			if (IS_ENABLED(CONFIG_BT_CTLR_ADV_RESERVE_MAX)) {
655 				uint32_t time_us;
656 
657 				time_us = ull_adv_aux_time_get(aux, PDU_AC_PAYLOAD_SIZE_MAX,
658 							       PDU_AC_PAYLOAD_SIZE_MAX);
659 				*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
660 			} else {
661 				*ticks_slot = aux->ull.ticks_slot;
662 
663 #if defined(CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET) && \
664 	(CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET != 0)
665 				struct ll_adv_sync_set *sync;
666 
667 				sync = HDR_LLL2ULL(aux->lll.adv->sync);
668 				if (sync->ull.ticks_slot > *ticks_slot) {
669 					*ticks_slot = sync->ull.ticks_slot;
670 				}
671 #endif /* CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET */
672 
673 			}
674 
675 			return &aux->ull;
676 		}
677 
678 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
679 	} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
680 		     TICKER_ID_ADV_SYNC_LAST)) {
681 		struct ll_adv_sync_set *sync;
682 
683 		sync = ull_adv_sync_get(ticker_id - TICKER_ID_ADV_SYNC_BASE);
684 		if (sync) {
685 			if (IS_ENABLED(CONFIG_BT_CTLR_ADV_RESERVE_MAX)) {
686 				uint32_t time_us;
687 
688 				time_us = ull_adv_sync_time_get(sync, PDU_AC_PAYLOAD_SIZE_MAX);
689 				*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
690 			} else {
691 				*ticks_slot = sync->ull.ticks_slot;
692 			}
693 
694 			return &sync->ull;
695 		}
696 
697 #if defined(CONFIG_BT_CTLR_ADV_ISO)
698 	} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_ISO_BASE,
699 			    TICKER_ID_ADV_ISO_LAST)) {
700 		struct ll_adv_iso_set *adv_iso;
701 
702 		adv_iso = ull_adv_iso_get(ticker_id - TICKER_ID_ADV_ISO_BASE);
703 		if (adv_iso) {
704 			uint32_t time_us;
705 
706 			time_us = ull_adv_iso_max_time_get(adv_iso);
707 			*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
708 
709 			return &adv_iso->ull;
710 		}
711 
712 #endif /* CONFIG_BT_CTLR_ADV_ISO */
713 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
714 #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
715 
716 #if defined(CONFIG_BT_CONN)
717 	} else if (IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
718 			    TICKER_ID_CONN_LAST)) {
719 		struct ll_conn *conn;
720 
721 		conn = ll_conn_get(ticker_id - TICKER_ID_CONN_BASE);
722 		if (conn && !conn->lll.role) {
723 			if (IS_ENABLED(CONFIG_BT_CTLR_CENTRAL_RESERVE_MAX)) {
724 				uint32_t ready_delay_us;
725 				uint16_t max_tx_time;
726 				uint16_t max_rx_time;
727 				uint32_t time_us;
728 
729 #if defined(CONFIG_BT_CTLR_PHY)
730 				ready_delay_us =
731 					lll_radio_tx_ready_delay_get(conn->lll.phy_tx,
732 								     conn->lll.phy_flags);
733 #else
734 				ready_delay_us =
735 					lll_radio_tx_ready_delay_get(0U, 0U);
736 #endif
737 
738 #if defined(CONFIG_BT_CTLR_PHY_CODED)
739 				max_tx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_TX_MAX,
740 							    PHY_CODED);
741 				max_rx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_RX_MAX,
742 							    PHY_CODED);
743 #else /* !CONFIG_BT_CTLR_PHY_CODED */
744 				max_tx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_TX_MAX,
745 							    PHY_1M);
746 				max_rx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_RX_MAX,
747 							    PHY_1M);
748 #endif /* !CONFIG_BT_CTLR_PHY_CODED */
749 
750 				time_us = EVENT_OVERHEAD_START_US +
751 					  EVENT_OVERHEAD_END_US +
752 					  ready_delay_us +  max_rx_time +
753 					  EVENT_IFS_US + max_tx_time +
754 					  (EVENT_CLOCK_JITTER_US << 1);
755 				*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
756 			} else {
757 				*ticks_slot = conn->ull.ticks_slot;
758 			}
759 
760 			if (*ticks_slot < HAL_TICKER_US_TO_TICKS(CONFIG_BT_CTLR_CENTRAL_SPACING)) {
761 				*ticks_slot =
762 					HAL_TICKER_US_TO_TICKS(CONFIG_BT_CTLR_CENTRAL_SPACING);
763 			}
764 
765 			return &conn->ull;
766 		}
767 
768 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
769 	} else if (IN_RANGE(ticker_id, TICKER_ID_CONN_ISO_BASE,
770 			    TICKER_ID_CONN_ISO_LAST)) {
771 		struct ll_conn_iso_group *cig;
772 
773 		cig = ll_conn_iso_group_get(ticker_id - TICKER_ID_CONN_ISO_BASE);
774 		if (cig) {
775 			*ticks_slot = cig->ull.ticks_slot;
776 
777 			return &cig->ull;
778 		}
779 
780 #endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
781 #endif /* CONFIG_BT_CONN */
782 
783 	}
784 
785 	return NULL;
786 }
787