| /* |
| * Copyright (c) 2011-2017 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 limPropExtsUtils.cc contains the utility functions |
| * to populate, parse proprietary extensions required to |
| * support ANI feature set. |
| * |
| * Author: Chandra Modumudi |
| * Date: 11/27/02 |
| * History:- |
| * Date Modified by Modification Information |
| * -------------------------------------------------------------------- |
| * |
| */ |
| #include "aniGlobal.h" |
| #include "wni_cfg.h" |
| #include "sirCommon.h" |
| #include "sirDebug.h" |
| #include "utilsApi.h" |
| #include "cfgApi.h" |
| #include "limApi.h" |
| #include "limTypes.h" |
| #include "limUtils.h" |
| #include "limAssocUtils.h" |
| #include "limPropExtsUtils.h" |
| #include "limSerDesUtils.h" |
| #include "limTrace.h" |
| #ifdef WLAN_FEATURE_VOWIFI_11R |
| #include "limFTDefs.h" |
| #endif |
| #include "limSession.h" |
| #define LIM_GET_NOISE_MAX_TRY 5 |
| |
| #include "wma.h" |
| /** |
| * limExtractApCapability() |
| * |
| *FUNCTION: |
| * This function is called to extract AP's HCF/WME/WSM capability |
| * from the IEs received from it in Beacon/Probe Response frames |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param pIE Pointer to starting IE in Beacon/Probe Response |
| * @param ieLen Length of all IEs combined |
| * @param qosCap Bits are set according to capabilities |
| * @return 0 - If AP does not assert HCF capability & 1 - otherwise |
| */ |
| void |
| limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, |
| tANI_U8 *qosCap, tANI_U16 *propCap, tANI_U8 *uapsd, |
| tPowerdBm *localConstraint, |
| tpPESession psessionEntry |
| ) |
| { |
| tSirProbeRespBeacon *pBeaconStruct; |
| #if !defined WLAN_FEATURE_VOWIFI |
| tANI_U32 localPowerConstraints = 0; |
| #endif |
| tANI_U32 enableTxBF20MHz; |
| |
| pBeaconStruct = vos_mem_malloc(sizeof(tSirProbeRespBeacon)); |
| if ( NULL == pBeaconStruct ) |
| { |
| limLog(pMac, LOGE, FL("Unable to allocate memory in limExtractApCapability") ); |
| return; |
| } |
| |
| vos_mem_set( (tANI_U8 *) pBeaconStruct, sizeof(tSirProbeRespBeacon), 0); |
| *qosCap = 0; |
| *propCap = 0; |
| *uapsd = 0; |
| PELOG3(limLog( pMac, LOG3, |
| FL("In limExtractApCapability: The IE's being received are:")); |
| sirDumpBuf( pMac, SIR_LIM_MODULE_ID, LOG3, pIE, ieLen );) |
| if (sirParseBeaconIE(pMac, pBeaconStruct, pIE, (tANI_U32)ieLen) == eSIR_SUCCESS) |
| { |
| if (pBeaconStruct->wmeInfoPresent || pBeaconStruct->wmeEdcaPresent |
| || pBeaconStruct->HTCaps.present) |
| LIM_BSS_CAPS_SET(WME, *qosCap); |
| if (LIM_BSS_CAPS_GET(WME, *qosCap) && pBeaconStruct->wsmCapablePresent) |
| LIM_BSS_CAPS_SET(WSM, *qosCap); |
| if (pBeaconStruct->propIEinfo.capabilityPresent) |
| *propCap = pBeaconStruct->propIEinfo.capability; |
| if (pBeaconStruct->HTCaps.present) |
| pMac->lim.htCapabilityPresentInBeacon = 1; |
| else |
| pMac->lim.htCapabilityPresentInBeacon = 0; |
| |
| #ifdef WLAN_FEATURE_11AC |
| limLog(pMac, LOG1, |
| FL("Beacon : VHTCaps.present: %d SU Beamformer: %d, IS_BSS_VHT_CAPABLE: %d"), |
| pBeaconStruct->VHTCaps.present, |
| pBeaconStruct->VHTCaps.suBeamFormerCap, |
| IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)); |
| |
| if (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) && pBeaconStruct->VHTOperation.present) |
| { |
| /* If VHT is supported min 80 MHz support is must */ |
| uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); |
| uint32_t vht_ch_wd; |
| |
| psessionEntry->vhtCapabilityPresentInBeacon = 1; |
| vht_ch_wd = VOS_MIN(fw_vht_ch_wd, |
| pBeaconStruct->VHTOperation.chanWidth); |
| /* |
| * First block covers 2 cases: |
| * 1) AP and STA both have same vht capab |
| * 2) AP is 160 (80+80), we are 160 only |
| */ |
| if (vht_ch_wd == pBeaconStruct->VHTOperation.chanWidth || |
| vht_ch_wd >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ ) { |
| psessionEntry->apCenterChan = |
| pBeaconStruct->VHTOperation.chanCenterFreqSeg1; |
| } else { |
| /* This is the case when AP was 160 but we were 80 only */ |
| psessionEntry->apCenterChan = |
| lim_get_80Mhz_center_channel(pBeaconStruct->channelNumber); |
| } |
| psessionEntry->apChanWidth = vht_ch_wd; |
| psessionEntry->vhtTxChannelWidthSet = vht_ch_wd; |
| |
| if (pBeaconStruct->Vendor1IEPresent && |
| pBeaconStruct->vendor2_ie.present && |
| pBeaconStruct->Vendor3IEPresent) |
| { |
| if (((pBeaconStruct->VHTCaps.txMCSMap & VHT_MCS_3x3_MASK) == |
| VHT_MCS_3x3_MASK) && |
| ((pBeaconStruct->VHTCaps.txMCSMap & VHT_MCS_2x2_MASK) != |
| VHT_MCS_2x2_MASK)) |
| { |
| psessionEntry->txBFIniFeatureEnabled = 0; |
| if (cfgSetInt(pMac, WNI_CFG_VHT_SU_BEAMFORMEE_CAP, 0) |
| != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("could not set " |
| "WNI_CFG_VHT_SU_BEAMFORMEE_CAP at CFG")); |
| } |
| } |
| } |
| if (!psessionEntry->htSupportedChannelWidthSet) { |
| if (HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, |
| WNI_CFG_VHT_ENABLE_TXBF_20MHZ, |
| &enableTxBF20MHz))) { |
| if (VOS_FALSE == enableTxBF20MHz) { |
| psessionEntry->txBFIniFeatureEnabled = 0; |
| if (cfgSetInt(pMac, WNI_CFG_VHT_SU_BEAMFORMEE_CAP, 0) |
| != eSIR_SUCCESS) { |
| limLog(pMac, LOGP, FL("could not set " |
| "WNI_CFG_VHT_SU_BEAMFORMEE_CAP at CFG")); |
| } |
| } |
| } |
| } |
| } |
| else |
| { |
| psessionEntry->vhtCapabilityPresentInBeacon = 0; |
| } |
| #endif |
| // Extract the UAPSD flag from WMM Parameter element |
| if (pBeaconStruct->wmeEdcaPresent) |
| *uapsd = pBeaconStruct->edcaParams.qosInfo.uapsd; |
| |
| if (pMac->roam.configParam.allow_tpc_from_ap) { |
| |
| if (pBeaconStruct->powerConstraintPresent) { |
| #if defined WLAN_FEATURE_VOWIFI |
| *localConstraint -= |
| pBeaconStruct->localPowerConstraint.localPowerConstraints; |
| #else |
| localPowerConstraints = |
| (tANI_U32)pBeaconStruct->localPowerConstraint. |
| localPowerConstraints; |
| #endif |
| } |
| else { |
| #if defined FEATURE_WLAN_ESE |
| /* If there is Power Constraint Element specifically, |
| * adapt to it. Hence there is else condition check |
| * for this if statement. |
| */ |
| if (pBeaconStruct->eseTxPwr.present) |
| *localConstraint = pBeaconStruct->eseTxPwr.power_limit; |
| |
| psessionEntry->is_ese_version_ie_present = |
| pBeaconStruct->is_ese_ver_ie_present; |
| #endif |
| } |
| } |
| #if !defined WLAN_FEATURE_VOWIFI |
| if (cfgSetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, localPowerConstraints) != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("Could not update local power constraint to cfg.")); |
| } |
| #endif |
| psessionEntry->countryInfoPresent = FALSE; |
| /* Initializing before first use */ |
| if (pBeaconStruct->countryInfoPresent) |
| psessionEntry->countryInfoPresent = TRUE; |
| } |
| /* Check if Extended caps are present in probe resp or not */ |
| if (pBeaconStruct->ExtCap.present) |
| psessionEntry->is_ext_caps_present = true; |
| |
| if (pBeaconStruct->vendor_sub20_capability != 0) |
| psessionEntry->sap_sub20_channelwidth = |
| pBeaconStruct->vendor_sub20_capability; |
| |
| /* Update HS 2.0 Information Element */ |
| sir_copy_hs20_ie(&psessionEntry->hs20vendor_ie, |
| &pBeaconStruct->hs20vendor_ie); |
| |
| vos_mem_free(pBeaconStruct); |
| return; |
| } /****** end limExtractApCapability() ******/ |
| |
| /** |
| * limGetHTCBState |
| * |
| *FUNCTION: |
| * This routing provides the translation of Airgo Enum to HT enum for determining |
| * secondary channel offset. |
| * Airgo Enum is required for backward compatibility purposes. |
| * |
| * |
| *NOTE: |
| * |
| * @param pMac - Pointer to Global MAC structure |
| * @return The corresponding HT enumeration |
| */ |
| ePhyChanBondState limGetHTCBState(ePhyChanBondState aniCBMode) |
| { |
| switch ( aniCBMode ) |
| { |
| #ifdef WLAN_FEATURE_11AC |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED: |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: |
| #endif |
| case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: |
| return PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; |
| #ifdef WLAN_FEATURE_11AC |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED: |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: |
| #endif |
| case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: |
| return PHY_DOUBLE_CHANNEL_LOW_PRIMARY; |
| #ifdef WLAN_FEATURE_11AC |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED: |
| return PHY_SINGLE_CHANNEL_CENTERED; |
| #endif |
| default : |
| return PHY_SINGLE_CHANNEL_CENTERED; |
| } |
| } |
| |
| /* |
| * limGetStaPeerType |
| * |
| *FUNCTION: |
| * This API returns STA peer type |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac - Pointer to Global MAC structure |
| * @param pStaDs - Pointer to the tpDphHashNode of the STA |
| * under consideration |
| * @return tStaRateMode |
| */ |
| tStaRateMode limGetStaPeerType( tpAniSirGlobal pMac, |
| tpDphHashNode pStaDs, |
| tpPESession psessionEntry) |
| { |
| tStaRateMode staPeerType = eSTA_11b; |
| #ifdef WLAN_FEATURE_11AC |
| if(pStaDs->mlmStaContext.vhtCapability) |
| staPeerType = eSTA_11ac; |
| #endif |
| else if(pStaDs->mlmStaContext.htCapability) |
| staPeerType = eSTA_11n; |
| else if(pStaDs->erpEnabled) |
| staPeerType = eSTA_11bg; |
| else if(psessionEntry->limRFBand == SIR_BAND_5_GHZ) |
| staPeerType = eSTA_11a; |
| return staPeerType; |
| } |