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 */
|
#endif /* CONFIG_BT_PERIPHERAL */
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CONN)
|
#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)
|
#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)
|
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_CTLR_PERIPHERAL_ISO */
|
||||||
#endif /* CONFIG_BT_PERIPHERAL */
|
#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)
|
#if defined(CONFIG_BT_CTLR_ISO)
|
||||||
case BT_OCF(BT_HCI_OP_LE_SETUP_ISO_PATH):
|
case BT_OCF(BT_HCI_OP_LE_SETUP_ISO_PATH):
|
||||||
le_setup_iso_path(cmd, evt);
|
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);
|
sep->rx_phy = find_lsb_set(pu->rx);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BT_CTLR_PHY */
|
#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 */
|
#endif /* CONFIG_BT_CONN */
|
||||||
|
|
||||||
#if defined(CONFIG_BT_HCI_MESH_EXT)
|
#if defined(CONFIG_BT_HCI_MESH_EXT)
|
||||||
|
@ -8181,6 +8226,12 @@ static void encode_control(struct node_rx_pdu *node_rx,
|
||||||
return;
|
return;
|
||||||
#endif /* CONFIG_BT_CTLR_CONN_ISO */
|
#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)
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
|
||||||
case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT:
|
case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT:
|
||||||
#if defined(CONFIG_BT_CTLR_DF_VS_CONN_IQ_REPORT_16_BITS_IQ_SAMPLES)
|
#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:
|
case NODE_RX_TYPE_CIS_REQUEST:
|
||||||
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
|
#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)
|
#if defined(CONFIG_BT_CTLR_CONN_ISO)
|
||||||
case NODE_RX_TYPE_CIS_ESTABLISHED:
|
case NODE_RX_TYPE_CIS_ESTABLISHED:
|
||||||
#endif /* CONFIG_BT_CTLR_CONN_ISO */
|
#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 const *const ltk);
|
||||||
uint8_t ll_start_enc_req_send(uint16_t handle, uint8_t err_code,
|
uint8_t ll_start_enc_req_send(uint16_t handle, uint8_t err_code,
|
||||||
uint8_t const *const ltk);
|
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_feature_req_send(uint16_t handle);
|
||||||
uint8_t ll_version_ind_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);
|
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:
|
case NODE_RX_TYPE_CIS_REQUEST:
|
||||||
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
|
#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)
|
#if defined(CONFIG_BT_CTLR_CONN_ISO)
|
||||||
case NODE_RX_TYPE_CIS_ESTABLISHED:
|
case NODE_RX_TYPE_CIS_ESTABLISHED:
|
||||||
#endif /* CONFIG_BT_CTLR_CONN_ISO */
|
#endif /* CONFIG_BT_CTLR_CONN_ISO */
|
||||||
|
@ -1503,6 +1507,10 @@ void ll_rx_mem_release(void **node_rx)
|
||||||
case NODE_RX_TYPE_CIS_ESTABLISHED:
|
case NODE_RX_TYPE_CIS_ESTABLISHED:
|
||||||
#endif /* CONFIG_BT_CTLR_CONN_ISO */
|
#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)
|
#if defined(CONFIG_BT_CTLR_ISO)
|
||||||
case NODE_RX_TYPE_ISO_PDU:
|
case NODE_RX_TYPE_ISO_PDU:
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -546,6 +546,20 @@ uint8_t ll_chm_get(uint16_t handle, uint8_t *chm)
|
||||||
return 0;
|
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)
|
static bool is_valid_disconnect_reason(uint8_t reason)
|
||||||
{
|
{
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
|
@ -7905,6 +7919,57 @@ uint16_t ull_conn_event_counter(struct ll_conn *conn)
|
||||||
|
|
||||||
return event_counter;
|
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,
|
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,
|
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_old;
|
||||||
uint16_t conn_interval_new;
|
uint16_t conn_interval_new;
|
||||||
uint32_t conn_interval_us;
|
uint32_t conn_interval_us;
|
||||||
uint8_t ticker_id_conn;
|
|
||||||
uint32_t ticker_status;
|
|
||||||
uint32_t periodic_us;
|
uint32_t periodic_us;
|
||||||
uint16_t latency_upd;
|
uint16_t latency_upd;
|
||||||
uint16_t instant_latency;
|
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 * instant_latency;
|
||||||
|
|
||||||
lll->periph.window_widening_periodic_us =
|
lll->periph.window_widening_periodic_us =
|
||||||
(((lll_clock_ppm_local_get() + lll_clock_ppm_get(conn->periph.sca)) *
|
ceiling_fraction(((lll_clock_ppm_local_get() +
|
||||||
conn_interval_us) +
|
lll_clock_ppm_get(conn->periph.sca)) *
|
||||||
(1000000U - 1U)) /
|
conn_interval_us), 1000000U);
|
||||||
1000000U;
|
|
||||||
lll->periph.window_widening_max_us = (conn_interval_us >> 1U) - EVENT_IFS_US;
|
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;
|
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;
|
conn->supervision_expire = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
|
/* Update ACL ticker */
|
||||||
/* disable ticker job, in order to chain stop and start
|
ull_conn_update_ticker(conn, ticks_win_offset, ticks_slot_overhead, periodic_us,
|
||||||
* to avoid RTC being stopped if no tickers active.
|
ticks_at_expire);
|
||||||
*/
|
|
||||||
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 */
|
|
||||||
|
|
||||||
/* Signal that the prepare needs to be canceled */
|
/* Signal that the prepare needs to be canceled */
|
||||||
conn->cancel_prepare = 1U;
|
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])
|
void ull_conn_chan_map_set(struct ll_conn *conn, const uint8_t chm[5])
|
||||||
{
|
{
|
||||||
struct lll_conn *lll = &conn->lll;
|
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 interval, uint16_t latency,
|
||||||
uint16_t timeout, uint16_t instant);
|
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_octets_set(uint16_t tx_octets);
|
||||||
|
|
||||||
void ull_conn_default_tx_time_set(uint16_t tx_time);
|
void ull_conn_default_tx_time_set(uint16_t tx_time);
|
||||||
|
|
|
@ -49,6 +49,7 @@ struct ll_conn_iso_group {
|
||||||
uint16_t iso_interval;
|
uint16_t iso_interval;
|
||||||
uint8_t cig_id;
|
uint8_t cig_id;
|
||||||
uint8_t started:1; /* 1 if CIG started and ticker is running */
|
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 {
|
struct node_rx_conn_iso_req {
|
||||||
|
|
|
@ -33,7 +33,9 @@
|
||||||
#include "isoal.h"
|
#include "isoal.h"
|
||||||
#include "ull_iso_types.h"
|
#include "ull_iso_types.h"
|
||||||
#include "ull_conn_iso_types.h"
|
#include "ull_conn_iso_types.h"
|
||||||
|
#include "ull_iso_internal.h"
|
||||||
#include "ull_conn_iso_internal.h"
|
#include "ull_conn_iso_internal.h"
|
||||||
|
#include "ull_peripheral_iso_internal.h"
|
||||||
|
|
||||||
#include "ull_conn_types.h"
|
#include "ull_conn_types.h"
|
||||||
#include "ull_chan_internal.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;
|
ctx->data.sca_update.error_code = BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
|
||||||
/* Fall through to complete procedure */
|
/* Fall through to complete procedure */
|
||||||
case PDU_DATA_LLCTRL_TYPE_CLOCK_ACCURACY_RSP:
|
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);
|
lp_sca_ntf(conn, ctx);
|
||||||
llcp_lr_complete(conn);
|
llcp_lr_complete(conn);
|
||||||
ctx->state = LP_COMMON_STATE_IDLE;
|
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)
|
#if defined(CONFIG_BT_CTLR_SCA_UPDATE)
|
||||||
case PROC_SCA_UPDATE: {
|
case PROC_SCA_UPDATE: {
|
||||||
ctx->tx_ack = NULL;
|
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);
|
llcp_rr_complete(conn);
|
||||||
ctx->state = RP_COMMON_STATE_IDLE;
|
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;
|
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,
|
static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
|
||||||
uint32_t remainder, uint16_t lazy, uint8_t force,
|
uint32_t remainder, uint16_t lazy, uint8_t force,
|
||||||
void *param)
|
void *param)
|
||||||
|
@ -387,6 +391,21 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
|
||||||
p.param = &cig->lll;
|
p.param = &cig->lll;
|
||||||
mfy.param = &p;
|
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 */
|
/* Kick LLL prepare */
|
||||||
err = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
|
err = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
|
||||||
0, &mfy);
|
0, &mfy);
|
||||||
|
@ -403,6 +422,35 @@ static void ticker_op_cb(uint32_t status, void *param)
|
||||||
LL_ASSERT(status == TICKER_STATUS_SUCCESS);
|
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,
|
void ull_peripheral_iso_start(struct ll_conn *acl, uint32_t ticks_at_expire,
|
||||||
uint16_t cis_handle)
|
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;
|
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);
|
uint16_t cis_handle);
|
||||||
void ull_peripheral_iso_start(struct ll_conn *acl, uint32_t ticks_at_expire,
|
void ull_peripheral_iso_start(struct ll_conn *acl, uint32_t ticks_at_expire,
|
||||||
uint16_t cis_handle);
|
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)
|
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