| /* |
| * 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 schBeaconGen.cc contains beacon generation related |
| * functions |
| * |
| * Author: Sandesh Goel |
| * Date: 02/25/02 |
| * History:- |
| * Date Modified by Modification Information |
| * -------------------------------------------------------------------- |
| * |
| */ |
| |
| #include "palTypes.h" |
| #include "wni_cfg.h" |
| #include "aniGlobal.h" |
| #include "sirMacProtDef.h" |
| |
| #include "limUtils.h" |
| #include "limApi.h" |
| |
| |
| #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}; |
| |
| |
| 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 ( vos_mem_compare ( (void *)(pExtraIe+2), &P2pOui, sizeof(P2pOui) ) ) |
| { |
| status = eSIR_SUCCESS; |
| break; |
| } |
| } |
| |
| (*pP2pIeOffset)++; |
| pExtraIe++; |
| }while(--extraIeLen > 0); |
| |
| return status; |
| } |
| |
| tSirRetStatus schAppendAddnIE(tpAniSirGlobal pMac, tpPESession psessionEntry, |
| tANI_U8 *pFrame, tANI_U32 maxBeaconSize, |
| tANI_U32 *nBytes, uint8_t *addn_ie, |
| uint16_t addn_ielen) |
| { |
| tSirRetStatus status = eSIR_FAILURE; |
| tANI_U8 addIE[WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN]; |
| |
| if(addn_ielen <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && addn_ielen && |
| ((addn_ielen + *nBytes) <= maxBeaconSize)) |
| { |
| |
| vos_mem_copy(&addIE[0], addn_ie, addn_ielen); |
| |
| { |
| tANI_U8* pP2pIe = limGetP2pIEPtr(pMac, &addIE[0], addn_ielen); |
| if ((pP2pIe != NULL) && !pMac->beacon_offload) |
| { |
| 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 + addn_ielen) <= |
| WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) { |
| vos_mem_copy(&addIE[addn_ielen], noaStream, noaLen); |
| addn_ielen += noaLen; |
| /* Update IE Len */ |
| pP2pIe[1] += noaLen; |
| } |
| else |
| { |
| schLog(pMac, LOGE, |
| FL("Not able to insert NoA because of addn_ielength constraint")); |
| } |
| } |
| } |
| if(addn_ielen <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) |
| { |
| vos_mem_copy(pFrame, &addIE[0], addn_ielen); |
| *nBytes = *nBytes + addn_ielen; |
| } |
| else |
| { |
| schLog(pMac, LOGW, FL("Not able to insert because of" |
| " addn_ielength constraint %d"), addn_ielen); |
| } |
| } |
| } |
| |
| return status; |
| } |
| |
| // -------------------------------------------------------------------- |
| /** |
| * schSetFixedBeaconFields |
| * |
| * FUNCTION: |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param None |
| * @return None |
| */ |
| |
| tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEntry) |
| { |
| tpAniBeaconStruct pBeacon = (tpAniBeaconStruct) |
| psessionEntry->pSchBeaconFrameBegin; |
| tpSirMacMgmtHdr mac; |
| tANI_U16 offset; |
| tANI_U8 *ptr; |
| tDot11fBeacon1 *pBcn1; |
| tDot11fBeacon2 *pBcn2; |
| tANI_U32 i, nStatus, nBytes; |
| tANI_U32 wpsApEnable=0, tmp; |
| tDot11fIEWscProbeRes *pWscProbeRes; |
| tANI_U8 *pExtraIe = NULL; |
| tANI_U32 extraIeLen =0; |
| tANI_U16 extraIeOffset = 0; |
| tANI_U16 p2pIeOffset = 0; |
| tSirRetStatus status = eSIR_SUCCESS; |
| tANI_BOOLEAN isVHTEnabled = eANI_BOOLEAN_FALSE; |
| uint16_t addn_ielen = 0; |
| uint8_t *addn_ie = NULL; |
| tDot11fIEExtCap extracted_extcap; |
| bool extcap_present = true, addnie_present = false; |
| |
| pBcn1 = vos_mem_malloc(sizeof(tDot11fBeacon1)); |
| if ( NULL == pBcn1 ) |
| { |
| schLog(pMac, LOGE, FL("Failed to allocate memory") ); |
| return eSIR_FAILURE; |
| } |
| |
| pBcn2 = vos_mem_malloc(sizeof(tDot11fBeacon2)); |
| if ( NULL == pBcn2 ) |
| { |
| schLog(pMac, LOGE, FL("Failed to allocate memory") ); |
| vos_mem_free(pBcn1); |
| return eSIR_FAILURE; |
| } |
| |
| pWscProbeRes = vos_mem_malloc(sizeof(tDot11fIEWscProbeRes)); |
| if ( NULL == pWscProbeRes ) |
| { |
| schLog(pMac, LOGE, FL("Failed to allocate memory") ); |
| vos_mem_free(pBcn1); |
| vos_mem_free(pBcn2); |
| return eSIR_FAILURE; |
| } |
| |
| PELOG1(schLog(pMac, LOG1, FL("Setting fixed beacon fields"));) |
| |
| /* |
| * First set the fixed fields |
| */ |
| |
| // set the TFP headers |
| |
| // set the mac header |
| vos_mem_set(( tANI_U8*) &pBeacon->macHdr, sizeof( tSirMacMgmtHdr ),0); |
| 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; |
| |
| vos_mem_copy(mac->sa, psessionEntry->selfMacAddr, sizeof(psessionEntry->selfMacAddr)); |
| vos_mem_copy(mac->bssId, psessionEntry->bssId, sizeof (psessionEntry->bssId)); |
| |
| mac->fc.fromDS = 0; |
| mac->fc.toDS = 0; |
| |
| /* |
| * Now set the beacon body |
| */ |
| |
| vos_mem_set(( tANI_U8*) pBcn1, sizeof( tDot11fBeacon1 ), 0); |
| |
| /* Skip over the time stamp (it'll be updated later). */ |
| |
| pBcn1->BeaconInterval.interval = psessionEntry->beaconParams.beaconInterval; |
| PopulateDot11fCapabilities( pMac, &pBcn1->Capabilities, psessionEntry ); |
| if (psessionEntry->ssidHidden) |
| { |
| pBcn1->SSID.present = 1; /* Rest of the fields are 0 for hidden ssid */ |
| if((psessionEntry->ssId.length) && |
| (psessionEntry->ssidHidden == eHIDDEN_SSID_ZERO_CONTENTS)) |
| pBcn1->SSID.num_ssid = psessionEntry->ssId.length; |
| } |
| else |
| { |
| PopulateDot11fSSID( pMac, &psessionEntry->ssId, &pBcn1->SSID ); |
| } |
| |
| |
| PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, &pBcn1->SuppRates,psessionEntry); |
| PopulateDot11fDSParams( pMac, &pBcn1->DSParams, psessionEntry->currentOperChannel, psessionEntry); |
| PopulateDot11fIBSSParams( pMac, &pBcn1->IBSSParams,psessionEntry); |
| |
| offset = sizeof( tAniBeaconStruct ); |
| ptr = psessionEntry->pSchBeaconFrameBegin + offset; |
| |
| if (LIM_IS_AP_ROLE(psessionEntry)) { |
| /* Initialize the default IE bitmap to zero */ |
| vos_mem_set(( tANI_U8* )&(psessionEntry->DefProbeRspIeBitmap), (sizeof( tANI_U32 ) * 8), 0); |
| |
| /* Initialize the default IE bitmap to zero */ |
| vos_mem_set(( tANI_U8* )&(psessionEntry->probeRespFrame), |
| sizeof(psessionEntry->probeRespFrame), 0); |
| |
| if (vos_is_probe_rsp_offload_enabled()) { |
| /* Can be efficiently updated whenever new IE added |
| * in Probe response in future |
| */ |
| if (limUpdateProbeRspTemplateIeBitmapBeacon1(pMac, pBcn1, |
| psessionEntry) != eSIR_SUCCESS) { |
| schLog(pMac, LOGE, |
| FL("Failed to build ProbeRsp template")); |
| } |
| } |
| } |
| |
| nStatus = dot11fPackBeacon1( pMac, pBcn1, ptr, |
| SCH_MAX_BEACON_SIZE - offset, |
| &nBytes ); |
| if ( DOT11F_FAILED( nStatus ) ) |
| { |
| schLog( pMac, LOGE, FL("Failed to packed a tDot11fBeacon1 (0x%0" |
| "8x.)."), nStatus ); |
| vos_mem_free(pBcn1); |
| vos_mem_free(pBcn2); |
| vos_mem_free(pWscProbeRes); |
| return eSIR_FAILURE; |
| } |
| else if ( DOT11F_WARNED( nStatus ) ) |
| { |
| schLog( pMac, LOGE, FL("There were warnings while packing a tDo" |
| "t11fBeacon1 (0x%08x.)."), nStatus ); |
| } |
| /*changed to correct beacon corruption */ |
| vos_mem_set(( tANI_U8*) pBcn2, sizeof( tDot11fBeacon2 ), 0); |
| psessionEntry->schBeaconOffsetBegin = offset + ( tANI_U16 )nBytes; |
| schLog( pMac, LOG1, FL("Initialized beacon begin, offset %d"), offset ); |
| |
| /* |
| * Initialize the 'new' fields at the end of the beacon |
| */ |
| |
| if ((psessionEntry->limSystemRole == eLIM_AP_ROLE) && |
| psessionEntry->dfsIncludeChanSwIe == VOS_TRUE) { |
| if (!CHAN_HOP_ALL_BANDS_ENABLE || |
| psessionEntry->lim_non_ecsa_cap_num == 0) |
| populate_dot_11_f_ext_chann_switch_ann( |
| pMac, &pBcn2->ext_chan_switch_ann, psessionEntry); |
| else |
| PopulateDot11fChanSwitchAnn(pMac, &pBcn2->ChanSwitchAnn, |
| psessionEntry); |
| } |
| |
| populate_dot11_supp_operating_classes(pMac, &pBcn2->SuppOperatingClasses, |
| psessionEntry); |
| PopulateDot11fCountry( pMac, &pBcn2->Country, psessionEntry); |
| if(pBcn1->Capabilities.qos) |
| { |
| PopulateDot11fEDCAParamSet( pMac, &pBcn2->EDCAParamSet, psessionEntry); |
| } |
| |
| if(psessionEntry->lim11hEnable) |
| { |
| PopulateDot11fPowerConstraints( pMac, &pBcn2->PowerConstraints ); |
| PopulateDot11fTPCReport( pMac, &pBcn2->TPCReport, psessionEntry); |
| |
| /* Need to insert channel switch announcement here */ |
| if ((LIM_IS_AP_ROLE(psessionEntry) || |
| LIM_IS_P2P_DEVICE_GO(psessionEntry)) && |
| psessionEntry->dfsIncludeChanSwIe == VOS_TRUE) { |
| /* Channel switch announcement only if radar is detected |
| * and SAP has instructed to announce channel switch IEs |
| * in beacon and probe responses |
| */ |
| if (!CHAN_HOP_ALL_BANDS_ENABLE) |
| PopulateDot11fChanSwitchAnn(pMac, &pBcn2->ChanSwitchAnn, |
| psessionEntry); |
| |
| #ifdef WLAN_FEATURE_11AC |
| /* TODO: If in 11AC mode, wider bw channel switch announcement needs |
| * to be called |
| */ |
| /*PopulateDot11fWiderBWChanSwitchAnn(pMac, &pBcn2->WiderBWChanSwitchAnn, |
| psessionEntry);*/ |
| #endif |
| /* |
| * Populate the Channel Switch Wrapper Element if |
| * SAP operates in 40/80 Mhz Channel Width. |
| */ |
| if (VOS_TRUE == psessionEntry->dfsIncludeChanWrapperIe) |
| { |
| PopulateDot11fChanSwitchWrapper(pMac, |
| &pBcn2->ChannelSwitchWrapper, |
| psessionEntry); |
| } |
| } |
| } |
| |
| #ifdef FEATURE_AP_MCC_CH_AVOIDANCE |
| /* populate proprietary IE for MDM device operating in AP-MCC */ |
| populate_dot11f_avoid_channel_ie(pMac, &pBcn2->QComVendorIE, psessionEntry); |
| #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ |
| |
| populate_dot11f_sub_20_channel_width_ie( |
| pMac, &pBcn2->QComVendorIE, psessionEntry); |
| |
| if (psessionEntry->dot11mode != WNI_CFG_DOT11_MODE_11B) |
| PopulateDot11fERPInfo( pMac, &pBcn2->ERPInfo, psessionEntry ); |
| |
| if(psessionEntry->htCapability) |
| { |
| PopulateDot11fHTCaps( pMac,psessionEntry, &pBcn2->HTCaps ); |
| PopulateDot11fHTInfo( pMac, &pBcn2->HTInfo, psessionEntry ); |
| } |
| #ifdef WLAN_FEATURE_11AC |
| if(psessionEntry->vhtCapability) |
| { |
| schLog( pMac, LOGW, FL("Populate VHT IEs in Beacon")); |
| PopulateDot11fVHTCaps( pMac, psessionEntry, &pBcn2->VHTCaps ); |
| PopulateDot11fVHTOperation( pMac, psessionEntry, &pBcn2->VHTOperation); |
| isVHTEnabled = eANI_BOOLEAN_TRUE; |
| // we do not support multi users yet |
| //PopulateDot11fVHTExtBssLoad( pMac, &bcn2.VHTExtBssLoad); |
| if(psessionEntry->gLimOperatingMode.present) |
| PopulateDot11fOperatingMode( pMac, &pBcn2->OperatingMode, psessionEntry ); |
| } |
| #endif |
| |
| if (psessionEntry->limSystemRole != eLIM_STA_IN_IBSS_ROLE) |
| PopulateDot11fExtCap(pMac, isVHTEnabled, &pBcn2->ExtCap, psessionEntry); |
| |
| PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, |
| &pBcn2->ExtSuppRates, psessionEntry ); |
| |
| if( psessionEntry->pLimStartBssReq != NULL ) |
| { |
| PopulateDot11fWPA( pMac, &psessionEntry->pLimStartBssReq->rsnIE, |
| &pBcn2->WPA ); |
| PopulateDot11fRSNOpaque( pMac, &psessionEntry->pLimStartBssReq->rsnIE, |
| &pBcn2->RSNOpaque ); |
| #ifdef SAP_AUTH_OFFLOAD |
| /* Software AP Authentication Offload feature |
| * only support WPA2-PSK AES and we |
| * need to update RSNIE for beacon |
| */ |
| sap_auth_offload_update_rsn_ie(pMac, &pBcn2->RSNOpaque); |
| #endif |
| } |
| |
| if(psessionEntry->limWmeEnabled) |
| { |
| PopulateDot11fWMM( pMac, &pBcn2->WMMInfoAp, &pBcn2->WMMParams, &pBcn2->WMMCaps, psessionEntry); |
| } |
| if (LIM_IS_AP_ROLE(psessionEntry)) { |
| if(psessionEntry->wps_state != SAP_WPS_DISABLED) |
| { |
| PopulateDot11fBeaconWPSIEs( pMac, &pBcn2->WscBeacon, psessionEntry); |
| } |
| } |
| else |
| { |
| if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS) |
| schLog(pMac, LOGP,"Failed to cfg get id %d", WNI_CFG_WPS_ENABLE ); |
| |
| wpsApEnable = tmp & WNI_CFG_WPS_ENABLE_AP; |
| |
| if (wpsApEnable) |
| { |
| PopulateDot11fWsc(pMac, &pBcn2->WscBeacon); |
| } |
| |
| if (pMac->lim.wscIeInfo.wscEnrollmentState == eLIM_WSC_ENROLL_BEGIN) |
| { |
| PopulateDot11fWscRegistrarInfo(pMac, &pBcn2->WscBeacon); |
| pMac->lim.wscIeInfo.wscEnrollmentState = eLIM_WSC_ENROLL_IN_PROGRESS; |
| } |
| |
| if (pMac->lim.wscIeInfo.wscEnrollmentState == eLIM_WSC_ENROLL_END) |
| { |
| DePopulateDot11fWscRegistrarInfo(pMac, &pBcn2->WscBeacon); |
| pMac->lim.wscIeInfo.wscEnrollmentState = eLIM_WSC_ENROLL_NOOP; |
| } |
| } |
| |
| if (LIM_IS_AP_ROLE(psessionEntry)) { |
| if (vos_is_probe_rsp_offload_enabled()) { |
| /* Can be efficiently updated whenever new IE added in Probe response in future */ |
| limUpdateProbeRspTemplateIeBitmapBeacon2(pMac,pBcn2,&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, pWscProbeRes, psessionEntry); |
| } |
| else |
| { |
| pWscProbeRes->present = 0; |
| } |
| if(pWscProbeRes->present) |
| { |
| SetProbeRspIeBitmap(&psessionEntry->DefProbeRspIeBitmap[0],SIR_MAC_WPA_EID); |
| vos_mem_copy((void *)&psessionEntry->probeRespFrame.WscProbeRes, |
| (void *)pWscProbeRes, |
| sizeof(tDot11fIEWscProbeRes)); |
| } |
| } |
| |
| } |
| |
| addnie_present = (psessionEntry->addIeParams.probeRespBCNDataLen != 0); |
| if (addnie_present) { |
| addn_ielen = psessionEntry->addIeParams.probeRespBCNDataLen; |
| addn_ie = vos_mem_malloc(addn_ielen); |
| if (!addn_ie) { |
| schLog(pMac, LOGE, FL("addn_ie malloc failed")); |
| vos_mem_free(pBcn1); |
| vos_mem_free(pBcn2); |
| vos_mem_free(pWscProbeRes); |
| return eSIR_MEM_ALLOC_FAILED; |
| } |
| vos_mem_copy(addn_ie, psessionEntry->addIeParams.probeRespBCNData_buff, |
| addn_ielen); |
| |
| vos_mem_set((uint8_t *)&extracted_extcap, sizeof(tDot11fIEExtCap), 0); |
| status = lim_strip_extcap_update_struct(pMac, addn_ie, &addn_ielen, |
| &extracted_extcap); |
| if (eSIR_SUCCESS != status) { |
| extcap_present = false; |
| schLog(pMac, LOG1, FL("extcap not extracted")); |
| } |
| /* merge extcap IE */ |
| if (extcap_present && |
| psessionEntry->limSystemRole != eLIM_STA_IN_IBSS_ROLE) |
| lim_merge_extcap_struct(&pBcn2->ExtCap, &extracted_extcap, true); |
| |
| } |
| |
| nStatus = dot11fPackBeacon2( pMac, pBcn2, |
| psessionEntry->pSchBeaconFrameEnd, |
| SCH_MAX_BEACON_SIZE, &nBytes ); |
| if ( DOT11F_FAILED( nStatus ) ) |
| { |
| schLog( pMac, LOGE, FL("Failed to packed a tDot11fBeacon2 (0x%0" |
| "8x.)."), nStatus ); |
| vos_mem_free(pBcn1); |
| vos_mem_free(pBcn2); |
| vos_mem_free(pWscProbeRes); |
| vos_mem_free(addn_ie); |
| return eSIR_FAILURE; |
| } |
| else if ( DOT11F_WARNED( nStatus ) ) |
| { |
| schLog( pMac, LOGE, FL("There were warnings while packing a tDo" |
| "t11fBeacon2 (0x%08x.)."), nStatus ); |
| } |
| |
| pExtraIe = psessionEntry->pSchBeaconFrameEnd + nBytes; |
| extraIeOffset = nBytes; |
| |
| if (addn_ielen > 0) |
| schAppendAddnIE(pMac, psessionEntry, |
| psessionEntry->pSchBeaconFrameEnd + nBytes, |
| SCH_MAX_BEACON_SIZE, &nBytes, addn_ie, addn_ielen); |
| |
| psessionEntry->schBeaconOffsetEnd = ( tANI_U16 )nBytes; |
| |
| 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 = |
| psessionEntry->schBeaconOffsetBegin + TIM_IE_SIZE + |
| extraIeOffset + p2pIeOffset; |
| } |
| else |
| { |
| pMac->sch.schObject.p2pIeOffset = 0; |
| } |
| |
| schLog( pMac, LOG1, FL("Initialized beacon end, offset %d"), |
| psessionEntry->schBeaconOffsetEnd ); |
| |
| pMac->sch.schObject.fBeaconChanged = 1; |
| vos_mem_free(pBcn1); |
| vos_mem_free(pBcn2); |
| vos_mem_free(pWscProbeRes); |
| vos_mem_free(addn_ie); |
| return eSIR_SUCCESS; |
| } |
| |
| tSirRetStatus limUpdateProbeRspTemplateIeBitmapBeacon1(tpAniSirGlobal pMac, |
| tDot11fBeacon1* beacon1, |
| tpPESession psessionEntry) |
| { |
| tANI_U32* DefProbeRspIeBitmap; |
| tDot11fProbeResponse* prb_rsp; |
| |
| if (!psessionEntry) { |
| schLog(pMac, LOGE, FL("PESession is null!")); |
| return eSIR_FAILURE; |
| } |
| |
| DefProbeRspIeBitmap = &psessionEntry->DefProbeRspIeBitmap[0]; |
| prb_rsp = &psessionEntry->probeRespFrame; |
| |
| prb_rsp->BeaconInterval = beacon1->BeaconInterval; |
| vos_mem_copy((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 |
| */ |
| PopulateDot11fSSID(pMac, &psessionEntry->ssId, &prb_rsp->SSID); |
| } |
| /* supported rates */ |
| if(beacon1->SuppRates.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_RATESET_EID); |
| vos_mem_copy((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); |
| vos_mem_copy((void *)&prb_rsp->DSParams, (void *)&beacon1->DSParams, |
| sizeof(beacon1->DSParams)); |
| |
| } |
| |
| /* IBSS params will not be present in the Beacons transmitted by AP */ |
| |
| return eSIR_SUCCESS; |
| } |
| |
| 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); |
| vos_mem_copy((void *)&prb_rsp->Country, (void *)&beacon2->Country, |
| sizeof(beacon2->Country)); |
| |
| } |
| /* Power constraint */ |
| if(beacon2->PowerConstraints.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_PWR_CONSTRAINT_EID); |
| vos_mem_copy((void *)&prb_rsp->PowerConstraints, (void *)&beacon2->PowerConstraints, |
| sizeof(beacon2->PowerConstraints)); |
| |
| } |
| /* Channel Switch Announcement SIR_MAC_CHNL_SWITCH_ANN_EID */ |
| if(beacon2->ChanSwitchAnn.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_CHNL_SWITCH_ANN_EID); |
| vos_mem_copy((void *)&prb_rsp->ChanSwitchAnn, (void *)&beacon2->ChanSwitchAnn, |
| sizeof(beacon2->ChanSwitchAnn)); |
| |
| } |
| |
| /* EXT Channel Switch Announcement CHNL_EXTENDED_SWITCH_ANN_EID*/ |
| if (beacon2->ext_chan_switch_ann.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap, |
| SIR_MAC_CHNL_EXTENDED_SWITCH_ANN_EID); |
| vos_mem_copy((void *)&prb_rsp->ext_chan_switch_ann, |
| (void *)&beacon2->ext_chan_switch_ann, |
| sizeof(beacon2->ext_chan_switch_ann)); |
| } |
| /* Supported operating class */ |
| if(beacon2->SuppOperatingClasses.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_OPERATING_CLASS_EID); |
| vos_mem_copy((void *)&prb_rsp->SuppOperatingClasses, |
| (void *)&beacon2->SuppOperatingClasses, |
| sizeof(beacon2->SuppOperatingClasses)); |
| } |
| |
| if(beacon2->QComVendorIE.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap, SIR_MAC_QCOM_VENDOR_EID); |
| vos_mem_copy((void *)&prb_rsp->QComVendorIE, |
| (void *)&beacon2->QComVendorIE, |
| sizeof(beacon2->QComVendorIE)); |
| } |
| |
| /* ERP information */ |
| if(beacon2->ERPInfo.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_ERP_INFO_EID); |
| vos_mem_copy((void *)&prb_rsp->ERPInfo, (void *)&beacon2->ERPInfo, |
| sizeof(beacon2->ERPInfo)); |
| |
| } |
| /* Extended supported rates */ |
| if(beacon2->ExtSuppRates.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_EXTENDED_RATE_EID); |
| vos_mem_copy((void *)&prb_rsp->ExtSuppRates, (void *)&beacon2->ExtSuppRates, |
| sizeof(beacon2->ExtSuppRates)); |
| |
| } |
| |
| /* WPA */ |
| if(beacon2->WPA.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_WPA_EID); |
| vos_mem_copy((void *)&prb_rsp->WPA, (void *)&beacon2->WPA, |
| sizeof(beacon2->WPA)); |
| |
| } |
| |
| /* RSN */ |
| if(beacon2->RSNOpaque.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_RSN_EID); |
| vos_mem_copy((void *)&prb_rsp->RSNOpaque, (void *)&beacon2->RSNOpaque, |
| sizeof(beacon2->RSNOpaque)); |
| } |
| |
| /* EDCA Parameter set */ |
| if(beacon2->EDCAParamSet.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_EDCA_PARAM_SET_EID); |
| vos_mem_copy((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); |
| vos_mem_copy((void *)&prb_rsp->HTCaps, (void *)&beacon2->HTCaps, |
| sizeof(beacon2->HTCaps)); |
| } |
| // HT Info IE |
| if(beacon2->HTInfo.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_HT_INFO_EID); |
| vos_mem_copy((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); |
| vos_mem_copy((void *)&prb_rsp->VHTCaps, (void *)&beacon2->VHTCaps, |
| sizeof(beacon2->VHTCaps)); |
| } |
| if(beacon2->VHTOperation.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_VHT_OPERATION_EID); |
| vos_mem_copy((void *)&prb_rsp->VHTOperation, (void *)&beacon2->VHTOperation, |
| sizeof(beacon2->VHTOperation)); |
| } |
| if(beacon2->VHTExtBssLoad.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_VHT_EXT_BSS_LOAD_EID); |
| vos_mem_copy((void *)&prb_rsp->VHTExtBssLoad, (void *)&beacon2->VHTExtBssLoad, |
| sizeof(beacon2->VHTExtBssLoad)); |
| } |
| #endif |
| |
| //WMM IE |
| if(beacon2->WMMParams.present) |
| { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_WPA_EID); |
| vos_mem_copy((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); |
| vos_mem_copy((void *)&prb_rsp->WMMCaps, (void *)&beacon2->WMMCaps, |
| sizeof(beacon2->WMMCaps)); |
| } |
| |
| /* Extended Capability */ |
| if (beacon2->ExtCap.present) { |
| SetProbeRspIeBitmap(DefProbeRspIeBitmap, DOT11F_EID_EXTCAP); |
| vos_mem_copy((void *)&prb_rsp->ExtCap, (void *)&beacon2->ExtCap, |
| sizeof(beacon2->ExtCap)); |
| } |
| |
| } |
| |
| 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; |
| } |
| |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * 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 < psessionEntry->schBeaconOffsetEnd; i++) |
| psessionEntry->pSchBeaconFrameBegin[size++] = psessionEntry->pSchBeaconFrameEnd[i]; |
| } |
| |
| // Update the beacon length |
| pBeacon = (tpAniBeaconStruct) psessionEntry->pSchBeaconFrameBegin; |
| // 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 pSchBeaconFrameBegin |
| PELOG2(schLog(pMac, LOG2, FL("Beacon size - %d bytes"), size);) |
| PELOG2(sirDumpBuf(pMac, SIR_SCH_MODULE_ID, LOG2, psessionEntry->pSchBeaconFrameBegin, 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, psessionEntry->pSchBeaconFrameBegin, |
| size, psessionEntry)) |
| PELOGE(schLog(pMac, LOGE, FL("schSendBeaconReq() returned an error (zsize %d)"), 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; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; |
| |
| if((psessionEntry = peFindSessionByBssid(pMac,pMsg->bssId, &sessionId))== NULL) |
| { |
| PELOGE(schLog(pMac, LOGE, FL("session lookup fails"));) |
| goto end; |
| } |
| |
| |
| beaconSize = psessionEntry->schBeaconOffsetBegin; |
| |
| // 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"), psessionEntry->limSmeState);) |
| goto end; |
| } |
| |
| switch(GET_LIM_SYSTEM_ROLE(psessionEntry)) { |
| 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"));) |
| break; |
| |
| case eLIM_AP_ROLE: { |
| tANI_U8 *ptr = &psessionEntry->pSchBeaconFrameBegin[psessionEntry->schBeaconOffsetBegin]; |
| 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"));) |
| } |
| break; |
| |
| default: |
| PELOGE(schLog(pMac, LOGE, |
| FL("Error-PE has Receive PreBeconGenIndication when System is in %d role"), |
| GET_LIM_SYSTEM_ROLE(psessionEntry));) |
| } |
| |
| end: |
| vos_mem_free(pMsg); |
| |
| } |