Bluetooth: controller: Implement CIS offset equivalent calculation

When the 'instant' of a CIS is postponed by increasing the conn_event of
the CIS_RSP compared to CIS_REQ, the CIS offset shall be calculated as
an equivalent window offset by an integer number of ISO intervals.
This is obtained by increasing the CIS_Offset_Min and CIS_Offset_Max by
the modulus of the connection interval delay time.

Signed-off-by: Morten Priess <mtpr@oticon.com>
This commit is contained in:
Morten Priess 2022-09-26 22:35:22 +02:00 committed by Fabio Baltieri
commit 78c3bf569b
3 changed files with 29 additions and 3 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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);
*/
}