blob: 0921d000952385f7d3688be1fd9ca6d6d7d2f2ce [file] [log] [blame]
/*
* Copyright (c) 2012, Code Aurora Forum. 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.
*/
/*
* Airgo Networks, Inc proprietary. All rights reserved.
* This file schBeaconGen.cc contains beacon generation related
* functions
*
* Author: Sandesh Goel
* Date: 02/25/02
* History:-
* Date Modified by Modification Information
* --------------------------------------------------------------------
*
*/
#include "palTypes.h"
#include "wniCfgAp.h"
#include "aniGlobal.h"
#include "sirMacProtDef.h"
#include "limUtils.h"
#include "limApi.h"
#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
#include "halCommonApi.h"
#include "halDataStruct.h"
#endif
#include "halMsgApi.h"
#include "cfgApi.h"
#include "pmmApi.h"
#include "schApi.h"
#include "parserApi.h"
#include "schDebug.h"
//
// March 15, 2006
// Temporarily (maybe for all of Alpha-1), assuming TIM = 0
//
const tANI_U8 P2pOui[] = {0x50, 0x6F, 0x9A, 0x9};
#ifdef ANI_PRODUCT_TYPE_AP
static void
specialBeaconProcessing(tpAniSirGlobal pMac, tANI_U32 beaconSize);
#endif
#if defined(WLAN_SOFTAP_FEATURE) && defined(WLAN_FEATURE_P2P)
tSirRetStatus schGetP2pIeOffset(tANI_U8 *pExtraIe, tANI_U32 extraIeLen, tANI_U16 *pP2pIeOffset)
{
tSirRetStatus status = eSIR_FAILURE;
*pP2pIeOffset = 0;
// Extra IE is not present
if(0 == extraIeLen)
{
return status;
}
// Calculate the P2P IE Offset
do
{
if(*pExtraIe == 0xDD)
{
if(palEqualMemory(NULL, (void *)(pExtraIe+2), &P2pOui, sizeof(P2pOui)))
{
(*pP2pIeOffset)++;
status = eSIR_SUCCESS;
break;
}
}
(*pP2pIeOffset)++;
pExtraIe++;
}while(--extraIeLen > 0);
return status;
}
#endif
tSirRetStatus schAppendAddnIE(tpAniSirGlobal pMac, tpPESession psessionEntry,
tANI_U8 *pFrame, tANI_U32 maxBeaconSize,
tANI_U32 *nBytes)
{
tSirRetStatus status = eSIR_FAILURE;
tANI_U32 present, len;
tANI_U8 addIE[WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN];
if((status = wlan_cfgGetInt(pMac, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
&present)) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("Unable to get WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
return status;
}
if(present)
{
if((status = wlan_cfgGetStrLen(pMac, WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA,
&len)) != eSIR_SUCCESS)
{
limLog(pMac, LOGP,
FL("Unable to get WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA length"));
return status;
}
if(len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len &&
((len + *nBytes) <= maxBeaconSize))
{
if((status = wlan_cfgGetStr(pMac,
WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, &addIE[0], &len))
== eSIR_SUCCESS)
{
#ifdef WLAN_FEATURE_P2P
tANI_U8* pP2pIe = limGetP2pIEPtr(pMac, &addIE[0], len);
if(pP2pIe != NULL)
{
tANI_U8 noaLen = 0;
tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN];
//get NoA attribute stream P2P IE
noaLen = limGetNoaAttrStream(pMac, noaStream, psessionEntry);
if(noaLen)
{
if(noaLen + len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN)
{
vos_mem_copy(&addIE[len], noaStream, noaLen);
len += noaLen;
/* Update IE Len */
pP2pIe[1] += noaLen;
}
else
{
limLog(pMac, LOGE,
FL("Not able to insert NoA because of length constraint"));
}
}
}
#endif
vos_mem_copy(pFrame, &addIE[0], len);
*nBytes = *nBytes + len;
}
}
}
return status;
}
// --------------------------------------------------------------------
/**
* schSetFixedBeaconFields
*
* FUNCTION:
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param None
* @return None
*/
tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEntry)
{
tpAniBeaconStruct pBeacon = (tpAniBeaconStruct)
pMac->sch.schObject.gSchBeaconFrameBegin;
tpSirMacMgmtHdr mac;
tANI_U16 offset;
tANI_U8 *ptr;
tDot11fBeacon1 bcn1;
tDot11fBeacon2 bcn2;
tANI_U32 i, nStatus, nBytes;
tANI_U32 wpsApEnable=0, tmp;
#ifdef WLAN_SOFTAP_FEATURE
tDot11fIEWscProbeRes WscProbeRes;
#ifdef WLAN_FEATURE_P2P
tANI_U8 *pExtraIe = NULL;
tANI_U32 extraIeLen =0;
tANI_U16 extraIeOffset = 0;
tANI_U16 p2pIeOffset = 0;
tSirRetStatus status = eSIR_SUCCESS;
#endif
#endif
PELOG1(schLog(pMac, LOG1, FL("Setting fixed beacon fields\n"));)
/*
* First set the fixed fields
*/
// set the TFP headers
// set the mac header
palZeroMemory( pMac->hHdd, ( tANI_U8*) &pBeacon->macHdr, sizeof( tSirMacMgmtHdr ) );
mac = (tpSirMacMgmtHdr) &pBeacon->macHdr;
mac->fc.type = SIR_MAC_MGMT_FRAME;
mac->fc.subType = SIR_MAC_MGMT_BEACON;
for (i=0; i<6; i++)
mac->da[i] = 0xff;
/* Knocking out Global pMac update */
/* limGetMyMacAddr(pMac, mac->sa); */
/* limGetBssid(pMac, mac->bssId); */
palCopyMemory(pMac->hHdd, mac->sa, psessionEntry->selfMacAddr, sizeof(psessionEntry->selfMacAddr));
palCopyMemory(pMac->hHdd, mac->bssId, psessionEntry->bssId, sizeof (psessionEntry->bssId));
mac->fc.fromDS = 0;
mac->fc.toDS = 0;
/*
* Now set the beacon body
*/
palZeroMemory( pMac->hHdd, ( tANI_U8*) &bcn1, sizeof( bcn1 ) );
// Skip over the timestamp (it'll be updated later).
bcn1.BeaconInterval.interval = pMac->sch.schObject.gSchBeaconInterval;
PopulateDot11fCapabilities( pMac, &bcn1.Capabilities, psessionEntry );
if (psessionEntry->ssidHidden)
{
bcn1.SSID.present = 1; //rest of the fileds are 0 for hidden ssid
}
else
{
PopulateDot11fSSID( pMac, &psessionEntry->ssId, &bcn1.SSID );
}
PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, &bcn1.SuppRates,psessionEntry);
PopulateDot11fDSParams( pMac, &bcn1.DSParams, psessionEntry->currentOperChannel, psessionEntry);
PopulateDot11fIBSSParams( pMac, &bcn1.IBSSParams,psessionEntry);
offset = sizeof( tAniBeaconStruct );
ptr = pMac->sch.schObject.gSchBeaconFrameBegin + offset;
#ifdef WLAN_SOFTAP_FEATURE
if((psessionEntry->limSystemRole == eLIM_AP_ROLE)
&& (psessionEntry->proxyProbeRspEn))
{
/* Initialize the default IE bitmap to zero */
palZeroMemory( pMac->hHdd, ( tANI_U8* )&(psessionEntry->DefProbeRspIeBitmap), (sizeof( tANI_U32 ) * 8));
/* Initialize the default IE bitmap to zero */
palZeroMemory( pMac->hHdd, ( tANI_U8* )&(psessionEntry->probeRespFrame), sizeof(psessionEntry->probeRespFrame));
/* Can be efficiently updated whenever new IE added in Probe response in future */
limUpdateProbeRspTemplateIeBitmapBeacon1(pMac,&bcn1,&psessionEntry->DefProbeRspIeBitmap[0],
&psessionEntry->probeRespFrame);
}
#endif
nStatus = dot11fPackBeacon1( pMac, &bcn1, ptr,
SCH_MAX_BEACON_SIZE - offset,
&nBytes );
if ( DOT11F_FAILED( nStatus ) )
{
schLog( pMac, LOGE, FL("Failed to packed a tDot11fBeacon1 (0x%0"
"8x.).\n"), nStatus );
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( nStatus ) )
{
schLog( pMac, LOGE, FL("There were warnings while packing a tDo"
"t11fBeacon1 (0x%08x.).\n"), nStatus );
}
/*changed to correct beacon corruption */
palZeroMemory( pMac->hHdd, ( tANI_U8*) &bcn2, sizeof( bcn2 ) );
pMac->sch.schObject.gSchBeaconOffsetBegin = offset + ( tANI_U16 )nBytes;
schLog( pMac, LOG1, FL("Initialized beacon begin, offset %d\n"), offset );
/*
* Initialize the 'new' fields at the end of the beacon
*/
PopulateDot11fCountry( pMac, &bcn2.Country, psessionEntry);
if(bcn1.Capabilities.qos)
{
PopulateDot11fEDCAParamSet( pMac, &bcn2.EDCAParamSet, psessionEntry);
}
if(psessionEntry->lim11hEnable)
{
PopulateDot11fPowerConstraints( pMac, &bcn2.PowerConstraints );
PopulateDot11fTPCReport( pMac, &bcn2.TPCReport, psessionEntry);
}
#ifdef ANI_PRODUCT_TYPE_AP
if( psessionEntry->lim11hEnable && (eLIM_QUIET_RUNNING == psessionEntry->gLimSpecMgmt.quietState))
{
PopulateDot11fQuiet( pMac, &bcn2.Quiet );
}
/* If 11h is enabled, and AP is in the state of changing either the
* primary channel, or both primary & secondary channel, and the
* channel switch count is still being decremented, then AP shall
* populate the 802.11h channel switch IE in its Beacons and Probe
* Responses.
*/
if ( (psessionEntry->lim11hEnable) &&
(psessionEntry->gLimChannelSwitch.switchCount != 0) &&
(psessionEntry->gLimSpecMgmt.dot11hChanSwState == eLIM_11H_CHANSW_RUNNING))
{
PopulateDot11fChanSwitchAnn( pMac, &bcn2.ChanSwitchAnn, psessionEntry );
PopulateDot11fExtChanSwitchAnn(pMac, &bcn2.ExtChanSwitchAnn, psessionEntry );
}
#endif
if (psessionEntry->dot11mode != WNI_CFG_DOT11_MODE_11B)
PopulateDot11fERPInfo( pMac, &bcn2.ERPInfo, psessionEntry );
if(psessionEntry->htCapability)
{
PopulateDot11fHTCaps( pMac, psessionEntry, &bcn2.HTCaps );
#ifdef WLAN_SOFTAP_FEATURE
PopulateDot11fHTInfo( pMac, &bcn2.HTInfo, psessionEntry );
#else
PopulateDot11fHTInfo( pMac, &bcn2.HTInfo );
#endif
}
#ifdef WLAN_FEATURE_11AC
if(psessionEntry->vhtCapability)
{
limLog( pMac, LOGW, FL("Populate VHT IEs in Beacon\n"));
PopulateDot11fVHTCaps( pMac, &bcn2.VHTCaps );
PopulateDot11fVHTOperation( pMac, &bcn2.VHTOperation);
// we do not support multi users yet
//PopulateDot11fVHTExtBssLoad( pMac, &bcn2.VHTExtBssLoad);
}
#endif
PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
&bcn2.ExtSuppRates, psessionEntry );
if( psessionEntry->pLimStartBssReq != NULL )
{
PopulateDot11fWPA( pMac, &psessionEntry->pLimStartBssReq->rsnIE,
&bcn2.WPA );
PopulateDot11fRSN( pMac, &psessionEntry->pLimStartBssReq->rsnIE,
&bcn2.RSN );
}
if(psessionEntry->limWmeEnabled)
{
PopulateDot11fWMM( pMac, &bcn2.WMMInfoAp, &bcn2.WMMParams, &bcn2.WMMCaps, psessionEntry);
}
#ifdef WLAN_SOFTAP_FEATURE
if(psessionEntry->limSystemRole == eLIM_AP_ROLE)
{
if(psessionEntry->wps_state != SAP_WPS_DISABLED)
{
PopulateDot11fBeaconWPSIEs( pMac, &bcn2.WscBeacon, psessionEntry);
}
}
else
{
#endif
if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS)
limLog(pMac, LOGP,"Failed to cfg get id %d\n", WNI_CFG_WPS_ENABLE );
wpsApEnable = tmp & WNI_CFG_WPS_ENABLE_AP;
if (wpsApEnable)
{
PopulateDot11fWsc(pMac, &bcn2.WscBeacon);
}
if (pMac->lim.wscIeInfo.wscEnrollmentState == eLIM_WSC_ENROLL_BEGIN)
{
PopulateDot11fWscRegistrarInfo(pMac, &bcn2.WscBeacon);
pMac->lim.wscIeInfo.wscEnrollmentState = eLIM_WSC_ENROLL_IN_PROGRESS;
}
if (pMac->lim.wscIeInfo.wscEnrollmentState == eLIM_WSC_ENROLL_END)
{
DePopulateDot11fWscRegistrarInfo(pMac, &bcn2.WscBeacon);
pMac->lim.wscIeInfo.wscEnrollmentState = eLIM_WSC_ENROLL_NOOP;
}
#ifdef WLAN_SOFTAP_FEATURE
}
#endif
#ifdef WLAN_SOFTAP_FEATURE
if((psessionEntry->limSystemRole == eLIM_AP_ROLE)
&& (psessionEntry->proxyProbeRspEn))
{
/* Can be efficiently updated whenever new IE added in Probe response in future */
limUpdateProbeRspTemplateIeBitmapBeacon2(pMac,&bcn2,&psessionEntry->DefProbeRspIeBitmap[0],
&psessionEntry->probeRespFrame);
/* update probe response WPS IE instead of beacon WPS IE
* */
if(psessionEntry->wps_state != SAP_WPS_DISABLED)
{
if(psessionEntry->APWPSIEs.SirWPSProbeRspIE.FieldPresent)
{
PopulateDot11fProbeResWPSIEs(pMac, &WscProbeRes, psessionEntry);
}
else
{
WscProbeRes.present = 0;
}
if(WscProbeRes.present)
{
SetProbeRspIeBitmap(&psessionEntry->DefProbeRspIeBitmap[0],SIR_MAC_WPA_EID);
palCopyMemory(pMac->hHdd,
(void *)&psessionEntry->probeRespFrame.WscProbeRes,
(void *)&WscProbeRes,
sizeof(WscProbeRes));
}
}
}
#endif
nStatus = dot11fPackBeacon2( pMac, &bcn2,
pMac->sch.schObject.gSchBeaconFrameEnd,
SCH_MAX_BEACON_SIZE, &nBytes );
if ( DOT11F_FAILED( nStatus ) )
{
schLog( pMac, LOGE, FL("Failed to packed a tDot11fBeacon2 (0x%0"
"8x.).\n"), nStatus );
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( nStatus ) )
{
schLog( pMac, LOGE, FL("There were warnings while packing a tDo"
"t11fBeacon2 (0x%08x.).\n"), nStatus );
}
#if defined(WLAN_SOFTAP_FEATURE) && defined(WLAN_FEATURE_P2P)
pExtraIe = pMac->sch.schObject.gSchBeaconFrameEnd + nBytes;
extraIeOffset = nBytes;
#endif
//TODO: Append additional IE here.
schAppendAddnIE(pMac, psessionEntry,
pMac->sch.schObject.gSchBeaconFrameEnd + nBytes,
SCH_MAX_BEACON_SIZE, &nBytes);
pMac->sch.schObject.gSchBeaconOffsetEnd = ( tANI_U16 )nBytes;
#if defined(WLAN_SOFTAP_FEATURE) && defined(WLAN_FEATURE_P2P)
extraIeLen = nBytes - extraIeOffset;
//Get the p2p Ie Offset
status = schGetP2pIeOffset(pExtraIe, extraIeLen, &p2pIeOffset);
if(eSIR_SUCCESS == status)
{
//Update the P2P Ie Offset
pMac->sch.schObject.p2pIeOffset =
pMac->sch.schObject.gSchBeaconOffsetBegin + TIM_IE_SIZE +
extraIeOffset + p2pIeOffset;
}
else
{
pMac->sch.schObject.p2pIeOffset = 0;
}
#endif
schLog( pMac, LOG1, FL("Initialized beacon end, offset %d\n"),
pMac->sch.schObject.gSchBeaconOffsetEnd );
pMac->sch.schObject.fBeaconChanged = 1;
return eSIR_SUCCESS;
}
#ifdef WLAN_SOFTAP_FEATURE
void limUpdateProbeRspTemplateIeBitmapBeacon1(tpAniSirGlobal pMac,
tDot11fBeacon1* beacon1,
tANI_U32* DefProbeRspIeBitmap,
tDot11fProbeResponse* prb_rsp)
{
prb_rsp->BeaconInterval = beacon1->BeaconInterval;
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->Capabilities,
(void *)&beacon1->Capabilities,
sizeof(beacon1->Capabilities));
/* SSID */
if(beacon1->SSID.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_SSID_EID);
/* populating it , because probe response has to go with SSID even in hidden case */
PopulateDot11fSSID2( pMac, &prb_rsp->SSID );
}
/* supported rates */
if(beacon1->SuppRates.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_RATESET_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->SuppRates,
(void *)&beacon1->SuppRates,
sizeof(beacon1->SuppRates));
}
/* DS Parameter set */
if(beacon1->DSParams.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_DS_PARAM_SET_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->DSParams,
(void *)&beacon1->DSParams,
sizeof(beacon1->DSParams));
}
/* IBSS params will not be present in the Beacons transmitted by AP */
}
void limUpdateProbeRspTemplateIeBitmapBeacon2(tpAniSirGlobal pMac,
tDot11fBeacon2* beacon2,
tANI_U32* DefProbeRspIeBitmap,
tDot11fProbeResponse* prb_rsp)
{
/* IBSS parameter set - will not be present in probe response tx by AP */
/* country */
if(beacon2->Country.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_COUNTRY_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->Country,
(void *)&beacon2->Country,
sizeof(beacon2->Country));
}
/* Power constraint */
if(beacon2->PowerConstraints.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_PWR_CONSTRAINT_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->PowerConstraints,
(void *)&beacon2->PowerConstraints,
sizeof(beacon2->PowerConstraints));
}
/* Channel Switch Annoouncement SIR_MAC_CHNL_SWITCH_ANN_EID */
if(beacon2->ChanSwitchAnn.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_CHNL_SWITCH_ANN_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->ChanSwitchAnn,
(void *)&beacon2->ChanSwitchAnn,
sizeof(beacon2->ChanSwitchAnn));
}
/* ERP information */
if(beacon2->ERPInfo.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_ERP_INFO_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->ERPInfo,
(void *)&beacon2->ERPInfo,
sizeof(beacon2->ERPInfo));
}
/* Extended supported rates */
if(beacon2->ExtSuppRates.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_EXTENDED_RATE_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->ExtSuppRates,
(void *)&beacon2->ExtSuppRates,
sizeof(beacon2->ExtSuppRates));
}
/* WPA */
if(beacon2->WPA.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_WPA_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->WPA,
(void *)&beacon2->WPA,
sizeof(beacon2->WPA));
}
/* RSN */
if(beacon2->RSN.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_RSN_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->RSN,
(void *)&beacon2->RSN,
sizeof(beacon2->RSN));
}
/*
// BSS load
if(beacon2->QBSSLoad.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_QBSS_LOAD_EID);
}
*/
/* EDCA Parameter set */
if(beacon2->EDCAParamSet.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_EDCA_PARAM_SET_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->EDCAParamSet,
(void *)&beacon2->EDCAParamSet,
sizeof(beacon2->EDCAParamSet));
}
/* Vendor specific - currently no vendor specific IEs added */
/* Requested IEs - currently we are not processing this will be added later */
//HT capability IE
if(beacon2->HTCaps.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_HT_CAPABILITIES_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->HTCaps,
(void *)&beacon2->HTCaps,
sizeof(beacon2->HTCaps));
}
// HT Info IE
if(beacon2->HTInfo.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_HT_INFO_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->HTInfo,
(void *)&beacon2->HTInfo,
sizeof(beacon2->HTInfo));
}
#ifdef WLAN_FEATURE_11AC
if(beacon2->VHTCaps.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_VHT_CAPABILITIES_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->VHTCaps,
(void *)&beacon2->VHTCaps,
sizeof(beacon2->VHTCaps));
}
if(beacon2->VHTOperation.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_VHT_OPERATION_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->VHTOperation,
(void *)&beacon2->VHTOperation,
sizeof(beacon2->VHTOperation));
}
if(beacon2->VHTExtBssLoad.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_VHT_EXT_BSS_LOAD_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->VHTExtBssLoad,
(void *)&beacon2->VHTExtBssLoad,
sizeof(beacon2->VHTExtBssLoad));
}
#endif
//WMM IE
if(beacon2->WMMParams.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_WPA_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->WMMParams,
(void *)&beacon2->WMMParams,
sizeof(beacon2->WMMParams));
}
//WMM capability - most of the case won't be present
if(beacon2->WMMCaps.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_WPA_EID);
palCopyMemory(pMac->hHdd,(void *)&prb_rsp->WMMCaps,
(void *)&beacon2->WMMCaps,
sizeof(beacon2->WMMCaps));
}
}
void SetProbeRspIeBitmap(tANI_U32* IeBitmap,tANI_U32 pos)
{
tANI_U32 index,temp;
index = pos >> 5;
if(index >= 8 )
{
return;
}
temp = IeBitmap[index];
temp |= 1 << (pos & 0x1F);
IeBitmap[index] = temp;
}
#endif
#ifdef ANI_PRODUCT_TYPE_AP
//----------------------------
/**
* @function : schUpdateCfpParam
* @brief : Generate the CFP Parameter Set
*
* @param : pMac - tpAniSirGlobal
* ptr - Pointer to the BeaconFrame
* pbeaconSize - The beaconSize
*
* @return : Return the Updated Ptrlocation
*/
static tANI_U8 *
__schUpdateCfpParam(tpAniSirGlobal pMac, tANI_U8 *ptr, tANI_U32 *pbeaconSize)
{
tANI_U32 val;
*ptr++ = SIR_MAC_CF_PARAM_SET_EID;
*ptr++ = SIR_MAC_CF_PARAM_SET_EID_MIN;
wlan_cfgGetInt(pMac, WNI_CFG_CFP_PERIOD, &val);
if (++pMac->sch.schObject.gSchCFPCount == val)
pMac->sch.schObject.gSchCFPCount = 0;
*ptr++ = pMac->sch.schObject.gSchCFPCount;
*ptr++ = (tANI_U8)val;
wlan_cfgGetInt(pMac, WNI_CFG_CFP_MAX_DURATION, &val);
pMac->sch.schObject.gSchCFPMaxDuration = (tANI_U8)val;
sirStoreU16(ptr, (tANI_U16)val);
ptr += 2;
if (pMac->sch.schObject.gSchCFPCount == 0)
pMac->sch.schObject.gSchCFPDurRemaining = pMac->sch.schObject.gSchCFPMaxDuration;
else if (pMac->sch.schObject.gSchCFPDurRemaining > pMac->sch.schObject.gSchBeaconInterval)
pMac->sch.schObject.gSchCFPDurRemaining -= pMac->sch.schObject.gSchBeaconInterval;
else
pMac->sch.schObject.gSchCFPDurRemaining = 0;
sirStoreU16(ptr, pMac->sch.schObject.gSchCFPDurRemaining);
ptr += 2;
(*pbeaconSize) += 2 + SIR_MAC_CF_PARAM_SET_EID_MIN;
return ptr;
}
#endif
// --------------------------------------------------------------------
/**
* writeBeaconToMemory
*
* FUNCTION:
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param None
* @param size Size of the beacon to write to memory
* @param length Length field of the beacon to write to memory
* @return None
*/
void writeBeaconToMemory(tpAniSirGlobal pMac, tANI_U16 size, tANI_U16 length, tpPESession psessionEntry)
{
tANI_U16 i;
tpAniBeaconStruct pBeacon;
// copy end of beacon only if length > 0
if (length > 0)
{
for (i=0; i < pMac->sch.schObject.gSchBeaconOffsetEnd; i++)
pMac->sch.schObject.gSchBeaconFrameBegin[size++] = pMac->sch.schObject.gSchBeaconFrameEnd[i];
}
// Update the beacon length
pBeacon = (tpAniBeaconStruct) pMac->sch.schObject.gSchBeaconFrameBegin;
// Do not include the beaconLength indicator itself
if (length == 0)
{
pBeacon->beaconLength = 0;
// Dont copy entire beacon, Copy length field alone
size = 4;
}
else
pBeacon->beaconLength = (tANI_U32) size - sizeof( tANI_U32 );
// write size bytes from gSchBeaconFrameBegin
PELOG2(schLog(pMac, LOG2, FL("Beacon size - %d bytes\n"), size);)
PELOG2(sirDumpBuf(pMac, SIR_SCH_MODULE_ID, LOG2, pMac->sch.schObject.gSchBeaconFrameBegin, size);)
if (! pMac->sch.schObject.fBeaconChanged)
return;
pMac->sch.gSchGenBeacon = 1;
if (pMac->sch.gSchGenBeacon)
{
pMac->sch.gSchBeaconsSent++;
//
// Copy beacon data to SoftMAC shared memory...
// Do this by sending a message to HAL
//
size = (size + 3) & (~3);
if( eSIR_SUCCESS != schSendBeaconReq( pMac, pMac->sch.schObject.gSchBeaconFrameBegin, size , psessionEntry))
PELOGE(schLog(pMac, LOGE, FL("schSendBeaconReq() returned an error (zsize %d)\n"), size);)
else
{
pMac->sch.gSchBeaconsWritten++;
}
}
pMac->sch.schObject.fBeaconChanged = 0;
}
// --------------------------------------------------------------------
/**
* @function: SchProcessPreBeaconInd
*
* @brief : Process the PreBeacon Indication from the Lim
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param : pMac - tpAniSirGlobal
*
* @return None
*/
void
schProcessPreBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
{
tpBeaconGenParams pMsg = (tpBeaconGenParams)limMsg->bodyptr;
tANI_U32 beaconSize = pMac->sch.schObject.gSchBeaconOffsetBegin;
tpPESession psessionEntry;
tANI_U8 sessionId;
if((psessionEntry = peFindSessionByBssid(pMac,pMsg->bssId, &sessionId))== NULL)
{
PELOGE(schLog(pMac, LOGE, FL("session lookup fails\n"));)
goto end;
}
// If SME is not in normal mode, no need to generate beacon
if (psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE)
{
PELOGE(schLog(pMac, LOG1, FL("PreBeaconInd received in invalid state: %d\n"), psessionEntry->limSmeState);)
goto end;
}
switch(psessionEntry->limSystemRole){
case eLIM_STA_IN_IBSS_ROLE:
case eLIM_BT_AMP_AP_ROLE:
case eLIM_BT_AMP_STA_ROLE:
// generate IBSS parameter set
if(psessionEntry->statypeForBss == STA_ENTRY_SELF)
writeBeaconToMemory(pMac, (tANI_U16) beaconSize, (tANI_U16)beaconSize, psessionEntry);
else
PELOGE(schLog(pMac, LOGE, FL("can not send beacon for PEER session entry\n"));)
break;
#ifdef WLAN_SOFTAP_FEATURE
case eLIM_AP_ROLE:{
tANI_U8 *ptr = &pMac->sch.schObject.gSchBeaconFrameBegin[pMac->sch.schObject.gSchBeaconOffsetBegin];
tANI_U16 timLength = 0;
if(psessionEntry->statypeForBss == STA_ENTRY_SELF){
pmmGenerateTIM(pMac, &ptr, &timLength, psessionEntry->dtimPeriod);
beaconSize += 2 + timLength;
writeBeaconToMemory(pMac, (tANI_U16) beaconSize, (tANI_U16)beaconSize, psessionEntry);
}
else
PELOGE(schLog(pMac, LOGE, FL("can not send beacon for PEER session entry\n"));)
}
break;
#endif
#ifdef ANI_PRODUCT_TYPE_AP
case eLIM_AP_ROLE:
{
tANI_U8 *ptr = &pMac->sch.schObject.gSchBeaconFrameBegin[pMac->sch.schObject.gSchBeaconOffsetBegin];
tANI_U16 timLength = 0;
if (pMac->sch.schObject.gSchCFPEnabled)
ptr = __schUpdateCfpParam( pMac, ptr, &beaconSize);
// generate TIM
pmmGenerateTIM(pMac, &ptr, &timLength);
beaconSize += 2 + timLength;
/**
* Safe to call this each time.
* Based on the requirement for updating the
* fixed beacon fields, this routine will
* appropriately update the fixed fields
*/
specialBeaconProcessing(pMac, beaconSize);
writeBeaconToMemory(pMac, beaconSize, beaconSize, psessionEntry);
pmmHandleTimBasedDisassociation( pMac, psessionEntry );
}
break;
#endif
default:
PELOGE(schLog(pMac, LOGE, FL("Error-PE has Receive PreBeconGenIndication when System is in %d role"),
psessionEntry->limSystemRole);)
}
end:
palFreeMemory(pMac->hHdd, (void*)pMsg);
}
/**-------------------------------------------------------------
\fn specialBeaconProcessing
\brief To add/update channel switch IE/ Quiet IE in beacons.
And also to resume transmission and measurement after
switching the channel.
\param pMac
\param beaconSize Size of the beacon
\return NONE
--------------------------------------------------------------*/
#ifdef ANI_PRODUCT_TYPE_AP
static void
specialBeaconProcessing( tpAniSirGlobal pMac, tANI_U32 beaconSize)
{
tpPESession psessionEntry = &pMac->lim.gpSession[0]; //TBD-RAJESH HOW TO GET sessionEntry?????
tANI_BOOLEAN fBeaconChanged = eANI_BOOLEAN_FALSE;
fBeaconChanged = limUpdateQuietIEInBeacons( pMac );
if((pMac->lim.wscIeInfo.wscEnrollmentState == eLIM_WSC_ENROLL_BEGIN) ||
(pMac->lim.wscIeInfo.wscEnrollmentState == eLIM_WSC_ENROLL_END))
{
fBeaconChanged = eANI_BOOLEAN_TRUE;
}
/*******************************
* Processing Channel Switch IE
*******************************/
if (pMac->lim.gLimSpecMgmt.dot11hChanSwState == eLIM_11H_CHANSW_RUNNING)
{
fBeaconChanged = eANI_BOOLEAN_TRUE;
#if 0
// If the station doesn't support 11h or have link monitoring enabled,
// AP has to send disassoc frame to indicate station before going
// to new channel. Otherwise station wont connect to AP in new channel.
if (pMac->lim.gLimChannelSwitch.switchCount == 1)
{
if((pMac->lim.gLimChannelSwitch.state
== eLIM_CHANNEL_SWITCH_PRIMARY_ONLY) ||
(pMac->lim.gLimChannelSwitch.state
== eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY))
{
tSirMacAddr bcAddr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
limSendDisassocMgmtFrame(pMac,
eSIR_MAC_DISASSOC_LEAVING_BSS_REASON,
bcAddr);
}
}
#endif
if (pMac->lim.gLimChannelSwitch.switchCount == 0)
{
/* length is set to 0, so that no beacon is transmitted without channel switch IE
* before switching to new channel */
pMac->sch.schObject.fBeaconChanged = 1;
writeBeaconToMemory(pMac, beaconSize, 0, psessionEntry);
schSetFixedBeaconFields(pMac,psessionEntry);
PELOG3(limLog(pMac, LOG3, FL("Channel switch state = %d\n"), pMac->lim.gLimChannelSwitch.state);)
switch(pMac->lim.gLimChannelSwitch.state)
{
case eLIM_CHANNEL_SWITCH_PRIMARY_ONLY:
limSwitchPrimaryChannel(pMac, pMac->lim.gLimChannelSwitch.primaryChannel);
break;
case eLIM_CHANNEL_SWITCH_SECONDARY_ONLY:
limSwitchPrimarySecondaryChannel(pMac, psessionEntry,
psessionEntry->currentOperChannel,
pMac->lim.gLimChannelSwitch.secondarySubBand);
break;
case eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY:
limSwitchPrimarySecondaryChannel(pMac, psessionEntry,
pMac->lim.gLimChannelSwitch.primaryChannel,
pMac->lim.gLimChannelSwitch.secondarySubBand);
break;
case eLIM_CHANNEL_SWITCH_IDLE:
PELOGE(schLog(pMac, LOGE, FL("incorrect state - CHANNEL_SWITCH_IDLE\n"));)
break;
default:
break;
}
pMac->lim.gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE;
limSendSmeRsp(pMac, eWNI_SME_SWITCH_CHL_RSP, eSIR_SME_SUCCESS);
limFrameTransmissionControl(pMac, eLIM_TX_BSS_BUT_BEACON, eLIM_RESUME_TX);
/* Flag to indicate 11h channel switch is done. */
pMac->lim.gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_INIT;
pMac->lim.gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
LIM_SET_RADAR_DETECTED(pMac, eANI_BOOLEAN_FALSE);
if (pMac->lim.gpLimMeasReq)
limReEnableLearnMode(pMac);
return;
}
}
if (fBeaconChanged)
{
schSetFixedBeaconFields(pMac,psessionEntry);
if (pMac->lim.gLimChannelSwitch.switchCount > 0)
pMac->lim.gLimChannelSwitch.switchCount--;
}
}
#endif