From 76439d0ba4ddd97a910fdede8b849c4624b8aae6 Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Fri, 28 Oct 2022 13:01:45 +0200 Subject: [PATCH] Bluetooth: controller: integrating SCA procedure and adding HCI API Adding controller support for updating SCA in ACL and ISO peripherals Adding HCI API support for le_request_peer_sca and complete event. Signed-off-by: Erik Brockhoff --- subsys/bluetooth/controller/hci/hci.c | 55 +++++++ subsys/bluetooth/controller/include/ll.h | 1 + subsys/bluetooth/controller/ll_sw/ull.c | 8 + subsys/bluetooth/controller/ll_sw/ull_conn.c | 148 ++++++++++++------ .../controller/ll_sw/ull_conn_internal.h | 2 + .../controller/ll_sw/ull_conn_iso_types.h | 1 + .../controller/ll_sw/ull_llcp_common.c | 22 +++ .../controller/ll_sw/ull_peripheral_iso.c | 78 +++++++++ .../ll_sw/ull_peripheral_iso_internal.h | 1 + .../mock_ctrl/src/ull_peripheral_iso.c | 4 + 10 files changed, 271 insertions(+), 49 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 25ac6f6ceaa..bdf6e79f10d 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -2418,6 +2418,20 @@ static void le_reject_cis(struct net_buf *buf, struct net_buf **evt) #endif /* CONFIG_BT_PERIPHERAL */ #if defined(CONFIG_BT_CONN) +#if defined(CONFIG_BT_CTLR_SCA_UPDATE) +static void le_req_peer_sca(struct net_buf *buf, struct net_buf **evt) +{ + struct bt_hci_cp_le_req_peer_sca *cmd = (void *)buf->data; + uint16_t handle; + uint8_t status; + + handle = sys_le16_to_cpu(cmd->handle); + status = ll_req_peer_sca(handle); + + *evt = cmd_status(status); +} +#endif /* CONFIG_BT_CTLR_SCA_UPDATE */ + #if defined(CONFIG_BT_CENTRAL) || defined(CONFIG_BT_CTLR_PER_INIT_FEAT_XCHG) static void le_read_remote_features(struct net_buf *buf, struct net_buf **evt) { @@ -4348,6 +4362,12 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd, #endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */ #endif /* CONFIG_BT_PERIPHERAL */ +#if defined(CONFIG_BT_CTLR_SCA_UPDATE) + case BT_OCF(BT_HCI_OP_LE_REQ_PEER_SC): + le_req_peer_sca(cmd, evt); + break; +#endif /* CONFIG_BT_CTLR_SCA_UPDATE */ + #if defined(CONFIG_BT_CTLR_ISO) case BT_OCF(BT_HCI_OP_LE_SETUP_ISO_PATH): le_setup_iso_path(cmd, evt); @@ -8014,6 +8034,31 @@ static void le_phy_upd_complete(struct pdu_data *pdu_data, uint16_t handle, sep->rx_phy = find_lsb_set(pu->rx); } #endif /* CONFIG_BT_CTLR_PHY */ + +#if defined(CONFIG_BT_CTLR_SCA_UPDATE) +static void le_req_peer_sca_complete(struct pdu_data *pdu, uint16_t handle, + struct net_buf *buf) +{ + struct bt_hci_evt_le_req_peer_sca_complete *sep; + struct node_rx_sca *scau; + + scau = (void *)pdu; + + if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) || + !(le_event_mask & BT_EVT_MASK_LE_REQ_PEER_SCA_COMPLETE)) { + BT_WARN("handle: 0x%04x, status: %x, sca: %x.", handle, + scau->status, + scau->sca); + return; + } + + sep = meta_evt(buf, BT_HCI_EVT_LE_REQ_PEER_SCA_COMPLETE, sizeof(*sep)); + + sep->status = scau->status; + sep->handle = sys_cpu_to_le16(handle); + sep->sca = scau->sca; +} +#endif /* CONFIG_BT_CTLR_SCA_UPDATE */ #endif /* CONFIG_BT_CONN */ #if defined(CONFIG_BT_HCI_MESH_EXT) @@ -8181,6 +8226,12 @@ static void encode_control(struct node_rx_pdu *node_rx, return; #endif /* CONFIG_BT_CTLR_CONN_ISO */ +#if defined(CONFIG_BT_CTLR_SCA_UPDATE) + case NODE_RX_TYPE_REQ_PEER_SCA_COMPLETE: + le_req_peer_sca_complete(pdu_data, handle, buf); + return; +#endif /* CONFIG_BT_CTLR_SCA_UPDATE */ + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: #if defined(CONFIG_BT_CTLR_DF_VS_CONN_IQ_REPORT_16_BITS_IQ_SAMPLES) @@ -8637,6 +8688,10 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx) case NODE_RX_TYPE_CIS_REQUEST: #endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */ +#if defined(CONFIG_BT_CTLR_SCA_UPDATE) + case NODE_RX_TYPE_REQ_PEER_SCA_COMPLETE: +#endif /* CONFIG_BT_CTLR_SCA_UPDATE */ + #if defined(CONFIG_BT_CTLR_CONN_ISO) case NODE_RX_TYPE_CIS_ESTABLISHED: #endif /* CONFIG_BT_CTLR_CONN_ISO */ diff --git a/subsys/bluetooth/controller/include/ll.h b/subsys/bluetooth/controller/include/ll.h index 094006ee5f5..2d848ea3211 100644 --- a/subsys/bluetooth/controller/include/ll.h +++ b/subsys/bluetooth/controller/include/ll.h @@ -246,6 +246,7 @@ uint8_t ll_enc_req_send(uint16_t handle, uint8_t const *const rand_num, uint8_t uint8_t const *const ltk); uint8_t ll_start_enc_req_send(uint16_t handle, uint8_t err_code, uint8_t const *const ltk); +uint8_t ll_req_peer_sca(uint16_t handle); uint8_t ll_feature_req_send(uint16_t handle); uint8_t ll_version_ind_send(uint16_t handle); uint8_t ll_terminate_ind_send(uint16_t handle, uint8_t reason); diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index 6cec7717894..6aa7c96a708 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -1305,6 +1305,10 @@ void ll_rx_dequeue(void) case NODE_RX_TYPE_CIS_REQUEST: #endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */ +#if defined(CONFIG_BT_CTLR_SCA_UPDATE) + case NODE_RX_TYPE_REQ_PEER_SCA_COMPLETE: +#endif /* CONFIG_BT_CTLR_SCA_UPDATE */ + #if defined(CONFIG_BT_CTLR_CONN_ISO) case NODE_RX_TYPE_CIS_ESTABLISHED: #endif /* CONFIG_BT_CTLR_CONN_ISO */ @@ -1503,6 +1507,10 @@ void ll_rx_mem_release(void **node_rx) case NODE_RX_TYPE_CIS_ESTABLISHED: #endif /* CONFIG_BT_CTLR_CONN_ISO */ +#if defined(CONFIG_BT_CTLR_SCA_UPDATE) + case NODE_RX_TYPE_REQ_PEER_SCA_COMPLETE: +#endif /* CONFIG_BT_CTLR_SCA_UPDATE */ + #if defined(CONFIG_BT_CTLR_ISO) case NODE_RX_TYPE_ISO_PDU: #endif diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 0f6f5c18d75..9d059c3c225 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -546,6 +546,20 @@ uint8_t ll_chm_get(uint16_t handle, uint8_t *chm) return 0; } +#if defined(CONFIG_BT_CTLR_SCA_UPDATE) +uint8_t ll_req_peer_sca(uint16_t handle) +{ + struct ll_conn *conn; + + conn = ll_connected_get(handle); + if (!conn) { + return BT_HCI_ERR_UNKNOWN_CONN_ID; + } + + return ull_cp_req_peer_sca(conn); +} +#endif /* CONFIG_BT_CTLR_SCA_UPDATE */ + static bool is_valid_disconnect_reason(uint8_t reason) { switch (reason) { @@ -7905,6 +7919,57 @@ uint16_t ull_conn_event_counter(struct ll_conn *conn) return event_counter; } +static void ull_conn_update_ticker(struct ll_conn *conn, + uint32_t ticks_win_offset, + uint32_t ticks_slot_overhead, + uint32_t periodic_us, + uint32_t ticks_at_expire) +{ +#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) + /* disable ticker job, in order to chain stop and start + * to avoid RTC being stopped if no tickers active. + */ + uint32_t mayfly_was_enabled = + mayfly_is_enabled(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW); + + mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 0U); +#endif /* CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO */ + + /* start periph/central with new timings */ + uint8_t ticker_id_conn = TICKER_ID_CONN_BASE + ll_conn_handle_get(conn); + uint32_t ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, + ticker_id_conn, ticker_stop_conn_op_cb, (void *)conn); + LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); + ticker_status = ticker_start( + TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, ticker_id_conn, ticks_at_expire, + ticks_win_offset, HAL_TICKER_US_TO_TICKS(periodic_us), + HAL_TICKER_REMAINDER(periodic_us), +#if defined(CONFIG_BT_TICKER_LOW_LAT) + TICKER_NULL_LAZY, +#else /* !CONFIG_BT_TICKER_LOW_LAT */ + TICKER_LAZY_MUST_EXPIRE_KEEP, +#endif /* CONFIG_BT_TICKER_LOW_LAT */ + (ticks_slot_overhead + conn->ull.ticks_slot), +#if defined(CONFIG_BT_PERIPHERAL) && defined(CONFIG_BT_CENTRAL) + conn->lll.role == BT_HCI_ROLE_PERIPHERAL ? + ull_periph_ticker_cb : ull_central_ticker_cb, +#elif defined(CONFIG_BT_PERIPHERAL) + ull_periph_ticker_cb, +#else + ull_central_ticker_cb, +#endif /* CONFIG_BT_PERIPHERAL && CONFIG_BT_CENTRAL */ + conn, ticker_start_conn_op_cb, (void *)conn); + LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); + +#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) + /* enable ticker job, if disabled in this function */ + if (mayfly_was_enabled) { + mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1U); + } +#endif /* CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO */ +} void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_t win_size, uint16_t win_offset_us, uint16_t interval, uint16_t latency, @@ -7916,8 +7981,6 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_ uint16_t conn_interval_old; uint16_t conn_interval_new; uint32_t conn_interval_us; - uint8_t ticker_id_conn; - uint32_t ticker_status; uint32_t periodic_us; uint16_t latency_upd; uint16_t instant_latency; @@ -7980,10 +8043,9 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_ lll->periph.window_widening_periodic_us * instant_latency; lll->periph.window_widening_periodic_us = - (((lll_clock_ppm_local_get() + lll_clock_ppm_get(conn->periph.sca)) * - conn_interval_us) + - (1000000U - 1U)) / - 1000000U; + ceiling_fraction(((lll_clock_ppm_local_get() + + lll_clock_ppm_get(conn->periph.sca)) * + conn_interval_us), 1000000U); lll->periph.window_widening_max_us = (conn_interval_us >> 1U) - EVENT_IFS_US; lll->periph.window_size_prepare_us = win_size * CONN_INT_UNIT_US; @@ -8042,53 +8104,41 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_ conn->supervision_expire = 0U; } -#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) - /* disable ticker job, in order to chain stop and start - * to avoid RTC being stopped if no tickers active. - */ - uint32_t mayfly_was_enabled = - mayfly_is_enabled(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW); - mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 0U); -#endif /* CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO */ - - /* start periph/central with new timings */ - ticker_id_conn = TICKER_ID_CONN_BASE + ll_conn_handle_get(conn); - ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, - ticker_id_conn, ticker_stop_conn_op_cb, (void *)conn); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); - ticker_status = ticker_start( - TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, ticker_id_conn, ticks_at_expire, - ticks_win_offset, HAL_TICKER_US_TO_TICKS(periodic_us), - HAL_TICKER_REMAINDER(periodic_us), -#if defined(CONFIG_BT_TICKER_LOW_LAT) - TICKER_NULL_LAZY, -#else /* !CONFIG_BT_TICKER_LOW_LAT */ - TICKER_LAZY_MUST_EXPIRE_KEEP, -#endif /* CONFIG_BT_TICKER_LOW_LAT */ - (ticks_slot_overhead + conn->ull.ticks_slot), -#if defined(CONFIG_BT_PERIPHERAL) && defined(CONFIG_BT_CENTRAL) - lll->role == BT_HCI_ROLE_PERIPHERAL ? ull_periph_ticker_cb : ull_central_ticker_cb, -#elif defined(CONFIG_BT_PERIPHERAL) - ull_periph_ticker_cb, -#else - ull_central_ticker_cb, -#endif /* CONFIG_BT_PERIPHERAL && CONFIG_BT_CENTRAL */ - conn, ticker_start_conn_op_cb, (void *)conn); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); - -#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) - /* enable ticker job, if disabled in this function */ - if (mayfly_was_enabled) { - mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1U); - } -#endif /* CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO */ - + /* Update ACL ticker */ + ull_conn_update_ticker(conn, ticks_win_offset, ticks_slot_overhead, periodic_us, + ticks_at_expire); /* Signal that the prepare needs to be canceled */ conn->cancel_prepare = 1U; } +#if defined(CONFIG_BT_PERIPHERAL) +void ull_conn_update_peer_sca(struct ll_conn *conn) +{ + struct lll_conn *lll; + + uint32_t conn_interval_us; + uint32_t periodic_us; + + lll = &conn->lll; + + /* calculate the window widening and interval */ + conn_interval_us = lll->interval * CONN_INT_UNIT_US; + periodic_us = conn_interval_us; + + lll->periph.window_widening_periodic_us = + ceiling_fraction(((lll_clock_ppm_local_get() + + lll_clock_ppm_get(conn->periph.sca)) * + conn_interval_us), 1000000U); + + periodic_us -= lll->periph.window_widening_periodic_us; + + /* Update ACL ticker */ + ull_conn_update_ticker(conn, HAL_TICKER_US_TO_TICKS(periodic_us), 0, periodic_us, + conn->llcp.prep.ticks_at_expire); + +} +#endif /* CONFIG_BT_PERIPHERAL */ + void ull_conn_chan_map_set(struct ll_conn *conn, const uint8_t chm[5]) { struct lll_conn *lll = &conn->lll; diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h index 1a4cd92ca43..435d328c11b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h @@ -85,6 +85,8 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint16_t interval, uint16_t latency, uint16_t timeout, uint16_t instant); +void ull_conn_update_peer_sca(struct ll_conn *conn); + void ull_conn_default_tx_octets_set(uint16_t tx_octets); void ull_conn_default_tx_time_set(uint16_t tx_time); diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_iso_types.h index 331a8102e3a..605fa76d850 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso_types.h @@ -49,6 +49,7 @@ struct ll_conn_iso_group { uint16_t iso_interval; uint8_t cig_id; uint8_t started:1; /* 1 if CIG started and ticker is running */ + uint8_t sca_update:4; /* (new SCA)+1 to trigger restart of ticker */ }; struct node_rx_conn_iso_req { diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index 8030d2c53f0..e445591279c 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -33,7 +33,9 @@ #include "isoal.h" #include "ull_iso_types.h" #include "ull_conn_iso_types.h" +#include "ull_iso_internal.h" #include "ull_conn_iso_internal.h" +#include "ull_peripheral_iso_internal.h" #include "ull_conn_types.h" #include "ull_chan_internal.h" @@ -544,6 +546,17 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t ctx->data.sca_update.error_code = BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL; /* Fall through to complete procedure */ case PDU_DATA_LLCTRL_TYPE_CLOCK_ACCURACY_RSP: +#if defined(CONFIG_BT_PERIPHERAL) + if (conn->lll.role == BT_HCI_ROLE_PERIPHERAL && + !ctx->data.sca_update.error_code && + conn->periph.sca != ctx->data.sca_update.sca) { + conn->periph.sca = ctx->data.sca_update.sca; + ull_conn_update_peer_sca(conn); +#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) + ull_peripheral_iso_update_peer_sca(conn); +#endif /* defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */ + } +#endif /* CONFIG_BT_PERIPHERAL */ lp_sca_ntf(conn, ctx); llcp_lr_complete(conn); ctx->state = LP_COMMON_STATE_IDLE; @@ -1394,6 +1407,15 @@ static void rp_comm_st_wait_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, u #if defined(CONFIG_BT_CTLR_SCA_UPDATE) case PROC_SCA_UPDATE: { ctx->tx_ack = NULL; +#if defined(CONFIG_BT_PERIPHERAL) + if (conn->lll.role == BT_HCI_ROLE_PERIPHERAL) { + conn->periph.sca = ctx->data.sca_update.sca; + ull_conn_update_peer_sca(conn); +#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) + ull_peripheral_iso_update_peer_sca(conn); +#endif /* defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */ + } +#endif /* CONFIG_BT_PERIPHERAL */ llcp_rr_complete(conn); ctx->state = RP_COMMON_STATE_IDLE; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index 289e1dfe93a..b3d57128b3a 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -314,6 +314,10 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind, return 0; } +static void ull_peripheral_iso_update_ticker(struct ll_conn_iso_group *cig, + uint32_t ticks_at_expire, + uint32_t iso_interval_us_frac); + static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, uint32_t remainder, uint16_t lazy, uint8_t force, void *param) @@ -387,6 +391,21 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, p.param = &cig->lll; mfy.param = &p; + if (cig->sca_update) { + /* CIG/ACL affilaition established */ + uint32_t iso_interval_us_frac = + EVENT_US_TO_US_FRAC(cig->iso_interval * CONN_INT_UNIT_US); + + cig->lll.window_widening_periodic_us_frac = + ceiling_fraction(((lll_clock_ppm_local_get() + + lll_clock_ppm_get(cig->sca_update - 1)) * + iso_interval_us_frac), + 1000000U); + iso_interval_us_frac -= cig->lll.window_widening_periodic_us_frac; + + ull_peripheral_iso_update_ticker(cig, ticks_at_expire, iso_interval_us_frac); + cig->sca_update = 0; + } /* Kick LLL prepare */ err = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); @@ -403,6 +422,35 @@ static void ticker_op_cb(uint32_t status, void *param) LL_ASSERT(status == TICKER_STATUS_SUCCESS); } +static void ull_peripheral_iso_update_ticker(struct ll_conn_iso_group *cig, + uint32_t ticks_at_expire, + uint32_t iso_interval_us_frac) +{ + + /* stop/start with new updated timings */ + uint8_t ticker_id_cig = TICKER_ID_CONN_ISO_BASE + ll_conn_iso_group_handle_get(cig); + uint32_t ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, + ticker_id_cig, ticker_op_cb, NULL); + LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); + + ticker_status = ticker_start(TICKER_INSTANCE_ID_CTLR, + TICKER_USER_ID_ULL_HIGH, + ticker_id_cig, + ticks_at_expire, + EVENT_US_FRAC_TO_TICKS(iso_interval_us_frac), + EVENT_US_FRAC_TO_TICKS(iso_interval_us_frac), + EVENT_US_FRAC_TO_REMAINDER(iso_interval_us_frac), + TICKER_NULL_LAZY, + 0, + ticker_cb, cig, + ticker_op_cb, NULL); + + LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); + +} + void ull_peripheral_iso_start(struct ll_conn *acl, uint32_t ticks_at_expire, uint16_t cis_handle) { @@ -491,3 +539,33 @@ void ull_peripheral_iso_start(struct ll_conn *acl, uint32_t ticks_at_expire, cig->started = 1; } + +void ull_peripheral_iso_update_peer_sca(struct ll_conn *acl) +{ + uint8_t cig_handle; + + /* Find CIG associated with ACL conn */ + for (cig_handle = 0; cig_handle < CONFIG_BT_CTLR_CONN_ISO_GROUPS; cig_handle++) { + /* Go through all ACL affiliated CIGs and update peer SCA */ + struct ll_conn_iso_stream *cis; + struct ll_conn_iso_group *cig; + + cig = ll_conn_iso_group_get(cig_handle); + if (!cig || !cig->lll.num_cis) { + continue; + } + cis = ll_conn_iso_stream_get_by_group(cig, NULL); + LL_ASSERT(cis); + + uint16_t cis_handle = cis->lll.handle; + + cis = ll_iso_stream_connected_get(cis_handle); + if (!cis) { + continue; + } + + if (cis->lll.acl_handle == acl->lll.handle) { + cig->sca_update = acl->periph.sca + 1; + } + } +} diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso_internal.h b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso_internal.h index b4db867e83a..85c8bea8fc8 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso_internal.h @@ -17,3 +17,4 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind, uint16_t cis_handle); void ull_peripheral_iso_start(struct ll_conn *acl, uint32_t ticks_at_expire, uint16_t cis_handle); +void ull_peripheral_iso_update_peer_sca(struct ll_conn *acl); diff --git a/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral_iso.c b/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral_iso.c index 1ddbe88c9e8..4fc0fef4fdc 100644 --- a/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral_iso.c +++ b/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral_iso.c @@ -60,3 +60,7 @@ void ull_peripheral_iso_start(struct ll_conn *acl, uint32_t ticks_at_expire, uint16_t cis_handle) { } + +void ull_peripheral_iso_update_peer_sca(struct ll_conn *acl) +{ +}