blob: 52f86adbced58fe96bfdabbfb68e83b411d1e66b [file] [log] [blame]
<
/*
* Copyright (c) 2012-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 parserApi.cc contains the code for parsing
* 802.11 messages.
* Author: Pierre Vandwalle
* Date: 03/18/02
* History:-
* Date Modified by Modification Information
* --------------------------------------------------------------------
*
*/
#include "sirApi.h"
#include "aniGlobal.h"
#include "parserApi.h"
#include "cfgApi.h"
#include "limUtils.h"
#include "utilsParser.h"
#include "limSerDesUtils.h"
#include "schApi.h"
#include "palApi.h"
#include "wmmApsd.h"
#if defined WLAN_FEATURE_VOWIFI
#include "rrmApi.h"
#endif
#include "regdomain_common.h"
#include "qdf_crypto.h"
#include "lim_process_fils.h"
#define DOT11F_RSN_VERSION 1 /* current supported version */
#define DOT11F_RSN_OUI_SIZE 4
#define DOT11F_RSN_CSE_NULL 0x00
#define DOT11F_RSN_CSE_WEP40 0x01
#define DOT11F_RSN_CSE_TKIP 0x02
#define DOT11F_RSN_CSE_WRAP 0x03
#define DOT11F_RSN_CSE_CCMP 0x04
#define DOT11F_RSN_CSE_WEP104 0x05
#define DOT11F_RSN_CSE_AES_CMAC 0x06
static const tANI_U8 sirRSNOui[][ DOT11F_RSN_OUI_SIZE ] = {
{ 0x00, 0x0F, 0xAC, 0x00 }, /* group cipher */
{ 0x00, 0x0F, 0xAC, 0x01 }, /* WEP-40 or RSN */
{ 0x00, 0x0F, 0xAC, 0x02 }, /* TKIP or RSN-PSK */
{ 0x00, 0x0F, 0xAC, 0x03 }, /* Reserved */
{ 0x00, 0x0F, 0xAC, 0x04 }, /* AES-CCMP */
{ 0x00, 0x0F, 0xAC, 0x05 }, /* WEP-104 */
{ 0x00, 0x40, 0x96, 0x00 }, /* CCKM */
/* BIP (encryption type) or RSN-PSK-SHA256 (authentication type) */
{ 0x00, 0x0F, 0xAC, 0x06 },
/* RSN-8021X-SHA256 (authentication type) */
{ 0x00, 0x0F, 0xAC, 0x05 }
};
////////////////////////////////////////////////////////////////////////
void dot11fLog(tpAniSirGlobal pMac, int loglevel, const char *pString,...)
{
#ifdef WLAN_DEBUG
if( (tANI_U32)loglevel > pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE( SIR_DBG_MODULE_ID )] )
{
return;
}
else
{
va_list marker;
va_start( marker, pString ); /* Initialize variable arguments. */
logDebug(pMac, SIR_DBG_MODULE_ID, loglevel, pString, marker);
va_end( marker ); /* Reset variable arguments. */
}
#endif
}
void
swapBitField16(tANI_U16 in, tANI_U16 *out)
{
# ifdef ANI_LITTLE_BIT_ENDIAN
*out = in;
# else // Big-Endian...
*out = ( ( in & 0x8000 ) >> 15 ) |
( ( in & 0x4000 ) >> 13 ) |
( ( in & 0x2000 ) >> 11 ) |
( ( in & 0x1000 ) >> 9 ) |
( ( in & 0x0800 ) >> 7 ) |
( ( in & 0x0400 ) >> 5 ) |
( ( in & 0x0200 ) >> 3 ) |
( ( in & 0x0100 ) >> 1 ) |
( ( in & 0x0080 ) << 1 ) |
( ( in & 0x0040 ) << 3 ) |
( ( in & 0x0020 ) << 5 ) |
( ( in & 0x0010 ) << 7 ) |
( ( in & 0x0008 ) << 9 ) |
( ( in & 0x0004 ) << 11 ) |
( ( in & 0x0002 ) << 13 ) |
( ( in & 0x0001 ) << 15 );
# endif // ANI_LITTLE_BIT_ENDIAN
}
void
swapBitField32(tANI_U32 in, tANI_U32 *out)
{
# ifdef ANI_LITTLE_BIT_ENDIAN
*out = in;
# else // Big-Endian...
*out = ( ( in & 0x80000000 ) >> 31 ) |
( ( in & 0x40000000 ) >> 29 ) |
( ( in & 0x20000000 ) >> 27 ) |
( ( in & 0x10000000 ) >> 25 ) |
( ( in & 0x08000000 ) >> 23 ) |
( ( in & 0x04000000 ) >> 21 ) |
( ( in & 0x02000000 ) >> 19 ) |
( ( in & 0x01000000 ) >> 17 ) |
( ( in & 0x00800000 ) >> 15 ) |
( ( in & 0x00400000 ) >> 13 ) |
( ( in & 0x00200000 ) >> 11 ) |
( ( in & 0x00100000 ) >> 9 ) |
( ( in & 0x00080000 ) >> 7 ) |
( ( in & 0x00040000 ) >> 5 ) |
( ( in & 0x00020000 ) >> 3 ) |
( ( in & 0x00010000 ) >> 1 ) |
( ( in & 0x00008000 ) << 1 ) |
( ( in & 0x00004000 ) << 3 ) |
( ( in & 0x00002000 ) << 5 ) |
( ( in & 0x00001000 ) << 7 ) |
( ( in & 0x00000800 ) << 9 ) |
( ( in & 0x00000400 ) << 11 ) |
( ( in & 0x00000200 ) << 13 ) |
( ( in & 0x00000100 ) << 15 ) |
( ( in & 0x00000080 ) << 17 ) |
( ( in & 0x00000040 ) << 19 ) |
( ( in & 0x00000020 ) << 21 ) |
( ( in & 0x00000010 ) << 23 ) |
( ( in & 0x00000008 ) << 25 ) |
( ( in & 0x00000004 ) << 27 ) |
( ( in & 0x00000002 ) << 29 ) |
( ( in & 0x00000001 ) << 31 );
# endif // ANI_LITTLE_BIT_ENDIAN
}
inline static void __printWMMParams(tpAniSirGlobal pMac, tDot11fIEWMMParams *pWmm)
{
limLog(pMac, LOG1, FL("WMM Parameters Received:"));
limLog(pMac, LOG1,
FL("BE: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d"),
pWmm->acbe_aifsn, pWmm->acbe_acm, pWmm->acbe_aci, pWmm->acbe_acwmin,
pWmm->acbe_acwmax, pWmm->acbe_txoplimit);
limLog(pMac, LOG1,
FL("BK: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d"),
pWmm->acbk_aifsn, pWmm->acbk_acm, pWmm->acbk_aci, pWmm->acbk_acwmin,
pWmm->acbk_acwmax, pWmm->acbk_txoplimit);
limLog(pMac, LOG1,
FL("VI: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d"),
pWmm->acvi_aifsn, pWmm->acvi_acm, pWmm->acvi_aci, pWmm->acvi_acwmin,
pWmm->acvi_acwmax, pWmm->acvi_txoplimit);
limLog(pMac, LOG1,
FL("VO: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d"),
pWmm->acvo_aifsn, pWmm->acvo_acm, pWmm->acvo_aci, pWmm->acvo_acwmin,
pWmm->acvo_acwmax, pWmm->acvo_txoplimit);
return;
}
////////////////////////////////////////////////////////////////////////
// Functions for populating "dot11f" style IEs
// return: >= 0, the starting location of the IE in rsnIEdata inside tSirRSNie
// < 0, cannot find
int FindIELocation( tpAniSirGlobal pMac,
tpSirRSNie pRsnIe,
tANI_U8 EID)
{
int idx, ieLen, bytesLeft;
int ret_val = -1;
// Here's what's going on: 'rsnIe' looks like this:
// typedef struct sSirRSNie
// {
// tANI_U16 length;
// tANI_U8 rsnIEdata[SIR_MAC_MAX_IE_LENGTH+2];
// } tSirRSNie, *tpSirRSNie;
// other code records both the WPA & RSN IEs (including their EIDs &
// lengths) into the array 'rsnIEdata'. We may have:
// With WAPI support, there may be 3 IEs here
// It can be only WPA IE, or only RSN IE or only WAPI IE
// Or two or all three of them with no particular ordering
// The if/then/else statements that follow are here to figure out
// whether we have the WPA IE, and where it is if we *do* have it.
//Save the first IE length
ieLen = pRsnIe->rsnIEdata[ 1 ] + 2;
idx = 0;
bytesLeft = pRsnIe->length;
while( 1 )
{
if ( EID == pRsnIe->rsnIEdata[ idx ] )
{
//Found it
return (idx);
}
else if ( EID != pRsnIe->rsnIEdata[ idx ] &&
// & if no more IE,
bytesLeft <= (tANI_U16)( ieLen ) )
{
dot11fLog(pMac, LOG3, FL("No IE (%d) in FindIELocation."), EID);
return ret_val;
}
bytesLeft -= ieLen;
ieLen = pRsnIe->rsnIEdata[ idx + 1 ] + 2;
idx += ieLen;
}
return ret_val;
}
tSirRetStatus
PopulateDot11fCapabilities(tpAniSirGlobal pMac,
tDot11fFfCapabilities *pDot11f,
tpPESession psessionEntry)
{
tANI_U16 cfg;
tSirRetStatus nSirStatus;
nSirStatus = cfgGetCapabilityInfo( pMac, &cfg,psessionEntry );
if ( eSIR_SUCCESS != nSirStatus )
{
dot11fLog(pMac, LOGP,
FL("Failed to retrieve the Capabilities bitfield from CFG (%d)"),
nSirStatus);
return nSirStatus;
}
swapBitField16( cfg, ( tANI_U16* )pDot11f );
return eSIR_SUCCESS;
} // End PopulateDot11fCapabilities.
/**
* populate_dot_11_f_ext_chann_switch_ann() - Function to populate ECS
* @mac_ptr: Pointer to PMAC structure
* @dot_11_ptr: ECS element
* @session_entry: PE session entry
*
* This function is used to populate the extended channel switch element
*
* Return: None
*
*/
void populate_dot_11_f_ext_chann_switch_ann(tpAniSirGlobal mac_ptr,
tDot11fIEext_chan_switch_ann *dot_11_ptr,
tpPESession session_entry)
{
dot_11_ptr->switch_mode = session_entry->gLimChannelSwitch.switchMode;
dot_11_ptr->new_reg_class = regdm_get_opclass_from_channel(
mac_ptr->scan.countryCodeCurrent,
session_entry->gLimChannelSwitch.
primaryChannel,
session_entry->gLimChannelSwitch.
secondarySubBand);
dot_11_ptr->new_channel =
session_entry->gLimChannelSwitch.primaryChannel;
dot_11_ptr->switch_count =
session_entry->gLimChannelSwitch.switchCount;
dot_11_ptr->present = 1;
}
void
PopulateDot11fChanSwitchAnn(tpAniSirGlobal pMac,
tDot11fIEChanSwitchAnn *pDot11f,
tpPESession psessionEntry)
{
pDot11f->switchMode = psessionEntry->gLimChannelSwitch.switchMode;
pDot11f->newChannel = psessionEntry->gLimChannelSwitch.primaryChannel;
pDot11f->switchCount = ( tANI_U8 ) psessionEntry->gLimChannelSwitch.switchCount;
pDot11f->present = 1;
} // End PopulateDot11fChanSwitchAnn.
void
populate_dot11_supp_operating_classes(tpAniSirGlobal mac_ptr,
tDot11fIESuppOperatingClasses *dot_11_ptr,
tpPESession session_entry)
{
uint8_t ch_bandwidth;
if (session_entry->vhtTxChannelWidthSet == eHT_CHANNEL_WIDTH_80MHZ)
ch_bandwidth = BW80;
else {
switch (session_entry->htSecondaryChannelOffset) {
case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
ch_bandwidth = BW40_HIGH_PRIMARY;
break;
case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
ch_bandwidth = BW40_LOW_PRIMARY;
break;
default:
ch_bandwidth = BW20;
break;
}
}
regdm_get_curr_opclasses(&dot_11_ptr->num_classes,
&dot_11_ptr->classes[1]);
dot_11_ptr->classes[0] = regdm_get_opclass_from_channel(
mac_ptr->scan.countryCodeCurrent,
session_entry->currentOperChannel,
ch_bandwidth);
dot_11_ptr->num_classes++;
dot_11_ptr->present = 1;
}
#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
void
populate_dot11f_avoid_channel_ie(tpAniSirGlobal mac_ctx,
tDot11fIEQComVendorIE *dot11f,
tpPESession pe_session)
{
if (!pe_session->sap_advertise_avoid_ch_ie)
return;
dot11f->present = true;
dot11f->MccChanInfo.present = true;
dot11f->MccChanInfo.channel = pe_session->currentOperChannel;
}
#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
#ifdef FEATURE_WLAN_SUB_20_MHZ
/**
* populate_dot11f_sub_20_channel_width_ie() - Populate a sDot11fIEQComVendorIE
* @mac_ctx_ptr: Pointer to Global MAC structure
* @dot11f_ptr: Pointer to Address of a sDot11fIEQComVendorIE to be filled in
* @pe_session: PE session entry
*
* Return: none
*/
void
populate_dot11f_sub_20_channel_width_ie(
tpAniSirGlobal mac_ctx_ptr,
tDot11fIEQComVendorIE *dot11f_ptr,
tpPESession pe_session)
{
uint8_t sub20_static_channelwidth;
uint8_t sub20_dynamic_channelwidth;
uint8_t sub20_capability;
sub20_static_channelwidth = mac_ctx_ptr->sub20_channelwidth;
sub20_dynamic_channelwidth = mac_ctx_ptr->sub20_dynamic_channelwidth;
if (sub20_static_channelwidth == 0 &&
sub20_dynamic_channelwidth == 0)
return;
if (sub20_dynamic_channelwidth != 0)
sub20_capability = sub20_dynamic_channelwidth;
else
sub20_capability = sub20_static_channelwidth;
if (LIM_IS_AP_ROLE(pe_session) ||
LIM_IS_STA_ROLE(pe_session)) {
dot11f_ptr->present = true;
dot11f_ptr->Sub20Info.present = true;
dot11f_ptr->Sub20Info.capability = sub20_capability;
}
if (LIM_IS_AP_ROLE(pe_session) &&
pe_session->dfsIncludeChanSwIe == VOS_TRUE) {
dot11f_ptr->present = true;
dot11f_ptr->Sub20Info.present = true;
dot11f_ptr->Sub20Info.csa_chanwidth =
pe_session->lim_sub20_channel_switch_bandwidth;
}
}
#endif
void
PopulateDot11fChanSwitchWrapper(tpAniSirGlobal pMac,
tDot11fIEChannelSwitchWrapper *pDot11f,
tpPESession psessionEntry)
{
uint8_t *ie_ptr = NULL;
/*
* The new country subelement is present only when
* 1. AP performs Extended Channel switching to new country.
* 2. New Operating Class table or a changed set of operating
* classes relative to the contents of the country element sent
* in the beacons.
*
* In the current scenario Channel Switch wrapper IE is included
* when we a radar is found and the AP does a channel change in
* the same regulatory domain(No country change or Operating class
* table). So, we do not need to include the New Country IE.
*
* Transmit Power Envlope Subelement is optional
* in Channel Switch Wrapper IE. So, not setting
* the TPE subelement. We include only WiderBWChanSwitchAnn.
*/
pDot11f->present = 1;
/*
* Add the Wide Channel Bandwidth Sublement.
*/
pDot11f->WiderBWChanSwitchAnn.newChanWidth =
psessionEntry->gLimWiderBWChannelSwitch.newChanWidth;
pDot11f->WiderBWChanSwitchAnn.newCenterChanFreq0 =
psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0;
pDot11f->WiderBWChanSwitchAnn.newCenterChanFreq1 =
psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1;
pDot11f->WiderBWChanSwitchAnn.present = 1;
/*
* Add the VHT Transmit power Envelope Sublement.
*/
ie_ptr = lim_get_ie_ptr(psessionEntry->addIeParams.probeRespBCNData_buff,
psessionEntry->addIeParams.probeRespBCNDataLen,
DOT11F_EID_VHT_TRANSMIT_POWER_ENV);
if (ie_ptr) {
/* Ignore EID field */
ie_ptr++;
pDot11f->vht_transmit_power_env.present = 1;
pDot11f->vht_transmit_power_env.num_bytes = *ie_ptr++;
vos_mem_copy(pDot11f->vht_transmit_power_env.bytes,
ie_ptr, pDot11f->vht_transmit_power_env.num_bytes);
}
}
#ifdef WLAN_FEATURE_11AC
void
PopulateDot11fWiderBWChanSwitchAnn(tpAniSirGlobal pMac,
tDot11fIEWiderBWChanSwitchAnn *pDot11f,
tpPESession psessionEntry)
{
pDot11f->present = 1;
pDot11f->newChanWidth = psessionEntry->gLimWiderBWChannelSwitch.newChanWidth;
pDot11f->newCenterChanFreq0 = psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0;
pDot11f->newCenterChanFreq1 = psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1;
}
#endif
tSirRetStatus
PopulateDot11fCountry(tpAniSirGlobal pMac,
tDot11fIECountry *pDot11f,
tpPESession psessionEntry)
{
tANI_U32 len, maxlen, codelen;
tANI_U16 item;
tSirRetStatus nSirStatus;
tSirRFBand rfBand;
tANI_U8 temp[CFG_MAX_STR_LEN], code[3];
if (psessionEntry->lim11dEnabled )
{
limGetRfBand(pMac, &rfBand, psessionEntry);
if (rfBand == SIR_BAND_5_GHZ)
{
item = WNI_CFG_MAX_TX_POWER_5;
maxlen = WNI_CFG_MAX_TX_POWER_5_LEN;
}
else
{
item = WNI_CFG_MAX_TX_POWER_2_4;
maxlen = WNI_CFG_MAX_TX_POWER_2_4_LEN;
}
CFG_GET_STR( nSirStatus, pMac, item, temp, len, maxlen );
if ( 3 > len )
{
// no limit on tx power, cannot include the IE because at least
// one (channel,num,tx power) must be present
return eSIR_SUCCESS;
}
CFG_GET_STR( nSirStatus, pMac, WNI_CFG_COUNTRY_CODE,
code, codelen, 3 );
vos_mem_copy( pDot11f->country, code, codelen );
if(len > MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE)
{
dot11fLog(pMac, LOGE,
FL("len:%d is out of bounds, resetting"), len);
len = MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE;
}
pDot11f->num_triplets = ( tANI_U8 ) ( len / 3 );
vos_mem_copy( ( tANI_U8* )pDot11f->triplets, temp, len );
pDot11f->present = 1;
}
return eSIR_SUCCESS;
} // End PopulateDot11fCountry.
tSirRetStatus
PopulateDot11fDSParams(tpAniSirGlobal pMac,
tDot11fIEDSParams *pDot11f, tANI_U8 channel,
tpPESession psessionEntry)
{
if (IS_24G_CH(channel)) {
// .11b/g mode PHY => Include the DS Parameter Set IE:
pDot11f->curr_channel = channel;
pDot11f->present = 1;
}
return eSIR_SUCCESS;
} // End PopulateDot11fDSParams.
#define SET_AIFSN(aifsn) (((aifsn) < 2) ? 2 : (aifsn))
void
PopulateDot11fEDCAParamSet(tpAniSirGlobal pMac,
tDot11fIEEDCAParamSet *pDot11f,
tpPESession psessionEntry)
{
if ( psessionEntry->limQosEnabled )
{
//change to bitwise operation, after this is fixed in frames.
pDot11f->qos = (tANI_U8)(0xf0 & (psessionEntry->gLimEdcaParamSetCount << 4) );
// Fill each EDCA parameter set in order: be, bk, vi, vo
pDot11f->acbe_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[0].aci.aifsn) );
pDot11f->acbe_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[0].aci.acm );
pDot11f->acbe_aci = ( 0x3 & SIR_MAC_EDCAACI_BESTEFFORT );
pDot11f->acbe_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[0].cw.min );
pDot11f->acbe_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[0].cw.max );
pDot11f->acbe_txoplimit = psessionEntry->gLimEdcaParamsBC[0].txoplimit;
pDot11f->acbk_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[1].aci.aifsn) );
pDot11f->acbk_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[1].aci.acm );
pDot11f->acbk_aci = ( 0x3 & SIR_MAC_EDCAACI_BACKGROUND );
pDot11f->acbk_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[1].cw.min );
pDot11f->acbk_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[1].cw.max );
pDot11f->acbk_txoplimit = psessionEntry->gLimEdcaParamsBC[1].txoplimit;
pDot11f->acvi_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[2].aci.aifsn) );
pDot11f->acvi_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[2].aci.acm );
pDot11f->acvi_aci = ( 0x3 & SIR_MAC_EDCAACI_VIDEO );
pDot11f->acvi_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[2].cw.min );
pDot11f->acvi_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[2].cw.max );
pDot11f->acvi_txoplimit = psessionEntry->gLimEdcaParamsBC[2].txoplimit;
pDot11f->acvo_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[3].aci.aifsn) );
pDot11f->acvo_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[3].aci.acm );
pDot11f->acvo_aci = ( 0x3 & SIR_MAC_EDCAACI_VOICE );
pDot11f->acvo_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[3].cw.min );
pDot11f->acvo_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[3].cw.max );
pDot11f->acvo_txoplimit = psessionEntry->gLimEdcaParamsBC[3].txoplimit;
pDot11f->present = 1;
}
} // End PopluateDot11fEDCAParamSet.
tSirRetStatus
PopulateDot11fERPInfo(tpAniSirGlobal pMac,
tDot11fIEERPInfo *pDot11f,
tpPESession psessionEntry)
{
tSirRetStatus nSirStatus;
tANI_U32 val;
tSirRFBand rfBand = SIR_BAND_UNKNOWN;
limGetRfBand(pMac, &rfBand, psessionEntry);
if(SIR_BAND_2_4_GHZ == rfBand)
{
pDot11f->present = 1;
val = psessionEntry->cfgProtection.fromllb;
if(!val ){
dot11fLog(pMac, LOGE,
FL("11B protection not enabled. Not populating ERP IE %d"),
val);
return eSIR_SUCCESS;
}
if (psessionEntry->gLim11bParams.protectionEnabled)
{
pDot11f->non_erp_present = 1;
pDot11f->use_prot = 1;
}
if ( psessionEntry->gLimOlbcParams.protectionEnabled )
{
//FIXME_PROTECTION: we should be setting non_erp present also.
//check the test plan first.
pDot11f->use_prot = 1;
}
if((psessionEntry->gLimNoShortParams.numNonShortPreambleSta)
|| !psessionEntry->beaconParams.fShortPreamble){
pDot11f->barker_preamble = 1;
}
// if protection always flag is set, advertise protection enabled
// regardless of legacy stations presence
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_11G_PROTECTION_ALWAYS, val );
if ( val )
{
pDot11f->use_prot = 1;
}
}
return eSIR_SUCCESS;
} // End PopulateDot11fERPInfo.
tSirRetStatus
PopulateDot11fExtSuppRates(tpAniSirGlobal pMac, tANI_U8 nChannelNum,
tDot11fIEExtSuppRates *pDot11f,
tpPESession psessionEntry)
{
tSirRetStatus nSirStatus;
tANI_U32 nRates = 0;
tANI_U8 rates[SIR_MAC_RATESET_EID_MAX];
/* Use the ext rates present in session entry whenever nChannelNum is set to OPERATIONAL
else use the ext supported rate set from CFG, which is fixed and does not change dynamically and is used for
sending mgmt frames (lile probe req) which need to go out before any session is present.
*/
if(POPULATE_DOT11F_RATES_OPERATIONAL == nChannelNum )
{
if(psessionEntry != NULL)
{
nRates = psessionEntry->extRateSet.numRates;
vos_mem_copy( rates, psessionEntry->extRateSet.rate,
nRates);
}
else
{
dot11fLog(pMac, LOGE,
FL("no session context exists while populating Operational Rate Set"));
}
}
else if ( HIGHEST_24GHZ_CHANNEL_NUM >= nChannelNum )
{
CFG_GET_STR( nSirStatus, pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
rates, nRates, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN );
}
if ( 0 != nRates )
{
pDot11f->num_rates = ( tANI_U8 )nRates;
vos_mem_copy( pDot11f->rates, rates, nRates );
pDot11f->present = 1;
}
return eSIR_SUCCESS;
} // End PopulateDot11fExtSuppRates.
tSirRetStatus
PopulateDot11fExtSuppRates1(tpAniSirGlobal pMac,
tANI_U8 nChannelNum,
tDot11fIEExtSuppRates *pDot11f)
{
tANI_U32 nRates;
tSirRetStatus nSirStatus;
tANI_U8 rates[SIR_MAC_MAX_NUMBER_OF_RATES];
if ( 14 < nChannelNum )
{
pDot11f->present = 0;
return eSIR_SUCCESS;
}
// N.B. I have *no* idea why we're calling 'wlan_cfgGetStr' with an argument
// of WNI_CFG_SUPPORTED_RATES_11A here, but that's what was done
// previously & I'm afraid to change it!
CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SUPPORTED_RATES_11A,
rates, nRates, SIR_MAC_MAX_NUMBER_OF_RATES );
if ( 0 != nRates )
{
pDot11f->num_rates = ( tANI_U8 ) nRates;
vos_mem_copy( pDot11f->rates, rates, nRates );
pDot11f->present = 1;
}
return eSIR_SUCCESS;
} // PopulateDot11fExtSuppRates1.
tSirRetStatus
PopulateDot11fHTCaps(tpAniSirGlobal pMac,
tpPESession psessionEntry,
tDot11fIEHTCaps *pDot11f)
{
tANI_U32 nCfgValue, nCfgLen;
tANI_U8 nCfgValue8;
tSirRetStatus nSirStatus;
tSirMacHTParametersInfo *pHTParametersInfo;
union {
tANI_U16 nCfgValue16;
tSirMacHTCapabilityInfo htCapInfo;
tSirMacExtendedHTCapabilityInfo extHtCapInfo;
} uHTCapabilityInfo;
tSirMacTxBFCapabilityInfo *pTxBFCapabilityInfo;
tSirMacASCapabilityInfo *pASCapabilityInfo;
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_CAP_INFO, nCfgValue );
uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
pDot11f->advCodingCap = uHTCapabilityInfo.htCapInfo.advCodingCap;
pDot11f->mimoPowerSave = uHTCapabilityInfo.htCapInfo.mimoPowerSave;
pDot11f->greenField = uHTCapabilityInfo.htCapInfo.greenField;
pDot11f->delayedBA = uHTCapabilityInfo.htCapInfo.delayedBA;
pDot11f->maximalAMSDUsize = uHTCapabilityInfo.htCapInfo.maximalAMSDUsize;
pDot11f->dsssCckMode40MHz = uHTCapabilityInfo.htCapInfo.dsssCckMode40MHz;
pDot11f->psmp = uHTCapabilityInfo.htCapInfo.psmp;
pDot11f->stbcControlFrame = uHTCapabilityInfo.htCapInfo.stbcControlFrame;
pDot11f->lsigTXOPProtection = uHTCapabilityInfo.htCapInfo.lsigTXOPProtection;
// All sessionized entries will need the check below
if (psessionEntry == NULL) // Only in case of NO session
{
pDot11f->supportedChannelWidthSet = uHTCapabilityInfo.htCapInfo.supportedChannelWidthSet;
pDot11f->txSTBC = uHTCapabilityInfo.htCapInfo.txSTBC;
pDot11f->rxSTBC = uHTCapabilityInfo.htCapInfo.rxSTBC;
pDot11f->shortGI20MHz = uHTCapabilityInfo.htCapInfo.shortGI20MHz;
pDot11f->shortGI40MHz = uHTCapabilityInfo.htCapInfo.shortGI40MHz;
}
else
{
pDot11f->supportedChannelWidthSet = psessionEntry->htSupportedChannelWidthSet;
pDot11f->txSTBC = psessionEntry->htConfig.ht_tx_stbc;
pDot11f->rxSTBC = psessionEntry->htConfig.ht_rx_stbc;
if (psessionEntry->htConfig.ht_sgi) {
pDot11f->shortGI20MHz =
uHTCapabilityInfo.htCapInfo.shortGI20MHz;
pDot11f->shortGI40MHz =
uHTCapabilityInfo.htCapInfo.shortGI40MHz;
}
}
/* Ensure that shortGI40MHz is Disabled if supportedChannelWidthSet is
eHT_CHANNEL_WIDTH_20MHZ */
if(pDot11f->supportedChannelWidthSet == eHT_CHANNEL_WIDTH_20MHZ)
{
pDot11f->shortGI40MHz = 0;
}
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_AMPDU_PARAMS, nCfgValue );
nCfgValue8 = ( tANI_U8 ) nCfgValue;
pHTParametersInfo = ( tSirMacHTParametersInfo* ) &nCfgValue8;
pDot11f->maxRxAMPDUFactor = pHTParametersInfo->maxRxAMPDUFactor;
pDot11f->mpduDensity = pHTParametersInfo->mpduDensity;
pDot11f->reserved1 = pHTParametersInfo->reserved;
CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SUPPORTED_MCS_SET,
pDot11f->supportedMCSSet, nCfgLen,
SIZE_OF_SUPPORTED_MCS_SET );
if (!pMac->per_band_chainmask_supp) {
if (psessionEntry && (pMac->lteCoexAntShare &&
(IS_24G_CH(psessionEntry->currentOperChannel)))) {
if(!(IS_2X2_CHAIN(psessionEntry->chainMask))) {
pDot11f->supportedMCSSet[1] = 0;
if (LIM_IS_STA_ROLE(psessionEntry)) {
pDot11f->mimoPowerSave = psessionEntry->smpsMode;
}
}
}
} else if (psessionEntry && psessionEntry->vdev_nss == NSS_1x1_MODE) {
pDot11f->supportedMCSSet[1] = 0;
}
/* If STA and mimo power save is enabled include ht smps */
if (psessionEntry &&
LIM_IS_STA_ROLE(psessionEntry) &&
(psessionEntry->enableHtSmps) &&
(!psessionEntry->supported_nss_1x1)) {
limLog(pMac, LOG1, FL("Add SM power save IE :%d"),
psessionEntry->htSmpsvalue);
pDot11f->mimoPowerSave = psessionEntry->htSmpsvalue;
}
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_EXT_HT_CAP_INFO, nCfgValue );
uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
pDot11f->pco = uHTCapabilityInfo.extHtCapInfo.pco;
pDot11f->transitionTime = uHTCapabilityInfo.extHtCapInfo.transitionTime;
pDot11f->mcsFeedback = uHTCapabilityInfo.extHtCapInfo.mcsFeedback;
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_TX_BF_CAP, nCfgValue );
pTxBFCapabilityInfo = ( tSirMacTxBFCapabilityInfo* ) &nCfgValue;
pDot11f->txBF = pTxBFCapabilityInfo->txBF;
pDot11f->rxStaggeredSounding = pTxBFCapabilityInfo->rxStaggeredSounding;
pDot11f->txStaggeredSounding = pTxBFCapabilityInfo->txStaggeredSounding;
pDot11f->rxZLF = pTxBFCapabilityInfo->rxZLF;
pDot11f->txZLF = pTxBFCapabilityInfo->txZLF;
pDot11f->implicitTxBF = pTxBFCapabilityInfo->implicitTxBF;
pDot11f->calibration = pTxBFCapabilityInfo->calibration;
pDot11f->explicitCSITxBF = pTxBFCapabilityInfo->explicitCSITxBF;
pDot11f->explicitUncompressedSteeringMatrix = pTxBFCapabilityInfo->explicitUncompressedSteeringMatrix;
pDot11f->explicitBFCSIFeedback = pTxBFCapabilityInfo->explicitBFCSIFeedback;
pDot11f->explicitUncompressedSteeringMatrixFeedback = pTxBFCapabilityInfo->explicitUncompressedSteeringMatrixFeedback;
pDot11f->explicitCompressedSteeringMatrixFeedback = pTxBFCapabilityInfo->explicitCompressedSteeringMatrixFeedback;
pDot11f->csiNumBFAntennae = pTxBFCapabilityInfo->csiNumBFAntennae;
pDot11f->uncompressedSteeringMatrixBFAntennae = pTxBFCapabilityInfo->uncompressedSteeringMatrixBFAntennae;
pDot11f->compressedSteeringMatrixBFAntennae = pTxBFCapabilityInfo->compressedSteeringMatrixBFAntennae;
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_AS_CAP, nCfgValue );
nCfgValue8 = ( tANI_U8 ) nCfgValue;
pASCapabilityInfo = ( tSirMacASCapabilityInfo* ) &nCfgValue8;
pDot11f->antennaSelection = pASCapabilityInfo->antennaSelection;
pDot11f->explicitCSIFeedbackTx = pASCapabilityInfo->explicitCSIFeedbackTx;
pDot11f->antennaIndicesFeedbackTx = pASCapabilityInfo->antennaIndicesFeedbackTx;
pDot11f->explicitCSIFeedback = pASCapabilityInfo->explicitCSIFeedback;
pDot11f->antennaIndicesFeedback = pASCapabilityInfo->antennaIndicesFeedback;
pDot11f->rxAS = pASCapabilityInfo->rxAS;
pDot11f->txSoundingPPDUs = pASCapabilityInfo->txSoundingPPDUs;
pDot11f->present = 1;
return eSIR_SUCCESS;
} // End PopulateDot11fHTCaps.
#ifdef WLAN_FEATURE_11AC
void limLogVHTCap(tpAniSirGlobal pMac,
tDot11fIEVHTCaps *pDot11f)
{
#ifdef DUMP_MGMT_CNTNTS
limLog(pMac, LOG1, FL("maxMPDULen (2): %d"), pDot11f->maxMPDULen);
limLog(pMac, LOG1, FL("supportedChannelWidthSet (2): %d"),
pDot11f->supportedChannelWidthSet);
limLog(pMac, LOG1, FL("ldpcCodingCap (1): %d"), pDot11f->ldpcCodingCap);
limLog(pMac, LOG1, FL("shortGI80MHz (1): %d"), pDot11f->shortGI80MHz);
limLog(pMac, LOG1, FL("shortGI160and80plus80MHz (1): %d"),
pDot11f->shortGI160and80plus80MHz);
limLog(pMac, LOG1, FL("txSTBC (1): %d"), pDot11f->txSTBC);
limLog(pMac, LOG1, FL("rxSTBC (3): %d"), pDot11f->rxSTBC);
limLog(pMac, LOG1, FL("suBeamFormerCap (1): %d"), pDot11f->suBeamFormerCap);
limLog(pMac, LOG1, FL("suBeamformeeCap (1): %d"), pDot11f->suBeamformeeCap);
limLog(pMac, LOG1, FL("csnofBeamformerAntSup (3): %d"),
pDot11f->csnofBeamformerAntSup);
limLog(pMac, LOG1, FL("numSoundingDim (3): %d"), pDot11f->numSoundingDim);
limLog(pMac, LOG1, FL("muBeamformerCap (1): %d"), pDot11f->muBeamformerCap);
limLog(pMac, LOG1, FL("muBeamformeeCap (1): %d"), pDot11f->muBeamformeeCap);
limLog(pMac, LOG1, FL("vhtTXOPPS (1): %d"), pDot11f->vhtTXOPPS);
limLog(pMac, LOG1, FL("htcVHTCap (1): %d"), pDot11f->htcVHTCap);
limLog(pMac, LOG1, FL("maxAMPDULenExp (3): %d"), pDot11f->maxAMPDULenExp);
limLog(pMac, LOG1, FL("vhtLinkAdaptCap (2): %d"), pDot11f->vhtLinkAdaptCap);
limLog(pMac, LOG1, FL("rxAntPattern (1): %d"), pDot11f->vhtLinkAdaptCap);
limLog(pMac, LOG1, FL("txAntPattern (1): %d"), pDot11f->vhtLinkAdaptCap);
limLog(pMac, LOG1, FL("reserved1 (2): %d"), pDot11f->reserved1);
limLog(pMac, LOG1, FL("rxMCSMap (16): %d"), pDot11f->rxMCSMap);
limLog(pMac, LOG1, FL("rxHighSupDataRate (13): %d"),
pDot11f->rxHighSupDataRate);
limLog(pMac, LOG1, FL("reserve (3): %d"), pDot11f->reserved2);
limLog(pMac, LOG1, FL("txMCSMap (16): %d"), pDot11f->txMCSMap);
limLog(pMac, LOG1, FL("txSupDataRate (13): %d"), pDot11f->txSupDataRate);
limLog(pMac, LOG1, FL("reserv (3): %d"), pDot11f->reserved3);
#endif /* DUMP_MGMT_CNTNTS */
}
void limLogVHTOperation(tpAniSirGlobal pMac,
tDot11fIEVHTOperation *pDot11f)
{
#ifdef DUMP_MGMT_CNTNTS
limLog(pMac, LOG1, FL("chanWidth : %d"), pDot11f->chanWidth);
limLog(pMac, LOG1, FL("chanCenterFreqSeg1: %d"),
pDot11f->chanCenterFreqSeg1);
limLog(pMac, LOG1, FL("chanCenterFreqSeg2: %d"),
pDot11f->chanCenterFreqSeg2);
limLog(pMac, LOG1, FL("basicMCSSet: %d"), pDot11f->basicMCSSet);
#endif /* DUMP_MGMT_CNTNTS */
}
void limLogVHTExtBssLoad(tpAniSirGlobal pMac,
tDot11fIEVHTExtBssLoad *pDot11f)
{
#ifdef DUMP_MGMT_CNTNTS
limLog(pMac, LOG1, FL("muMIMOCapStaCount : %d"),
pDot11f->muMIMOCapStaCount);
limLog(pMac, LOG1, FL("ssUnderUtil: %d"), pDot11f->ssUnderUtil);
limLog(pMac, LOG1, FL("FortyMHzUtil: %d"), pDot11f->FortyMHzUtil);
limLog(pMac, LOG1, FL("EightyMHzUtil: %d"), pDot11f->EightyMHzUtil);
limLog(pMac, LOG1, FL("OneSixtyMHzUtil: %d"), pDot11f->OneSixtyMHzUtil);
#endif /* DUMP_MGMT_CNTNTS */
}
void limLogOperatingMode( tpAniSirGlobal pMac,
tDot11fIEOperatingMode *pDot11f)
{
#ifdef DUMP_MGMT_CNTNTS
limLog(pMac, LOG1, FL("ChanWidth : %d"), pDot11f->chanWidth);
limLog(pMac, LOG1, FL("reserved: %d"), pDot11f->reserved);
limLog(pMac, LOG1, FL("rxNSS: %d"), pDot11f->rxNSS);
limLog(pMac, LOG1, FL("rxNSS Type: %d"), pDot11f->rxNSSType);
#endif /* DUMP_MGMT_CNTNTS */
}
void limLogQosMapSet(tpAniSirGlobal pMac, tSirQosMapSet *pQosMapSet)
{
tANI_U8 i;
if (pQosMapSet->num_dscp_exceptions > 21)
pQosMapSet->num_dscp_exceptions = 21;
limLog(pMac, LOG1, FL("num of dscp exceptions : %d"),
pQosMapSet->num_dscp_exceptions);
for (i = 0; i < pQosMapSet->num_dscp_exceptions; i++)
{
limLog(pMac, LOG1, FL("dscp value: %d"),
pQosMapSet->dscp_exceptions[i][0]);
limLog(pMac, LOG1, FL("User priority value: %d"),
pQosMapSet->dscp_exceptions[i][1]);
}
for (i = 0; i < 8; i++)
{
limLog(pMac, LOG1, FL("dscp low for up %d: %d"),i,
pQosMapSet->dscp_range[i][0]);
limLog(pMac, LOG1, FL("dscp high for up %d: %d"),i,
pQosMapSet->dscp_range[i][1]);
}
}
tSirRetStatus
PopulateDot11fVHTCaps(tpAniSirGlobal pMac,
tpPESession psessionEntry,
tDot11fIEVHTCaps *pDot11f)
{
tSirRetStatus nStatus;
tANI_U32 nCfgValue=0;
pDot11f->present = 1;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_MAX_MPDU_LENGTH, nCfgValue );
pDot11f->maxMPDULen = (nCfgValue & 0x0003);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
nCfgValue );
pDot11f->supportedChannelWidthSet = (nCfgValue & 0x0003);
nCfgValue = 0;
//With VHT it suffices if we just examine HT
if (psessionEntry)
{
if (psessionEntry->htConfig.ht_rx_ldpc)
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_LDPC_CODING_CAP,
nCfgValue );
pDot11f->ldpcCodingCap = (nCfgValue & 0x0001);
if (psessionEntry->vhtTxChannelWidthSet <
WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) {
pDot11f->shortGI80MHz = 0;
} else {
nCfgValue = 0;
if (psessionEntry->htConfig.ht_sgi)
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SHORT_GI_80MHZ,
nCfgValue );
pDot11f->shortGI80MHz= (nCfgValue & 0x0001);
}
if (psessionEntry->vhtTxChannelWidthSet <
WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) {
pDot11f->shortGI160and80plus80MHz = 0;
} else {
nCfgValue = 0;
if (psessionEntry->htConfig.ht_sgi)
CFG_GET_INT( nStatus, pMac,
WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
nCfgValue );
pDot11f->shortGI160and80plus80MHz = (nCfgValue & 0x0001);
}
nCfgValue = 0;
if (psessionEntry->htConfig.ht_tx_stbc)
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TXSTBC, nCfgValue );
pDot11f->txSTBC = (nCfgValue & 0x0001);
nCfgValue = 0;
if (psessionEntry->htConfig.ht_rx_stbc)
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_RXSTBC, nCfgValue );
pDot11f->rxSTBC = (nCfgValue & 0x0007);
pDot11f->suBeamformeeCap = psessionEntry->txBFIniFeatureEnabled;
if (psessionEntry->txBFIniFeatureEnabled) {
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
nCfgValue );
pDot11f->muBeamformeeCap = (nCfgValue & 0x0001);
} else {
pDot11f->muBeamformeeCap = 0;
}
}
else
{
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_LDPC_CODING_CAP, nCfgValue );
pDot11f->ldpcCodingCap = (nCfgValue & 0x0001);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SHORT_GI_80MHZ, nCfgValue );
pDot11f->shortGI80MHz= (nCfgValue & 0x0001);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
nCfgValue );
pDot11f->shortGI160and80plus80MHz = (nCfgValue & 0x0001);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TXSTBC, nCfgValue );
pDot11f->txSTBC = (nCfgValue & 0x0001);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_RXSTBC, nCfgValue );
pDot11f->rxSTBC = (nCfgValue & 0x0007);
pDot11f->suBeamformeeCap = 0;
pDot11f->muBeamformeeCap = 0;
}
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SU_BEAMFORMER_CAP, nCfgValue );
pDot11f->suBeamFormerCap = (nCfgValue & 0x0001);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED,
nCfgValue );
pDot11f->csnofBeamformerAntSup = (nCfgValue & 0x0007);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS,
nCfgValue );
pDot11f->numSoundingDim = (nCfgValue & 0x0007);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_MU_BEAMFORMER_CAP, nCfgValue );
pDot11f->muBeamformerCap = (nCfgValue & 0x0001);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TXOP_PS, nCfgValue );
pDot11f->vhtTXOPPS = (nCfgValue & 0x0001);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_HTC_VHTC_CAP, nCfgValue );
pDot11f->htcVHTCap = (nCfgValue & 0x0001);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_AMPDU_LEN_EXPONENT, nCfgValue );
pDot11f->maxAMPDULenExp = (nCfgValue & 0x0007);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_LINK_ADAPTATION_CAP, nCfgValue );
pDot11f->vhtLinkAdaptCap = (nCfgValue & 0x0003);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_RX_ANT_PATTERN, nCfgValue );
pDot11f->rxAntPattern = nCfgValue;
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TX_ANT_PATTERN, nCfgValue );
pDot11f->txAntPattern = nCfgValue;
pDot11f->reserved1= 0;
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_RX_MCS_MAP, nCfgValue );
pDot11f->rxMCSMap = (nCfgValue & 0x0000FFFF);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
nCfgValue );
pDot11f->rxHighSupDataRate = (nCfgValue & 0x00001FFF);
pDot11f->reserved2= 0;
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TX_MCS_MAP, nCfgValue );
pDot11f->txMCSMap = (nCfgValue & 0x0000FFFF);
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
nCfgValue );
pDot11f->txSupDataRate = (nCfgValue & 0x00001FFF);
pDot11f->reserved3= 0;
if (!pMac->per_band_chainmask_supp) {
if (psessionEntry) {
if (pMac->lteCoexAntShare &&
(IS_24G_CH(psessionEntry->currentOperChannel))) {
if(!(IS_2X2_CHAIN(psessionEntry->chainMask))) {
pDot11f->txMCSMap |= DISABLE_NSS2_MCS;
pDot11f->rxMCSMap |= DISABLE_NSS2_MCS;
}
}
}
} else {
if (psessionEntry && psessionEntry->vdev_nss == NSS_1x1_MODE) {
pDot11f->txMCSMap |= DISABLE_NSS2_MCS;
pDot11f->rxMCSMap |= DISABLE_NSS2_MCS;
pDot11f->txSupDataRate =
VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
pDot11f->rxHighSupDataRate =
VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
}
}
limLogVHTCap(pMac, pDot11f);
return eSIR_SUCCESS;
}
tSirRetStatus
PopulateDot11fVHTOperation(tpAniSirGlobal pMac,
tpPESession psessionEntry,
tDot11fIEVHTOperation *pDot11f)
{
tSirRetStatus nStatus;
tANI_U32 nCfgValue=0;
pDot11f->present = 1;
if (psessionEntry->htSupportedChannelWidthSet) {
pDot11f->chanWidth = psessionEntry->vhtTxChannelWidthSet;
pDot11f->chanCenterFreqSeg1 = psessionEntry->apCenterChan;
} else {
pDot11f->chanWidth = 0;
}
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2,
nCfgValue );
pDot11f->chanCenterFreqSeg2 = (tANI_U8)nCfgValue;
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_BASIC_MCS_SET,nCfgValue );
pDot11f->basicMCSSet = (tANI_U16)nCfgValue;
limLogVHTOperation(pMac,pDot11f);
return eSIR_SUCCESS;
}
tSirRetStatus
PopulateDot11fVHTExtBssLoad(tpAniSirGlobal pMac,
tDot11fIEVHTExtBssLoad *pDot11f)
{
tSirRetStatus nStatus;
tANI_U32 nCfgValue=0;
pDot11f->present = 1;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT,
nCfgValue );
pDot11f->muMIMOCapStaCount = (tANI_U8)nCfgValue;
nCfgValue = 0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SS_UNDER_UTIL,nCfgValue );
pDot11f->ssUnderUtil = (tANI_U8)nCfgValue;
nCfgValue=0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_40MHZ_UTILIZATION,nCfgValue );
pDot11f->FortyMHzUtil = (tANI_U8)nCfgValue;
nCfgValue=0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_80MHZ_UTILIZATION,nCfgValue );
pDot11f->EightyMHzUtil = (tANI_U8)nCfgValue;
nCfgValue=0;
CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_160MHZ_UTILIZATION,nCfgValue );
pDot11f->EightyMHzUtil = (tANI_U8)nCfgValue;
limLogVHTExtBssLoad(pMac,pDot11f);
return eSIR_SUCCESS;
}
tSirRetStatus
PopulateDot11fExtCap(tpAniSirGlobal pMac,
tANI_BOOLEAN isVHTEnabled,
tDot11fIEExtCap *pDot11f, tpPESession psessionEntry)
{
tANI_U32 val=0;
struct s_ext_cap *p_ext_cap;
pDot11f->present = 1;
if (!psessionEntry) {
limLog(pMac, LOG1, FL("11MC support enabled for non-SAP cases"));
pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN;
} else if (psessionEntry->sap_dot11mc) {
limLog(pMac, LOG1, FL("11MC support enabled"));
pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN;
} else {
if (eLIM_AP_ROLE != psessionEntry->limSystemRole) {
limLog(pMac, LOG1, FL("11MC support enabled"));
pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN;
} else {
limLog(pMac, LOG1, FL("11MC support disabled"));
pDot11f->num_bytes = DOT11F_IE_EXTCAP_MIN_LEN;
}
}
p_ext_cap = (struct s_ext_cap *)pDot11f->bytes;
#ifdef WLAN_FEATURE_11AC
if (isVHTEnabled == eANI_BOOLEAN_TRUE)
{
p_ext_cap->operModeNotification = 1;
}
#endif
if (wlan_cfgGetInt(pMac, WNI_CFG_RTT3_ENABLE, &val) != eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE,
FL("could not retrieve RTT3 Variable from DAT File"));)
return eSIR_FAILURE;
}
if (val)
{
if (!psessionEntry || LIM_IS_STA_ROLE(psessionEntry)) {
p_ext_cap->fine_time_meas_initiator =
(pMac->fine_time_meas_cap & WMI_FW_STA_RTT_INITR) ? 1 : 0;
p_ext_cap->fine_time_meas_responder =
(pMac->fine_time_meas_cap & WMI_FW_STA_RTT_RESPR) ? 1 : 0;
} else if (LIM_IS_AP_ROLE(psessionEntry)) {
p_ext_cap->fine_time_meas_initiator =
(pMac->fine_time_meas_cap & WMI_FW_AP_RTT_INITR) ? 1 : 0;
p_ext_cap->fine_time_meas_responder =
(pMac->fine_time_meas_cap & WMI_FW_AP_RTT_RESPR) ? 1 : 0;
}
}
#ifdef QCA_HT_2040_COEX
if (pMac->roam.configParam.obssEnabled)
{
p_ext_cap->bssCoexistMgmtSupport = 1;
}
#endif
p_ext_cap->extChanSwitch = 1;
if (pDot11f->present)
{
/* Need to compute the num_bytes based on bits set */
pDot11f->num_bytes = lim_compute_ext_cap_ie_length(pDot11f);
}
return eSIR_SUCCESS;
}
tSirRetStatus
PopulateDot11fOperatingMode(tpAniSirGlobal pMac,
tDot11fIEOperatingMode *pDot11f,
tpPESession psessionEntry)
{
pDot11f->present = 1;
pDot11f->chanWidth = psessionEntry->gLimOperatingMode.chanWidth;
pDot11f->rxNSS = psessionEntry->gLimOperatingMode.rxNSS;
pDot11f->rxNSSType = psessionEntry->gLimOperatingMode.rxNSSType;
return eSIR_SUCCESS;
}
#endif
tSirRetStatus
PopulateDot11fHTInfo(tpAniSirGlobal pMac,
tDot11fIEHTInfo *pDot11f,
tpPESession psessionEntry )
{
tANI_U32 nCfgValue, nCfgLen;
tANI_U8 htInfoField1;
tANI_U16 htInfoField2;
tSirRetStatus nSirStatus;
tSirMacHTInfoField1 *pHTInfoField1;
tSirMacHTInfoField2 *pHTInfoField2;
union {
tANI_U16 nCfgValue16;
tSirMacHTInfoField3 infoField3;
}uHTInfoField;
union {
tANI_U16 nCfgValue16;
tSirMacHTInfoField2 infoField2;
}uHTInfoField2={0};
#if 0
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_CURRENT_CHANNEL, nCfgValue );
#endif // TO SUPPORT BT-AMP
if (NULL == psessionEntry)
{
PELOGE(limLog(pMac, LOG1,
FL("Invalid session entry in PopulateDot11fHTInfo()"));)
return eSIR_FAILURE;
}
pDot11f->primaryChannel = psessionEntry->currentOperChannel;
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_INFO_FIELD1, nCfgValue );
htInfoField1 = ( tANI_U8 ) nCfgValue;
pHTInfoField1 = ( tSirMacHTInfoField1* ) &htInfoField1;
pHTInfoField1->rifsMode = psessionEntry->beaconParams.fRIFSMode;
pHTInfoField1->serviceIntervalGranularity = pMac->lim.gHTServiceIntervalGranularity;
if (psessionEntry == NULL)
{
PELOGE(limLog(pMac, LOG1,
FL("Keep the value retrieved from cfg for secondary channel offset and recommended Tx Width set"));)
}
else
{
pHTInfoField1->secondaryChannelOffset = psessionEntry->htSecondaryChannelOffset;
pHTInfoField1->recommendedTxWidthSet = psessionEntry->htRecommendedTxWidthSet;
}
if (psessionEntry && LIM_IS_AP_ROLE(psessionEntry)) {
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_INFO_FIELD2, nCfgValue );
/* This is added for fixing CRs on MDM9K platform - 257951, 259577 */
uHTInfoField2.nCfgValue16 = nCfgValue & 0xFFFF;
uHTInfoField2.infoField2.opMode = psessionEntry->htOperMode;
uHTInfoField2.infoField2.nonGFDevicesPresent =
psessionEntry->beaconParams.llnNonGFCoexist;
/* Added for Obss */
uHTInfoField2.infoField2.obssNonHTStaPresent =
psessionEntry->beaconParams.gHTObssMode;
uHTInfoField2.infoField2.reserved = 0;
} else {
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_INFO_FIELD2, nCfgValue );
htInfoField2 = ( tANI_U16 ) nCfgValue;
pHTInfoField2 = ( tSirMacHTInfoField2* ) &htInfoField2;
pHTInfoField2->opMode = pMac->lim.gHTOperMode;
pHTInfoField2->nonGFDevicesPresent = pMac->lim.gHTNonGFDevicesPresent;
/* Added for Obss */
pHTInfoField2->obssNonHTStaPresent = pMac->lim.gHTObssMode;
pHTInfoField2->reserved = 0;
}
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_INFO_FIELD3, nCfgValue );
uHTInfoField.nCfgValue16 = nCfgValue & 0xFFFF;
uHTInfoField.infoField3.basicSTBCMCS = pMac->lim.gHTSTBCBasicMCS;
uHTInfoField.infoField3.dualCTSProtection = pMac->lim.gHTDualCTSProtection;
uHTInfoField.infoField3.secondaryBeacon = pMac->lim.gHTSecondaryBeacon;
uHTInfoField.infoField3.lsigTXOPProtectionFullSupport = psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport;
uHTInfoField.infoField3.pcoActive = pMac->lim.gHTPCOActive;
uHTInfoField.infoField3.pcoPhase = pMac->lim.gHTPCOPhase;
uHTInfoField.infoField3.reserved = 0;
pDot11f->secondaryChannelOffset = pHTInfoField1->secondaryChannelOffset;
pDot11f->recommendedTxWidthSet = pHTInfoField1->recommendedTxWidthSet;
pDot11f->rifsMode = pHTInfoField1->rifsMode;
pDot11f->controlledAccessOnly = pHTInfoField1->controlledAccessOnly;
pDot11f->serviceIntervalGranularity = pHTInfoField1->serviceIntervalGranularity;
pDot11f->opMode = uHTInfoField2.infoField2.opMode;
pDot11f->nonGFDevicesPresent = uHTInfoField2.infoField2.nonGFDevicesPresent;
pDot11f->obssNonHTStaPresent = uHTInfoField2.infoField2.obssNonHTStaPresent;
pDot11f->reserved = uHTInfoField2.infoField2.reserved;
pDot11f->basicSTBCMCS = uHTInfoField.infoField3.basicSTBCMCS;
pDot11f->dualCTSProtection = uHTInfoField.infoField3.dualCTSProtection;
pDot11f->secondaryBeacon = uHTInfoField.infoField3.secondaryBeacon;
pDot11f->lsigTXOPProtectionFullSupport = uHTInfoField.infoField3.lsigTXOPProtectionFullSupport;
pDot11f->pcoActive = uHTInfoField.infoField3.pcoActive;
pDot11f->pcoPhase = uHTInfoField.infoField3.pcoPhase;
pDot11f->reserved2 = uHTInfoField.infoField3.reserved;
CFG_GET_STR( nSirStatus, pMac, WNI_CFG_BASIC_MCS_SET,
pDot11f->basicMCSSet, nCfgLen,
SIZE_OF_BASIC_MCS_SET );
pDot11f->present = 1;
return eSIR_SUCCESS;
} // End PopulateDot11fHTInfo.
void
PopulateDot11fIBSSParams(tpAniSirGlobal pMac,
tDot11fIEIBSSParams *pDot11f, tpPESession psessionEntry)
{
tANI_U32 val = 0;
if (LIM_IS_IBSS_ROLE(psessionEntry)) {
if(wlan_cfgGetInt(pMac,
WNI_CFG_IBSS_ATIM_WIN_SIZE, &val) != eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE,
FL("could not retrieve IBSS ATIM WIN size"));)
}
pDot11f->present = 1;
// ATIM duration is always set to 0
pDot11f->atim = val;
}
} // End PopulateDot11fIBSSParams.
void
PopulateDot11fPowerCaps(tpAniSirGlobal pMac,
tDot11fIEPowerCaps *pCaps,
tANI_U8 nAssocType,
tpPESession psessionEntry)
{
if (nAssocType == LIM_REASSOC)
{
pCaps->minTxPower = psessionEntry->pLimReAssocReq->powerCap.minTxPower;
pCaps->maxTxPower = psessionEntry->pLimReAssocReq->powerCap.maxTxPower;
}else
{
pCaps->minTxPower = psessionEntry->pLimJoinReq->powerCap.minTxPower;
pCaps->maxTxPower = psessionEntry->pLimJoinReq->powerCap.maxTxPower;
}
pCaps->present = 1;
} // End PopulateDot11fPowerCaps.
tSirRetStatus
PopulateDot11fPowerConstraints(tpAniSirGlobal pMac,
tDot11fIEPowerConstraints *pDot11f)
{
tANI_U32 cfg;
tSirRetStatus nSirStatus;
CFG_GET_INT( nSirStatus, pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, cfg );
pDot11f->localPowerConstraints = ( tANI_U8 )cfg;
pDot11f->present = 1;
return eSIR_SUCCESS;
} // End PopulateDot11fPowerConstraints.
void
PopulateDot11fQOSCapsAp(tpAniSirGlobal pMac,
tDot11fIEQOSCapsAp *pDot11f, tpPESession psessionEntry)
{
pDot11f->count = psessionEntry->gLimEdcaParamSetCount;
pDot11f->reserved = 0;
pDot11f->txopreq = 0;
pDot11f->qreq = 0;
pDot11f->qack = 0;
pDot11f->present = 1;
} // End PopulatedDot11fQOSCaps.
void
PopulateDot11fQOSCapsStation(tpAniSirGlobal pMac,
tDot11fIEQOSCapsStation *pDot11f)
{
tANI_U32 val = 0;
if(wlan_cfgGetInt(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != eSIR_SUCCESS)
PELOGE(limLog(pMac, LOGE, FL("could not retrieve Max SP Length"));)
pDot11f->more_data_ack = 0;
pDot11f->max_sp_length = (tANI_U8)val;
pDot11f->qack = 0;
if (pMac->lim.gUapsdEnable)
{
pDot11f->acbe_uapsd = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcBitmask);
pDot11f->acbk_uapsd = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcBitmask);
pDot11f->acvi_uapsd = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcBitmask);
pDot11f->acvo_uapsd = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcBitmask);
}
pDot11f->present = 1;
} // End PopulatedDot11fQOSCaps.
tSirRetStatus
PopulateDot11fRSN(tpAniSirGlobal pMac,
tpSirRSNie pRsnIe,
tDot11fIERSN *pDot11f)
{
tANI_U32 status;
int idx;
if ( pRsnIe->length )
{
if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_RSN ) ) )
{
status = dot11fUnpackIeRSN( pMac,
pRsnIe->rsnIEdata + idx + 2, //EID, length
pRsnIe->rsnIEdata[ idx + 1 ],
pDot11f );
if ( DOT11F_FAILED( status ) )
{
dot11fLog(pMac, LOGE,
FL("Parse failure in PopulateDot11fRSN (0x%08x)"),
status);
return eSIR_FAILURE;
}
dot11fLog(pMac, LOG2,
FL("dot11fUnpackIeRSN returned 0x%08x in PopulateDot11fRSN"),
status);
}
}
return eSIR_SUCCESS;
} // End PopulateDot11fRSN.
tSirRetStatus PopulateDot11fRSNOpaque( tpAniSirGlobal pMac,
tpSirRSNie pRsnIe,
tDot11fIERSNOpaque *pDot11f )
{
int idx;
if ( pRsnIe->length )
{
if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_RSN ) ) )
{
pDot11f->present = 1;
pDot11f->num_data = pRsnIe->rsnIEdata[ idx + 1 ];
vos_mem_copy( pDot11f->data,
pRsnIe->rsnIEdata + idx + 2, // EID, len
pRsnIe->rsnIEdata[ idx + 1 ] );
}
}
return eSIR_SUCCESS;
} // End PopulateDot11fRSNOpaque.
#if defined(FEATURE_WLAN_WAPI)
tSirRetStatus
PopulateDot11fWAPI(tpAniSirGlobal pMac,
tpSirRSNie pRsnIe,
tDot11fIEWAPI *pDot11f)
{
tANI_U32 status;
int idx;
if ( pRsnIe->length )
{
if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_WAPI ) ) )
{
status = dot11fUnpackIeWAPI( pMac,
pRsnIe->rsnIEdata + idx + 2, //EID, length
pRsnIe->rsnIEdata[ idx + 1 ],
pDot11f );
if ( DOT11F_FAILED( status ) )
{
dot11fLog(pMac, LOGE,
FL("Parse failure in PopulateDot11fWAPI (0x%08x)"),
status);
return eSIR_FAILURE;
}
dot11fLog(pMac, LOG2,
FL("dot11fUnpackIeRSN returned 0x%08x in %s"),
status, __func__);
}
}
return eSIR_SUCCESS;
} // End PopulateDot11fWAPI.
tSirRetStatus PopulateDot11fWAPIOpaque( tpAniSirGlobal pMac,
tpSirRSNie pRsnIe,
tDot11fIEWAPIOpaque *pDot11f )
{
int idx;
if ( pRsnIe->length )
{
if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_WAPI ) ) )
{
pDot11f->present = 1;
pDot11f->num_data = pRsnIe->rsnIEdata[ idx + 1 ];
vos_mem_copy ( pDot11f->data,
pRsnIe->rsnIEdata + idx + 2, // EID, len
pRsnIe->rsnIEdata[ idx + 1 ] );
}
}
return eSIR_SUCCESS;
} // End PopulateDot11fWAPIOpaque.
#endif //defined(FEATURE_WLAN_WAPI)
void
PopulateDot11fSSID(tpAniSirGlobal pMac,
tSirMacSSid *pInternal,
tDot11fIESSID *pDot11f)
{
pDot11f->present = 1;
pDot11f->num_ssid = pInternal->length;
if ( pInternal->length )
{
vos_mem_copy( ( tANI_U8* )pDot11f->ssid, ( tANI_U8* )&pInternal->ssId,
pInternal->length );
}
} // End PopulateDot11fSSID.
tSirRetStatus
PopulateDot11fSSID2(tpAniSirGlobal pMac,
tDot11fIESSID *pDot11f)
{
tANI_U32 nCfg;
tSirRetStatus nSirStatus;
CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SSID, pDot11f->ssid, nCfg, 32 );
pDot11f->num_ssid = ( tANI_U8 )nCfg;
pDot11f->present = 1;
return eSIR_SUCCESS;
} // End PopulateDot11fSSID2.
void
PopulateDot11fSchedule(tSirMacScheduleIE *pSchedule,
tDot11fIESchedule *pDot11f)
{
pDot11f->aggregation = pSchedule->info.aggregation;
pDot11f->tsid = pSchedule->info.tsid;
pDot11f->direction = pSchedule->info.direction;
pDot11f->reserved = pSchedule->info.rsvd;
pDot11f->service_start_time = pSchedule->svcStartTime;
pDot11f->service_interval = pSchedule->svcInterval;
pDot11f->max_service_dur = pSchedule->maxSvcDuration;
pDot11f->spec_interval = pSchedule->specInterval;
pDot11f->present = 1;
} // End PopulateDot11fSchedule.
void
PopulateDot11fSuppChannels(tpAniSirGlobal pMac,
tDot11fIESuppChannels *pDot11f,
tANI_U8 nAssocType,
tpPESession psessionEntry)
{
tANI_U8 i;
tANI_U8 *p;
if (nAssocType == LIM_REASSOC)
{
p = ( tANI_U8* )psessionEntry->pLimReAssocReq->supportedChannels.channelList;
pDot11f->num_bands = psessionEntry->pLimReAssocReq->supportedChannels.numChnl;
}else
{
p = ( tANI_U8* )psessionEntry->pLimJoinReq->supportedChannels.channelList;
pDot11f->num_bands = psessionEntry->pLimJoinReq->supportedChannels.numChnl;
}
for ( i = 0U; i < pDot11f->num_bands; ++i, ++p)
{
pDot11f->bands[i][0] = *p;
pDot11f->bands[i][1] = 1;
}
pDot11f->present = 1;
} // End PopulateDot11fSuppChannels.
tSirRetStatus
PopulateDot11fSuppRates(tpAniSirGlobal pMac,
tANI_U8 nChannelNum,
tDot11fIESuppRates *pDot11f,tpPESession psessionEntry)
{
tSirRetStatus nSirStatus;
tANI_U32 nRates;
tANI_U8 rates[SIR_MAC_MAX_NUMBER_OF_RATES];
/* Use the operational rates present in session entry whenever nChannelNum is set to OPERATIONAL
else use the supported rate set from CFG, which is fixed and does not change dynamically and is used for
sending mgmt frames (lile probe req) which need to go out before any session is present.
*/
if(POPULATE_DOT11F_RATES_OPERATIONAL == nChannelNum )
{
#if 0
CFG_GET_STR( nSirStatus, pMac, WNI_CFG_OPERATIONAL_RATE_SET,
rates, nRates, SIR_MAC_MAX_NUMBER_OF_RATES );
#endif //TO SUPPORT BT-AMP
if(psessionEntry != NULL)
{
nRates = psessionEntry->rateSet.numRates;
vos_mem_copy( rates, psessionEntry->rateSet.rate,
nRates);
}
else
{
dot11fLog(pMac, LOGE,
FL("no session context exists while populating Operational Rate Set"));
nRates = 0;
}
}
else if ( 14 >= nChannelNum )
{
CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SUPPORTED_RATES_11B,
rates, nRates, SIR_MAC_MAX_NUMBER_OF_RATES );
}
else
{
CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SUPPORTED_RATES_11A,
rates, nRates, SIR_MAC_MAX_NUMBER_OF_RATES );
}
if ( 0 != nRates )
{
pDot11f->num_rates = ( tANI_U8 )nRates;
vos_mem_copy( pDot11f->rates, rates, nRates );
pDot11f->present = 1;
}
return eSIR_SUCCESS;
} // End PopulateDot11fSuppRates.
/**
* populate_dot11f_rates_tdls() - populate supported rates and
* extended supported rates IE.
* @p_mac gloabl - header.
* @p_supp_rates - pointer to supported rates IE
* @p_ext_supp_rates - pointer to extended supported rates IE
*
* This function populates the supported rates and extended supported
* rates IE based in the STA capability. If the number of rates
* supported is less than MAX_NUM_SUPPORTED_RATES, only supported rates
* IE is populated.
*
* Return: tSirRetStatus eSIR_SUCCESS on Success and eSIR_FAILURE
* on failure.
*/
tSirRetStatus
populate_dot11f_rates_tdls(tpAniSirGlobal p_mac,
tDot11fIESuppRates *p_supp_rates,
tDot11fIEExtSuppRates *p_ext_supp_rates,
uint8_t curr_oper_channel)
{
tSirMacRateSet temp_rateset;
tSirMacRateSet temp_rateset2;
uint32_t val, i;
uint32_t self_dot11mode = 0;
wlan_cfgGetInt(p_mac, WNI_CFG_DOT11_MODE, &self_dot11mode);
/**
* Include 11b rates only when the device configured in
* auto, 11a/b/g or 11b_only and also if current base
* channel is 5 GHz then no need to advertise the 11b rates.
* If devices move to 2.4GHz off-channel then they can communicate
* in 11g rates i.e. (6, 9, 12, 18, 24, 36 and 54).
*/
limLog(p_mac, LOG1,
FL("Current operating channel %d self_dot11mode = %d"),
curr_oper_channel, self_dot11mode);
if ((curr_oper_channel <= SIR_11B_CHANNEL_END) &&
((self_dot11mode == WNI_CFG_DOT11_MODE_ALL) ||
(self_dot11mode == WNI_CFG_DOT11_MODE_11A) ||
(self_dot11mode == WNI_CFG_DOT11_MODE_11AC) ||
(self_dot11mode == WNI_CFG_DOT11_MODE_11N) ||
(self_dot11mode == WNI_CFG_DOT11_MODE_11G) ||
(self_dot11mode == WNI_CFG_DOT11_MODE_11B))) {
val = WNI_CFG_SUPPORTED_RATES_11B_LEN;
wlan_cfgGetStr(p_mac, WNI_CFG_SUPPORTED_RATES_11B,
(tANI_U8 *)&temp_rateset.rate, &val);
temp_rateset.numRates = (tANI_U8) val;
}
else {
temp_rateset.numRates = 0;
}
/* Include 11a rates when the device configured in non-11b mode */
if (!IS_DOT11_MODE_11B(self_dot11mode)) {
val = WNI_CFG_SUPPORTED_RATES_11A_LEN;
wlan_cfgGetStr(p_mac, WNI_CFG_SUPPORTED_RATES_11A,
(tANI_U8 *)&temp_rateset2.rate, &val);
temp_rateset2.numRates = (tANI_U8) val;
} else {
temp_rateset2.numRates = 0;
}
if ((temp_rateset.numRates + temp_rateset2.numRates) >
SIR_MAC_MAX_NUMBER_OF_RATES) {
limLog(p_mac, LOGP, FL("more than %d rates in CFG"),
SIR_MAC_MAX_NUMBER_OF_RATES);
return eSIR_FAILURE;
}
/**
* copy all rates in temp_rateset,
* there are SIR_MAC_MAX_NUMBER_OF_RATES rates max
*/
for (i = 0; i < temp_rateset2.numRates; i++)
temp_rateset.rate[i + temp_rateset.numRates] =
temp_rateset2.rate[i];
temp_rateset.numRates += temp_rateset2.numRates;
if (temp_rateset.numRates <= MAX_NUM_SUPPORTED_RATES) {
p_supp_rates->num_rates = temp_rateset.numRates;
vos_mem_copy(p_supp_rates->rates, temp_rateset.rate,
p_supp_rates->num_rates);
p_supp_rates->present = 1;
} else { /* Populate extended capability as well */
p_supp_rates->num_rates = MAX_NUM_SUPPORTED_RATES;
vos_mem_copy(p_supp_rates->rates, temp_rateset.rate,
p_supp_rates->num_rates);
p_supp_rates->present = 1;
p_ext_supp_rates->num_rates = temp_rateset.numRates -
MAX_NUM_SUPPORTED_RATES;
vos_mem_copy(p_ext_supp_rates->rates,
(tANI_U8 *)temp_rateset.rate +
MAX_NUM_SUPPORTED_RATES,
p_ext_supp_rates->num_rates);
p_ext_supp_rates->present = 1;
}
return eSIR_SUCCESS;
} /* End populate_dot11f_rates_tdls */
tSirRetStatus
PopulateDot11fTPCReport(tpAniSirGlobal pMac,
tDot11fIETPCReport *pDot11f,
tpPESession psessionEntry)
{
tANI_U16 staid, txPower;
tSirRetStatus nSirStatus;
nSirStatus = limGetMgmtStaid( pMac, &staid, psessionEntry);
if ( eSIR_SUCCESS != nSirStatus )
{
dot11fLog(pMac, LOG1,
FL("Failed to get the STAID in Populate Dot11fTPCReport; limGetMgmtStaid returned status %d"),
nSirStatus);
return eSIR_FAILURE;
}
// FramesToDo: This function was "misplaced" in the move to Gen4_TVM...
// txPower = halGetRateToPwrValue( pMac, staid, pMac->lim.gLimCurrentChannelId, isBeacon );
txPower = 0;
pDot11f->tx_power = ( tANI_U8 )txPower;
pDot11f->link_margin = 0;
pDot11f->present = 1;
return eSIR_SUCCESS;
} // End PopulateDot11fTPCReport.
void PopulateDot11fTSInfo(tSirMacTSInfo *pInfo,
tDot11fFfTSInfo *pDot11f)
{
pDot11f->traffic_type = pInfo->traffic.trafficType;
pDot11f->tsid = pInfo->traffic.tsid;
pDot11f->direction = pInfo->traffic.direction;
pDot11f->access_policy = pInfo->traffic.accessPolicy;
pDot11f->aggregation = pInfo->traffic.aggregation;
pDot11f->psb = pInfo->traffic.psb;
pDot11f->user_priority = pInfo->traffic.userPrio;
pDot11f->tsinfo_ack_pol = pInfo->traffic.ackPolicy;
pDot11f->schedule = pInfo->schedule.schedule;
} // End PopulatedDot11fTSInfo.
void PopulateDot11fWMM(tpAniSirGlobal pMac,
tDot11fIEWMMInfoAp *pInfo,
tDot11fIEWMMParams *pParams,
tDot11fIEWMMCaps *pCaps,
tpPESession psessionEntry)
{
if ( psessionEntry->limWmeEnabled )
{
if (LIM_IS_IBSS_ROLE(psessionEntry)) {
PopulateDot11fWMMInfoAp( pMac, pInfo, psessionEntry );
} else {
PopulateDot11fWMMParams( pMac, pParams, psessionEntry);
if (psessionEntry->limWsmEnabled) {
PopulateDot11fWMMCaps( pCaps );
}
}
}
} // End PopulateDot11fWMM.
void PopulateDot11fWMMCaps(tDot11fIEWMMCaps *pCaps)
{
pCaps->version = SIR_MAC_OUI_VERSION_1;
pCaps->qack = 0;
pCaps->queue_request = 1;
pCaps->txop_request = 0;
pCaps->more_ack = 0;
pCaps->present = 1;
} // End PopulateDot11fWmmCaps.
#ifdef FEATURE_WLAN_ESE
void PopulateDot11fReAssocTspec(tpAniSirGlobal pMac, tDot11fReAssocRequest *pReassoc, tpPESession psessionEntry)
{
tANI_U8 numTspecs = 0, idx;
tTspecInfo *pTspec = NULL;
numTspecs = psessionEntry->pLimReAssocReq->eseTspecInfo.numTspecs;
pTspec = &psessionEntry->pLimReAssocReq->eseTspecInfo.tspec[0];
pReassoc->num_WMMTSPEC = numTspecs;
if (numTspecs) {
for (idx=0; idx<numTspecs; idx++) {
PopulateDot11fWMMTSPEC(&pTspec->tspec, &pReassoc->WMMTSPEC[idx]);
pTspec->tspec.mediumTime = 0;
pTspec++;
}
}
}
#endif
void PopulateDot11fWMMInfoAp(tpAniSirGlobal pMac, tDot11fIEWMMInfoAp *pInfo,
tpPESession psessionEntry)
{
pInfo->version = SIR_MAC_OUI_VERSION_1;
/* WMM Specification 3.1.3, 3.2.3
* An IBSS staion shall always use its default WMM parameters.
*/
if (LIM_IS_IBSS_ROLE(psessionEntry)) {
pInfo->param_set_count = 0;
pInfo->uapsd = 0;
} else {
pInfo->param_set_count = ( 0xf & psessionEntry->gLimEdcaParamSetCount );
if (LIM_IS_AP_ROLE(psessionEntry)) {
pInfo->uapsd = ( 0x1 & psessionEntry->apUapsdEnable );
} else
pInfo->uapsd = ( 0x1 & pMac->lim.gUapsdEnable );
}
pInfo->present = 1;
}
void PopulateDot11fWMMInfoStation(tpAniSirGlobal pMac, tDot11fIEWMMInfoStation *pInfo)
{
tANI_U32 val = 0;
pInfo->version = SIR_MAC_OUI_VERSION_1;
pInfo->acvo_uapsd = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcBitmask);
pInfo->acvi_uapsd = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcBitmask);
pInfo->acbk_uapsd = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcBitmask);
pInfo->acbe_uapsd = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcBitmask);
if(wlan_cfgGetInt(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != eSIR_SUCCESS)
PELOGE(limLog(pMac, LOGE, FL("could not retrieve Max SP Length"));)
pInfo->max_sp_length = (tANI_U8)val;
pInfo->present = 1;
}
void PopulateDot11fWMMInfoStationPerSession(tpAniSirGlobal pMac,
tpPESession psessionEntry,
tDot11fIEWMMInfoStation *pInfo)
{
tANI_U32 val = 0;
pInfo->version = SIR_MAC_OUI_VERSION_1;
pInfo->acvo_uapsd = LIM_UAPSD_GET(ACVO, psessionEntry->gUapsdPerAcBitmask);
pInfo->acvi_uapsd = LIM_UAPSD_GET(ACVI, psessionEntry->gUapsdPerAcBitmask);
pInfo->acbk_uapsd = LIM_UAPSD_GET(ACBK, psessionEntry->gUapsdPerAcBitmask);
pInfo->acbe_uapsd = LIM_UAPSD_GET(ACBE, psessionEntry->gUapsdPerAcBitmask);
if(wlan_cfgGetInt(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != eSIR_SUCCESS)
PELOGE(limLog(pMac, LOGE, FL("could not retrieve Max SP Length"));)
pInfo->max_sp_length = (tANI_U8)val;
pInfo->present = 1;
}
void PopulateDot11fWMMParams(tpAniSirGlobal pMac,
tDot11fIEWMMParams *pParams,
tpPESession psessionEntry)
{
pParams->version = SIR_MAC_OUI_VERSION_1;
if (LIM_IS_AP_ROLE(psessionEntry))
pParams->qosInfo =
(psessionEntry->apUapsdEnable << 7) | ((tANI_U8)(0x0f & psessionEntry->gLimEdcaParamSetCount));
else
pParams->qosInfo =
(pMac->lim.gUapsdEnable << 7) | ((tANI_U8)(0x0f & psessionEntry->gLimEdcaParamSetCount));
// Fill each EDCA parameter set in order: be, bk, vi, vo
pParams->acbe_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[0].aci.aifsn) );
pParams->acbe_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[0].aci.acm );
pParams->acbe_aci = ( 0x3 & SIR_MAC_EDCAACI_BESTEFFORT );
pParams->acbe_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[0].cw.min );
pParams->acbe_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[0].cw.max );
pParams->acbe_txoplimit = psessionEntry->gLimEdcaParamsBC[0].txoplimit;
pParams->acbk_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[1].aci.aifsn) );
pParams->acbk_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[1].aci.acm );
pParams->acbk_aci = ( 0x3 & SIR_MAC_EDCAACI_BACKGROUND );
pParams->acbk_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[1].cw.min );
pParams->acbk_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[1].cw.max );
pParams->acbk_txoplimit = psessionEntry->gLimEdcaParamsBC[1].txoplimit;
if (LIM_IS_AP_ROLE(psessionEntry))
pParams->acvi_aifsn = ( 0xf & psessionEntry->gLimEdcaParamsBC[2].aci.aifsn );
else
pParams->acvi_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[2].aci.aifsn) );
pParams->acvi_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[2].aci.acm );
pParams->acvi_aci = ( 0x3 & SIR_MAC_EDCAACI_VIDEO );
pParams->acvi_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[2].cw.min );
pParams->acvi_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[2].cw.max );
pParams->acvi_txoplimit = psessionEntry->gLimEdcaParamsBC[2].txoplimit;
if (LIM_IS_AP_ROLE(psessionEntry))
pParams->acvo_aifsn = ( 0xf & psessionEntry->gLimEdcaParamsBC[3].aci.aifsn );
else
pParams->acvo_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[3].aci.aifsn) );
pParams->acvo_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[3].aci.acm );
pParams->acvo_aci = ( 0x3 & SIR_MAC_EDCAACI_VOICE );
pParams->acvo_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[3].cw.min );
pParams->acvo_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[3].cw.max );
pParams->acvo_txoplimit = psessionEntry->gLimEdcaParamsBC[3].txoplimit;
pParams->present = 1;
} // End PopulateDot11fWMMParams.
void PopulateDot11fWMMSchedule(tSirMacScheduleIE *pSchedule,
tDot11fIEWMMSchedule *pDot11f)
{
pDot11f->version = 1;
pDot11f->aggregation = pSchedule->info.aggregation;
pDot11f->tsid = pSchedule->info.tsid;
pDot11f->direction = pSchedule->info.direction;
pDot11f->reserved = pSchedule->info.rsvd;
pDot11f->service_start_time = pSchedule->svcStartTime;
pDot11f->service_interval = pSchedule->svcInterval;
pDot11f->max_service_dur = pSchedule->maxSvcDuration;
pDot11f->spec_interval = pSchedule->specInterval;
pDot11f->present = 1;
} // End PopulateDot11fWMMSchedule.
tSirRetStatus
PopulateDot11fWPA(tpAniSirGlobal pMac,
tpSirRSNie pRsnIe,
tDot11fIEWPA *pDot11f)
{
tANI_U32 status;
int idx;
if ( pRsnIe->length )
{
if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_WPA ) ) )
{
status = dot11fUnpackIeWPA( pMac,
pRsnIe->rsnIEdata + idx + 2 + 4, // EID, length, OUI
pRsnIe->rsnIEdata[ idx + 1 ] - 4, // OUI
pDot11f );
if ( DOT11F_FAILED( status ) )
{
dot11fLog(pMac, LOGE,
FL("Parse failure in PopulateDot11fWPA (0x%08x)"),
status);
return eSIR_FAILURE;
}
}
}
return eSIR_SUCCESS;
} // End PopulateDot11fWPA.
tSirRetStatus PopulateDot11fWPAOpaque( tpAniSirGlobal pMac,
tpSirRSNie pRsnIe,
tDot11fIEWPAOpaque *pDot11f )
{
int idx;
if ( pRsnIe->length )
{
if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_WPA ) ) )
{
pDot11f->present = 1;
pDot11f->num_data = pRsnIe->rsnIEdata[ idx + 1 ] - 4;
vos_mem_copy( pDot11f->data,
pRsnIe->rsnIEdata + idx + 2 + 4, // EID, len, OUI
pRsnIe->rsnIEdata[ idx + 1 ] - 4 ); // OUI
}
}
return eSIR_SUCCESS;
} // End PopulateDot11fWPAOpaque.
////////////////////////////////////////////////////////////////////////
tSirRetStatus
sirConvertProbeReqFrame2Struct(tpAniSirGlobal pMac,
tANI_U8 *pFrame,
tANI_U32 nFrame,
tpSirProbeReq pProbeReq)
{
tANI_U32 status;
tDot11fProbeRequest pr;
// Ok, zero-init our [out] parameter,
vos_mem_set( (tANI_U8*)pProbeReq, sizeof(tSirProbeReq), 0);
// delegate to the framesc-generated code,
status = dot11fUnpackProbeRequest(pMac, pFrame, nFrame, &pr);
if ( DOT11F_FAILED( status ) )
{
limLog(pMac, LOGE,
FL("Failed to parse a Probe Request (0x%08x, %d bytes):"),
status, nFrame);
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);)
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog(pMac, LOGW,
FL("Warnings while unpacking a Probe Request (0x%08x, %d bytes):"),
status, nFrame);
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);)
}
// & "transliterate" from a 'tDot11fProbeRequestto' a 'tSirProbeReq'...
if ( ! pr.SSID.present )
{
PELOGW(limLog(pMac, LOGW, FL("Mandatory IE SSID not present!"));)
}
else
{
pProbeReq->ssidPresent = 1;
ConvertSSID( pMac, &pProbeReq->ssId, &pr.SSID );
}
if ( ! pr.SuppRates.present )
{
PELOGW(limLog(pMac, LOGW,
FL("Mandatory IE Supported Rates not present!"));)
return eSIR_FAILURE;
}
else
{
pProbeReq->suppRatesPresent = 1;
ConvertSuppRates( pMac, &pProbeReq->supportedRates, &pr.SuppRates );
}
if ( pr.ExtSuppRates.present )
{
pProbeReq->extendedRatesPresent = 1;
ConvertExtSuppRates( pMac, &pProbeReq->extendedRates, &pr.ExtSuppRates );
}
if ( pr.HTCaps.present )
{
vos_mem_copy( &pProbeReq->HTCaps, &pr.HTCaps, sizeof( tDot11fIEHTCaps ) );
}
if (pr.WscProbeReq.present) {
pProbeReq->wscIePresent = 1;
vos_mem_copy(&pProbeReq->probeReqWscIeInfo, &pr.WscProbeReq,
sizeof(tDot11fIEWscProbeReq));
}
#ifdef WLAN_FEATURE_11AC
if ( pr.VHTCaps.present )
{
vos_mem_copy( &pProbeReq->VHTCaps, &pr.VHTCaps, sizeof( tDot11fIEVHTCaps ) );
}
#endif
if ( pr.P2PProbeReq.present )
{
pProbeReq->p2pIePresent = 1;
}
return eSIR_SUCCESS;
} // End sirConvertProbeReqFrame2Struct.
/**
* sirvalidateandrectifyies checks for the malformed frame.
* The frame would contain fixed IEs of 12 bytes follwed by Variable IEs
* (Tagged elements).
* Every Tagged IE has tag number, tag length and data. Tag length indicates
* the size of data in bytes.
* This function checks for size of Frame recived with the sum of all IEs.
* And also rectifies missing optional fields in IE.
*
* NOTE : Presently this function rectifies RSN capability in RSN IE, can
* extended to rectify other optional fields in other IEs.
*/
tSirRetStatus sirvalidateandrectifyies(tpAniSirGlobal pMac,
tANI_U8 *pMgmtFrame,
tANI_U32 nFrameBytes,
tANI_U32 *nMissingRsnBytes)
{
tANI_U32 length = SIZE_OF_FIXED_PARAM;
tANI_U8 *refFrame;
/* Frame contains atleast one IE */
if (nFrameBytes > (SIZE_OF_FIXED_PARAM + 2)) {
while (length < nFrameBytes) {
/* refFrame points to next IE */
refFrame = pMgmtFrame + length;
length += (tANI_U32)(SIZE_OF_TAG_PARAM_NUM + SIZE_OF_TAG_PARAM_LEN
+ (*(refFrame + SIZE_OF_TAG_PARAM_NUM)));
}
if (length != nFrameBytes) {
/*
* Workaround : Some APs may not include RSN Capability but
* the length of which is included in RSN IE length.
* this may cause in updating RSN Capability with junk value.
* To avoid this, add RSN Capability value with default value.
* Going further we can have such workaround for other IEs
*/
if ((*refFrame == RSNIEID) &&
(length == (nFrameBytes + RSNIE_CAPABILITY_LEN))) {
/* Assume RSN Capability as 00 */
vos_mem_set( ( tANI_U8* ) (pMgmtFrame + (nFrameBytes)),
RSNIE_CAPABILITY_LEN, DEFAULT_RSNIE_CAP_VAL );
*nMissingRsnBytes = RSNIE_CAPABILITY_LEN;
limLog(pMac, LOG1,
FL("Added RSN Capability to the RSNIE as 0x00 0x00"));
return eHAL_STATUS_SUCCESS;
} else {
/*
* Workaround: Some APs may add extra 0x00 padding after IEs.
* Return true to allow these probe response frames proceed.
*/
if (nFrameBytes - length > 0) {
tANI_U32 i;
tANI_BOOLEAN zero_padding = VOS_TRUE;
for (i = length; i < nFrameBytes; i ++) {
if (pMgmtFrame[i-1] != 0x0) {
zero_padding = VOS_FALSE;
break;
}
}
if (zero_padding) {
return eHAL_STATUS_SUCCESS;
}
}
}
return eSIR_FAILURE;
}
}
return eHAL_STATUS_SUCCESS;
}
/**
* sir_copy_hs20_ie() - Update HS 2.0 Information Element.
* @dest: dest HS IE buffer to be updated
* @src: src HS IE buffer
*
* Update HS2.0 IE info from src to dest
*
* Return: void
*/
void sir_copy_hs20_ie(tDot11fIEhs20vendor_ie *dest, tDot11fIEhs20vendor_ie *src)
{
if (src->present) {
adf_os_mem_copy(dest,
src,
sizeof(tDot11fIEhs20vendor_ie) -
sizeof(src->hs_id));
if (src->hs_id_present)
adf_os_mem_copy(&dest->hs_id,
&src->hs_id,
sizeof(src->hs_id));
}
}
#ifdef WLAN_FEATURE_FILS_SK
void populate_dot11f_fils_params(tpAniSirGlobal mac_ctx,
tDot11fAssocRequest *frm,
tpPESession pe_session)
{
struct pe_fils_session *fils_info = pe_session->fils_info;
/* Populate RSN IE with FILS AKM */
PopulateDot11fRSNOpaque(mac_ctx, &(pe_session->pLimJoinReq->rsnIE),
&frm->RSNOpaque);
/* Populate FILS session IE */
frm->fils_session.present = true;
vos_mem_copy(frm->fils_session.session,
fils_info->fils_session, FILS_SESSION_LENGTH);
/* Populate FILS Key confirmation IE */
if (fils_info->key_auth_len) {
frm->fils_key_confirmation.present = true;
frm->fils_key_confirmation.num_key_auth =
fils_info->key_auth_len;
vos_mem_copy(frm->fils_key_confirmation.key_auth,
fils_info->key_auth, fils_info->key_auth_len);
}
}
/**
* update_fils_data: update fils params from beacon/probe response
* @fils_ind: pointer to sir_fils_indication
* @fils_indication: pointer to tDot11fIEfils_indication
*
* Return: None
*/
static void update_fils_data(struct sir_fils_indication *fils_ind,
tDot11fIEfils_indication *fils_indication)
{
uint8_t *data;
data = fils_indication->variable_data;
fils_ind->is_present = true;
fils_ind->is_ip_config_supported =
fils_indication->is_ip_config_supported;
fils_ind->is_fils_sk_auth_supported =
fils_indication->is_fils_sk_auth_supported;
fils_ind->is_fils_sk_auth_pfs_supported =
fils_indication->is_fils_sk_auth_pfs_supported;
fils_ind->is_pk_auth_supported =
fils_indication->is_pk_auth_supported;
if (fils_indication->is_cache_id_present) {
fils_ind->cache_identifier.is_present = true;
vos_mem_copy(fils_ind->cache_identifier.identifier,
data, SIR_CACHE_IDENTIFIER_LEN);
data = data + SIR_CACHE_IDENTIFIER_LEN;
}
if (fils_indication->is_hessid_present) {
fils_ind->hessid.is_present = true;
vos_mem_copy(fils_ind->hessid.hessid,
data, SIR_HESSID_LEN);
data = data + SIR_HESSID_LEN;
}
if (fils_indication->realm_identifiers_cnt) {
fils_ind->realm_identifier.is_present = true;
fils_ind->realm_identifier.realm_cnt =
fils_indication->realm_identifiers_cnt;
vos_mem_copy(fils_ind->realm_identifier.realm,
data, fils_ind->realm_identifier.realm_cnt *
SIR_REALM_LEN);
}
}
/**
* sir_convert_fils_data_to_probersp_struct: update fils params from probe resp
* @probe_resp: pointer to tpSirProbeRespBeacon
* @pr: pointer to tDot11fProbeResponse
*
* Return: None
*/
static void
sir_convert_fils_data_to_probersp_struct(tpSirProbeRespBeacon probe_resp,
tDot11fProbeResponse *pr)
{
if (!pr->fils_indication.present)
return;
update_fils_data(&probe_resp->fils_ind, &pr->fils_indication);
}
#else
static inline void
sir_convert_fils_data_to_probersp_struct(tpSirProbeRespBeacon probe_resp,
tDot11fProbeResponse *pr)
{
}
#endif
tSirRetStatus sirConvertProbeFrame2Struct(tpAniSirGlobal pMac,
tANI_U8 *pFrame,
tANI_U32 nFrame,
tpSirProbeRespBeacon pProbeResp)
{
tANI_U32 status;
tDot11fProbeResponse *pr;
// Ok, zero-init our [out] parameter,
vos_mem_set( ( tANI_U8* )pProbeResp, sizeof(tSirProbeRespBeacon), 0 );
pr = vos_mem_malloc(sizeof(tDot11fProbeResponse));
if ( NULL == pr )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (!HAL_STATUS_SUCCESS(status))
{
limLog(pMac, LOGE, FL("Failed to allocate memory"));
return eSIR_FAILURE;
}
vos_mem_set( ( tANI_U8* )pr, sizeof(tDot11fProbeResponse), 0 );
// delegate to the framesc-generated code,
status = dot11fUnpackProbeResponse( pMac, pFrame, nFrame, pr );
if ( DOT11F_FAILED( status ) )
{
limLog(pMac, LOGE,
FL("Failed to parse a Probe Response (0x%08x, %d bytes):"),
status, nFrame);
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);)
vos_mem_free(pr);
return eSIR_FAILURE;
}
// & "transliterate" from a 'tDot11fProbeResponse' to a 'tSirProbeRespBeacon'...
// Timestamp
vos_mem_copy( ( tANI_U8* )pProbeResp->timeStamp, ( tANI_U8* )&pr->TimeStamp,
sizeof(tSirMacTimeStamp) );
// Beacon Interval
pProbeResp->beaconInterval = pr->BeaconInterval.interval;
// Capabilities
pProbeResp->capabilityInfo.ess = pr->Capabilities.ess;
pProbeResp->capabilityInfo.ibss = pr->Capabilities.ibss;
pProbeResp->capabilityInfo.cfPollable = pr->Capabilities.cfPollable;
pProbeResp->capabilityInfo.cfPollReq = pr->Capabilities.cfPollReq;
pProbeResp->capabilityInfo.privacy = pr->Capabilities.privacy;
pProbeResp->capabilityInfo.shortPreamble = pr->Capabilities.shortPreamble;
pProbeResp->capabilityInfo.pbcc = pr->Capabilities.pbcc;
pProbeResp->capabilityInfo.channelAgility = pr->Capabilities.channelAgility;
pProbeResp->capabilityInfo.spectrumMgt = pr->Capabilities.spectrumMgt;
pProbeResp->capabilityInfo.qos = pr->Capabilities.qos;
pProbeResp->capabilityInfo.shortSlotTime = pr->Capabilities.shortSlotTime;
pProbeResp->capabilityInfo.apsd = pr->Capabilities.apsd;
pProbeResp->capabilityInfo.rrm = pr->Capabilities.rrm;
pProbeResp->capabilityInfo.dsssOfdm = pr->Capabilities.dsssOfdm;
pProbeResp->capabilityInfo.delayedBA = pr->Capabilities.delayedBA;
pProbeResp->capabilityInfo.immediateBA = pr->Capabilities.immediateBA;
if ( ! pr->SSID.present )
{
PELOGW(limLog(pMac, LOGW, FL("Mandatory IE SSID not present!"));)
}
else
{
pProbeResp->ssidPresent = 1;
ConvertSSID( pMac, &pProbeResp->ssId, &pr->SSID );
}
if ( ! pr->SuppRates.present )
{
PELOGW(limLog(pMac, LOGW,
FL("Mandatory IE Supported Rates not present!"));)
}
else
{
pProbeResp->suppRatesPresent = 1;
ConvertSuppRates( pMac, &pProbeResp->supportedRates, &pr->SuppRates );
}
if ( pr->ExtSuppRates.present )
{
pProbeResp->extendedRatesPresent = 1;
ConvertExtSuppRates( pMac, &pProbeResp->extendedRates, &pr->ExtSuppRates );
}
if ( pr->CFParams.present )
{
pProbeResp->cfPresent = 1;
ConvertCFParams( pMac, &pProbeResp->cfParamSet, &pr->CFParams );
}
if ( pr->Country.present )
{
pProbeResp->countryInfoPresent = 1;
ConvertCountry( pMac, &pProbeResp->countryInfoParam, &pr->Country );
}
if ( pr->EDCAParamSet.present )
{
pProbeResp->edcaPresent = 1;
ConvertEDCAParam( pMac, &pProbeResp->edcaParams, &pr->EDCAParamSet );
}
if ( pr->ChanSwitchAnn.present )
{
pProbeResp->channelSwitchPresent = 1;
vos_mem_copy( &pProbeResp->channelSwitchIE, &pr->ChanSwitchAnn,
sizeof(pProbeResp->channelSwitchIE) );
}
if (pr->ext_chan_switch_ann.present) {
pProbeResp->ext_chan_switch_present = 1;
vos_mem_copy(&pProbeResp->ext_chan_switch, &pr->ext_chan_switch_ann,
sizeof(tDot11fIEext_chan_switch_ann));
}
if (pr->SuppOperatingClasses.present) {
pProbeResp->supp_operating_class_present = 1;
vos_mem_copy(&pProbeResp->supp_operating_classes, &pr->SuppOperatingClasses,
sizeof(tDot11fIESuppOperatingClasses));
}
if (pr->sec_chan_offset_ele.present) {
pProbeResp->sec_chan_offset_present = 1;
vos_mem_copy(&pProbeResp->sec_chan_offset, &pr->sec_chan_offset_ele,
sizeof(pProbeResp->sec_chan_offset));
}
if( pr->TPCReport.present)
{
pProbeResp->tpcReportPresent = 1;
vos_mem_copy( &pProbeResp->tpcReport, &pr->TPCReport, sizeof(tDot11fIETPCReport));
}
if( pr->PowerConstraints.present)
{
pProbeResp->powerConstraintPresent = 1;
vos_mem_copy( &pProbeResp->localPowerConstraint, &pr->PowerConstraints,
sizeof(tDot11fIEPowerConstraints));
}
if ( pr->Quiet.present )
{
pProbeResp->quietIEPresent = 1;
vos_mem_copy( &pProbeResp->quietIE, &pr->Quiet, sizeof(tDot11fIEQuiet) );
}
if ( pr->HTCaps.present )
{
vos_mem_copy( &pProbeResp->HTCaps, &pr->HTCaps, sizeof( tDot11fIEHTCaps ) );
}
if ( pr->HTInfo.present )
{
vos_mem_copy( &pProbeResp->HTInfo, &pr->HTInfo, sizeof( tDot11fIEHTInfo ) );
}
if ( pr->DSParams.present )
{
pProbeResp->dsParamsPresent = 1;
pProbeResp->channelNumber = pr->DSParams.curr_channel;
}
else if(pr->HTInfo.present)
{
pProbeResp->channelNumber = pr->HTInfo.primaryChannel;
}
if ( pr->RSNOpaque.present )
{
pProbeResp->rsnPresent = 1;
ConvertRSNOpaque( pMac, &pProbeResp->rsn, &pr->RSNOpaque );
}
if ( pr->WPA.present )
{
pProbeResp->wpaPresent = 1;
ConvertWPA( pMac, &pProbeResp->wpa, &pr->WPA );
}
if ( pr->WMMParams.present )
{
pProbeResp->wmeEdcaPresent = 1;
ConvertWMMParams( pMac, &pProbeResp->edcaParams, &pr->WMMParams );
PELOG1(limLog(pMac, LOG1,
FL("WMM Parameter present in Probe Response Frame!"));
__printWMMParams(pMac, &pr->WMMParams);)
}
if ( pr->WMMInfoAp.present )
{
pProbeResp->wmeInfoPresent = 1;
PELOG1(limLog(pMac, LOG1,
FL("WMM Information Element present in Probe Rsp Frame!"));)
}
if ( pr->WMMCaps.present )
{
pProbeResp->wsmCapablePresent = 1;
}
if ( pr->ERPInfo.present )
{
pProbeResp->erpPresent = 1;
ConvertERPInfo( pMac, &pProbeResp->erpIEInfo, &pr->ERPInfo );
}
#ifdef WLAN_FEATURE_VOWIFI_11R
if (pr->MobilityDomain.present)
{
// MobilityDomain
pProbeResp->mdiePresent = 1;
vos_mem_copy( (tANI_U8 *)&(pProbeResp->mdie[0]), (tANI_U8 *)&(pr->MobilityDomain.MDID),
sizeof(tANI_U16) );
pProbeResp->mdie[2] = ((pr->MobilityDomain.overDSCap << 0) | (pr->MobilityDomain.resourceReqCap << 1));
#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
limLog(pMac, LOG2,
FL("mdie=%02x%02x%02x"), (unsigned int)pProbeResp->mdie[0],
(unsigned int)pProbeResp->mdie[1], (unsigned int)pProbeResp->mdie[2]);
#endif
}
#endif
#if defined FEATURE_WLAN_ESE
if (pr->ESEVersion.present) {
pProbeResp->is_ese_ver_ie_present = 1;
}
if (pr->QBSSLoad.present)
{
vos_mem_copy(&pProbeResp->QBSSLoad, &pr->QBSSLoad, sizeof(tDot11fIEQBSSLoad));
}
#endif
if (pr->P2PProbeRes.present)
{
vos_mem_copy( &pProbeResp->P2PProbeRes, &pr->P2PProbeRes,
sizeof(tDot11fIEP2PProbeRes) );
}
#ifdef WLAN_FEATURE_11AC
if ( pr->VHTCaps.present )
{
vos_mem_copy( &pProbeResp->VHTCaps, &pr->VHTCaps, sizeof( tDot11fIEVHTCaps ) );
}
if ( pr->VHTOperation.present )
{
vos_mem_copy( &pProbeResp->VHTOperation, &pr->VHTOperation, sizeof( tDot11fIEVHTOperation) );
}
if ( pr->VHTExtBssLoad.present )
{
vos_mem_copy( &pProbeResp->VHTExtBssLoad, &pr->VHTExtBssLoad, sizeof( tDot11fIEVHTExtBssLoad) );
}
#endif
pProbeResp->Vendor1IEPresent = pr->Vendor1IE.present;
pProbeResp->Vendor3IEPresent = pr->Vendor3IE.present;
pProbeResp->vendor2_ie.present = pr->vendor2_ie.present;
if (pr->vendor2_ie.present) {
pProbeResp->vendor2_ie.type = pr->vendor2_ie.type;
pProbeResp->vendor2_ie.sub_type = pr->vendor2_ie.sub_type;
}
if (pr->vendor2_ie.VHTCaps.present) {
vos_mem_copy(&pProbeResp->vendor2_ie.VHTCaps,
&pr->vendor2_ie.VHTCaps,
sizeof(tDot11fIEVHTCaps));
}
if (pr->vendor2_ie.VHTOperation.present) {
vos_mem_copy(&pProbeResp->vendor2_ie.VHTOperation,
&pr->vendor2_ie.VHTOperation,
sizeof(tDot11fIEVHTOperation));
}
if (pr->QComVendorIE.present &&
pr->QComVendorIE.Sub20Info.present) {
pProbeResp->vendor_sub20_capability =
pr->QComVendorIE.Sub20Info.capability;
}
#ifdef WLAN_FEATURE_FILS_SK
sir_convert_fils_data_to_probersp_struct(pProbeResp, pr);
#endif
sir_copy_hs20_ie(&pProbeResp->hs20vendor_ie, &pr->hs20vendor_ie);
vos_mem_free(pr);
return eSIR_SUCCESS;
} // End sirConvertProbeFrame2Struct.
tSirRetStatus
sirConvertAssocReqFrame2Struct(tpAniSirGlobal pMac,
tANI_U8 *pFrame,
tANI_U32 nFrame,
tpSirAssocReq pAssocReq)
{
tDot11fAssocRequest *ar;
tANI_U32 status;
ar = vos_mem_malloc(sizeof(tDot11fAssocRequest));
if ( NULL == ar )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (!HAL_STATUS_SUCCESS(status))
{
limLog(pMac, LOGE, FL("Failed to allocate memory"));
return eSIR_FAILURE;
}
// Zero-init our [out] parameter,
vos_mem_set( ( tANI_U8* )pAssocReq, sizeof(tSirAssocReq), 0 );
vos_mem_set( ( tANI_U8* )ar, sizeof( tDot11fAssocRequest ), 0 );
// delegate to the framesc-generated code,
status = dot11fUnpackAssocRequest( pMac, pFrame, nFrame, ar );
if ( DOT11F_FAILED( status ) )
{
limLog(pMac, LOGE,
FL("Failed to parse an Association Request (0x%08x, %d bytes):"),
status, nFrame);
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);)
vos_mem_free(ar);
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog(pMac, LOGW,
FL("Warnings while unpacking an Assoc Req(0x%08x, %d bytes):"),
status, nFrame);
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);)
}
// & "transliterate" from a 'tDot11fAssocRequest' to a 'tSirAssocReq'...
// make sure this is seen as an assoc request
pAssocReq->reassocRequest = 0;
// Capabilities
pAssocReq->capabilityInfo.ess = ar->Capabilities.ess;
pAssocReq->capabilityInfo.ibss = ar->Capabilities.ibss;
pAssocReq->capabilityInfo.cfPollable = ar->Capabilities.cfPollable;
pAssocReq->capabilityInfo.cfPollReq = ar->Capabilities.cfPollReq;
pAssocReq->capabilityInfo.privacy = ar->Capabilities.privacy;
pAssocReq->capabilityInfo.shortPreamble = ar->Capabilities.shortPreamble;
pAssocReq->capabilityInfo.pbcc = ar->Capabilities.pbcc;
pAssocReq->capabilityInfo.channelAgility = ar->Capabilities.channelAgility;
pAssocReq->capabilityInfo.spectrumMgt = ar->Capabilities.spectrumMgt;
pAssocReq->capabilityInfo.qos = ar->Capabilities.qos;
pAssocReq->capabilityInfo.shortSlotTime = ar->Capabilities.shortSlotTime;
pAssocReq->capabilityInfo.apsd = ar->Capabilities.apsd;
pAssocReq->capabilityInfo.rrm = ar->Capabilities.rrm;
pAssocReq->capabilityInfo.dsssOfdm = ar->Capabilities.dsssOfdm;
pAssocReq->capabilityInfo.delayedBA = ar->Capabilities.delayedBA;
pAssocReq->capabilityInfo.immediateBA = ar->Capabilities.immediateBA;
// Listen Interval
pAssocReq->listenInterval = ar->ListenInterval.interval;
// SSID
if ( ar->SSID.present )
{
pAssocReq->ssidPresent = 1;
ConvertSSID( pMac, &pAssocReq->ssId, &ar->SSID );
}
// Supported Rates
if ( ar->SuppRates.present )
{
pAssocReq->suppRatesPresent = 1;
ConvertSuppRates( pMac, &pAssocReq->supportedRates, &ar->SuppRates );
}
// Extended Supported Rates
if ( ar->ExtSuppRates.present )
{
pAssocReq->extendedRatesPresent = 1;
ConvertExtSuppRates( pMac, &pAssocReq->extendedRates, &ar->ExtSuppRates );
}
// QOS Capabilities:
if ( ar->QOSCapsStation.present )
{
pAssocReq->qosCapabilityPresent = 1;
ConvertQOSCapsStation( pMac, &pAssocReq->qosCapability, &ar->QOSCapsStation );
}
// WPA
if ( ar->WPAOpaque.present )
{
pAssocReq->wpaPresent = 1;
ConvertWPAOpaque( pMac, &pAssocReq->wpa, &ar->WPAOpaque );
}
#ifdef FEATURE_WLAN_WAPI
// WAPI
if ( ar->WAPIOpaque.present )
{
pAssocReq->wapiPresent = 1;
ConvertWAPIOpaque( pMac, &pAssocReq->wapi, &ar->WAPIOpaque );
}
#endif
// RSN
if ( ar->RSNOpaque.present )
{
pAssocReq->rsnPresent = 1;
ConvertRSNOpaque( pMac, &pAssocReq->rsn, &ar->RSNOpaque );
}
// WSC IE
if (ar->WscIEOpaque.present)
{
pAssocReq->addIEPresent = 1;
ConvertWscOpaque(pMac, &pAssocReq->addIE, &ar->WscIEOpaque);
}
if(ar->P2PIEOpaque.present)
{
pAssocReq->addIEPresent = 1;
ConvertP2POpaque( pMac, &pAssocReq->addIE, &ar->P2PIEOpaque);
}
#ifdef WLAN_FEATURE_WFD
if(ar->WFDIEOpaque.present)
{
pAssocReq->addIEPresent = 1;
ConvertWFDOpaque( pMac, &pAssocReq->addIE, &ar->WFDIEOpaque);
}
#endif
// Power Capabilities
if ( ar->PowerCaps.present )
{
pAssocReq->powerCapabilityPresent = 1;
ConvertPowerCaps( pMac, &pAssocReq->powerCapability, &ar->PowerCaps );
}
// Supported Channels
if ( ar->SuppChannels.present )
{
pAssocReq->supportedChannelsPresent = 1;
ConvertSuppChannels( pMac, &pAssocReq->supportedChannels, &ar->SuppChannels );
}
if ( ar->HTCaps.present )
{
vos_mem_copy( &pAssocReq->HTCaps, &ar->HTCaps, sizeof( tDot11fIEHTCaps ) );
}
if ( ar->WMMInfoStation.present )
{
pAssocReq->wmeInfoPresent = 1;
vos_mem_copy( &pAssocReq->WMMInfoStation, &ar->WMMInfoStation,
sizeof( tDot11fIEWMMInfoStation ) );
}
if ( ar->WMMCaps.present ) pAssocReq->wsmCapablePresent = 1;
if ( ! pAssocReq->ssidPresent )
{
PELOG2(limLog(pMac, LOG2, FL("Received Assoc without SSID IE."));)
vos_mem_free(ar);
return eSIR_FAILURE;
}
if ( !pAssocReq->suppRatesPresent && !pAssocReq->extendedRatesPresent )
{
PELOG2(limLog(pMac, LOG2, FL("Received Assoc without supp rate IE."));)
vos_mem_free(ar);
return eSIR_FAILURE;
}
#ifdef WLAN_FEATURE_11AC
if ( ar->VHTCaps.present )
{
vos_mem_copy( &pAssocReq->VHTCaps, &ar->VHTCaps, sizeof( tDot11fIEVHTCaps ) );
limLog(pMac, LOGW, FL("Received Assoc Req with VHT Cap"));