Skip to content

[Backport v2.2-branch] Bluetooth: Controller: Fix device address in Periodic Adv Sync #2457

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: v3.2.99-ncs1-branch
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 35 additions & 6 deletions subsys/bluetooth/controller/ll_sw/ull_scan_aux.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,19 +361,30 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx)

ptr = h->data;

#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
bool is_aux_addr_match = false;
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */

if (h->adv_addr) {
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
/* Check if Periodic Advertising Synchronization to be created
*/
if (sync && (scan->periodic.state != LL_SYNC_STATE_CREATED)) {
/* Check address and update internal state */
#if defined(CONFIG_BT_CTLR_PRIVACY)
ull_sync_setup_addr_check(scan, pdu->tx_addr, ptr,
ftr->rl_idx);
uint8_t rl_idx = ftr->rl_idx;
#else /* !CONFIG_BT_CTLR_PRIVACY */
ull_sync_setup_addr_check(scan, pdu->tx_addr, ptr, 0U);
uint8_t rl_idx = 0U;
#endif /* !CONFIG_BT_CTLR_PRIVACY */

/* Check address and update internal state */
is_aux_addr_match =
ull_sync_setup_addr_check(scan, pdu->tx_addr,
ptr, rl_idx);
if (is_aux_addr_match) {
scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH;
} else {
scan->periodic.state = LL_SYNC_STATE_IDLE;
}
}
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */

Expand Down Expand Up @@ -406,14 +417,22 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx)
si = (void *)ptr;
ptr += sizeof(*si);

#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
/* Check if Periodic Advertising Synchronization to be created.
* Setup synchronization if address and SID match in the
* Periodic Advertiser List or with the explicitly supplied.
*
* is_aux_addr_match, device address in auxiliary channel PDU;
* scan->periodic.param has not been assigned yet.
* Otherwise, address was in primary channel PDU and we are now
* checking SID (in SyncInfo) in auxiliary channel PDU.
*/
if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync && adi &&
ull_sync_setup_sid_match(scan, adi->sid)) {
if (sync && aux && (is_aux_addr_match ||
(scan->periodic.param == aux)) &&
adi && ull_sync_setup_sid_match(scan, adi->sid)) {
ull_sync_setup(scan, aux, rx, si);
}
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
}

if (h->tx_pwr) {
Expand Down Expand Up @@ -522,6 +541,15 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx)
aux->parent = lll ? (void *)lll : (void *)sync_lll;

#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
/* Store the aux context that has Periodic Advertising
* Synchronization address match.
*/
if (sync && (scan->periodic.state == LL_SYNC_STATE_ADDR_MATCH)) {
scan->periodic.param = aux;
}

/* Store the node rx allocated for incomplete report, if needed.
*/
aux->rx_incomplete = rx_incomplete;
rx_incomplete = NULL;
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
Expand Down Expand Up @@ -708,6 +736,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx)
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
if (sync && (scan->periodic.state != LL_SYNC_STATE_CREATED)) {
scan->periodic.state = LL_SYNC_STATE_IDLE;
scan->periodic.param = NULL;
}
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */

Expand Down
7 changes: 6 additions & 1 deletion subsys/bluetooth/controller/ll_sw/ull_scan_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct ll_scan_set {
struct {
uint8_t sid;

uint8_t adv_addr_type:1;
uint8_t adv_addr_type:2;
uint8_t filter_policy:1;
uint8_t cancelled:1;
uint8_t state:2;
Expand All @@ -34,6 +34,11 @@ struct ll_scan_set {
* cancelling sync create, hence the volatile keyword.
*/
struct ll_sync_set *volatile sync;

/* Non-NULL when Periodic Advertising Synchronisation address
* matched.
*/
void *param;
} periodic;
#endif
};
Expand Down
42 changes: 36 additions & 6 deletions subsys/bluetooth/controller/ll_sw/ull_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,13 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,

scan->periodic.cancelled = 0U;
scan->periodic.state = LL_SYNC_STATE_IDLE;
scan->periodic.param = NULL;
scan->periodic.filter_policy =
options & BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_USE_LIST;
if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
scan_coded->periodic.cancelled = 0U;
scan_coded->periodic.state = LL_SYNC_STATE_IDLE;
scan_coded->periodic.param = NULL;
scan_coded->periodic.filter_policy =
scan->periodic.filter_policy;
}
Expand Down Expand Up @@ -591,7 +593,7 @@ void ull_sync_release(struct ll_sync_set *sync)
mem_release(sync, &sync_free);
}

void ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
bool ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
uint8_t *addr, uint8_t rl_idx)
{
/* Check if Periodic Advertiser list to be used */
Expand All @@ -607,7 +609,7 @@ void ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
BDADDR_SIZE);

/* Address matched */
scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH;
return true;

/* Check in Resolving List */
} else if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY) &&
Expand All @@ -618,26 +620,34 @@ void ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
*/
scan->periodic.adv_addr_type = addr_type;

/* Mark it as identity address from RPA (0x02, 0x03) */
scan->periodic.adv_addr_type += 2U;

/* Address matched */
scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH;
return true;
}

/* Check with explicitly supplied address */
} else if ((addr_type == scan->periodic.adv_addr_type) &&
!memcmp(addr, scan->periodic.adv_addr, BDADDR_SIZE)) {
/* Address matched */
scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH;
return true;

/* Check identity address with explicitly supplied address */
} else if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY) &&
(rl_idx < ll_rl_size_get())) {
ll_rl_id_addr_get(rl_idx, &addr_type, addr);
if ((addr_type == scan->periodic.adv_addr_type) &&
!memcmp(addr, scan->periodic.adv_addr, BDADDR_SIZE)) {
/* Mark it as identity address from RPA (0x02, 0x03) */
scan->periodic.adv_addr_type += 2U;

/* Identity address matched */
scan->periodic.state = LL_SYNC_STATE_ADDR_MATCH;
return true;
}
}

return false;
}

bool ull_sync_setup_sid_match(struct ll_scan_set *scan, uint8_t sid)
Expand Down Expand Up @@ -666,6 +676,7 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
struct lll_sync *lll;
uint16_t sync_handle;
uint32_t interval_us;
uint32_t overhead_us;
struct pdu_adv *pdu;
uint16_t interval;
uint8_t chm_last;
Expand Down Expand Up @@ -699,7 +710,7 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
/* Remember the peer address.
* NOTE: Peer identity address is copied here when privacy is enable.
*/
sync->peer_id_addr_type = scan->periodic.adv_addr_type;
sync->peer_id_addr_type = scan->periodic.adv_addr_type & 0x01;
(void)memcpy(sync->peer_id_addr, scan->periodic.adv_addr,
sizeof(sync->peer_id_addr));
#endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC ||
Expand Down Expand Up @@ -749,6 +760,7 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,

/* Set the state to sync create */
scan->periodic.state = LL_SYNC_STATE_CREATED;
scan->periodic.param = NULL;
if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
struct ll_scan_set *scan_1m;

Expand All @@ -758,8 +770,10 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,

scan_coded = ull_scan_set_get(SCAN_HANDLE_PHY_CODED);
scan_coded->periodic.state = LL_SYNC_STATE_CREATED;
scan_coded->periodic.param = NULL;
} else {
scan_1m->periodic.state = LL_SYNC_STATE_CREATED;
scan_1m->periodic.param = NULL;
}
}

Expand Down Expand Up @@ -793,6 +807,22 @@ void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
sync_offset_us -= EVENT_JITTER_US;
sync_offset_us -= ready_delay_us;

/* Minimum prepare tick offset + minimum preempt tick offset are the
* overheads before ULL scheduling can setup radio for reception
*/
overhead_us = HAL_TICKER_TICKS_TO_US(HAL_TICKER_CNTR_CMP_OFFSET_MIN << 1);

/* CPU execution overhead to setup the radio for reception */
overhead_us += EVENT_OVERHEAD_END_US + EVENT_OVERHEAD_START_US;

/* If not sufficient CPU processing time, skip to receiving next
* event.
*/
if ((sync_offset_us - ftr->radio_end_us) < overhead_us) {
sync_offset_us += interval_us;
lll->event_counter++;
}

interval_us -= lll->window_widening_periodic_us;

/* TODO: active_to_start feature port */
Expand Down
2 changes: 1 addition & 1 deletion subsys/bluetooth/controller/ll_sw/ull_sync_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ int ull_sync_reset(void);
uint16_t ull_sync_handle_get(struct ll_sync_set *sync);
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_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
bool ull_sync_setup_addr_check(struct ll_scan_set *scan, uint8_t addr_type,
uint8_t *addr, uint8_t rl_idx);
bool ull_sync_setup_sid_match(struct ll_scan_set *scan, uint8_t sid);
void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
Expand Down
Loading