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