| /* |
| * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| /* |
| * This file lim_scan_result_utils.cc contains the utility functions |
| * LIM uses for maintaining and accessing scan results on STA. |
| * Author: Chandra Modumudi |
| * Date: 02/13/02 |
| * History:- |
| * Date Modified by Modification Information |
| * -------------------------------------------------------------------- |
| */ |
| |
| #include "lim_types.h" |
| #include "lim_utils.h" |
| #include "lim_ser_des_utils.h" |
| #include "lim_api.h" |
| #include "lim_ft_defs.h" |
| #include "lim_session.h" |
| #include "rrm_api.h" |
| #include "cds_utils.h" |
| |
| /** |
| * lim_collect_bss_description() |
| * |
| ***FUNCTION: |
| * This function is called during scan upon receiving |
| * Beacon/Probe Response frame to check if the received |
| * frame matches scan criteria, collect BSS description |
| * and add it to cached scan results. |
| * |
| ***LOGIC: |
| * |
| ***ASSUMPTIONS: |
| * NA |
| * |
| ***NOTE: |
| * NA |
| * |
| * @param pMac - Pointer to Global MAC structure |
| * @param pBPR - Pointer to parsed Beacon/Probe Response structure |
| * @param pRxPacketInfo - Pointer to Received frame's BD |
| * @param fScanning - flag to indicate if it is during scan. |
| * --------------------------------------------- |
| * |
| * @return None |
| */ |
| void |
| lim_collect_bss_description(tpAniSirGlobal pMac, |
| tSirBssDescription *pBssDescr, |
| tpSirProbeRespBeacon pBPR, |
| uint8_t *pRxPacketInfo, uint8_t fScanning) |
| { |
| uint8_t *pBody; |
| uint32_t ieLen = 0; |
| tpSirMacMgmtHdr pHdr; |
| uint8_t channelNum; |
| uint8_t rxChannel; |
| uint8_t rfBand = 0; |
| |
| pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); |
| |
| if (SIR_MAC_B_PR_SSID_OFFSET > WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo)) { |
| QDF_ASSERT(WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) >= |
| SIR_MAC_B_PR_SSID_OFFSET); |
| return; |
| } |
| ieLen = |
| WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) - SIR_MAC_B_PR_SSID_OFFSET; |
| rxChannel = WMA_GET_RX_CH(pRxPacketInfo); |
| pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); |
| rfBand = WMA_GET_RX_RFBAND(pRxPacketInfo); |
| |
| /** |
| * Length of BSS desription is without length of |
| * length itself and length of pointer that holds ieFields. |
| * |
| * tSirBssDescription |
| * +--------+---------------------------------+---------------+ |
| * | length | other fields | pointer to IEs| |
| * +--------+---------------------------------+---------------+ |
| * ^ |
| * ieFields |
| */ |
| pBssDescr->length = (uint16_t)(offsetof(tSirBssDescription, ieFields[0]) |
| - sizeof(pBssDescr->length) + ieLen); |
| |
| /* Copy BSS Id */ |
| qdf_mem_copy((uint8_t *) &pBssDescr->bssId, |
| (uint8_t *) pHdr->bssId, sizeof(tSirMacAddr)); |
| |
| /* Copy Timestamp, Beacon Interval and Capability Info */ |
| pBssDescr->scansystimensec = qdf_get_bootbased_boottime_ns(); |
| |
| pBssDescr->timeStamp[0] = pBPR->timeStamp[0]; |
| pBssDescr->timeStamp[1] = pBPR->timeStamp[1]; |
| pBssDescr->beaconInterval = pBPR->beaconInterval; |
| pBssDescr->capabilityInfo = |
| lim_get_u16((uint8_t *) &pBPR->capabilityInfo); |
| |
| if (!pBssDescr->beaconInterval) { |
| pe_warn("Beacon Interval is ZERO, making it to default 100 " |
| MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pHdr->bssId)); |
| pBssDescr->beaconInterval = 100; |
| } |
| /* |
| * There is a narrow window after Channel Switch msg is sent to HAL and before the AGC is shut |
| * down and beacons/Probe Rsps can trickle in and we may report the incorrect channel in 5Ghz |
| * band, so not relying on the 'last Scanned Channel' stored in LIM. |
| * Instead use the value returned by RXP in BD. This the the same value which HAL programs into |
| * RXP before every channel switch. |
| * Right now there is a problem in 5Ghz, where we are receiving beacons from a channel different from |
| * the currently scanned channel. so incorrect channel is reported to CSR and association does not happen. |
| * So for now we keep on looking for the channel info in the beacon (DSParamSet IE OR HT Info IE), and only if it |
| * is not present in the beacon, we go for the channel info present in RXP. |
| * This fix will work for 5Ghz 11n devices, but for 11a devices, we have to rely on RXP routing flag to get the correct channel. |
| * So The problem of incorrect channel reporting in 5Ghz will still remain for 11a devices. |
| */ |
| pBssDescr->channelId = lim_get_channel_from_beacon(pMac, pBPR); |
| |
| if (pBssDescr->channelId == 0) { |
| /* If the channel Id is not retrieved from Beacon, extract the channel from BD */ |
| if (!rxChannel) { |
| rxChannel = pMac->lim.gLimCurrentScanChannelId; |
| } |
| pBssDescr->channelId = rxChannel; |
| } |
| |
| pBssDescr->channelIdSelf = pBssDescr->channelId; |
| pBssDescr->rx_channel = rxChannel; |
| |
| /* set the network type in bss description */ |
| channelNum = pBssDescr->channelId; |
| pBssDescr->nwType = |
| lim_get_nw_type(pMac, channelNum, SIR_MAC_MGMT_FRAME, pBPR); |
| |
| /* Copy RSSI & SINR from BD */ |
| pBssDescr->rssi = (int8_t) WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo); |
| pBssDescr->rssi_raw = (int8_t) WMA_GET_RX_RSSI_RAW(pRxPacketInfo); |
| |
| /* SINR no longer reported by HW */ |
| pBssDescr->sinr = 0; |
| pe_debug(MAC_ADDRESS_STR " rssi: normalized: %d, absolute: %d", |
| MAC_ADDR_ARRAY(pHdr->bssId), pBssDescr->rssi, |
| pBssDescr->rssi_raw); |
| |
| pBssDescr->received_time = (uint64_t)qdf_mc_timer_get_system_time(); |
| pBssDescr->tsf_delta = WMA_GET_RX_TSF_DELTA(pRxPacketInfo); |
| pBssDescr->seq_ctrl = pHdr->seqControl; |
| |
| pe_debug("Received %s from BSSID: %pM tsf_delta = %u Seq Num: %x ssid:%.*s, rssi: %d", |
| pBssDescr->fProbeRsp ? "Probe Rsp" : "Beacon", pHdr->bssId, |
| pBssDescr->tsf_delta, ((pHdr->seqControl.seqNumHi << |
| HIGH_SEQ_NUM_OFFSET) | pHdr->seqControl.seqNumLo), |
| pBPR->ssId.length, pBPR->ssId.ssId, pBssDescr->rssi_raw); |
| |
| if (fScanning) { |
| rrm_get_start_tsf(pMac, pBssDescr->startTSF); |
| pBssDescr->parentTSF = WMA_GET_RX_TIMESTAMP(pRxPacketInfo); |
| } |
| |
| /* MobilityDomain */ |
| pBssDescr->mdie[0] = 0; |
| pBssDescr->mdie[1] = 0; |
| pBssDescr->mdie[2] = 0; |
| pBssDescr->mdiePresent = false; |
| /* If mdie is present in the probe resp we */ |
| /* fill it in the bss description */ |
| if (pBPR->mdiePresent) { |
| pBssDescr->mdiePresent = true; |
| pBssDescr->mdie[0] = pBPR->mdie[0]; |
| pBssDescr->mdie[1] = pBPR->mdie[1]; |
| pBssDescr->mdie[2] = pBPR->mdie[2]; |
| } |
| |
| #ifdef FEATURE_WLAN_ESE |
| pBssDescr->QBSSLoad_present = false; |
| pBssDescr->QBSSLoad_avail = 0; |
| if (pBPR->QBSSLoad.present) { |
| pBssDescr->QBSSLoad_present = true; |
| pBssDescr->QBSSLoad_avail = pBPR->QBSSLoad.avail; |
| } |
| #endif |
| /* Copy IE fields */ |
| qdf_mem_copy((uint8_t *) &pBssDescr->ieFields, |
| pBody + SIR_MAC_B_PR_SSID_OFFSET, ieLen); |
| |
| /*set channel number in beacon in case it is not present */ |
| pBPR->channelNumber = pBssDescr->channelId; |
| pMac->lim.beacon_probe_rsp_cnt_per_scan++; |
| |
| return; |
| } /*** end lim_collect_bss_description() ***/ |