mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-02 07:10:02 +00:00
Merge pull request #375 from andrzej-kaczmarek/bt5-featexch
Nimble: improvements on controller/peer features handling X-Original-Commit: 087e80189a8b52018ecba2d5aa81b40fcbb5fc14
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));
|
||||
@@ -228,7 +230,8 @@ struct ble_ll_conn_sm
|
||||
uint8_t disconnect_reason;
|
||||
uint8_t rxd_disconnect_reason;
|
||||
uint8_t vers_nr;
|
||||
uint32_t common_features;
|
||||
uint8_t conn_features;
|
||||
uint8_t remote_features[7];
|
||||
uint16_t pending_ctrl_procs;
|
||||
uint16_t event_cntr;
|
||||
uint16_t completed_pkts;
|
||||
|
||||
@@ -25,7 +25,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* For supported commands */
|
||||
#define BLE_LL_SUPP_CMD_LEN (36)
|
||||
#define BLE_LL_SUPP_CMD_LEN (40)
|
||||
extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN];
|
||||
|
||||
/* The largest event the controller will send. */
|
||||
|
||||
@@ -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
|
||||
*
|
||||
@@ -1819,7 +1835,8 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
|
||||
connsm->event_cntr = 0;
|
||||
connsm->conn_state = BLE_LL_CONN_STATE_IDLE;
|
||||
connsm->disconnect_reason = 0;
|
||||
connsm->common_features = 0;
|
||||
connsm->conn_features = 0;
|
||||
memset(connsm->remote_features, 0, sizeof(connsm->remote_features));
|
||||
connsm->vers_nr = 0;
|
||||
connsm->comp_id = 0;
|
||||
connsm->sub_vers_nr = 0;
|
||||
@@ -2010,6 +2027,16 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
|
||||
/* Connection state machine is now idle */
|
||||
connsm->conn_state = BLE_LL_CONN_STATE_IDLE;
|
||||
|
||||
/*
|
||||
* If we have features and there's pending HCI command, send an event before
|
||||
* disconnection event so it does make sense to host.
|
||||
*/
|
||||
if (connsm->csmflags.cfbit.pending_hci_rd_features &&
|
||||
connsm->csmflags.cfbit.rxd_features) {
|
||||
ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS);
|
||||
connsm->csmflags.cfbit.pending_hci_rd_features = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to send a disconnection complete event or a connection complete
|
||||
* event when the connection ends. We send a connection complete event
|
||||
@@ -2028,6 +2055,15 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is still pending read features request HCI command, send an
|
||||
* event to complete it.
|
||||
*/
|
||||
if (connsm->csmflags.cfbit.pending_hci_rd_features) {
|
||||
ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_UNK_CONN_ID);
|
||||
connsm->csmflags.cfbit.pending_hci_rd_features = 0;
|
||||
}
|
||||
|
||||
/* Put connection state machine back on free list */
|
||||
STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
|
||||
|
||||
@@ -2359,19 +2395,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 {
|
||||
@@ -2381,6 +2404,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;
|
||||
@@ -2513,6 +2539,13 @@ ble_ll_conn_event_end(struct os_event *ev)
|
||||
|
||||
/* If we have completed packets, send an event */
|
||||
ble_ll_conn_num_comp_pkts_event_send(connsm);
|
||||
|
||||
/* If we have features and there's pending HCI command, send an event */
|
||||
if (connsm->csmflags.cfbit.pending_hci_rd_features &&
|
||||
connsm->csmflags.cfbit.rxd_features) {
|
||||
ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS);
|
||||
connsm->csmflags.cfbit.pending_hci_rd_features = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -761,15 +761,12 @@ 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;
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
@@ -813,9 +810,9 @@ ble_ll_conn_hci_update(uint8_t *cmdbuf)
|
||||
}
|
||||
|
||||
/* See if this feature is supported on both sides */
|
||||
if ((connsm->common_features & BLE_LL_FEAT_CONN_PARM_REQ) == 0) {
|
||||
if ((connsm->conn_features & BLE_LL_FEAT_CONN_PARM_REQ) == 0) {
|
||||
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
|
||||
return BLE_ERR_UNKNOWN_HCI_CMD;
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
ctrl_proc = BLE_LL_CTRL_PROC_CONN_UPDATE;
|
||||
} else {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1513,6 +1517,27 @@ ble_ll_ctrl_rx_conn_update(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
return rsp_opcode;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm)
|
||||
{
|
||||
if (!(connsm->conn_features & BLE_LL_FEAT_DATA_LEN_EXT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we receive a feature request or a slave initiated feature
|
||||
* request.
|
||||
@@ -1530,7 +1555,7 @@ ble_ll_ctrl_rx_feature_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
uint8_t *rspbuf, uint8_t opcode)
|
||||
{
|
||||
uint8_t rsp_opcode;
|
||||
uint32_t remote_feat;
|
||||
uint32_t our_feat;
|
||||
|
||||
/*
|
||||
* Only accept slave feature requests if we are a master and feature
|
||||
@@ -1547,13 +1572,29 @@ ble_ll_ctrl_rx_feature_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
}
|
||||
}
|
||||
|
||||
remote_feat = get_le32(dptr);
|
||||
our_feat = ble_ll_read_supp_features();
|
||||
|
||||
/* Set common features and reply */
|
||||
rsp_opcode = BLE_LL_CTRL_FEATURE_RSP;
|
||||
connsm->common_features = remote_feat & ble_ll_read_supp_features();
|
||||
|
||||
/*
|
||||
* 1st octet of features should be common features of local and remote
|
||||
* controller - we call this 'connection features'
|
||||
* remaining octets are features of controller which sends PDU, in this case
|
||||
* it's our controller
|
||||
*
|
||||
* See: Vol 6, Part B, section 2.4.2.10
|
||||
*/
|
||||
|
||||
connsm->conn_features = dptr[0] & our_feat;
|
||||
memset(rspbuf + 1, 0, 8);
|
||||
put_le32(rspbuf + 1, connsm->common_features);
|
||||
put_le32(rspbuf + 1, our_feat);
|
||||
rspbuf[1] = connsm->conn_features;
|
||||
|
||||
/* If this is the first time we received remote features, try to start DLE */
|
||||
if (!connsm->csmflags.cfbit.rxd_features) {
|
||||
ble_ll_ctrl_initiate_dle(connsm);
|
||||
connsm->csmflags.cfbit.rxd_features = 1;
|
||||
}
|
||||
|
||||
return rsp_opcode;
|
||||
}
|
||||
@@ -2132,7 +2173,7 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
|
||||
features = ble_ll_read_supp_features();
|
||||
if ((features & feature) == 0) {
|
||||
if (opcode == BLE_LL_CTRL_ENC_REQ) {
|
||||
if (connsm->common_features & BLE_LL_FEAT_EXTENDED_REJ) {
|
||||
if (connsm->conn_features & BLE_LL_FEAT_EXTENDED_REJ) {
|
||||
rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT;
|
||||
rspbuf[1] = opcode;
|
||||
rspbuf[2] = BLE_ERR_UNSUPP_REM_FEATURE;
|
||||
@@ -2201,12 +2242,22 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
|
||||
break;
|
||||
/* XXX: check to see if ctrl procedure was running? Do we care? */
|
||||
case BLE_LL_CTRL_FEATURE_RSP:
|
||||
connsm->conn_features = dptr[0];
|
||||
memcpy(connsm->remote_features, dptr + 1, 7);
|
||||
/* If this is the first time we received remote features, try to start DLE */
|
||||
if (!connsm->csmflags.cfbit.rxd_features) {
|
||||
ble_ll_ctrl_initiate_dle(connsm);
|
||||
connsm->csmflags.cfbit.rxd_features = 1;
|
||||
}
|
||||
/* Stop the control procedure */
|
||||
connsm->common_features = dptr[0];
|
||||
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);
|
||||
@@ -2321,7 +2372,7 @@ ble_ll_ctrl_reject_ind_send(struct ble_ll_conn_sm *connsm, uint8_t rej_opcode,
|
||||
rspbuf = om->om_data;
|
||||
opcode = BLE_LL_CTRL_REJECT_IND_EXT;
|
||||
if (rej_opcode == BLE_LL_CTRL_ENC_REQ) {
|
||||
if ((connsm->common_features & BLE_LL_FEAT_EXTENDED_REJ) == 0) {
|
||||
if ((connsm->conn_features & BLE_LL_FEAT_EXTENDED_REJ) == 0) {
|
||||
opcode = BLE_LL_CTRL_REJECT_IND;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +198,8 @@ ble_ll_hci_ev_rd_rem_used_feat(struct ble_ll_conn_sm *connsm, uint8_t status)
|
||||
evbuf[3] = status;
|
||||
put_le16(evbuf + 4, connsm->conn_handle);
|
||||
memset(evbuf + 6, 0, BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN);
|
||||
put_le32(evbuf + 6, connsm->common_features);
|
||||
evbuf[6] = connsm->conn_features;
|
||||
memcpy(evbuf + 7, connsm->remote_features, 7);
|
||||
ble_ll_hci_event_send(evbuf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,11 +128,13 @@
|
||||
/* Octet 28 */
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
|
||||
#define BLE_SUPP_CMD_LE_START_ENCRYPT (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (1 << 2)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_START_ENCRYPT (0 << 0)
|
||||
#endif
|
||||
#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (0 << 2)
|
||||
#endif
|
||||
#define BLE_SUPP_CMD_LE_READ_SUPP_STATES (1 << 3)
|
||||
#define BLE_SUPP_CMD_LE_RX_TEST (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_TX_TEST (0 << 5)
|
||||
@@ -152,8 +154,13 @@
|
||||
/* Octet 33 */
|
||||
#define BLE_SUPP_CMD_LE_REM_CONN_PRR (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_REM_CONN_PRNR (1 << 5)
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) == 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_DATALEN (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_DATALEN (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_33 \
|
||||
( \
|
||||
@@ -163,9 +170,176 @@
|
||||
BLE_SUPP_CMD_LE_RD_SUGG_DATALEN \
|
||||
)
|
||||
|
||||
/* Octet 34 */
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) == 1)
|
||||
#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (1 << 0)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (0 << 0)
|
||||
#endif
|
||||
#define BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_GENERATE_DH_KEY (0 << 2)
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (1 << 3)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (0 << 3)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_34 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_WR_SUGG_DATALEN | \
|
||||
BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK | \
|
||||
BLE_SUPP_CMD_LE_GENERATE_DH_KEY | \
|
||||
BLE_SUPP_CMD_LE_ADD_RESOLV_LIST | \
|
||||
BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST | \
|
||||
BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST | \
|
||||
BLE_SUPP_CMD_LE_RD_RESOLV_SIZE | \
|
||||
BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR \
|
||||
)
|
||||
|
||||
/* Octet 35 */
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (1 << 2)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (0 << 2)
|
||||
#endif
|
||||
#define BLE_SUPP_CMD_LE_RD_MAX_DATALEN (1 << 3)
|
||||
#define BLE_LL_SUPP_CMD_OCTET_35 (BLE_SUPP_CMD_LE_RD_MAX_DATALEN)
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
#define BLE_SUPP_CMD_LE_READ_PHY (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_SET_PHY (1 << 6)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_READ_PHY (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_SET_PHY (0 << 6)
|
||||
#endif
|
||||
#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (0 << 7)
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_35 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR | \
|
||||
BLE_SUPP_CMD_LE_SET_ADDR_RES_EN | \
|
||||
BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO | \
|
||||
BLE_SUPP_CMD_LE_RD_MAX_DATALEN | \
|
||||
BLE_SUPP_CMD_LE_READ_PHY | \
|
||||
BLE_SUPP_CMD_LE_SET_DEFAULT_PHY | \
|
||||
BLE_SUPP_CMD_LE_SET_PHY | \
|
||||
BLE_SUPP_CMD_LE_ENHANCED_RX_TEST \
|
||||
)
|
||||
|
||||
/* Octet 36 */
|
||||
#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (0 << 0)
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) == 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (1 << 2)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (1 << 3)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (0 << 2)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (0 << 3)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_36 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_ENHANCED_TX_TEST | \
|
||||
BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE | \
|
||||
BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN | \
|
||||
BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS \
|
||||
)
|
||||
|
||||
/* Octet 37 */
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) == 1)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_ADVS (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_ADVS (1 << 1)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_ADVS (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_ADVS (0 << 1)
|
||||
#endif
|
||||
#define BLE_SUPP_CMD_LE_SET_PADV_PARAM (0 << 2)
|
||||
#define BLE_SUPP_CMD_LE_SET_PADV_DATA (0 << 3)
|
||||
#define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (0 << 4)
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) == 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_37 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_REMOVE_ADVS | \
|
||||
BLE_SUPP_CMD_LE_CLEAR_ADVS | \
|
||||
BLE_SUPP_CMD_LE_SET_PADV_PARAM | \
|
||||
BLE_SUPP_CMD_LE_SET_PADV_DATA | \
|
||||
BLE_SUPP_CMD_LE_SET_PADV_ENABLE | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE | \
|
||||
BLE_SUPP_CMD_LE_EXT_CREATE_CONN \
|
||||
)
|
||||
|
||||
/* Octet 38 */
|
||||
#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (0 << 2)
|
||||
#define BLE_SUPP_CMD_LE_ADD_PADV_LIST (0 << 3)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_TX_POWER (0 << 7)
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_38 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_PADV_CREATE_SYNC | \
|
||||
BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C | \
|
||||
BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC | \
|
||||
BLE_SUPP_CMD_LE_ADD_PADV_LIST | \
|
||||
BLE_SUPP_CMD_LE_REMOVE_PADV_LIST | \
|
||||
BLE_SUPP_CMD_LE_CLEAR_PADV_LIST | \
|
||||
BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE | \
|
||||
BLE_SUPP_CMD_LE_RD_TX_POWER \
|
||||
)
|
||||
|
||||
/* Octet 39 */
|
||||
#define BLE_SUPP_CMD_LE_RD_RF_PATH_COMP (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_WR_RF_PATH_COMP (0 << 1)
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (1 << 2)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (0 << 2)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_39 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_RD_RF_PATH_COMP | \
|
||||
BLE_SUPP_CMD_LE_WR_RF_PATH_COMP | \
|
||||
BLE_SUPP_CMD_LE_SET_PRIVACY_MODE \
|
||||
)
|
||||
|
||||
/* Defines the array of supported commands */
|
||||
const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] =
|
||||
@@ -204,6 +378,10 @@ const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] =
|
||||
0,
|
||||
0, /* Octet 32 */
|
||||
BLE_LL_SUPP_CMD_OCTET_33,
|
||||
0,
|
||||
BLE_LL_SUPP_CMD_OCTET_35
|
||||
BLE_LL_SUPP_CMD_OCTET_34,
|
||||
BLE_LL_SUPP_CMD_OCTET_35,
|
||||
BLE_LL_SUPP_CMD_OCTET_36,
|
||||
BLE_LL_SUPP_CMD_OCTET_37,
|
||||
BLE_LL_SUPP_CMD_OCTET_38,
|
||||
BLE_LL_SUPP_CMD_OCTET_39,
|
||||
};
|
||||
|
||||
@@ -188,7 +188,7 @@ syscfg.defs:
|
||||
This option enables/disables the connection parameter request
|
||||
procedure. This is implemented in the controller but is disabled
|
||||
by default.
|
||||
value: '0'
|
||||
value: '1'
|
||||
|
||||
BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG:
|
||||
description: >
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef H_BLE_HS_HCI_
|
||||
#define H_BLE_HS_HCI_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
+59
-18
@@ -25,6 +25,7 @@
|
||||
#include "mem/mem.h"
|
||||
#include "nimble/nimble_opt.h"
|
||||
#include "host/ble_hs_adv.h"
|
||||
#include "host/ble_hs_hci.h"
|
||||
#include "ble_hs_priv.h"
|
||||
|
||||
/**
|
||||
@@ -1182,6 +1183,26 @@ ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc)
|
||||
ble_gap_disc_report(desc);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ble_gap_rd_rem_sup_feat_tx(uint16_t handle)
|
||||
{
|
||||
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CONN_RD_REM_FEAT_LEN];
|
||||
int rc;
|
||||
|
||||
rc = ble_hs_hci_cmd_build_le_read_remote_feat(handle, buf, sizeof buf);
|
||||
if (rc != 0) {
|
||||
return BLE_HS_EUNKNOWN;
|
||||
}
|
||||
|
||||
rc = ble_hs_hci_cmd_tx_empty_ack(buf);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes an incoming connection-complete HCI event.
|
||||
*/
|
||||
@@ -1308,9 +1329,30 @@ ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt)
|
||||
event.connect.status = 0;
|
||||
ble_gap_call_conn_event_cb(&event, evt->connection_handle);
|
||||
|
||||
ble_gap_rd_rem_sup_feat_tx(evt->connection_handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ble_gap_rx_rd_rem_sup_feat_complete(struct hci_le_rd_rem_supp_feat_complete *evt)
|
||||
{
|
||||
#if !NIMBLE_BLE_CONNECT
|
||||
return;
|
||||
#endif
|
||||
|
||||
struct ble_hs_conn *conn;
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
conn = ble_hs_conn_find(evt->connection_handle);
|
||||
if (conn != NULL && evt->status == 0) {
|
||||
conn->supported_feat = get_le32(evt->features);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
}
|
||||
|
||||
int
|
||||
ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
|
||||
struct ble_gap_upd_params *params)
|
||||
@@ -3435,8 +3477,11 @@ ble_gap_update_params(uint16_t conn_handle,
|
||||
struct ble_gap_update_entry *entry;
|
||||
struct ble_gap_update_entry *dup;
|
||||
struct ble_hs_conn *conn;
|
||||
int l2cap_update;
|
||||
int rc;
|
||||
|
||||
l2cap_update = 0;
|
||||
|
||||
/* Validate parameters with a spec */
|
||||
if (!ble_gap_validate_conn_params(params)) {
|
||||
return BLE_HS_EINVAL;
|
||||
@@ -3475,32 +3520,28 @@ ble_gap_update_params(uint16_t conn_handle,
|
||||
ble_gap_log_update(conn_handle, params);
|
||||
BLE_HS_LOG(INFO, "\n");
|
||||
|
||||
rc = ble_gap_update_tx(conn_handle, params);
|
||||
|
||||
/* If our controller reports that it doesn't support the update procedure,
|
||||
* and we are the slave, fail over to the L2CAP update procedure.
|
||||
/*
|
||||
* If LL update procedure is not supported on this connection and we are the
|
||||
* slave, fail over to the L2CAP update procedure.
|
||||
*/
|
||||
if (rc == BLE_HS_HCI_ERR(BLE_ERR_UNKNOWN_HCI_CMD) &&
|
||||
!(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) {
|
||||
|
||||
ble_gap_update_to_l2cap(params, &l2cap_params);
|
||||
if ((conn->supported_feat & BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST) == 0 &&
|
||||
!(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) {
|
||||
l2cap_update = 1;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = ble_gap_update_tx(conn_handle, params);
|
||||
}
|
||||
|
||||
done:
|
||||
ble_hs_unlock();
|
||||
|
||||
if (rc == 0) {
|
||||
if (!l2cap_update) {
|
||||
ble_hs_timer_resched();
|
||||
} else {
|
||||
/* If the l2cap_params struct is populated, the only error is that the
|
||||
* controller doesn't support the connection parameters request
|
||||
* procedure. In this case, fallback to the L2CAP update procedure.
|
||||
*/
|
||||
if (l2cap_params.itvl_min != 0) {
|
||||
rc = ble_l2cap_sig_update(conn_handle,
|
||||
&l2cap_params,
|
||||
ble_gap_update_l2cap_cb, NULL);
|
||||
}
|
||||
ble_gap_update_to_l2cap(params, &l2cap_params);
|
||||
|
||||
rc = ble_l2cap_sig_update(conn_handle, &l2cap_params,
|
||||
ble_gap_update_l2cap_cb, NULL);
|
||||
}
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
@@ -78,6 +78,7 @@ extern STATS_SECT_DECL(ble_gap_stats) ble_gap_stats;
|
||||
void ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc);
|
||||
#endif
|
||||
void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc);
|
||||
void ble_gap_rx_rd_rem_sup_feat_complete(struct hci_le_rd_rem_supp_feat_complete *evt);
|
||||
int ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt);
|
||||
void ble_gap_rx_disconn_complete(struct hci_disconn_complete *evt);
|
||||
void ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt);
|
||||
|
||||
@@ -50,6 +50,8 @@ struct ble_hs_conn {
|
||||
uint16_t bhc_supervision_timeout;
|
||||
uint8_t bhc_master_clock_accuracy;
|
||||
|
||||
uint32_t supported_feat;
|
||||
|
||||
ble_hs_conn_flags_t bhc_flags;
|
||||
|
||||
struct ble_l2cap_chan_list bhc_channels;
|
||||
|
||||
@@ -34,6 +34,7 @@ static struct os_sem ble_hs_hci_sem;
|
||||
static uint8_t *ble_hs_hci_ack;
|
||||
static uint16_t ble_hs_hci_buf_sz;
|
||||
static uint8_t ble_hs_hci_max_pkts;
|
||||
static uint32_t ble_hs_hci_sup_feat;
|
||||
|
||||
#if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS)
|
||||
static ble_hs_hci_phony_ack_fn *ble_hs_hci_phony_ack_cb;
|
||||
@@ -455,6 +456,18 @@ err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
ble_hs_hci_set_le_supported_feat(uint32_t feat)
|
||||
{
|
||||
ble_hs_hci_sup_feat = feat;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ble_hs_hci_get_le_supported_feat(void)
|
||||
{
|
||||
return ble_hs_hci_sup_feat;
|
||||
}
|
||||
|
||||
void
|
||||
ble_hs_hci_init(void)
|
||||
{
|
||||
|
||||
@@ -1839,3 +1839,25 @@ ble_hs_hci_cmd_build_set_random_addr(const uint8_t *addr,
|
||||
return ble_hs_hci_cmd_body_set_random_addr(&r_addr,
|
||||
dst + BLE_HCI_CMD_HDR_LEN);
|
||||
}
|
||||
|
||||
static void
|
||||
ble_hs_hci_cmd_body_le_read_remote_feat(uint16_t handle, uint8_t *dst)
|
||||
{
|
||||
put_le16(dst, handle);
|
||||
}
|
||||
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_read_remote_feat(uint16_t handle, uint8_t *dst,
|
||||
int dst_len)
|
||||
{
|
||||
BLE_HS_DBG_ASSERT(
|
||||
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_CONN_RD_REM_FEAT_LEN);
|
||||
|
||||
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_REM_FEAT,
|
||||
BLE_HCI_CONN_RD_REM_FEAT_LEN, dst);
|
||||
dst += BLE_HCI_CMD_HDR_LEN;
|
||||
|
||||
ble_hs_hci_cmd_body_le_read_remote_feat(handle, dst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_parm_req;
|
||||
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_dir_adv_rpt;
|
||||
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_phy_update_complete;
|
||||
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_ext_adv_rpt;
|
||||
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_rd_rem_used_feat_complete;
|
||||
|
||||
/* Statistics */
|
||||
struct host_hci_stats
|
||||
@@ -97,6 +98,8 @@ static const struct ble_hs_hci_evt_le_dispatch_entry
|
||||
{ BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE,
|
||||
ble_hs_hci_evt_le_phy_update_complete },
|
||||
{ BLE_HCI_LE_SUBEV_EXT_ADV_RPT, ble_hs_hci_evt_le_ext_adv_rpt },
|
||||
{ BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT,
|
||||
ble_hs_hci_evt_le_rd_rem_used_feat_complete },
|
||||
};
|
||||
|
||||
#define BLE_HS_HCI_EVT_LE_DISPATCH_SZ \
|
||||
@@ -455,6 +458,26 @@ ble_hs_hci_evt_le_dir_adv_rpt(uint8_t subevent, uint8_t *data, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_hs_hci_evt_le_rd_rem_used_feat_complete(uint8_t subevent, uint8_t *data,
|
||||
int len)
|
||||
{
|
||||
struct hci_le_rd_rem_supp_feat_complete evt;
|
||||
|
||||
if (len < BLE_HCI_LE_RD_REM_USED_FEAT_LEN) {
|
||||
return BLE_HS_ECONTROLLER;
|
||||
}
|
||||
|
||||
evt.subevent_code = data[0];
|
||||
evt.status = data[1];
|
||||
evt.connection_handle = get_le16(data + 2);
|
||||
memcpy(evt.features, data + 4, 8);
|
||||
|
||||
ble_gap_rx_rd_rem_sup_feat_complete(&evt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
static int
|
||||
ble_hs_hci_decode_legacy_type(uint16_t evt_type)
|
||||
|
||||
@@ -28,6 +28,24 @@ extern "C" {
|
||||
struct ble_hs_conn;
|
||||
struct os_mbuf;
|
||||
|
||||
#define BLE_HS_HCI_LE_FEAT_ENCRYPTION (0x00000001)
|
||||
#define BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST (0x00000002)
|
||||
#define BLE_HS_HCI_LE_FEAT_EXT_REJECT (0x00000004)
|
||||
#define BLE_HS_HCI_LE_FEAT_SLAVE_FEAT_EXCHANGE (0x00000008)
|
||||
#define BLE_HS_HCI_LE_FEAT_PING (0x00000010)
|
||||
#define BLE_HS_HCI_LE_FEAT_DATA_PACKET_LENGTH_EXT (0x00000020)
|
||||
#define BLE_HS_HCI_LE_FEAT_LL_PRIVACY (0x00000040)
|
||||
#define BLE_HS_HCI_LE_FEAT_EXT_SCANNER_FILTER_POLICIES (0x00000080)
|
||||
#define BLE_HS_HCI_LE_FEAT_2M_PHY (0x00000100)
|
||||
#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_TX (0x00000200)
|
||||
#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_RX (0x00000400)
|
||||
#define BLE_HS_HCI_LE_FEAT_CODED_PHY (0x00000800)
|
||||
#define BLE_HS_HCI_LE_FEAT_EXT_ADV (0x00001000)
|
||||
#define BLE_HS_HCI_LE_FEAT_PERIODIC_ADV (0x00002000)
|
||||
#define BLE_HS_HCI_LE_FEAT_CSA2 (0x00004000)
|
||||
#define BLE_HS_HCI_LE_FEAT_POWER_CLASS_1 (0x00008000)
|
||||
#define BLE_HS_HCI_LE_FEAT_MIN_NUM_USED_CHAN (0x00010000)
|
||||
|
||||
struct ble_hs_hci_ack {
|
||||
int bha_status; /* A BLE_HS_E<...> error; NOT a naked HCI code. */
|
||||
uint8_t *bha_params;
|
||||
@@ -57,6 +75,9 @@ int ble_hs_hci_cmd_tx_empty_ack(void *cmd);
|
||||
void ble_hs_hci_rx_ack(uint8_t *ack_ev);
|
||||
void ble_hs_hci_init(void);
|
||||
|
||||
void ble_hs_hci_set_le_supported_feat(uint32_t feat);
|
||||
uint32_t ble_hs_hci_get_le_supported_feat(void);
|
||||
|
||||
#if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS)
|
||||
typedef int ble_hs_hci_phony_ack_fn(uint8_t *ack, int ack_buf_len);
|
||||
void ble_hs_hci_set_phony_ack_cb(ble_hs_hci_phony_ack_fn *cb);
|
||||
@@ -220,6 +241,9 @@ int ble_hs_hci_cmd_build_le_set_phy(uint16_t conn_handle, uint8_t tx_phys_mask,
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
#endif
|
||||
|
||||
int ble_hs_hci_cmd_build_le_read_remote_feat(uint16_t handle, uint8_t *dst,
|
||||
int dst_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "host/ble_hs.h"
|
||||
#include "host/ble_hs_hci.h"
|
||||
#include "ble_hs_priv.h"
|
||||
|
||||
static int
|
||||
@@ -28,6 +29,7 @@ ble_hs_startup_le_read_sup_f_tx(void)
|
||||
uint8_t ack_params[BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN];
|
||||
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
|
||||
uint8_t ack_params_len;
|
||||
uint32_t feat;
|
||||
int rc;
|
||||
|
||||
ble_hs_hci_cmd_build_le_read_loc_supp_feat(buf, sizeof buf);
|
||||
@@ -41,7 +43,9 @@ ble_hs_startup_le_read_sup_f_tx(void)
|
||||
return BLE_HS_ECONTROLLER;
|
||||
}
|
||||
|
||||
/* XXX: Do something with the supported features bit map. */
|
||||
/* For now 32-bits of features is enough */
|
||||
feat = get_le32(ack_params);
|
||||
ble_hs_hci_set_le_supported_feat(feat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -137,47 +141,13 @@ ble_hs_startup_set_evmask_tx(void)
|
||||
|
||||
/**
|
||||
* Enable the following events:
|
||||
* 0x0000000000000001 Inquiry Complete Event
|
||||
* 0x0000000000000002 Inquiry Result Event
|
||||
* 0x0000000000000004 Connection Complete Event
|
||||
* 0x0000000000000008 Connection Request Event
|
||||
* 0x0000000000000010 Disconnection Complete Event
|
||||
* 0x0000000000000020 Authentication Complete Event
|
||||
* 0x0000000000000040 Remote Name Request Complete Event
|
||||
* 0x0000000000000080 Encryption Change Event
|
||||
* 0x0000000000000100 Change Connection Link Key Complete Event
|
||||
* 0x0000000000000200 Master Link Key Complete Event
|
||||
* 0x0000000000000400 Read Remote Supported Features Complete Event
|
||||
* 0x0000000000000800 Read Remote Version Information Complete Event
|
||||
* 0x0000000000001000 QoS Setup Complete Event
|
||||
* 0x0000000000002000 Reserved
|
||||
* 0x0000000000004000 Reserved
|
||||
* 0x0000000000008000 Hardware Error Event
|
||||
* 0x0000000000010000 Flush Occurred Event
|
||||
* 0x0000000000020000 Role Change Event
|
||||
* 0x0000000000040000 Reserved
|
||||
* 0x0000000000080000 Mode Change Event
|
||||
* 0x0000000000100000 Return Link Keys Event
|
||||
* 0x0000000000200000 PIN Code Request Event
|
||||
* 0x0000000000400000 Link Key Request Event
|
||||
* 0x0000000000800000 Link Key Notification Event
|
||||
* 0x0000000001000000 Loopback Command Event
|
||||
* 0x0000000002000000 Data Buffer Overflow Event
|
||||
* 0x0000000004000000 Max Slots Change Event
|
||||
* 0x0000000008000000 Read Clock Offset Complete Event
|
||||
* 0x0000000010000000 Connection Packet Type Changed Event
|
||||
* 0x0000000020000000 QoS Violation Event
|
||||
* 0x0000000040000000 Page Scan Mode Change Event [deprecated]
|
||||
* 0x0000000080000000 Page Scan Repetition Mode Change Event
|
||||
* 0x0000000100000000 Flow Specification Complete Event
|
||||
* 0x0000000200000000 Inquiry Result with RSSI Event
|
||||
* 0x0000000400000000 Read Remote Extended Features Complete Event
|
||||
* 0x0000080000000000 Synchronous Connection Complete Event
|
||||
* 0x0000100000000000 Synchronous Connection Changed Event
|
||||
* 0x0000800000000000 Encryption Key Refresh Complete Event
|
||||
* 0x2000000000000000 LE Meta-Event
|
||||
*/
|
||||
ble_hs_hci_cmd_build_set_event_mask(0x20009807ffffffff, buf, sizeof buf);
|
||||
ble_hs_hci_cmd_build_set_event_mask(0x2000000002008090, buf, sizeof buf);
|
||||
rc = ble_hs_hci_cmd_tx_empty_ack(buf);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
|
||||
@@ -967,6 +967,15 @@ struct hci_le_conn_param_req
|
||||
uint16_t timeout;
|
||||
};
|
||||
|
||||
/* Read Remote Supported Features complete LE meta subevent */
|
||||
struct hci_le_rd_rem_supp_feat_complete
|
||||
{
|
||||
uint8_t subevent_code;
|
||||
uint8_t status;
|
||||
uint16_t connection_handle;
|
||||
uint8_t features[8];
|
||||
};
|
||||
|
||||
/* LE long term key request event (note: fields out of order). */
|
||||
struct hci_le_lt_key_req
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user