Commit 81136cbc authored by Piotr Pryga's avatar Piotr Pryga Committed by Christopher Friedt
Browse files

Bluetooth: controller: ULL: add per sync filtering by CTE type



Follow up on changes in lower link layer to add filtering
of periodic advertisements synchronization by CTE type.

The NODE_RX_TYPE_SYNC is used to transport information that:
- Sync is established. In such situation the node_rx
  includes data related with received PDU
- Sync scanning is terminated.
In first case ULL will generate NODE_RX_TYPE_SYNC_REPORT
after sending NODE_RX_TYPE_SYNC.

Also EVENT_DONE_EXTRA_TYPE_SYNC handling has additional
execution path that terminates sync scanning if requested
by lower link layer. In other case it adjusts sync scan
window and maintains timeout as usual.

Signed-off-by: default avatarPiotr Pryga <piotr.pryga@nordicsemi.no>
parent 42276f5b
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -2392,6 +2392,14 @@ static inline int rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx)
		ull_scan_aux_release(link, rx);
	}
	break;
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
	case NODE_RX_TYPE_SYNC:
	{
		(void)memq_dequeue(memq_ull_rx.tail, &memq_ull_rx.head, NULL);
		ull_sync_established_report(link, rx);
	}
	break;
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#endif /* CONFIG_BT_OBSERVER */

+0 −2
Original line number Diff line number Diff line
@@ -26,8 +26,6 @@ struct ll_scan_set {

		uint8_t adv_addr[BDADDR_SIZE];

		struct node_rx_hdr *node_rx_estab;

		/* Non-Null when creating sync, reset in ISR context on
		 * synchronisation state and checked in Thread context when
		 * cancelling sync create, hence the volatile keyword.
+124 −89
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@

static int init_reset(void);
static inline struct ll_sync_set *sync_acquire(void);
static void timeout_cleanup(struct ll_sync_set *sync);
static void sync_ticker_cleanup(struct ll_sync_set *sync, ticker_op_func stop_of_cb);
static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
		      uint32_t remainder, uint16_t lazy, uint8_t force,
		      void *param);
@@ -72,6 +72,9 @@ static void *sync_free;
static struct k_sem sem_ticker_cb;
#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */

static memq_link_t link_lll_prepare;
static struct mayfly mfy_lll_prepare = { 0, 0, &link_lll_prepare, NULL, lll_sync_prepare };

uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
			    uint8_t *adv_addr, uint16_t skip,
			    uint16_t sync_timeout, uint8_t sync_cte_type)
@@ -125,14 +128,10 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
		return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
	}

	node_rx->link = link_sync_estab;
	scan->per_scan.node_rx_estab = node_rx;
	scan->per_scan.state = LL_SYNC_STATE_IDLE;
	scan->per_scan.filter_policy = options & BIT(0);
	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
		scan_coded->per_scan.state = LL_SYNC_STATE_IDLE;
		scan_coded->per_scan.node_rx_estab =
			scan->per_scan.node_rx_estab;
		scan_coded->per_scan.filter_policy =
			scan->per_scan.filter_policy;
	}
@@ -154,9 +153,9 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
	sync->skip = skip;
	sync->timeout = sync_timeout;

	/* TODO: Support for CTE type */

	/* Initialize sync context */
	node_rx->link = link_sync_estab;
	sync->node_rx_sync_estab = node_rx;
	sync->timeout_reload = 0U;
	sync->timeout_expire = 0U;

@@ -171,6 +170,8 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
	lll_sync->skip_event = 0U;
	lll_sync->window_widening_prepare_us = 0U;
	lll_sync->window_widening_event_us = 0U;
	lll_sync->cte_type = sync_cte_type;
	lll_sync->filter_policy = scan->per_scan.filter_policy;

	/* Reporting initially enabled/disabled */
	lll_sync->is_rx_enabled = options & BIT(1);
@@ -235,7 +236,7 @@ uint8_t ll_sync_create_cancel(void **rx)
		return BT_HCI_ERR_CMD_DISALLOWED;
	}

	node_rx = (void *)scan->per_scan.node_rx_estab;
	node_rx = (void *)sync->node_rx_sync_estab;
	link_sync_estab = node_rx->hdr.link;
	link_sync_lost = sync->node_rx_lost.hdr.link;

