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 = 0U;
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 = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
184 	} else {
185 		ticks_slot_overhead = 0U;
186 	}
187 
188 	ticks_at_expire = p->ticks_at_expire;
189 	remainder_us = p->remainder;
190 	hal_ticker_remove_jitter(&ticks_at_expire, &remainder_us);
191 
192 	after_cen_offset_get(lll->conn->interval,
193 			     (ticks_slot_overhead + conn->ull.ticks_slot),
194 			     ticks_at_expire, &lll->conn_win_offset_us);
195 	if (lll->conn_win_offset_us) {
196 		lll->conn_win_offset_us +=
197 			HAL_TICKER_TICKS_TO_US(p->ticks_at_expire -
198 					       ticks_at_expire) -
199 			remainder_us;
200 	}
201 }
202 #endif /* CONFIG_BT_CENTRAL */
203 
ull_sched_mfy_win_offset_use(void * param)204 void ull_sched_mfy_win_offset_use(void *param)
205 {
206 	uint32_t ticks_slot_overhead;
207 
208 	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
209 		ticks_slot_overhead = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
210 	} else {
211 		ticks_slot_overhead = 0U;
212 	}
213 
214 	/*
215 	 * TODO: update calculationg of the win_offset
216 	 * when updating the connection update procedure
217 	 * see the legacy code from Zephyr v3.3 for inspiration
218 	 */
219 }
220 
221 #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
ull_sched_mfy_free_win_offset_calc(void * param)222 void ull_sched_mfy_free_win_offset_calc(void *param)
223 {
224 	uint32_t ticks_to_offset_default = 0U;
225 	uint32_t *ticks_to_offset_next;
226 
227 	ticks_to_offset_next = &ticks_to_offset_default;
228 
229 	/*
230 	 * TODO: update when updating the connection update procedure
231 	 * see the legacy code from Zephyr v3.3 for inspiration
232 	 */
233 }
234 
ull_sched_mfy_win_offset_select(void * param)235 void ull_sched_mfy_win_offset_select(void *param)
236 {
237 #define OFFSET_S_MAX 6
238 #define OFFSET_M_MAX 6
239 
240 	/*
241 	 * TODO: update calculation of win_offset when
242 	 * updating the connection update procedure
243 	 * see the legacy code from Zephyr v3.3 for inspiration
244 	 */
245 
246 #undef OFFSET_S_MAX
247 #undef OFFSET_M_MAX
248 }
249 
250 /*
251  * TODO: probably we need a function for calculating the window offset
252  * see the legacy code from Zephyr v3.3 for inspiration
253  */
254 #endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
255 
256 #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)257 static void after_cen_offset_get(uint16_t conn_interval, uint32_t ticks_slot,
258 				 uint32_t ticks_anchor,
259 				 uint32_t *win_offset_us)
260 {
261 	uint32_t ticks_anchor_offset = ticks_anchor;
262 	int err;
263 
264 	err = ull_sched_after_cen_slot_get(TICKER_USER_ID_ULL_LOW, ticks_slot,
265 					   &ticks_anchor_offset,
266 					   win_offset_us);
267 	if (err) {
268 		return;
269 	}
270 
271 	if ((ticks_anchor_offset - ticks_anchor) & BIT(HAL_TICKER_CNTR_MSBIT)) {
272 		*win_offset_us -= HAL_TICKER_TICKS_TO_US(
273 			ticker_ticks_diff_get(ticks_anchor,
274 					      ticks_anchor_offset));
275 	} else {
276 		*win_offset_us += HAL_TICKER_TICKS_TO_US(
277 			ticker_ticks_diff_get(ticks_anchor_offset,
278 					      ticks_anchor));
279 	}
280 
281 	/* Round positive offset value in the future to within one connection
282 	 * interval value.
283 	 * Offsets in the past, value with MSBit set, are handled by caller by
284 	 * adding radio end time and connection interval as necessary to get a
285 	 * window offset in future when establishing a connection.
286 	 */
287 	if ((*win_offset_us & BIT(31)) == 0) {
288 		uint32_t conn_interval_us = conn_interval * CONN_INT_UNIT_US;
289 
290 		while (*win_offset_us > conn_interval_us) {
291 			*win_offset_us -= conn_interval_us;
292 		}
293 	}
294 }
295 #endif /* CONFIG_BT_CENTRAL */
296 #endif /* CONFIG_BT_CONN */
297 
298 #if (defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)) || \
299 	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)300 static int group_free_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
301 			       uint32_t *ticks_to_expire_prev,
302 			       uint32_t *ticks_slot_prev,
303 			       uint32_t *ticks_anchor)
304 {
305 	uint32_t remainder_prev;
306 	uint8_t ticker_id;
307 
308 	ticker_id = after_match_slot_get(user_id, ticks_slot_abs,
309 					 ticker_match_any_op_cb, ull_hdr_get_cb,
310 					 ticks_anchor, ticks_to_expire_prev,
311 					 &remainder_prev, ticks_slot_prev);
312 	if (ticker_id != TICKER_NULL) {
313 		uint32_t ticks_to_expire;
314 		uint32_t ticks_slot;
315 
316 		ticks_to_expire = *ticks_to_expire_prev;
317 		ticks_slot = *ticks_slot_prev;
318 
319 		if (false) {
320 
321 #if defined(CONFIG_BT_BROADCASTER) && CONFIG_BT_CTLR_ADV_AUX_SET > 0
322 		} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE,
323 				    TICKER_ID_ADV_AUX_LAST)) {
324 			*ticks_anchor += ticks_to_expire;
325 			*ticks_anchor += ticks_slot;
326 			*ticks_anchor += HAL_TICKER_US_TO_TICKS(
327 				EVENT_TICKER_RES_MARGIN_US << 1);
328 
329 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
330 			const struct ll_adv_aux_set *aux;
331 
332 			aux = ull_adv_aux_get(ticker_id -
333 					      TICKER_ID_ADV_AUX_BASE);
334 			if (aux->lll.adv->sync) {
335 				const struct ll_adv_sync_set *sync;
336 
337 				sync = HDR_LLL2ULL(aux->lll.adv->sync);
338 				if (sync->is_started) {
339 					*ticks_anchor += sync->ull.ticks_slot;
340 					*ticks_anchor += HAL_TICKER_US_TO_TICKS(
341 						EVENT_TICKER_RES_MARGIN_US << 1);
342 				}
343 			}
344 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
345 
346 			return 0;
347 
348 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
349 		} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
350 				    TICKER_ID_ADV_SYNC_LAST)) {
351 			*ticks_anchor += ticks_to_expire;
352 			*ticks_anchor += ticks_slot;
353 			*ticks_anchor += HAL_TICKER_US_TO_TICKS(
354 				EVENT_TICKER_RES_MARGIN_US << 1);
355 
356 			return 0;
357 
358 #if defined(CONFIG_BT_CTLR_ADV_ISO)
359 		} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_ISO_BASE,
360 				    TICKER_ID_ADV_ISO_LAST)) {
361 			*ticks_anchor += ticks_to_expire;
362 			*ticks_anchor += ticks_slot;
363 			*ticks_anchor += HAL_TICKER_US_TO_TICKS(
364 				EVENT_TICKER_RES_MARGIN_US << 1);
365 
366 			return 0;
367 
368 #endif /* CONFIG_BT_CTLR_ADV_ISO */
369 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
370 #endif /* CONFIG_BT_BROADCASTER && CONFIG_BT_CTLR_ADV_AUX_SET > 0 */
371 
372 #if defined(CONFIG_BT_CONN)
373 		} else if (IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
374 				    TICKER_ID_CONN_LAST)) {
375 			*ticks_anchor += ticks_to_expire;
376 			*ticks_anchor += ticks_slot;
377 			*ticks_anchor += HAL_TICKER_US_TO_TICKS(
378 				EVENT_TICKER_RES_MARGIN_US << 1);
379 
380 			return 0;
381 #endif /* CONFIG_BT_CONN */
382 
383 		}
384 	}
385 
386 	return -ECHILD;
387 }
388 #endif /* (CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER) ||
389 	* CONFIG_BT_CTLR_CENTRAL_ISO
390 	*/
391 
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)392 static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
393 				    ticker_op_match_func ticker_match_op_cb,
394 				    ull_hdr_get_func ull_hdr_get_cb_fn,
395 				    uint32_t *ticks_anchor,
396 				    uint32_t *ticks_to_expire_match,
397 				    uint32_t *remainder_match,
398 				    uint32_t *ticks_slot_match)
399 {
400 	uint32_t ticks_to_expire_prev;
401 	uint32_t ticks_slot_abs_prev;
402 	uint32_t ticks_anchor_prev;
403 	uint32_t ticks_to_expire;
404 	uint32_t remainder_prev;
405 	uint32_t remainder;
406 	uint8_t ticker_id_prev;
407 	uint8_t ticker_id;
408 	uint8_t retry;
409 
410 	/* As we may place the event between two other events, ensure there is
411 	 * space for 4 times +/- 16 us jitter. I.e. with 32KHz sleep clock,
412 	 * ~30.517 us after previous event, ~30.517 us before and after current
413 	 * event, and an ~30.517 us before next event. Hence 8 time of ceil
414 	 * value 16 us (30.517 / 2) or 4 times EVENT_TICKER_RES_MARGIN_US.
415 	 */
416 	ticks_slot_abs += HAL_TICKER_US_TO_TICKS(EVENT_TICKER_RES_MARGIN_US << 2);
417 
418 	/* There is a possibility that ticker nodes expire during iterations in
419 	 * this function causing the reference ticks_anchor returned for the
420 	 * found ticker to change. In this case the iterations have to be
421 	 * restarted with the new reference ticks_anchor value.
422 	 * Simultaneous continuous scanning on 1M and Coded PHY, alongwith
423 	 * directed advertising and N other state/role could expire in quick
424 	 * succession, hence have a retry count of UINT8_MAX, which is possible
425 	 * maximum implementation limit for ticker nodes.
426 	 */
427 	retry = UINT8_MAX;
428 
429 	/* Initialize variable required for iterations to find a free slot */
430 	ticker_id = ticker_id_prev = TICKER_NULL;
431 	ticks_anchor_prev = 0U;
432 	ticks_to_expire = ticks_to_expire_prev = 0U;
433 	remainder = remainder_prev = 0U;
434 	ticks_slot_abs_prev = 0U;
435 	while (1) {
436 		uint32_t ticks_slot_abs_curr = 0U;
437 		uint32_t ticks_to_expire_normal;
438 		uint32_t volatile ret_cb;
439 		uint32_t ticks_slot;
440 		struct ull_hdr *hdr;
441 		uint32_t ret;
442 		bool success;
443 
444 		ret_cb = TICKER_STATUS_BUSY;
445 #if defined(CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH)
446 		ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR, user_id,
447 					       &ticker_id, ticks_anchor,
448 					       &ticks_to_expire, &remainder,
449 					       NULL, /* lazy */
450 					       ticker_match_op_cb,
451 					       NULL, /* match_op_context */
452 					       ticker_op_cb, (void *)&ret_cb);
453 #else /* !CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
454 		ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR, user_id,
455 					   &ticker_id, ticks_anchor,
456 					   &ticks_to_expire,
457 					   ticker_op_cb, (void *)&ret_cb);
458 #endif /* !CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
459 		if (ret == TICKER_STATUS_BUSY) {
460 			while (ret_cb == TICKER_STATUS_BUSY) {
461 				ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
462 						 user_id);
463 			}
464 		}
465 
466 		/* Using a local variable to address the Coverity rule:
467 		 * Incorrect expression  (ASSERT_SIDE_EFFECT)
468 		 * Argument "ret_cb" of LL_ASSERT() has a side effect
469 		 * because the variable is volatile.  The containing function
470 		 * might work differently in a non-debug build.
471 		 */
472 		success = (ret_cb == TICKER_STATUS_SUCCESS);
473 		LL_ASSERT(success);
474 
475 		/* There is a possibility that tickers expire while we
476 		 * iterate through the active list of tickers, start over with
477 		 * a fresh iteration.
478 		 */
479 		if ((ticker_id_prev != TICKER_NULL) &&
480 		    (*ticks_anchor != ticks_anchor_prev)) {
481 			LL_ASSERT(retry);
482 			retry--;
483 
484 			ticker_id = ticker_id_prev = TICKER_NULL;
485 
486 			continue;
487 		}
488 
489 		/* No more active tickers with slot */
490 		if (ticker_id == TICKER_NULL) {
491 			break;
492 		}
493 
494 #if !defined(CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH)
495 		if (!ticker_match_op_cb(ticker_id, 0, 0, NULL)) {
496 			continue;
497 		}
498 #endif /* CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
499 
500 		hdr = ull_hdr_get_cb_fn(ticker_id, &ticks_slot);
501 		if (!hdr) {
502 			continue;
503 		}
504 
505 #if defined(CONFIG_BT_CONN)
506 		/* Consider Peripheral role ticks_slot as available */
507 		if (IN_RANGE(ticker_id, TICKER_ID_CONN_BASE, TICKER_ID_CONN_LAST)) {
508 			const struct ll_conn *conn;
509 
510 			conn = ll_conn_get(ticker_id - TICKER_ID_CONN_BASE);
511 			if (conn && (conn->lll.role == BT_HCI_ROLE_PERIPHERAL)) {
512 				continue;
513 			}
514 		}
515 #endif /* CONFIG_BT_CONN */
516 
517 		ticks_to_expire_normal = ticks_to_expire;
518 
519 #if defined(CONFIG_BT_CTLR_LOW_LAT)
520 		ticks_slot_abs_curr = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
521 #endif
522 
523 		ticks_slot_abs_curr += ticks_slot;
524 
525 		if ((ticker_id_prev != TICKER_NULL) &&
526 		    (ticker_ticks_diff_get(ticks_to_expire_normal,
527 					   ticks_to_expire_prev) >
528 		     (ticks_slot_abs_prev + ticks_slot_abs))) {
529 			break;
530 		}
531 
532 		ticks_anchor_prev = *ticks_anchor;
533 		ticker_id_prev = ticker_id;
534 		ticks_to_expire_prev = ticks_to_expire_normal;
535 		remainder_prev = remainder;
536 		ticks_slot_abs_prev = ticks_slot_abs_curr;
537 	}
538 
539 	if (ticker_id_prev != TICKER_NULL) {
540 		*ticks_to_expire_match = ticks_to_expire_prev;
541 		*remainder_match = remainder_prev;
542 		*ticks_slot_match = ticks_slot_abs_prev;
543 	}
544 
545 	return ticker_id_prev;
546 }
547 
ticker_op_cb(uint32_t status,void * param)548 static void ticker_op_cb(uint32_t status, void *param)
549 {
550 	*((uint32_t volatile *)param) = status;
551 }
552 
553 #if (defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)) || \
554 	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)555 static bool ticker_match_any_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
556 				   uint32_t ticks_to_expire, void *op_context)
557 {
558 	ARG_UNUSED(ticks_slot);
559 	ARG_UNUSED(ticks_to_expire);
560 	ARG_UNUSED(op_context);
561 
562 	return false ||
563 
564 #if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
565 	       IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE,
566 			TICKER_ID_ADV_AUX_LAST) ||
567 
568 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
569 	       IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
570 			TICKER_ID_ADV_SYNC_LAST) ||
571 
572 #if defined(CONFIG_BT_CTLR_ADV_ISO)
573 	       IN_RANGE(ticker_id, TICKER_ID_ADV_ISO_BASE,
574 			TICKER_ID_ADV_ISO_LAST) ||
575 #endif /* CONFIG_BT_CTLR_ADV_ISO */
576 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
577 #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
578 
579 #if defined(CONFIG_BT_CONN)
580 	       IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
581 			TICKER_ID_CONN_LAST) ||
582 
583 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
584 	       IN_RANGE(ticker_id, TICKER_ID_CONN_ISO_BASE,
585 			TICKER_ID_CONN_ISO_LAST) ||
586 #endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
587 #endif /* CONFIG_BT_CONN */
588 
589 	       false;
590 }
591 #endif /* (CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER) ||
592 	* CONFIG_BT_CTLR_CENTRAL_ISO
593 	*/
594 
595 #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)596 static bool ticker_match_cen_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
597 				   uint32_t ticks_to_expire, void *op_context)
598 {
599 	ARG_UNUSED(ticks_slot);
600 	ARG_UNUSED(ticks_to_expire);
601 	ARG_UNUSED(op_context);
602 
603 	return IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
604 			TICKER_ID_CONN_LAST) ||
605 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO) && \
606 		(CONFIG_BT_CTLR_CENTRAL_SPACING == 0)
607 	       IN_RANGE(ticker_id, TICKER_ID_CONN_ISO_BASE,
608 			TICKER_ID_CONN_ISO_LAST) ||
609 #endif /* CONFIG_BT_CTLR_CENTRAL_ISO &&
610 	*  (CONFIG_BT_CTLR_CENTRAL_SPACING == 0)
611 	*/
612 	       false;
613 }
614 #endif /* CONFIG_BT_CENTRAL */
615 
ull_hdr_get_cb(uint8_t ticker_id,uint32_t * ticks_slot)616 static struct ull_hdr *ull_hdr_get_cb(uint8_t ticker_id, uint32_t *ticks_slot)
617 {
618 	if (false) {
619 
620 #if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
621 	} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE,
622 		     TICKER_ID_ADV_AUX_LAST)) {
623 		struct ll_adv_aux_set *aux;
624 
625 		aux = ull_adv_aux_get(ticker_id - TICKER_ID_ADV_AUX_BASE);
626 		if (aux) {
627 			if (IS_ENABLED(CONFIG_BT_CTLR_ADV_RESERVE_MAX)) {
628 				uint32_t time_us;
629 
630 				time_us = ull_adv_aux_time_get(aux, PDU_AC_PAYLOAD_SIZE_MAX,
631 							       PDU_AC_PAYLOAD_SIZE_MAX);
632 				*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
633 			} else {
634 				*ticks_slot = aux->ull.ticks_slot;
635 
636 #if defined(CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET) && \
637 	(CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET != 0)
638 				struct ll_adv_sync_set *sync;
639 
640 				sync = HDR_LLL2ULL(aux->lll.adv->sync);
641 				if (sync->ull.ticks_slot > *ticks_slot) {
642 					*ticks_slot = sync->ull.ticks_slot;
643 				}
644 #endif /* CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET */
645 
646 			}
647 
648 			return &aux->ull;
649 		}
650 
651 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
652 	} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
653 		     TICKER_ID_ADV_SYNC_LAST)) {
654 		struct ll_adv_sync_set *sync;
655 
656 		sync = ull_adv_sync_get(ticker_id - TICKER_ID_ADV_SYNC_BASE);
657 		if (sync) {
658 			if (IS_ENABLED(CONFIG_BT_CTLR_ADV_RESERVE_MAX)) {
659 				uint32_t time_us;
660 
661 				time_us = ull_adv_sync_time_get(sync, PDU_AC_PAYLOAD_SIZE_MAX);
662 				*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
663 			} else {
664 				*ticks_slot = sync->ull.ticks_slot;
665 			}
666 
667 			return &sync->ull;
668 		}
669 
670 #if defined(CONFIG_BT_CTLR_ADV_ISO)
671 	} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_ISO_BASE,
672 			    TICKER_ID_ADV_ISO_LAST)) {
673 		struct ll_adv_iso_set *adv_iso;
674 
675 		adv_iso = ull_adv_iso_get(ticker_id - TICKER_ID_ADV_ISO_BASE);
676 		if (adv_iso) {
677 			uint32_t time_us;
678 
679 			time_us = ull_adv_iso_max_time_get(adv_iso);
680 			*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
681 
682 			return &adv_iso->ull;
683 		}
684 
685 #endif /* CONFIG_BT_CTLR_ADV_ISO */
686 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
687 #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
688 
689 #if defined(CONFIG_BT_CONN)
690 	} else if (IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
691 			    TICKER_ID_CONN_LAST)) {
692 		struct ll_conn *conn;
693 
694 		conn = ll_conn_get(ticker_id - TICKER_ID_CONN_BASE);
695 		if (conn) {
696 			if (IS_ENABLED(CONFIG_BT_CTLR_CENTRAL_RESERVE_MAX) &&
697 			    (conn->lll.role == BT_HCI_ROLE_CENTRAL)) {
698 				uint32_t ready_delay_us;
699 				uint16_t max_tx_time;
700 				uint16_t max_rx_time;
701 				uint32_t time_us;
702 
703 #if defined(CONFIG_BT_CTLR_PHY)
704 				ready_delay_us =
705 					lll_radio_tx_ready_delay_get(conn->lll.phy_tx,
706 								     conn->lll.phy_flags);
707 #else
708 				ready_delay_us =
709 					lll_radio_tx_ready_delay_get(0U, 0U);
710 #endif
711 
712 #if defined(CONFIG_BT_CTLR_PHY_CODED)
713 				max_tx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_TX_MAX,
714 							    PHY_CODED);
715 				max_rx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_RX_MAX,
716 							    PHY_CODED);
717 #else /* !CONFIG_BT_CTLR_PHY_CODED */
718 				max_tx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_TX_MAX,
719 							    PHY_1M);
720 				max_rx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_RX_MAX,
721 							    PHY_1M);
722 #endif /* !CONFIG_BT_CTLR_PHY_CODED */
723 
724 				time_us = EVENT_OVERHEAD_START_US +
725 					  EVENT_OVERHEAD_END_US +
726 					  ready_delay_us +  max_rx_time +
727 					  EVENT_IFS_US + max_tx_time +
728 					  (EVENT_CLOCK_JITTER_US << 1);
729 				*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
730 			} else {
731 				*ticks_slot = conn->ull.ticks_slot;
732 			}
733 
734 			if ((conn->lll.role == BT_HCI_ROLE_CENTRAL) &&
735 			    (*ticks_slot <
736 			     HAL_TICKER_US_TO_TICKS(CONFIG_BT_CTLR_CENTRAL_SPACING))) {
737 				*ticks_slot =
738 					HAL_TICKER_US_TO_TICKS(CONFIG_BT_CTLR_CENTRAL_SPACING);
739 			}
740 
741 			return &conn->ull;
742 		}
743 
744 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
745 	} else if (IN_RANGE(ticker_id, TICKER_ID_CONN_ISO_BASE,
746 			    TICKER_ID_CONN_ISO_LAST)) {
747 		struct ll_conn_iso_group *cig;
748 
749 		cig = ll_conn_iso_group_get(ticker_id - TICKER_ID_CONN_ISO_BASE);
750 		if (cig) {
751 			*ticks_slot = cig->ull.ticks_slot;
752 
753 			return &cig->ull;
754 		}
755 
756 #endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
757 #endif /* CONFIG_BT_CONN */
758 
759 	}
760 
761 	return NULL;
762 }
763