Skip to content

Commit

Permalink
Bluetooth: Controller: Separate SDU interval for C_to_P and P_to_C
Browse files Browse the repository at this point in the history
Support for separate SDU interval for C_to_P and P_to_C
directions when setting CIG parameters.

Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
  • Loading branch information
cvinayak committed Jul 30, 2024
1 parent 3bcaa6f commit ca4c50a
Showing 1 changed file with 40 additions and 19 deletions.
59 changes: 40 additions & 19 deletions subsys/bluetooth/controller/ll_sw/ull_central_iso.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ static void mfy_cis_offset_get(void *param);
static void ticker_op_cb(uint32_t status, void *param);
#endif /* CONFIG_BT_CTLR_CENTRAL_SPACING == 0 */

static void set_bn_max_pdu(bool framed, uint32_t iso_interval,
uint32_t sdu_interval, uint16_t max_sdu, uint8_t *bn,
uint8_t *max_pdu);
static uint32_t set_bn_max_pdu(bool framed, uint32_t iso_interval,
uint32_t iso_interval_cig, uint32_t sdu_interval,
uint16_t max_sdu, uint8_t *bn, uint8_t *max_pdu);
static uint8_t ll_cig_parameters_validate(void);
static uint8_t ll_cis_parameters_validate(uint8_t cis_idx, uint8_t cis_id,
uint16_t c_sdu, uint16_t p_sdu,
Expand Down Expand Up @@ -154,6 +154,7 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles)
uint16_t cis_created_handles[STREAMS_PER_GROUP];
struct ll_conn_iso_stream *cis;
struct ll_conn_iso_group *cig;
uint32_t iso_interval_cig_us;
uint32_t iso_interval_us;
uint32_t cig_sync_delay;
uint32_t max_se_length;
Expand Down Expand Up @@ -228,19 +229,19 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles)
* handle the throughput. For unframed these must be divisible, if they're not,
* framed mode must be forced.
*/
cig->iso_interval = cig->c_sdu_interval / ISO_INT_UNIT_US;
iso_interval_us = cig->c_sdu_interval;

if (cig->iso_interval < BT_HCI_ISO_INTERVAL_MIN) {
if (iso_interval_us < 5000U) {
/* ISO_Interval is below minimum (5 ms) */
cig->iso_interval = BT_HCI_ISO_INTERVAL_MIN;
iso_interval_us = 5000U;
}

#if defined(CONFIG_BT_CTLR_CONN_ISO_AVOID_SEGMENTATION)
/* Check if this is a HAP usecase which requires higher link bandwidth to ensure
* segmentation is not invoked in ISO-AL.
*/
if (cig->central.framing && cig->c_sdu_interval == 10000U) {
cig->iso_interval = 6; /* 7500 us */
iso_interval_us = 7500U; /* us */
}
#endif

Expand All @@ -252,8 +253,7 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles)
}
}

iso_interval_us = cig->iso_interval * ISO_INT_UNIT_US;
cig->lll.iso_interval_us = iso_interval_us;
iso_interval_cig_us = iso_interval_us;

lll_hdr_init(&cig->lll, cig);
max_se_length = 0U;
Expand Down Expand Up @@ -360,29 +360,43 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles)
* directions
*/
if (tx) {
uint32_t iso_interval_adjust_us;
uint8_t max_pdu;
uint8_t bn;

bn = cis->lll.tx.bn;
max_pdu = cis->lll.tx.max_pdu;
set_bn_max_pdu(cis->framed, iso_interval_us,
cig->c_sdu_interval,
cis->c_max_sdu, &bn, &max_pdu);
iso_interval_adjust_us =
set_bn_max_pdu(cis->framed, iso_interval_us,
iso_interval_cig_us, cig->c_sdu_interval,
cis->c_max_sdu, &bn, &max_pdu);
if (iso_interval_adjust_us != iso_interval_us) {
iso_interval_us = iso_interval_adjust_us;

goto ll_cig_parameters_commit_retry;
}
cis->lll.tx.bn = bn;
cis->lll.tx.max_pdu = max_pdu;
} else {
cis->lll.tx.bn = 0U;
}

if (rx) {
uint32_t iso_interval_adjust_us;
uint8_t max_pdu;
uint8_t bn;

bn = cis->lll.rx.bn;
max_pdu = cis->lll.rx.max_pdu;
set_bn_max_pdu(cis->framed, iso_interval_us,
cig->p_sdu_interval,
cis->p_max_sdu, &bn, &max_pdu);
iso_interval_adjust_us =
set_bn_max_pdu(cis->framed, iso_interval_us,
iso_interval_cig_us, cig->p_sdu_interval,
cis->p_max_sdu, &bn, &max_pdu);
if (iso_interval_adjust_us != iso_interval_us) {
iso_interval_us = iso_interval_adjust_us;

goto ll_cig_parameters_commit_retry;
}
cis->lll.rx.bn = bn;
cis->lll.rx.max_pdu = max_pdu;
} else {
Expand All @@ -402,6 +416,9 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles)
(cis->central.p_rtn + 1) * cis->lll.rx.bn);
}

cig->lll.iso_interval_us = iso_interval_us;
cig->iso_interval = iso_interval_us / ISO_INT_UNIT_US;

handle_iter = UINT16_MAX;
total_time = 0U;

Expand Down Expand Up @@ -1170,9 +1187,9 @@ static void ticker_op_cb(uint32_t status, void *param)
}
#endif /* CONFIG_BT_CTLR_CENTRAL_SPACING == 0 */

static void set_bn_max_pdu(bool framed, uint32_t iso_interval,
uint32_t sdu_interval, uint16_t max_sdu, uint8_t *bn,
uint8_t *max_pdu)
static uint32_t set_bn_max_pdu(bool framed, uint32_t iso_interval,
uint32_t iso_interval_cig, uint32_t sdu_interval,
uint16_t max_sdu, uint8_t *bn, uint8_t *max_pdu)
{
if (framed) {
uint32_t max_drift_us;
Expand Down Expand Up @@ -1222,13 +1239,17 @@ static void set_bn_max_pdu(bool framed, uint32_t iso_interval,
}
} else {
/* For unframed, ISO_Interval must be N x SDU_Interval */
LL_ASSERT(iso_interval % sdu_interval == 0);
if ((iso_interval % sdu_interval) != 0) {
iso_interval += iso_interval_cig;
}

/* Core 5.3 Vol 6, Part G section 2.1:
* BN >= ceil(Max_SDU/Max_PDU * ISO_Interval/SDU_Interval)
*/
*bn = DIV_ROUND_UP(max_sdu * iso_interval, (*max_pdu) * sdu_interval);
}

return iso_interval;
}

static uint8_t ll_cig_parameters_validate(void)
Expand Down

0 comments on commit ca4c50a

Please sign in to comment.