1 /*
2 * Copyright (c) 2020 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8
9 #include <zephyr/sys/byteorder.h>
10 #include <zephyr/sys/util.h>
11
12 #include <zephyr/bluetooth/hci_types.h>
13
14 #include "hal/ccm.h"
15 #include "hal/radio.h"
16 #include "hal/ticker.h"
17 #include "hal/radio_df.h"
18
19 #include "util/util.h"
20 #include "util/memq.h"
21 #include "util/dbuf.h"
22 #include "util/mayfly.h"
23
24 #include "pdu_df.h"
25 #include "pdu_vendor.h"
26 #include "pdu.h"
27
28 #include "lll.h"
29 #include "lll_vendor.h"
30 #include "lll_clock.h"
31 #include "lll_filter.h"
32 #include "lll_scan.h"
33 #include "lll_scan_aux.h"
34 #include "lll_df_types.h"
35 #include "lll_df_internal.h"
36 #include "lll_sync.h"
37 #include "lll_sync_iso.h"
38 #include "lll_conn.h"
39 #include "lll_sched.h"
40
41 #include "lll_internal.h"
42 #include "lll_tim_internal.h"
43 #include "lll_prof_internal.h"
44 #include "lll_scan_internal.h"
45 #include "lll_sync_internal.h"
46
47 #include "ll_feat.h"
48
49 #include <soc.h>
50 #include <ull_scan_types.h>
51 #include "hal/debug.h"
52
53 static int init_reset(void);
54 static int prepare_cb(struct lll_prepare_param *p);
55 static int is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb);
56 static void abort_cb(struct lll_prepare_param *prepare_param, void *param);
57 static void isr_done(void *param);
58 static void isr_rx_ull_schedule(void *param);
59 static void isr_rx_lll_schedule(void *param);
60 static void isr_rx(struct lll_scan *lll, struct lll_scan_aux *lll_aux,
61 uint8_t phy_aux);
62 static int isr_rx_pdu(struct lll_scan *lll, struct lll_scan_aux *lll_aux,
63 struct node_rx_pdu *node_rx, struct pdu_adv *pdu,
64 uint8_t phy_aux, uint8_t phy_aux_flags_rx,
65 uint8_t devmatch_ok, uint8_t devmatch_id,
66 uint8_t irkmatch_ok, uint8_t irkmatch_id, uint8_t rl_idx,
67 uint8_t rssi_ready);
68 static void isr_tx_scan_req_ull_schedule(void *param);
69 static void isr_tx_scan_req_lll_schedule(void *param);
70 #if defined(CONFIG_BT_CENTRAL)
71 static void isr_tx_connect_req(void *param);
72 static void isr_rx_connect_rsp(void *param);
73 static bool isr_rx_connect_rsp_check(struct lll_scan *lll,
74 struct pdu_adv *pdu_tx,
75 struct pdu_adv *pdu_rx, uint8_t rl_idx);
76 static void isr_early_abort(void *param);
77 #endif /* CONFIG_BT_CENTRAL */
78
79 static uint16_t trx_cnt; /* TODO: move to a union in lll.c, common to all roles
80 */
81
lll_scan_aux_init(void)82 int lll_scan_aux_init(void)
83 {
84 int err;
85
86 err = init_reset();
87 if (err) {
88 return err;
89 }
90
91 return 0;
92 }
93
lll_scan_aux_reset(void)94 int lll_scan_aux_reset(void)
95 {
96 int err;
97
98 err = init_reset();
99 if (err) {
100 return err;
101 }
102
103 return 0;
104 }
105
lll_scan_aux_prepare(void * param)106 void lll_scan_aux_prepare(void *param)
107 {
108 int err;
109
110 err = lll_hfclock_on();
111 LL_ASSERT(err >= 0);
112
113 err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, param);
114 LL_ASSERT(!err || err == -EINPROGRESS);
115 }
116
lll_scan_aux_setup(struct pdu_adv * pdu,uint8_t pdu_phy,uint8_t pdu_phy_flags_rx,radio_isr_cb_t setup_cb,void * param)117 uint8_t lll_scan_aux_setup(struct pdu_adv *pdu, uint8_t pdu_phy,
118 uint8_t pdu_phy_flags_rx, radio_isr_cb_t setup_cb,
119 void *param)
120 {
121 struct pdu_adv_com_ext_adv *pri_com_hdr;
122 struct pdu_adv_ext_hdr *pri_hdr;
123 struct pdu_adv_aux_ptr *aux_ptr;
124 struct pdu_cte_info *cte_info;
125 struct node_rx_pdu *node_rx;
126 uint32_t window_widening_us;
127 struct node_rx_ftr *ftr;
128 uint16_t window_size_us;
129 uint32_t aux_offset_us;
130 uint32_t overhead_us;
131 uint8_t *pri_dptr;
132 uint32_t pdu_us;
133 uint8_t phy;
134
135 LL_ASSERT(pdu->type == PDU_ADV_TYPE_EXT_IND);
136
137 /* Get reference to extended header */
138 pri_com_hdr = (void *)&pdu->adv_ext_ind;
139 if (unlikely(!pdu->len || !pri_com_hdr->ext_hdr_len)) {
140 return 0U;
141 }
142
143 /* Get reference to flags and contents */
144 pri_hdr = (void *)pri_com_hdr->ext_hdr_adv_data;
145 pri_dptr = pri_hdr->data;
146
147 /* traverse through adv_addr, if present */
148 if (pri_hdr->adv_addr) {
149 pri_dptr += BDADDR_SIZE;
150 }
151
152 /* traverse through tgt_addr, if present */
153 if (pri_hdr->tgt_addr) {
154 pri_dptr += BDADDR_SIZE;
155 }
156
157 /* traverse through cte_info, if present */
158 if (pri_hdr->cte_info) {
159 cte_info = (void *)pri_dptr;
160 pri_dptr += sizeof(struct pdu_cte_info);
161 } else {
162 cte_info = NULL;
163 }
164
165 /* traverse through adi, if present */
166 if (pri_hdr->adi) {
167 pri_dptr += sizeof(struct pdu_adv_adi);
168 }
169
170 /* No need to scan further if no aux_ptr filled */
171 aux_ptr = (void *)pri_dptr;
172 if (unlikely(!pri_hdr->aux_ptr || !PDU_ADV_AUX_PTR_OFFSET_GET(aux_ptr) ||
173 (PDU_ADV_AUX_PTR_PHY_GET(aux_ptr) > EXT_ADV_AUX_PHY_LE_CODED))) {
174 return 0;
175 }
176
177 /* Determine the window size */
178 if (aux_ptr->offs_units) {
179 window_size_us = OFFS_UNIT_300_US;
180 } else {
181 window_size_us = OFFS_UNIT_30_US;
182 }
183
184 /* Calculate the aux offset from start of the scan window */
185 aux_offset_us = (uint32_t)PDU_ADV_AUX_PTR_OFFSET_GET(aux_ptr) * window_size_us;
186
187 /* Skip reception if invalid aux offset */
188 pdu_us = PDU_AC_US(pdu->len, pdu_phy, pdu_phy_flags_rx);
189 if (unlikely(!AUX_OFFSET_IS_VALID(aux_offset_us, window_size_us, pdu_us))) {
190 return 0U;
191 }
192
193 /* Calculate the window widening that needs to be deducted */
194 if (aux_ptr->ca) {
195 window_widening_us = SCA_DRIFT_50_PPM_US(aux_offset_us);
196 } else {
197 window_widening_us = SCA_DRIFT_500_PPM_US(aux_offset_us);
198 }
199
200 phy = BIT(PDU_ADV_AUX_PTR_PHY_GET(aux_ptr));
201
202 /* Calculate the minimum overhead to decide if LLL or ULL scheduling
203 * to be used for auxiliary PDU reception.
204 */
205 overhead_us = PDU_AC_US(pdu->len, pdu_phy, pdu_phy_flags_rx);
206 #if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX)
207 /* Add CTE time if samples are available (8us unit) */
208 /* TODO: check if CTE was actually enabled for rx */
209 if (cte_info && radio_df_iq_samples_amount_get()) {
210 overhead_us += cte_info->time << 3;
211 }
212 #endif
213 overhead_us += radio_rx_chain_delay_get(pdu_phy, pdu_phy_flags_rx);
214 overhead_us += lll_radio_rx_ready_delay_get(phy, PHY_FLAGS_S8);
215 overhead_us += window_widening_us;
216 overhead_us += EVENT_TICKER_RES_MARGIN_US;
217 overhead_us += EVENT_JITTER_US;
218
219 /* CPU execution overhead to setup the radio for reception plus the
220 * minimum prepare tick offset. And allow one additional event in
221 * between as overhead (say, an advertising event in between got closed
222 * when reception for auxiliary PDU is being setup).
223 */
224 overhead_us += (EVENT_OVERHEAD_END_US + EVENT_OVERHEAD_START_US +
225 HAL_TICKER_TICKS_TO_US(HAL_TICKER_CNTR_CMP_OFFSET_MIN)) << 1;
226
227 /* Sufficient offset to ULL schedule the auxiliary PDU scan? */
228 if (aux_offset_us > overhead_us) {
229 return 0;
230 }
231
232 node_rx = ull_pdu_rx_alloc_peek(1);
233 LL_ASSERT(node_rx);
234
235 /* Store the lll context, aux_ptr and start of PDU in footer */
236 ftr = &(node_rx->rx_ftr);
237 ftr->param = param;
238 ftr->aux_ptr = aux_ptr;
239 ftr->radio_end_us = radio_tmr_end_get() -
240 radio_rx_chain_delay_get(pdu_phy,
241 pdu_phy_flags_rx) -
242 pdu_us;
243
244 radio_isr_set(setup_cb, node_rx);
245 radio_disable();
246
247 return 1;
248 }
249
lll_scan_aux_isr_aux_setup(void * param)250 void lll_scan_aux_isr_aux_setup(void *param)
251 {
252 struct pdu_adv_aux_ptr *aux_ptr;
253 struct lll_scan_aux *lll_aux;
254 struct node_rx_pdu *node_rx;
255 uint32_t window_widening_us;
256 uint32_t window_size_us;
257 struct node_rx_ftr *ftr;
258 uint32_t aux_offset_us;
259 uint32_t aux_start_us;
260 struct lll_scan *lll;
261 uint32_t start_us;
262 uint8_t phy_aux;
263 uint32_t hcto;
264
265 lll_isr_status_reset();
266
267 node_rx = param;
268 ftr = &node_rx->rx_ftr;
269 aux_ptr = ftr->aux_ptr;
270 phy_aux = BIT(PDU_ADV_AUX_PTR_PHY_GET(aux_ptr));
271 ftr->aux_phy = phy_aux;
272
273 lll = ull_scan_lll_is_valid_get(ftr->param);
274 if (!lll) {
275 /* param is a scan_aux */
276 lll_aux = ftr->param;
277 lll = ull_scan_aux_lll_parent_get(lll_aux, NULL);
278 } else {
279 lll_aux = NULL;
280 }
281
282 /* Determine the window size */
283 if (aux_ptr->offs_units) {
284 window_size_us = OFFS_UNIT_300_US;
285 } else {
286 window_size_us = OFFS_UNIT_30_US;
287 }
288
289 /* Calculate the aux offset from start of the scan window */
290 aux_offset_us = (uint32_t)PDU_ADV_AUX_PTR_OFFSET_GET(aux_ptr) * window_size_us;
291
292 /* Calculate the window widening that needs to be deducted */
293 if (aux_ptr->ca) {
294 window_widening_us = SCA_DRIFT_50_PPM_US(aux_offset_us);
295 } else {
296 window_widening_us = SCA_DRIFT_500_PPM_US(aux_offset_us);
297 }
298
299 /* Reset Tx/rx count */
300 trx_cnt = 0U;
301
302 /* Setup radio for auxiliary PDU scan */
303 radio_phy_set(phy_aux, PHY_FLAGS_S8);
304 radio_pkt_configure(RADIO_PKT_CONF_LENGTH_8BIT, LL_EXT_OCTETS_RX_MAX,
305 RADIO_PKT_CONF_PHY(phy_aux));
306 lll_chan_set(aux_ptr->chan_idx);
307
308 radio_pkt_rx_set(node_rx->pdu);
309
310 /* Use isr_rx_ull_schedule if already have aux context allocated,
311 * i.e. some previous aux was scheduled from ull already.
312 */
313 if (lll_aux) {
314 radio_isr_set(isr_rx_ull_schedule, lll_aux);
315 } else {
316 radio_isr_set(isr_rx_lll_schedule, node_rx);
317 }
318
319 /* setup tIFS switching */
320 radio_tmr_tifs_set(EVENT_IFS_US);
321 /* TODO: for passive scanning use complete_and_disable */
322 radio_switch_complete_and_tx(phy_aux, 0, phy_aux, 1);
323
324 /* TODO: skip filtering if AdvA was already found in previous PDU */
325
326 if (0) {
327 #if defined(CONFIG_BT_CTLR_PRIVACY)
328 } else if (ull_filter_lll_rl_enabled()) {
329 const struct lll_filter *fal =
330 ull_filter_lll_get((lll->filter_policy &
331 SCAN_FP_FILTER) != 0U);
332 uint8_t count, *irks = ull_filter_lll_irks_get(&count);
333
334 radio_filter_configure(fal->enable_bitmask,
335 fal->addr_type_bitmask,
336 (uint8_t *)fal->bdaddr);
337
338 radio_ar_configure(count, irks, (phy_aux << 2) | BIT(1));
339 #endif /* CONFIG_BT_CTLR_PRIVACY */
340 } else if (IS_ENABLED(CONFIG_BT_CTLR_FILTER_ACCEPT_LIST) && lll->filter_policy) {
341 /* Setup Radio Filter */
342 const struct lll_filter *fal = ull_filter_lll_get(true);
343
344 radio_filter_configure(fal->enable_bitmask,
345 fal->addr_type_bitmask,
346 (uint8_t *)fal->bdaddr);
347 }
348
349 /* Setup radio rx on micro second offset. Note that radio_end_us stores
350 * PDU start time in this case.
351 */
352 aux_start_us = ftr->radio_end_us + aux_offset_us;
353 aux_start_us -= lll_radio_rx_ready_delay_get(phy_aux, PHY_FLAGS_S8);
354 aux_start_us -= window_widening_us;
355 aux_start_us -= EVENT_JITTER_US;
356
357 start_us = radio_tmr_start_us(0, aux_start_us);
358 LL_ASSERT(start_us == (aux_start_us + 1U));
359
360 /* Setup header complete timeout */
361 hcto = start_us;
362 hcto += EVENT_JITTER_US;
363 hcto += window_widening_us;
364 hcto += lll_radio_rx_ready_delay_get(phy_aux, PHY_FLAGS_S8);
365 hcto += window_size_us;
366 hcto += radio_rx_chain_delay_get(phy_aux, PHY_FLAGS_S8);
367 hcto += addr_us_get(phy_aux);
368 radio_tmr_hcto_configure(hcto);
369
370 /* capture end of Rx-ed PDU, extended scan to schedule auxiliary
371 * channel chaining, create connection or to create periodic sync.
372 */
373 radio_tmr_end_capture();
374
375 /* scanner always measures RSSI */
376 radio_rssi_measure();
377
378 #if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN)
379 radio_gpio_lna_setup();
380
381 radio_gpio_pa_lna_enable(start_us +
382 radio_rx_ready_delay_get(phy_aux,
383 PHY_FLAGS_S8) -
384 HAL_RADIO_GPIO_LNA_OFFSET);
385 #endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */
386 }
387
lll_scan_aux_addr_match_get(const struct lll_scan * lll,const struct pdu_adv * pdu,uint8_t * const devmatch_ok,uint8_t * const devmatch_id,uint8_t * const irkmatch_ok,uint8_t * const irkmatch_id)388 bool lll_scan_aux_addr_match_get(const struct lll_scan *lll,
389 const struct pdu_adv *pdu,
390 uint8_t *const devmatch_ok,
391 uint8_t *const devmatch_id,
392 uint8_t *const irkmatch_ok,
393 uint8_t *const irkmatch_id)
394 {
395 const struct pdu_adv_ext_hdr *ext_hdr;
396
397 ext_hdr = &pdu->adv_ext_ind.ext_hdr;
398 if (unlikely(!ext_hdr->adv_addr)) {
399 return false;
400 }
401
402 if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY) && ull_filter_lll_rl_enabled()) {
403 const struct lll_filter *fal =
404 ull_filter_lll_get((lll->filter_policy &
405 SCAN_FP_FILTER) != 0);
406 const uint8_t *adva = &ext_hdr->data[ADVA_OFFSET];
407
408 *devmatch_ok = ull_filter_lll_fal_match(fal, pdu->tx_addr, adva,
409 devmatch_id);
410 if (!*devmatch_ok && pdu->tx_addr) {
411 uint8_t count;
412
413 (void)ull_filter_lll_irks_get(&count);
414 if (count) {
415 *irkmatch_ok = radio_ar_resolve(adva);
416 *irkmatch_id = radio_ar_match_get();
417 }
418 }
419 } else if (IS_ENABLED(CONFIG_BT_CTLR_FILTER_ACCEPT_LIST) &&
420 lll->filter_policy) {
421 const struct lll_filter *fal = ull_filter_lll_get(true);
422 const uint8_t *adva = &ext_hdr->data[ADVA_OFFSET];
423
424 *devmatch_ok = ull_filter_lll_fal_match(fal, pdu->tx_addr, adva,
425 devmatch_id);
426 }
427
428 return true;
429 }
430
init_reset(void)431 static int init_reset(void)
432 {
433 return 0;
434 }
435
prepare_cb(struct lll_prepare_param * p)436 static int prepare_cb(struct lll_prepare_param *p)
437 {
438 struct lll_scan_aux *lll_aux;
439 struct node_rx_pdu *node_rx;
440 uint32_t ticks_at_event;
441 uint32_t ticks_at_start;
442 uint32_t remainder_us;
443 struct lll_scan *lll;
444 struct ull_hdr *ull;
445 uint8_t is_lll_scan;
446 uint32_t remainder;
447 uint32_t hcto;
448 uint32_t ret;
449 uint32_t aa;
450
451 DEBUG_RADIO_START_O(1);
452
453 lll_aux = p->param;
454 lll = ull_scan_aux_lll_parent_get(lll_aux, &is_lll_scan);
455
456 /* Check if this aux scan is for periodic advertising train */
457 if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && !is_lll_scan) {
458 lll_sync_aux_prepare_cb((void *)lll, lll_aux);
459
460 lll = NULL;
461
462 goto sync_aux_prepare_done;
463 }
464
465 #if defined(CONFIG_BT_CENTRAL)
466 /* Check if stopped (on connection establishment race between
467 * LL and ULL.
468 */
469 if (unlikely(lll->is_stop ||
470 (lll->conn &&
471 (lll->conn->central.initiated ||
472 lll->conn->central.cancelled)))) {
473 radio_isr_set(isr_early_abort, lll_aux);
474 radio_disable();
475
476 return 0;
477 }
478 #endif /* CONFIG_BT_CENTRAL */
479
480 /* Initialize scanning state */
481 lll_aux->state = 0U;
482
483 /* Reset Tx/rx count */
484 trx_cnt = 0U;
485
486 /* Start setting up Radio h/w */
487 radio_reset();
488
489 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
490 radio_tx_power_set(lll->tx_pwr_lvl);
491 #else
492 radio_tx_power_set(RADIO_TXP_DEFAULT);
493 #endif
494
495 radio_phy_set(lll_aux->phy, PHY_FLAGS_S8);
496 radio_pkt_configure(RADIO_PKT_CONF_LENGTH_8BIT, LL_EXT_OCTETS_RX_MAX,
497 RADIO_PKT_CONF_PHY(lll_aux->phy));
498
499 node_rx = ull_pdu_rx_alloc_peek(1);
500 LL_ASSERT(node_rx);
501
502 radio_pkt_rx_set(node_rx->pdu);
503
504 aa = sys_cpu_to_le32(PDU_AC_ACCESS_ADDR);
505 radio_aa_set((uint8_t *)&aa);
506 radio_crc_configure(PDU_CRC_POLYNOMIAL,
507 PDU_AC_CRC_IV);
508
509 lll_chan_set(lll_aux->chan);
510
511 radio_isr_set(isr_rx_ull_schedule, lll_aux);
512
513 /* setup tIFS switching */
514 radio_tmr_tifs_set(EVENT_IFS_US);
515 /* TODO: for passive scanning use complete_and_disable */
516 radio_switch_complete_and_tx(lll_aux->phy, 0, lll_aux->phy, 1);
517
518 /* TODO: skip filtering if AdvA was already found in previous PDU */
519
520 if (0) {
521 #if defined(CONFIG_BT_CTLR_PRIVACY)
522 } else if (ull_filter_lll_rl_enabled()) {
523 struct lll_filter *filter =
524 ull_filter_lll_get((lll->filter_policy &
525 SCAN_FP_FILTER) != 0);
526 uint8_t count, *irks = ull_filter_lll_irks_get(&count);
527
528 radio_filter_configure(filter->enable_bitmask,
529 filter->addr_type_bitmask,
530 (uint8_t *) filter->bdaddr);
531
532 radio_ar_configure(count, irks, (lll_aux->phy << 2) | BIT(1));
533 #endif /* CONFIG_BT_CTLR_PRIVACY */
534 } else if (IS_ENABLED(CONFIG_BT_CTLR_FILTER_ACCEPT_LIST) &&
535 lll->filter_policy) {
536 /* Setup Radio Filter */
537 struct lll_filter *fal = ull_filter_lll_get(true);
538
539 radio_filter_configure(fal->enable_bitmask,
540 fal->addr_type_bitmask,
541 (uint8_t *)fal->bdaddr);
542 }
543
544 sync_aux_prepare_done:
545 /* Calculate event timings, coarse and fine */
546 ticks_at_event = p->ticks_at_expire;
547 ull = HDR_LLL2ULL(lll_aux);
548 ticks_at_event += lll_event_offset_get(ull);
549
550 ticks_at_start = ticks_at_event;
551 ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
552
553 remainder = p->remainder;
554 remainder_us = radio_tmr_start(0, ticks_at_start, remainder);
555
556 hcto = remainder_us + lll_aux->window_size_us;
557 hcto += radio_rx_ready_delay_get(lll_aux->phy, PHY_FLAGS_S8);
558 hcto += addr_us_get(lll_aux->phy);
559 hcto += radio_rx_chain_delay_get(lll_aux->phy, PHY_FLAGS_S8);
560 radio_tmr_hcto_configure(hcto);
561
562 /* capture end of Rx-ed PDU, extended scan to schedule auxiliary
563 * channel chaining, create connection or to create periodic sync.
564 */
565 radio_tmr_end_capture();
566
567 /* scanner always measures RSSI */
568 radio_rssi_measure();
569
570 #if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN)
571 radio_gpio_lna_setup();
572
573 radio_gpio_pa_lna_enable(remainder_us +
574 radio_rx_ready_delay_get(lll_aux->phy,
575 PHY_FLAGS_S8) -
576 HAL_RADIO_GPIO_LNA_OFFSET);
577 #endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */
578
579 #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
580 (EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
581 uint32_t overhead;
582
583 #if defined(CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS)
584 overhead = lll_preempt_calc(ull, TICKER_ID_SCAN_AUX, ticks_at_event);
585 #else /* !CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS */
586 overhead = lll_preempt_calc(ull, (TICKER_ID_SCAN_AUX_BASE +
587 ull_scan_aux_lll_handle_get(lll_aux)), ticks_at_event);
588 #endif /* !CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS */
589 /* check if preempt to start has changed */
590 if (overhead) {
591 LL_ASSERT_OVERHEAD(overhead);
592
593 radio_isr_set(isr_done, lll_aux);
594 radio_disable();
595
596 return -ECANCELED;
597 }
598 #endif /* !CONFIG_BT_CTLR_XTAL_ADVANCED */
599
600 #if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
601 /* calc end of group in us for the anchor where next connection
602 * event to be placed.
603 */
604 if (lll && lll->conn) {
605 static memq_link_t link;
606 static struct mayfly mfy_after_cen_offset_get = {
607 0U, 0U, &link, NULL, ull_sched_mfy_after_cen_offset_get};
608
609 /* NOTE: LLL scan instance passed, as done when
610 * establishing legacy connections.
611 */
612 p->param = lll;
613 mfy_after_cen_offset_get.param = p;
614
615 ret = mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_LOW, 1U,
616 &mfy_after_cen_offset_get);
617 LL_ASSERT(!ret);
618 }
619 #endif /* CONFIG_BT_CENTRAL && CONFIG_BT_CTLR_SCHED_ADVANCED */
620
621 ret = lll_prepare_done(lll_aux);
622 LL_ASSERT(!ret);
623
624 DEBUG_RADIO_START_O(1);
625
626 return 0;
627 }
628
is_abort_cb(void * next,void * curr,lll_prepare_cb_t * resume_cb)629 static int is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb)
630 {
631 struct lll_scan *lll;
632
633 /* Auxiliary context shall not resume when being preempted, i.e. they
634 * shall not use -EAGAIN as return value.
635 */
636 ARG_UNUSED(resume_cb);
637
638 /* Auxiliary event shall not overlap as they are not periodically
639 * scheduled.
640 */
641 LL_ASSERT(next != curr);
642
643 lll = ull_scan_lll_is_valid_get(next);
644 if (lll) {
645 /* Next event is scan context, let the current auxiliary scan
646 * continue.
647 */
648 return 0;
649 }
650
651 /* Yield current auxiliary event to other than scan events */
652 return -ECANCELED;
653 }
654
abort_cb(struct lll_prepare_param * prepare_param,void * param)655 static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
656 {
657 struct event_done_extra *e;
658 int err;
659
660 /* NOTE: This is not a prepare being cancelled */
661 if (!prepare_param) {
662 /* Perform event abort here.
663 * After event has been cleanly aborted, clean up resources
664 * and dispatch event done.
665 */
666 radio_isr_set(isr_done, param);
667 radio_disable();
668 return;
669 }
670
671 /* NOTE: Else clean the top half preparations of the aborted event
672 * currently in preparation pipeline.
673 */
674 err = lll_hfclock_off();
675 LL_ASSERT(err >= 0);
676
677 e = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN_AUX);
678 LL_ASSERT(e);
679
680 #if defined(CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS)
681 e->lll = param;
682 #endif /* CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS */
683
684 lll_done(param);
685 }
686
isr_done(void * param)687 static void isr_done(void *param)
688 {
689 struct lll_sync *lll;
690 uint8_t is_lll_scan;
691
692 lll_isr_status_reset();
693
694 if (param) {
695 lll = ull_scan_aux_lll_parent_get(param, &is_lll_scan);
696 } else {
697 lll = NULL;
698 }
699
700 /* Check if this aux scan is for periodic advertising train */
701 if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && lll && !is_lll_scan) {
702 struct node_rx_pdu *node_rx;
703
704 /* Generate message to release aux context and flag the report
705 * generated thereafter by HCI as incomplete.
706 */
707 node_rx = ull_pdu_rx_alloc();
708 LL_ASSERT(node_rx);
709
710 node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE;
711
712 node_rx->rx_ftr.param = lll;
713 node_rx->rx_ftr.aux_failed = 1U;
714
715 ull_rx_put_sched(node_rx->hdr.link, node_rx);
716
717 } else if (!trx_cnt) {
718 struct event_done_extra *e;
719
720 e = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN_AUX);
721 LL_ASSERT(e);
722
723 #if defined(CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS)
724 e->lll = param;
725 #endif /* CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS */
726 }
727
728 lll_isr_cleanup(param);
729 }
730
isr_rx_ull_schedule(void * param)731 static void isr_rx_ull_schedule(void *param)
732 {
733 struct lll_scan_aux *lll_aux;
734 struct lll_scan *lll;
735
736 lll_aux = param;
737 lll = ull_scan_aux_lll_parent_get(lll_aux, NULL);
738
739 isr_rx(lll, lll_aux, lll_aux->phy);
740 }
741
isr_rx_lll_schedule(void * param)742 static void isr_rx_lll_schedule(void *param)
743 {
744 struct node_rx_pdu *node_rx;
745 struct lll_scan *lll;
746 uint8_t phy_aux;
747
748 node_rx = param;
749 lll = node_rx->rx_ftr.param;
750 phy_aux = node_rx->rx_ftr.aux_phy; /* PHY remembered in node rx */
751
752 /* scan context has used LLL scheduling for aux reception */
753 if (lll->is_aux_sched) {
754 isr_rx(lll, NULL, phy_aux);
755 } else {
756 /* `lll->lll_aux` would be allocated in ULL for LLL scheduled
757 * auxiliary PDU reception by scan context and for case
758 * where LLL scheduled chain PDU reception by aux context, it
759 * is assigned with the current aux context's LLL context.
760 */
761 isr_rx(lll, lll->lll_aux, phy_aux);
762 }
763 }
764
isr_rx(struct lll_scan * lll,struct lll_scan_aux * lll_aux,uint8_t phy_aux)765 static void isr_rx(struct lll_scan *lll, struct lll_scan_aux *lll_aux,
766 uint8_t phy_aux)
767 {
768 struct node_rx_pdu *node_rx;
769 uint8_t phy_aux_flags_rx;
770 uint8_t devmatch_ok;
771 uint8_t devmatch_id;
772 uint8_t irkmatch_ok;
773 uint8_t irkmatch_id;
774 struct pdu_adv *pdu;
775 uint8_t rssi_ready;
776 uint8_t trx_done;
777 uint8_t crc_ok;
778 uint8_t rl_idx;
779 bool has_adva;
780 int err;
781
782 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
783 lll_prof_latency_capture();
784 }
785
786 /* Read radio status and events */
787 trx_done = radio_is_done();
788 if (trx_done) {
789 crc_ok = radio_crc_is_valid();
790 devmatch_ok = radio_filter_has_match();
791 devmatch_id = radio_filter_match_get();
792 if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY)) {
793 irkmatch_ok = radio_ar_has_match();
794 irkmatch_id = radio_ar_match_get();
795 } else {
796 irkmatch_ok = 0U;
797 irkmatch_id = FILTER_IDX_NONE;
798 }
799 rssi_ready = radio_rssi_is_ready();
800 phy_aux_flags_rx = radio_phy_flags_rx_get();
801 } else {
802 crc_ok = devmatch_ok = irkmatch_ok = rssi_ready =
803 phy_aux_flags_rx = 0U;
804 devmatch_id = irkmatch_id = FILTER_IDX_NONE;
805 }
806
807 /* Clear radio rx status and events */
808 lll_isr_rx_status_reset();
809
810 /* No Rx */
811 if (unlikely(!trx_done || !crc_ok)) {
812 /* TODO: Combine the early exit with above if-then-else block
813 */
814 err = -EINVAL;
815
816 goto isr_rx_do_close;
817 }
818
819 node_rx = ull_pdu_rx_alloc_peek(3);
820 if (!node_rx) {
821 err = -ENOBUFS;
822
823 goto isr_rx_do_close;
824 }
825
826 pdu = (void *)node_rx->pdu;
827 if (unlikely((pdu->type != PDU_ADV_TYPE_EXT_IND) || !pdu->len)) {
828 err = -EINVAL;
829
830 goto isr_rx_do_close;
831 }
832
833 has_adva = lll_scan_aux_addr_match_get(lll, pdu, &devmatch_ok,
834 &devmatch_id, &irkmatch_ok,
835 &irkmatch_id);
836
837 #if defined(CONFIG_BT_CTLR_PRIVACY)
838 rl_idx = devmatch_ok ?
839 ull_filter_lll_rl_idx(((lll->filter_policy &
840 SCAN_FP_FILTER) != 0U),
841 devmatch_id) :
842 irkmatch_ok ? ull_filter_lll_rl_irk_idx(irkmatch_id) :
843 FILTER_IDX_NONE;
844 #else
845 rl_idx = FILTER_IDX_NONE;
846 #endif /* CONFIG_BT_CTLR_PRIVACY */
847
848 if (has_adva) {
849 bool allow;
850
851 allow = lll_scan_isr_rx_check(lll, irkmatch_ok, devmatch_ok,
852 rl_idx);
853 if (false) {
854 #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) && \
855 defined(CONFIG_BT_CTLR_FILTER_ACCEPT_LIST)
856 } else if (allow || lll->is_sync) {
857 devmatch_ok = allow ? 1U : 0U;
858 #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC && CONFIG_BT_CTLR_FILTER_ACCEPT_LIST */
859 } else if (!allow) {
860 err = -EINVAL;
861
862 goto isr_rx_do_close;
863 }
864 }
865
866 err = isr_rx_pdu(lll, lll_aux, node_rx, pdu, phy_aux, phy_aux_flags_rx,
867 devmatch_ok, devmatch_id, irkmatch_ok, irkmatch_ok,
868 rl_idx, rssi_ready);
869 if (!err) {
870 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
871 lll_prof_send();
872 }
873
874 return;
875 }
876
877 isr_rx_do_close:
878 if (lll_aux) {
879 radio_isr_set(isr_done, lll_aux);
880 } else {
881 /* Send message to flush Auxiliary PDU list */
882 if (lll->is_aux_sched && err != -ECANCELED) {
883 struct node_rx_pdu *node_rx2;
884
885 node_rx2 = ull_pdu_rx_alloc();
886 LL_ASSERT(node_rx2);
887
888 node_rx2->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE;
889
890 /* Use LLL scan context pointer which will be resolved
891 * to LLL aux context in the `ull_scan_aux_release`
892 * function in ULL execution context.
893 * As ULL execution context is the one assigning the
894 * `lll->lll_aux`, if it has not been assigned then
895 * `ull_scan_aux_release` will not dereference it, but
896 * under race, if ULL execution did assign one, it will
897 * free it.
898 */
899 node_rx2->rx_ftr.param = lll;
900
901 ull_rx_put_sched(node_rx2->hdr.link, node_rx2);
902 }
903
904 /* Check if LLL scheduled auxiliary PDU reception by scan
905 * context or auxiliary PDU reception by aux context
906 */
907 if (lll->is_aux_sched) {
908 lll->is_aux_sched = 0U;
909
910 /* Go back to resuming primary channel scanning */
911 radio_isr_set(lll_scan_isr_resume, lll);
912 } else {
913 /* auxiliary channel radio event done */
914 radio_isr_set(isr_done, lll->lll_aux);
915 }
916 }
917 radio_disable();
918 }
919
isr_rx_pdu(struct lll_scan * lll,struct lll_scan_aux * lll_aux,struct node_rx_pdu * node_rx,struct pdu_adv * pdu,uint8_t phy_aux,uint8_t phy_aux_flags_rx,uint8_t devmatch_ok,uint8_t devmatch_id,uint8_t irkmatch_ok,uint8_t irkmatch_id,uint8_t rl_idx,uint8_t rssi_ready)920 static int isr_rx_pdu(struct lll_scan *lll, struct lll_scan_aux *lll_aux,
921 struct node_rx_pdu *node_rx, struct pdu_adv *pdu,
922 uint8_t phy_aux, uint8_t phy_aux_flags_rx,
923 uint8_t devmatch_ok, uint8_t devmatch_id,
924 uint8_t irkmatch_ok, uint8_t irkmatch_id, uint8_t rl_idx,
925 uint8_t rssi_ready)
926 {
927 struct node_rx_ftr *ftr;
928
929 bool dir_report = false;
930
931 if (0) {
932 #if defined(CONFIG_BT_CENTRAL)
933 /* Initiator */
934 } else if (lll->conn && !lll->conn->central.cancelled &&
935 (pdu->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_CONN) &&
936 lll_scan_ext_tgta_check(lll, false, true, pdu,
937 rl_idx, NULL)) {
938 struct lll_scan_aux *lll_aux_to_use;
939 struct node_rx_pdu *rx;
940 struct pdu_adv *pdu_tx;
941 uint32_t conn_space_us;
942 struct ull_hdr *ull;
943 uint32_t pdu_end_us;
944 uint8_t init_tx_addr;
945 uint8_t *init_addr;
946 #if defined(CONFIG_BT_CTLR_PRIVACY)
947 bt_addr_t *lrpa;
948 #endif /* CONFIG_BT_CTLR_PRIVACY */
949
950 if (!lll_aux) {
951 lll_aux_to_use = lll->lll_aux;
952 } else {
953 lll_aux_to_use = lll_aux;
954 }
955
956 if (!lll_aux_to_use) {
957 /* Return -ECHILD, as ULL execution has not yet assigned
958 * an aux context. This can happen only under LLL
959 * scheduling where in LLL auxiliary channel PDU
960 * reception is spawn from LLL primary channel scanning
961 * and on completion will join back to resume primary
962 * channel PDU scanning.
963 */
964 return -ECHILD;
965 }
966
967 /* Always use CSA#2 on secondary channel, we need 2 nodes for conn
968 * and CSA#2 events and 2 nodes are always reserved for connection.
969 */
970 rx = ull_pdu_rx_alloc_peek(4);
971 if (!rx) {
972 return -ENOBUFS;
973 }
974
975 pdu_end_us = radio_tmr_end_get();
976 if (!lll->ticks_window) {
977 uint32_t scan_interval_us;
978
979 /* FIXME: is this correct for continuous scanning? */
980 scan_interval_us = lll->interval * SCAN_INT_UNIT_US;
981 pdu_end_us %= scan_interval_us;
982 }
983
984 /* AUX_CONNECT_REQ is the same as CONNECT_IND */
985 const uint8_t aux_connect_req_len =
986 sizeof(struct pdu_adv_connect_ind);
987 /* AUX_CONNECT_RSP has only AdvA and TargetA in extended common
988 * header
989 */
990 const uint8_t aux_connect_rsp_len =
991 PDU_AC_EXT_HEADER_SIZE_MIN +
992 sizeof(struct pdu_adv_ext_hdr) +
993 ADVA_SIZE + TARGETA_SIZE;
994
995 ull = HDR_LLL2ULL(lll);
996 if (pdu_end_us > (HAL_TICKER_TICKS_TO_US(ull->ticks_slot) -
997 EVENT_IFS_US -
998 PDU_AC_MAX_US(aux_connect_req_len, phy_aux) -
999 EVENT_IFS_US -
1000 PDU_AC_MAX_US(aux_connect_rsp_len, phy_aux) -
1001 EVENT_OVERHEAD_START_US -
1002 EVENT_TICKER_RES_MARGIN_US)) {
1003 return -ETIME;
1004 }
1005
1006 #if defined(CONFIG_BT_CTLR_PRIVACY)
1007 lrpa = ull_filter_lll_lrpa_get(rl_idx);
1008 if (lll->rpa_gen && lrpa) {
1009 init_tx_addr = 1;
1010 init_addr = lrpa->val;
1011 } else {
1012 #else
1013 if (1) {
1014 #endif
1015 init_tx_addr = lll->init_addr_type;
1016 init_addr = lll->init_addr;
1017 }
1018
1019 pdu_tx = radio_pkt_scratch_get();
1020
1021 lll_scan_prepare_connect_req(lll, pdu_tx, phy_aux,
1022 phy_aux_flags_rx, pdu->tx_addr,
1023 pdu->adv_ext_ind.ext_hdr.data,
1024 init_tx_addr, init_addr,
1025 &conn_space_us);
1026
1027 radio_pkt_tx_set(pdu_tx);
1028
1029 /* assert if radio packet ptr is not set and radio started tx */
1030 LL_ASSERT(!radio_is_ready());
1031
1032 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1033 lll_prof_cputime_capture();
1034 }
1035
1036 /* capture end of Tx-ed PDU, used to calculate HCTO. */
1037 radio_tmr_end_capture();
1038
1039 radio_tmr_tifs_set(EVENT_IFS_US);
1040 radio_switch_complete_and_rx(phy_aux);
1041 radio_isr_set(isr_tx_connect_req, lll_aux_to_use);
1042
1043 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
1044 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1045 /* PA/LNA enable is overwriting packet end
1046 * used in ISR profiling, hence back it up
1047 * for later use.
1048 */
1049 lll_prof_radio_end_backup();
1050 }
1051 radio_gpio_pa_setup();
1052 radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
1053 EVENT_IFS_US -
1054 radio_rx_chain_delay_get(phy_aux,
1055 phy_aux_flags_rx) -
1056 HAL_RADIO_GPIO_PA_OFFSET);
1057 #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */
1058
1059 #if defined(CONFIG_BT_CTLR_CONN_RSSI)
1060 if (rssi_ready) {
1061 lll->conn->rssi_latest = radio_rssi_get();
1062 }
1063 #endif /* CONFIG_BT_CTLR_CONN_RSSI */
1064
1065 /* block CPU so that there is no CRC error on pdu tx,
1066 * this is only needed if we want the CPU to sleep.
1067 * while(!radio_has_disabled())
1068 * {cpu_sleep();}
1069 * radio_status_reset();
1070 */
1071
1072 /* Stop further connection initiation */
1073 lll->conn->central.initiated = 1U;
1074
1075 /* Stop further initiating events */
1076 lll->is_stop = 1U;
1077
1078 /* Populate the connection complete message */
1079 rx = ull_pdu_rx_alloc();
1080 rx->hdr.type = NODE_RX_TYPE_CONNECTION;
1081 rx->hdr.handle = 0xffff;
1082
1083 (void)memcpy(rx->pdu, pdu_tx,
1084 (offsetof(struct pdu_adv, connect_ind) +
1085 sizeof(struct pdu_adv_connect_ind)));
1086
1087 /* ChSel is RFU in AUX_ADV_IND but we do need to use CSA#2 for
1088 * connections initiated on the secondary advertising channel
1089 * thus overwrite chan_sel to make it work seamlessly.
1090 */
1091 pdu = (void *)rx->pdu;
1092 pdu->chan_sel = 1;
1093
1094 ftr = &(rx->rx_ftr);
1095 ftr->param = lll;
1096 ftr->ticks_anchor = radio_tmr_start_get();
1097 ftr->radio_end_us = conn_space_us;
1098
1099 #if defined(CONFIG_BT_CTLR_PRIVACY)
1100 ftr->rl_idx = irkmatch_ok ? rl_idx : FILTER_IDX_NONE;
1101 ftr->lrpa_used = lll->rpa_gen && lrpa;
1102 #endif /* CONFIG_BT_CTLR_PRIVACY */
1103
1104 ftr->extra = ull_pdu_rx_alloc();
1105
1106 /* Hold onto connection event message until after successful
1107 * reception of CONNECT_RSP
1108 */
1109 lll_aux_to_use->node_conn_rx = rx;
1110
1111 /* Increase trx count so as to not generate done extra event
1112 * when LLL scheduling of Auxiliary PDU reception
1113 */
1114 if (!lll_aux) {
1115 trx_cnt++;
1116 }
1117
1118 return 0;
1119
1120 /* Active scanner */
1121 } else if (!lll->conn &&
1122 lll->type &&
1123 ((lll_aux && !lll_aux->state) ||
1124 (lll->lll_aux && !lll->lll_aux->state)) &&
1125 (pdu->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_SCAN) &&
1126 lll_scan_ext_tgta_check(lll, false, false, pdu, rl_idx,
1127 &dir_report)) {
1128 #else /* !CONFIG_BT_CENTRAL */
1129 } else if (lll && lll->type &&
1130 ((lll_aux && !lll_aux->state) ||
1131 (lll->lll_aux && !lll->lll_aux->state)) &&
1132 (pdu->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_SCAN) &&
1133 lll_scan_ext_tgta_check(lll, false, false, pdu, rl_idx,
1134 &dir_report)) {
1135 #endif /* !CONFIG_BT_CENTRAL */
1136 struct node_rx_pdu *rx;
1137 struct pdu_adv *pdu_tx;
1138 #if defined(CONFIG_BT_CTLR_PRIVACY)
1139 bt_addr_t *lrpa;
1140 #endif /* CONFIG_BT_CTLR_PRIVACY */
1141
1142 /* Check if 4 nodes free, 2 will be utilized for aux PDU and
1143 * scan response PDU; 2 more to ensure connections have them.
1144 */
1145 rx = ull_pdu_rx_alloc_peek(4);
1146 if (!rx) {
1147 return -ENOBUFS;
1148 }
1149
1150 /* setup tIFS switching */
1151 radio_tmr_tifs_set(EVENT_IFS_US);
1152 radio_switch_complete_and_rx(phy_aux);
1153
1154 /* prepare the scan request packet */
1155 pdu_tx = (void *)radio_pkt_scratch_get();
1156 pdu_tx->type = PDU_ADV_TYPE_SCAN_REQ;
1157 pdu_tx->rx_addr = pdu->tx_addr;
1158 pdu_tx->len = sizeof(struct pdu_adv_scan_req);
1159 #if defined(CONFIG_BT_CTLR_PRIVACY)
1160 lrpa = ull_filter_lll_lrpa_get(rl_idx);
1161 if (lll->rpa_gen && lrpa) {
1162 pdu_tx->tx_addr = 1;
1163 (void)memcpy(pdu_tx->scan_req.scan_addr, lrpa->val,
1164 BDADDR_SIZE);
1165 } else {
1166 #else
1167 if (1) {
1168 #endif /* CONFIG_BT_CTLR_PRIVACY */
1169 pdu_tx->tx_addr = lll->init_addr_type;
1170 (void)memcpy(pdu_tx->scan_req.scan_addr, lll->init_addr,
1171 BDADDR_SIZE);
1172 }
1173 (void)memcpy(pdu_tx->scan_req.adv_addr,
1174 &pdu->adv_ext_ind.ext_hdr.data[ADVA_OFFSET],
1175 BDADDR_SIZE);
1176
1177 radio_pkt_tx_set(pdu_tx);
1178
1179 /* assert if radio packet ptr is not set and radio started tx */
1180 LL_ASSERT(!radio_is_ready());
1181
1182 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1183 lll_prof_cputime_capture();
1184 }
1185
1186 /* capture end of Tx-ed PDU, used to calculate HCTO. */
1187 radio_tmr_end_capture();
1188
1189 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
1190 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1191 /* PA/LNA enable is overwriting packet end
1192 * used in ISR profiling, hence back it up
1193 * for later use.
1194 */
1195 lll_prof_radio_end_backup();
1196 }
1197
1198 radio_gpio_pa_setup();
1199 radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
1200 EVENT_IFS_US -
1201 radio_rx_chain_delay_get(phy_aux,
1202 phy_aux_flags_rx) -
1203 HAL_RADIO_GPIO_PA_OFFSET);
1204 #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */
1205
1206 (void)ull_pdu_rx_alloc();
1207
1208 node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_REPORT;
1209
1210 ftr = &(node_rx->rx_ftr);
1211 if (lll_aux) {
1212 ftr->param = lll_aux;
1213 radio_isr_set(isr_tx_scan_req_ull_schedule,
1214 lll_aux);
1215 lll_aux->state = 1U;
1216 } else {
1217 ftr->param = lll;
1218 ftr->lll_aux = lll->lll_aux;
1219 radio_isr_set(isr_tx_scan_req_lll_schedule,
1220 node_rx);
1221 lll->lll_aux->state = 1U;
1222 }
1223 ftr->ticks_anchor = radio_tmr_start_get();
1224 ftr->radio_end_us = radio_tmr_end_get() -
1225 radio_rx_chain_delay_get(phy_aux,
1226 phy_aux_flags_rx);
1227 ftr->rssi = (rssi_ready) ? radio_rssi_get() :
1228 BT_HCI_LE_RSSI_NOT_AVAILABLE;
1229 ftr->scan_req = 1U;
1230 ftr->scan_rsp = 0U;
1231
1232 #if defined(CONFIG_BT_CTLR_PRIVACY)
1233 ftr->rl_idx = irkmatch_ok ? rl_idx : FILTER_IDX_NONE;
1234 #endif /* CONFIG_BT_CTLR_PRIVACY */
1235
1236 #if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
1237 ftr->direct = dir_report;
1238 #endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
1239
1240 #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) && \
1241 defined(CONFIG_BT_CTLR_FILTER_ACCEPT_LIST)
1242 ftr->devmatch = devmatch_ok;
1243 #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC && CONFIG_BT_CTLR_FILTER_ACCEPT_LIST */
1244
1245 ftr->aux_lll_sched = 0U;
1246
1247 ull_rx_put_sched(node_rx->hdr.link, node_rx);
1248
1249 return 0;
1250
1251 /* Passive scanner or scan responses */
1252 #if defined(CONFIG_BT_CENTRAL)
1253 } else if (!lll->conn &&
1254 ((lll_aux && lll_aux->is_chain_sched) ||
1255 (lll->lll_aux && lll->lll_aux->is_chain_sched) ||
1256 lll_scan_ext_tgta_check(lll, false, false, pdu, rl_idx,
1257 &dir_report))) {
1258 #else /* !CONFIG_BT_CENTRAL */
1259 } else if ((lll_aux && lll_aux->is_chain_sched) ||
1260 (lll->lll_aux && lll->lll_aux->is_chain_sched) ||
1261 lll_scan_ext_tgta_check(lll, false, false, pdu, rl_idx,
1262 &dir_report)) {
1263 #endif /* !CONFIG_BT_CENTRAL */
1264
1265 ftr = &(node_rx->rx_ftr);
1266 if (lll_aux) {
1267 /* Auxiliary context was used in ULL scheduling in the
1268 * reception of this current PDU.
1269 */
1270 ftr->param = lll_aux;
1271 ftr->scan_rsp = lll_aux->state;
1272
1273 /* Further auxiliary PDU reception will be chain PDUs */
1274 lll_aux->is_chain_sched = 1U;
1275
1276 /* Reset auxiliary context association with scan context
1277 * as ULL scheduling has been used and may switch to
1278 * using LLL scheduling if the next auxiliary PDU in
1279 * chain is below the threshold to use ULL scheduling.
1280 */
1281 lll->lll_aux = NULL;
1282
1283 } else if (lll->lll_aux) {
1284 /* Auxiliary context was allocated to Scan context in
1285 * LLL scheduling in the reception of this current PDU.
1286 */
1287 ftr->param = lll;
1288 ftr->lll_aux = lll->lll_aux;
1289 ftr->scan_rsp = lll->lll_aux->state;
1290
1291 /* Further auxiliary PDU reception will be chain PDUs */
1292 lll->lll_aux->is_chain_sched = 1U;
1293
1294 } else {
1295 /* Return -ECHILD, as ULL execution has not yet assigned
1296 * an aux context. This can happen only under LLL
1297 * scheduling where in LLL auxiliary channel PDU
1298 * reception is spawn from LLL primary channel scanning
1299 * and on completion will join back to resume primary
1300 * channel PDU scanning.
1301 */
1302 return -ECHILD;
1303 }
1304
1305 /* Allocate before `lll_scan_aux_setup` call, so that a new
1306 * free PDU buffer is used to receive auxiliary PDU when using
1307 * LLL scheduling.
1308 */
1309 (void)ull_pdu_rx_alloc();
1310
1311 ftr->ticks_anchor = radio_tmr_start_get();
1312 ftr->radio_end_us = radio_tmr_end_get() -
1313 radio_rx_chain_delay_get(phy_aux,
1314 phy_aux_flags_rx);
1315 ftr->phy_flags = phy_aux_flags_rx;
1316 ftr->rssi = (rssi_ready) ? radio_rssi_get() :
1317 BT_HCI_LE_RSSI_NOT_AVAILABLE;
1318 ftr->scan_req = 0U;
1319
1320 #if defined(CONFIG_BT_CTLR_PRIVACY)
1321 ftr->rl_idx = irkmatch_ok ? rl_idx : FILTER_IDX_NONE;
1322 #endif /* CONFIG_BT_CTLR_PRIVACY */
1323
1324 #if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
1325 ftr->direct = dir_report;
1326 #endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
1327
1328 #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC) && \
1329 defined(CONFIG_BT_CTLR_FILTER_ACCEPT_LIST)
1330 ftr->devmatch = devmatch_ok;
1331 #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC && CONFIG_BT_CTLR_FILTER_ACCEPT_LIST */
1332
1333 ftr->aux_lll_sched = lll_scan_aux_setup(pdu, phy_aux,
1334 phy_aux_flags_rx,
1335 lll_scan_aux_isr_aux_setup,
1336 lll_aux ? (void *)lll_aux : (void *)lll);
1337
1338 node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_REPORT;
1339
1340 ull_rx_put_sched(node_rx->hdr.link, node_rx);
1341
1342 /* Next aux scan is scheduled from LLL, we already handled radio
1343 * disable so prevent caller from doing it again.
1344 */
1345 if (ftr->aux_lll_sched) {
1346 if (!lll_aux) {
1347 lll->is_aux_sched = 1U;
1348 }
1349
1350 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1351 lll_prof_cputime_capture();
1352 }
1353
1354 return 0;
1355 }
1356
1357 /* Increase trx count so as to not generate done extra event
1358 * as a valid Auxiliary PDU node rx is being reported to ULL.
1359 */
1360 trx_cnt++;
1361
1362 return -ECANCELED;
1363 }
1364
1365 return -EINVAL;
1366 }
1367
1368 static void isr_tx(struct lll_scan_aux *lll_aux, void *pdu_rx,
1369 void (*isr)(void *), void *param)
1370 {
1371 uint32_t hcto;
1372
1373 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1374 lll_prof_latency_capture();
1375 }
1376
1377 /* Clear radio tx status and events */
1378 lll_isr_tx_status_reset();
1379
1380 /* complete the reception and disable radio */
1381 radio_switch_complete_and_disable();
1382
1383 radio_pkt_rx_set(pdu_rx);
1384
1385 /* assert if radio packet ptr is not set and radio started rx */
1386 LL_ASSERT(!radio_is_ready());
1387
1388 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1389 lll_prof_cputime_capture();
1390 }
1391
1392 #if defined(CONFIG_BT_CTLR_PRIVACY)
1393 if (ull_filter_lll_rl_enabled()) {
1394 uint8_t count, *irks = ull_filter_lll_irks_get(&count);
1395
1396 radio_ar_configure(count, irks, (lll_aux->phy << 2) | BIT(1));
1397 }
1398 #endif /* CONFIG_BT_CTLR_PRIVACY */
1399
1400 /* +/- 2us active clock jitter, +1 us PPI to timer start compensation */
1401 hcto = radio_tmr_tifs_base_get() + EVENT_IFS_US +
1402 (EVENT_CLOCK_JITTER_US << 1) + RANGE_DELAY_US +
1403 HAL_RADIO_TMR_START_DELAY_US;
1404 hcto += radio_rx_chain_delay_get(lll_aux->phy, PHY_FLAGS_S8);
1405 hcto += addr_us_get(lll_aux->phy);
1406 hcto -= radio_tx_chain_delay_get(lll_aux->phy, PHY_FLAGS_S8);
1407 radio_tmr_hcto_configure(hcto);
1408
1409 /* capture end of Rx-ed PDU, extended scan to schedule auxiliary
1410 * channel chaining.
1411 */
1412 radio_tmr_end_capture();
1413
1414 /* scanner always measures RSSI */
1415 radio_rssi_measure();
1416
1417 #if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN)
1418 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1419 /* PA/LNA enable is overwriting packet end used in ISR
1420 * profiling, hence back it up for later use.
1421 */
1422 lll_prof_radio_end_backup();
1423 }
1424
1425 radio_gpio_lna_setup();
1426 radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US -
1427 (EVENT_CLOCK_JITTER_US << 1U) -
1428 radio_tx_chain_delay_get(lll_aux->phy,
1429 PHY_FLAGS_S8) -
1430 HAL_RADIO_GPIO_LNA_OFFSET);
1431 #endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */
1432
1433 radio_isr_set(isr, param);
1434
1435 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1436 /* NOTE: as scratch packet is used to receive, it is safe to
1437 * generate profile event using rx nodes.
1438 */
1439 lll_prof_send();
1440 }
1441 }
1442
1443 static void isr_tx_scan_req_ull_schedule(void *param)
1444 {
1445 struct node_rx_pdu *node_rx;
1446
1447 node_rx = ull_pdu_rx_alloc_peek(1);
1448 LL_ASSERT(node_rx);
1449
1450 isr_tx(param, node_rx->pdu, isr_rx_ull_schedule, param);
1451 }
1452
1453 static void isr_tx_scan_req_lll_schedule(void *param)
1454 {
1455 struct node_rx_pdu *node_rx_adv = param;
1456 struct node_rx_pdu *node_rx;
1457 struct lll_scan *lll;
1458
1459 lll = node_rx_adv->rx_ftr.param;
1460
1461 node_rx = ull_pdu_rx_alloc_peek(1);
1462 LL_ASSERT(node_rx);
1463
1464 isr_tx(lll->lll_aux, node_rx->pdu, isr_rx_lll_schedule, param);
1465 }
1466
1467 #if defined(CONFIG_BT_CENTRAL)
1468 static void isr_tx_connect_req(void *param)
1469 {
1470 struct node_rx_pdu *node_rx;
1471
1472 node_rx = ull_pdu_rx_alloc_peek(1);
1473 LL_ASSERT(node_rx);
1474
1475 isr_tx(param, (void *)node_rx->pdu, isr_rx_connect_rsp, param);
1476 }
1477
1478 static void isr_rx_connect_rsp(void *param)
1479 {
1480 struct lll_scan_aux *lll_aux;
1481 uint8_t phy_aux_flags_rx;
1482 struct pdu_adv *pdu_rx;
1483 struct node_rx_pdu *rx;
1484 struct lll_scan *lll;
1485 uint8_t irkmatch_ok;
1486 uint8_t irkmatch_id;
1487 uint8_t trx_done;
1488 uint8_t rl_idx;
1489 uint8_t crc_ok;
1490
1491 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1492 lll_prof_latency_capture();
1493 }
1494
1495 /* Read radio status */
1496 trx_done = radio_is_done();
1497 if (trx_done) {
1498 crc_ok = radio_crc_is_valid();
1499 if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY)) {
1500 irkmatch_ok = radio_ar_has_match();
1501 irkmatch_id = radio_ar_match_get();
1502 } else {
1503 irkmatch_ok = 0U;
1504 irkmatch_id = FILTER_IDX_NONE;
1505 }
1506 phy_aux_flags_rx = radio_phy_flags_rx_get();
1507 } else {
1508 crc_ok = irkmatch_ok = phy_aux_flags_rx = 0U;
1509 irkmatch_id = FILTER_IDX_NONE;
1510 }
1511
1512 /* Clear radio rx status and events */
1513 lll_isr_rx_status_reset();
1514
1515 /* Get the reference to primary scanner's LLL context */
1516 lll_aux = param;
1517 lll = ull_scan_aux_lll_parent_get(lll_aux, NULL);
1518
1519 /* Use the reserved/saved node rx to generate connection complete or
1520 * release it if failed to receive AUX_CONNECT_RSP PDU.
1521 */
1522 rx = lll_aux->node_conn_rx;
1523 LL_ASSERT(rx);
1524 lll_aux->node_conn_rx = NULL;
1525
1526 #if defined(CONFIG_BT_CTLR_PRIVACY)
1527 rl_idx = irkmatch_ok ? ull_filter_lll_rl_irk_idx(irkmatch_id) :
1528 FILTER_IDX_NONE;
1529 #else
1530 rl_idx = FILTER_IDX_NONE;
1531 #endif /* CONFIG_BT_CTLR_PRIVACY */
1532
1533 /* Check for PDU reception */
1534 if (trx_done && crc_ok) {
1535 struct node_rx_pdu *node_rx;
1536 struct pdu_adv *pdu_tx;
1537
1538 pdu_tx = radio_pkt_scratch_get();
1539
1540 node_rx = ull_pdu_rx_alloc_peek(1);
1541 LL_ASSERT(node_rx);
1542 pdu_rx = (void *)node_rx->pdu;
1543
1544 trx_done = isr_rx_connect_rsp_check(lll, pdu_tx, pdu_rx,
1545 rl_idx);
1546 } else {
1547 trx_done = 0U;
1548 }
1549
1550 /* No Rx or invalid PDU received */
1551 if (unlikely(!trx_done)) {
1552 struct node_rx_ftr *ftr;
1553
1554 /* Try again with connection initiation */
1555 lll->conn->central.initiated = 0U;
1556
1557 /* Dont stop initiating events on primary channels */
1558 lll->is_stop = 0U;
1559
1560 ftr = &(rx->rx_ftr);
1561
1562 rx->hdr.type = NODE_RX_TYPE_RELEASE;
1563 ull_rx_put(rx->hdr.link, rx);
1564
1565 rx = ftr->extra;
1566 rx->hdr.type = NODE_RX_TYPE_RELEASE;
1567
1568 goto isr_rx_connect_rsp_do_close;
1569 }
1570
1571 /* Update the max Tx and Rx time; and connection PHY based on the
1572 * extended advertising PHY used to establish the connection.
1573 */
1574 #if defined(CONFIG_BT_CTLR_PHY)
1575 struct lll_conn *conn_lll = lll->conn;
1576
1577 #if defined(CONFIG_BT_CTLR_DATA_LENGTH)
1578 conn_lll->dle.eff.max_tx_time = MAX(conn_lll->dle.eff.max_tx_time,
1579 PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN,
1580 lll_aux->phy));
1581 conn_lll->dle.eff.max_rx_time = MAX(conn_lll->dle.eff.max_rx_time,
1582 PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN,
1583 lll_aux->phy));
1584 #endif /* CONFIG_BT_CTLR_DATA_LENGTH*/
1585
1586 conn_lll->phy_tx = lll_aux->phy;
1587 conn_lll->phy_tx_time = lll_aux->phy;
1588 conn_lll->phy_flags = phy_aux_flags_rx;
1589 conn_lll->phy_rx = lll_aux->phy;
1590 #endif /* CONFIG_BT_CTLR_PHY */
1591
1592 #if defined(CONFIG_BT_CTLR_PRIVACY)
1593 if (irkmatch_ok) {
1594 struct node_rx_ftr *ftr;
1595 struct pdu_adv *pdu;
1596
1597 pdu = (void *)rx->pdu;
1598 pdu->rx_addr = pdu_rx->tx_addr;
1599 (void)memcpy(pdu->connect_ind.adv_addr,
1600 &pdu_rx->adv_ext_ind.ext_hdr.data[ADVA_OFFSET],
1601 BDADDR_SIZE);
1602 ftr = &(rx->rx_ftr);
1603 ftr->rl_idx = rl_idx;
1604 }
1605 #endif /* CONFIG_BT_CTLR_PRIVACY */
1606
1607 isr_rx_connect_rsp_do_close:
1608 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1609 lll_prof_cputime_capture();
1610 }
1611
1612 ull_rx_put_sched(rx->hdr.link, rx);
1613
1614 if (lll->lll_aux) {
1615 struct node_rx_pdu *node_rx;
1616
1617 /* Send message to flush Auxiliary PDU list */
1618 node_rx = ull_pdu_rx_alloc();
1619 LL_ASSERT(node_rx);
1620
1621 node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE;
1622
1623 node_rx->rx_ftr.param = lll->lll_aux;
1624
1625 ull_rx_put_sched(node_rx->hdr.link, node_rx);
1626
1627 radio_isr_set(lll_scan_isr_resume, lll);
1628 } else {
1629 radio_isr_set(isr_done, lll_aux);
1630 }
1631
1632 radio_disable();
1633
1634 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1635 lll_prof_send();
1636 }
1637 }
1638
1639 static bool isr_rx_connect_rsp_check(struct lll_scan *lll,
1640 struct pdu_adv *pdu_tx,
1641 struct pdu_adv *pdu_rx, uint8_t rl_idx)
1642 {
1643 if (unlikely(pdu_rx->type != PDU_ADV_TYPE_AUX_CONNECT_RSP)) {
1644 return false;
1645 }
1646
1647 if (unlikely(pdu_rx->len != (offsetof(struct pdu_adv_com_ext_adv, ext_hdr_adv_data) +
1648 offsetof(struct pdu_adv_ext_hdr, data) + ADVA_SIZE +
1649 TARGETA_SIZE))) {
1650 return false;
1651 }
1652
1653 if (unlikely(pdu_rx->adv_ext_ind.adv_mode || !pdu_rx->adv_ext_ind.ext_hdr.adv_addr ||
1654 !pdu_rx->adv_ext_ind.ext_hdr.tgt_addr)) {
1655 return false;
1656 }
1657
1658 return lll_scan_adva_check(lll, pdu_rx->tx_addr,
1659 &pdu_rx->adv_ext_ind.ext_hdr.data[ADVA_OFFSET],
1660 rl_idx) &&
1661 (pdu_rx->rx_addr == pdu_tx->tx_addr) &&
1662 (memcmp(&pdu_rx->adv_ext_ind.ext_hdr.data[TGTA_OFFSET],
1663 pdu_tx->connect_ind.init_addr, BDADDR_SIZE) == 0);
1664 }
1665
1666 static void isr_early_abort(void *param)
1667 {
1668 struct event_done_extra *e;
1669
1670 e = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN_AUX);
1671 LL_ASSERT(e);
1672
1673 #if defined(CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS)
1674 e->lll = param;
1675 #endif /* CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS */
1676
1677 lll_isr_early_abort(param);
1678 }
1679 #endif /* CONFIG_BT_CENTRAL */
1680