From 0475687f34f596004ec8ef3ffac3e38056cb1bfb Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 17 Oct 2024 20:21:08 +0200 Subject: [PATCH] nimble/ll: Fix offset calculation in BIGInfo Offset calculation in BIGInfo assumes BIG event start time is always after AUX_SYNC_IND since BIG should be advanced to next event by the time AUX_SYNC_IND is sent. However, if AUX_SYNC_IND is scheduled close to BIG event this may not happend and thus calculated offset is invalid. This makes sure that we always use BIG event after AUX_SYNC_IND to calculate offset. --- nimble/controller/src/ble_ll_adv.c | 1 - nimble/controller/src/ble_ll_iso_big.c | 30 ++++++++++++++++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index fb7aee633..46c4cc93c 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -2191,7 +2191,6 @@ ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) sync->sch.start_time + g_ble_ll_sched_offset_ticks, sync->sch.remainder); - BLE_LL_ASSERT(biginfo_len > 0); dptr += biginfo_len; } diff --git a/nimble/controller/src/ble_ll_iso_big.c b/nimble/controller/src/ble_ll_iso_big.c index 19af3e61f..0fffe3ed7 100644 --- a/nimble/controller/src/ble_ll_iso_big.c +++ b/nimble/controller/src/ble_ll_iso_big.c @@ -307,20 +307,38 @@ ble_ll_iso_big_biginfo_copy(struct ble_ll_iso_big *big, uint8_t *dptr, uint32_t base_ticks, uint8_t base_rem_us) { uint8_t *dptr_start; + uint32_t event_start; + uint8_t event_start_us; uint64_t counter; uint32_t offset_us; uint32_t offset; - uint32_t d_ticks; - uint8_t d_rem_us; dptr_start = dptr; counter = big->bis_counter; - d_ticks = big->event_start - base_ticks; - d_rem_us = big->event_start_us; - ble_ll_tmr_sub(&d_ticks, &d_rem_us, base_rem_us); + event_start = big->event_start; + event_start_us = big->event_start_us; + + /* Use next BIG event in case current one is before AUX_SYNC_IND. This can + * happen if AUX_SYNC_IND is scheduled right after BIG event and the BIG + * was not yet advanced to next event. + */ + if (event_start <= base_ticks) { + ble_ll_tmr_add(&event_start, &event_start_us, big->iso_interval * 1250); + counter++; + } + + /* Drop BIGInfo if BIG event is still before AUX_SYNC_IND. This should not + * happen but better not send invalid offset. + */ + if (event_start <= base_ticks) { + return 0; + } + + offset_us = ble_ll_tmr_t2u(event_start - base_ticks); + offset_us += event_start_us; + offset_us -= base_rem_us; - offset_us = ble_ll_tmr_t2u(d_ticks) + d_rem_us; if (offset_us <= 600) { counter += big->bn; offset_us += big->iso_interval * 1250;