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 <erbr@oticon.com>
This commit is contained in:
parent
b3b4b9e322
commit
76439d0ba4
10 changed files with 271 additions and 49 deletions
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue