diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index c8bc9368ea9..6fdbb75b3b8 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -8064,12 +8064,25 @@ uint16_t ull_conn_event_counter(struct ll_conn *conn) struct lll_conn *lll; uint16_t event_counter; - uint16_t lazy = conn->llcp.prep.lazy; - lll = &conn->lll; - /* Calculate current event counter */ - event_counter = lll->event_counter + lll->latency_prepare + lazy; + /* Calculate current event counter. If refcount is non-zero, we have called + * prepare and the LLL implementation has calculated and incremented the event + * counter (RX path). In this case we need to subtract one from the current + * event counter. + * Otherwise we are in the TX path, and we calculate the current event counter + * similar to LLL by taking the expected event counter value plus accumulated + * latency. + */ + if (ull_ref_get(&conn->ull)) { + /* We are in post-prepare (RX path). Event counter is already + * calculated and incremented by 1 for next event. + */ + event_counter = lll->event_counter - 1; + } else { + event_counter = lll->event_counter + lll->latency_prepare + + conn->llcp.prep.lazy; + } return event_counter; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c index 1dde5bec746..184661e7610 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c @@ -89,22 +89,6 @@ static void cc_ntf_established(struct ll_conn *conn, struct proc_ctx *ctx) } #if defined(CONFIG_BT_PERIPHERAL) -static uint16_t cc_event_counter(struct ll_conn *conn) -{ - struct lll_conn *lll; - uint16_t event_counter; - - uint16_t lazy = conn->llcp.prep.lazy; - - /**/ - lll = &conn->lll; - - /* Calculate current event counter */ - event_counter = lll->event_counter + lll->latency_prepare + lazy; - - return event_counter; -} - /* LLCP Remote Procedure FSM states */ enum { /* Establish Procedure */ @@ -147,6 +131,9 @@ enum { RP_CC_EVT_UNKNOWN, }; +static void rp_cc_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, + void *param); + /* * LLCP Remote Procedure FSM */ @@ -162,8 +149,13 @@ static void llcp_rp_cc_tx_rsp(struct ll_conn *conn, struct proc_ctx *ctx) pdu = (struct pdu_data *)tx->pdu; + /* 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. + * We need at least 2 connection events to get ready. First for receiving the indication, + * the second for setting up the CIS. + */ ctx->data.cis_create.conn_event_count = MAX(ctx->data.cis_create.conn_event_count, - cc_event_counter(conn) + 2); + ull_conn_event_counter(conn) + 2); llcp_pdu_encode_cis_rsp(ctx, pdu); ctx->tx_opcode = pdu->llctrl.opcode; @@ -380,19 +372,13 @@ static void rp_cc_state_wait_rx_cis_ind(struct ll_conn *conn, struct proc_ctx *c case RP_CC_EVT_CIS_IND: llcp_pdu_decode_cis_ind(ctx, pdu); if (!ull_peripheral_iso_setup(&pdu->llctrl.cis_ind, ctx->data.cis_create.cig_id, - ctx->data.cis_create.cis_handle)) { + ctx->data.cis_create.cis_handle)) { /* CIS has been setup, go wait for 'instant' before starting */ ctx->state = RP_CC_STATE_WAIT_INSTANT; - /* Fixme - Implement CIS Supervision timeout - * Spec: - * When establishing a CIS, the Peripheral shall start the CIS supervision - * timer at the start of the next CIS event after receiving the LL_CIS_IND. - * If the CIS supervision timer reaches 6 * ISO_Interval before the CIS is - * established, the CIS shall be considered lost. - */ - + /* Check if this connection event is where we need to start the CIS */ + rp_cc_check_instant(conn, ctx, evt, param); break; } /* If we get to here the CIG_ID referred in req/acquire has become void/invalid */ @@ -454,7 +440,7 @@ static void rp_cc_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint } if (is_instant_reached_or_passed(start_event_count, - cc_event_counter(conn))) { + ull_conn_event_counter(conn))) { /* Start CIS */ ull_conn_iso_start(conn, conn->llcp.prep.ticks_at_expire, ctx->data.cis_create.cis_handle); @@ -625,6 +611,11 @@ void llcp_rp_cc_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param) { rp_cc_execute_fsm(conn, ctx, RP_CC_EVT_RUN, param); } + +bool llcp_rp_cc_awaiting_instant(struct proc_ctx *ctx) +{ + return (ctx->state == RP_CC_STATE_WAIT_INSTANT); +} #endif /* CONFIG_BT_PERIPHERAL */ #if defined(CONFIG_BT_CTLR_CENTRAL_ISO) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c index 5bc4b615e46..02f375716dc 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c @@ -204,6 +204,10 @@ void llcp_lp_chmu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param) lp_chmu_execute_fsm(conn, ctx, LP_CHMU_EVT_RUN, param); } +bool llcp_lp_chmu_awaiting_instant(struct proc_ctx *ctx) +{ + return (ctx->state == LP_CHMU_STATE_WAIT_INSTANT); +} #endif /* CONFIG_BT_CENTRAL */ #if defined(CONFIG_BT_PERIPHERAL) @@ -320,4 +324,9 @@ void llcp_rp_chmu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param) { rp_chmu_execute_fsm(conn, ctx, RP_CHMU_EVT_RUN, param); } + +bool llcp_rp_chmu_awaiting_instant(struct proc_ctx *ctx) +{ + return (ctx->state == RP_CHMU_STATE_WAIT_INSTANT); +} #endif /* CONFIG_BT_PERIPHERAL */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c index fadd6846082..c2cd4115f8e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c @@ -1225,6 +1225,16 @@ void llcp_rp_cu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param) rp_cu_execute_fsm(conn, ctx, RP_CU_EVT_RUN, param); } +bool llcp_rp_cu_awaiting_instant(struct proc_ctx *ctx) +{ + return (ctx->state == RP_CU_STATE_WAIT_INSTANT); +} + +bool llcp_lp_cu_awaiting_instant(struct proc_ctx *ctx) +{ + return (ctx->state == LP_CU_STATE_WAIT_INSTANT); +} + #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) void llcp_rp_conn_param_req_reply(struct ll_conn *conn, struct proc_ctx *ctx) { diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h index ef502fc9754..0502983dcfc 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h @@ -458,6 +458,7 @@ void llcp_lp_pu_init_proc(struct proc_ctx *ctx); void llcp_lp_pu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param); void llcp_lp_pu_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, void *param); void llcp_lp_pu_tx_ntf(struct ll_conn *conn, struct proc_ctx *ctx); +bool llcp_lp_pu_awaiting_instant(struct proc_ctx *ctx); #endif /* CONFIG_BT_CTLR_PHY */ /* @@ -466,6 +467,7 @@ void llcp_lp_pu_tx_ntf(struct ll_conn *conn, struct proc_ctx *ctx); void llcp_lp_cu_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx); void llcp_lp_cu_init_proc(struct proc_ctx *ctx); void llcp_lp_cu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param); +bool llcp_lp_cu_awaiting_instant(struct proc_ctx *ctx); /* * LLCP Local Channel Map Update @@ -473,6 +475,7 @@ void llcp_lp_cu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param); void llcp_lp_chmu_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx); void llcp_lp_chmu_init_proc(struct proc_ctx *ctx); void llcp_lp_chmu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param); +bool llcp_lp_chmu_awaiting_instant(struct proc_ctx *ctx); #if defined(CONFIG_BT_CTLR_PHY) /* @@ -483,6 +486,7 @@ void llcp_rp_pu_init_proc(struct proc_ctx *ctx); void llcp_rp_pu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param); void llcp_rp_pu_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, void *param); void llcp_rp_pu_tx_ntf(struct ll_conn *conn, struct proc_ctx *ctx); +bool llcp_rp_pu_awaiting_instant(struct proc_ctx *ctx); #endif /* CONFIG_BT_CTLR_PHY */ /* @@ -495,6 +499,7 @@ void llcp_rp_conn_param_req_reply(struct ll_conn *conn, struct proc_ctx *ctx); void llcp_rp_conn_param_req_neg_reply(struct ll_conn *conn, struct proc_ctx *ctx); bool llcp_rp_conn_param_req_apm_awaiting_reply(struct proc_ctx *ctx); void llcp_rp_conn_param_req_apm_reply(struct ll_conn *conn, struct proc_ctx *ctx); +bool llcp_rp_cu_awaiting_instant(struct proc_ctx *ctx); /* * Terminate Helper @@ -659,6 +664,7 @@ void llcp_pdu_decode_chan_map_update_ind(struct proc_ctx *ctx, struct pdu_data * void llcp_rp_chmu_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx); void llcp_rp_chmu_init_proc(struct proc_ctx *ctx); void llcp_rp_chmu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param); +bool llcp_rp_chmu_awaiting_instant(struct proc_ctx *ctx); #if defined(CONFIG_BT_CTLR_DATA_LENGTH) /* @@ -712,6 +718,7 @@ void llcp_rp_cc_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param); bool llcp_rp_cc_awaiting_reply(struct proc_ctx *ctx); void llcp_rp_cc_accept(struct ll_conn *conn, struct proc_ctx *ctx); void llcp_rp_cc_reject(struct ll_conn *conn, struct proc_ctx *ctx); +bool llcp_rp_cc_awaiting_instant(struct proc_ctx *ctx); void llcp_pdu_decode_cis_req(struct proc_ctx *ctx, struct pdu_data *pdu); void llcp_pdu_encode_cis_rsp(struct proc_ctx *ctx, struct pdu_data *pdu); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c index 8aec2838dc4..25a43382a9c 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c @@ -892,6 +892,12 @@ void llcp_lp_pu_tx_ntf(struct ll_conn *conn, struct proc_ctx *ctx) { lp_pu_execute_fsm(conn, ctx, LP_PU_EVT_NTF, NULL); } + +bool llcp_lp_pu_awaiting_instant(struct proc_ctx *ctx) +{ + return (ctx->state == LP_PU_STATE_WAIT_INSTANT); +} + /* * LLCP Remote Procedure PHY Update FSM */ @@ -1318,3 +1324,8 @@ void llcp_rp_pu_tx_ntf(struct ll_conn *conn, struct proc_ctx *ctx) { rp_pu_execute_fsm(conn, ctx, RP_PU_EVT_NTF, NULL); } + +bool llcp_rp_pu_awaiting_instant(struct proc_ctx *ctx) +{ + return (ctx->state == RP_PU_STATE_WAIT_INSTANT); +} diff --git a/tests/bluetooth/controller/mock_ctrl/src/ull_conn_iso.c b/tests/bluetooth/controller/mock_ctrl/src/ull_conn_iso.c index fcde35cdcb6..daf70974a46 100644 --- a/tests/bluetooth/controller/mock_ctrl/src/ull_conn_iso.c +++ b/tests/bluetooth/controller/mock_ctrl/src/ull_conn_iso.c @@ -54,6 +54,11 @@ struct ll_conn_iso_stream *ll_conn_iso_stream_get(uint16_t handle) return &cis; } +struct ll_conn_iso_stream *ll_iso_stream_connected_get(uint16_t handle) +{ + return &cis; +} + struct ll_conn_iso_group *ll_conn_iso_group_get_by_id(uint8_t id) { return &cig;