From 3b3d53f09e1f39d9444c00a017dfaeac3b1a45e4 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 14 May 2023 15:32:02 +0530 Subject: [PATCH] Bluetooth: Controller: Fix CIS offset_min for dissimilar interval Fix CIS offset_min calculation to consider that ACL interval and ISO interval can be dissimilar and the offset value has to be compensated for the latency until the instant at which the offset is used. Signed-off-by: Vinayak Kariappa Chettimada --- .../bluetooth/controller/ll_sw/lll_conn_iso.h | 2 ++ subsys/bluetooth/controller/ll_sw/pdu.h | 1 + .../controller/ll_sw/ull_central_iso.c | 32 +++++++++++++++++-- .../controller/ll_sw/ull_peripheral_iso.c | 2 +- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h index 66bd71d39e9..89be10c9ba8 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h @@ -53,6 +53,8 @@ struct lll_conn_iso_stream { memq_link_t *link_tx_free; }; +#define LLL_CONN_ISO_EVENT_COUNT_MAX BIT64_MASK(39) + struct lll_conn_iso_group { struct lll_hdr hdr; diff --git a/subsys/bluetooth/controller/ll_sw/pdu.h b/subsys/bluetooth/controller/ll_sw/pdu.h index 79abe60bfb9..4fd61e81514 100644 --- a/subsys/bluetooth/controller/ll_sw/pdu.h +++ b/subsys/bluetooth/controller/ll_sw/pdu.h @@ -351,6 +351,7 @@ ((enc) ? \ (PDU_MIC_SIZE) : 0), \ (phy)) +#define PDU_CIS_OFFSET_MIN_US 500U struct pdu_adv_adv_ind { uint8_t addr[BDADDR_SIZE]; diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index beda9f54557..1f7f4418c4f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -563,7 +563,7 @@ void ll_cis_create(uint16_t cis_handle, uint16_t acl_handle) /* Initialize stream states */ cis->established = 0; cis->teardown = 0; - cis->lll.event_count = 0; + cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX; cis->lll.sn = 0; cis->lll.nesn = 0; cis->lll.cie = 0; @@ -732,7 +732,6 @@ uint8_t ull_central_iso_setup(uint16_t cis_handle, #endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */ cis->central.instant = instant; - cis->lll.event_count = -1; cis->lll.next_subevent = 0U; cis->lll.sn = 0U; cis->lll.nesn = 0U; @@ -863,10 +862,13 @@ static void cis_offset_get(struct ll_conn_iso_stream *cis) static void mfy_cis_offset_get(void *param) { + uint32_t elapsed_acl_us, elapsed_cig_us; + uint16_t latency_acl, latency_cig; struct ll_conn_iso_stream *cis; struct ll_conn_iso_group *cig; uint32_t cig_remainder_us; uint32_t acl_remainder_us; + uint32_t cig_interval_us; uint32_t ticks_to_expire; uint32_t ticks_current; uint32_t offset_min_us; @@ -953,6 +955,32 @@ static void mfy_cis_offset_get(void *param) cig_remainder_us + cig->sync_delay - acl_remainder_us - cis->sync_delay; + /* Calculate instant latency */ + /* 32-bits are sufficient as maximum connection interval is 4 seconds, + * and latency counts (typically 3) is low enough to avoid 32-bit + * overflow. Refer to ull_central_iso_cis_offset_get(). + */ + latency_acl = cis->central.instant - ull_conn_event_counter(conn); + elapsed_acl_us = latency_acl * conn->lll.interval * CONN_INT_UNIT_US; + + /* Calculate elapsed CIG intervals until the instant */ + cig_interval_us = cig->iso_interval * ISO_INT_UNIT_US; + latency_cig = DIV_ROUND_UP(elapsed_acl_us, cig_interval_us); + elapsed_cig_us = latency_cig * cig_interval_us; + + /* Compensate for the difference between ACL elapsed vs CIG elapsed */ + offset_min_us += elapsed_cig_us - elapsed_acl_us; + while (offset_min_us > (cig_interval_us + PDU_CIS_OFFSET_MIN_US)) { + offset_min_us -= cig_interval_us; + } + + /* Decrement event_count to compensate for offset_min_us greater than + * CIG interval due to offset being atleast PDU_CIS_OFFSET_MIN_US. + */ + if (offset_min_us > cig_interval_us) { + cis->lll.event_count--; + } + ull_cp_cc_offset_calc_reply(conn, offset_min_us, offset_min_us); } diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index ef59ac520dd..af17dd9347d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -319,7 +319,7 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind, cis->sync_delay = sys_get_le24(ind->cis_sync_delay); cis->offset = cis_offset; memcpy(cis->lll.access_addr, ind->aa, sizeof(ind->aa)); - cis->lll.event_count = -1; + cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX; cis->lll.next_subevent = 0U; cis->lll.sn = 0U; cis->lll.nesn = 0U;