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