| /* |
| * Copyright (c) 2011-2014, 2016-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 schApi.cc contains functions related to the API exposed |
| * by scheduler module |
| * |
| * Author: Sandesh Goel |
| * Date: 02/25/02 |
| * History:- |
| * Date Modified by Modification Information |
| * -------------------------------------------------------------------- |
| * |
| */ |
| #include "palTypes.h" |
| #include "aniGlobal.h" |
| #include "wni_cfg.h" |
| #include "sirMacProtDef.h" |
| #include "sirMacPropExts.h" |
| #include "sirCommon.h" |
| |
| |
| #include "cfgApi.h" |
| #include "pmmApi.h" |
| |
| #include "limApi.h" |
| |
| #include "schApi.h" |
| #include "schDebug.h" |
| |
| #include "schSysParams.h" |
| #include "limTrace.h" |
| #include "limTypes.h" |
| #include "limUtils.h" |
| |
| #include "wlan_qct_wda.h" |
| |
| //-------------------------------------------------------------------- |
| // |
| // Static Variables |
| // |
| //------------------------------------------------------------------- |
| |
| // -------------------------------------------------------------------- |
| /** |
| * schGetCFPCount |
| * |
| * FUNCTION: |
| * Function used by other Sirius modules to read CFPcount |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param None |
| * @return None |
| */ |
| |
| tANI_U8 |
| schGetCFPCount(tpAniSirGlobal pMac) |
| { |
| return pMac->sch.schObject.gSchCFPCount; |
| } |
| |
| // -------------------------------------------------------------------- |
| /** |
| * schGetCFPDurRemaining |
| * |
| * FUNCTION: |
| * Function used by other Sirius modules to read CFPDuration remaining |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param None |
| * @return None |
| */ |
| |
| tANI_U16 |
| schGetCFPDurRemaining(tpAniSirGlobal pMac) |
| { |
| return pMac->sch.schObject.gSchCFPDurRemaining; |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * schInitialize |
| * |
| * FUNCTION: |
| * Initialize |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param None |
| * @return None |
| */ |
| |
| void |
| schInitialize(tpAniSirGlobal pMac) |
| { |
| pmmInitialize(pMac); |
| } |
| |
| // -------------------------------------------------------------------- |
| /** |
| * schInitGlobals |
| * |
| * FUNCTION: |
| * Initialize globals |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param None |
| * @return None |
| */ |
| |
| void |
| schInitGlobals(tpAniSirGlobal pMac) |
| { |
| pMac->sch.gSchHcfEnabled = false; |
| |
| pMac->sch.gSchScanRequested = false; |
| pMac->sch.gSchScanReqRcvd = false; |
| |
| pMac->sch.gSchGenBeacon = 1; |
| pMac->sch.gSchBeaconsSent = 0; |
| pMac->sch.gSchBeaconsWritten = 0; |
| pMac->sch.gSchBcnParseErrorCnt = 0; |
| pMac->sch.gSchBcnIgnored = 0; |
| pMac->sch.gSchBBXportRcvCnt = 0; |
| pMac->sch.gSchUnknownRcvCnt = 0; |
| pMac->sch.gSchBcnRcvCnt = 0; |
| pMac->sch.gSchRRRcvCnt = 0; |
| pMac->sch.qosNullCnt = 0; |
| pMac->sch.numData = 0; |
| pMac->sch.numPoll = 0; |
| pMac->sch.numCorrupt = 0; |
| pMac->sch.numBogusInt = 0; |
| pMac->sch.numTxAct0 = 0; |
| pMac->sch.rrTimeout = SCH_RR_TIMEOUT; |
| pMac->sch.pollPeriod = SCH_POLL_PERIOD; |
| pMac->sch.keepAlive = 0; |
| pMac->sch.multipleSched = 1; |
| pMac->sch.maxPollTimeouts = 20; |
| pMac->sch.checkCfbFlagStuck = 0; |
| } |
| |
| // -------------------------------------------------------------------- |
| /** |
| * schPostMessage |
| * |
| * FUNCTION: |
| * Post the beacon message to the scheduler message queue |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param pMsg pointer to message |
| * @return None |
| */ |
| |
| tSirRetStatus |
| schPostMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| schProcessMessage(pMac, pMsg); |
| |
| return eSIR_SUCCESS; |
| } |
| |
| |
| |
| |
| |
| // --------------------------------------------------------------------------- |
| /** |
| * schSendStartScanRsp |
| * |
| * FUNCTION: |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param None |
| * @return None |
| */ |
| |
| void |
| schSendStartScanRsp(tpAniSirGlobal pMac) |
| { |
| tSirMsgQ msgQ; |
| tANI_U32 retCode; |
| |
| PELOG1(schLog(pMac, LOG1, FL("Sending LIM message to go into scan"));) |
| msgQ.type = SIR_SCH_START_SCAN_RSP; |
| if ((retCode = limPostMsgApi(pMac, &msgQ)) != eSIR_SUCCESS) |
| schLog(pMac, LOGE, |
| FL("Posting START_SCAN_RSP to LIM failed, reason=%X"), retCode); |
| } |
| |
| /** |
| * schSendBeaconReq |
| * |
| * FUNCTION: |
| * |
| * LOGIC: |
| * 1) SCH received SIR_SCH_BEACON_GEN_IND |
| * 2) SCH updates TIM IE and other beacon related IE's |
| * 3) SCH sends WDA_SEND_BEACON_REQ to HAL. HAL then copies the beacon |
| * template to memory |
| * |
| * ASSUMPTIONS: |
| * Memory allocation is reqd to send this message and SCH allocates memory. |
| * The assumption is that HAL will "free" this memory. |
| * |
| * NOTE: |
| * |
| * @param pMac global |
| * |
| * @param beaconPayload |
| * |
| * @param size - Length of the beacon |
| * |
| * @return eHalStatus |
| */ |
| tSirRetStatus schSendBeaconReq( tpAniSirGlobal pMac, tANI_U8 *beaconPayload, tANI_U16 size, tpPESession psessionEntry) |
| { |
| tSirMsgQ msgQ; |
| tpSendbeaconParams beaconParams = NULL; |
| tSirRetStatus retCode; |
| |
| schLog( pMac, LOG2, |
| FL( "Indicating HAL to copy the beacon template [%d bytes] to memory" ), |
| size ); |
| |
| beaconParams = vos_mem_malloc(sizeof(tSendbeaconParams)); |
| if ( NULL == beaconParams ) |
| return eSIR_FAILURE; |
| |
| msgQ.type = WDA_SEND_BEACON_REQ; |
| |
| // No Dialog Token reqd, as a response is not solicited |
| msgQ.reserved = 0; |
| |
| // Fill in tSendbeaconParams members |
| vos_mem_copy(beaconParams->bssId, psessionEntry->bssId, sizeof(psessionEntry->bssId)); |
| |
| if (LIM_IS_IBSS_ROLE(psessionEntry)) { |
| beaconParams->timIeOffset = 0; |
| } else { |
| beaconParams->timIeOffset = psessionEntry->schBeaconOffsetBegin; |
| } |
| |
| /* p2pIeOffset should be at-least greater than timIeOffset */ |
| if ((pMac->sch.schObject.p2pIeOffset != 0) && |
| (pMac->sch.schObject.p2pIeOffset < |
| psessionEntry->schBeaconOffsetBegin)) |
| { |
| schLog(pMac, LOGE,FL("Invalid p2pIeOffset:[%d]"), |
| pMac->sch.schObject.p2pIeOffset); |
| VOS_ASSERT( 0 ); |
| vos_mem_free(beaconParams); |
| return eSIR_FAILURE; |
| } |
| beaconParams->p2pIeOffset = pMac->sch.schObject.p2pIeOffset; |
| #ifdef WLAN_SOFTAP_FW_BEACON_TX_PRNT_LOG |
| schLog(pMac, LOGE,FL("TimIeOffset:[%d]"),beaconParams->TimIeOffset ); |
| #endif |
| |
| beaconParams->beacon = beaconPayload; |
| beaconParams->beaconLength = (tANI_U32) size; |
| msgQ.bodyptr = beaconParams; |
| msgQ.bodyval = 0; |
| |
| // Keep a copy of recent beacon frame sent |
| |
| // free previous copy of the beacon |
| if (psessionEntry->beacon ) |
| { |
| vos_mem_free(psessionEntry->beacon); |
| } |
| |
| psessionEntry->bcnLen = 0; |
| psessionEntry->beacon = NULL; |
| |
| psessionEntry->beacon = vos_mem_malloc(size); |
| if ( psessionEntry->beacon != NULL ) |
| { |
| vos_mem_copy(psessionEntry->beacon, beaconPayload, size); |
| psessionEntry->bcnLen = size; |
| } |
| |
| MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); |
| if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) |
| { |
| schLog( pMac, LOGE, |
| FL("Posting SEND_BEACON_REQ to HAL failed, reason=%X"), |
| retCode ); |
| } else |
| { |
| schLog( pMac, LOG2, |
| FL("Successfully posted WDA_SEND_BEACON_REQ to HAL")); |
| |
| if (LIM_IS_AP_ROLE(psessionEntry) && |
| pMac->sch.schObject.fBeaconChanged && |
| vos_is_probe_rsp_offload_enabled()) { |
| if(eSIR_SUCCESS != (retCode = limSendProbeRspTemplateToHal(pMac,psessionEntry, |
| &psessionEntry->DefProbeRspIeBitmap[0]))) |
| { |
| /* check whether we have to free any memory */ |
| schLog(pMac, LOGE, FL("FAILED to send probe response template with retCode %d"), retCode); |
| } |
| } |
| } |
| |
| return retCode; |
| } |
| |
| tANI_U32 limRemoveP2pIeFromAddIe(tpAniSirGlobal pMac, |
| tpPESession psessionEntry, |
| tANI_U8 *addIeWoP2pIe, |
| tANI_U32 *addnIELenWoP2pIe) |
| { |
| tANI_U32 left = psessionEntry->addIeParams.probeRespDataLen; |
| v_U8_t *ptr = psessionEntry->addIeParams.probeRespData_buff; |
| v_U8_t elem_id,elem_len; |
| tANI_U32 offset=0; |
| v_U8_t eid = 0xDD; |
| |
| vos_mem_copy(addIeWoP2pIe, ptr, left); |
| *addnIELenWoP2pIe = left; |
| |
| if (addIeWoP2pIe != NULL) |
| { |
| while (left >= 2) |
| { |
| elem_id = ptr[0]; |
| elem_len = ptr[1]; |
| left -= 2; |
| if(elem_len > left) |
| { |
| schLog(pMac, LOGE, FL("Invalid IEs")); |
| return eSIR_FAILURE; |
| } |
| if ((elem_id == eid) && |
| (vos_mem_compare( &ptr[2], "\x50\x6f\x9a\x09", 4)==VOS_TRUE)) |
| { |
| left -= elem_len; |
| ptr += (elem_len + 2); |
| vos_mem_copy(&addIeWoP2pIe[offset], ptr, left); |
| *addnIELenWoP2pIe -= (2 + elem_len); |
| } |
| else |
| { |
| left -= elem_len; |
| ptr += (elem_len + 2); |
| offset += 2 + elem_len; |
| } |
| } |
| } |
| return eSIR_SUCCESS; |
| } |
| |
| tANI_U32 limSendProbeRspTemplateToHal(tpAniSirGlobal pMac,tpPESession psessionEntry |
| ,tANI_U32* IeBitmap) |
| { |
| tSirMsgQ msgQ; |
| tANI_U8 *pFrame2Hal = psessionEntry->pSchProbeRspTemplate; |
| tpSendProbeRespParams pprobeRespParams=NULL; |
| tANI_U32 retCode = eSIR_FAILURE; |
| tANI_U32 nPayload, nBytes = 0, nStatus; |
| tpSirMacMgmtHdr pMacHdr; |
| tANI_U32 addnIEPresent = VOS_FALSE; |
| tSirRetStatus nSirStatus; |
| tANI_U8 *addIE = NULL; |
| tANI_U8 *addIeWoP2pIe = NULL; |
| tANI_U32 addnIELenWoP2pIe = 0; |
| tANI_U32 retStatus; |
| tDot11fIEExtCap extracted_extcap; |
| bool extcap_present = false; |
| tDot11fProbeResponse *prb_rsp_frm; |
| tSirRetStatus status; |
| uint16_t addn_ielen = 0; |
| |
| //Check if probe response IE is present or not |
| addnIEPresent = (psessionEntry->addIeParams.probeRespDataLen != 0); |
| if (addnIEPresent) |
| { |
| /* |
| * probe response template should not have P2P IE. |
| * In case probe request has P2P IE or WPS IE, the |
| * probe request will be forwarded to the Host and |
| * Host will send the probe response. In other cases |
| * FW will send the probe response. So, if the template |
| * has P2P IE, the probe response sent to non P2P devices |
| * by the FW, may also have P2P IE which will fail |
| * P2P cert case 6.1.3 |
| */ |
| addIeWoP2pIe = vos_mem_malloc(psessionEntry->addIeParams.probeRespDataLen); |
| if ( NULL == addIeWoP2pIe ) |
| { |
| schLog(pMac, LOGE, FL("FAILED to alloc memory when removing P2P IE")); |
| return eSIR_FAILURE; |
| } |
| |
| retStatus = limRemoveP2pIeFromAddIe(pMac, psessionEntry, |
| addIeWoP2pIe, &addnIELenWoP2pIe); |
| if (retStatus != eSIR_SUCCESS) |
| { |
| vos_mem_free(addIeWoP2pIe); |
| return eSIR_FAILURE; |
| } |
| |
| //Probe rsp IE available |
| /*need to check the data length*/ |
| addIE = vos_mem_malloc(addnIELenWoP2pIe); |
| |
| if ( NULL == addIE ) |
| { |
| schLog(pMac, LOGE, |
| FL("Unable to get WNI_CFG_PROBE_RSP_ADDNIE_DATA1 length")); |
| vos_mem_free(addIeWoP2pIe); |
| return retCode; |
| } |
| addn_ielen = addnIELenWoP2pIe; |
| |
| if (addn_ielen <= WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && addn_ielen && |
| (nBytes + addn_ielen) <= SIR_MAX_PACKET_SIZE) |
| { |
| vos_mem_copy(addIE, addIeWoP2pIe, addnIELenWoP2pIe); |
| } |
| vos_mem_free(addIeWoP2pIe); |
| |
| vos_mem_set((uint8_t *)&extracted_extcap, sizeof(tDot11fIEExtCap), 0); |
| status = lim_strip_extcap_update_struct(pMac, addIE, &addn_ielen, |
| &extracted_extcap); |
| if (eSIR_SUCCESS != status) { |
| limLog(pMac, LOG1, FL("extcap not extracted")); |
| } else { |
| extcap_present = true; |
| } |
| |
| } |
| |
| if (addnIEPresent) |
| { |
| if ((nBytes + addn_ielen) <= SIR_MAX_PACKET_SIZE ) |
| nBytes += addn_ielen; |
| else |
| addnIEPresent = false; //Dont include the IE. |
| } |
| |
| /* merge extcap IE */ |
| prb_rsp_frm = &psessionEntry->probeRespFrame; |
| if (extcap_present) |
| lim_merge_extcap_struct(&prb_rsp_frm->ExtCap, &extracted_extcap, true); |
| |
| nStatus = dot11fGetPackedProbeResponseSize(pMac, &psessionEntry->probeRespFrame, &nPayload); |
| if (DOT11F_FAILED(nStatus)) |
| { |
| schLog(pMac, LOGE, |
| FL("Failed to calculate the packed size for a Probe Response (0x%08x)."), |
| nStatus); |
| /* We'll fall back on the worst case scenario: */ |
| nPayload = sizeof(tDot11fProbeResponse); |
| } |
| else if (DOT11F_WARNED(nStatus)) |
| { |
| schLog(pMac, LOGE, |
| FL("There were warnings while calculating the packed size for a Probe Response (0x%08x)."), |
| nStatus); |
| } |
| |
| nBytes += nPayload + sizeof(tSirMacMgmtHdr); |
| |
| // Paranoia: |
| vos_mem_set(pFrame2Hal, nBytes, 0); |
| |
| // Next, we fill out the buffer descriptor: |
| nSirStatus = limPopulateMacHeader( pMac, pFrame2Hal, SIR_MAC_MGMT_FRAME, |
| SIR_MAC_MGMT_PROBE_RSP, psessionEntry->selfMacAddr,psessionEntry->selfMacAddr); |
| |
| if ( eSIR_SUCCESS != nSirStatus ) |
| { |
| schLog( pMac, LOGE, FL("Failed to populate the buffer descrip" |
| "tor for a Probe Response (%d)."), |
| nSirStatus ); |
| |
| vos_mem_free(addIE); |
| return retCode; |
| } |
| |
| pMacHdr = ( tpSirMacMgmtHdr ) pFrame2Hal; |
| |
| sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); |
| |
| // That done, pack the Probe Response: |
| nStatus = dot11fPackProbeResponse( pMac, &psessionEntry->probeRespFrame, pFrame2Hal + sizeof(tSirMacMgmtHdr), |
| nPayload, &nPayload ); |
| |
| if ( DOT11F_FAILED( nStatus ) ) |
| { |
| schLog( pMac, LOGE, FL("Failed to pack a Probe Response (0x%08x)."), |
| nStatus ); |
| |
| vos_mem_free(addIE); |
| return retCode; // allocated! |
| } |
| else if ( DOT11F_WARNED( nStatus ) ) |
| { |
| schLog( pMac, LOGE, FL("There were warnings while packing a P" |
| "robe Response (0x%08x)."), nStatus ); |
| } |
| |
| if (addnIEPresent) |
| vos_mem_copy(&pFrame2Hal[nBytes - addn_ielen], &addIE[0], addn_ielen); |
| |
| /* free the allocated Memory */ |
| vos_mem_free(addIE); |
| |
| pprobeRespParams = vos_mem_malloc(sizeof( tSendProbeRespParams )); |
| if ( NULL == pprobeRespParams ) |
| { |
| schLog( pMac, LOGE, FL("limSendProbeRspTemplateToHal: HAL probe response params malloc failed for bytes %d"), nBytes ); |
| } |
| else |
| { |
| sirCopyMacAddr( pprobeRespParams->bssId, psessionEntry->bssId); |
| pprobeRespParams->pProbeRespTemplate = pFrame2Hal; |
| pprobeRespParams->probeRespTemplateLen = nBytes; |
| vos_mem_copy(pprobeRespParams->ucProxyProbeReqValidIEBmap,IeBitmap,(sizeof(tANI_U32) * 8)); |
| msgQ.type = WDA_SEND_PROBE_RSP_TMPL; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pprobeRespParams; |
| msgQ.bodyval = 0; |
| |
| if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) |
| { |
| /* free the allocated Memory */ |
| schLog( pMac,LOGE, FL("limSendProbeRspTemplateToHal: FAIL bytes %d retcode[%X]"), nBytes, retCode ); |
| vos_mem_free(pprobeRespParams); |
| } |
| else |
| { |
| schLog( pMac,LOG1, FL("limSendProbeRspTemplateToHal: Probe response template msg posted to HAL of bytes %d"),nBytes ); |
| } |
| } |
| |
| return retCode; |
| } |
| |
| /** |
| * schGenTimingAdvertFrame() - Generate the TA frame and populate the buffer |
| * @pMac: the global MAC context |
| * @self_addr: the self MAC address |
| * @buf: the buffer that will contain the frame |
| * @timestamp_offset: return for the offset of the timestamp field |
| * @time_value_offset: return for the time_value field in the TA IE |
| * |
| * Return: the length of the buffer. |
| */ |
| int schGenTimingAdvertFrame(tpAniSirGlobal mac_ctx, tSirMacAddr self_addr, |
| uint8_t **buf, uint32_t *timestamp_offset, uint32_t *time_value_offset) |
| { |
| tDot11fTimingAdvertisementFrame frame; |
| uint32_t payload_size, buf_size; |
| int status; |
| v_MACADDR_t wildcard_bssid = { |
| {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, |
| }; |
| |
| vos_mem_zero((uint8_t*)&frame, sizeof(tDot11fTimingAdvertisementFrame)); |
| |
| /* Populate the TA fields */ |
| status = PopulateDot11fTimingAdvertFrame(mac_ctx, &frame); |
| if (status) { |
| schLog(mac_ctx, LOGE, FL("Error populating TA frame %x"), status); |
| return status; |
| } |
| |
| status = dot11fGetPackedTimingAdvertisementFrameSize(mac_ctx, &frame, |
| &payload_size); |
| if (DOT11F_FAILED(status)) { |
| schLog(mac_ctx, LOGE, FL("Error getting packed frame size %x"), status); |
| return status; |
| } else if (DOT11F_WARNED(status)) { |
| schLog(mac_ctx, LOGW, FL("Warning getting packed frame size")); |
| } |
| |
| buf_size = sizeof(tSirMacMgmtHdr) + payload_size; |
| *buf = vos_mem_malloc(buf_size); |
| if (*buf == NULL) { |
| schLog(mac_ctx, LOGE, FL("Cannot allocate memory")); |
| return eSIR_FAILURE; |
| } |
| vos_mem_zero(*buf, buf_size); |
| |
| payload_size = 0; |
| status = dot11fPackTimingAdvertisementFrame(mac_ctx, &frame, |
| *buf + sizeof(tSirMacMgmtHdr), buf_size - sizeof(tSirMacMgmtHdr), |
| &payload_size); |
| schLog(mac_ctx, LOGE, FL("TA payload size2 = %d"), payload_size); |
| if (DOT11F_FAILED(status)) { |
| schLog(mac_ctx, LOGE, FL("Error packing frame %x"), status); |
| goto fail; |
| } else if (DOT11F_WARNED(status)) { |
| schLog(mac_ctx, LOGE, FL("Warning packing frame")); |
| } |
| |
| limPopulateMacHeader(mac_ctx, *buf, SIR_MAC_MGMT_FRAME, |
| SIR_MAC_MGMT_TIME_ADVERT, wildcard_bssid.bytes, self_addr); |
| |
| /* The timestamp field is right after the header */ |
| *timestamp_offset = sizeof(tSirMacMgmtHdr); |
| |
| *time_value_offset = sizeof(tSirMacMgmtHdr) + sizeof(tDot11fFfTimeStamp) + |
| sizeof(tDot11fFfCapabilities); |
| |
| /* Add the Country IE length */ |
| dot11fGetPackedIECountry(mac_ctx, &frame.Country, time_value_offset); |
| /* Add 2 for Country IE EID and Length fields */ |
| *time_value_offset += 2; |
| |
| /* Add the PowerConstraint IE size */ |
| if (frame.Country.present == 1) |
| *time_value_offset += 3; |
| |
| /* Add the offset inside TA IE */ |
| *time_value_offset += 3; |
| |
| return payload_size + sizeof(tSirMacMgmtHdr); |
| |
| fail: |
| if (*buf) |
| vos_mem_free(*buf); |
| return status; |
| } |