@@ -465,19 +466,15 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
	sync_handle = ull_sync_handle_get(sync);

	/* Prepare and dispatch sync notification */
	rx = (void *)scan->per_scan.node_rx_estab;
	rx = (void *)sync->node_rx_sync_estab;
	rx->hdr.type = NODE_RX_TYPE_SYNC;
	rx->hdr.handle = sync_handle;
	rx->hdr.rx_ftr.param = scan;
	se = (void *)rx->pdu;
	se->status = BT_HCI_ERR_SUCCESS;
	se->interval = interval;
	se->phy = lll->phy;
	se->sca = sca;

	ll_rx_put(rx->hdr.link, rx);
	ll_rx_sched();

	/* Calculate offset and schedule sync radio events */
	ftr = &node_rx->rx_ftr;
	pdu = (void *)((struct node_rx_pdu *)node_rx)->pdu;
@@ -515,6 +512,8 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
	}
	ticks_slot_offset += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);

	mfy_lll_prepare.fp = lll_sync_create_prepare;

	ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
			   (TICKER_ID_SCAN_SYNC_BASE + sync_handle),
			   ftr->ticks_anchor - ticks_slot_offset,
@@ -528,6 +527,52 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
		  (ret == TICKER_STATUS_BUSY));
}

void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx)
{
	struct node_rx_pdu *rx_establ;
	struct ll_sync_set *ull_sync;
	struct node_rx_ftr *ftr;
	struct node_rx_sync *se;
	struct lll_sync *lll;

	ftr = &rx->rx_ftr;

	/* Send periodic advertisement sync established report when sync has correct CTE type
	 * or the CTE type is incorrect and filter policy doesn't allow to continue scanning.
	 */
	if (ftr->sync_status != SYNC_STAT_READY) {
		/* Set the sync handle corresponding to the LLL context passed in the node rx
		 * footer field.
		 */
		lll = ftr->param;
		ull_sync = HDR_LLL2ULL(lll);

		/* Prepare and dispatch sync notification */
		rx_establ = (void *)ull_sync->node_rx_sync_estab;
		rx_establ->hdr.type = NODE_RX_TYPE_SYNC;
		se = (void *)rx_establ->pdu;
		se->status = (ftr->sync_status == SYNC_STAT_TERM) ?
					   BT_HCI_ERR_UNSUPP_REMOTE_FEATURE :
					   BT_HCI_ERR_SUCCESS;

		ll_rx_put(rx_establ->hdr.link, rx_establ);
		ll_rx_sched();
	}

	/* Handle periodic advertising PDU and send periodic advertising scan report when
	 * the sync was found or was established in the past. The report is not send if
	 * scanning is terminated due to wrong CTE type.
	 */
	if (ftr->sync_status != SYNC_STAT_TERM) {
		/* Switch sync event prepare function to one reposnsible for regular PDUs receive */
		mfy_lll_prepare.fp = lll_sync_prepare;

		/* Change node type to appropriately handle periodic advertising PDU report */
		rx->type = NODE_RX_TYPE_SYNC_REPORT;
		ull_scan_aux_setup(link, rx);
	}
}

