/**
 * 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;
}
示例#2
0
/**
 * 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;
}