mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-10-09 07:57:21 +00:00
nimble/ll: Refactor conn init param handling
This fixes handling of parameters used for conn init. Firstly, we only need conn init params when intiating new connection so we can have single, global instance of that params - no need to store them in conns. This saves 72 bytes of RAM per connsm. Secondly, we do not need to store all parameters from HCI command since some of them are only used to initialize scanner and those can be used immediately. We only need to store connection parameters for ext conn create. This also allows to share more code between legacy and ext conn create code paths.
This commit is contained in:
@@ -188,29 +188,6 @@ struct hci_conn_update
|
||||
uint16_t max_ce_len;
|
||||
};
|
||||
|
||||
struct hci_ext_conn_params
|
||||
{
|
||||
uint16_t scan_itvl;
|
||||
uint16_t scan_window;
|
||||
uint32_t conn_itvl;
|
||||
uint16_t conn_itvl_ticks;
|
||||
uint8_t conn_itvl_usecs;
|
||||
uint16_t conn_latency;
|
||||
uint16_t supervision_timeout;
|
||||
uint16_t min_ce_len;
|
||||
uint16_t max_ce_len;
|
||||
};
|
||||
|
||||
struct hci_ext_create_conn
|
||||
{
|
||||
uint8_t filter_policy;
|
||||
uint8_t own_addr_type;
|
||||
uint8_t peer_addr_type;
|
||||
uint8_t peer_addr[BLE_DEV_ADDR_LEN];
|
||||
uint8_t init_phy_mask;
|
||||
struct hci_ext_conn_params params[3];
|
||||
};
|
||||
|
||||
/* Connection state machine */
|
||||
struct ble_ll_conn_sm
|
||||
{
|
||||
@@ -379,10 +356,6 @@ struct ble_ll_conn_sm
|
||||
/* XXX: for now, just store them all */
|
||||
struct ble_ll_conn_params conn_cp;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
struct hci_ext_create_conn initial_params;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
uint8_t sync_transfer_mode;
|
||||
uint16_t sync_transfer_skip;
|
||||
|
||||
@@ -197,10 +197,11 @@ int ble_ll_scan_can_chg_whitelist(void);
|
||||
int ble_ll_scan_enabled(void);
|
||||
|
||||
/* Initialize the scanner when we start initiating */
|
||||
struct hci_create_conn;
|
||||
struct ble_ll_conn_create_scan;
|
||||
struct ble_ll_conn_create_params;
|
||||
int
|
||||
ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
|
||||
struct ble_ll_conn_sm *connsm);
|
||||
ble_ll_scan_initiator_start(struct ble_ll_conn_sm *connsm, uint8_t ext,
|
||||
struct ble_ll_conn_create_scan *cc_scan);
|
||||
|
||||
/* Returns storage for PDU data (for SCAN_REQ or CONNECT_IND) */
|
||||
struct ble_ll_scan_pdu_data *ble_ll_scan_get_pdu_data(void);
|
||||
@@ -227,12 +228,6 @@ void ble_ll_scan_wfr_timer_exp(void);
|
||||
void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
/* Initialize the extended scanner when we start initiating */
|
||||
struct hci_ext_create_conn;
|
||||
int
|
||||
ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
|
||||
struct ble_ll_conn_sm *connsm);
|
||||
|
||||
/* Called to parse extended advertising*/
|
||||
void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data);
|
||||
#endif
|
||||
|
||||
@@ -202,6 +202,11 @@ void ble_phy_resolv_list_disable(void);
|
||||
#define BLE_PHY_MASK_2M (BLE_HCI_LE_PHY_2M_PREF_MASK)
|
||||
#define BLE_PHY_MASK_CODED (BLE_HCI_LE_PHY_CODED_PREF_MASK)
|
||||
|
||||
/* PHY indices (for a zero-based array) */
|
||||
#define BLE_PHY_IDX_1M (0)
|
||||
#define BLE_PHY_IDX_2M (1)
|
||||
#define BLE_PHY_IDX_CODED (2)
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY))
|
||||
uint32_t ble_phy_mode_pdu_start_off(int phy);
|
||||
void ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode);
|
||||
|
||||
@@ -577,7 +577,7 @@ ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext)
|
||||
* Test specification extends this also to initiating.
|
||||
*/
|
||||
|
||||
if (g_ble_ll_conn_create_sm || ble_ll_scan_enabled() ||
|
||||
if (g_ble_ll_conn_create_sm.connsm || ble_ll_scan_enabled() ||
|
||||
(!hci_adv_ext && ble_ll_adv_enabled())) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
@@ -143,8 +143,7 @@ struct ble_ll_conn_global_params g_ble_ll_conn_params;
|
||||
struct ble_ll_conn_sync_transfer_params g_ble_ll_conn_sync_transfer_params;
|
||||
#endif
|
||||
|
||||
/* Pointer to connection state machine we are trying to create */
|
||||
struct ble_ll_conn_sm *g_ble_ll_conn_create_sm;
|
||||
struct ble_ll_conn_create_sm g_ble_ll_conn_create_sm;
|
||||
|
||||
/* Pointer to current connection */
|
||||
struct ble_ll_conn_sm *g_ble_ll_conn_cur_sm;
|
||||
@@ -421,25 +420,23 @@ ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *csm)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ble_ll_conn_calc_itvl_ticks(struct ble_ll_conn_sm *connsm)
|
||||
void
|
||||
ble_ll_conn_itvl_to_ticks(uint32_t itvl, uint32_t *itvl_ticks,
|
||||
uint8_t *itvl_usecs)
|
||||
{
|
||||
uint32_t ticks;
|
||||
uint32_t usecs;
|
||||
|
||||
/*
|
||||
* Precalculate the number of ticks and remaining microseconds for
|
||||
* the connection interval
|
||||
*/
|
||||
usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
|
||||
usecs = itvl * BLE_LL_CONN_ITVL_USECS;
|
||||
ticks = os_cputime_usecs_to_ticks(usecs);
|
||||
connsm->conn_itvl_usecs = (uint8_t)(usecs -
|
||||
os_cputime_ticks_to_usecs(ticks));
|
||||
if (connsm->conn_itvl_usecs == 31) {
|
||||
connsm->conn_itvl_usecs = 0;
|
||||
usecs = usecs - os_cputime_ticks_to_usecs(ticks);
|
||||
if (usecs == 31) {
|
||||
usecs = 0;
|
||||
++ticks;
|
||||
}
|
||||
connsm->conn_itvl_ticks = ticks;
|
||||
|
||||
*itvl_ticks = ticks;
|
||||
*itvl_usecs = usecs;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1578,37 +1575,23 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm)
|
||||
*/
|
||||
void
|
||||
ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm,
|
||||
struct hci_create_conn *hcc)
|
||||
struct ble_ll_conn_create_scan *cc_scan,
|
||||
struct ble_ll_conn_create_params *cc_params)
|
||||
{
|
||||
|
||||
ble_ll_conn_master_common_init(connsm);
|
||||
|
||||
/* Set slave latency and supervision timeout */
|
||||
connsm->slave_latency = hcc->conn_latency;
|
||||
connsm->supervision_tmo = hcc->supervision_timeout;
|
||||
connsm->own_addr_type = cc_scan->own_addr_type;
|
||||
memcpy(&connsm->peer_addr, &cc_scan->peer_addr, BLE_DEV_ADDR_LEN);
|
||||
connsm->peer_addr_type = cc_scan->peer_addr_type;
|
||||
|
||||
/* Set own address type and peer address if needed */
|
||||
connsm->own_addr_type = hcc->own_addr_type;
|
||||
if (hcc->filter_policy == 0) {
|
||||
memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN);
|
||||
connsm->peer_addr_type = hcc->peer_addr_type;
|
||||
}
|
||||
|
||||
/* XXX: for now, just make connection interval equal to max */
|
||||
connsm->conn_itvl = hcc->conn_itvl_max;
|
||||
|
||||
/* Check the min/max CE lengths are less than connection interval */
|
||||
if (hcc->min_ce_len > (connsm->conn_itvl * 2)) {
|
||||
connsm->min_ce_len = connsm->conn_itvl * 2;
|
||||
} else {
|
||||
connsm->min_ce_len = hcc->min_ce_len;
|
||||
}
|
||||
|
||||
if (hcc->max_ce_len > (connsm->conn_itvl * 2)) {
|
||||
connsm->max_ce_len = connsm->conn_itvl * 2;
|
||||
} else {
|
||||
connsm->max_ce_len = hcc->max_ce_len;
|
||||
}
|
||||
connsm->conn_itvl = cc_params->conn_itvl;
|
||||
connsm->conn_itvl_ticks = cc_params->conn_itvl_ticks;
|
||||
connsm->conn_itvl_usecs = cc_params->conn_itvl_usecs;
|
||||
connsm->slave_latency = cc_params->conn_latency;
|
||||
connsm->supervision_tmo = cc_params->supervision_timeout;
|
||||
connsm->min_ce_len = cc_params->min_ce_len;
|
||||
connsm->max_ce_len = cc_params->max_ce_len;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1684,54 +1667,20 @@ ble_ll_conn_init_phy(struct ble_ll_conn_sm *connsm, int phy)
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
|
||||
void
|
||||
ble_ll_conn_ext_master_init(struct ble_ll_conn_sm *connsm,
|
||||
struct hci_ext_create_conn *hcc)
|
||||
static void
|
||||
ble_ll_conn_create_set_params(struct ble_ll_conn_sm *connsm, uint8_t phy)
|
||||
{
|
||||
struct ble_ll_conn_create_params *cc_params;
|
||||
|
||||
ble_ll_conn_master_common_init(connsm);
|
||||
cc_params = &g_ble_ll_conn_create_sm.params[phy - 1];
|
||||
|
||||
/* Set own address type and peer address if needed */
|
||||
connsm->own_addr_type = hcc->own_addr_type;
|
||||
if (hcc->filter_policy == 0) {
|
||||
memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN);
|
||||
connsm->peer_addr_type = hcc->peer_addr_type;
|
||||
}
|
||||
connsm->slave_latency = cc_params->conn_latency;
|
||||
connsm->supervision_tmo = cc_params->supervision_timeout;
|
||||
|
||||
connsm->initial_params = *hcc;
|
||||
connsm->conn_itvl = cc_params->conn_itvl;
|
||||
connsm->conn_itvl_ticks = cc_params->conn_itvl_ticks;
|
||||
connsm->conn_itvl_usecs = cc_params->conn_itvl_usecs;
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm,
|
||||
struct hci_ext_conn_params *hcc_params, int phy)
|
||||
{
|
||||
connsm->slave_latency = hcc_params->conn_latency;
|
||||
connsm->supervision_tmo = hcc_params->supervision_timeout;
|
||||
|
||||
connsm->conn_itvl = hcc_params->conn_itvl;
|
||||
connsm->conn_itvl_ticks = hcc_params->conn_itvl_ticks;
|
||||
connsm->conn_itvl_usecs = hcc_params->conn_itvl_usecs;
|
||||
|
||||
/* Check the min/max CE lengths are less than connection interval */
|
||||
if (hcc_params->min_ce_len > (connsm->conn_itvl * 2)) {
|
||||
connsm->min_ce_len = connsm->conn_itvl * 2;
|
||||
} else {
|
||||
connsm->min_ce_len = hcc_params->min_ce_len;
|
||||
}
|
||||
|
||||
if (hcc_params->max_ce_len > (connsm->conn_itvl * 2)) {
|
||||
connsm->max_ce_len = connsm->conn_itvl * 2;
|
||||
} else {
|
||||
connsm->max_ce_len = hcc_params->max_ce_len;
|
||||
}
|
||||
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
ble_ll_conn_init_phy(connsm, phy);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
@@ -1862,8 +1811,6 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
|
||||
connsm);
|
||||
#endif
|
||||
|
||||
ble_ll_conn_calc_itvl_ticks(connsm);
|
||||
|
||||
/* Add to list of active connections */
|
||||
SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle);
|
||||
}
|
||||
@@ -2170,7 +2117,10 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
|
||||
connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS;
|
||||
connsm->tx_win_off = upd->winoffset;
|
||||
connsm->conn_itvl = upd->interval;
|
||||
ble_ll_conn_calc_itvl_ticks(connsm);
|
||||
|
||||
ble_ll_conn_itvl_to_ticks(connsm->conn_itvl, &connsm->conn_itvl_ticks,
|
||||
&connsm->conn_itvl_usecs);
|
||||
|
||||
if (upd->winoffset != 0) {
|
||||
usecs = upd->winoffset * BLE_LL_CONN_ITVL_USECS;
|
||||
ticks = os_cputime_usecs_to_ticks(usecs);
|
||||
@@ -2651,7 +2601,7 @@ ble_ll_conn_prepare_connect_ind(struct ble_ll_conn_sm *connsm,
|
||||
}
|
||||
} else {
|
||||
/* Get pointer to our device address */
|
||||
connsm = g_ble_ll_conn_create_sm;
|
||||
connsm = g_ble_ll_conn_create_sm.connsm;
|
||||
if ((connsm->own_addr_type & 1) == 0) {
|
||||
addr = g_dev_addr;
|
||||
} else {
|
||||
@@ -2764,12 +2714,11 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu,
|
||||
struct ble_mbuf_hdr *rxhdr;
|
||||
int8_t rpa_index;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
struct hci_ext_conn_params *ecp;
|
||||
uint8_t phy;
|
||||
#endif
|
||||
int rc;
|
||||
|
||||
connsm = g_ble_ll_conn_create_sm;
|
||||
connsm = g_ble_ll_conn_create_sm.connsm;
|
||||
rxhdr = BLE_MBUF_HDR_PTR(rxpdu);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
@@ -2779,8 +2728,7 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu,
|
||||
#else
|
||||
phy = BLE_PHY_1M;
|
||||
#endif
|
||||
ecp = &connsm->initial_params.params[phy - 1];
|
||||
ble_ll_conn_ext_set_params(connsm, ecp, phy);
|
||||
ble_ll_conn_create_set_params(connsm, phy);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2806,6 +2754,12 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu,
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && BLE_LL_BT5_PHY_SUPPORTED
|
||||
if (ext) {
|
||||
ble_ll_conn_init_phy(connsm, phy);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2814,7 +2768,7 @@ ble_ll_conn_send_connect_req_cancel(void)
|
||||
{
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
|
||||
connsm = g_ble_ll_conn_create_sm;
|
||||
connsm = g_ble_ll_conn_create_sm.connsm;
|
||||
|
||||
ble_ll_sched_rmv_elem(&connsm->conn_sch);
|
||||
}
|
||||
@@ -2825,8 +2779,8 @@ ble_ll_conn_master_start(uint8_t phy, uint8_t csa,
|
||||
{
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
|
||||
connsm = g_ble_ll_conn_create_sm;
|
||||
g_ble_ll_conn_create_sm = NULL;
|
||||
connsm = g_ble_ll_conn_create_sm.connsm;
|
||||
g_ble_ll_conn_create_sm.connsm = NULL;
|
||||
|
||||
connsm->peer_addr_type = addrd->adv_addr_type;
|
||||
memcpy(connsm->peer_addr, addrd->adv_addr, 6);
|
||||
@@ -3688,6 +3642,9 @@ ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr,
|
||||
goto err_slave_start;
|
||||
}
|
||||
|
||||
ble_ll_conn_itvl_to_ticks(connsm->conn_itvl, &connsm->conn_itvl_ticks,
|
||||
&connsm->conn_itvl_usecs);
|
||||
|
||||
/* Start the connection state machine */
|
||||
connsm->conn_role = BLE_LL_CONN_ROLE_SLAVE;
|
||||
ble_ll_conn_sm_new(connsm);
|
||||
@@ -3751,7 +3708,7 @@ ble_ll_conn_module_reset(void)
|
||||
}
|
||||
|
||||
/* Reset connection we are attempting to create */
|
||||
g_ble_ll_conn_create_sm = NULL;
|
||||
g_ble_ll_conn_create_sm.connsm = NULL;
|
||||
|
||||
/* Now go through and end all the connections */
|
||||
while (1) {
|
||||
|
||||
@@ -43,19 +43,22 @@ static ble_npl_time_t g_ble_ll_last_num_comp_pkt_evt;
|
||||
extern uint8_t *g_ble_ll_conn_comp_ev;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
static const uint8_t ble_ll_valid_conn_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK
|
||||
static const uint8_t ble_ll_conn_create_valid_phy_mask = (
|
||||
BLE_HCI_LE_PHY_1M_PREF_MASK |
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
|
||||
| BLE_HCI_LE_PHY_2M_PREF_MASK
|
||||
BLE_HCI_LE_PHY_2M_PREF_MASK |
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
| BLE_HCI_LE_PHY_CODED_PREF_MASK
|
||||
BLE_HCI_LE_PHY_CODED_PREF_MASK |
|
||||
#endif
|
||||
);
|
||||
static const uint8_t ble_ll_conn_required_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK
|
||||
0);
|
||||
|
||||
static const uint8_t ble_ll_conn_create_required_phy_mask = (
|
||||
BLE_HCI_LE_PHY_1M_PREF_MASK |
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
| BLE_HCI_LE_PHY_CODED_PREF_MASK
|
||||
BLE_HCI_LE_PHY_CODED_PREF_MASK |
|
||||
#endif
|
||||
);
|
||||
0);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -401,18 +404,74 @@ ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t reason)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_conn_hci_chk_scan_params(uint16_t itvl, uint16_t window)
|
||||
int
|
||||
ble_ll_conn_hci_create_check_scan(struct ble_ll_conn_create_scan *p)
|
||||
{
|
||||
/* Check interval and window */
|
||||
if ((itvl < BLE_HCI_SCAN_ITVL_MIN) ||
|
||||
(itvl > BLE_HCI_SCAN_ITVL_MAX) ||
|
||||
(window < BLE_HCI_SCAN_WINDOW_MIN) ||
|
||||
(window > BLE_HCI_SCAN_WINDOW_MAX) ||
|
||||
(itvl < window)) {
|
||||
if (p->filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if ((p->filter_policy == 0) &&
|
||||
(p->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (p->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
if (p->init_phy_mask & ~ble_ll_conn_create_valid_phy_mask) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (!(p->init_phy_mask & ble_ll_conn_create_required_phy_mask)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_conn_hci_create_check_params(struct ble_ll_conn_create_params *cc_params)
|
||||
{
|
||||
uint32_t supervision_tmo_us;
|
||||
uint32_t conn_itvl_us;
|
||||
|
||||
if ((cc_params->conn_itvl < BLE_HCI_CONN_ITVL_MIN) ||
|
||||
(cc_params->conn_itvl > BLE_HCI_CONN_ITVL_MAX) ||
|
||||
(cc_params->conn_latency > BLE_HCI_CONN_LATENCY_MAX) ||
|
||||
(cc_params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) ||
|
||||
(cc_params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* Supervision timeout must be longer than (1 + latency) * interval * 2 */
|
||||
supervision_tmo_us = cc_params->supervision_timeout *
|
||||
BLE_HCI_CONN_SPVN_TMO_UNITS * 1000;
|
||||
conn_itvl_us = cc_params->conn_itvl * BLE_LL_CONN_ITVL_USECS;
|
||||
|
||||
if (supervision_tmo_us <= (1 + cc_params->conn_latency) * conn_itvl_us * 2) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (cc_params->min_ce_len > cc_params->max_ce_len) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* Adjust min/max ce length to be less than interval */
|
||||
if (cc_params->min_ce_len > cc_params->conn_itvl) {
|
||||
cc_params->min_ce_len = cc_params->conn_itvl;
|
||||
}
|
||||
if (cc_params->max_ce_len > cc_params->conn_itvl) {
|
||||
cc_params->max_ce_len = cc_params->conn_itvl;
|
||||
}
|
||||
|
||||
/* Precalculate conn interval */
|
||||
ble_ll_conn_itvl_to_ticks(cc_params->conn_itvl, &cc_params->conn_itvl_ticks,
|
||||
&cc_params->conn_itvl_usecs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -426,11 +485,14 @@ ble_ll_conn_hci_chk_scan_params(uint16_t itvl, uint16_t window)
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len)
|
||||
ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_create_conn_cp *cmd = (const void *) cmdbuf;
|
||||
struct ble_ll_conn_create_scan cc_scan;
|
||||
struct ble_ll_conn_create_params cc_params;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
struct hci_create_conn hcc = { 0 };
|
||||
uint16_t conn_itvl_min;
|
||||
uint16_t conn_itvl_max;
|
||||
int rc;
|
||||
|
||||
if (len < sizeof(*cmd)) {
|
||||
@@ -438,7 +500,7 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len)
|
||||
}
|
||||
|
||||
/* If we are already creating a connection we should leave */
|
||||
if (g_ble_ll_conn_create_sm) {
|
||||
if (g_ble_ll_conn_create_sm.connsm) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
@@ -447,57 +509,48 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len)
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
/* Retrieve command data */
|
||||
hcc.scan_itvl = le16toh(cmd->scan_itvl);
|
||||
hcc.scan_window = le16toh(cmd->scan_window);
|
||||
|
||||
rc = ble_ll_conn_hci_chk_scan_params(hcc.scan_itvl, hcc.scan_window);
|
||||
if (rc) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
cc_scan.own_addr_type = cmd->own_addr_type;
|
||||
cc_scan.filter_policy = cmd->filter_policy;
|
||||
if (cc_scan.filter_policy == 0) {
|
||||
cc_scan.peer_addr_type = cmd->peer_addr_type;
|
||||
memcpy(&cc_scan.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN);
|
||||
} else {
|
||||
cc_scan.peer_addr_type = 0;
|
||||
memset(&cc_scan.peer_addr, 0, BLE_DEV_ADDR_LEN);
|
||||
}
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
cc_scan.init_phy_mask = BLE_HCI_LE_PHY_1M_PREF_MASK;
|
||||
#endif
|
||||
|
||||
/* Check filter policy */
|
||||
hcc.filter_policy = cmd->filter_policy;
|
||||
if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
cc_scan.scan_params[PHY_UNCODED].itvl = le16toh(cmd->scan_itvl);
|
||||
cc_scan.scan_params[PHY_UNCODED].window = le16toh(cmd->scan_window);
|
||||
|
||||
/* Get peer address type and address only if no whitelist used */
|
||||
if (hcc.filter_policy == 0) {
|
||||
hcc.peer_addr_type = cmd->peer_addr_type;
|
||||
if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
memcpy(&hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN);
|
||||
}
|
||||
|
||||
/* Get own address type (used in connection request) */
|
||||
hcc.own_addr_type = cmd->own_addr_type;
|
||||
if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* Check connection interval, latency and supervision timeoout */
|
||||
hcc.conn_itvl_min = le16toh(cmd->min_conn_itvl);
|
||||
hcc.conn_itvl_max = le16toh(cmd->max_conn_itvl);
|
||||
hcc.conn_latency = le16toh(cmd->conn_latency);
|
||||
hcc.supervision_timeout = le16toh(cmd->tmo);
|
||||
rc = ble_ll_conn_hci_chk_conn_params(hcc.conn_itvl_min,
|
||||
hcc.conn_itvl_max,
|
||||
hcc.conn_latency,
|
||||
hcc.supervision_timeout);
|
||||
rc = ble_ll_conn_hci_create_check_scan(&cc_scan);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Min/max connection event lengths */
|
||||
hcc.min_ce_len = le16toh(cmd->min_ce);
|
||||
hcc.max_ce_len = le16toh(cmd->max_ce);
|
||||
if (hcc.min_ce_len > hcc.max_ce_len) {
|
||||
conn_itvl_min = le16toh(cmd->min_conn_itvl);
|
||||
conn_itvl_max = le16toh(cmd->max_conn_itvl);
|
||||
|
||||
/* Check min/max interval here since generic check does not have min/max
|
||||
* parameters to check.
|
||||
*/
|
||||
if (conn_itvl_min > conn_itvl_max) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
cc_params.conn_itvl = conn_itvl_max;
|
||||
cc_params.conn_latency = le16toh(cmd->conn_latency);
|
||||
cc_params.supervision_timeout = le16toh(cmd->tmo);
|
||||
cc_params.min_ce_len = le16toh(cmd->min_ce);
|
||||
cc_params.max_ce_len = le16toh(cmd->max_ce);
|
||||
|
||||
rc = ble_ll_conn_hci_create_check_params(&cc_params);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Make sure we can allocate an event to send the connection complete */
|
||||
if (ble_ll_init_alloc_conn_comp_ev()) {
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
@@ -510,18 +563,14 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len)
|
||||
}
|
||||
|
||||
/* Initialize state machine in master role and start state machine */
|
||||
ble_ll_conn_master_init(connsm, &hcc);
|
||||
ble_ll_conn_master_init(connsm, &cc_scan, &cc_params);
|
||||
ble_ll_conn_sm_new(connsm);
|
||||
/* CSA will be selected when advertising is received */
|
||||
|
||||
/* Start scanning */
|
||||
rc = ble_ll_scan_initiator_start(&hcc, connsm);
|
||||
rc = ble_ll_scan_initiator_start(connsm, 0, &cc_scan);
|
||||
if (rc) {
|
||||
SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle);
|
||||
STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
|
||||
} else {
|
||||
/* Set the connection state machine we are trying to create. */
|
||||
g_ble_ll_conn_create_sm = connsm;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -529,68 +578,117 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len)
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
static void
|
||||
ble_ll_conn_hcc_params_set_fallback(struct hci_ext_create_conn *hcc,
|
||||
const struct hci_ext_conn_params *fallback)
|
||||
ble_ll_conn_hci_ext_create_set_fb_params(uint8_t init_phy_mask,
|
||||
struct ble_ll_conn_create_params *cc_params_fb)
|
||||
{
|
||||
BLE_LL_ASSERT(fallback);
|
||||
|
||||
if (!(hcc->init_phy_mask & BLE_PHY_MASK_1M)) {
|
||||
hcc->params[0] = *fallback;
|
||||
if ((init_phy_mask & BLE_PHY_MASK_1M) == 0) {
|
||||
g_ble_ll_conn_create_sm.params[BLE_PHY_IDX_1M] = *cc_params_fb;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
|
||||
if (!(hcc->init_phy_mask & BLE_PHY_MASK_2M)) {
|
||||
hcc->params[1] = *fallback;
|
||||
if ((init_phy_mask & BLE_PHY_MASK_2M) == 0) {
|
||||
g_ble_ll_conn_create_sm.params[BLE_PHY_IDX_2M] = *cc_params_fb;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
if (!(hcc->init_phy_mask & BLE_PHY_MASK_CODED)) {
|
||||
hcc->params[2] = *fallback;
|
||||
if ((init_phy_mask & BLE_PHY_MASK_CODED) == 0) {
|
||||
g_ble_ll_conn_create_sm.params[BLE_PHY_IDX_CODED] = *cc_params_fb;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_conn_itvl_to_ticks(uint32_t itvl, uint16_t *itvl_ticks,
|
||||
uint8_t *itvl_usecs)
|
||||
static int
|
||||
ble_ll_conn_hci_ext_create_parse_params(const struct conn_params *params,
|
||||
uint8_t phy,
|
||||
struct ble_ll_conn_create_scan *cc_scan,
|
||||
struct ble_ll_conn_create_params *cc_params)
|
||||
{
|
||||
uint32_t ticks;
|
||||
uint32_t usecs;
|
||||
|
||||
usecs = itvl * BLE_LL_CONN_ITVL_USECS;
|
||||
ticks = os_cputime_usecs_to_ticks(usecs);
|
||||
usecs = usecs - os_cputime_ticks_to_usecs(ticks);
|
||||
if (usecs == 31) {
|
||||
usecs = 0;
|
||||
++ticks;
|
||||
}
|
||||
|
||||
*itvl_ticks = ticks;
|
||||
*itvl_usecs = usecs;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_ext_create_conn_cp *cmd = (const void *) cmdbuf;
|
||||
const struct conn_params *params = cmd->conn_params;
|
||||
const struct hci_ext_conn_params *fallback_params = NULL;
|
||||
struct hci_ext_create_conn hcc = { 0 };
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
uint16_t conn_itvl_min;
|
||||
uint16_t conn_itvl_max;
|
||||
uint16_t scan_itvl;
|
||||
uint16_t scan_window;
|
||||
int rc;
|
||||
|
||||
/* validate length */
|
||||
if (len < sizeof(*cmd)) {
|
||||
conn_itvl_min = le16toh(params->conn_min_itvl);
|
||||
conn_itvl_max = le16toh(params->conn_max_itvl);
|
||||
|
||||
/* Check min/max interval here since generic check does not have min/max
|
||||
* parameters to check.
|
||||
*/
|
||||
if (conn_itvl_min > conn_itvl_max) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
len -= sizeof(*cmd);
|
||||
cc_params->conn_itvl = conn_itvl_max;
|
||||
cc_params->conn_latency = le16toh(params->conn_latency);
|
||||
cc_params->supervision_timeout = le16toh(params->supervision_timeout);
|
||||
cc_params->min_ce_len = le16toh(params->min_ce);
|
||||
cc_params->max_ce_len = le16toh(params->max_ce);
|
||||
|
||||
rc = ble_ll_conn_hci_create_check_params(cc_params);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (phy != BLE_PHY_2M) {
|
||||
scan_itvl = le16toh(params->scan_itvl);
|
||||
scan_window = le16toh(params->scan_window);
|
||||
|
||||
if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
|
||||
(scan_itvl > BLE_HCI_SCAN_ITVL_MAX) ||
|
||||
(scan_window < BLE_HCI_SCAN_WINDOW_MIN) ||
|
||||
(scan_window > BLE_HCI_SCAN_WINDOW_MAX) ||
|
||||
(scan_itvl < scan_window)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (phy == BLE_PHY_1M) {
|
||||
cc_scan->scan_params[PHY_UNCODED].itvl = scan_itvl;
|
||||
cc_scan->scan_params[PHY_UNCODED].window = scan_window;
|
||||
} else {
|
||||
cc_scan->scan_params[PHY_CODED].itvl = scan_itvl;
|
||||
cc_scan->scan_params[PHY_CODED].window = scan_window;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
static const struct init_phy {
|
||||
uint8_t idx;
|
||||
uint8_t mask;
|
||||
uint8_t phy;
|
||||
} init_phys[] = {
|
||||
{BLE_PHY_IDX_1M, BLE_PHY_MASK_1M, BLE_PHY_1M},
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
|
||||
{BLE_PHY_IDX_2M, BLE_PHY_MASK_2M, BLE_PHY_2M},
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
{BLE_PHY_IDX_CODED, BLE_PHY_MASK_CODED, BLE_PHY_CODED},
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct ble_hci_le_ext_create_conn_cp *cmd = (const void *)cmdbuf;
|
||||
const struct conn_params *params = cmd->conn_params;
|
||||
struct ble_ll_conn_create_scan cc_scan;
|
||||
struct ble_ll_conn_create_params *cc_params;
|
||||
struct ble_ll_conn_create_params *cc_params_fb;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
const struct init_phy *init_phy;
|
||||
int rc;
|
||||
|
||||
/* validate length */
|
||||
if (len < sizeof(*cmd) +
|
||||
__builtin_popcount(cmd->init_phy_mask) * sizeof(*params)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* If we are already creating a connection we should leave */
|
||||
if (g_ble_ll_conn_create_sm) {
|
||||
if (g_ble_ll_conn_create_sm.connsm) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
@@ -599,161 +697,47 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len)
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
hcc.filter_policy = cmd->filter_policy;
|
||||
if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
cc_scan.own_addr_type = cmd->own_addr_type;
|
||||
cc_scan.filter_policy = cmd->filter_policy;
|
||||
if (cc_scan.filter_policy == 0) {
|
||||
cc_scan.peer_addr_type = cmd->peer_addr_type;
|
||||
memcpy(cc_scan.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN);
|
||||
} else {
|
||||
cc_scan.peer_addr_type = 0;
|
||||
memset(cc_scan.peer_addr, 0, BLE_DEV_ADDR_LEN);
|
||||
}
|
||||
cc_scan.init_phy_mask = cmd->init_phy_mask;
|
||||
|
||||
rc = ble_ll_conn_hci_create_check_scan(&cc_scan);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
hcc.own_addr_type = cmd->own_addr_type;
|
||||
if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
cc_params_fb = NULL;
|
||||
|
||||
/* Validate peer address type only if no whitelist used */
|
||||
if (hcc.filter_policy == 0) {
|
||||
hcc.peer_addr_type = cmd->peer_addr_type;
|
||||
for (int i = 0; i < ARRAY_SIZE(init_phys); i++) {
|
||||
init_phy = &init_phys[i];
|
||||
|
||||
if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
if ((cc_scan.init_phy_mask & init_phy->mask) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN);
|
||||
}
|
||||
cc_params = &g_ble_ll_conn_create_sm.params[init_phy->idx];
|
||||
|
||||
hcc.init_phy_mask = cmd->init_phy_mask;
|
||||
if (hcc.init_phy_mask & ~ble_ll_valid_conn_phy_mask) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (!(hcc.init_phy_mask & ble_ll_conn_required_phy_mask)) {
|
||||
/* At least one of those need to be set */
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (hcc.init_phy_mask & BLE_PHY_MASK_1M) {
|
||||
if (len < sizeof(*params)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
len -= sizeof(*params);
|
||||
|
||||
hcc.params[0].scan_itvl = le16toh(params->scan_itvl);
|
||||
hcc.params[0].scan_window = le16toh(params->scan_window);
|
||||
|
||||
rc = ble_ll_conn_hci_chk_scan_params(hcc.params[0].scan_itvl,
|
||||
hcc.params[0].scan_window);
|
||||
rc = ble_ll_conn_hci_ext_create_parse_params(params, init_phy->phy,
|
||||
&cc_scan, cc_params);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
conn_itvl_min = le16toh(params->conn_min_itvl);
|
||||
conn_itvl_max = le16toh(params->conn_max_itvl);
|
||||
hcc.params[0].conn_latency = le16toh(params->conn_latency);
|
||||
hcc.params[0].supervision_timeout = le16toh(params->supervision_timeout);
|
||||
|
||||
rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max,
|
||||
hcc.params[0].conn_latency,
|
||||
hcc.params[0].supervision_timeout);
|
||||
if (rc) {
|
||||
return rc;
|
||||
if (!cc_params_fb) {
|
||||
cc_params_fb = cc_params;
|
||||
}
|
||||
|
||||
/* Min/max connection event lengths */
|
||||
hcc.params[0].min_ce_len = le16toh(params->min_ce);
|
||||
hcc.params[0].max_ce_len = le16toh(params->max_ce);
|
||||
if (hcc.params[0].min_ce_len > hcc.params[0].max_ce_len) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
hcc.params[0].conn_itvl = conn_itvl_max;
|
||||
ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[0].conn_itvl_ticks,
|
||||
&hcc.params[0].conn_itvl_usecs);
|
||||
|
||||
fallback_params = &hcc.params[0];
|
||||
params++;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
|
||||
if (hcc.init_phy_mask & BLE_PHY_MASK_2M) {
|
||||
if (len < sizeof(*params)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
len -= sizeof(*params);
|
||||
|
||||
conn_itvl_min = le16toh(params->conn_min_itvl);
|
||||
conn_itvl_max = le16toh(params->conn_max_itvl);
|
||||
hcc.params[1].conn_latency = le16toh(params->conn_latency);
|
||||
hcc.params[1].supervision_timeout = le16toh(params->supervision_timeout);
|
||||
|
||||
rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max,
|
||||
hcc.params[1].conn_latency,
|
||||
hcc.params[1].supervision_timeout);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Min/max connection event lengths */
|
||||
hcc.params[1].min_ce_len = le16toh(params->min_ce);
|
||||
hcc.params[1].max_ce_len = le16toh(params->max_ce);
|
||||
if (hcc.params[1].min_ce_len > hcc.params[1].max_ce_len) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
hcc.params[1].conn_itvl = conn_itvl_max;
|
||||
ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[1].conn_itvl_ticks,
|
||||
&hcc.params[1].conn_itvl_usecs);
|
||||
|
||||
if (!fallback_params) {
|
||||
fallback_params = &hcc.params[1];
|
||||
}
|
||||
params++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
if (hcc.init_phy_mask & BLE_PHY_MASK_CODED) {
|
||||
if (len < sizeof(*params)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
len -= sizeof(*params);
|
||||
|
||||
hcc.params[2].scan_itvl = le16toh(params->scan_itvl);
|
||||
hcc.params[2].scan_window = le16toh(params->scan_window);
|
||||
|
||||
rc = ble_ll_conn_hci_chk_scan_params(hcc.params[2].scan_itvl,
|
||||
hcc.params[2].scan_window);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
conn_itvl_min = le16toh(params->conn_min_itvl);
|
||||
conn_itvl_max = le16toh(params->conn_max_itvl);
|
||||
hcc.params[2].conn_latency = le16toh(params->conn_latency);
|
||||
hcc.params[2].supervision_timeout = le16toh(params->supervision_timeout);
|
||||
|
||||
rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max,
|
||||
hcc.params[2].conn_latency,
|
||||
hcc.params[2].supervision_timeout);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Min/max connection event lengths */
|
||||
hcc.params[2].min_ce_len = le16toh(params->min_ce);
|
||||
hcc.params[2].max_ce_len = le16toh(params->max_ce);
|
||||
if (hcc.params[2].min_ce_len > hcc.params[2].max_ce_len) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
hcc.params[2].conn_itvl = conn_itvl_max;
|
||||
ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[2].conn_itvl_ticks,
|
||||
&hcc.params[2].conn_itvl_usecs);
|
||||
|
||||
if (!fallback_params) {
|
||||
fallback_params = &hcc.params[2];
|
||||
}
|
||||
params++;
|
||||
}
|
||||
#endif
|
||||
ble_ll_conn_hci_ext_create_set_fb_params(cc_scan.init_phy_mask,
|
||||
cc_params_fb);
|
||||
|
||||
/* Make sure we can allocate an event to send the connection complete */
|
||||
if (ble_ll_init_alloc_conn_comp_ev()) {
|
||||
@@ -766,20 +750,16 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len)
|
||||
return BLE_ERR_CONN_LIMIT;
|
||||
}
|
||||
|
||||
ble_ll_conn_hcc_params_set_fallback(&hcc, fallback_params);
|
||||
|
||||
/* Initialize state machine in master role and start state machine */
|
||||
ble_ll_conn_ext_master_init(connsm, &hcc);
|
||||
ble_ll_conn_master_init(connsm, &cc_scan,
|
||||
&g_ble_ll_conn_create_sm.params[0]);
|
||||
ble_ll_conn_sm_new(connsm);
|
||||
|
||||
/* Start scanning */
|
||||
rc = ble_ll_scan_ext_initiator_start(&hcc, connsm);
|
||||
rc = ble_ll_scan_initiator_start(connsm, 1, &cc_scan);
|
||||
if (rc) {
|
||||
SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle);
|
||||
STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
|
||||
} else {
|
||||
/* Set the connection state machine we are trying to create. */
|
||||
g_ble_ll_conn_create_sm = connsm;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -1125,10 +1105,10 @@ ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
|
||||
* return disallowed as well
|
||||
*/
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
connsm = g_ble_ll_conn_create_sm;
|
||||
connsm = g_ble_ll_conn_create_sm.connsm;
|
||||
if (connsm && (connsm->conn_state == BLE_LL_CONN_STATE_IDLE)) {
|
||||
/* stop scanning and end the connection event */
|
||||
g_ble_ll_conn_create_sm = NULL;
|
||||
g_ble_ll_conn_create_sm.connsm = NULL;
|
||||
ble_ll_scan_sm_stop(1);
|
||||
ble_ll_conn_end(connsm, BLE_ERR_UNK_CONN_ID);
|
||||
|
||||
|
||||
@@ -93,8 +93,38 @@ STAILQ_HEAD(ble_ll_conn_free_list, ble_ll_conn_sm);
|
||||
extern struct ble_ll_conn_active_list g_ble_ll_conn_active_list;
|
||||
extern struct ble_ll_conn_free_list g_ble_ll_conn_free_list;
|
||||
|
||||
/* Pointer to connection state machine we are trying to create */
|
||||
extern struct ble_ll_conn_sm *g_ble_ll_conn_create_sm;
|
||||
struct ble_ll_conn_create_scan {
|
||||
uint8_t filter_policy;
|
||||
uint8_t own_addr_type;
|
||||
uint8_t peer_addr_type;
|
||||
uint8_t peer_addr[BLE_DEV_ADDR_LEN];
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
uint8_t init_phy_mask;
|
||||
#endif
|
||||
struct {
|
||||
uint16_t itvl;
|
||||
uint16_t window;
|
||||
} scan_params[2];
|
||||
};
|
||||
|
||||
struct ble_ll_conn_create_params {
|
||||
uint32_t conn_itvl;
|
||||
uint32_t conn_itvl_ticks;
|
||||
uint8_t conn_itvl_usecs;
|
||||
uint16_t conn_latency;
|
||||
uint16_t supervision_timeout;
|
||||
uint16_t min_ce_len;
|
||||
uint16_t max_ce_len;
|
||||
};
|
||||
|
||||
struct ble_ll_conn_create_sm {
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
struct ble_ll_conn_create_params params[3];
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct ble_ll_conn_create_sm g_ble_ll_conn_create_sm;
|
||||
|
||||
/* Generic interface */
|
||||
struct ble_ll_len_req;
|
||||
@@ -123,15 +153,8 @@ void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om,
|
||||
uint8_t hdr_byte, uint16_t length);
|
||||
struct ble_ll_conn_sm *ble_ll_conn_sm_get(void);
|
||||
void ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm,
|
||||
struct hci_create_conn *hcc);
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
void ble_ll_conn_ext_master_init(struct ble_ll_conn_sm *connsm,
|
||||
struct hci_ext_create_conn *hcc);
|
||||
|
||||
void ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm,
|
||||
struct hci_ext_conn_params *hcc_params,
|
||||
int phy);
|
||||
#endif
|
||||
struct ble_ll_conn_create_scan *cc_scan,
|
||||
struct ble_ll_conn_create_params *cc_params);
|
||||
|
||||
struct ble_ll_conn_sm *ble_ll_conn_find_active_conn(uint16_t handle);
|
||||
void ble_ll_conn_update_eff_data_len(struct ble_ll_conn_sm *connsm);
|
||||
@@ -158,7 +181,7 @@ void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm,
|
||||
void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm);
|
||||
int ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd);
|
||||
int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len,
|
||||
@@ -205,6 +228,9 @@ bool ble_ll_conn_cth_flow_enable(bool enabled);
|
||||
void ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf);
|
||||
#endif
|
||||
|
||||
void ble_ll_conn_itvl_to_ticks(uint32_t itvl,
|
||||
uint32_t *itvl_ticks, uint8_t *itvl_usecs);
|
||||
|
||||
int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg);
|
||||
int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg);
|
||||
|
||||
@@ -213,7 +239,7 @@ int ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len,
|
||||
int ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *connsm);
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
int ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t cmdlen);
|
||||
int ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len);
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
|
||||
@@ -910,7 +910,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
|
||||
rc = ble_ll_hci_scan_set_enable(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_CREATE_CONN:
|
||||
rc = ble_ll_conn_create(cmdbuf, len);
|
||||
rc = ble_ll_conn_hci_create(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL:
|
||||
if (len == 0) {
|
||||
@@ -1113,7 +1113,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
|
||||
rc = ble_ll_hci_ext_scan_set_enable(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_EXT_CREATE_CONN:
|
||||
rc = ble_ll_ext_conn_create(cmdbuf, len);
|
||||
rc = ble_ll_conn_hci_ext_create(cmdbuf, len);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV)
|
||||
|
||||
@@ -57,7 +57,7 @@ ble_ll_is_controller_busy(void)
|
||||
#endif
|
||||
|
||||
return ble_ll_adv_enabled() || ble_ll_scan_enabled() ||
|
||||
g_ble_ll_conn_create_sm;
|
||||
g_ble_ll_conn_create_sm.connsm;
|
||||
}
|
||||
/**
|
||||
* Called to determine if a change is allowed to the resolving list at this
|
||||
|
||||
@@ -2411,65 +2411,37 @@ ble_ll_scan_can_chg_whitelist(void)
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
|
||||
struct ble_ll_conn_sm *connsm)
|
||||
{
|
||||
struct ble_ll_scan_sm *scansm;
|
||||
struct ble_ll_scan_phy *scanp;
|
||||
int rc;
|
||||
|
||||
scansm = &g_ble_ll_scan_sm;
|
||||
scansm->own_addr_type = hcc->own_addr_type;
|
||||
scansm->scan_filt_policy = hcc->filter_policy;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
scansm->ext_scanning = 0;
|
||||
#endif
|
||||
scansm->connsm = connsm;
|
||||
|
||||
scansm->scanp = &scansm->scan_phys[PHY_UNCODED];
|
||||
scansm->scanp_next = NULL;
|
||||
|
||||
scanp = scansm->scanp;
|
||||
scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(hcc->scan_itvl);
|
||||
scanp->timing.window = ble_ll_scan_time_hci_to_ticks(hcc->scan_window);
|
||||
scanp->scan_type = BLE_SCAN_TYPE_INITIATE;
|
||||
scanp->configured = 1;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
scanp = &scansm->scan_phys[PHY_CODED];
|
||||
scanp->configured = 0;
|
||||
#endif
|
||||
|
||||
rc = ble_ll_scan_sm_start(scansm);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
int
|
||||
ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
|
||||
struct ble_ll_conn_sm *connsm)
|
||||
ble_ll_scan_initiator_start(struct ble_ll_conn_sm *connsm, uint8_t ext,
|
||||
struct ble_ll_conn_create_scan *cc_scan)
|
||||
{
|
||||
struct ble_ll_scan_sm *scansm;
|
||||
struct ble_ll_scan_phy *scanp_uncoded;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
struct ble_ll_scan_phy *scanp_coded;
|
||||
struct hci_ext_conn_params *params;
|
||||
#endif
|
||||
uint8_t init_phy_mask;
|
||||
int rc;
|
||||
|
||||
scansm = &g_ble_ll_scan_sm;
|
||||
scansm->own_addr_type = hcc->own_addr_type;
|
||||
scansm->scan_filt_policy = hcc->filter_policy;
|
||||
scansm->own_addr_type = cc_scan->own_addr_type;
|
||||
scansm->scan_filt_policy = cc_scan->filter_policy;
|
||||
scansm->scanp = NULL;
|
||||
scansm->scanp_next = NULL;
|
||||
scansm->ext_scanning = 1;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
scansm->ext_scanning = ext;
|
||||
init_phy_mask = cc_scan->init_phy_mask;
|
||||
#else
|
||||
init_phy_mask = BLE_PHY_MASK_1M;
|
||||
#endif
|
||||
scansm->connsm = connsm;
|
||||
|
||||
params = &hcc->params[0];
|
||||
scanp_uncoded = &scansm->scan_phys[PHY_UNCODED];
|
||||
if (hcc->init_phy_mask & BLE_PHY_MASK_1M) {
|
||||
if (init_phy_mask & BLE_PHY_MASK_1M) {
|
||||
scanp_uncoded->configured = 1;
|
||||
scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl);
|
||||
scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
|
||||
scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(
|
||||
cc_scan->scan_params[PHY_UNCODED].itvl);
|
||||
scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(
|
||||
cc_scan->scan_params[PHY_UNCODED].window);
|
||||
scanp_uncoded->scan_type = BLE_SCAN_TYPE_INITIATE;
|
||||
scansm->scanp = scanp_uncoded;
|
||||
} else {
|
||||
@@ -2477,12 +2449,13 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
params = &hcc->params[2];
|
||||
scanp_coded = &scansm->scan_phys[PHY_CODED];
|
||||
if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) {
|
||||
if (init_phy_mask & BLE_PHY_MASK_CODED) {
|
||||
scanp_coded->configured = 1;
|
||||
scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl);
|
||||
scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
|
||||
scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks(
|
||||
cc_scan->scan_params[PHY_CODED].itvl);
|
||||
scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks(
|
||||
cc_scan->scan_params[PHY_CODED].window);
|
||||
scanp_coded->scan_type = BLE_SCAN_TYPE_INITIATE;
|
||||
if (scansm->scanp) {
|
||||
scansm->scanp_next = scanp_coded;
|
||||
@@ -2492,9 +2465,6 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
|
||||
} else {
|
||||
scanp_coded->configured = 0;
|
||||
}
|
||||
#else
|
||||
scanp_coded = NULL;
|
||||
#endif
|
||||
|
||||
/* if any of PHYs is configured for continuous scan we alter interval to
|
||||
* fit other PHY
|
||||
@@ -2509,12 +2479,15 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
|
||||
scanp_uncoded->timing.interval += scanp_coded->timing.window;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = ble_ll_scan_sm_start(scansm);
|
||||
if (rc == 0) {
|
||||
g_ble_ll_conn_create_sm.connsm = connsm;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Checks to see if the scanner is enabled.
|
||||
|
||||
Reference in New Issue
Block a user