/** * Called when the LL receives a scan request or connection request * * Context: Called from interrupt context. * * @param rxbuf * * @return -1: request not for us or is a connect request. * 0: request (scan) is for us and we successfully went from rx to tx. * > 0: PHY error attempting to go from rx to tx. */ static int ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) { int rc; uint8_t chk_whitelist; uint8_t txadd; uint8_t *rxbuf; struct ble_mbuf_hdr *ble_hdr; struct ble_ll_adv_sm *advsm; rxbuf = rxpdu->om_data; if (ble_ll_adv_addr_cmp(rxbuf)) { return -1; } /* Set device match bit if we are whitelisting */ advsm = &g_ble_ll_adv_sm; if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { chk_whitelist = advsm->adv_filter_policy & 1; } else { chk_whitelist = advsm->adv_filter_policy & 2; } /* Set device match bit if we are whitelisting */ ble_hdr = BLE_MBUF_HDR_PTR(rxpdu); if (chk_whitelist) { /* Get the scanners address type */ if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { txadd = BLE_ADDR_TYPE_RANDOM; } else { txadd = BLE_ADDR_TYPE_PUBLIC; } /* Check for whitelist match */ if (!ble_ll_whitelist_match(rxbuf + BLE_LL_PDU_HDR_LEN, txadd)) { return -1; } ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH; } /* Setup to transmit the scan response if appropriate */ rc = -1; if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { ble_phy_set_txend_cb(ble_ll_adv_tx_done, &g_ble_ll_adv_sm); rc = ble_phy_tx(advsm->scan_rsp_pdu, BLE_PHY_TRANSITION_NONE); if (!rc) { ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_SCAN_RSP_TXD; STATS_INC(ble_ll_stats, scan_rsp_txg); } } return rc; }
/** * Called when the LL receives a scan request or connection request * * Context: Called from interrupt context. * * @param rxbuf * * @return -1: request not for us or is a connect request. * 0: request (scan) is for us and we successfully went from rx to tx. * > 0: PHY error attempting to go from rx to tx. */ static int ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) { int rc; int resolved; uint8_t chk_wl; uint8_t txadd; uint8_t peer_addr_type; uint8_t *rxbuf; uint8_t *adva; uint8_t *peer; struct ble_mbuf_hdr *ble_hdr; struct ble_ll_adv_sm *advsm; struct os_mbuf *scan_rsp; /* See if adva in the request (scan or connect) matches what we sent */ advsm = &g_ble_ll_adv_sm; rxbuf = rxpdu->om_data; adva = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN; if (memcmp(advsm->adva, adva, BLE_DEV_ADDR_LEN)) { return -1; } /* Set device match bit if we are whitelisting */ if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { chk_wl = advsm->adv_filter_policy & 1; } else { chk_wl = advsm->adv_filter_policy & 2; } /* Get the peer address type */ if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { txadd = BLE_ADDR_TYPE_RANDOM; } else { txadd = BLE_ADDR_TYPE_PUBLIC; } ble_hdr = BLE_MBUF_HDR_PTR(rxpdu); peer = rxbuf + BLE_LL_PDU_HDR_LEN; peer_addr_type = txadd; resolved = 0; #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) if (ble_ll_is_rpa(peer, txadd) && ble_ll_resolv_enabled()) { advsm->adv_rpa_index = ble_hw_resolv_list_match(); if (advsm->adv_rpa_index >= 0) { ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED; if (chk_wl) { peer = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr; peer_addr_type = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type; resolved = 1; } } else { if (chk_wl) { return -1; } } } #endif /* Set device match bit if we are whitelisting */ if (chk_wl && !ble_ll_whitelist_match(peer, peer_addr_type, resolved)) { return -1; } /* * We set the device match bit to tell the upper layer that we will * accept the request */ ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH; /* Setup to transmit the scan response if appropriate */ rc = -1; if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { scan_rsp = ble_ll_adv_scan_rsp_pdu_make(advsm); if (scan_rsp) { ble_phy_set_txend_cb(ble_ll_adv_tx_done, &g_ble_ll_adv_sm); rc = ble_phy_tx(scan_rsp, BLE_PHY_TRANSITION_NONE); if (!rc) { ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_SCAN_RSP_TXD; STATS_INC(ble_ll_stats, scan_rsp_txg); } os_mbuf_free_chain(scan_rsp); } } return rc; }