mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-20 07:57:22 +00:00
nimble/controller: Refactor remote features handling
This patch changes the way we handle features exchange in controller. On new connection, the controller will automatically initiate features exchange and store complete features mask. This makes used features available immediately after connection. Also we cache remote's features so the LE Read Remote Supported Features command does not initiate features exchange procedure at any time and will always return cached data. Initial Data Length Update procedure is removed as it should be now started after features exchange is completed - this will be added soon. X-Original-Commit: c5177bd24239ae17ea260ccce459c70697205e9a
This commit is contained in:
@@ -124,6 +124,8 @@ union ble_ll_conn_sm_flags {
|
||||
uint32_t peer_phy_update: 1; /* XXX:combine with ctrlr udpate bit? */
|
||||
uint32_t aux_conn_req: 1;
|
||||
uint32_t aux_conn_rsp: 1;
|
||||
uint32_t rxd_features:1;
|
||||
uint32_t pending_hci_rd_features:1;
|
||||
} cfbit;
|
||||
uint32_t conn_flags;
|
||||
} __attribute__((packed));
|
||||
@@ -292,6 +294,8 @@ struct ble_ll_conn_sm
|
||||
struct os_callout auth_pyld_timer;
|
||||
#endif
|
||||
|
||||
struct os_callout rd_features_timer;
|
||||
|
||||
/*
|
||||
* XXX: a note on all these structures for control procedures. First off,
|
||||
* all of these need to be ifdef'd to save memory. Another thing to
|
||||
|
||||
@@ -1596,6 +1596,22 @@ ble_ll_conn_auth_pyld_timer_cb(struct os_event *ev)
|
||||
ble_ll_conn_auth_pyld_timer_start(connsm);
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_conn_rd_features_timer_cb(struct os_event *ev)
|
||||
{
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
|
||||
connsm = (struct ble_ll_conn_sm *)ev->ev_arg;
|
||||
|
||||
if (!connsm->csmflags.cfbit.pending_hci_rd_features ||
|
||||
!connsm->csmflags.cfbit.rxd_features) {
|
||||
return;
|
||||
}
|
||||
|
||||
ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS);
|
||||
connsm->csmflags.cfbit.pending_hci_rd_features = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start (or restart) the authenticated payload timer
|
||||
*
|
||||
@@ -1900,6 +1916,11 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
|
||||
connsm);
|
||||
#endif
|
||||
|
||||
os_callout_init(&connsm->rd_features_timer,
|
||||
&g_ble_ll_data.ll_evq,
|
||||
ble_ll_conn_rd_features_timer_cb,
|
||||
connsm);
|
||||
|
||||
ble_ll_conn_calc_itvl_ticks(connsm);
|
||||
|
||||
/* Add to list of active connections */
|
||||
@@ -1985,6 +2006,8 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
|
||||
os_callout_stop(&connsm->auth_pyld_timer);
|
||||
#endif
|
||||
|
||||
os_callout_stop(&connsm->rd_features_timer);
|
||||
|
||||
/* Remove from the active connection list */
|
||||
SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle);
|
||||
|
||||
@@ -2031,6 +2054,10 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
|
||||
}
|
||||
}
|
||||
|
||||
if (connsm->csmflags.cfbit.pending_hci_rd_features) {
|
||||
ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_UNK_CONN_ID);
|
||||
}
|
||||
|
||||
/* Put connection state machine back on free list */
|
||||
STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
|
||||
|
||||
@@ -2362,19 +2389,6 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
|
||||
CONN_F_CTRLR_PHY_UPDATE(connsm) = 1;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Section 4.5.10 Vol 6 PART B. If the max tx/rx time or octets
|
||||
* exceeds the minimum, data length procedure needs to occur
|
||||
*/
|
||||
if ((connsm->max_tx_octets > BLE_LL_CONN_SUPP_BYTES_MIN) ||
|
||||
(connsm->max_rx_octets > BLE_LL_CONN_SUPP_BYTES_MIN) ||
|
||||
(connsm->max_tx_time > BLE_LL_CONN_SUPP_TIME_MIN) ||
|
||||
(connsm->max_rx_time > BLE_LL_CONN_SUPP_TIME_MIN)) {
|
||||
/* Start the data length update procedure */
|
||||
if (ble_ll_read_supp_features() & BLE_LL_FEAT_DATA_LEN_EXT) {
|
||||
ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
|
||||
}
|
||||
}
|
||||
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
|
||||
ble_ll_adv_send_conn_comp_ev(connsm, rxhdr);
|
||||
} else {
|
||||
@@ -2384,6 +2398,9 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
|
||||
ble_ll_hci_ev_le_csa(connsm);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Initiate features exchange */
|
||||
ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -761,15 +761,14 @@ ble_ll_conn_hci_read_rem_features(uint8_t *cmdbuf)
|
||||
return BLE_ERR_UNK_CONN_ID;
|
||||
}
|
||||
|
||||
/* See if we support this feature */
|
||||
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
|
||||
if ((ble_ll_read_supp_features() & BLE_LL_FEAT_SLAVE_INIT) == 0) {
|
||||
return BLE_ERR_UNKNOWN_HCI_CMD;
|
||||
}
|
||||
/* If already pending exit with error */
|
||||
if (connsm->csmflags.cfbit.pending_hci_rd_features) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
/* Start the control procedure */
|
||||
ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG);
|
||||
connsm->csmflags.cfbit.pending_hci_rd_features = 1;
|
||||
|
||||
os_callout_reset(&connsm->rd_features_timer, 0);
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -151,6 +151,7 @@ void ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
|
||||
int ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max,
|
||||
uint16_t latency, uint16_t spvn_tmo);
|
||||
int ble_ll_conn_hci_read_rem_features(uint8_t *cmdbuf);
|
||||
int ble_ll_conn_hci_read_rem_features_complete(void);
|
||||
int ble_ll_conn_hci_rd_rssi(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_conn_hci_rd_chan_map(uint8_t *cmdbuf, uint8_t *rspbuf,
|
||||
uint8_t *rsplen);
|
||||
|
||||
@@ -433,7 +433,11 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
if (ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ) {
|
||||
ble_ll_hci_ev_conn_update(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
|
||||
} else if (ctrl_proc == BLE_LL_CTRL_PROC_FEATURE_XCHG) {
|
||||
ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
|
||||
if (connsm->csmflags.cfbit.pending_hci_rd_features) {
|
||||
ble_ll_hci_ev_rd_rem_used_feat(connsm,
|
||||
BLE_ERR_UNSUPP_REM_FEATURE);
|
||||
}
|
||||
connsm->csmflags.cfbit.pending_hci_rd_features = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1565,6 +1569,9 @@ ble_ll_ctrl_rx_feature_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
put_le32(rspbuf + 1, our_feat);
|
||||
rspbuf[1] = connsm->conn_features;
|
||||
|
||||
/* We now have remote features */
|
||||
connsm->csmflags.cfbit.rxd_features = 1;
|
||||
|
||||
return rsp_opcode;
|
||||
}
|
||||
|
||||
@@ -2213,11 +2220,17 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
|
||||
case BLE_LL_CTRL_FEATURE_RSP:
|
||||
connsm->conn_features = dptr[0];
|
||||
memcpy(connsm->remote_features, dptr + 1, 7);
|
||||
/* We now have remote features */
|
||||
connsm->csmflags.cfbit.rxd_features = 1;
|
||||
/* Stop the control procedure */
|
||||
if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG)) {
|
||||
ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS);
|
||||
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG);
|
||||
}
|
||||
/* Send event to host if pending features read */
|
||||
if (connsm->csmflags.cfbit.pending_hci_rd_features) {
|
||||
ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS);
|
||||
connsm->csmflags.cfbit.pending_hci_rd_features = 0;
|
||||
}
|
||||
break;
|
||||
case BLE_LL_CTRL_VERSION_IND:
|
||||
rsp_opcode = ble_ll_ctrl_rx_version_ind(connsm, dptr, rspdata);
|
||||
|
||||
Reference in New Issue
Block a user