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 			*ticks_anchor += ticks_to_expire;
328 			*ticks_anchor += ticks_slot;
329 			*ticks_anchor += HAL_TICKER_US_TO_TICKS(
330 				EVENT_TICKER_RES_MARGIN_US << 1);
331 
332 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
333 			const struct ll_adv_aux_set *aux;
334 
335 			aux = ull_adv_aux_get(ticker_id -
336 					      TICKER_ID_ADV_AUX_BASE);
337 			if (aux->lll.adv->sync) {
338 				const struct ll_adv_sync_set *sync;
339 
340 				sync = HDR_LLL2ULL(aux->lll.adv->sync);
341 				if (sync->is_started) {
342 					*ticks_anchor += sync->ull.ticks_slot;
343 					*ticks_anchor += HAL_TICKER_US_TO_TICKS(
344 						EVENT_TICKER_RES_MARGIN_US << 1);
345 				}
346 			}
347 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
348 
349 			return 0;
350 
351 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
352 		} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
353 				    TICKER_ID_ADV_SYNC_LAST)) {
354 			*ticks_anchor += ticks_to_expire;
355 			*ticks_anchor += ticks_slot;
356 			*ticks_anchor += HAL_TICKER_US_TO_TICKS(
357 				EVENT_TICKER_RES_MARGIN_US << 1);
358 
359 			return 0;
360 
361 #if defined(CONFIG_BT_CTLR_ADV_ISO)
362 		} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_ISO_BASE,
363 				    TICKER_ID_ADV_ISO_LAST)) {
364 			*ticks_anchor += ticks_to_expire;
365 			*ticks_anchor += ticks_slot;
366 			*ticks_anchor += HAL_TICKER_US_TO_TICKS(
367 				EVENT_TICKER_RES_MARGIN_US << 1);
368 
369 			return 0;
370 
371 #endif /* CONFIG_BT_CTLR_ADV_ISO */
372 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
373 #endif /* CONFIG_BT_BROADCASTER && CONFIG_BT_CTLR_ADV_AUX_SET > 0 */
374 
375 #if defined(CONFIG_BT_CONN)
376 		} else if (IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
377 				    TICKER_ID_CONN_LAST)) {
378 			*ticks_anchor += ticks_to_expire;
379 			*ticks_anchor += ticks_slot;
380 			*ticks_anchor += HAL_TICKER_US_TO_TICKS(
381 				EVENT_TICKER_RES_MARGIN_US << 1);
382 
383 			return 0;
384 #endif /* CONFIG_BT_CONN */
385 
386 		}
387 	}
388 
389 	return -ECHILD;
390 }
391 #endif /* (CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER) ||
392 	* CONFIG_BT_CTLR_CENTRAL_ISO
393 	*/
394 
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)395 static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
396 				    ticker_op_match_func ticker_match_op_cb,
397 				    ull_hdr_get_func ull_hdr_get_cb_fn,
398 				    uint32_t *ticks_anchor,
399 				    uint32_t *ticks_to_expire_match,
400 				    uint32_t *remainder_match,
401 				    uint32_t *ticks_slot_match)
402 {
403 	uint32_t ticks_to_expire_prev;
404 	uint32_t ticks_slot_abs_prev;
405 	uint32_t ticks_anchor_prev;
406 	uint32_t ticks_to_expire;
407 	uint32_t remainder_prev;
408 	uint32_t remainder;
409 	uint8_t ticker_id_prev;
410 	uint8_t ticker_id;
411 	uint8_t retry;
412 
413 	/* As we may place the event between two other events, ensure there is
414 	 * space for 4 times +/- 16 us jitter. I.e. with 32KHz sleep clock,
415 	 * ~30.517 us after previous event, ~30.517 us before and after current
416 	 * event, and an ~30.517 us before next event. Hence 8 time of ceil
417 	 * value 16 us (30.517 / 2) or 4 times EVENT_TICKER_RES_MARGIN_US.
418 	 */
419 	ticks_slot_abs += HAL_TICKER_US_TO_TICKS(EVENT_TICKER_RES_MARGIN_US << 2);
420 
421 	/* There is a possibility that ticker nodes expire during iterations in
422 	 * this function causing the reference ticks_anchor returned for the
423 	 * found ticker to change. In this case the iterations have to be
424 	 * restarted with the new reference ticks_anchor value.
425 	 * Simultaneous continuous scanning on 1M and Coded PHY, alongwith
426 	 * directed advertising and N other state/role could expire in quick
427 	 * succession, hence have a retry count of UINT8_MAX, which is possible
428 	 * maximum implementation limit for ticker nodes.
429 	 */
430 	retry = UINT8_MAX;
431 
432 	/* Initialize variable required for iterations to find a free slot */
433 	ticker_id = ticker_id_prev = TICKER_NULL;
434 	ticks_anchor_prev = 0U;
435 	ticks_to_expire = ticks_to_expire_prev = 0U;
436 	remainder = remainder_prev = 0U;
437 	ticks_slot_abs_prev = 0U;
438 	while (1) {
439 		uint32_t ticks_slot_abs_curr = 0U;
440 		uint32_t ticks_to_expire_normal;
441 		uint32_t volatile ret_cb;
442 		uint32_t ticks_slot;
443 		struct ull_hdr *hdr;
444 		uint32_t ret;
445 		bool success;
446 
447 		ret_cb = TICKER_STATUS_BUSY;
448 #if defined(CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH)
449 		ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR, user_id,
450 					       &ticker_id, ticks_anchor,
451 					       &ticks_to_expire, &remainder,
452 					       NULL, /* lazy */
453 					       ticker_match_op_cb,
454 					       NULL, /* match_op_context */
455 					       ticker_op_cb, (void *)&ret_cb);
456 #else /* !CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
457 		ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR, user_id,
458 					   &ticker_id, ticks_anchor,
459 					   &ticks_to_expire,
460 					   ticker_op_cb, (void *)&ret_cb);
461 #endif /* !CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
462 		if (ret == TICKER_STATUS_BUSY) {
463 			while (ret_cb == TICKER_STATUS_BUSY) {
464 				ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
465 						 user_id);
466 			}
467 		}
468 
469 		/* Using a local variable to address the Coverity rule:
470 		 * Incorrect expression  (ASSERT_SIDE_EFFECT)
471 		 * Argument "ret_cb" of LL_ASSERT() has a side effect
472 		 * because the variable is volatile.  The containing function
473 		 * might work differently in a non-debug build.
474 		 */
475 		success = (ret_cb == TICKER_STATUS_SUCCESS);
476 		LL_ASSERT(success);
477 
478 		/* There is a possibility that tickers expire while we
479 		 * iterate through the active list of tickers, start over with
480 		 * a fresh iteration.
481 		 */
482 		if ((ticker_id_prev != TICKER_NULL) &&
483 		    (*ticks_anchor != ticks_anchor_prev)) {
484 			LL_ASSERT(retry);
485 			retry--;
486 
487 			ticker_id = ticker_id_prev = TICKER_NULL;
488 
489 			continue;
490 		}
491 
492 		/* No more active tickers with slot */
493 		if (ticker_id == TICKER_NULL) {
494 			break;
495 		}
496 
497 #if !defined(CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH)
498 		if (!ticker_match_op_cb(ticker_id, 0, 0, NULL)) {
499 			continue;
500 		}
501 #endif /* CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
502 
503 		hdr = ull_hdr_get_cb_fn(ticker_id, &ticks_slot);
504 		if (!hdr) {
505 			continue;
506 		}
507 
508 		ticks_to_expire_normal = ticks_to_expire;
509 
510 #if defined(CONFIG_BT_CTLR_LOW_LAT)
511 #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
512 		if (hdr->ticks_prepare_to_start & XON_BITMASK) {
513 			const uint32_t ticks_prepare_to_start =
514 				MAX(hdr->ticks_active_to_start,
515 				    hdr->ticks_preempt_to_start);
516 
517 			ticks_slot_abs_curr = hdr->ticks_prepare_to_start &
518 					      ~XON_BITMASK;
519 			ticks_to_expire_normal -= ticks_slot_abs_curr -
520 						  ticks_prepare_to_start;
521 		} else
522 #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
523 		{
524 			const uint32_t ticks_prepare_to_start =
525 				MAX(hdr->ticks_active_to_start,
526 				    hdr->ticks_prepare_to_start);
527 
528 			ticks_slot_abs_curr = ticks_prepare_to_start;
529 		}
530 #endif
531 
532 		ticks_slot_abs_curr += ticks_slot;
533 
534 		if ((ticker_id_prev != TICKER_NULL) &&
535 		    (ticker_ticks_diff_get(ticks_to_expire_normal,
536 					   ticks_to_expire_prev) >
537 		     (ticks_slot_abs_prev + ticks_slot_abs))) {
538 			break;
539 		}
540 
541 		ticks_anchor_prev = *ticks_anchor;
542 		ticker_id_prev = ticker_id;
543 		ticks_to_expire_prev = ticks_to_expire_normal;
544 		remainder_prev = remainder;
545 		ticks_slot_abs_prev = ticks_slot_abs_curr;
546 	}
547 
548 	if (ticker_id_prev != TICKER_NULL) {
549 		*ticks_to_expire_match = ticks_to_expire_prev;
550 		*remainder_match = remainder_prev;
551 		*ticks_slot_match = ticks_slot_abs_prev;
552 	}
553 
554 	return ticker_id_prev;
555 }
556 
ticker_op_cb(uint32_t status,void * param)557 static void ticker_op_cb(uint32_t status, void *param)
558 {
559 	*((uint32_t volatile *)param) = status;
560 }
561 
562 #if (defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)) || \
563 	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)564 static bool ticker_match_any_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
565 				   uint32_t ticks_to_expire, void *op_context)
566 {
567 	ARG_UNUSED(ticks_slot);
568 	ARG_UNUSED(ticks_to_expire);
569 	ARG_UNUSED(op_context);
570 
571 	return false ||
572 
573 #if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
574 	       IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE,
575 			TICKER_ID_ADV_AUX_LAST) ||
576 
577 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
578 	       IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
579 			TICKER_ID_ADV_SYNC_LAST) ||
580 
581 #if defined(CONFIG_BT_CTLR_ADV_ISO)
582 	       IN_RANGE(ticker_id, TICKER_ID_ADV_ISO_BASE,
583 			TICKER_ID_ADV_ISO_LAST) ||
584 #endif /* CONFIG_BT_CTLR_ADV_ISO */
585 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
586 #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
587 
588 #if defined(CONFIG_BT_CONN)
589 	       IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
590 			TICKER_ID_CONN_LAST) ||
591 
592 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
593 	       IN_RANGE(ticker_id, TICKER_ID_CONN_ISO_BASE,
594 			TICKER_ID_CONN_ISO_LAST) ||
595 #endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
596 #endif /* CONFIG_BT_CONN */
597 
598 	       false;
599 }
600 #endif /* (CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER) ||
601 	* CONFIG_BT_CTLR_CENTRAL_ISO
602 	*/
603 
604 #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)605 static bool ticker_match_cen_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
606 				   uint32_t ticks_to_expire, void *op_context)
607 {
608 	ARG_UNUSED(ticks_slot);
609 	ARG_UNUSED(ticks_to_expire);
610 	ARG_UNUSED(op_context);
611 
612 	return IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
613 			TICKER_ID_CONN_LAST) ||
614 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO) && \
615 		(CONFIG_BT_CTLR_CENTRAL_SPACING == 0)
616 	       IN_RANGE(ticker_id, TICKER_ID_CONN_ISO_BASE,
617 			TICKER_ID_CONN_ISO_LAST) ||
618 #endif /* CONFIG_BT_CTLR_CENTRAL_ISO &&
619 	*  (CONFIG_BT_CTLR_CENTRAL_SPACING == 0)
620 	*/
621 	       false;
622 }
623 #endif /* CONFIG_BT_CENTRAL */
624 
ull_hdr_get_cb(uint8_t ticker_id,uint32_t * ticks_slot)625 static struct ull_hdr *ull_hdr_get_cb(uint8_t ticker_id, uint32_t *ticks_slot)
626 {
627 	if (false) {
628 
629 #if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
630 	} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE,
631 		     TICKER_ID_ADV_AUX_LAST)) {
632 		struct ll_adv_aux_set *aux;
633 
634 		aux = ull_adv_aux_get(ticker_id - TICKER_ID_ADV_AUX_BASE);
635 		if (aux) {
636 			if (IS_ENABLED(CONFIG_BT_CTLR_ADV_RESERVE_MAX)) {
637 				uint32_t time_us;
638 
639 				time_us = ull_adv_aux_time_get(aux, PDU_AC_PAYLOAD_SIZE_MAX,
640 							       PDU_AC_PAYLOAD_SIZE_MAX);
641 				*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
642 			} else {
643 				*ticks_slot = aux->ull.ticks_slot;
644 
645 #if defined(CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET) && \
646 	(CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET != 0)
647 				struct ll_adv_sync_set *sync;
648 
649 				sync = HDR_LLL2ULL(aux->lll.adv->sync);
650 				if (sync->ull.ticks_slot > *ticks_slot) {
651 					*ticks_slot = sync->ull.ticks_slot;
652 				}
653 #endif /* CONFIG_BT_CTLR_ADV_AUX_SYNC_OFFSET */
654 
655 			}
656 
657 			return &aux->ull;
658 		}
659 
660 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
661 	} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
662 		     TICKER_ID_ADV_SYNC_LAST)) {
663 		struct ll_adv_sync_set *sync;
664 
665 		sync = ull_adv_sync_get(ticker_id - TICKER_ID_ADV_SYNC_BASE);
666 		if (sync) {
667 			if (IS_ENABLED(CONFIG_BT_CTLR_ADV_RESERVE_MAX)) {
668 				uint32_t time_us;
669 
670 				time_us = ull_adv_sync_time_get(sync, PDU_AC_PAYLOAD_SIZE_MAX);
671 				*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
672 			} else {
673 				*ticks_slot = sync->ull.ticks_slot;
674 			}
675 
676 			return &sync->ull;
677 		}
678 
679 #if defined(CONFIG_BT_CTLR_ADV_ISO)
680 	} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_ISO_BASE,
681 			    TICKER_ID_ADV_ISO_LAST)) {
682 		struct ll_adv_iso_set *adv_iso;
683 
684 		adv_iso = ull_adv_iso_get(ticker_id - TICKER_ID_ADV_ISO_BASE);
685 		if (adv_iso) {
686 			uint32_t time_us;
687 
688 			time_us = ull_adv_iso_max_time_get(adv_iso);
689 			*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
690 
691 			return &adv_iso->ull;
692 		}
693 
694 #endif /* CONFIG_BT_CTLR_ADV_ISO */
695 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
696 #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
697 
698 #if defined(CONFIG_BT_CONN)
699 	} else if (IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
700 			    TICKER_ID_CONN_LAST)) {
701 		struct ll_conn *conn;
702 
703 		conn = ll_conn_get(ticker_id - TICKER_ID_CONN_BASE);
704 		if (conn && !conn->lll.role) {
705 			if (IS_ENABLED(CONFIG_BT_CTLR_CENTRAL_RESERVE_MAX)) {
706 				uint32_t ready_delay_us;
707 				uint16_t max_tx_time;
708 				uint16_t max_rx_time;
709 				uint32_t time_us;
710 
711 #if defined(CONFIG_BT_CTLR_PHY)
712 				ready_delay_us =
713 					lll_radio_tx_ready_delay_get(conn->lll.phy_tx,
714 								     conn->lll.phy_flags);
715 #else
716 				ready_delay_us =
717 					lll_radio_tx_ready_delay_get(0U, 0U);
718 #endif
719 
720 #if defined(CONFIG_BT_CTLR_PHY_CODED)
721 				max_tx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_TX_MAX,
722 							    PHY_CODED);
723 				max_rx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_RX_MAX,
724 							    PHY_CODED);
725 #else /* !CONFIG_BT_CTLR_PHY_CODED */
726 				max_tx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_TX_MAX,
727 							    PHY_1M);
728 				max_rx_time = PDU_DC_MAX_US(LL_LENGTH_OCTETS_RX_MAX,
729 							    PHY_1M);
730 #endif /* !CONFIG_BT_CTLR_PHY_CODED */
731 
732 				time_us = EVENT_OVERHEAD_START_US +
733 					  EVENT_OVERHEAD_END_US +
734 					  ready_delay_us +  max_rx_time +
735 					  EVENT_IFS_US + max_tx_time +
736 					  (EVENT_CLOCK_JITTER_US << 1);
737 				*ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
738 			} else {
739 				*ticks_slot = conn->ull.ticks_slot;
740 			}
741 
742 			if (*ticks_slot < HAL_TICKER_US_TO_TICKS(CONFIG_BT_CTLR_CENTRAL_SPACING)) {
743 				*ticks_slot =
744 					HAL_TICKER_US_TO_TICKS(CONFIG_BT_CTLR_CENTRAL_SPACING);
745 			}
746 
747 			return &conn->ull;
748 		}
749 
750 #if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
751 	} else if (IN_RANGE(ticker_id, TICKER_ID_CONN_ISO_BASE,
752 			    TICKER_ID_CONN_ISO_LAST)) {
753 		struct ll_conn_iso_group *cig;
754 
755 		cig = ll_conn_iso_group_get(ticker_id - TICKER_ID_CONN_ISO_BASE);
756 		if (cig) {
757 			*ticks_slot = cig->ull.ticks_slot;
758 
759 			return &cig->ull;
760 		}
761 
762 #endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
763 #endif /* CONFIG_BT_CONN */
764 
765 	}
766 
767 	return NULL;
768 }
769