diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c index 184661e7610..fa46947d7c3 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c @@ -140,14 +140,17 @@ static void rp_cc_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint static void llcp_rp_cc_tx_rsp(struct ll_conn *conn, struct proc_ctx *ctx) { - struct node_tx *tx; + uint16_t delay_conn_events; + uint16_t conn_event_count; struct pdu_data *pdu; + struct node_tx *tx; /* Allocate tx node */ tx = llcp_tx_alloc(conn, ctx); LL_ASSERT(tx); pdu = (struct pdu_data *)tx->pdu; + conn_event_count = ctx->data.cis_create.conn_event_count; /* Postpone if instant is in this or next connection event. This would handle obsolete value * due to retransmission, as well as incorrect behavior by central. @@ -157,6 +160,29 @@ static void llcp_rp_cc_tx_rsp(struct ll_conn *conn, struct proc_ctx *ctx) ctx->data.cis_create.conn_event_count = MAX(ctx->data.cis_create.conn_event_count, ull_conn_event_counter(conn) + 2); + delay_conn_events = ctx->data.cis_create.conn_event_count - conn_event_count; + + /* If instant is postponed, calculate the offset to add to CIS_Offset_Min and + * CIS_Offset_Max. + * + * BT Core v5.3, Vol 6, Part B, section 5.1.15: + * Two windows are equivalent if they have the same width and the difference between their + * start times is an integer multiple of ISO_Interval for the CIS. + * + * The offset shall compensate for the relation between ISO- and connection interval. The + * offset translates to what is additionally needed to move the window by an integer number + * of ISO intervals. I.e.: + * offset = (delayed * CONN_interval) MOD ISO_interval + */ + if (delay_conn_events) { + uint32_t conn_interval_us = conn->lll.interval * CONN_INT_UNIT_US; + uint32_t iso_interval_us = ctx->data.cis_create.iso_interval * ISO_INT_UNIT_US; + uint32_t offset_us = (delay_conn_events * conn_interval_us) % iso_interval_us; + + ctx->data.cis_create.cis_offset_min += offset_us; + ctx->data.cis_create.cis_offset_max += offset_us; + } + llcp_pdu_encode_cis_rsp(ctx, pdu); ctx->tx_opcode = pdu->llctrl.opcode; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h index 0502983dcfc..dfe2460c2d6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h @@ -258,6 +258,7 @@ struct proc_ctx { uint8_t cig_id; uint8_t cis_id; uint16_t conn_event_count; + uint16_t iso_interval; uint32_t cis_offset_min; uint32_t cis_offset_max; #if defined(CONFIG_BT_PERIPHERAL) @@ -281,7 +282,6 @@ struct proc_ctx { uint8_t c_bn; uint8_t c_ft; uint8_t p_ft; - uint16_t iso_interval; uint8_t aa[4]; #endif /* defined(CONFIG_BT_CENTRAL) */ } cis_create; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c index 74c62d7f9f6..336f9934b30 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c @@ -775,6 +775,7 @@ void llcp_pdu_decode_cis_req(struct proc_ctx *ctx, struct pdu_data *pdu) ctx->data.cis_create.cis_offset_max = sys_get_le24(pdu->llctrl.cis_req.cis_offset_max); ctx->data.cis_create.conn_event_count = sys_le16_to_cpu(pdu->llctrl.cis_req.conn_event_count); + ctx->data.cis_create.iso_interval = sys_le16_to_cpu(pdu->llctrl.cis_req.iso_interval); /* The remainder of the req is decoded by ull_peripheral_iso_acquire, so * no need to do it here too ctx->data.cis_create.c_phy = pdu->llctrl.cis_req.c_phy; @@ -792,7 +793,6 @@ void llcp_pdu_decode_cis_req(struct proc_ctx *ctx, struct pdu_data *pdu) ctx->data.cis_create.c_bn = pdu->llctrl.cis_req.c_bn; ctx->data.cis_create.c_ft = pdu->llctrl.cis_req.c_ft; ctx->data.cis_create.p_ft = pdu->llctrl.cis_req.p_ft; - ctx->data.cis_create.iso_interval = sys_le16_to_cpu(pdu->llctrl.cis_req.iso_interval); */ }