nimble/ll: Use generic scanner for initiator

This moves initiator state handling to generic scanner and removes
existing spearate ll_initiating state from LL and associated code.
By using generic code we no longer need to worry about maintaining two
separate instances of similar code since e.g. privacy and filtering
is done via the same code path. Also we no longer need old aux scanner
code so all remaining parts of that code can be removed.

This saves ~3K of flash (optimized build with all features enabled)
and also some RAM (mostly depending on pool size used by old aux
scanner).
This commit is contained in:
Andrzej Kaczmarek
2021-11-02 12:54:47 +01:00
parent 4d95b1c3cc
commit 2443892ccc
12 changed files with 497 additions and 1686 deletions
@@ -216,7 +216,6 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats;
#define BLE_LL_STATE_STANDBY (0)
#define BLE_LL_STATE_ADV (1)
#define BLE_LL_STATE_SCANNING (2)
#define BLE_LL_STATE_INITIATING (3)
#define BLE_LL_STATE_CONNECTION (4)
#define BLE_LL_STATE_DTM (5)
#define BLE_LL_STATE_SYNC (6)
@@ -225,9 +225,6 @@ struct ble_ll_conn_sm
/* RSSI */
int8_t conn_rssi;
/* For privacy */
int8_t rpa_index;
/* Connection data length management */
uint8_t max_tx_octets;
uint8_t max_rx_octets;
@@ -328,6 +325,9 @@ struct ble_ll_conn_sm
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_PRIVACY)
uint8_t peer_addr_resolved;
#endif
/*
* XXX: TODO. Could save memory. Have single event at LL and put these
@@ -379,7 +379,6 @@ struct ble_ll_conn_sm
/* XXX: for now, just store them all */
struct ble_ll_conn_params conn_cp;
struct ble_ll_scan_sm *scansm;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
struct hci_ext_create_conn initial_params;
#endif
@@ -426,6 +425,34 @@ uint8_t ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency);
void ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event,
uint32_t *anchor, uint8_t *anchor_usecs);
struct ble_ll_scan_addr_data;
struct ble_ll_scan_pdu_data;
uint8_t ble_ll_conn_tx_connect_ind_pducb(uint8_t *dptr, void *pducb_arg,
uint8_t *hdr_byte);
void ble_ll_conn_prepare_connect_ind(struct ble_ll_conn_sm *connsm,
struct ble_ll_scan_pdu_data *pdu_data,
uint8_t adva_type, uint8_t *adva,
uint8_t inita_type, uint8_t *inita,
int rpa_index, uint8_t channel);
/* Send CONNECT_IND/AUX_CONNECT_REQ */
int ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu,
struct ble_ll_scan_addr_data *addrd,
uint8_t ext);
/* Cancel connection after AUX_CONNECT_REQ was sent */
void ble_ll_conn_send_connect_req_cancel(void);
/* Signal connection created via CONNECT_IND */
void ble_ll_conn_created_on_legacy(struct os_mbuf *rxpdu,
struct ble_ll_scan_addr_data *addrd,
uint8_t *targeta);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
/* Signal connection created via AUX_CONNECT_REQ */
void ble_ll_conn_created_on_aux(struct os_mbuf *rxpdu,
struct ble_ll_scan_addr_data *addrd,
uint8_t *targeta);
#endif
#ifdef __cplusplus
}
#endif
@@ -89,56 +89,6 @@ struct ble_ll_scan_phy
struct ble_ll_scan_timing timing;
};
#define BLE_LL_AUX_HAS_ADVA 0x01
#define BLE_LL_AUX_HAS_TARGETA 0x02
#define BLE_LL_AUX_HAS_ADI 0x04
#define BLE_LL_AUX_IS_MATCHED 0x08
#define BLE_LL_AUX_IS_TARGETA_RESOLVED 0x10
#define BLE_LL_AUX_FLAG_HCI_SENT_ANY 0x02
#define BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED 0x04
#define BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED 0x08
#define BLE_LL_AUX_FLAG_SCAN_COMPLETE 0x10
#define BLE_LL_AUX_FLAG_SCAN_ERROR 0x20
#define BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED 0x40
#define BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED 0x80
struct ble_ll_aux_data {
uint8_t flags;
/*
* Since aux_data can be accessed from ISR and LL, we have separate copies
* of flags to make sure that ISR does not modify flags while LL uses them.
* ISR updates 'flags_isr' and LL adds these to 'flags_ll' which it then
* uses for further processing allowing to update 'flags_isr' if another
* scan for given 'aux_data' is scheduled. Note that flags must not be unset
* while aux_data is valid.
*/
uint8_t flags_isr;
uint8_t flags_ll;
uint8_t ref_cnt;
uint8_t chan;
uint8_t aux_phy;
uint8_t aux_primary_phy;
uint8_t mode;
uint8_t scanning;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
int8_t rpa_index;
#endif
uint16_t adi;
uint32_t offset;
uint8_t offset_units;
uint8_t adva[6];
uint8_t adva_type;
uint8_t targeta[6];
uint8_t targeta_type;
uint16_t evt_type;
struct ble_ll_sched_item sch;
struct ble_hci_ev *evt;
struct ble_npl_event ev;
};
struct ble_ll_scan_pdu_data {
uint8_t hdr_byte;
/* ScanA for SCAN_REQ and InitA for CONNECT_IND */
@@ -197,11 +147,13 @@ struct ble_ll_scan_sm
#endif
uint8_t restart_timer_needed;
struct ble_ll_aux_data *cur_aux_data;
struct ble_ll_scan_phy *scanp;
struct ble_ll_scan_phy *scanp_next;
struct ble_ll_scan_phy scan_phys[BLE_LL_SCAN_PHY_NUMBER];
/* Connection sm for initiator scan */
struct ble_ll_conn_sm *connsm;
};
/* Scan types */
@@ -244,13 +196,11 @@ int ble_ll_scan_can_chg_whitelist(void);
/* Boolean function returning true if scanning enabled */
int ble_ll_scan_enabled(void);
/* Boolean function returns true if whitelist is enabled for scanning */
int ble_ll_scan_whitelist_enabled(void);
/* Initialize the scanner when we start initiating */
struct hci_create_conn;
int ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
struct ble_ll_scan_sm **sm);
int
ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
struct ble_ll_conn_sm *connsm);
/* Returns storage for PDU data (for SCAN_REQ or CONNECT_IND) */
struct ble_ll_scan_pdu_data *ble_ll_scan_get_pdu_data(void);
@@ -276,24 +226,14 @@ void ble_ll_scan_wfr_timer_exp(void);
/* Called when scan could be interrupted */
void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm);
int ble_ll_scan_adv_decode_addr(uint8_t pdu_type, uint8_t *rxbuf,
struct ble_mbuf_hdr *ble_hdr,
uint8_t **addr, uint8_t *addr_type,
uint8_t **inita, uint8_t *init_addr_type,
int *ext_mode);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
int ble_ll_scan_update_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf,
bool *adva_present);
/* 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_scan_sm **sm);
int
ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
struct ble_ll_conn_sm *connsm);
/* Called to parse extended advertising*/
struct ble_ll_aux_data *ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_scan);
void ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_scan);
void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data);
#endif
@@ -316,8 +256,10 @@ int ble_ll_scan_have_rxd_scan_rsp(uint8_t *addr, uint8_t txadd, uint8_t ext_adv,
void ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd, uint8_t ext_adv,
uint16_t adi);
int ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy,
struct ble_ll_scan_addr_data *addrd, uint8_t *scan_ok);
int
ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy,
struct ble_ll_scan_addr_data *addrd, uint8_t *scan_ok);
int ble_ll_scan_rx_check_init(struct ble_ll_scan_addr_data *addrd);
#ifdef __cplusplus
}
@@ -67,7 +67,6 @@ extern uint8_t g_ble_ll_sched_offset_ticks;
#define BLE_LL_SCHED_TYPE_ADV (1)
#define BLE_LL_SCHED_TYPE_SCAN (2)
#define BLE_LL_SCHED_TYPE_CONN (3)
#define BLE_LL_SCHED_TYPE_AUX_SCAN (4)
#define BLE_LL_SCHED_TYPE_DTM (5)
#define BLE_LL_SCHED_TYPE_PERIODIC (6)
#define BLE_LL_SCHED_TYPE_SYNC (7)
-12
View File
@@ -677,9 +677,6 @@ ble_ll_wfr_timer_exp(void *arg)
case BLE_LL_STATE_SCANNING:
ble_ll_scan_wfr_timer_exp();
break;
case BLE_LL_STATE_INITIATING:
ble_ll_conn_init_wfr_timer_exp();
break;
#if MYNEWT_VAL(BLE_LL_DTM)
case BLE_LL_STATE_DTM:
ble_ll_dtm_wfr_timer_exp();
@@ -842,9 +839,6 @@ ble_ll_rx_pkt_in(void)
case BLE_LL_STATE_SCANNING:
ble_ll_scan_rx_pkt_in(pdu_type, m, ble_hdr);
break;
case BLE_LL_STATE_INITIATING:
ble_ll_init_rx_pkt_in(pdu_type, rxbuf, ble_hdr);
break;
#if MYNEWT_VAL(BLE_LL_DTM)
case BLE_LL_STATE_DTM:
ble_ll_dtm_rx_pkt_in(m, ble_hdr);
@@ -980,9 +974,6 @@ ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr)
case BLE_LL_STATE_ADV:
rc = ble_ll_adv_rx_isr_start(pdu_type);
break;
case BLE_LL_STATE_INITIATING:
rc = ble_ll_init_rx_isr_start(pdu_type, rxhdr);
break;
case BLE_LL_STATE_SCANNING:
rc = ble_ll_scan_rx_isr_start(pdu_type, &rxhdr->rxinfo.flags);
break;
@@ -1122,9 +1113,6 @@ ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
}
rc = ble_ll_scan_rx_isr_end(rxpdu, crcok);
break;
case BLE_LL_STATE_INITIATING:
rc = ble_ll_init_rx_isr_end(rxbuf, crcok, rxhdr);
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
case BLE_LL_STATE_SCAN_AUX:
if (!badpkt) {
+115 -747
View File
@@ -674,64 +674,6 @@ ble_ll_conn_wfr_timer_exp(void)
STATS_INC(ble_ll_conn_stats, wfr_expirations);
}
void
ble_ll_conn_reset_pending_aux_conn_rsp(void)
{
#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
return;
#endif
struct ble_ll_conn_sm *connsm;
connsm = g_ble_ll_conn_create_sm;
if (!connsm) {
return;
}
if (CONN_F_AUX_CONN_REQ(connsm)) {
STATS_INC(ble_ll_stats, aux_conn_rsp_err);
CONN_F_CONN_REQ_TXD(connsm) = 0;
CONN_F_AUX_CONN_REQ(connsm) = 0;
ble_ll_sched_rmv_elem(&connsm->conn_sch);
return;
}
return;
}
bool
ble_ll_conn_init_pending_aux_conn_rsp(void)
{
#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
return false;
#endif
struct ble_ll_conn_sm *connsm;
connsm = g_ble_ll_conn_create_sm;
if (!connsm) {
return false;
}
return CONN_F_AUX_CONN_REQ(connsm);
}
void
ble_ll_conn_init_wfr_timer_exp(void)
{
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
struct ble_ll_conn_sm *connsm;
connsm = g_ble_ll_conn_create_sm;
if (!connsm) {
return;
}
ble_ll_conn_reset_pending_aux_conn_rsp();
connsm->inita_identity_used = 0;
ble_ll_scan_interrupted(connsm->scansm);
#endif
}
/**
* Callback for slave when it transmits a data pdu and the connection event
* ends after the transmission.
@@ -1764,6 +1706,13 @@ 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;
@@ -1833,7 +1782,6 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
connsm->sub_vers_nr = 0;
connsm->reject_reason = BLE_ERR_SUCCESS;
connsm->conn_rssi = BLE_LL_CONN_UNKNOWN_RSSI;
connsm->rpa_index = -1;
connsm->inita_identity_used = 0;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
@@ -2667,8 +2615,8 @@ ble_ll_conn_event_end(struct ble_npl_event *ev)
* @param txoffset The tx window offset for this connection
*/
static void
ble_ll_conn_connect_ind_prepare(struct ble_ll_conn_sm *connsm,
void
ble_ll_conn_prepare_connect_ind(struct ble_ll_conn_sm *connsm,
struct ble_ll_scan_pdu_data *pdu_data,
uint8_t adva_type, uint8_t *adva,
uint8_t inita_type, uint8_t *inita,
@@ -2753,110 +2701,8 @@ ble_ll_conn_connect_ind_prepare(struct ble_ll_conn_sm *connsm,
pdu_data->hdr_byte = hdr;
}
/* Returns true if the address matches the connection peer address having in
* mind privacy mode
*/
static int
ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva, int index)
{
int rc;
uint8_t *peer_addr = NULL;
struct ble_ll_conn_sm *connsm;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
struct ble_ll_resolv_entry *rl;
#endif
/* XXX: Deal with different types of random addresses here! */
connsm = g_ble_ll_conn_create_sm;
if (!connsm) {
return 0;
}
switch (connsm->peer_addr_type) {
/* Fall-through intentional */
case BLE_HCI_CONN_PEER_ADDR_PUBLIC:
case BLE_HCI_CONN_PEER_ADDR_RANDOM:
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
if (ble_ll_addr_is_id(adva, addr_type)) {
/* Peer uses its identity address. Let's verify privacy mode.
*
* Note: Core Spec 5.0 Vol 6, Part B
* If the Host has added the peer device to the resolving list
* with an all-zero peer IRK, the Controller shall only accept
* the peer's identity address.
*/
if (ble_ll_resolv_enabled()) {
rl = ble_ll_resolv_list_find(adva, addr_type);
if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) &&
rl->rl_has_peer) {
return 0;
}
}
}
/* Check if peer uses RPA. If so and it match, use it as controller
* supports privacy mode
*/
if ((index >= 0) &&
(g_ble_ll_resolv_list[index].rl_addr_type == connsm->peer_addr_type)) {
peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr;
}
#endif
/*
* If we are here it means we don't know the device, lets
* check if type is what we are looking for and later
* if address matches
*/
if ((connsm->peer_addr_type == addr_type) && !peer_addr) {
peer_addr = adva;
}
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
case BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT:
if ((index < 0) ||
(g_ble_ll_resolv_list[index].rl_addr_type != 0)) {
return 0;
}
peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr;
break;
case BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT:
if ((index < 0) ||
(g_ble_ll_resolv_list[index].rl_addr_type != 1)) {
return 0;
}
peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr;
break;
#endif
default:
peer_addr = NULL;
break;
}
rc = 0;
if (peer_addr) {
if (!memcmp(peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN)) {
rc = 1;
}
}
return rc;
}
static void
ble_ll_conn_connect_ind_txend_to_standby(void *arg)
{
ble_ll_state_set(BLE_LL_STATE_STANDBY);
}
static void
ble_ll_conn_connect_ind_txend_to_init(void *arg)
{
ble_ll_state_set(BLE_LL_STATE_INITIATING);
}
static uint8_t
ble_ll_conn_connect_ind_tx_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
uint8_t
ble_ll_conn_tx_connect_ind_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
{
struct ble_ll_conn_sm *connsm;
struct ble_ll_scan_pdu_data *pdu_data;
@@ -2890,30 +2736,6 @@ ble_ll_conn_connect_ind_tx_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_by
return 34;
}
/**
* Send a connection requestion to an advertiser
*
* Context: Interrupt
*
* @param addr_type Address type of advertiser
* @param adva Address of advertiser
*/
int
ble_ll_conn_connect_ind_send(struct ble_ll_conn_sm *connsm, uint8_t end_trans)
{
int rc;
if (end_trans == BLE_PHY_TRANSITION_NONE) {
ble_phy_set_txend_cb(ble_ll_conn_connect_ind_txend_to_standby, NULL);
} else {
ble_phy_set_txend_cb(ble_ll_conn_connect_ind_txend_to_init, NULL);
}
rc = ble_phy_tx(ble_ll_conn_connect_ind_tx_pducb, connsm, end_trans);
return rc;
}
/**
* Called when a schedule item overlaps the currently running connection
* event. This generally should not happen, but if it does we stop the
@@ -2933,596 +2755,142 @@ ble_ll_conn_event_halt(void)
}
}
/**
* Process a received PDU while in the initiating state.
*
* Context: Link Layer task.
*
* @param pdu_type
* @param rxbuf
* @param ble_hdr
*/
void
ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf,
struct ble_mbuf_hdr *ble_hdr)
{
uint8_t addr_type;
uint8_t *addr;
uint8_t *adv_addr;
uint8_t *inita;
uint8_t inita_type;
struct ble_ll_conn_sm *connsm;
int ext_adv_mode = -1;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
struct ble_ll_aux_data *aux_data = NULL;
if (ble_hdr->rxinfo.user_data) {
/* aux_data just a local helper, no need to ref
* as ble_hdr->rxinfo.user_data is unref in the end of this function
*/
aux_data = ble_hdr->rxinfo.user_data;
}
#endif
/* Get the connection state machine we are trying to create */
connsm = g_ble_ll_conn_create_sm;
if (!connsm) {
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
if (aux_data) {
ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data);
ble_hdr->rxinfo.user_data = NULL;
}
#endif
return;
}
if (!BLE_MBUF_HDR_CRC_OK(ble_hdr)) {
goto scan_continue;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
if (BLE_MBUF_HDR_AUX_INVALID(ble_hdr)) {
goto scan_continue;
}
if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) {
if (BLE_MBUF_HDR_WAIT_AUX(ble_hdr)) {
/* Just continue scanning. We are waiting for AUX */
if (!ble_ll_sched_aux_scan(ble_hdr, connsm->scansm, aux_data)) {
/* ref for aux ptr in the scheduler */
ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data);
ble_hdr->rxinfo.user_data = NULL;
ble_ll_scan_chk_resume();
return;
}
goto scan_continue;
}
}
if (CONN_F_AUX_CONN_REQ(connsm)) {
if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) {
/* Wait for connection response, in this point of time aux is NULL */
BLE_LL_ASSERT(ble_hdr->rxinfo.user_data == NULL);
return;
}
}
#endif
/* If we have sent a connect request, we need to enter CONNECTION state */
if (connsm && CONN_F_CONN_REQ_TXD(connsm)) {
/* Set address of advertiser to which we are connecting. */
if (ble_ll_scan_adv_decode_addr(pdu_type, rxbuf, ble_hdr,
&adv_addr, &addr_type,
&inita, &inita_type, &ext_adv_mode)) {
/* Something got wrong, keep trying to connect */
goto scan_continue;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
/*
* Did we resolve this address? If so, set correct peer address
* and peer address type.
*/
if (connsm->rpa_index >= 0) {
addr_type = g_ble_ll_resolv_list[connsm->rpa_index].rl_addr_type + 2;
addr = g_ble_ll_resolv_list[connsm->rpa_index].rl_identity_addr;
} else {
addr = adv_addr;
}
#else
addr = adv_addr;
#endif
if (connsm->rpa_index >= 0) {
connsm->peer_addr_type = addr_type;
memcpy(connsm->peer_addr, addr, BLE_DEV_ADDR_LEN);
ble_ll_scan_set_peer_rpa(adv_addr);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
/* Update resolving list with current peer RPA */
ble_ll_resolv_set_peer_rpa(connsm->rpa_index, rxbuf + BLE_LL_PDU_HDR_LEN);
if (ble_ll_is_rpa(inita, inita_type)) {
ble_ll_resolv_set_local_rpa(connsm->rpa_index, inita);
}
#endif
} else if (ble_ll_scan_whitelist_enabled()) {
/* if WL is used we need to store peer addr also if it was not
* resolved
*/
connsm->peer_addr_type = addr_type;
memcpy(connsm->peer_addr, addr, BLE_DEV_ADDR_LEN);
}
/* Connection has been created. Stop scanning */
g_ble_ll_conn_create_sm = NULL;
ble_ll_scan_sm_stop(0);
/* For AUX Connect CSA2 is mandatory. Otherwise we need to check bit
* mask
*/
if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) {
ble_ll_conn_set_csa(connsm, 1);
} else {
ble_ll_conn_set_csa(connsm, rxbuf[0] & BLE_ADV_PDU_HDR_CHSEL_MASK);
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
/* Lets take last used phy */
ble_ll_conn_init_phy(connsm, ble_hdr->rxinfo.phy);
#endif
if (aux_data) {
ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data);
ble_hdr->rxinfo.user_data = NULL;
}
#endif
ble_ll_conn_created(connsm, NULL);
return;
}
scan_continue:
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
/* Drop last reference and keep continue to connect */
if (aux_data) {
ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data);
ble_hdr->rxinfo.user_data = NULL;
}
#endif
ble_ll_scan_chk_resume();
}
/**
* Called when a receive PDU has started and we are in the initiating state.
*
* Context: Interrupt
*
* @param pdu_type
* @param ble_hdr
*
* @return int
* 0: we will not attempt to reply to this frame
* 1: we may send a response to this frame.
*/
int
ble_ll_init_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *ble_hdr)
ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu,
struct ble_ll_scan_addr_data *addrd,
uint8_t ext)
{
struct ble_ll_conn_sm *connsm;
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;
if (!connsm) {
return 0;
}
if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) ||
(pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND ||
pdu_type == BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP)) {
return 1;
}
rxhdr = BLE_MBUF_HDR_PTR(rxpdu);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND &&
connsm->scansm->ext_scanning) {
if (connsm->scansm->cur_aux_data) {
STATS_INC(ble_ll_stats, aux_received);
}
ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_EXT_ADV;
return 1;
if (ext) {
#if BLE_LL_BT5_PHY_SUPPORTED
phy = rxhdr->rxinfo.phy;
#else
phy = BLE_PHY_1M;
#endif
ecp = &connsm->initial_params.params[phy - 1];
ble_ll_conn_ext_set_params(connsm, ecp, phy);
}
#endif
if (ble_ll_sched_master_new(connsm, rxhdr, 0)) {
return -1;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
rpa_index = addrd->rpa_index;
#else
rpa_index = -1;
#endif
ble_ll_conn_prepare_connect_ind(connsm, ble_ll_scan_get_pdu_data(),
addrd->adva_type, addrd->adva,
addrd->targeta_type, addrd->targeta,
rpa_index, rxhdr->rxinfo.channel);
ble_phy_set_txend_cb(NULL, NULL);
rc = ble_phy_tx(ble_ll_conn_tx_connect_ind_pducb, connsm,
ext ? BLE_PHY_TRANSITION_TX_RX : BLE_PHY_TRANSITION_NONE);
if (rc) {
ble_ll_conn_send_connect_req_cancel();
return -1;
}
return 0;
}
/**
* Called when a receive PDU has ended and we are in the initiating state.
*
* Context: Interrupt
*
* @param rxpdu
* @param crcok
* @param ble_hdr
*
* @return int
* < 0: Disable the phy after reception.
* == 0: Success. Do not disable the PHY.
* > 0: Do not disable PHY as that has already been done.
*/
int
ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
struct ble_mbuf_hdr *ble_hdr)
void
ble_ll_conn_send_connect_req_cancel(void)
{
int rc;
int resolved;
int chk_wl;
int index;
uint8_t pdu_type;
uint8_t adv_addr_type;
uint8_t peer_addr_type;
uint8_t *adv_addr = NULL;
uint8_t *peer;
uint8_t *init_addr = NULL;
uint8_t init_addr_type;
uint8_t pyld_len;
uint8_t inita_is_rpa;
uint8_t conn_req_end_trans;
struct os_mbuf *rxpdu;
struct ble_ll_conn_sm *connsm;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
struct ble_ll_resolv_entry *rl;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
struct hci_ext_conn_params *hcp;
struct ble_ll_scan_sm *scansm;
uint8_t phy;
#endif
int ext_adv_mode = -1;
/* Get connection state machine to use if connection to be established */
connsm = g_ble_ll_conn_create_sm;
/* This could happen if connection init was cancelled while isr end was
* already pending
*/
if (!connsm) {
ble_ll_state_set(BLE_LL_STATE_STANDBY);
return -1;
}
rc = -1;
pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
pyld_len = rxbuf[1];
ble_ll_sched_rmv_elem(&connsm->conn_sch);
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
scansm = connsm->scansm;
if (scansm->cur_aux_data) {
ble_hdr->rxinfo.user_data = scansm->cur_aux_data;
scansm->cur_aux_data = NULL;
}
#endif
static void
ble_ll_conn_master_start(uint8_t phy, uint8_t csa,
struct ble_ll_scan_addr_data *addrd, uint8_t *targeta)
{
struct ble_ll_conn_sm *connsm;
if (!crcok) {
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
/* Invalid packet - make sure we do not wait for AUX_CONNECT_RSP */
ble_ll_conn_reset_pending_aux_conn_rsp();
#endif
connsm = g_ble_ll_conn_create_sm;
g_ble_ll_conn_create_sm = NULL;
/* Ignore this packet */
goto init_rx_isr_exit;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
/* If we sent AUX_CONNECT_REQ, we only expect AUX_CONNECT_RSP here */
if (CONN_F_AUX_CONN_REQ(connsm)) {
if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) {
STATS_INC(ble_ll_stats, aux_conn_rsp_err);
CONN_F_CONN_REQ_TXD(connsm) = 0;
CONN_F_AUX_CONN_REQ(connsm) = 0;
ble_ll_sched_rmv_elem(&connsm->conn_sch);
}
goto init_rx_isr_exit;
}
#endif
inita_is_rpa = 0;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) {
if (!scansm->ext_scanning) {
goto init_rx_isr_exit;
}
rc = ble_ll_scan_update_aux_data(ble_hdr, rxbuf, NULL);
if (rc < 0) {
/* No memory or broken packet */
ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID;
goto init_rx_isr_exit;
}
}
#endif
/* Lets get addresses from advertising report*/
if (ble_ll_scan_adv_decode_addr(pdu_type, rxbuf, ble_hdr,
&adv_addr, &adv_addr_type,
&init_addr, &init_addr_type,
&ext_adv_mode)) {
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID;
#endif
goto init_rx_isr_exit;
}
switch (pdu_type) {
case BLE_ADV_PDU_TYPE_ADV_IND:
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
case BLE_ADV_PDU_TYPE_ADV_EXT_IND:
rc = -1;
/* If this is not connectable adv mode, lets skip it */
if (!(ext_adv_mode & BLE_LL_EXT_ADV_MODE_CONN)) {
goto init_rx_isr_exit;
}
if (!adv_addr) {
ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_PTR_WAIT;
goto init_rx_isr_exit;
}
if (!init_addr) {
break;
}
/* if there is direct address lets fall down and check it.*/
// no break
#endif
case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND:
inita_is_rpa = (uint8_t)ble_ll_is_rpa(init_addr, init_addr_type);
if (!inita_is_rpa) {
/* Resolving will be done later. Check if identity InitA matches */
if (!ble_ll_is_our_devaddr(init_addr, init_addr_type)) {
goto init_rx_isr_exit;
}
}
#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
else {
/* If privacy is off - reject RPA InitA*/
goto init_rx_isr_exit;
}
#endif
break;
default:
goto init_rx_isr_exit;
}
/* Should we send a connect request? */
index = -1;
peer = adv_addr;
peer_addr_type = adv_addr_type;
resolved = 0;
chk_wl = ble_ll_scan_whitelist_enabled();
connsm->peer_addr_type = addrd->adv_addr_type;
memcpy(connsm->peer_addr, addrd->adv_addr, 6);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
if (ble_ll_is_rpa(adv_addr, adv_addr_type) && ble_ll_resolv_enabled()) {
index = ble_hw_resolv_list_match();
if (index >= 0) {
rl = &g_ble_ll_resolv_list[index];
ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED;
connsm->rpa_index = index;
peer = rl->rl_identity_addr;
peer_addr_type = rl->rl_addr_type;
resolved = 1;
/* Assure privacy */
if ((rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && init_addr &&
!inita_is_rpa && rl->rl_has_local) {
goto init_rx_isr_exit;
}
/*
* If the InitA is a RPA, we must see if it resolves based on the
* identity address of the resolved ADVA.
*/
if (init_addr && inita_is_rpa) {
if (!ble_ll_resolv_rpa(init_addr,
g_ble_ll_resolv_list[index].rl_local_irk)) {
goto init_rx_isr_exit;
}
/* Core Specification Vol 6, Part B, Section 6.4:
* "The Link Layer should not set the InitA field to the same
* value as the TargetA field in the received advertising PDU."
*
* We update the received PDU directly here, so ble_ll_init_rx_pkt_in
* can process it as is.
*/
memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
}
} else {
if (chk_wl) {
goto init_rx_isr_exit;
}
/* Could not resolved InitA */
if (init_addr && inita_is_rpa) {
goto init_rx_isr_exit;
}
}
} else if (init_addr) {
/* If resolving is off and InitA is RPA we reject advertising */
if (inita_is_rpa && !ble_ll_resolv_enabled()) {
goto init_rx_isr_exit;
}
/* Let's see if we have IRK with that peer.*/
rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type);
/* Lets make sure privacy mode is correct together with InitA in case it
* is identity address
*/
if (rl && !inita_is_rpa &&
(rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) &&
rl->rl_has_local) {
goto init_rx_isr_exit;
}
/*
* If the InitA is a RPA, we must see if it resolves based on the
* identity address of the resolved ADVA.
*/
if (inita_is_rpa) {
if (!rl || !ble_ll_resolv_rpa(init_addr, rl->rl_local_irk)) {
goto init_rx_isr_exit;
}
/* Core Specification Vol 6, Part B, Section 6.4:
* "The Link Layer should not set the InitA field to the same
* value as the TargetA field in the received advertising PDU."
*
* We update the received PDU directly here, so ble_ll_init_rx_pkt_in
* can process it as is.
*/
memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
}
} else if (!ble_ll_is_rpa(adv_addr, adv_addr_type)) {
/* undirected with ID address, assure privacy if on RL */
rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type);
if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) &&
rl->rl_has_peer) {
goto init_rx_isr_exit;
}
}
#endif
/* Check filter policy */
if (chk_wl) {
if (!ble_ll_whitelist_match(peer, peer_addr_type, resolved)) {
goto init_rx_isr_exit;
}
if (addrd->adva_resolved) {
BLE_LL_ASSERT(addrd->rpa_index >= 0);
connsm->peer_addr_resolved = 1;
ble_ll_resolv_set_peer_rpa(addrd->rpa_index, addrd->adva);
ble_ll_scan_set_peer_rpa(addrd->adva);
} else {
/* Must match the connection address */
if (!ble_ll_conn_is_peer_adv(adv_addr_type, adv_addr, index)) {
goto init_rx_isr_exit;
}
}
ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH;
/* For CONNECT_IND we don't go into RX state */
conn_req_end_trans = BLE_PHY_TRANSITION_NONE;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
/* Check if we should send AUX_CONNECT_REQ and wait for AUX_CONNECT_RSP */
if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) {
conn_req_end_trans = BLE_PHY_TRANSITION_TX_RX;
connsm->peer_addr_resolved = 0;
}
if (connsm->scansm->ext_scanning) {
phy = ble_hdr->rxinfo.phy;
hcp = &connsm->initial_params.params[phy - 1];
connsm->slave_latency = hcp->conn_latency;
connsm->supervision_tmo = hcp->supervision_timeout;
connsm->conn_itvl = hcp->conn_itvl;
connsm->conn_itvl_ticks = hcp->conn_itvl_ticks;
connsm->conn_itvl_usecs = hcp->conn_itvl_usecs;
if (addrd->targeta_resolved) {
BLE_LL_ASSERT(addrd->rpa_index >= 0);
BLE_LL_ASSERT(targeta);
ble_ll_resolv_set_local_rpa(addrd->rpa_index, targeta);
}
#endif
/* Schedule new connection */
if (ble_ll_sched_master_new(connsm, ble_hdr, pyld_len)) {
STATS_INC(ble_ll_conn_stats, cant_set_sched);
goto init_rx_isr_exit;
}
/* Prepare data for connect request */
ble_ll_conn_connect_ind_prepare(connsm,
ble_ll_scan_get_pdu_data(),
adv_addr_type, adv_addr,
init_addr_type, init_addr,
index, ble_hdr->rxinfo.channel);
/* Setup to transmit the connect request */
rc = ble_ll_conn_connect_ind_send(connsm, conn_req_end_trans);
if (rc) {
ble_ll_sched_rmv_elem(&connsm->conn_sch);
goto init_rx_isr_exit;
}
if (init_addr && !inita_is_rpa) {
connsm->inita_identity_used = 1;
}
CONN_F_CONN_REQ_TXD(connsm) = 1;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) {
/* Lets wait for AUX_CONNECT_RSP */
CONN_F_AUX_CONN_REQ(connsm) = 1;
/* Keep aux data until we get scan response */
scansm->cur_aux_data = ble_hdr->rxinfo.user_data;
ble_hdr->rxinfo.user_data = NULL;
STATS_INC(ble_ll_stats, aux_conn_req_tx);
}
if (connsm->scansm->ext_scanning) {
phy = ble_hdr->rxinfo.phy;
/* Update connection state machine with appropriate parameters for
* certain PHY
*/
ble_ll_conn_ext_set_params(connsm,
&connsm->initial_params.params[phy - 1],
phy);
}
ble_ll_conn_set_csa(connsm, csa);
#if BLE_LL_BT5_PHY_SUPPORTED
ble_ll_conn_init_phy(connsm, phy);
#endif
STATS_INC(ble_ll_conn_stats, conn_req_txd);
init_rx_isr_exit:
/*
* We have to restart receive if we cant hand up pdu. We return 0 so that
* the phy does not get disabled.
*/
rxpdu = ble_ll_rxpdu_alloc(pyld_len + BLE_LL_PDU_HDR_LEN);
if (rxpdu == NULL) {
/*
* XXX: possible allocate the PDU when we start initiating?
* I cannot say I like this solution, but if we cannot allocate a PDU
* to hand up to the LL, we need to remove the connection we just
* scheduled since the connection state machine will not get processed
* by link layer properly. For now, just remove it from the scheduler
*/
if (CONN_F_CONN_REQ_TXD(connsm) == 1) {
CONN_F_CONN_REQ_TXD(connsm) = 0;
CONN_F_AUX_CONN_REQ(connsm) = 0;
ble_ll_sched_rmv_elem(&connsm->conn_sch);
}
ble_phy_restart_rx();
rc = 0;
} else {
ble_phy_rxpdu_copy(rxbuf, rxpdu);
ble_ll_rx_pdu_in(rxpdu);
}
if (rc) {
ble_ll_state_set(BLE_LL_STATE_STANDBY);
}
return rc;
ble_ll_conn_created(connsm, NULL);
}
void
ble_ll_conn_created_on_legacy(struct os_mbuf *rxpdu,
struct ble_ll_scan_addr_data *addrd,
uint8_t *targeta)
{
uint8_t *rxbuf;
uint8_t csa;
rxbuf = rxpdu->om_data;
csa = rxbuf[0] & BLE_ADV_PDU_HDR_CHSEL_MASK;
ble_ll_conn_master_start(BLE_PHY_1M, csa, addrd, targeta);
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
void
ble_ll_conn_created_on_aux(struct os_mbuf *rxpdu,
struct ble_ll_scan_addr_data *addrd,
uint8_t *targeta)
{
#if BLE_LL_BT5_PHY_SUPPORTED
struct ble_mbuf_hdr *rxhdr;
#endif
uint8_t phy;
#if BLE_LL_BT5_PHY_SUPPORTED
rxhdr = BLE_MBUF_HDR_PTR(rxpdu);
phy = rxhdr->rxinfo.phy;
#else
phy = BLE_PHY_1M;
#endif
ble_ll_conn_master_start(phy, 1, addrd, targeta);
}
#endif /* BLE_LL_CFG_FEAT_LL_EXT_ADV */
/**
* Function called when a timeout has occurred for a connection. There are
* two types of timeouts: a connection supervision timeout and control
+6 -13
View File
@@ -179,13 +179,12 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
memcpy(enh_ev->local_rpa, rpa, BLE_DEV_ADDR_LEN);
}
/* We need to adjust peer type if device connected using RPA
* and was resolved since RPA needs to be added to HCI event.
*/
if (connsm->peer_addr_type < BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT
&& (connsm->rpa_index > -1)) {
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
/* Adjust address type if peer address was resolved */
if (connsm->peer_addr_resolved) {
enh_ev->peer_addr_type += 2;
}
#endif
if (enh_ev->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
@@ -220,10 +219,6 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
ev->conn_handle = htole16(connsm->conn_handle);
ev->role = connsm->conn_role - 1;
ev->peer_addr_type = connsm->peer_addr_type;
if (ev->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
ev->peer_addr_type -= 2;
}
memcpy(ev->peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN);
ev->conn_itvl = htole16(connsm->conn_itvl);
ev->conn_latency = htole16(connsm->slave_latency);
@@ -520,7 +515,7 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len)
/* CSA will be selected when advertising is received */
/* Start scanning */
rc = ble_ll_scan_initiator_start(&hcc, &connsm->scansm);
rc = ble_ll_scan_initiator_start(&hcc, connsm);
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);
@@ -777,10 +772,8 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len)
ble_ll_conn_ext_master_init(connsm, &hcc);
ble_ll_conn_sm_new(connsm);
/* CSA will be selected when advertising is received */
/* Start scanning */
rc = ble_ll_scan_ext_initiator_start(&hcc, &connsm->scansm);
rc = ble_ll_scan_ext_initiator_start(&hcc, connsm);
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);
-8
View File
@@ -148,18 +148,10 @@ void ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t len);
int ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa);
int ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr);
void ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr);
void ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf,
struct ble_mbuf_hdr *ble_hdr);
int ble_ll_init_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *ble_hdr);
int ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
struct ble_mbuf_hdr *ble_hdr);
void ble_ll_conn_wfr_timer_exp(void);
void ble_ll_conn_init_wfr_timer_exp(void);
int ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2);
uint32_t ble_ll_conn_get_ce_end_time(void);
void ble_ll_conn_event_halt(void);
void ble_ll_conn_reset_pending_aux_conn_rsp(void);
bool ble_ll_conn_init_pending_aux_conn_rsp(void);
/* HCI */
void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm,
uint8_t reason);
File diff suppressed because it is too large Load Diff
+200 -10
View File
@@ -50,6 +50,8 @@
#define BLE_LL_SCAN_AUX_F_HAS_ADI 0x0080
#define BLE_LL_SCAN_AUX_F_RESOLVED_ADVA 0x0100
#define BLE_LL_SCAN_AUX_F_RESOLVED_TARGETA 0x0200
#define BLE_LL_SCAN_AUX_F_CONNECTABLE 0x0400
#define BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP 0x0800
#define BLE_LL_SCAN_AUX_H_SENT_ANY 0x01
#define BLE_LL_SCAN_AUX_H_DONE 0x02
@@ -668,6 +670,10 @@ ble_ll_scan_aux_break_ev(struct ble_npl_event *ev)
void
ble_ll_scan_aux_break(struct ble_ll_scan_aux_data *aux)
{
if (aux->flags & BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP) {
ble_ll_conn_send_connect_req_cancel();
}
ble_npl_event_init(&aux->break_ev, ble_ll_scan_aux_break_ev, aux);
ble_ll_event_send(&aux->break_ev);
}
@@ -751,18 +757,29 @@ ble_ll_scan_aux_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr)
{
struct ble_ll_scan_aux_data *aux;
if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) {
return -1;
}
BLE_LL_ASSERT(aux_data_current);
aux = aux_data_current;
if (aux->flags & BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP) {
if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) {
aux_data_current = NULL;
ble_ll_scan_aux_break(aux);
return -1;
}
return 0;
}
if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) {
aux_data_current = NULL;
ble_ll_scan_aux_break(aux);
return -1;
}
/*
* Prepare TX transition when doing active scanning and receiving 1st PDU
* since we may want to send AUX_SCAN_REQ.
*/
if ((aux->scan_type == BLE_SCAN_TYPE_ACTIVE) &&
if ((aux->scan_type != BLE_SCAN_TYPE_PASSIVE) &&
!(aux->flags & BLE_LL_SCAN_AUX_F_AUX_ADV)) {
return 1;
}
@@ -1012,6 +1029,10 @@ ble_ll_scan_aux_rx_isr_end_on_ext(struct ble_ll_scan_sm *scansm,
return -1;
}
/* Don't care about initiator here, there are no AdvA and TargetA
* in connectable ADV_EXT_IND so no filtering to do.
*/
if (!aux_ptr) {
/* We do not allocate aux_data for ADV_EXT_IND without AuxPtr so
* need to pass match data in rxinfo.
@@ -1046,6 +1067,10 @@ ble_ll_scan_aux_rx_isr_end_on_ext(struct ble_ll_scan_sm *scansm,
aux->adi = adi;
aux->flags |= BLE_LL_SCAN_AUX_F_HAS_ADI;
if (aux->scan_type == BLE_SCAN_TYPE_INITIATE) {
aux->flags |= BLE_LL_SCAN_AUX_F_CONNECTABLE;
}
if (do_match) {
aux->flags |= BLE_LL_SCAN_AUX_F_MATCHED;
ble_ll_scan_aux_update_aux_data_from_addrd(&addrd, aux);
@@ -1187,6 +1212,7 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
struct ble_mbuf_hdr_rxinfo *rxinfo;
struct ble_ll_scan_aux_data *aux;
struct ble_mbuf_hdr *rxhdr;
uint8_t scan_filt_policy;
uint8_t scan_ok;
uint8_t adv_mode;
uint8_t *rxbuf;
@@ -1212,6 +1238,12 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
rxbuf = rxpdu->om_data;
if (aux->flags & BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP) {
aux->flags &= ~BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP;
rxinfo->flags |= BLE_MBUF_HDR_F_CONNECT_RSP_RXD;
goto done;
}
if (aux->flags & BLE_LL_SCAN_AUX_F_W4_SCAN_RSP) {
aux->flags &= ~BLE_LL_SCAN_AUX_F_W4_SCAN_RSP;
aux->flags |= BLE_LL_SCAN_AUX_F_SCANNED;
@@ -1251,9 +1283,10 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
addrd.rpa_index = aux->rpa_index;
#endif
scan_filt_policy = ble_ll_scan_get_filt_policy();
rc = ble_ll_scan_rx_filter(ble_ll_scan_get_own_addr_type(),
ble_ll_scan_get_filt_policy(),
&addrd, &scan_ok);
scan_filt_policy, &addrd, &scan_ok);
if (rc < 0) {
rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED;
/*
@@ -1269,21 +1302,42 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
goto done;
}
if ((aux->scan_type == BLE_SCAN_TYPE_INITIATE) &&
!(scan_filt_policy & 0x01)) {
rc = ble_ll_scan_rx_check_init(&addrd);
if (rc < 0) {
goto done;
}
}
aux->flags |= BLE_LL_SCAN_AUX_F_MATCHED;
ble_ll_scan_aux_update_aux_data_from_addrd(&addrd, aux);
adv_mode = rxbuf[2] >> 6;
if ((aux->scan_type == BLE_SCAN_TYPE_ACTIVE) &&
(adv_mode == BLE_LL_EXT_ADV_MODE_SCAN) && scan_ok) {
if (ble_ll_scan_aux_send_scan_req(aux, &addrd)) {
switch (aux->scan_type) {
case BLE_SCAN_TYPE_ACTIVE:
if ((adv_mode == BLE_LL_EXT_ADV_MODE_SCAN) && scan_ok &&
ble_ll_scan_aux_send_scan_req(aux, &addrd)) {
/* AUX_SCAN_REQ sent, keep PHY enabled to continue */
aux->flags |= BLE_LL_SCAN_AUX_F_W4_SCAN_RSP;
rxinfo->flags |= BLE_MBUF_HDR_F_SCAN_REQ_TXD;
aux_data_current = aux;
return 0;
}
break;
case BLE_SCAN_TYPE_INITIATE:
if (ble_ll_conn_send_connect_req(rxpdu, &addrd, 1) == 0) {
/* AUX_CONNECT_REQ sent, keep PHY enabled to continue */
aux->flags |= BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP;
rxinfo->flags |= BLE_MBUF_HDR_F_CONNECT_REQ_TXD;
aux_data_current = aux;
return 0;
} else {
rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED;
}
break;
}
done:
@@ -1399,6 +1453,137 @@ ble_ll_scan_aux_sync_check(struct os_mbuf *rxpdu,
}
#endif
static int
ble_ll_scan_aux_check_connect_rsp(uint8_t *rxbuf,
struct ble_ll_scan_pdu_data *pdu_data,
struct ble_ll_scan_addr_data *addrd)
{
uint8_t pdu_hdr;
uint8_t pdu_len;
uint8_t adv_mode;
uint8_t eh_len;
uint8_t eh_flags;
uint8_t *eh_data;
uint8_t adva_type;
uint8_t *adva;
uint8_t targeta_type;
uint8_t *targeta;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
struct ble_ll_resolv_entry *rl = NULL;
#endif
pdu_hdr = rxbuf[0];
pdu_len = rxbuf[1];
if (pdu_len == 0) {
return -1;
}
adv_mode = rxbuf[2] >> 6;
eh_len = rxbuf[2] & 0x3f;
if ((adv_mode != 0) || (eh_len == 0)) {
return -1;
}
eh_flags = rxbuf[3];
eh_data = &rxbuf[4];
/* AUX_CONNECT_RSP without AdvA or TargetA is not valid */
if (!(eh_flags & ((1 << BLE_LL_EXT_ADV_ADVA_BIT) |
(1 << BLE_LL_EXT_ADV_TARGETA_BIT)))) {
return -1;
}
adva = eh_data;
adva_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_TXADD_RAND);
eh_data += BLE_LL_EXT_ADV_ADVA_SIZE;
targeta = eh_data;
targeta_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_RAND);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
/* If AdvA was initially resolved, we need to check if current AdvA also
* resolved with the same IRK since it may have changes due to RPA timeout.
* Otherwise it shall be the same as in AUX_CONNECT_REQ.
*/
if (addrd->adva_resolved) {
if (!adva_type) {
return -1;
}
BLE_LL_ASSERT(addrd->rpa_index >= 0);
rl = &g_ble_ll_resolv_list[addrd->rpa_index];
if (!ble_ll_resolv_rpa(adva, rl->rl_peer_irk)) {
return -1;
}
addrd->adva = adva;
} else if ((adva_type !=
!!(pdu_data->hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK)) ||
(memcmp(adva, pdu_data->adva, 6) != 0)) {
return -1;
}
#else
if ((adva_type != !!(pdu_data->hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK)) ||
(memcmp(adva, pdu_data->adva, 6) != 0)) {
return -1;
}
#endif /* BLE_LL_CFG_FEAT_LL_PRIVACY */
if ((targeta_type != !!(pdu_data->hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK)) ||
(memcmp(targeta, pdu_data->inita, 6) != 0)) {
return -1;
}
return 0;
}
static void
ble_ll_scan_aux_rx_pkt_in_for_initiator(struct os_mbuf *rxpdu,
struct ble_mbuf_hdr *rxhdr)
{
struct ble_ll_scan_addr_data addrd;
struct ble_mbuf_hdr_rxinfo *rxinfo;
struct ble_ll_scan_aux_data *aux;
rxinfo = &rxhdr->rxinfo;
aux = rxinfo->user_data;
if (rxinfo->flags & BLE_MBUF_HDR_F_IGNORED) {
ble_ll_scan_chk_resume();
goto done;
}
if (!(rxinfo->flags & BLE_MBUF_HDR_F_CONNECT_RSP_RXD)) {
BLE_LL_ASSERT(rxinfo->flags & BLE_MBUF_HDR_F_CONNECT_REQ_TXD);
/* Waiting for AUX_CONNECT_RSP, do nothing */
return;
}
ble_ll_scan_aux_init_addrd_from_aux_data(aux, &addrd);
if (ble_ll_scan_aux_check_connect_rsp(rxpdu->om_data,
ble_ll_scan_get_pdu_data(),
&addrd) < 0) {
ble_ll_scan_chk_resume();
goto done;
}
aux->flags &= ~BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP;
ble_ll_scan_sm_stop(0);
ble_ll_conn_created_on_aux(rxpdu, &addrd, aux->targeta);
done:
if (aux->flags & BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP) {
ble_ll_conn_send_connect_req_cancel();
}
ble_ll_scan_aux_free(aux);
}
void
ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr)
{
@@ -1416,6 +1601,11 @@ ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr)
BLE_LL_ASSERT(aux);
if (aux->scan_type == BLE_SCAN_TYPE_INITIATE) {
ble_ll_scan_aux_rx_pkt_in_for_initiator(rxpdu, rxhdr);
return;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV)
sync_check = ble_ll_sync_enabled() &&
!(aux->flags & BLE_LL_SCAN_AUX_F_AUX_CHAIN);
-94
View File
@@ -134,9 +134,6 @@ ble_ll_sched_preempt(struct ble_ll_sched_item *sch,
case BLE_LL_SCHED_TYPE_SCAN_AUX:
ble_ll_scan_aux_break(entry->cb_arg);
break;
case BLE_LL_SCHED_TYPE_AUX_SCAN:
ble_ll_scan_end_adv_evt(entry->cb_arg);
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV)
case BLE_LL_SCHED_TYPE_PERIODIC:
ble_ll_adv_periodic_rmvd_from_sched(entry->cb_arg);
@@ -1133,20 +1130,6 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch)
goto sched;
}
/* If aux scan scheduled and LL is in state when scanner is running
* in 3 states:
* BLE_LL_STATE_SCANNING
* BLE_LL_STATE_INITIATING
* BLE_LL_STATE_STANDBY
*
* Let scanner to decide to disable phy or not.
*/
if (sch->sched_type == BLE_LL_SCHED_TYPE_AUX_SCAN) {
if (lls == BLE_LL_STATE_INITIATING || lls == BLE_LL_STATE_SCANNING) {
goto sched;
}
}
/*
* This is either an advertising event or connection event start. If
* we are scanning or initiating just stop it.
@@ -1158,11 +1141,6 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch)
if (lls == BLE_LL_STATE_SCANNING) {
ble_ll_state_set(BLE_LL_STATE_STANDBY);
ble_ll_scan_halt();
} else if (lls == BLE_LL_STATE_INITIATING) {
ble_ll_state_set(BLE_LL_STATE_STANDBY);
ble_ll_scan_halt();
/* PHY is disabled - make sure we do not wait for AUX_CONNECT_RSP */
ble_ll_conn_reset_pending_aux_conn_rsp();
} else if (lls == BLE_LL_STATE_ADV) {
STATS_INC(ble_ll_stats, sched_state_adv_errs);
ble_ll_adv_halt();
@@ -1262,78 +1240,6 @@ ble_ll_sched_next_time(uint32_t *next_event_time)
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
/**
* Called to schedule a aux scan.
*
* Context: Interrupt
*
* @param ble_hdr
* @param scansm
* @param aux_scan
*
* @return 0 on success, 1 otherwise
*/
int
ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr,
struct ble_ll_scan_sm *scansm,
struct ble_ll_aux_data *aux_scan)
{
int rc = 1;
os_sr_t sr;
uint32_t off_ticks;
uint32_t off_rem_usecs;
uint32_t start_time;
uint32_t start_time_rem_usecs;
uint32_t end_time;
uint32_t dur;
struct ble_ll_sched_item *sch;
int phy_mode;
sch = &aux_scan->sch;
BLE_LL_ASSERT(sch->cb_arg == NULL);
off_ticks = os_cputime_usecs_to_ticks(aux_scan->offset);
off_rem_usecs = aux_scan->offset - os_cputime_ticks_to_usecs(off_ticks);
start_time = ble_hdr->beg_cputime + off_ticks;
start_time_rem_usecs = ble_hdr->rem_usecs + off_rem_usecs;
if (start_time_rem_usecs >= 31) {
start_time++;
start_time_rem_usecs -= 31;
}
start_time -= g_ble_ll_sched_offset_ticks;
/* Let's calculate time we reserve for aux packet. For now we assume to wait
* for fixed number of bytes and handle possible interrupting it in
* ble_ll_sched_execute_item(). This is because aux packet can be up to
* 256bytes and we don't want to block sched that long
*/
phy_mode = ble_ll_phy_to_phy_mode(aux_scan->aux_phy,
BLE_HCI_LE_PHY_CODED_ANY);
dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_AUX_PDU_LEN),
phy_mode);
end_time = start_time + os_cputime_usecs_to_ticks(dur);
sch->start_time = start_time;
sch->remainder = start_time_rem_usecs;
sch->end_time = end_time;
OS_ENTER_CRITICAL(sr);
rc = ble_ll_sched_insert(sch, 0, preempt_none);
if (rc == 0) {
sch->cb_arg = ble_ll_scan_aux_data_ref(aux_scan);
STATS_INC(ble_ll_stats, aux_scheduled);
}
OS_EXIT_CRITICAL(sr);
ble_ll_sched_restart();
return rc;
}
int
ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time,
uint8_t pdu_time_rem, uint32_t offset_us)
+3
View File
@@ -88,6 +88,9 @@ struct ble_mbuf_hdr_rxinfo
* set for the same PDU (e.g. one use by scanner, other one used by
* connection)
*/
#define BLE_MBUF_HDR_F_CONNECT_IND_TXD (0x4000)
#define BLE_MBUF_HDR_F_CONNECT_REQ_TXD (0x4000)
#define BLE_MBUF_HDR_F_CONNECT_RSP_RXD (0x0008)
#define BLE_MBUF_HDR_F_CONN_CREDIT (0x8000)
#define BLE_MBUF_HDR_F_IGNORED (0x8000)
#define BLE_MBUF_HDR_F_SCAN_REQ_TXD (0x4000)