void ull_sync_done(struct node_rx_event_done *done)
{
	uint32_t ticks_drift_minus;
@@ -543,18 +588,20 @@ void ull_sync_done(struct node_rx_event_done *done)
	sync = CONTAINER_OF(done->param, struct ll_sync_set, ull);
	lll = &sync->lll;

	if (done->extra.sync_term) {
		/* Stop periodic advertising scan ticker */
		sync_ticker_cleanup(sync, NULL);
	} else {
		/* Events elapsed used in timeout checks below */
		skip_event = lll->skip_event;
		elapsed_event = skip_event + 1;

	/* Sync drift compensation and new skip calculation
	 */
		/* Sync drift compensation and new skip calculation */
		ticks_drift_plus = 0U;
		ticks_drift_minus = 0U;
		if (done->extra.trx_cnt) {
			/* Calculate drift in ticks unit */
		ull_drift_ticks_get(done, &ticks_drift_plus,
				    &ticks_drift_minus);
			ull_drift_ticks_get(done, &ticks_drift_plus, &ticks_drift_minus);

			/* Enforce skip */
			lll->skip_event = sync->skip;
@@ -564,15 +611,10 @@ void ull_sync_done(struct node_rx_event_done *done)
		if (done->extra.crc_valid) {
			sync->timeout_expire = 0U;
		}

	/* if anchor point not sync-ed, start timeout countdown, and break
	 * skip if any.
	 */
	else {
		if (!sync->timeout_expire) {
		/* If anchor point not sync-ed, start timeout countdown, and break skip if any */
		else if (!sync->timeout_expire) {
			sync->timeout_expire = sync->timeout_reload;
		}
	}

		/* check timeout */
		force = 0U;
@@ -587,13 +629,13 @@ void ull_sync_done(struct node_rx_event_done *done)
					force = 1U;
				}
			} else {
			timeout_cleanup(sync);
				sync_ticker_cleanup(sync, ticker_stop_op_cb);

				return;
			}
		}

	/* check if skip needs update */
		/* Check if skip needs update */
		lazy = 0U;
		if ((force) || (skip_event != lll->skip_event)) {
			lazy = lll->skip_event + 1U;
@@ -610,19 +652,17 @@ void ull_sync_done(struct node_rx_event_done *done)
			 * that gets into close state. Accept failure when periodic sync
			 * role is being stopped.
			 */
		ticker_status = ticker_update(TICKER_INSTANCE_ID_CTLR,
					      TICKER_USER_ID_ULL_HIGH,
					      (TICKER_ID_SCAN_SYNC_BASE +
					       sync_handle),
					      ticks_drift_plus,
					      ticks_drift_minus, 0, 0,
					      lazy, force,
					      ticker_update_sync_op_cb, sync);
			ticker_status =
				ticker_update(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
					      (TICKER_ID_SCAN_SYNC_BASE + sync_handle),
					      ticks_drift_plus, ticks_drift_minus, 0, 0, lazy,
					      force, ticker_update_sync_op_cb, sync);
			LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
				  (ticker_status == TICKER_STATUS_BUSY) ||
				  ((void *)sync == ull_disable_mark_get()));
		}
	}
}

void ull_sync_chm_update(uint8_t sync_handle, uint8_t *acad, uint8_t acad_len)
{
@@ -762,15 +802,14 @@ static inline struct ll_sync_set *sync_acquire(void)
	return mem_acquire(&sync_free);
}

static void timeout_cleanup(struct ll_sync_set *sync)
static void sync_ticker_cleanup(struct ll_sync_set *sync, ticker_op_func stop_of_cb)
{
	uint16_t sync_handle = ull_sync_handle_get(sync);
	uint32_t ret;

	/* Stop Periodic Sync Ticker */
	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
			  TICKER_ID_SCAN_SYNC_BASE + sync_handle,
			  ticker_stop_op_cb, (void *)sync);
			  TICKER_ID_SCAN_SYNC_BASE + sync_handle, stop_of_cb, (void *)sync);
	LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
		  (ret == TICKER_STATUS_BUSY));
}
@@ -779,8 +818,6 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
		      uint32_t remainder, uint16_t lazy, uint8_t force,
		      void *param)
{
	static memq_link_t link;
	static struct mayfly mfy = {0, 0, &link, NULL, lll_sync_prepare};
	static struct lll_prepare_param p;
	struct ll_sync_set *sync = param;
	struct lll_sync *lll;
@@ -801,11 +838,10 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
	p.lazy = lazy;
	p.force = force;
	p.param = lll;
	mfy.param = &p;
	mfy_lll_prepare.param = &p;

	/* Kick LLL prepare */
	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
			     TICKER_USER_ID_LLL, 0, &mfy);
	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy_lll_prepare);
	LL_ASSERT(!ret);

	DEBUG_RADIO_PREPARE_O(1);
@@ -814,7 +850,6 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
static void ticker_op_cb(uint32_t status, void *param)
{
	ARG_UNUSED(param);

	LL_ASSERT(status == TICKER_STATUS_SUCCESS);
}

+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ struct ll_sync_set *ull_sync_is_enabled_get(uint16_t handle);
void ull_sync_release(struct ll_sync_set *sync);
void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
		    struct node_rx_hdr *node_rx, struct pdu_adv_sync_info *si);
void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx);
void ull_sync_done(struct node_rx_event_done *done);
void ull_sync_chm_update(uint8_t sync_handle, uint8_t *acad, uint8_t acad_len);
int ull_sync_slot_update(struct ll_sync_set *sync, uint32_t slot_plus_us,