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:
Andrzej Kaczmarek
2017-07-04 09:54:11 +02:00
parent db989bf770
commit 0a9a60b06f
5 changed files with 56 additions and 22 deletions
@@ -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
+30 -13
View File
@@ -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;
+6 -7
View File
@@ -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;
}
+1
View File
@@ -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);
+15 -2
View File
@@ -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);