1 /*
2  * Copyright (c) 2016-2019 Nordic Semiconductor ASA
3  * Copyright (c) 2016 Vinayak Kariappa Chettimada
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr.h>
9 #include <soc.h>
10 #include <bluetooth/hci.h>
11 
12 #include "hal/cpu.h"
13 #include "hal/ccm.h"
14 #include "hal/radio.h"
15 #include "hal/ticker.h"
16 
17 #include "util/util.h"
18 #include "util/mem.h"
19 #include "util/memq.h"
20 #include "util/mayfly.h"
21 
22 #include "ticker/ticker.h"
23 
24 #include "pdu.h"
25 
26 #include "lll.h"
27 #include "lll/lll_vendor.h"
28 #include "lll/lll_adv_types.h"
29 #include "lll_adv.h"
30 #include "lll/lll_adv_pdu.h"
31 #include "lll_scan.h"
32 #include "lll/lll_df_types.h"
33 #include "lll_conn.h"
34 #include "lll_filter.h"
35 
36 #include "ull_adv_types.h"
37 #include "ull_scan_types.h"
38 #include "ull_filter.h"
39 
40 #include "ull_internal.h"
41 #include "ull_adv_internal.h"
42 #include "ull_scan_internal.h"
43 #include "ull_sched_internal.h"
44 
45 #include "ll.h"
46 
47 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
48 #define LOG_MODULE_NAME bt_ctlr_ull_scan
49 #include "common/log.h"
50 #include "hal/debug.h"
51 
52 static int init_reset(void);
53 static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
54 		      uint32_t remainder, uint16_t lazy, uint8_t force,
55 		      void *param);
56 static uint8_t disable(uint8_t handle);
57 
58 #if defined(CONFIG_BT_CTLR_ADV_EXT)
59 static uint8_t is_scan_update(uint8_t handle, uint16_t duration,
60 			      uint16_t period, struct ll_scan_set **scan,
61 			      struct node_rx_pdu **node_rx_scan_term);
62 static uint8_t duration_period_setup(struct ll_scan_set *scan,
63 				     uint16_t duration, uint16_t period,
64 				     struct node_rx_pdu **node_rx_scan_term);
65 static uint8_t duration_period_update(struct ll_scan_set *scan,
66 				      uint8_t is_update);
67 static void ticker_stop_ext_op_cb(uint32_t status, void *param);
68 static void ext_disable(void *param);
69 static void ext_disabled_cb(void *param);
70 #endif /* CONFIG_BT_CTLR_ADV_EXT */
71 
72 static struct ll_scan_set ll_scan[BT_CTLR_SCAN_SET];
73 
ll_scan_params_set(uint8_t type,uint16_t interval,uint16_t window,uint8_t own_addr_type,uint8_t filter_policy)74 uint8_t ll_scan_params_set(uint8_t type, uint16_t interval, uint16_t window,
75 			uint8_t own_addr_type, uint8_t filter_policy)
76 {
77 	struct ll_scan_set *scan;
78 	struct lll_scan *lll;
79 
80 	scan = ull_scan_is_disabled_get(SCAN_HANDLE_1M);
81 	if (!scan) {
82 		return BT_HCI_ERR_CMD_DISALLOWED;
83 	}
84 
85 #if defined(CONFIG_BT_CTLR_ADV_EXT)
86 	uint8_t phy;
87 
88 	phy  = type >> 1;
89 	if (phy & BT_HCI_LE_EXT_SCAN_PHY_CODED) {
90 		struct ll_scan_set *scan_coded;
91 
92 		if (!IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
93 			return BT_HCI_ERR_CMD_DISALLOWED;
94 		}
95 
96 		scan_coded = ull_scan_is_disabled_get(SCAN_HANDLE_PHY_CODED);
97 		if (!scan_coded) {
98 			return BT_HCI_ERR_CMD_DISALLOWED;
99 		}
100 
101 		scan = scan_coded;
102 	}
103 
104 	lll = &scan->lll;
105 
106 	/* NOTE: Pass invalid interval value to not start scanning using this
107 	 *       scan instance.
108 	 */
109 	if (!interval) {
110 		/* Set PHY to 0 to not start scanning on this instance */
111 		lll->phy = 0U;
112 
113 		return 0;
114 	}
115 
116 	lll->phy = phy;
117 
118 #else /* !CONFIG_BT_CTLR_ADV_EXT */
119 	lll = &scan->lll;
120 #endif /* !CONFIG_BT_CTLR_ADV_EXT */
121 
122 	scan->own_addr_type = own_addr_type;
123 
124 	ull_scan_params_set(lll, type, interval, window, filter_policy);
125 
126 	return 0;
127 }
128 
129 #if defined(CONFIG_BT_CTLR_ADV_EXT)
ll_scan_enable(uint8_t enable,uint16_t duration,uint16_t period)130 uint8_t ll_scan_enable(uint8_t enable, uint16_t duration, uint16_t period)
131 {
132 	struct node_rx_pdu *node_rx_scan_term = NULL;
133 	uint8_t is_update_coded = 0U;
134 	uint8_t is_update_1m = 0U;
135 #else /* !CONFIG_BT_CTLR_ADV_EXT */
136 uint8_t ll_scan_enable(uint8_t enable)
137 {
138 #endif /* !CONFIG_BT_CTLR_ADV_EXT */
139 	struct ll_scan_set *scan_coded = NULL;
140 	uint8_t own_addr_type = 0U;
141 	uint8_t is_coded_phy = 0U;
142 	struct ll_scan_set *scan;
143 	uint8_t err;
144 
145 	if (!enable) {
146 		err = disable(SCAN_HANDLE_1M);
147 
148 		if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) &&
149 		    IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
150 			uint8_t err_coded;
151 
152 			err_coded = disable(SCAN_HANDLE_PHY_CODED);
153 			if (!err_coded) {
154 				err = 0U;
155 			}
156 		}
157 
158 		return err;
159 	}
160 
161 	scan = ull_scan_is_disabled_get(SCAN_HANDLE_1M);
162 	if (!scan) {
163 #if defined(CONFIG_BT_CTLR_ADV_EXT)
164 		is_update_1m = is_scan_update(SCAN_HANDLE_1M, duration, period,
165 					      &scan, &node_rx_scan_term);
166 		if (!is_update_1m)
167 #endif /* CONFIG_BT_CTLR_ADV_EXT */
168 		{
169 			return BT_HCI_ERR_CMD_DISALLOWED;
170 		}
171 	}
172 
173 #if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_CTLR_PHY_CODED)
174 	scan_coded = ull_scan_is_disabled_get(SCAN_HANDLE_PHY_CODED);
175 	if (!scan_coded) {
176 		is_update_coded = is_scan_update(SCAN_HANDLE_PHY_CODED,
177 						 duration, period, &scan_coded,
178 						 &node_rx_scan_term);
179 		if (!is_update_coded) {
180 			return BT_HCI_ERR_CMD_DISALLOWED;
181 		}
182 	}
183 
184 	own_addr_type = scan_coded->own_addr_type;
185 	is_coded_phy = (scan_coded->lll.phy &
186 			BT_HCI_LE_EXT_SCAN_PHY_CODED);
187 #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_CTLR_PHY_CODED */
188 
189 	if ((is_coded_phy && (own_addr_type & 0x1)) ||
190 	    (!is_coded_phy && (scan->own_addr_type & 0x1))) {
191 		if (!mem_nz(ll_addr_get(BT_ADDR_LE_RANDOM), BDADDR_SIZE)) {
192 			return BT_HCI_ERR_INVALID_PARAM;
193 		}
194 	}
195 
196 #if defined(CONFIG_BT_CTLR_ADV_EXT)
197 #if defined(CONFIG_BT_CTLR_PHY_CODED)
198 	if (!is_coded_phy || (scan->lll.phy & PHY_1M))
199 #endif /* CONFIG_BT_CTLR_PHY_CODED */
200 	{
201 		err = duration_period_setup(scan, duration, period,
202 					    &node_rx_scan_term);
203 		if (err) {
204 			return err;
205 		}
206 	}
207 
208 	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED) &&
209 	    is_coded_phy) {
210 		err = duration_period_setup(scan_coded, duration, period,
211 					    &node_rx_scan_term);
212 		if (err) {
213 			return err;
214 		}
215 	}
216 #endif /* CONFIG_BT_CTLR_ADV_EXT */
217 
218 #if defined(CONFIG_BT_CTLR_PRIVACY)
219 	struct lll_scan *lll;
220 
221 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) && is_coded_phy) {
222 		lll = &scan_coded->lll;
223 
224 		/* TODO: Privacy support in Advertising Extensions */
225 	} else {
226 		lll = &scan->lll;
227 		own_addr_type = scan->own_addr_type;
228 	}
229 
230 	ull_filter_scan_update(lll->filter_policy);
231 
232 	lll->rl_idx = FILTER_IDX_NONE;
233 	lll->rpa_gen = 0;
234 
235 	if ((lll->type & 0x1) &&
236 	    (own_addr_type == BT_ADDR_LE_PUBLIC_ID ||
237 	     own_addr_type == BT_ADDR_LE_RANDOM_ID)) {
238 		/* Generate RPAs if required */
239 		ull_filter_rpa_update(false);
240 		lll->rpa_gen = 1;
241 	}
242 #endif /* CONFIG_BT_CTLR_PRIVACY */
243 
244 #if defined(CONFIG_BT_CTLR_ADV_EXT)
245 #if defined(CONFIG_BT_CTLR_PHY_CODED)
246 	if (!is_coded_phy || (scan->lll.phy & PHY_1M))
247 #endif /* CONFIG_BT_CTLR_PHY_CODED */
248 	{
249 		err = duration_period_update(scan, is_update_1m);
250 		if (err) {
251 			return err;
252 		} else if (is_update_1m) {
253 			return 0;
254 		}
255 	}
256 
257 	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED) &&
258 	    is_coded_phy) {
259 		err = duration_period_update(scan_coded, is_update_coded);
260 		if (err) {
261 			return err;
262 		} else if (is_update_coded) {
263 			return 0;
264 		}
265 	}
266 
267 #if defined(CONFIG_BT_CTLR_PHY_CODED)
268 	if (!is_coded_phy || (scan->lll.phy & PHY_1M))
269 #endif /* CONFIG_BT_CTLR_PHY_CODED */
270 #endif /* CONFIG_BT_CTLR_ADV_EXT */
271 	{
272 		err = ull_scan_enable(scan);
273 		if (err) {
274 			return err;
275 		}
276 	}
277 
278 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) &&
279 	    IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED) &&
280 	    is_coded_phy) {
281 		err = ull_scan_enable(scan_coded);
282 		if (err) {
283 			return err;
284 		}
285 	}
286 
287 	return 0;
288 }
289 
290 int ull_scan_init(void)
291 {
292 	int err;
293 
294 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT)) {
295 		err = ull_scan_aux_init();
296 		if (err) {
297 			return err;
298 		}
299 	}
300 
301 	err = init_reset();
302 	if (err) {
303 		return err;
304 	}
305 
306 	return 0;
307 }
308 
309 int ull_scan_reset(void)
310 {
311 	uint8_t handle;
312 	int err;
313 
314 	for (handle = 0U; handle < BT_CTLR_SCAN_SET; handle++) {
315 		(void)disable(handle);
316 	}
317 
318 	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT)) {
319 		err = ull_scan_aux_reset();
320 		if (err) {
321 			return err;
322 		}
323 	}
324 
325 	err = init_reset();
326 	if (err) {
327 		return err;
328 	}
329 
330 	return 0;
331 }
332 
333 void ull_scan_params_set(struct lll_scan *lll, uint8_t type, uint16_t interval,
334 			 uint16_t window, uint8_t filter_policy)
335 {
336 	/* type value:
337 	 * 0000b - legacy 1M passive
338 	 * 0001b - legacy 1M active
339 	 * 0010b - Ext. 1M passive
340 	 * 0011b - Ext. 1M active
341 	 * 0100b - invalid
342 	 * 0101b - invalid
343 	 * 0110b - invalid
344 	 * 0111b - invalid
345 	 * 1000b - Ext. Coded passive
346 	 * 1001b - Ext. Coded active
347 	 */
348 	lll->type = type;
349 	lll->filter_policy = filter_policy;
350 	lll->interval = interval;
351 	lll->ticks_window = HAL_TICKER_US_TO_TICKS((uint64_t)window *
352 						   SCAN_INT_UNIT_US);
353 }
354 
355 uint8_t ull_scan_enable(struct ll_scan_set *scan)
356 {
357 	struct lll_scan *lll = &scan->lll;
358 	uint32_t ticks_slot_overhead;
359 	uint32_t volatile ret_cb;
360 	uint32_t ticks_interval;
361 	uint32_t ticks_anchor;
362 	uint32_t ret;
363 
364 	lll->init_addr_type = scan->own_addr_type;
365 	(void)ll_addr_read(lll->init_addr_type, lll->init_addr);
366 	lll->chan = 0U;
367 	lll->is_stop = 0U;
368 
369 	ull_hdr_init(&scan->ull);
370 	lll_hdr_init(lll, scan);
371 
372 	ticks_interval = HAL_TICKER_US_TO_TICKS((uint64_t)lll->interval *
373 						SCAN_INT_UNIT_US);
374 
375 	/* TODO: active_to_start feature port */
376 	scan->ull.ticks_active_to_start = 0U;
377 	scan->ull.ticks_prepare_to_start =
378 		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
379 	scan->ull.ticks_preempt_to_start =
380 		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
381 	if ((lll->ticks_window +
382 	     HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US)) <
383 	    (ticks_interval -
384 	     HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US))) {
385 		scan->ull.ticks_slot =
386 			(lll->ticks_window +
387 			 HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US));
388 	} else {
389 		if (IS_ENABLED(CONFIG_BT_CTLR_SCAN_UNRESERVED)) {
390 			scan->ull.ticks_slot = 0U;
391 		} else {
392 			scan->ull.ticks_slot = ticks_interval -
393 				HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
394 		}
395 
396 		lll->ticks_window = 0U;
397 	}
398 
399 	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
400 		ticks_slot_overhead = MAX(scan->ull.ticks_active_to_start,
401 					  scan->ull.ticks_prepare_to_start);
402 	} else {
403 		ticks_slot_overhead = 0U;
404 	}
405 
406 	ticks_anchor = ticker_ticks_now_get();
407 
408 #if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
409 	if (!lll->conn) {
410 		uint32_t ticks_ref = 0U;
411 		uint32_t offset_us = 0U;
412 
413 		ull_sched_after_mstr_slot_get(TICKER_USER_ID_THREAD,
414 					      (scan->ull.ticks_slot +
415 					       ticks_slot_overhead),
416 					      &ticks_ref, &offset_us);
417 
418 		/* Use the ticks_ref as scanner's anchor if a free time space
419 		 * after any central role is available (indicated by a non-zero
420 		 * offset_us value).
421 		 */
422 		if (offset_us) {
423 			ticks_anchor = ticks_ref +
424 				       HAL_TICKER_US_TO_TICKS(offset_us);
425 		}
426 	}
427 #endif /* CONFIG_BT_CENTRAL && CONFIG_BT_CTLR_SCHED_ADVANCED */
428 
429 	uint8_t handle = ull_scan_handle_get(scan);
430 
431 	ret_cb = TICKER_STATUS_BUSY;
432 	ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
433 			   TICKER_USER_ID_THREAD, TICKER_ID_SCAN_BASE + handle,
434 			   ticks_anchor, 0, ticks_interval,
435 			   HAL_TICKER_REMAINDER((uint64_t)lll->interval *
436 						SCAN_INT_UNIT_US),
437 			   TICKER_NULL_LAZY,
438 			   (scan->ull.ticks_slot + ticks_slot_overhead),
439 			   ticker_cb, scan,
440 			   ull_ticker_status_give, (void *)&ret_cb);
441 	ret = ull_ticker_status_take(ret, &ret_cb);
442 	if (ret != TICKER_STATUS_SUCCESS) {
443 		return BT_HCI_ERR_CMD_DISALLOWED;
444 	}
445 
446 	scan->is_enabled = 1U;
447 
448 #if defined(CONFIG_BT_CTLR_PRIVACY)
449 #if defined(CONFIG_BT_BROADCASTER)
450 	if (!ull_adv_is_enabled_get(0))
451 #endif
452 	{
453 		ull_filter_adv_scan_state_cb(BIT(1));
454 	}
455 #endif
456 
457 	return 0;
458 }
459 
460 uint8_t ull_scan_disable(uint8_t handle, struct ll_scan_set *scan)
461 {
462 	int err;
463 
464 	err = ull_ticker_stop_with_mark(TICKER_ID_SCAN_BASE + handle,
465 					scan, &scan->lll);
466 	LL_ASSERT(err == 0 || err == -EALREADY);
467 	if (err) {
468 		return BT_HCI_ERR_CMD_DISALLOWED;
469 	}
470 
471 	return 0;
472 }
473 
474 #if defined(CONFIG_BT_CTLR_ADV_EXT)
475 void ull_scan_done(struct node_rx_event_done *done)
476 {
477 	struct node_rx_hdr *rx_hdr;
478 	struct ll_scan_set *scan;
479 	struct lll_scan *lll;
480 	uint8_t handle;
481 	uint32_t ret;
482 
483 	/* Get reference to ULL context */
484 	scan = CONTAINER_OF(done->param, struct ll_scan_set, ull);
485 	lll = &scan->lll;
486 
487 	if (likely(scan->duration_lazy || !lll->duration_reload ||
488 		   lll->duration_expire)) {
489 		return;
490 	}
491 
492 	rx_hdr = (void *)scan->node_rx_scan_term;
493 	if (!rx_hdr) {
494 		/* Prevent generation if another scan instance already did so.
495 		 */
496 		return;
497 	}
498 
499 	handle = ull_scan_handle_get(scan);
500 	LL_ASSERT(handle < BT_CTLR_SCAN_SET);
501 
502 #if defined(CONFIG_BT_CTLR_PHY_CODED)
503 	/* Reset the singular node rx buffer, so that it does not get used if
504 	 * ull_scan_done get called by the other scan instance.
505 	 */
506 	struct ll_scan_set *scan_other;
507 
508 	if (handle == SCAN_HANDLE_1M) {
509 		scan_other = ull_scan_set_get(SCAN_HANDLE_PHY_CODED);
510 	} else {
511 		scan_other = ull_scan_set_get(SCAN_HANDLE_1M);
512 	}
513 	scan_other->node_rx_scan_term = NULL;
514 #endif /* CONFIG_BT_CTLR_PHY_CODED */
515 
516 	rx_hdr->type = NODE_RX_TYPE_EXT_SCAN_TERMINATE;
517 	rx_hdr->handle = handle;
518 
519 	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
520 			  (TICKER_ID_SCAN_BASE + handle), ticker_stop_ext_op_cb,
521 			  scan);
522 
523 	LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
524 		  (ret == TICKER_STATUS_BUSY));
525 }
526 
527 void ull_scan_term_dequeue(uint8_t handle)
528 {
529 	struct ll_scan_set *scan;
530 
531 	scan = ull_scan_set_get(handle);
532 	LL_ASSERT(scan);
533 
534 	scan->is_enabled = 0U;
535 
536 #if defined(CONFIG_BT_CTLR_PHY_CODED)
537 	if (handle == SCAN_HANDLE_1M) {
538 		struct ll_scan_set *scan_coded;
539 
540 		scan_coded = ull_scan_set_get(SCAN_HANDLE_PHY_CODED);
541 		if (scan_coded->lll.phy & PHY_CODED) {
542 			uint8_t err;
543 
544 			err = disable(SCAN_HANDLE_PHY_CODED);
545 			LL_ASSERT(!err);
546 		}
547 	} else {
548 		struct ll_scan_set *scan_1m;
549 
550 		scan_1m = ull_scan_set_get(SCAN_HANDLE_1M);
551 		if (scan_1m->lll.phy & PHY_1M) {
552 			uint8_t err;
553 
554 			err = disable(SCAN_HANDLE_1M);
555 			LL_ASSERT(!err);
556 		}
557 	}
558 #endif /* CONFIG_BT_CTLR_PHY_CODED */
559 }
560 #endif /* CONFIG_BT_CTLR_ADV_EXT */
561 
562 struct ll_scan_set *ull_scan_set_get(uint8_t handle)
563 {
564 	if (handle >= BT_CTLR_SCAN_SET) {
565 		return NULL;
566 	}
567 
568 	return &ll_scan[handle];
569 }
570 
571 uint8_t ull_scan_handle_get(struct ll_scan_set *scan)
572 {
573 	return ((uint8_t *)scan - (uint8_t *)ll_scan) / sizeof(*scan);
574 }
575 
576 uint8_t ull_scan_lll_handle_get(struct lll_scan *lll)
577 {
578 	return ull_scan_handle_get((void *)lll->hdr.parent);
579 }
580 
581 struct ll_scan_set *ull_scan_is_valid_get(struct ll_scan_set *scan)
582 {
583 	if (((uint8_t *)scan < (uint8_t *)ll_scan) ||
584 	    ((uint8_t *)scan > ((uint8_t *)ll_scan +
585 				(sizeof(struct ll_scan_set) *
586 				 (BT_CTLR_SCAN_SET - 1))))) {
587 		return NULL;
588 	}
589 
590 	return scan;
591 }
592 
593 struct ll_scan_set *ull_scan_is_enabled_get(uint8_t handle)
594 {
595 	struct ll_scan_set *scan;
596 
597 	scan = ull_scan_set_get(handle);
598 	if (!scan || !scan->is_enabled) {
599 		return NULL;
600 	}
601 
602 	return scan;
603 }
604 
605 struct ll_scan_set *ull_scan_is_disabled_get(uint8_t handle)
606 {
607 	struct ll_scan_set *scan;
608 
609 	scan = ull_scan_set_get(handle);
610 	if (!scan || scan->is_enabled) {
611 		return NULL;
612 	}
613 
614 	return scan;
615 }
616 
617 uint32_t ull_scan_is_enabled(uint8_t handle)
618 {
619 	struct ll_scan_set *scan;
620 
621 	scan = ull_scan_is_enabled_get(handle);
622 	if (!scan) {
623 #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
624 		scan = ull_scan_set_get(handle);
625 
626 		return scan->per_scan.sync ? ULL_SCAN_IS_SYNC : 0U;
627 #else
628 		return 0U;
629 #endif
630 	}
631 
632 	return (((uint32_t)scan->is_enabled << scan->lll.type) |
633 #if defined(CONFIG_BT_CENTRAL)
634 		(scan->lll.conn ? ULL_SCAN_IS_INITIATOR : 0U) |
635 #endif
636 #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
637 		(scan->per_scan.sync ? ULL_SCAN_IS_SYNC : 0U) |
638 #endif
639 		0U);
640 }
641 
642 uint32_t ull_scan_filter_pol_get(uint8_t handle)
643 {
644 	struct ll_scan_set *scan;
645 
646 	scan = ull_scan_is_enabled_get(handle);
647 	if (!scan) {
648 		return 0;
649 	}
650 
651 	return scan->lll.filter_policy;
652 }
653 
654 static int init_reset(void)
655 {
656 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) && \
657 	!defined(CONFIG_BT_CTLR_ADV_EXT)
658 	ll_scan[0].lll.tx_pwr_lvl = RADIO_TXP_DEFAULT;
659 #endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL && !CONFIG_BT_CTLR_ADV_EXT */
660 
661 	return 0;
662 }
663 
664 static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
665 		      uint32_t remainder, uint16_t lazy, uint8_t force,
666 		      void *param)
667 {
668 	static memq_link_t link;
669 	static struct mayfly mfy = {0, 0, &link, NULL, lll_scan_prepare};
670 	static struct lll_prepare_param p;
671 	struct ll_scan_set *scan;
672 	struct lll_scan *lll;
673 	uint32_t ret;
674 	uint8_t ref;
675 
676 	DEBUG_RADIO_PREPARE_O(1);
677 
678 	scan = param;
679 	lll = &scan->lll;
680 
681 	/* Increment prepare reference count */
682 	ref = ull_ref_inc(&scan->ull);
683 	LL_ASSERT(ref);
684 
685 	/* Append timing parameters */
686 	p.ticks_at_expire = ticks_at_expire;
687 	p.remainder = remainder;
688 	p.lazy = lazy;
689 	p.param = lll;
690 	p.force = force;
691 	mfy.param = &p;
692 
693 	/* Kick LLL prepare */
694 	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
695 			     0, &mfy);
696 	LL_ASSERT(!ret);
697 
698 #if defined(CONFIG_BT_CTLR_ADV_EXT)
699 	if (lll->duration_expire) {
700 		uint16_t elapsed;
701 
702 		elapsed = lazy + 1;
703 		if (lll->duration_expire > elapsed) {
704 			lll->duration_expire -= elapsed;
705 		} else {
706 			if (scan->duration_lazy) {
707 				uint8_t handle;
708 				uint16_t duration_lazy;
709 
710 				duration_lazy = lll->duration_expire +
711 						scan->duration_lazy - elapsed;
712 
713 				handle = ull_scan_handle_get(scan);
714 				LL_ASSERT(handle < BT_CTLR_SCAN_SET);
715 
716 				ret = ticker_update(TICKER_INSTANCE_ID_CTLR,
717 						    TICKER_USER_ID_ULL_HIGH,
718 						    (TICKER_ID_SCAN_BASE +
719 						     handle), 0, 0, 0, 0,
720 						    duration_lazy, 0,
721 						    NULL, NULL);
722 				LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
723 					  (ret == TICKER_STATUS_BUSY));
724 			}
725 
726 			lll->duration_expire = 0U;
727 		}
728 	} else if (lll->duration_reload && lazy) {
729 		uint8_t handle;
730 
731 		handle = ull_scan_handle_get(scan);
732 		LL_ASSERT(handle < BT_CTLR_SCAN_SET);
733 
734 		lll->duration_expire = lll->duration_reload;
735 		ret = ticker_update(TICKER_INSTANCE_ID_CTLR,
736 				    TICKER_USER_ID_ULL_HIGH,
737 				    (TICKER_ID_SCAN_BASE + handle),
738 				    0, 0, 0, 0, 1, 1, NULL, NULL);
739 		LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
740 			  (ret == TICKER_STATUS_BUSY));
741 	}
742 #endif /* CONFIG_BT_CTLR_ADV_EXT */
743 
744 	DEBUG_RADIO_PREPARE_O(1);
745 }
746 
747 #if defined(CONFIG_BT_CTLR_ADV_EXT)
748 static uint8_t is_scan_update(uint8_t handle, uint16_t duration,
749 			      uint16_t period, struct ll_scan_set **scan,
750 			      struct node_rx_pdu **node_rx_scan_term)
751 {
752 	*scan = ull_scan_set_get(handle);
753 	*node_rx_scan_term = (void *)(*scan)->node_rx_scan_term;
754 	return duration && period && (*scan)->lll.duration_reload &&
755 	       (*scan)->duration_lazy;
756 }
757 
758 static uint8_t duration_period_setup(struct ll_scan_set *scan,
759 				     uint16_t duration, uint16_t period,
760 				     struct node_rx_pdu **node_rx_scan_term)
761 {
762 	struct lll_scan *lll;
763 
764 	lll = &scan->lll;
765 	if (duration) {
766 		lll->duration_reload =
767 			ULL_SCAN_DURATION_TO_EVENTS(duration,
768 						    scan->lll.interval);
769 		if (period) {
770 			if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK) &&
771 			    (duration >= ULL_SCAN_PERIOD_TO_DURATION(period))) {
772 				return BT_HCI_ERR_INVALID_PARAM;
773 			}
774 
775 			scan->duration_lazy =
776 				ULL_SCAN_PERIOD_TO_EVENTS(period,
777 							  scan->lll.interval);
778 			scan->duration_lazy -= lll->duration_reload;
779 			scan->node_rx_scan_term = NULL;
780 		} else {
781 			struct node_rx_pdu *node_rx;
782 			void *link_scan_term;
783 
784 			scan->duration_lazy = 0U;
785 
786 			if (*node_rx_scan_term) {
787 				scan->node_rx_scan_term =
788 					(void *)*node_rx_scan_term;
789 
790 				return 0;
791 			}
792 
793 			/* The alloc here used for ext scan termination event */
794 			link_scan_term = ll_rx_link_alloc();
795 			if (!link_scan_term) {
796 				return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
797 			}
798 
799 			node_rx = ll_rx_alloc();
800 			if (!node_rx) {
801 				ll_rx_link_release(link_scan_term);
802 
803 				return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
804 			}
805 
806 			node_rx->hdr.link = (void *)link_scan_term;
807 			scan->node_rx_scan_term = (void *)node_rx;
808 			*node_rx_scan_term = node_rx;
809 		}
810 	} else {
811 		lll->duration_reload = 0U;
812 		scan->duration_lazy = 0U;
813 		scan->node_rx_scan_term = NULL;
814 	}
815 
816 	return 0;
817 }
818 
819 static uint8_t duration_period_update(struct ll_scan_set *scan,
820 				      uint8_t is_update)
821 {
822 	if (is_update) {
823 		uint32_t volatile ret_cb;
824 		uint32_t ret;
825 
826 		scan->lll.duration_expire = 0U;
827 
828 		ret_cb = TICKER_STATUS_BUSY;
829 		ret = ticker_update(TICKER_INSTANCE_ID_CTLR,
830 				    TICKER_USER_ID_THREAD,
831 				    (TICKER_ID_SCAN_BASE +
832 				     ull_scan_handle_get(scan)),
833 				    0, 0, 0, 0, 1, 1,
834 				    ull_ticker_status_give, (void *)&ret_cb);
835 		ret = ull_ticker_status_take(ret, &ret_cb);
836 		if (ret != TICKER_STATUS_SUCCESS) {
837 			return BT_HCI_ERR_CMD_DISALLOWED;
838 		}
839 
840 		return 0;
841 	} else {
842 		scan->lll.duration_expire = scan->lll.duration_reload;
843 	}
844 
845 	return 0;
846 }
847 
848 static void ticker_stop_ext_op_cb(uint32_t status, void *param)
849 {
850 	static memq_link_t link;
851 	static struct mayfly mfy = {0, 0, &link, NULL, ext_disable};
852 	uint32_t ret;
853 
854 	/* Ignore if race between thread and ULL */
855 	if (status != TICKER_STATUS_SUCCESS) {
856 		/* TODO: detect race */
857 
858 		return;
859 	}
860 
861 	/* Check if any pending LLL events that need to be aborted */
862 	mfy.param = param;
863 	ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW,
864 			     TICKER_USER_ID_ULL_HIGH, 0, &mfy);
865 	LL_ASSERT(!ret);
866 }
867 
868 static void ext_disable(void *param)
869 {
870 	struct ll_scan_set *scan;
871 	struct ull_hdr *hdr;
872 
873 	/* Check ref count to determine if any pending LLL events in pipeline */
874 	scan = param;
875 	hdr = &scan->ull;
876 	if (ull_ref_get(hdr)) {
877 		static memq_link_t link;
878 		static struct mayfly mfy = {0, 0, &link, NULL, lll_disable};
879 		uint32_t ret;
880 
881 		mfy.param = &scan->lll;
882 
883 		/* Setup disabled callback to be called when ref count
884 		 * returns to zero.
885 		 */
886 		LL_ASSERT(!hdr->disabled_cb);
887 		hdr->disabled_param = mfy.param;
888 		hdr->disabled_cb = ext_disabled_cb;
889 
890 		/* Trigger LLL disable */
891 		ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
892 				     TICKER_USER_ID_LLL, 0, &mfy);
893 		LL_ASSERT(!ret);
894 	} else {
895 		/* No pending LLL events */
896 		ext_disabled_cb(&scan->lll);
897 	}
898 }
899 
900 static void ext_disabled_cb(void *param)
901 {
902 	struct node_rx_hdr *rx_hdr;
903 	struct ll_scan_set *scan;
904 	struct lll_scan *lll;
905 
906 	/* Under race condition, if a connection has been established then
907 	 * node_rx is already utilized to send terminate event on connection
908 	 */
909 	lll = (void *)param;
910 	scan = HDR_LLL2ULL(lll);
911 	rx_hdr = (void *)scan->node_rx_scan_term;
912 	if (!rx_hdr) {
913 		return;
914 	}
915 
916 	/* NOTE: parameters are already populated on disable,
917 	 * just enqueue here
918 	 */
919 	ll_rx_put(rx_hdr->link, rx_hdr);
920 	ll_rx_sched();
921 }
922 #endif /* CONFIG_BT_CTLR_ADV_EXT */
923 
924 static uint8_t disable(uint8_t handle)
925 {
926 	struct ll_scan_set *scan;
927 	uint8_t ret;
928 
929 	scan = ull_scan_is_enabled_get(handle);
930 	if (!scan) {
931 		return BT_HCI_ERR_CMD_DISALLOWED;
932 	}
933 
934 #if defined(CONFIG_BT_CENTRAL)
935 	if (scan->lll.conn) {
936 		return BT_HCI_ERR_CMD_DISALLOWED;
937 	}
938 #endif
939 
940 	ret = ull_scan_disable(handle, scan);
941 	if (ret) {
942 		return ret;
943 	}
944 
945 	scan->is_enabled = 0U;
946 
947 #if defined(CONFIG_BT_CTLR_ADV_EXT)
948 	if (scan->node_rx_scan_term) {
949 		struct node_rx_pdu *node_rx_scan_term =
950 			(void *)scan->node_rx_scan_term;
951 
952 		scan->node_rx_scan_term = NULL;
953 
954 		ll_rx_link_release(node_rx_scan_term->hdr.link);
955 		ll_rx_release(node_rx_scan_term);
956 	}
957 #endif /* CONFIG_BT_CTLR_ADV_EXT */
958 
959 #if defined(CONFIG_BT_CTLR_PRIVACY)
960 #if defined(CONFIG_BT_BROADCASTER)
961 	if (!ull_adv_is_enabled_get(0))
962 #endif
963 	{
964 		ull_filter_adv_scan_state_cb(0);
965 	}
966 #endif
967 
968 	return 0;
969 }
970