| /****************************************************************************** |
| * |
| * This file is provided under a dual license. When you use or |
| * distribute this software, you may choose to be licensed under |
| * version 2 of the GNU General Public License ("GPLv2 License") |
| * or BSD License. |
| * |
| * GPLv2 License |
| * |
| * Copyright(C) 2016 MediaTek Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of version 2 of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| * See http://www.gnu.org/licenses/gpl-2.0.html for more details. |
| * |
| * BSD LICENSE |
| * |
| * Copyright(C) 2016 MediaTek Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of the copyright holder nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| *****************************************************************************/ |
| /* |
| ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm.c#3 |
| */ |
| |
| /*! \file "rlm.c" |
| * \brief |
| * |
| */ |
| |
| |
| /******************************************************************************* |
| * C O M P I L E R F L A G S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * E X T E R N A L R E F E R E N C E S |
| ******************************************************************************** |
| */ |
| #include "precomp.h" |
| |
| /******************************************************************************* |
| * C O N S T A N T S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * D A T A T Y P E S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * P U B L I C D A T A |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * P R I V A T E D A T A |
| ******************************************************************************** |
| */ |
| BOOLEAN g_bCaptureDone = FALSE; |
| BOOLEAN g_bIcapEnable = FALSE; |
| UINT_16 g_u2DumpIndex; |
| BOOLEAN g_fgHasChannelSwitchIE = FALSE; |
| BOOLEAN g_fgHasStopTx = FALSE; |
| |
| #if CFG_SUPPORT_QA_TOOL |
| UINT_32 g_au4Offset[2][2]; |
| UINT_32 g_au4IQData[256]; |
| #endif |
| |
| #if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST |
| RLM_CAL_RESULT_ALL_V2_T g_rBackupCalDataAllV2; |
| #endif |
| |
| /******************************************************************************* |
| * M A C R O S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N D E C L A R A T I O N S |
| ******************************************************************************** |
| */ |
| static VOID rlmFillHtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); |
| |
| static VOID rlmFillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); |
| |
| static VOID rlmFillHtOpIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); |
| |
| static UINT_8 rlmRecIeInfoForClient(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pucIE, UINT_16 u2IELength); |
| |
| static BOOLEAN |
| rlmRecBcnFromNeighborForClient(P_ADAPTER_T prAdapter, |
| P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); |
| |
| static BOOLEAN |
| rlmRecBcnInfoForClient(P_ADAPTER_T prAdapter, |
| P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); |
| |
| static VOID rlmBssReset(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); |
| |
| #if CFG_SUPPORT_802_11AC |
| static VOID rlmFillVhtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); |
| static VOID rlmFillVhtOpNotificationIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, |
| P_MSDU_INFO_T prMsduInfo, BOOLEAN fgIsMaxCap); |
| |
| #endif |
| /******************************************************************************* |
| * F U N C T I O N S |
| ******************************************************************************** |
| */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmFsmEventInit(P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| /* Note: assume TIMER_T structures are reset to zero or stopped |
| * before invoking this function. |
| */ |
| |
| /* Initialize OBSS FSM */ |
| rlmObssInit(prAdapter); |
| |
| #if CFG_SUPPORT_PWR_LIMIT_COUNTRY |
| rlmDomainCheckCountryPowerLimitTable(prAdapter); |
| #endif |
| |
| g_fgHasChannelSwitchIE = FALSE; |
| g_bCaptureDone = FALSE; |
| g_bIcapEnable = FALSE; |
| g_u2DumpIndex = 0; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmFsmEventUninit(P_ADAPTER_T prAdapter) |
| { |
| P_BSS_INFO_T prBssInfo; |
| UINT_8 i; |
| |
| ASSERT(prAdapter); |
| |
| for (i = 0; i < BSS_INFO_NUM; i++) { |
| prBssInfo = prAdapter->aprBssInfo[i]; |
| |
| /* Note: all RLM timers will also be stopped. |
| * Now only one OBSS scan timer. |
| */ |
| rlmBssReset(prAdapter, prBssInfo); |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For association request, power capability |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmReqGeneratePowerCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| PUINT_8 pucBuffer; |
| P_BSS_INFO_T prBssInfo; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); |
| |
| /* We should add power capability IE in assoc/reassoc req if the spectrum |
| * management bit is set to 1 in Capability Infor field, or the connection |
| * will be rejected by Marvell APs in some TGn items. (e.g. 5.2.32). |
| * Spectrum management related feature (802.11h) is for 5G band. |
| */ |
| if (!prBssInfo || prBssInfo->eBand != BAND_5G) |
| return; |
| |
| pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); |
| |
| POWER_CAP_IE(pucBuffer)->ucId = ELEM_ID_PWR_CAP; |
| POWER_CAP_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_POWER_CAP; |
| POWER_CAP_IE(pucBuffer)->cMinTxPowerCap = 15; |
| POWER_CAP_IE(pucBuffer)->cMaxTxPowerCap = 20; |
| |
| prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); |
| pucBuffer += IE_SIZE(pucBuffer); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For association request, supported channels |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmReqGenerateSupportedChIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| PUINT_8 pucBuffer; |
| P_BSS_INFO_T prBssInfo; |
| RF_CHANNEL_INFO_T auc2gChannelList[MAX_2G_BAND_CHN_NUM]; |
| RF_CHANNEL_INFO_T auc5gChannelList[MAX_5G_BAND_CHN_NUM]; |
| UINT_8 ucNumOf2gChannel = 0; |
| UINT_8 ucNumOf5gChannel = 0; |
| UINT_8 ucChIdx = 0; |
| UINT_8 ucIdx = 0; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); |
| |
| /* We should add supported channels IE in assoc/reassoc req if the spectrum |
| * management bit is set to 1 in Capability Infor field, or the connection |
| * will be rejected by Marvell APs in some TGn items. (e.g. 5.2.3). |
| * Spectrum management related feature (802.11h) is for 5G band. |
| */ |
| if (!prBssInfo || prBssInfo->eBand != BAND_5G) |
| return; |
| |
| |
| pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); |
| |
| rlmDomainGetChnlList(prAdapter, BAND_2G4, TRUE, |
| MAX_2G_BAND_CHN_NUM, &ucNumOf2gChannel, auc2gChannelList); |
| rlmDomainGetChnlList(prAdapter, BAND_5G, TRUE, |
| MAX_5G_BAND_CHN_NUM, &ucNumOf5gChannel, auc5gChannelList); |
| |
| SUP_CH_IE(pucBuffer)->ucId = ELEM_ID_SUP_CHS; |
| SUP_CH_IE(pucBuffer)->ucLength = (ucNumOf2gChannel + ucNumOf5gChannel) * 2; |
| |
| for (ucIdx = 0; ucIdx < ucNumOf2gChannel; ucIdx++, ucChIdx += 2) { |
| SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx] = |
| auc2gChannelList[ucIdx].ucChannelNum; |
| SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx + 1] = 1; |
| } |
| |
| for (ucIdx = 0; ucIdx < ucNumOf5gChannel; ucIdx++, ucChIdx += 2) { |
| SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx] = |
| auc5gChannelList[ucIdx].ucChannelNum; |
| SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx + 1] = 1; |
| } |
| |
| prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); |
| pucBuffer += IE_SIZE(pucBuffer); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For probe request, association request |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmReqGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && |
| (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) |
| rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For probe request, association request |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmReqGenerateExtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && |
| (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) |
| rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); |
| #if CFG_SUPPORT_PASSPOINT |
| else if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) |
| hs20FillExtCapIE(prAdapter, prBssInfo, prMsduInfo); |
| #endif /* CFG_SUPPORT_PASSPOINT */ |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For probe response (GO, IBSS) and association response |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmRspGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| UINT_8 ucPhyTypeSet; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| |
| if (!IS_BSS_ACTIVE(prBssInfo)) |
| return; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| /* Decide PHY type set source */ |
| if (prStaRec) { |
| /* Get PHY type set from target STA */ |
| ucPhyTypeSet = prStaRec->ucPhyTypeSet; |
| } else { |
| /* Get PHY type set from current BSS */ |
| ucPhyTypeSet = prBssInfo->ucPhyTypeSet; |
| } |
| |
| if (RLM_NET_IS_11N(prBssInfo) && (ucPhyTypeSet & PHY_TYPE_SET_802_11N) && |
| (!prBssInfo->fgIsWepCipherGroup)) |
| rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For probe response (GO, IBSS) and association response |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmRspGenerateExtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| UINT_8 ucPhyTypeSet; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| |
| if (!IS_BSS_ACTIVE(prBssInfo)) |
| return; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| /* Decide PHY type set source */ |
| if (prStaRec) { |
| /* Get PHY type set from target STA */ |
| ucPhyTypeSet = prStaRec->ucPhyTypeSet; |
| } else { |
| /* Get PHY type set from current BSS */ |
| ucPhyTypeSet = prBssInfo->ucPhyTypeSet; |
| } |
| |
| if (RLM_NET_IS_11N(prBssInfo) && (ucPhyTypeSet & PHY_TYPE_SET_802_11N)) |
| rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For probe response (GO, IBSS) and association response |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmRspGenerateHtOpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| UINT_8 ucPhyTypeSet; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| |
| if (!IS_BSS_ACTIVE(prBssInfo)) |
| return; |
| |
| /* Decide PHY type set source */ |
| if (prStaRec) { |
| /* Get PHY type set from target STA */ |
| ucPhyTypeSet = prStaRec->ucPhyTypeSet; |
| } else { |
| /* Get PHY type set from current BSS */ |
| ucPhyTypeSet = prBssInfo->ucPhyTypeSet; |
| } |
| |
| if (RLM_NET_IS_11N(prBssInfo) && (ucPhyTypeSet & PHY_TYPE_SET_802_11N) && |
| (!prBssInfo->fgIsWepCipherGroup)) |
| rlmFillHtOpIE(prAdapter, prBssInfo, prMsduInfo); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For probe response (GO, IBSS) and association response |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmRspGenerateErpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| P_IE_ERP_T prErpIe; |
| UINT_8 ucPhyTypeSet; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| |
| if (!IS_BSS_ACTIVE(prBssInfo)) |
| return; |
| |
| /* Decide PHY type set source */ |
| if (prStaRec) { |
| /* Get PHY type set from target STA */ |
| ucPhyTypeSet = prStaRec->ucPhyTypeSet; |
| } else { |
| /* Get PHY type set from current BSS */ |
| ucPhyTypeSet = prBssInfo->ucPhyTypeSet; |
| } |
| |
| if (RLM_NET_IS_11GN(prBssInfo) && prBssInfo->eBand == BAND_2G4 && (ucPhyTypeSet & PHY_TYPE_SET_802_11GN)) { |
| prErpIe = (P_IE_ERP_T) |
| (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); |
| |
| /* Add ERP IE */ |
| prErpIe->ucId = ELEM_ID_ERP_INFO; |
| prErpIe->ucLength = 1; |
| |
| prErpIe->ucERP = prBssInfo->fgObssErpProtectMode ? ERP_INFO_USE_PROTECTION : 0; |
| |
| if (prBssInfo->fgErpProtectMode) |
| prErpIe->ucERP |= (ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION); |
| |
| /* Handle barker preamble */ |
| if (!prBssInfo->fgUseShortPreamble) |
| prErpIe->ucERP |= ERP_INFO_BARKER_PREAMBLE_MODE; |
| |
| ASSERT(IE_SIZE(prErpIe) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_ERP)); |
| |
| prMsduInfo->u2FrameLength += IE_SIZE(prErpIe); |
| } |
| } |
| |
| #if CFG_SUPPORT_MTK_SYNERGY |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is used to generate MTK Vendor Specific OUI |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmGenerateMTKOuiIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| PUINT_8 pucBuffer; |
| UINT_8 aucMtkOui[] = VENDOR_OUI_MTK; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| if (prAdapter->rWifiVar.ucMtkOui == FEATURE_DISABLED) |
| return; |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| |
| pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); |
| |
| MTK_OUI_IE(pucBuffer)->ucId = ELEM_ID_VENDOR; |
| MTK_OUI_IE(pucBuffer)->ucLength = ELEM_MIN_LEN_MTK_OUI; |
| MTK_OUI_IE(pucBuffer)->aucOui[0] = aucMtkOui[0]; |
| MTK_OUI_IE(pucBuffer)->aucOui[1] = aucMtkOui[1]; |
| MTK_OUI_IE(pucBuffer)->aucOui[2] = aucMtkOui[2]; |
| MTK_OUI_IE(pucBuffer)->aucCapability[0] = MTK_SYNERGY_CAP0 & (prAdapter->rWifiVar.aucMtkFeature[0]); |
| MTK_OUI_IE(pucBuffer)->aucCapability[1] = MTK_SYNERGY_CAP1 & (prAdapter->rWifiVar.aucMtkFeature[1]); |
| MTK_OUI_IE(pucBuffer)->aucCapability[2] = MTK_SYNERGY_CAP2 & (prAdapter->rWifiVar.aucMtkFeature[2]); |
| MTK_OUI_IE(pucBuffer)->aucCapability[3] = MTK_SYNERGY_CAP3 & (prAdapter->rWifiVar.aucMtkFeature[3]); |
| |
| prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); |
| pucBuffer += IE_SIZE(pucBuffer); |
| } /* rlmGenerateMTKOuiIE */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used to check MTK Vendor Specific OUI |
| * |
| * |
| * @return true: correct MTK OUI |
| * false: incorrect MTK OUI |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN rlmParseCheckMTKOuiIE(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN PUINT_32 pu4Cap) |
| { |
| UINT_8 aucMtkOui[] = VENDOR_OUI_MTK; |
| P_IE_MTK_OUI_T prMtkOuiIE = (P_IE_MTK_OUI_T) NULL; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); |
| |
| prMtkOuiIE = (P_IE_MTK_OUI_T) pucBuf; |
| |
| if (prAdapter->rWifiVar.ucMtkOui == FEATURE_DISABLED) |
| break; |
| else if (IE_LEN(pucBuf) < ELEM_MIN_LEN_MTK_OUI) |
| break; |
| else if (prMtkOuiIE->aucOui[0] != aucMtkOui[0] || |
| prMtkOuiIE->aucOui[1] != aucMtkOui[1] || prMtkOuiIE->aucOui[2] != aucMtkOui[2]) |
| break; |
| /* apply NvRam setting */ |
| prMtkOuiIE->aucCapability[0] = prMtkOuiIE->aucCapability[0] & (prAdapter->rWifiVar.aucMtkFeature[0]); |
| prMtkOuiIE->aucCapability[1] = prMtkOuiIE->aucCapability[1] & (prAdapter->rWifiVar.aucMtkFeature[1]); |
| prMtkOuiIE->aucCapability[2] = prMtkOuiIE->aucCapability[2] & (prAdapter->rWifiVar.aucMtkFeature[2]); |
| prMtkOuiIE->aucCapability[3] = prMtkOuiIE->aucCapability[3] & (prAdapter->rWifiVar.aucMtkFeature[3]); |
| |
| kalMemCopy(pu4Cap, prMtkOuiIE->aucCapability, sizeof(UINT_32)); |
| |
| return TRUE; |
| } while (FALSE); |
| |
| return FALSE; |
| } /* rlmParseCheckMTKOuiIE */ |
| |
| #endif |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmGenerateCsaIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| PUINT_8 pucBuffer; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| if (prAdapter->rWifiVar.fgCsaInProgress) { |
| |
| pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); |
| |
| CSA_IE(pucBuffer)->ucId = ELEM_ID_CH_SW_ANNOUNCEMENT; |
| CSA_IE(pucBuffer)->ucLength = ELEM_MIN_LEN_CSA; |
| CSA_IE(pucBuffer)->ucChannelSwitchMode = prAdapter->rWifiVar.ucChannelSwitchMode; |
| CSA_IE(pucBuffer)->ucNewChannelNum = prAdapter->rWifiVar.ucNewChannelNumber; |
| CSA_IE(pucBuffer)->ucChannelSwitchCount = prAdapter->rWifiVar.ucChannelSwitchCount; |
| |
| prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); |
| pucBuffer += IE_SIZE(pucBuffer); |
| } |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static VOID rlmFillHtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_IE_HT_CAP_T prHtCap; |
| P_SUP_MCS_SET_FIELD prSupMcsSet; |
| BOOLEAN fg40mAllowed; |
| UINT_8 ucIdx; |
| |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| ASSERT(prMsduInfo); |
| |
| fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; |
| |
| prHtCap = (P_IE_HT_CAP_T) |
| (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); |
| |
| /* Add HT capabilities IE */ |
| prHtCap->ucId = ELEM_ID_HT_CAP; |
| prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; |
| |
| prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) |
| prHtCap->u2HtCapInfo |= (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) |
| prHtCap->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucTxStbc)) |
| prHtCap->u2HtCapInfo |= HT_CAP_INFO_TX_STBC; |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) { |
| |
| UINT_8 tempRxStbcNss; |
| |
| tempRxStbcNss = prAdapter->rWifiVar.ucRxStbcNss; |
| tempRxStbcNss = (tempRxStbcNss > wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) ? |
| wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex) : (tempRxStbcNss); |
| if (tempRxStbcNss != prAdapter->rWifiVar.ucRxStbcNss) { |
| DBGLOG(RLM, WARN, "Apply Nss:%d as RxStbcNss in HT Cap", |
| wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)); |
| DBGLOG(RLM, WARN, " due to set RxStbcNss more than Nss is not appropriate.\n"); |
| } |
| if (tempRxStbcNss == 1) |
| prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_1_SS; |
| else if (tempRxStbcNss == 2) |
| prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_2_SS; |
| else if (tempRxStbcNss >= 3) |
| prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_3_SS; |
| } |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxGf)) |
| prHtCap->u2HtCapInfo |= HT_CAP_INFO_HT_GF; |
| |
| if (prAdapter->rWifiVar.ucRxMaxMpduLen > VHT_CAP_INFO_MAX_MPDU_LEN_3K) |
| prHtCap->u2HtCapInfo |= HT_CAP_INFO_MAX_AMSDU_LEN; |
| |
| if (!fg40mAllowed) |
| prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | |
| HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); |
| |
| /* SM power saving */ /* TH3_Huang */ |
| if (prBssInfo->ucNss < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) |
| prHtCap->u2HtCapInfo &= ~HT_CAP_INFO_SM_POWER_SAVE;/*Set as static power save */ |
| |
| prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; |
| |
| prSupMcsSet = &prHtCap->rSupMcsSet; |
| kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); |
| |
| for (ucIdx = 0; ucIdx < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex); ucIdx++) |
| prSupMcsSet->aucRxMcsBitmask[ucIdx] = BITS(0, 7); |
| |
| /* prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); */ |
| |
| if (fg40mAllowed && IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucMCS32)) |
| prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ |
| prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; |
| prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; |
| |
| prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; |
| if (!fg40mAllowed || prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) |
| prHtCap->u2HtExtendedCap &= ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); |
| |
| prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; |
| if ((prAdapter->rWifiVar.ucDbdcMode == DBDC_MODE_DISABLED) || |
| (prBssInfo->eBand == BAND_5G)) { |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfee)) |
| prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_BFEE; |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfer)) |
| prHtCap->u4TxBeamformingCap |= TX_BEAMFORMING_CAP_BFER; |
| } |
| |
| prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; |
| |
| ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); |
| |
| prMsduInfo->u2FrameLength += IE_SIZE(prHtCap); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static VOID rlmFillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_EXT_CAP_T prExtCap; |
| BOOLEAN fg40mAllowed, fgAppendVhtCap; |
| P_STA_RECORD_T prStaRec; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; |
| |
| /* Add Extended Capabilities IE */ |
| prExtCap = (P_EXT_CAP_T) |
| (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); |
| |
| prExtCap->ucId = ELEM_ID_EXTENDED_CAP; |
| #if 0 /* CFG_SUPPORT_HOTSPOT_2_0 */ |
| if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) |
| prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; |
| else |
| #endif |
| prExtCap->ucLength = 1; |
| |
| /* Reset memory */ |
| kalMemZero(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP); |
| |
| prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; |
| |
| if (!fg40mAllowed) |
| prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_20_40_COEXIST_SUPPORT; |
| |
| if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) |
| prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| #if CFG_SUPPORT_802_11AC |
| fgAppendVhtCap = FALSE; |
| |
| /* Check append rule */ |
| if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) { |
| /* Note: For AIS connecting state, structure in BSS_INFO will not be inited */ |
| /* So, we check StaRec instead of BssInfo */ |
| if (prStaRec) { |
| if (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC) |
| fgAppendVhtCap = TRUE; |
| } else if ((RLM_NET_IS_11AC(prBssInfo)) && ((prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) || |
| (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT))) |
| fgAppendVhtCap = TRUE; |
| } |
| |
| if (fgAppendVhtCap) { |
| if (prExtCap->ucLength < ELEM_MAX_LEN_EXT_CAP) |
| prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; |
| |
| SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_OP_MODE_NOTIFICATION_BIT); |
| |
| } |
| #endif |
| |
| #if CFG_SUPPORT_PASSPOINT |
| if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { |
| |
| if (prExtCap->ucLength < ELEM_MAX_LEN_EXT_CAP) |
| prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; |
| |
| SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); |
| |
| /* For R2 WNM-Notification */ |
| SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); |
| } |
| #endif /* CFG_SUPPORT_PASSPOINT */ |
| |
| ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); |
| |
| prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static VOID rlmFillHtOpIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_IE_HT_OP_T prHtOp; |
| UINT_16 i; |
| |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| ASSERT(prMsduInfo); |
| |
| prHtOp = (P_IE_HT_OP_T) |
| (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); |
| |
| /* Add HT operation IE */ |
| prHtOp->ucId = ELEM_ID_HT_OP; |
| prHtOp->ucLength = sizeof(IE_HT_OP_T) - ELEM_HDR_LEN; |
| |
| /* RIFS and 20/40 bandwidth operations are included */ |
| prHtOp->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; |
| prHtOp->ucInfo1 = prBssInfo->ucHtOpInfo1; |
| |
| /* Decide HT protection mode field */ |
| if (prBssInfo->eHtProtectMode == HT_PROTECT_MODE_NON_HT) |
| prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_HT; |
| else if (prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) |
| prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_MEMBER; |
| else { |
| /* It may be SYS_PROTECT_MODE_NONE or SYS_PROTECT_MODE_20M */ |
| prHtOp->u2Info2 = (UINT_8) prBssInfo->eHtProtectMode; |
| } |
| |
| if (prBssInfo->eGfOperationMode != GF_MODE_NORMAL) { |
| /* It may be GF_MODE_PROTECT or GF_MODE_DISALLOWED |
| * Note: it will also be set in ad-hoc network |
| */ |
| prHtOp->u2Info2 |= HT_OP_INFO2_NON_GF_HT_STA_PRESENT; |
| } |
| |
| if (0 /* Regulatory class 16 */ && |
| prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) { |
| /* (TBD) It is HT_PROTECT_MODE_NON_MEMBER, so require protection |
| * although it is possible to have no protection by spec. |
| */ |
| prHtOp->u2Info2 |= HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; |
| } |
| |
| prHtOp->u2Info3 = prBssInfo->u2HtOpInfo3; /* To do: handle L-SIG TXOP */ |
| |
| /* No basic MCSx are needed temporarily */ |
| for (i = 0; i < 16; i++) |
| prHtOp->aucBasicMcsSet[i] = 0; |
| |
| ASSERT(IE_SIZE(prHtOp) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP)); |
| |
| prMsduInfo->u2FrameLength += IE_SIZE(prHtOp); |
| } |
| |
| #if CFG_SUPPORT_802_11AC |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For probe request, association request |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmReqGenerateVhtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) && |
| (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC))) |
| rlmFillVhtCapIE(prAdapter, prBssInfo, prMsduInfo); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For probe response (GO, IBSS) and association response |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmRspGenerateVhtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| UINT_8 ucPhyTypeSet; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| |
| if (!IS_BSS_ACTIVE(prBssInfo)) |
| return; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| /* Decide PHY type set source */ |
| if (prStaRec) { |
| /* Get PHY type set from target STA */ |
| ucPhyTypeSet = prStaRec->ucPhyTypeSet; |
| } else { |
| /* Get PHY type set from current BSS */ |
| ucPhyTypeSet = prBssInfo->ucPhyTypeSet; |
| } |
| |
| if (RLM_NET_IS_11AC(prBssInfo) && (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) |
| rlmFillVhtCapIE(prAdapter, prBssInfo, prMsduInfo); |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmRspGenerateVhtOpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| UINT_8 ucPhyTypeSet; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| |
| if (!IS_BSS_ACTIVE(prBssInfo)) |
| return; |
| |
| /* Decide PHY type set source */ |
| if (prStaRec) { |
| /* Get PHY type set from target STA */ |
| ucPhyTypeSet = prStaRec->ucPhyTypeSet; |
| } else { |
| /* Get PHY type set from current BSS */ |
| ucPhyTypeSet = prBssInfo->ucPhyTypeSet; |
| } |
| |
| if (RLM_NET_IS_11AC(prBssInfo) && (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) |
| rlmFillVhtOpIE(prAdapter, prBssInfo, prMsduInfo); |
| } |
| |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For probe request, association request |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmReqGenerateVhtOpNotificationIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| /* [TGac 5.2.46 STBC Receive Test with UCC 9.2.x] |
| * Operating Notification IE of Nss=2 will make Ralink testbed send data frames without STBC |
| * Enable the Operating Notification IE only for DBDC enable case. |
| */ |
| if (!prAdapter->rWifiVar.fgDbDcModeEn) |
| return; |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) && |
| (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC))) |
| rlmFillVhtOpNotificationIE(prAdapter, prBssInfo, prMsduInfo, TRUE); |
| } |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmRspGenerateVhtOpNotificationIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| UINT_8 ucPhyTypeSet; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| if (!prBssInfo) |
| return; |
| |
| if (!IS_BSS_ACTIVE(prBssInfo)) |
| return; |
| |
| /* Decide PHY type set source */ |
| if (prStaRec) { |
| /* Get PHY type set from target STA */ |
| ucPhyTypeSet = prStaRec->ucPhyTypeSet; |
| } else { |
| /* Get PHY type set from current BSS */ |
| ucPhyTypeSet = prBssInfo->ucPhyTypeSet; |
| } |
| |
| if (RLM_NET_IS_11AC(prBssInfo) && (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) |
| rlmFillVhtOpNotificationIE(prAdapter, prBssInfo, prMsduInfo, FALSE); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * add VHT operation notification IE for VHT-BW40 case specific |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static VOID rlmFillVhtOpNotificationIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, |
| P_MSDU_INFO_T prMsduInfo, BOOLEAN fgIsMaxCap) |
| { |
| P_IE_VHT_OP_MODE_NOTIFICATION_T prVhtOpMode; |
| UINT_8 ucMaxBw; |
| |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| ASSERT(prMsduInfo); |
| |
| prVhtOpMode = (P_IE_VHT_OP_MODE_NOTIFICATION_T) |
| (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); |
| |
| kalMemZero((PVOID) prVhtOpMode, sizeof(IE_VHT_OP_MODE_NOTIFICATION_T)); |
| |
| prVhtOpMode->ucId = ELEM_ID_OP_MODE; |
| prVhtOpMode->ucLength = sizeof(IE_VHT_OP_MODE_NOTIFICATION_T) - ELEM_HDR_LEN; |
| |
| DBGLOG(RLM, INFO, "rlmFillVhtOpNotificationIE(%d) %u %u\n", |
| prBssInfo->ucBssIndex, fgIsMaxCap, prBssInfo->ucNss); |
| |
| if (fgIsMaxCap) { |
| |
| ucMaxBw = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); |
| |
| /*handle 80P80 case*/ |
| if (ucMaxBw >= MAX_BW_160MHZ) |
| ucMaxBw = MAX_BW_160MHZ; |
| |
| prVhtOpMode->ucOperatingMode |= ucMaxBw; |
| |
| prVhtOpMode->ucOperatingMode |= |
| (((prBssInfo->ucNss-1) << VHT_OP_MODE_RX_NSS_OFFSET) & VHT_OP_MODE_RX_NSS); |
| |
| } else { |
| |
| switch (prBssInfo->ucVhtChannelWidth) { |
| case VHT_OP_CHANNEL_WIDTH_80P80: |
| ucMaxBw = MAX_BW_160MHZ; |
| break; |
| |
| case VHT_OP_CHANNEL_WIDTH_160: |
| ucMaxBw = MAX_BW_160MHZ; |
| break; |
| |
| case VHT_OP_CHANNEL_WIDTH_80: |
| ucMaxBw = MAX_BW_80MHZ; |
| break; |
| |
| case VHT_OP_CHANNEL_WIDTH_20_40: |
| { |
| ucMaxBw = MAX_BW_20MHZ; |
| |
| if (prBssInfo->eBssSCO != CHNL_EXT_SCN) |
| ucMaxBw = MAX_BW_40MHZ; |
| } |
| break; |
| |
| default: |
| /*VHT default IE should support BW 80*/ |
| ucMaxBw = MAX_BW_80MHZ; |
| break; |
| } |
| |
| prVhtOpMode->ucOperatingMode |= ucMaxBw; |
| |
| prVhtOpMode->ucOperatingMode |= (((prBssInfo->ucNss-1) |
| << VHT_OP_MODE_RX_NSS_OFFSET) & VHT_OP_MODE_RX_NSS); |
| } |
| |
| |
| prMsduInfo->u2FrameLength += IE_SIZE(prVhtOpMode); |
| |
| } |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static VOID rlmFillVhtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_IE_VHT_CAP_T prVhtCap; |
| P_VHT_SUPPORTED_MCS_FIELD prVhtSupportedMcsSet; |
| UINT_8 i; |
| UINT_8 ucMaxBw; |
| P_STA_RECORD_T prStaRec; |
| |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| ASSERT(prMsduInfo); |
| |
| prVhtCap = (P_IE_VHT_CAP_T) |
| (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); |
| |
| prVhtCap->ucId = ELEM_ID_VHT_CAP; |
| prVhtCap->ucLength = sizeof(IE_VHT_CAP_T) - ELEM_HDR_LEN; |
| prVhtCap->u4VhtCapInfo = VHT_CAP_INFO_DEFAULT_VAL; |
| |
| ucMaxBw = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); |
| |
| prVhtCap->u4VhtCapInfo |= (prAdapter->rWifiVar.ucRxMaxMpduLen & VHT_CAP_INFO_MAX_MPDU_LEN_MASK); |
| |
| if (ucMaxBw == MAX_BW_160MHZ) |
| prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160; |
| else if (ucMaxBw == MAX_BW_80_80_MHZ) |
| prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160_80P80; |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfee)) { |
| prVhtCap->u4VhtCapInfo |= FIELD_VHT_CAP_INFO_BFEE; |
| #if CFG_SUPPORT_BFEE |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| if (prStaRec && (prStaRec->ucVhtCapNumSoundingDimensions == 0x2)) { |
| /* For the compatibility with netgear R7000 AP */ |
| prVhtCap->u4VhtCapInfo |= (((UINT_32)prStaRec->ucVhtCapNumSoundingDimensions) << |
| VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_SUPPOERTED_OFFSET); |
| DBGLOG(RLM, INFO, "Set VHT Cap BFEE STS CAP=%d\n", |
| prStaRec->ucVhtCapNumSoundingDimensions); |
| } else { |
| /* For 11ac cert. VHT-5.2.63C MU-BFee step3, |
| * it requires STAUT to set its maximum STS capability here |
| */ |
| prVhtCap->u4VhtCapInfo |= |
| VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_4_SUPPOERTED; |
| DBGLOG(RLM, INFO, "Set VHT Cap BFEE STS CAP=%d\n", VHT_CAP_INFO_BEAMFORMEE_STS_CAP_MAX); |
| } |
| #endif |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtMuBfee)) |
| prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_MU_BEAMFOMEE_CAPABLE; |
| } |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfer)) |
| prVhtCap->u4VhtCapInfo |= FIELD_VHT_CAP_INFO_BFER; |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) { |
| prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; |
| |
| if (ucMaxBw >= MAX_BW_160MHZ) |
| prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_160_80P80; |
| } |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) |
| prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) { |
| UINT_8 tempRxStbcNss; |
| |
| if (prAdapter->rWifiVar.u4SwTestMode == ENUM_SW_TEST_MODE_SIGMA_AC) { |
| tempRxStbcNss = 1; |
| DBGLOG(RLM, INFO, "Set RxStbcNss to 1 for 11ac certification.\n"); |
| } else { |
| tempRxStbcNss = prAdapter->rWifiVar.ucRxStbcNss; |
| tempRxStbcNss = (tempRxStbcNss > wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) ? |
| wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex) : (tempRxStbcNss); |
| if (tempRxStbcNss != prAdapter->rWifiVar.ucRxStbcNss) { |
| DBGLOG(RLM, WARN, "Apply Nss:%d as RxStbcNss in VHT Cap", |
| wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)); |
| DBGLOG(RLM, WARN, "due to set RxStbcNss more than Nss is not appropriate.\n"); |
| } |
| } |
| prVhtCap->u4VhtCapInfo |= ((tempRxStbcNss << VHT_CAP_INFO_RX_STBC_OFFSET) & VHT_CAP_INFO_RX_STBC_MASK); |
| } |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucTxStbc)) |
| prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_TX_STBC; |
| |
| /*set MCS map */ |
| prVhtSupportedMcsSet = &prVhtCap->rVhtSupportedMcsSet; |
| kalMemZero((PVOID) prVhtSupportedMcsSet, sizeof(VHT_SUPPORTED_MCS_FIELD)); |
| |
| for (i = 0; i < 8; i++) { |
| UINT_8 ucOffset = i * 2; |
| UINT_8 ucMcsMap; |
| |
| if (i < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) |
| ucMcsMap = VHT_CAP_INFO_MCS_MAP_MCS9; |
| else |
| ucMcsMap = VHT_CAP_INFO_MCS_NOT_SUPPORTED; |
| |
| prVhtSupportedMcsSet->u2RxMcsMap |= (ucMcsMap << ucOffset); |
| prVhtSupportedMcsSet->u2TxMcsMap |= (ucMcsMap << ucOffset); |
| } |
| |
| #if 0 |
| for (i = 0; i < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex); i++) { |
| UINT_8 ucOffset = i * 2; |
| |
| prVhtSupportedMcsSet->u2RxMcsMap &= |
| ((VHT_CAP_INFO_MCS_MAP_MCS9 << ucOffset) & BITS(ucOffset, ucOffset + 1)); |
| prVhtSupportedMcsSet->u2TxMcsMap &= |
| ((VHT_CAP_INFO_MCS_MAP_MCS9 << ucOffset) & BITS(ucOffset, ucOffset + 1)); |
| } |
| #endif |
| |
| prVhtSupportedMcsSet->u2RxHighestSupportedDataRate = VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; |
| prVhtSupportedMcsSet->u2TxHighestSupportedDataRate = VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; |
| |
| ASSERT(IE_SIZE(prVhtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP)); |
| |
| prMsduInfo->u2FrameLength += IE_SIZE(prVhtCap); |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmFillVhtOpIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) |
| { |
| P_IE_VHT_OP_T prVhtOp; |
| |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| ASSERT(prMsduInfo); |
| |
| prVhtOp = (P_IE_VHT_OP_T) |
| (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); |
| |
| /* Add HT operation IE */ |
| prVhtOp->ucId = ELEM_ID_VHT_OP; |
| prVhtOp->ucLength = sizeof(IE_VHT_OP_T) - ELEM_HDR_LEN; |
| |
| ASSERT(IE_SIZE(prVhtOp) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP)); |
| |
| prVhtOp->ucVhtOperation[0] = prBssInfo->ucVhtChannelWidth; /* (UINT8)VHT_OP_CHANNEL_WIDTH_80; */ |
| prVhtOp->ucVhtOperation[1] = prBssInfo->ucVhtChannelFrequencyS1; |
| prVhtOp->ucVhtOperation[2] = prBssInfo->ucVhtChannelFrequencyS2; |
| |
| #if 0 |
| if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) < MAX_BW_80MHZ) { |
| prVhtOp->ucVhtOperation[0] = VHT_OP_CHANNEL_WIDTH_20_40; |
| prVhtOp->ucVhtOperation[1] = 0; |
| prVhtOp->ucVhtOperation[2] = 0; |
| } else if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) == MAX_BW_80MHZ) { |
| prVhtOp->ucVhtOperation[0] = VHT_OP_CHANNEL_WIDTH_80; |
| prVhtOp->ucVhtOperation[1] = nicGetVhtS1(prBssInfo->ucPrimaryChannel); |
| prVhtOp->ucVhtOperation[2] = 0; |
| } else { |
| /* TODO: BW80 + 80/160 support */ |
| } |
| #endif |
| |
| prVhtOp->u2VhtBasicMcsSet = prBssInfo->u2VhtBasicMcsSet; |
| |
| prMsduInfo->u2FrameLength += IE_SIZE(prVhtOp); |
| } |
| |
| #endif |
| |
| #if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST |
| WLAN_STATUS rlmCalBackup( |
| P_ADAPTER_T prAdapter, |
| UINT_8 ucReason, |
| UINT_8 ucAction, |
| UINT_8 ucRomRam |
| ) |
| { |
| WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; |
| P_GLUE_INFO_T prGlueInfo = NULL; |
| PARAM_CAL_BACKUP_STRUCT_V2_T rCalBackupDataV2; |
| UINT_32 u4BufLen = 0; |
| |
| ASSERT(prAdapter); |
| ASSERT(prAdapter->prGlueInfo); |
| |
| prGlueInfo = prAdapter->prGlueInfo; |
| |
| rCalBackupDataV2.ucReason = ucReason; |
| rCalBackupDataV2.ucAction = ucAction; |
| rCalBackupDataV2.ucNeedResp = 1; |
| rCalBackupDataV2.ucFragNum = 0; |
| rCalBackupDataV2.ucRomRam = ucRomRam; |
| rCalBackupDataV2.u4ThermalValue = 0; |
| rCalBackupDataV2.u4Address = 0; |
| rCalBackupDataV2.u4Length = 0; |
| rCalBackupDataV2.u4RemainLength = 0; |
| |
| if (ucReason == 0 && ucAction == 0) { |
| DBGLOG(RFTEST, INFO, "RLM CMD : Get Thermal Temp from FW.\n"); |
| /* Step 1 : Get Thermal Temp from FW */ |
| |
| rStatus = kalIoctl(prGlueInfo, |
| wlanoidQueryCalBackupV2, |
| &rCalBackupDataV2, |
| sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), |
| TRUE, |
| TRUE, |
| TRUE, |
| &u4BufLen); |
| |
| if (rStatus != WLAN_STATUS_SUCCESS) { |
| DBGLOG(RFTEST, INFO, |
| "RLM CMD : Get Thermal Temp from FW Return Fail (0x%08x)!!!!!!!!!!!\n", rStatus); |
| return rStatus; |
| } |
| |
| DBGLOG(RFTEST, INFO, "CMD : Get Thermal Temp (%d) from FW. Finish!!!!!!!!!!!\n", |
| rCalBackupDataV2.u4ThermalValue); |
| } else if (ucReason == 1 && ucAction == 2) { |
| DBGLOG(RFTEST, INFO, "RLM CMD : Trigger FW Do All Cal.\n"); |
| /* Step 2 : Trigger All Cal Function */ |
| |
| rStatus = kalIoctl(prGlueInfo, |
| wlanoidSetCalBackup, |
| &rCalBackupDataV2, |
| sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), |
| FALSE, |
| FALSE, |
| TRUE, |
| &u4BufLen); |
| |
| if (rStatus != WLAN_STATUS_SUCCESS) { |
| DBGLOG(RFTEST, INFO, |
| "RLM CMD : Trigger FW Do All Cal Return Fail (0x%08x)!!!!!!!!!!!\n", rStatus); |
| return rStatus; |
| } |
| |
| DBGLOG(RFTEST, INFO, "CMD : Trigger FW Do All Cal. Finish!!!!!!!!!!!\n"); |
| } else if (ucReason == 0 && ucAction == 1) { |
| DBGLOG(RFTEST, INFO, "RLM CMD : Get Cal Data (%s) Size from FW.\n", |
| ucRomRam == 0 ? "ROM" : "RAM"); |
| /* Step 3 : Get Cal Data Size from FW */ |
| |
| rStatus = kalIoctl(prGlueInfo, |
| wlanoidQueryCalBackupV2, |
| &rCalBackupDataV2, |
| sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), |
| TRUE, |
| TRUE, |
| TRUE, |
| &u4BufLen); |
| |
| if (rStatus != WLAN_STATUS_SUCCESS) { |
| DBGLOG(RFTEST, INFO, |
| "RLM CMD : Get Cal Data (%s) Size from FW Return Fail (0x%08x)!!!!!!!!!!!\n", |
| ucRomRam == 0 ? "ROM" : "RAM", rStatus); |
| return rStatus; |
| } |
| |
| DBGLOG(RFTEST, INFO, "CMD : Get Cal Data (%s) Size from FW. Finish!!!!!!!!!!!\n", |
| ucRomRam == 0 ? "ROM" : "RAM"); |
| } else if (ucReason == 2 && ucAction == 4) { |
| DBGLOG(RFTEST, INFO, "RLM CMD : Get Cal Data from FW (%s). Start!!!!!!!!!!!!!!!!\n", |
| ucRomRam == 0 ? "ROM" : "RAM"); |
| DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", g_rBackupCalDataAllV2.u4ThermalInfo); |
| /* Step 4 : Get Cal Data from FW */ |
| |
| rStatus = kalIoctl(prGlueInfo, |
| wlanoidQueryCalBackupV2, |
| &rCalBackupDataV2, |
| sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), |
| TRUE, |
| TRUE, |
| TRUE, |
| &u4BufLen); |
| if (rStatus != WLAN_STATUS_SUCCESS) { |
| DBGLOG(RFTEST, INFO, |
| "RLM CMD : Get Cal Data (%s) Size from FW Return Fail (0x%08x)!!!!!!!!!!!\n", |
| ucRomRam == 0 ? "ROM" : "RAM", rStatus); |
| return rStatus; |
| } |
| |
| DBGLOG(RFTEST, INFO, "CMD : Get Cal Data from FW (%s). Finish!!!!!!!!!!!\n", |
| ucRomRam == 0 ? "ROM" : "RAM"); |
| |
| if (ucRomRam == 0) { |
| DBGLOG(RFTEST, INFO, |
| "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", |
| g_rBackupCalDataAllV2.au4RomCalData[670], g_rBackupCalDataAllV2.au4RomCalData[671], |
| g_rBackupCalDataAllV2.au4RomCalData[672], g_rBackupCalDataAllV2.au4RomCalData[673], |
| g_rBackupCalDataAllV2.au4RomCalData[674]); |
| DBGLOG(RFTEST, INFO, |
| "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", |
| g_rBackupCalDataAllV2.au4RomCalData[675], g_rBackupCalDataAllV2.au4RomCalData[676], |
| g_rBackupCalDataAllV2.au4RomCalData[677], g_rBackupCalDataAllV2.au4RomCalData[678], |
| g_rBackupCalDataAllV2.au4RomCalData[679]); |
| } |
| } else if (ucReason == 4 && ucAction == 6) { |
| DBGLOG(RFTEST, INFO, "RLM CMD : Print Cal Data in FW (%s).\n", |
| ucRomRam == 0 ? "ROM" : "RAM"); |
| /* Debug Use : Print Cal Data in FW */ |
| |
| rStatus = kalIoctl(prGlueInfo, |
| wlanoidSetCalBackup, |
| &rCalBackupDataV2, |
| sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), |
| TRUE, |
| TRUE, |
| TRUE, |
| &u4BufLen); |
| |
| if (rStatus != WLAN_STATUS_SUCCESS) { |
| DBGLOG(RFTEST, INFO, |
| "RLM CMD : Print Cal Data in FW (%s) Return Fail (0x%08x)!!!!!!!!!!!\n", |
| ucRomRam == 0 ? "ROM" : "RAM", rStatus); |
| return rStatus; |
| } |
| |
| DBGLOG(RFTEST, INFO, "CMD : Print Cal Data in FW (%s). Finish!!!!!!!!!!!\n", |
| ucRomRam == 0 ? "ROM" : "RAM"); |
| } else if (ucReason == 3 && ucAction == 5) { |
| DBGLOG(RFTEST, INFO, "RLM CMD : Send Cal Data to FW (%s).\n", |
| ucRomRam == 0 ? "ROM" : "RAM"); |
| /* Send Cal Data to FW */ |
| |
| rStatus = kalIoctl(prGlueInfo, |
| wlanoidSetCalBackup, |
| &rCalBackupDataV2, |
| sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), |
| TRUE, |
| TRUE, |
| TRUE, |
| &u4BufLen); |
| |
| if (rStatus != WLAN_STATUS_SUCCESS) { |
| DBGLOG(RFTEST, INFO, |
| "RLM CMD : Send Cal Data to FW (%s) Return Fail (0x%08x)!!!!!!!!!!!\n", |
| ucRomRam == 0 ? "ROM" : "RAM", rStatus); |
| return rStatus; |
| } |
| |
| DBGLOG(RFTEST, INFO, "CMD : Send Cal Data to FW (%s). Finish!!!!!!!!!!!\n", |
| ucRomRam == 0 ? "ROM" : "RAM"); |
| } else { |
| DBGLOG(RFTEST, INFO, "CMD : Undefined Reason (%d) and Action (%d) for Cal Backup in Host Side!\n", |
| ucReason, ucAction); |
| |
| return rStatus; |
| } |
| |
| return rStatus; |
| } |
| |
| WLAN_STATUS rlmTriggerCalBackup( |
| P_ADAPTER_T prAdapter, |
| BOOLEAN fgIsCalDataBackuped |
| ) |
| { |
| WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; |
| |
| if (!fgIsCalDataBackuped) { |
| DBGLOG(RFTEST, INFO, "======== Boot Time Wi-Fi Enable........\n"); |
| DBGLOG(RFTEST, INFO, "Step 0 : Reset All Cal Data in Driver.\n"); |
| memset(&g_rBackupCalDataAllV2, 1, sizeof(RLM_CAL_RESULT_ALL_V2_T)); |
| g_rBackupCalDataAllV2.u4MagicNum1 = 6632; |
| g_rBackupCalDataAllV2.u4MagicNum2 = 6632; |
| |
| DBGLOG(RFTEST, INFO, "Step 1 : Get Thermal Temp from FW.\n"); |
| if (rlmCalBackup(prAdapter, 0, 0, 0) == WLAN_STATUS_FAILURE) { |
| DBGLOG(RFTEST, INFO, "Step 1 : Return Failure.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| DBGLOG(RFTEST, INFO, "Step 2 : Get Rom Cal Data Size from FW.\n"); |
| if (rlmCalBackup(prAdapter, 0, 1, 0) == WLAN_STATUS_FAILURE) { |
| DBGLOG(RFTEST, INFO, "Step 2 : Return Failure.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| DBGLOG(RFTEST, INFO, "Step 3 : Get Ram Cal Data Size from FW.\n"); |
| if (rlmCalBackup(prAdapter, 0, 1, 1) == WLAN_STATUS_FAILURE) { |
| DBGLOG(RFTEST, INFO, "Step 3 : Return Failure.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| DBGLOG(RFTEST, INFO, "Step 4 : Trigger FW Do Full Cal.\n"); |
| if (rlmCalBackup(prAdapter, 1, 2, 0) == WLAN_STATUS_FAILURE) { |
| DBGLOG(RFTEST, INFO, "Step 4 : Return Failure.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| } else { |
| DBGLOG(RFTEST, INFO, "======== Normal Wi-Fi Enable........\n"); |
| DBGLOG(RFTEST, INFO, "Step 0 : Sent Rom Cal data to FW.\n"); |
| if (rlmCalBackup(prAdapter, 3, 5, 0) == WLAN_STATUS_FAILURE) { |
| DBGLOG(RFTEST, INFO, "Step 0 : Return Failure.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| DBGLOG(RFTEST, INFO, "Step 1 : Sent Ram Cal data to FW.\n"); |
| if (rlmCalBackup(prAdapter, 3, 5, 1) == WLAN_STATUS_FAILURE) { |
| DBGLOG(RFTEST, INFO, "Step 1 : Return Failure.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| } |
| |
| return rStatus; |
| } |
| #endif |
| |
| VOID rlmModifyVhtBwPara( |
| PUINT_8 pucVhtChannelFrequencyS1, |
| PUINT_8 pucVhtChannelFrequencyS2, |
| PUINT_8 pucVhtChannelWidth |
| ) |
| { |
| UINT_8 i = 0, ucTempS = 0; |
| |
| if ((*pucVhtChannelFrequencyS1 != 0) && |
| (*pucVhtChannelFrequencyS2 != 0)) { |
| |
| UINT_8 ucBW160Inteval = 8; |
| |
| DBGLOG(RLM, WARN, "S1=%d, S2=%d\n", *pucVhtChannelFrequencyS1, *pucVhtChannelFrequencyS2); |
| |
| if (((*pucVhtChannelFrequencyS2 - *pucVhtChannelFrequencyS1) == ucBW160Inteval) || |
| ((*pucVhtChannelFrequencyS1 - *pucVhtChannelFrequencyS2) == ucBW160Inteval)) { |
| /*C160 case*/ |
| |
| /*NEW spec should set central ch of bw80 at S1, |
| *set central ch of bw160 at S2 |
| */ |
| for (i = 0; i < 2; i++) { |
| |
| if (i == 0) |
| ucTempS = *pucVhtChannelFrequencyS1; |
| else |
| ucTempS = *pucVhtChannelFrequencyS2; |
| |
| if ((ucTempS == 50) || (ucTempS == 82) || |
| (ucTempS == 114) || (ucTempS == 163)) |
| break; |
| } |
| |
| |
| if (ucTempS == 0) { |
| DBGLOG(RLM, WARN, "please check BW160 setting, find central freq fail\n"); |
| return; |
| } |
| |
| *pucVhtChannelFrequencyS1 = ucTempS; |
| *pucVhtChannelFrequencyS2 = 0; |
| *pucVhtChannelWidth = CW_160MHZ; |
| DBGLOG(RLM, WARN, "[BW160][new spec] S1 change to %d\n", *pucVhtChannelFrequencyS1); |
| } else { |
| /*real 80P80 case*/ |
| } |
| |
| } |
| |
| } |
| |
| static VOID rlmRevisePreferBandwidthNss( |
| P_ADAPTER_T prAdapter, |
| UINT_8 ucBssIndex, |
| P_STA_RECORD_T prStaRec |
| ) |
| { |
| ENUM_CHANNEL_WIDTH_T eChannelWidth = CW_20_40MHZ; |
| P_BSS_INFO_T prBssInfo; |
| |
| #define VHT_MCS_TX_RX_MAX_2SS BITS(2, 3) |
| #define VHT_MCS_TX_RX_MAX_2SS_SHIFT 2 |
| |
| #define AR_STA_2AC_MCS(prStaRec) \ |
| (((prStaRec)->u2VhtRxMcsMap & VHT_MCS_TX_RX_MAX_2SS) >> VHT_MCS_TX_RX_MAX_2SS_SHIFT) |
| |
| #define AR_IS_STA_2SS_AC(prStaRec) \ |
| ((AR_STA_2AC_MCS(prStaRec) != BITS(0, 1))) |
| |
| |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| |
| eChannelWidth = prBssInfo->ucVhtChannelWidth; |
| |
| /* |
| *Prefer setting modification |
| *80+80 1x1 and 80 2x2 have the same phy rate, choose the 80 2x2 |
| */ |
| |
| if (AR_IS_STA_2SS_AC(prStaRec)) { |
| /* |
| *DBGLOG(RLM, WARN, "support 2ss\n"); |
| */ |
| |
| if ((eChannelWidth == CW_80P80MHZ && prBssInfo->ucVhtChannelFrequencyS2 != 0)) { |
| DBGLOG(RLM, WARN, "support (2Nss) and (80+80)\n"); |
| DBGLOG(RLM, WARN, "choose (2Nss) and (80) for Bss_info\n"); |
| prBssInfo->ucVhtChannelWidth = CW_80MHZ; |
| prBssInfo->ucVhtChannelFrequencyS2 = 0; |
| } |
| } |
| } |
| |
| VOID rlmReviseMaxBw( |
| P_ADAPTER_T prAdapter, |
| UINT_8 ucBssIndex, |
| P_ENUM_CHNL_EXT_T peExtend, |
| P_ENUM_CHANNEL_WIDTH_P peChannelWidth, |
| PUINT_8 pucS1, |
| PUINT_8 pucPrimaryCh) |
| { |
| UINT_8 ucMaxBandwidth = MAX_BW_80MHZ; |
| UINT_8 ucCurrentBandwidth = MAX_BW_20MHZ; |
| UINT_8 ucOffset = (MAX_BW_80MHZ - CW_80MHZ); |
| |
| ucMaxBandwidth = cnmGetBssMaxBw(prAdapter, ucBssIndex); |
| |
| if (*peChannelWidth > CW_20_40MHZ) { |
| /*case BW > 80 , 160 80P80 */ |
| ucCurrentBandwidth = (UINT_8)*peChannelWidth + ucOffset; |
| } else { |
| /*case BW20 BW40 */ |
| if (*peExtend != CHNL_EXT_SCN) { |
| /*case BW40 */ |
| ucCurrentBandwidth = MAX_BW_40MHZ; |
| } |
| } |
| |
| if (ucCurrentBandwidth > ucMaxBandwidth) { |
| DBGLOG(RLM, INFO, "Decreasse the BW to (%d)\n", ucMaxBandwidth); |
| |
| if (ucMaxBandwidth <= MAX_BW_40MHZ) { |
| /*BW20 * BW40*/ |
| *peChannelWidth = CW_20_40MHZ; |
| |
| if (ucMaxBandwidth == MAX_BW_20MHZ) |
| *peExtend = CHNL_EXT_SCN; |
| } else { |
| /* BW80, BW160, BW80P80 */ |
| /* ucMaxBandwidth Must be MAX_BW_80MHZ,MAX_BW_160MHZ,MAX_BW_80MHZ */ |
| /* peExtend should not change */ |
| *peChannelWidth = (ucMaxBandwidth - ucOffset); |
| |
| if (ucMaxBandwidth == MAX_BW_80MHZ) { |
| /* modify S1 for Bandwidth 160 downgrade 80 case */ |
| if (ucCurrentBandwidth == MAX_BW_160MHZ) { |
| if ((*pucPrimaryCh >= 36) && (*pucPrimaryCh <= 48)) |
| *pucS1 = 42; |
| else if ((*pucPrimaryCh >= 52) && (*pucPrimaryCh <= 64)) |
| *pucS1 = 58; |
| else if ((*pucPrimaryCh >= 100) && (*pucPrimaryCh <= 112)) |
| *pucS1 = 106; |
| else if ((*pucPrimaryCh >= 116) && (*pucPrimaryCh <= 128)) |
| *pucS1 = 122; |
| else if ((*pucPrimaryCh >= 132) && (*pucPrimaryCh <= 144)) |
| *pucS1 = 138; /*160 downgrade should not in this case*/ |
| else if ((*pucPrimaryCh >= 149) && (*pucPrimaryCh <= 161)) |
| *pucS1 = 155; /*160 downgrade should not in this case*/ |
| else |
| DBGLOG(RLM, INFO, "Check connect 160 downgrde (%d) case\n" |
| , ucMaxBandwidth); |
| |
| DBGLOG(RLM, INFO, "Decreasse the BW160 to BW80, shift S1 to (%d)\n", *pucS1); |
| } |
| } |
| } |
| |
| DBGLOG(RLM, INFO, "Modify ChannelWidth (%d) and Extend (%d)\n", *peChannelWidth, *peExtend); |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Change VHT OP Channel Width, S1, S2 |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmChangeVhtOpBwPara(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 ucChannelWidth) |
| { |
| P_BSS_INFO_T prBssInfo; |
| UINT_8 ucVhtLowerChannelFrequency, ucVhtUpperChannelFrequency = 0; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| |
| if (!prBssInfo) |
| return; |
| |
| if (ucChannelWidth == MAX_BW_80_80_MHZ) |
| prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_80P80; |
| else if (ucChannelWidth == MAX_BW_160MHZ) |
| prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_160; |
| else if (ucChannelWidth == MAX_BW_80MHZ) { |
| prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_80; |
| if (prBssInfo->ucVhtPeerChannelWidth == VHT_OP_CHANNEL_WIDTH_160) |
| prBssInfo->ucVhtChannelFrequencyS1 = |
| (prBssInfo->ucVhtPeerChannelFrequencyS1 > prBssInfo->ucPrimaryChannel) ? |
| (prBssInfo->ucVhtPeerChannelFrequencyS1 - 8) : (prBssInfo->ucVhtPeerChannelFrequencyS1 + 8); |
| else if (prBssInfo->ucVhtPeerChannelWidth == VHT_OP_CHANNEL_WIDTH_80P80) { |
| if (prBssInfo->ucVhtChannelFrequencyS1 < prBssInfo->ucVhtChannelFrequencyS2) { |
| ucVhtLowerChannelFrequency = prBssInfo->ucVhtChannelFrequencyS1; |
| ucVhtUpperChannelFrequency = prBssInfo->ucVhtChannelFrequencyS2; |
| } else { |
| ucVhtLowerChannelFrequency = prBssInfo->ucVhtChannelFrequencyS2; |
| ucVhtUpperChannelFrequency = prBssInfo->ucVhtChannelFrequencyS1; |
| } |
| prBssInfo->ucVhtChannelFrequencyS1 = prBssInfo->ucPrimaryChannel < |
| ((ucVhtLowerChannelFrequency + ucVhtUpperChannelFrequency)/2) ? |
| ucVhtLowerChannelFrequency : ucVhtUpperChannelFrequency; |
| prBssInfo->ucVhtChannelFrequencyS2 = 0; |
| } |
| } else if ((ucChannelWidth == MAX_BW_40MHZ) || (ucChannelWidth == MAX_BW_20MHZ)) |
| prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function should be invoked to update parameters of associated AP. |
| * (Association response and Beacon) |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static UINT_8 rlmRecIeInfoForClient(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pucIE, UINT_16 u2IELength) |
| { |
| UINT_16 u2Offset; |
| P_STA_RECORD_T prStaRec; |
| P_IE_HT_CAP_T prHtCap; |
| P_IE_HT_OP_T prHtOp; |
| P_IE_OBSS_SCAN_PARAM_T prObssScnParam; |
| UINT_8 ucERP, ucPrimaryChannel; |
| P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; |
| #if CFG_SUPPORT_QUIET && 0 |
| BOOLEAN fgHasQuietIE = FALSE; |
| #endif |
| BOOLEAN IsfgHtCapChange = FALSE; |
| |
| #if CFG_SUPPORT_802_11AC |
| P_IE_VHT_OP_T prVhtOp; |
| P_IE_VHT_CAP_T prVhtCap; |
| P_IE_OP_MODE_NOTIFICATION_T prOPModeNotification; /* Operation Mode Notification */ |
| BOOLEAN fgHasOPModeIE = FALSE; |
| UINT_8 ucVhtOpModeChannelWidth = 0; |
| UINT_8 ucVhtOpModeRxNss = 0; |
| UINT_8 ucVhtCapMcsOwnNotSupportOffset; |
| UINT_8 ucMaxBwAllowed; |
| UINT_8 ucInitVhtOpMode = 0; |
| #endif |
| |
| #if CFG_SUPPORT_DFS |
| BOOLEAN fgHasWideBandIE = FALSE; |
| BOOLEAN fgHasSCOIE = FALSE; |
| BOOLEAN fgHasChannelSwitchIE = FALSE; |
| BOOLEAN fgNeedSwitchChannel = FALSE; |
| UINT_8 ucChannelAnnouncePri; |
| ENUM_CHNL_EXT_T eChannelAnnounceSco; |
| UINT_8 ucChannelAnnounceChannelS1 = 0; |
| UINT_8 ucChannelAnnounceChannelS2 = 0; |
| UINT_8 ucChannelAnnounceVhtBw; |
| P_IE_CHANNEL_SWITCH_T prChannelSwitchAnnounceIE; |
| P_IE_SECONDARY_OFFSET_T prSecondaryOffsetIE; |
| P_IE_WIDE_BAND_CHANNEL_T prWideBandChannelIE; |
| #endif |
| PUINT_8 pucDumpIE; |
| |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| ASSERT(pucIE); |
| |
| prStaRec = prBssInfo->prStaRecOfAP; |
| ASSERT(prStaRec); |
| if (!prStaRec) |
| return 0; |
| |
| prBssInfo->fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; |
| ucPrimaryChannel = 0; |
| prObssScnParam = NULL; |
| ucMaxBwAllowed = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); |
| pucDumpIE = pucIE; |
| |
| /* Note: HT-related members in staRec may not be zero before, so |
| * if following IE does not exist, they are still not zero. |
| * These HT-related parameters are valid only when the corresponding |
| * BssInfo supports 802.11n, i.e., RLM_NET_IS_11N() |
| */ |
| IE_FOR_EACH(pucIE, u2IELength, u2Offset) { |
| switch (IE_ID(pucIE)) { |
| case ELEM_ID_HT_CAP: |
| if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) |
| break; |
| prHtCap = (P_IE_HT_CAP_T) pucIE; |
| prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; |
| prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; |
| |
| kalMemCopy(prStaRec->aucRxMcsBitmask, prHtCap->rSupMcsSet.aucRxMcsBitmask, |
| sizeof(prStaRec->aucRxMcsBitmask) /*SUP_MCS_RX_BITMASK_OCTET_NUM */); |
| |
| prStaRec->u2RxHighestSupportedRate = prHtCap->rSupMcsSet.u2RxHighestSupportedRate; |
| prStaRec->u4TxRateInfo = prHtCap->rSupMcsSet.u4TxRateInfo; |
| |
| if ((prStaRec->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE) != |
| (prHtCap->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE)) |
| IsfgHtCapChange = TRUE;/* Purpose : To detect SMPS change */ |
| |
| prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; |
| /* Set LDPC Tx capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxLdpc)) |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; |
| else if (IS_FEATURE_DISABLED(prWifiVar->ucTxLdpc)) |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_LDPC_CAP; |
| |
| /* Set STBC Tx capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxStbc)) |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_RX_STBC; |
| else if (IS_FEATURE_DISABLED(prWifiVar->ucTxStbc)) |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_RX_STBC; |
| |
| /* Set Short GI Tx capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxShortGI)) { |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_SHORT_GI_20M; |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_SHORT_GI_40M; |
| } else if (IS_FEATURE_DISABLED(prWifiVar->ucTxShortGI)) { |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SHORT_GI_20M; |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SHORT_GI_40M; |
| } |
| |
| /* Set HT Greenfield Tx capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxGf)) |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; |
| else if (IS_FEATURE_DISABLED(prWifiVar->ucTxGf)) |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; |
| |
| prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; |
| prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; |
| prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; |
| prStaRec->ucAselCap = prHtCap->ucAselCap; |
| break; |
| |
| case ELEM_ID_HT_OP: |
| if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) |
| break; |
| prHtOp = (P_IE_HT_OP_T) pucIE; |
| /* Workaround that some APs fill primary channel field by its |
| * secondary channel, but its DS IE is correct 20110610 |
| */ |
| if (ucPrimaryChannel == 0) |
| ucPrimaryChannel = prHtOp->ucPrimaryChannel; |
| prBssInfo->ucHtOpInfo1 = prHtOp->ucInfo1; |
| prBssInfo->u2HtOpInfo2 = prHtOp->u2Info2; |
| prBssInfo->u2HtOpInfo3 = prHtOp->u2Info3; |
| |
| /*Backup peer HT OP Info*/ |
| prBssInfo->ucHtPeerOpInfo1 = prHtOp->ucInfo1; |
| |
| if (!prBssInfo->fg40mBwAllowed) |
| prBssInfo->ucHtOpInfo1 &= ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); |
| |
| if ((prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) |
| prBssInfo->eBssSCO = (ENUM_CHNL_EXT_T) (prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_SCO); |
| |
| if (prBssInfo->ucOpChangeChannelWidth == MAX_BW_20MHZ && prBssInfo->fgIsOpChangeChannelWidth) { |
| prBssInfo->ucHtOpInfo1 &= ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); |
| prBssInfo->eBssSCO = CHNL_EXT_SCN; |
| } |
| |
| prBssInfo->eHtProtectMode = (ENUM_HT_PROTECT_MODE_T) |
| (prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_HT_PROTECTION); |
| |
| /* To do: process regulatory class 16 */ |
| if ((prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT) |
| && 0 /* && regulatory class is 16 */) |
| prBssInfo->eGfOperationMode = GF_MODE_DISALLOWED; |
| else if (prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_NON_GF_HT_STA_PRESENT) |
| prBssInfo->eGfOperationMode = GF_MODE_PROTECT; |
| else |
| prBssInfo->eGfOperationMode = GF_MODE_NORMAL; |
| |
| prBssInfo->eRifsOperationMode = |
| (prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_RIFS_MODE) ? RIFS_MODE_NORMAL : RIFS_MODE_DISALLOWED; |
| |
| break; |
| |
| #if CFG_SUPPORT_802_11AC |
| case ELEM_ID_VHT_CAP: |
| if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_VHT_CAP_T) - 2)) |
| break; |
| |
| prVhtCap = (P_IE_VHT_CAP_T) pucIE; |
| |
| prStaRec->u4VhtCapInfo = prVhtCap->u4VhtCapInfo; |
| /* Set Tx LDPC capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxLdpc)) |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; |
| else if (IS_FEATURE_DISABLED(prWifiVar->ucTxLdpc)) |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_RX_LDPC; |
| |
| /* Set Tx STBC capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxStbc)) |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_RX_STBC_MASK; |
| else if (IS_FEATURE_DISABLED(prWifiVar->ucTxStbc)) |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_RX_STBC_MASK; |
| |
| /* Set Tx TXOP PS capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxopPsTx)) |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_VHT_TXOP_PS; |
| else if (IS_FEATURE_DISABLED(prWifiVar->ucTxopPsTx)) |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_VHT_TXOP_PS; |
| |
| /* Set Tx Short GI capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxShortGI)) { |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_160_80P80; |
| } else if (IS_FEATURE_DISABLED(prWifiVar->ucTxShortGI)) { |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_SHORT_GI_80; |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_SHORT_GI_160_80P80; |
| } |
| |
| /*Set Vht Rx Mcs Map upon peer's capability and our capability */ |
| prStaRec->u2VhtRxMcsMap = prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap; |
| if (wlanGetSupportNss(prAdapter, prStaRec->ucBssIndex) < 8) { |
| ucVhtCapMcsOwnNotSupportOffset = wlanGetSupportNss(prAdapter, prStaRec->ucBssIndex) * 2; |
| /*Mark Rx Mcs Map which we don't support*/ |
| prStaRec->u2VhtRxMcsMap |= BITS(ucVhtCapMcsOwnNotSupportOffset, 15); |
| } |
| if (prStaRec->u2VhtRxMcsMap != prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap) |
| DBGLOG(RLM, INFO, "Change VhtRxMcsMap from 0x%x to 0x%x due to our Nss setting\n", |
| prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap, prStaRec->u2VhtRxMcsMap); |
| |
| prStaRec->u2VhtRxHighestSupportedDataRate = |
| prVhtCap->rVhtSupportedMcsSet.u2RxHighestSupportedDataRate; |
| prStaRec->u2VhtTxMcsMap = prVhtCap->rVhtSupportedMcsSet.u2TxMcsMap; |
| prStaRec->u2VhtTxHighestSupportedDataRate = |
| prVhtCap->rVhtSupportedMcsSet.u2TxHighestSupportedDataRate; |
| |
| break; |
| |
| case ELEM_ID_VHT_OP: |
| if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_VHT_OP_T) - 2)) |
| break; |
| |
| prVhtOp = (P_IE_VHT_OP_T) pucIE; |
| |
| /*Backup peer VHT OpInfo*/ |
| prBssInfo->ucVhtPeerChannelWidth = prVhtOp->ucVhtOperation[0]; |
| prBssInfo->ucVhtPeerChannelFrequencyS1 = prVhtOp->ucVhtOperation[1]; |
| prBssInfo->ucVhtPeerChannelFrequencyS2 = prVhtOp->ucVhtOperation[2]; |
| |
| rlmModifyVhtBwPara(&prBssInfo->ucVhtPeerChannelFrequencyS1, |
| &prBssInfo->ucVhtPeerChannelFrequencyS2, |
| &prBssInfo->ucVhtPeerChannelWidth); |
| |
| prBssInfo->ucVhtChannelWidth = prVhtOp->ucVhtOperation[0]; |
| prBssInfo->ucVhtChannelFrequencyS1 = prVhtOp->ucVhtOperation[1]; |
| prBssInfo->ucVhtChannelFrequencyS2 = prVhtOp->ucVhtOperation[2]; |
| prBssInfo->u2VhtBasicMcsSet = prVhtOp->u2VhtBasicMcsSet; |
| |
| rlmModifyVhtBwPara(&prBssInfo->ucVhtChannelFrequencyS1, |
| &prBssInfo->ucVhtChannelFrequencyS2, |
| &prBssInfo->ucVhtChannelWidth); |
| |
| if (prBssInfo->fgIsOpChangeChannelWidth) |
| rlmChangeVhtOpBwPara(prAdapter, prBssInfo->ucBssIndex, |
| prBssInfo->ucOpChangeChannelWidth); |
| |
| /* Set initial value of VHT OP mode */ |
| ucInitVhtOpMode = 0; |
| switch (prBssInfo->ucVhtChannelWidth) { |
| case VHT_OP_CHANNEL_WIDTH_20_40: |
| ucInitVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_40; |
| break; |
| case VHT_OP_CHANNEL_WIDTH_80: |
| ucInitVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_80; |
| break; |
| case VHT_OP_CHANNEL_WIDTH_160: |
| case VHT_OP_CHANNEL_WIDTH_80P80: |
| ucInitVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_160_80P80; |
| break; |
| default: |
| ucInitVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_80; |
| break; |
| } |
| ucInitVhtOpMode |= ((prBssInfo->ucNss-1) << VHT_OP_MODE_RX_NSS_OFFSET) & VHT_OP_MODE_RX_NSS; |
| break; |
| case ELEM_ID_OP_MODE: |
| if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_OP_MODE_NOTIFICATION_T) - 2)) |
| break; |
| prOPModeNotification = (P_IE_OP_MODE_NOTIFICATION_T) pucIE; |
| |
| if ((prOPModeNotification->ucOpMode & VHT_OP_MODE_RX_NSS_TYPE) |
| != VHT_OP_MODE_RX_NSS_TYPE) { |
| if (prStaRec->ucVhtOpMode != prOPModeNotification->ucOpMode) { |
| prStaRec->ucVhtOpMode = prOPModeNotification->ucOpMode; |
| fgHasOPModeIE = TRUE; |
| ucVhtOpModeChannelWidth = |
| ((prOPModeNotification->ucOpMode) & VHT_OP_MODE_CHANNEL_WIDTH); |
| ucVhtOpModeRxNss = |
| ((prOPModeNotification->ucOpMode) & VHT_OP_MODE_RX_NSS) >> |
| VHT_OP_MODE_RX_NSS_OFFSET; |
| } else /* Let the further flow not to update VhtOpMode */ |
| ucInitVhtOpMode = prStaRec->ucVhtOpMode; |
| } |
| |
| break; |
| #if CFG_SUPPORT_DFS |
| case ELEM_ID_WIDE_BAND_CHANNEL_SWITCH: |
| if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_WIDE_BAND_CHANNEL_T) - 2)) |
| break; |
| DBGLOG(RLM, INFO, "[Channel Switch] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, 11AC\n"); |
| prWideBandChannelIE = (P_IE_WIDE_BAND_CHANNEL_T) pucIE; |
| ucChannelAnnounceVhtBw = prWideBandChannelIE->ucNewChannelWidth; |
| ucChannelAnnounceChannelS1 = prWideBandChannelIE->ucChannelS1; |
| ucChannelAnnounceChannelS2 = prWideBandChannelIE->ucChannelS2; |
| fgHasWideBandIE = TRUE; |
| DBGLOG(RLM, INFO, |
| "[Ch] BW=%d, s1=%d, s2=%d\n", ucChannelAnnounceVhtBw, ucChannelAnnounceChannelS1, |
| ucChannelAnnounceChannelS2); |
| break; |
| #endif |
| |
| #endif |
| case ELEM_ID_20_40_BSS_COEXISTENCE: |
| if (!RLM_NET_IS_11N(prBssInfo)) |
| break; |
| /* To do: store if scanning exemption grant to BssInfo */ |
| break; |
| |
| case ELEM_ID_OBSS_SCAN_PARAMS: |
| if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_OBSS_SCAN_PARAM_T) - 2)) |
| break; |
| /* Store OBSS parameters to BssInfo */ |
| prObssScnParam = (P_IE_OBSS_SCAN_PARAM_T) pucIE; |
| break; |
| |
| case ELEM_ID_EXTENDED_CAP: |
| if (!RLM_NET_IS_11N(prBssInfo)) |
| break; |
| /* To do: store extended capability (PSMP, coexist) to BssInfo */ |
| break; |
| |
| case ELEM_ID_ERP_INFO: |
| if (IE_LEN(pucIE) != (sizeof(IE_ERP_T) - 2) || prBssInfo->eBand != BAND_2G4) |
| break; |
| ucERP = ERP_INFO_IE(pucIE)->ucERP; |
| prBssInfo->fgErpProtectMode = (ucERP & ERP_INFO_USE_PROTECTION) ? TRUE : FALSE; |
| |
| if (ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) |
| prBssInfo->fgUseShortPreamble = FALSE; |
| break; |
| |
| case ELEM_ID_DS_PARAM_SET: |
| if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) |
| ucPrimaryChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; |
| break; |
| #if CFG_SUPPORT_DFS |
| case ELEM_ID_CH_SW_ANNOUNCEMENT: |
| if (IE_LEN(pucIE) != (sizeof(IE_CHANNEL_SWITCH_T) - 2)) |
| break; |
| |
| prChannelSwitchAnnounceIE = (P_IE_CHANNEL_SWITCH_T) pucIE; |
| |
| DBGLOG(RLM, INFO, "[Ch] Count=%d\n", prChannelSwitchAnnounceIE->ucChannelSwitchCount); |
| |
| if (prChannelSwitchAnnounceIE->ucChannelSwitchMode == 1) { |
| /* Need to stop data transmission immediately */ |
| fgHasChannelSwitchIE = TRUE; |
| if (!g_fgHasStopTx) { |
| g_fgHasStopTx = TRUE; |
| #if CFG_SUPPORT_TDLS |
| /* TDLS peers */ |
| TdlsTxCtrl(prAdapter, prBssInfo, FALSE); |
| #endif |
| /* AP */ |
| qmSetStaRecTxAllowed(prAdapter, prStaRec, FALSE); |
| DBGLOG(RLM, EVENT, "[Ch] TxAllowed = FALSE\n"); |
| } |
| |
| if (prChannelSwitchAnnounceIE->ucChannelSwitchCount <= 3) { |
| DBGLOG(RLM, INFO, |
| "[Ch] switch channel [%d]->[%d]\n", prBssInfo->ucPrimaryChannel, |
| prChannelSwitchAnnounceIE->ucNewChannelNum); |
| ucChannelAnnouncePri = prChannelSwitchAnnounceIE->ucNewChannelNum; |
| fgNeedSwitchChannel = TRUE; |
| g_fgHasChannelSwitchIE = TRUE; |
| } |
| |
| if (RLM_NET_IS_11AC(prBssInfo)) { |
| DBGLOG(RLM, INFO, "Send Operation Action Frame"); |
| rlmSendOpModeNotificationFrame(prAdapter, prStaRec, |
| VHT_OP_MODE_CHANNEL_WIDTH_20, 1); |
| } else { |
| DBGLOG(RLM, INFO, "Skip Send Operation Action Frame"); |
| } |
| } |
| |
| break; |
| case ELEM_ID_SCO: |
| if (IE_LEN(pucIE) != (sizeof(IE_SECONDARY_OFFSET_T) - 2)) |
| break; |
| |
| prSecondaryOffsetIE = (P_IE_SECONDARY_OFFSET_T) pucIE; |
| DBGLOG(RLM, INFO, |
| "[Channel Switch] SCO [%d]->[%d]\n", prBssInfo->eBssSCO, |
| prSecondaryOffsetIE->ucSecondaryOffset); |
| eChannelAnnounceSco = (ENUM_CHNL_EXT_T) prSecondaryOffsetIE->ucSecondaryOffset; |
| fgHasSCOIE = TRUE; |
| break; |
| #endif |
| |
| #if CFG_SUPPORT_QUIET && 0 |
| /* Note: RRM code should be moved to independent RRM function by |
| * component design rule. But we attach it to RLM temporarily |
| */ |
| case ELEM_ID_QUIET: |
| rrmQuietHandleQuietIE(prBssInfo, (P_IE_QUIET_T) pucIE); |
| fgHasQuietIE = TRUE; |
| break; |
| #endif |
| default: |
| break; |
| } /* end of switch */ |
| } /* end of IE_FOR_EACH */ |
| |
| if (IsfgHtCapChange && (prStaRec->ucStaState == STA_STATE_3)) |
| cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); |
| |
| /* Some AP will have wrong channel number (255) when running time. |
| * Check if correct channel number information. 20110501 |
| */ |
| if ((prBssInfo->eBand == BAND_2G4 && ucPrimaryChannel > 14) || |
| (prBssInfo->eBand != BAND_2G4 && (ucPrimaryChannel >= 200 || ucPrimaryChannel <= 14))) |
| ucPrimaryChannel = 0; |
| #if CFG_SUPPORT_802_11AC |
| /* Check whether the Operation Mode IE is exist or not. |
| * If exists, then the channel bandwidth of VHT operation field is changed |
| * with the channel bandwidth setting of Operation Mode field. |
| * The channel bandwidth of OP Mode IE is 0, represent as 20MHz. |
| * The channel bandwidth of OP Mode IE is 1, represent as 40MHz. |
| * The channel bandwidth of OP Mode IE is 2, represent as 80MHz. |
| * The channel bandwidth of OP Mode IE is 3, represent as 160/80+80MHz. |
| */ |
| if (fgHasOPModeIE == TRUE) { |
| /* 1.Channel width change */ |
| |
| if (ucVhtOpModeChannelWidth == VHT_OP_MODE_CHANNEL_WIDTH_20) { |
| prBssInfo->ucVhtChannelWidth = CW_20_40MHZ; |
| prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; |
| |
| #if CFG_WORKAROUND_OPMODE_CONFLICT_OPINFO |
| if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { |
| DBGLOG(RLM, WARN, "HT_OP_Info != OPmode_Notifify, follow OPmode_Notify to BW20.\n"); |
| prBssInfo->eBssSCO = CHNL_EXT_SCN; |
| } |
| #endif |
| } |
| |
| else if (ucVhtOpModeChannelWidth == VHT_OP_MODE_CHANNEL_WIDTH_40) { |
| prBssInfo->ucVhtChannelWidth = CW_20_40MHZ; |
| prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; |
| |
| #if CFG_WORKAROUND_OPMODE_CONFLICT_OPINFO |
| if (prBssInfo->eBssSCO == CHNL_EXT_SCN) { |
| prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; |
| DBGLOG(RLM, WARN, "HT_OP_Info != OPmode_Notifify, follow HT_OP_Info to BW20.\n"); |
| } |
| #endif |
| } |
| |
| else if (ucVhtOpModeChannelWidth == VHT_OP_MODE_CHANNEL_WIDTH_80) { |
| prBssInfo->ucVhtChannelWidth = CW_80MHZ; |
| prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_MASK; |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; |
| } |
| |
| else if (ucVhtOpModeChannelWidth == VHT_OP_MODE_CHANNEL_WIDTH_160_80P80) { |
| prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; |
| |
| /* Use VHT OP Info to determine it's BW160 or BW80+BW80 */ |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_MASK; |
| if (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_160) |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160; |
| else if (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_80P80) |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160_80P80; |
| } |
| |
| if (prStaRec->ucStaState == STA_STATE_3) { |
| DBGLOG(RLM, INFO, "Update OpMode to 0x%x", prStaRec->ucVhtOpMode); |
| DBGLOG(RLM, INFO, "to FW due to OpMode Notificaition\n"); |
| cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); |
| } |
| } else {/* Set Default if the VHT OP mode field is not present */ |
| if ((prStaRec->ucVhtOpMode != ucInitVhtOpMode) && (prStaRec->ucStaState == STA_STATE_3)) { |
| prStaRec->ucVhtOpMode = ucInitVhtOpMode; |
| DBGLOG(RLM, INFO, "Update OpMode to 0x%x", prStaRec->ucVhtOpMode); |
| DBGLOG(RLM, INFO, "to FW due to NO OpMode Notificaition\n"); |
| cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); |
| } else |
| prStaRec->ucVhtOpMode = ucInitVhtOpMode; |
| } |
| #endif |
| |
| #if CFG_SUPPORT_DFS |
| /*Check whether Channel Announcement IE, Secondary Offset IE & |
| * Wide Bandwidth Channel Switch IE exist or not. If exist, the priority is |
| the highest. |
| */ |
| |
| if (fgNeedSwitchChannel) { |
| P_BSS_DESC_T prBssDesc; |
| |
| prBssInfo->ucPrimaryChannel = ucChannelAnnouncePri; |
| prBssInfo->ucVhtChannelWidth = 0; |
| prBssInfo->ucVhtChannelFrequencyS1 = 0; |
| prBssInfo->ucVhtChannelFrequencyS2 = 0; |
| prBssInfo->eBssSCO = 0; |
| |
| prBssDesc = scanSearchBssDescByBssid(prAdapter, prBssInfo->aucBSSID); |
| |
| if (prBssDesc) { |
| DBGLOG(RLM, INFO, "DFS: BSS: " MACSTR " Desc found, channel from %u to %u\n ", |
| MAC2STR(prBssInfo->aucBSSID), prBssDesc->ucChannelNum, ucChannelAnnouncePri); |
| prBssDesc->ucChannelNum = ucChannelAnnouncePri; |
| } else { |
| DBGLOG(RLM, INFO, "DFS: BSS: " MACSTR " Desc is not found\n ", MAC2STR(prBssInfo->aucBSSID)); |
| } |
| |
| if (fgHasWideBandIE != FALSE) { |
| prBssInfo->ucVhtChannelWidth = ucChannelAnnounceVhtBw; |
| prBssInfo->ucVhtChannelFrequencyS1 = ucChannelAnnounceChannelS1; |
| prBssInfo->ucVhtChannelFrequencyS2 = ucChannelAnnounceChannelS2; |
| } |
| if (fgHasSCOIE != FALSE) |
| prBssInfo->eBssSCO = eChannelAnnounceSco; |
| } |
| |
| if (!fgHasChannelSwitchIE && g_fgHasStopTx) { |
| #if CFG_SUPPORT_TDLS |
| /* TDLS peers */ |
| TdlsTxCtrl(prAdapter, prBssInfo, TRUE); |
| #endif |
| /* AP */ |
| qmSetStaRecTxAllowed(prAdapter, prStaRec, TRUE); |
| |
| DBGLOG(RLM, EVENT, "[Ch] TxAllowed = TRUE\n"); |
| g_fgHasStopTx = FALSE; |
| } |
| |
| /*DFS Certification for Channel Bandwidth 20MHz */ |
| DBGLOG(RLM, INFO, "Ch : SwitchIE = %d\n", g_fgHasChannelSwitchIE); |
| if (g_fgHasChannelSwitchIE == TRUE) { |
| prBssInfo->eBssSCO = CHNL_EXT_SCN; |
| prBssInfo->ucVhtChannelWidth = CW_20_40MHZ; |
| prBssInfo->ucVhtChannelFrequencyS1 = 0; |
| prBssInfo->ucVhtChannelFrequencyS2 = 255; |
| prBssInfo->ucHtOpInfo1 &= ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); |
| DBGLOG(RLM, INFO, "Ch : DFS has Appeared\n"); |
| } |
| #endif |
| rlmReviseMaxBw(prAdapter, prBssInfo->ucBssIndex, &prBssInfo->eBssSCO, |
| (P_ENUM_CHANNEL_WIDTH_P)&prBssInfo->ucVhtChannelWidth, |
| &prBssInfo->ucVhtChannelFrequencyS1, &prBssInfo->ucPrimaryChannel); |
| |
| rlmRevisePreferBandwidthNss(prAdapter, prBssInfo->ucBssIndex, prStaRec); |
| |
| /*printk("Modify ChannelWidth (%d) and Extend (%d)\n",prBssInfo->eBssSCO,prBssInfo->ucVhtChannelWidth);*/ |
| |
| if (!rlmDomainIsValidRfSetting(prAdapter, prBssInfo->eBand, |
| prBssInfo->ucPrimaryChannel, prBssInfo->eBssSCO, |
| prBssInfo->ucVhtChannelWidth, prBssInfo->ucVhtChannelFrequencyS1, |
| prBssInfo->ucVhtChannelFrequencyS2)) { |
| |
| /*Dump IE Inforamtion */ |
| DBGLOG(RLM, WARN, "rlmRecIeInfoForClient IE Information\n"); |
| DBGLOG(RLM, WARN, "IE Length = %d\n", u2IELength); |
| DBGLOG_MEM8(RLM, WARN, pucDumpIE, u2IELength); |
| |
| /*Error Handling for Non-predicted IE - Fixed to set 20MHz */ |
| prBssInfo->ucVhtChannelWidth = CW_20_40MHZ; |
| prBssInfo->ucVhtChannelFrequencyS1 = 0; |
| prBssInfo->ucVhtChannelFrequencyS2 = 0; |
| prBssInfo->eBssSCO = CHNL_EXT_SCN; |
| prBssInfo->ucHtOpInfo1 &= ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); |
| } |
| #if CFG_SUPPORT_QUIET && 0 |
| if (!fgHasQuietIE) |
| rrmQuietIeNotExist(prAdapter, prBssInfo); |
| #endif |
| |
| /* Check if OBSS scan process will launch */ |
| if (!prAdapter->fgEnOnlineScan || !prObssScnParam || |
| !(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH) || |
| prBssInfo->eBand != BAND_2G4 || !prBssInfo->fg40mBwAllowed) { |
| |
| /* Note: it is ok not to stop rObssScanTimer() here */ |
| prBssInfo->u2ObssScanInterval = 0; |
| } else { |
| if (prObssScnParam->u2TriggerScanInterval < OBSS_SCAN_MIN_INTERVAL) |
| prObssScnParam->u2TriggerScanInterval = OBSS_SCAN_MIN_INTERVAL; |
| if (prBssInfo->u2ObssScanInterval != prObssScnParam->u2TriggerScanInterval) { |
| |
| prBssInfo->u2ObssScanInterval = prObssScnParam->u2TriggerScanInterval; |
| |
| /* Start timer to trigger OBSS scanning */ |
| cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, |
| prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); |
| } |
| } |
| |
| return ucPrimaryChannel; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Update parameters from Association Response frame |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static VOID |
| rlmRecAssocRespIeInfoForClient(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pucIE, UINT_16 u2IELength) |
| { |
| UINT_16 u2Offset; |
| P_STA_RECORD_T prStaRec; |
| BOOLEAN fgIsHasHtCap = FALSE; |
| BOOLEAN fgIsHasVhtCap = FALSE; |
| P_BSS_DESC_T prBssDesc; |
| |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| ASSERT(pucIE); |
| |
| prStaRec = prBssInfo->prStaRecOfAP; |
| |
| ASSERT(prStaRec); |
| if (!prStaRec) |
| return; |
| |
| prBssDesc = scanSearchBssDescByBssid(prAdapter, prStaRec->aucMacAddr); |
| |
| IE_FOR_EACH(pucIE, u2IELength, u2Offset) { |
| switch (IE_ID(pucIE)) { |
| case ELEM_ID_HT_CAP: |
| if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) |
| break; |
| fgIsHasHtCap = TRUE; |
| break; |
| #if CFG_SUPPORT_802_11AC |
| case ELEM_ID_VHT_CAP: |
| if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_VHT_CAP_T) - 2)) |
| break; |
| fgIsHasVhtCap = TRUE; |
| break; |
| #endif |
| default: |
| break; |
| } /* end of switch */ |
| } /* end of IE_FOR_EACH */ |
| |
| if (!fgIsHasHtCap) { |
| prStaRec->ucDesiredPhyTypeSet &= ~PHY_TYPE_BIT_HT; |
| if (prBssDesc) { |
| if (prBssDesc->ucPhyTypeSet & PHY_TYPE_BIT_HT) { |
| DBGLOG(RLM, WARN, "PhyTypeSet in Beacon and AssocResp are unsync. "); |
| DBGLOG(RLM, WARN, "Follow AssocResp to disable HT.\n"); |
| } |
| } |
| } |
| if (!fgIsHasVhtCap) { |
| prStaRec->ucDesiredPhyTypeSet &= ~PHY_TYPE_BIT_VHT; |
| if (prBssDesc) { |
| if (prBssDesc->ucPhyTypeSet & PHY_TYPE_BIT_VHT) { |
| DBGLOG(RLM, WARN, "PhyTypeSet in Beacon and AssocResp are unsync. "); |
| DBGLOG(RLM, WARN, "Follow AssocResp to disable VHT.\n"); |
| } |
| } |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief AIS or P2P GC. |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static BOOLEAN |
| rlmRecBcnFromNeighborForClient(P_ADAPTER_T prAdapter, |
| P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) |
| { |
| UINT_16 u2Offset, i; |
| UINT_8 ucPriChannel, ucSecChannel; |
| ENUM_CHNL_EXT_T eSCO; |
| BOOLEAN fgHtBss, fg20mReq; |
| |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo && prSwRfb); |
| ASSERT(pucIE); |
| |
| /* Record it to channel list to change 20/40 bandwidth */ |
| ucPriChannel = 0; |
| eSCO = CHNL_EXT_SCN; |
| |
| fgHtBss = FALSE; |
| fg20mReq = FALSE; |
| |
| IE_FOR_EACH(pucIE, u2IELength, u2Offset) { |
| switch (IE_ID(pucIE)) { |
| case ELEM_ID_HT_CAP: |
| { |
| P_IE_HT_CAP_T prHtCap; |
| |
| if (IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) |
| break; |
| |
| prHtCap = (P_IE_HT_CAP_T) pucIE; |
| if (prHtCap->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) |
| fg20mReq = TRUE; |
| fgHtBss = TRUE; |
| break; |
| } |
| case ELEM_ID_HT_OP: |
| { |
| P_IE_HT_OP_T prHtOp; |
| |
| if (IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) |
| break; |
| |
| prHtOp = (P_IE_HT_OP_T) pucIE; |
| /* Workaround that some APs fill primary channel field by its |
| * secondary channel, but its DS IE is correct 20110610 |
| */ |
| if (ucPriChannel == 0) |
| ucPriChannel = prHtOp->ucPrimaryChannel; |
| |
| if ((prHtOp->ucInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) |
| eSCO = (ENUM_CHNL_EXT_T) (prHtOp->ucInfo1 & HT_OP_INFO1_SCO); |
| break; |
| } |
| case ELEM_ID_20_40_BSS_COEXISTENCE: |
| { |
| P_IE_20_40_COEXIST_T prCoexist; |
| |
| if (IE_LEN(pucIE) != (sizeof(IE_20_40_COEXIST_T) - 2)) |
| break; |
| |
| prCoexist = (P_IE_20_40_COEXIST_T) pucIE; |
| if (prCoexist->ucData & BSS_COEXIST_40M_INTOLERANT) |
| fg20mReq = TRUE; |
| break; |
| } |
| case ELEM_ID_DS_PARAM_SET: |
| if (IE_LEN(pucIE) != (sizeof(IE_DS_PARAM_SET_T) - 2)) |
| break; |
| ucPriChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| /* To do: Update channel list and 5G band. All channel lists have the same |
| * update procedure. We should give it the entry pointer of desired |
| * channel list. |
| */ |
| if (HAL_RX_STATUS_GET_RF_BAND(prSwRfb->prRxStatus) != BAND_2G4) |
| return FALSE; |
| |
| if (ucPriChannel == 0 || ucPriChannel > 14) |
| ucPriChannel = HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus); |
| |
| if (fgHtBss) { |
| ASSERT(prBssInfo->auc2G_PriChnlList[0] <= CHNL_LIST_SZ_2G); |
| for (i = 1; i <= prBssInfo->auc2G_PriChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { |
| if (prBssInfo->auc2G_PriChnlList[i] == ucPriChannel) |
| break; |
| } |
| if ((i > prBssInfo->auc2G_PriChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { |
| prBssInfo->auc2G_PriChnlList[i] = ucPriChannel; |
| prBssInfo->auc2G_PriChnlList[0]++; |
| } |
| |
| /* Update secondary channel */ |
| if (eSCO != CHNL_EXT_SCN) { |
| ucSecChannel = (eSCO == CHNL_EXT_SCA) ? (ucPriChannel + 4) : (ucPriChannel - 4); |
| |
| ASSERT(prBssInfo->auc2G_SecChnlList[0] <= CHNL_LIST_SZ_2G); |
| for (i = 1; i <= prBssInfo->auc2G_SecChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { |
| if (prBssInfo->auc2G_SecChnlList[i] == ucSecChannel) |
| break; |
| } |
| if ((i > prBssInfo->auc2G_SecChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { |
| prBssInfo->auc2G_SecChnlList[i] = ucSecChannel; |
| prBssInfo->auc2G_SecChnlList[0]++; |
| } |
| } |
| |
| /* Update 20M bandwidth request channels */ |
| if (fg20mReq) { |
| ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); |
| for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { |
| if (prBssInfo->auc2G_20mReqChnlList[i] == ucPriChannel) |
| break; |
| } |
| if ((i > prBssInfo->auc2G_20mReqChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { |
| prBssInfo->auc2G_20mReqChnlList[i] = ucPriChannel; |
| prBssInfo->auc2G_20mReqChnlList[0]++; |
| } |
| } |
| } else { |
| /* Update non-HT channel list */ |
| ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); |
| for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { |
| if (prBssInfo->auc2G_NonHtChnlList[i] == ucPriChannel) |
| break; |
| } |
| if ((i > prBssInfo->auc2G_NonHtChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { |
| prBssInfo->auc2G_NonHtChnlList[i] = ucPriChannel; |
| prBssInfo->auc2G_NonHtChnlList[0]++; |
| } |
| |
| } |
| |
| return FALSE; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief AIS or P2P GC. |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static BOOLEAN |
| rlmRecBcnInfoForClient(P_ADAPTER_T prAdapter, |
| P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) |
| { |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo && prSwRfb); |
| ASSERT(pucIE); |
| |
| #if 0 /* SW migration 2010/8/20 */ |
| /* Note: we shall not update parameters when scanning, otherwise |
| * channel and bandwidth will not be correct or asserted failure |
| * during scanning. |
| * Note: remove channel checking. All received Beacons should be processed |
| * if measurement or other actions are executed in adjacent channels |
| * and Beacon content checking mechanism is not disabled. |
| */ |
| if (IS_SCAN_ACTIVE() |
| /* || prBssInfo->ucPrimaryChannel != CHNL_NUM_BY_SWRFB(prSwRfb) */ |
| ) { |
| return FALSE; |
| } |
| #endif |
| |
| /* Handle change of slot time */ |
| prBssInfo->u2CapInfo = ((P_WLAN_BEACON_FRAME_T) (prSwRfb->pvHeader))->u2CapInfo; |
| prBssInfo->fgUseShortSlotTime = ((prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) |
| || (prBssInfo->eBand != BAND_2G4)) ? TRUE : FALSE; |
| |
| rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); |
| |
| return TRUE; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmProcessBcn(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) |
| { |
| P_BSS_INFO_T prBssInfo; |
| BOOLEAN fgNewParameter; |
| UINT_8 i; |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| ASSERT(pucIE); |
| |
| fgNewParameter = FALSE; |
| |
| /* When concurrent networks exist, GO shall have the same handle as |
| * the other BSS, so the Beacon shall be processed for bandwidth and |
| * protection mechanism. |
| * Note1: we do not have 2 AP (GO) cases simultaneously now. |
| * Note2: If we are GO, concurrent AIS AP should detect it and reflect |
| * action in its Beacon, so AIS STA just follows Beacon from AP. |
| */ |
| for (i = 0; i < BSS_INFO_NUM; i++) { |
| prBssInfo = prAdapter->aprBssInfo[i]; |
| |
| if (IS_BSS_BOW(prBssInfo)) |
| continue; |
| |
| if (IS_BSS_ACTIVE(prBssInfo)) { |
| if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && |
| prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { |
| /* P2P client or AIS infra STA */ |
| if (EQUAL_MAC_ADDR(prBssInfo->aucBSSID, ((P_WLAN_MAC_MGMT_HEADER_T) |
| (prSwRfb->pvHeader))->aucBSSID)) { |
| |
| fgNewParameter = rlmRecBcnInfoForClient(prAdapter, |
| prBssInfo, prSwRfb, pucIE, u2IELength); |
| } else { |
| fgNewParameter = rlmRecBcnFromNeighborForClient(prAdapter, |
| prBssInfo, |
| prSwRfb, pucIE, u2IELength); |
| } |
| } |
| #if CFG_ENABLE_WIFI_DIRECT |
| else if (prAdapter->fgIsP2PRegistered && |
| (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT || |
| prBssInfo->eCurrentOPMode == OP_MODE_P2P_DEVICE)) { |
| /* AP scan to check if 20/40M bandwidth is permitted */ |
| rlmRecBcnFromNeighborForClient(prAdapter, prBssInfo, prSwRfb, pucIE, u2IELength); |
| } |
| #endif |
| else if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { |
| /* To do: Nothing */ |
| /* To do: Ad-hoc */ |
| } |
| |
| /* Appy new parameters if necessary */ |
| if (fgNewParameter) { |
| rlmSyncOperationParams(prAdapter, prBssInfo); |
| fgNewParameter = FALSE; |
| } |
| } /* end of IS_BSS_ACTIVE() */ |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function should be invoked after judging successful association. |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmProcessAssocRsp(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| UINT_8 ucPriChannel; |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| ASSERT(pucIE); |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); |
| if (!prStaRec) |
| return; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); |
| if (!prBssInfo) |
| return; |
| |
| if (prStaRec != prBssInfo->prStaRecOfAP) |
| return; |
| |
| /* To do: the invoked function is used to clear all members. It may be |
| * done by center mechanism in invoker. |
| */ |
| rlmBssReset(prAdapter, prBssInfo); |
| |
| prBssInfo->fgUseShortSlotTime = ((prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) |
| || (prBssInfo->eBand != BAND_2G4)) ? TRUE : FALSE; |
| ucPriChannel = rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); |
| |
| /*Update the parameters from Association Response only, |
| *if the parameters need to be updated by both Beacon and Association Response, |
| *user should use another function, rlmRecIeInfoForClient() |
| */ |
| rlmRecAssocRespIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); |
| |
| if (prBssInfo->ucPrimaryChannel != ucPriChannel) { |
| DBGLOG(RLM, INFO, |
| "Use RF pri channel[%u].Pri channel in HT OP IE is :[%u]\n", prBssInfo->ucPrimaryChannel, |
| ucPriChannel); |
| } |
| /*Avoid wrong primary channel info in HT operation IE info when accept association response */ |
| #if 0 |
| if (ucPriChannel > 0) |
| prBssInfo->ucPrimaryChannel = ucPriChannel; |
| #endif |
| |
| if (!RLM_NET_IS_11N(prBssInfo) || !(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) |
| prBssInfo->fg40mBwAllowed = FALSE; |
| |
| /* Note: Update its capabilities to WTBL by cnmStaRecChangeState(), which |
| * shall be invoked afterwards. |
| * Update channel, bandwidth and protection mode by nicUpdateBss() |
| */ |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmProcessHtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) |
| { |
| P_ACTION_NOTIFY_CHNL_WIDTH_FRAME prRxFrame; |
| P_ACTION_SM_POWER_SAVE_FRAME prRxSmpsFrame; |
| P_STA_RECORD_T prStaRec; |
| P_BSS_INFO_T prBssInfo; |
| UINT_16 u2HtCapInfoBitmask = 0; |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prRxFrame = (P_ACTION_NOTIFY_CHNL_WIDTH_FRAME) prSwRfb->pvHeader; |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); |
| |
| if (!prStaRec) |
| return; |
| |
| switch (prRxFrame->ucAction) { |
| case ACTION_HT_NOTIFY_CHANNEL_WIDTH: |
| if (prStaRec->ucStaState != STA_STATE_3 || |
| prSwRfb->u2PacketLen < sizeof(ACTION_NOTIFY_CHNL_WIDTH_FRAME)) { |
| return; |
| } |
| |
| /* To do: depending regulation class 13 and 14 based on spec |
| * Note: (ucChannelWidth==1) shall restored back to original capability, |
| * not current setting to 40MHz BW here |
| */ |
| /* 1. Update StaRec for AP/STA mode */ |
| if (prRxFrame->ucChannelWidth == 0) |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; |
| else if (prRxFrame->ucChannelWidth == 1) |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; |
| |
| cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); |
| |
| /* 2. Update BssInfo for STA mode */ |
| prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; |
| if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { |
| if (prRxFrame->ucChannelWidth == 0) |
| prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; |
| if (prRxFrame->ucChannelWidth == 1) |
| prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; |
| |
| nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); |
| } |
| break; |
| /* Support SM power save */ /* TH3_Huang */ |
| case ACTION_HT_SM_POWER_SAVE: |
| prRxSmpsFrame = (P_ACTION_SM_POWER_SAVE_FRAME) prSwRfb->pvHeader; |
| if (prStaRec->ucStaState != STA_STATE_3 || |
| prSwRfb->u2PacketLen < sizeof(ACTION_SM_POWER_SAVE_FRAME)) { |
| return; |
| } |
| |
| /* The SM power enable bit is different definition in HtCap and SMpower IE field */ |
| if (!(prRxSmpsFrame->ucSmPowerCtrl & |
| (HT_SM_POWER_SAVE_CONTROL_ENABLED|HT_SM_POWER_SAVE_CONTROL_SM_MODE))) |
| u2HtCapInfoBitmask |= HT_CAP_INFO_SM_POWER_SAVE; |
| |
| /* Support SMPS action frame, TH3_Huang */ |
| /* Update StaRec if SM power state changed */ |
| if ((prStaRec->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE) != u2HtCapInfoBitmask) { |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SM_POWER_SAVE; |
| prStaRec->u2HtCapInfo |= u2HtCapInfoBitmask; |
| DBGLOG(RLM, INFO, |
| "rlmProcessHtAction -- SMPS change u2HtCapInfo to (%x)\n", |
| prStaRec->u2HtCapInfo); |
| cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| |
| #if CFG_SUPPORT_802_11AC |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmProcessVhtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) |
| { |
| P_ACTION_OP_MODE_NOTIFICATION_FRAME prRxFrame; |
| P_STA_RECORD_T prStaRec; |
| P_BSS_INFO_T prBssInfo; |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prRxFrame = (P_ACTION_OP_MODE_NOTIFICATION_FRAME) prSwRfb->pvHeader; |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); |
| |
| if (!prStaRec) |
| return; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); |
| |
| if (!prBssInfo) |
| return; |
| |
| switch (prRxFrame->ucAction) { |
| /* Support Operating mode notification action frame, TH3_Huang */ |
| case ACTION_OPERATING_MODE_NOTIFICATION: |
| if (prStaRec->ucStaState != STA_STATE_3 || |
| prSwRfb->u2PacketLen < sizeof(ACTION_OP_MODE_NOTIFICATION_FRAME)) { |
| return; |
| } |
| |
| if (((prRxFrame->ucOperatingMode & VHT_OP_MODE_RX_NSS_TYPE) |
| != VHT_OP_MODE_RX_NSS_TYPE) && |
| (prStaRec->ucVhtOpMode != prRxFrame->ucOperatingMode)) { |
| prStaRec->ucVhtOpMode = prRxFrame->ucOperatingMode; |
| DBGLOG(RLM, INFO, |
| "rlmProcessVhtAction -- Update ucVhtOpMode to 0x%x\n", prStaRec->ucVhtOpMode); |
| cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| #endif |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function should be invoked after judging successful association. |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmFillSyncCmdParam(P_CMD_SET_BSS_RLM_PARAM_T prCmdBody, P_BSS_INFO_T prBssInfo) |
| { |
| ASSERT(prCmdBody && prBssInfo); |
| if (!prCmdBody || !prBssInfo) |
| return; |
| |
| prCmdBody->ucBssIndex = prBssInfo->ucBssIndex; |
| prCmdBody->ucRfBand = (UINT_8) prBssInfo->eBand; |
| prCmdBody->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; |
| prCmdBody->ucRfSco = (UINT_8) prBssInfo->eBssSCO; |
| prCmdBody->ucErpProtectMode = (UINT_8) prBssInfo->fgErpProtectMode; |
| prCmdBody->ucHtProtectMode = (UINT_8) prBssInfo->eHtProtectMode; |
| prCmdBody->ucGfOperationMode = (UINT_8) prBssInfo->eGfOperationMode; |
| prCmdBody->ucTxRifsMode = (UINT_8) prBssInfo->eRifsOperationMode; |
| prCmdBody->u2HtOpInfo3 = prBssInfo->u2HtOpInfo3; |
| prCmdBody->u2HtOpInfo2 = prBssInfo->u2HtOpInfo2; |
| prCmdBody->ucHtOpInfo1 = prBssInfo->ucHtOpInfo1; |
| prCmdBody->ucUseShortPreamble = prBssInfo->fgUseShortPreamble; |
| prCmdBody->ucUseShortSlotTime = prBssInfo->fgUseShortSlotTime; |
| prCmdBody->ucVhtChannelWidth = prBssInfo->ucVhtChannelWidth; |
| prCmdBody->ucVhtChannelFrequencyS1 = prBssInfo->ucVhtChannelFrequencyS1; |
| prCmdBody->ucVhtChannelFrequencyS2 = prBssInfo->ucVhtChannelFrequencyS2; |
| prCmdBody->u2VhtBasicMcsSet = prBssInfo->u2BSSBasicRateSet; |
| prCmdBody->ucNss = prBssInfo->ucNss; |
| |
| if (RLM_NET_PARAM_VALID(prBssInfo)) { |
| DBGLOG(RLM, INFO, "N=%d b=%d c=%d s=%d e=%d h=%d I=0x%02x l=%d p=%d w=%d s1=%d s2=%d n=%d\n", |
| prCmdBody->ucBssIndex, prCmdBody->ucRfBand, |
| prCmdBody->ucPrimaryChannel, prCmdBody->ucRfSco, |
| prCmdBody->ucErpProtectMode, prCmdBody->ucHtProtectMode, |
| prCmdBody->ucHtOpInfo1, prCmdBody->ucUseShortSlotTime, |
| prCmdBody->ucUseShortPreamble, |
| prCmdBody->ucVhtChannelWidth, |
| prCmdBody->ucVhtChannelFrequencyS1, prCmdBody->ucVhtChannelFrequencyS2, |
| prCmdBody->ucNss); |
| } else { |
| DBGLOG(RLM, INFO, "N=%d closed\n", prCmdBody->ucBssIndex); |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function will operation parameters based on situations of |
| * concurrent networks. Channel, bandwidth, protection mode, supported |
| * rate will be modified. |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmSyncOperationParams(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) |
| { |
| P_CMD_SET_BSS_RLM_PARAM_T prCmdBody; |
| WLAN_STATUS rStatus; |
| |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| |
| prCmdBody = (P_CMD_SET_BSS_RLM_PARAM_T) |
| cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_BSS_RLM_PARAM_T)); |
| |
| /* ASSERT(prCmdBody); */ |
| /* To do: exception handle */ |
| if (!prCmdBody) { |
| DBGLOG(RLM, WARN, "No buf for sync RLM params (Net=%d)\n", prBssInfo->ucBssIndex); |
| return; |
| } |
| |
| rlmFillSyncCmdParam(prCmdBody, prBssInfo); |
| |
| rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ |
| CMD_ID_SET_BSS_RLM_PARAM, /* ucCID */ |
| TRUE, /* fgSetQuery */ |
| FALSE, /* fgNeedResp */ |
| FALSE, /* fgIsOid */ |
| NULL, /* pfCmdDoneHandler */ |
| NULL, /* pfCmdTimeoutHandler */ |
| sizeof(CMD_SET_BSS_RLM_PARAM_T), /* u4SetQueryInfoLen */ |
| (PUINT_8) prCmdBody, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| |
| /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ |
| if (rStatus != WLAN_STATUS_PENDING) |
| DBGLOG(RLM, WARN, "rlmSyncOperationParams set cmd fail\n"); |
| |
| cnmMemFree(prAdapter, prCmdBody); |
| } |
| |
| #if CFG_SUPPORT_AAA |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function should be invoked after judging successful association. |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmProcessAssocReq(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| UINT_16 u2Offset; |
| P_IE_HT_CAP_T prHtCap; |
| #if CFG_SUPPORT_802_11AC |
| P_IE_VHT_CAP_T prVhtCap; |
| UINT_8 ucVhtCapMcsOwnNotSupportOffset; |
| /* UINT_8 ucVhtCapMcsPeerNotSupportOffset; */ |
| P_IE_OP_MODE_NOTIFICATION_T prOPModeNotification; /* Operation Mode Notification */ |
| #endif |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| ASSERT(pucIE); |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); |
| if (!prStaRec) |
| return; |
| ASSERT(prStaRec->ucBssIndex <= MAX_BSS_INDEX); |
| |
| prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; |
| |
| IE_FOR_EACH(pucIE, u2IELength, u2Offset) { |
| switch (IE_ID(pucIE)) { |
| case ELEM_ID_HT_CAP: |
| if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) |
| break; |
| prHtCap = (P_IE_HT_CAP_T) pucIE; |
| prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; |
| prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; |
| |
| kalMemCopy(prStaRec->aucRxMcsBitmask, prHtCap->rSupMcsSet.aucRxMcsBitmask, |
| sizeof(prStaRec->aucRxMcsBitmask) /*SUP_MCS_RX_BITMASK_OCTET_NUM */); |
| |
| prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; |
| |
| /* Set Short LDPC Tx capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxLdpc)) |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; |
| else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxLdpc)) |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_LDPC_CAP; |
| |
| /* Set STBC Tx capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxStbc)) |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_TX_STBC; |
| else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxStbc)) |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_TX_STBC; |
| /* Set Short GI Tx capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxShortGI)) { |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_SHORT_GI_20M; |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_SHORT_GI_40M; |
| } else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxShortGI)) { |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SHORT_GI_20M; |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SHORT_GI_40M; |
| } |
| |
| /* Set HT Greenfield Tx capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxGf)) |
| prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; |
| else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxGf)) |
| prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; |
| |
| prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; |
| prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; |
| prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; |
| prStaRec->ucAselCap = prHtCap->ucAselCap; |
| break; |
| |
| #if CFG_SUPPORT_802_11AC |
| case ELEM_ID_VHT_CAP: |
| if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_VHT_CAP_T) - 2)) |
| break; |
| |
| prVhtCap = (P_IE_VHT_CAP_T) pucIE; |
| |
| prStaRec->u4VhtCapInfo = prVhtCap->u4VhtCapInfo; |
| |
| /* Set Tx LDPC capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxLdpc)) |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; |
| else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxLdpc)) |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_RX_LDPC; |
| |
| /* Set Tx STBC capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxStbc)) |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_TX_STBC; |
| else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxStbc)) |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_TX_STBC; |
| |
| /* Set Tx TXOP PS capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxopPsTx)) |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_VHT_TXOP_PS; |
| else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxopPsTx)) |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_VHT_TXOP_PS; |
| |
| /* Set Tx Short GI capability */ |
| if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxShortGI)) { |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; |
| prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_160_80P80; |
| } else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxShortGI)) { |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_SHORT_GI_80; |
| prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_SHORT_GI_160_80P80; |
| } |
| |
| /*Set Vht Rx Mcs Map upon peer's capability and our capability */ |
| prStaRec->u2VhtRxMcsMap = prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap; |
| if (wlanGetSupportNss(prAdapter, prStaRec->ucBssIndex) < 8) { |
| ucVhtCapMcsOwnNotSupportOffset = |
| wlanGetSupportNss(prAdapter, prStaRec->ucBssIndex) * 2; |
| prStaRec->u2VhtRxMcsMap |= BITS(ucVhtCapMcsOwnNotSupportOffset, 15); |
| /*Mark Rx Mcs Map which we don't support*/ |
| } |
| if (prStaRec->u2VhtRxMcsMap != prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap) |
| DBGLOG(RLM, INFO, "Change VhtRxMcsMap from 0x%x to 0x%x due to our Nss setting\n", |
| prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap, |
| prStaRec->u2VhtRxMcsMap); |
| |
| prStaRec->u2VhtRxHighestSupportedDataRate = |
| prVhtCap->rVhtSupportedMcsSet.u2RxHighestSupportedDataRate; |
| prStaRec->u2VhtTxMcsMap = prVhtCap->rVhtSupportedMcsSet.u2TxMcsMap; |
| prStaRec->u2VhtTxHighestSupportedDataRate = |
| prVhtCap->rVhtSupportedMcsSet.u2TxHighestSupportedDataRate; |
| |
| /* Set initial value of VHT OP mode */ |
| prStaRec->ucVhtOpMode = 0; |
| switch (prBssInfo->ucVhtChannelWidth) { |
| case VHT_OP_CHANNEL_WIDTH_20_40: |
| prStaRec->ucVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_40; |
| break; |
| case VHT_OP_CHANNEL_WIDTH_80: |
| prStaRec->ucVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_80; |
| break; |
| case VHT_OP_CHANNEL_WIDTH_160: |
| case VHT_OP_CHANNEL_WIDTH_80P80: |
| prStaRec->ucVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_160_80P80; |
| break; |
| default: |
| prStaRec->ucVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_80; |
| break; |
| } |
| prStaRec->ucVhtOpMode |= ((prBssInfo->ucNss-1) << |
| VHT_OP_MODE_RX_NSS_OFFSET) & VHT_OP_MODE_RX_NSS; |
| |
| break; |
| case ELEM_ID_OP_MODE: |
| if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_OP_MODE_NOTIFICATION_T) - 2)) |
| break; |
| prOPModeNotification = (P_IE_OP_MODE_NOTIFICATION_T) pucIE; |
| |
| if ((prOPModeNotification->ucOpMode & VHT_OP_MODE_RX_NSS_TYPE) |
| != VHT_OP_MODE_RX_NSS_TYPE) { |
| prStaRec->ucVhtOpMode = prOPModeNotification->ucOpMode; |
| } |
| |
| break; |
| |
| #endif |
| |
| default: |
| break; |
| } /* end of switch */ |
| } /* end of IE_FOR_EACH */ |
| } |
| #endif /* CFG_SUPPORT_AAA */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief It is for both STA and AP modes |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmBssInitForAPandIbss(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) |
| { |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| |
| #if CFG_ENABLE_WIFI_DIRECT |
| if (prAdapter->fgIsP2PRegistered && prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) |
| rlmBssInitForAP(prAdapter, prBssInfo); |
| #endif |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief It is for both STA and AP modes |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmBssAborted(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) |
| { |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| |
| rlmBssReset(prAdapter, prBssInfo); |
| |
| prBssInfo->fg40mBwAllowed = FALSE; |
| prBssInfo->fgAssoc40mBwAllowed = FALSE; |
| |
| /* Assume FW state is updated by CMD_ID_SET_BSS_INFO, so |
| * the sync CMD is not needed here. |
| */ |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief All RLM timers will also be stopped. |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static VOID rlmBssReset(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) |
| { |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| |
| /* HT related parameters */ |
| prBssInfo->ucHtOpInfo1 = 0; /* RIFS disabled. 20MHz */ |
| prBssInfo->u2HtOpInfo2 = 0; |
| prBssInfo->u2HtOpInfo3 = 0; |
| |
| #if CFG_SUPPORT_802_11AC |
| prBssInfo->ucVhtChannelWidth = 0; /* VHT_OP_CHANNEL_WIDTH_80; */ |
| prBssInfo->ucVhtChannelFrequencyS1 = 0; /* 42; */ |
| prBssInfo->ucVhtChannelFrequencyS2 = 0; |
| prBssInfo->u2VhtBasicMcsSet = 0; /* 0xFFFF; */ |
| #endif |
| |
| prBssInfo->eBssSCO = 0; |
| prBssInfo->fgErpProtectMode = 0; |
| prBssInfo->eHtProtectMode = 0; |
| prBssInfo->eGfOperationMode = 0; |
| prBssInfo->eRifsOperationMode = 0; |
| |
| /* OBSS related parameters */ |
| prBssInfo->auc2G_20mReqChnlList[0] = 0; |
| prBssInfo->auc2G_NonHtChnlList[0] = 0; |
| prBssInfo->auc2G_PriChnlList[0] = 0; |
| prBssInfo->auc2G_SecChnlList[0] = 0; |
| prBssInfo->auc5G_20mReqChnlList[0] = 0; |
| prBssInfo->auc5G_NonHtChnlList[0] = 0; |
| prBssInfo->auc5G_PriChnlList[0] = 0; |
| prBssInfo->auc5G_SecChnlList[0] = 0; |
| |
| /* All RLM timers will also be stopped */ |
| cnmTimerStopTimer(prAdapter, &prBssInfo->rObssScanTimer); |
| prBssInfo->u2ObssScanInterval = 0; |
| |
| prBssInfo->fgObssErpProtectMode = 0; /* GO only */ |
| prBssInfo->eObssHtProtectMode = 0; /* GO only */ |
| prBssInfo->eObssGfOperationMode = 0; /* GO only */ |
| prBssInfo->fgObssRifsOperationMode = 0; /* GO only */ |
| prBssInfo->fgObssActionForcedTo20M = 0; /* GO only */ |
| prBssInfo->fgObssBeaconForcedTo20M = 0; /* GO only */ |
| } |
| |
| #if CFG_SUPPORT_TDLS |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_32 rlmFillVhtCapIEByAdapter(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf) |
| { |
| P_IE_VHT_CAP_T prVhtCap; |
| P_VHT_SUPPORTED_MCS_FIELD prVhtSupportedMcsSet; |
| UINT_8 i; |
| |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| /* ASSERT(prMsduInfo); */ |
| |
| prVhtCap = (P_IE_VHT_CAP_T) pOutBuf; |
| |
| prVhtCap->ucId = ELEM_ID_VHT_CAP; |
| prVhtCap->ucLength = sizeof(IE_VHT_CAP_T) - ELEM_HDR_LEN; |
| prVhtCap->u4VhtCapInfo = VHT_CAP_INFO_DEFAULT_VAL; |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) |
| prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) |
| prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) |
| prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_STBC_ONE_STREAM; |
| |
| /*set MCS map */ |
| prVhtSupportedMcsSet = &prVhtCap->rVhtSupportedMcsSet; |
| kalMemZero((PVOID) prVhtSupportedMcsSet, sizeof(VHT_SUPPORTED_MCS_FIELD)); |
| |
| for (i = 0; i < 8; i++) { |
| prVhtSupportedMcsSet->u2RxMcsMap |= BITS(2 * i, (2 * i + 1)); |
| prVhtSupportedMcsSet->u2TxMcsMap |= BITS(2 * i, (2 * i + 1)); |
| } |
| |
| prVhtSupportedMcsSet->u2RxMcsMap &= (VHT_CAP_INFO_MCS_MAP_MCS9 << VHT_CAP_INFO_MCS_1SS_OFFSET); |
| prVhtSupportedMcsSet->u2TxMcsMap &= (VHT_CAP_INFO_MCS_MAP_MCS9 << VHT_CAP_INFO_MCS_1SS_OFFSET); |
| prVhtSupportedMcsSet->u2RxHighestSupportedDataRate = VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; |
| prVhtSupportedMcsSet->u2TxHighestSupportedDataRate = VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; |
| |
| ASSERT(IE_SIZE(prVhtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP)); |
| |
| return IE_SIZE(prVhtCap); |
| } |
| #endif |
| |
| #if CFG_SUPPORT_TDLS |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_32 |
| rlmFillHtCapIEByParams(BOOLEAN fg40mAllowed, |
| BOOLEAN fgShortGIDisabled, |
| UINT_8 u8SupportRxSgi20, |
| UINT_8 u8SupportRxSgi40, UINT_8 u8SupportRxGf, ENUM_OP_MODE_T eCurrentOPMode, UINT_8 *pOutBuf) |
| { |
| P_IE_HT_CAP_T prHtCap; |
| P_SUP_MCS_SET_FIELD prSupMcsSet; |
| |
| ASSERT(pOutBuf); |
| |
| prHtCap = (P_IE_HT_CAP_T) pOutBuf; |
| |
| /* Add HT capabilities IE */ |
| prHtCap->ucId = ELEM_ID_HT_CAP; |
| prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; |
| |
| prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; |
| if (!fg40mAllowed) { |
| prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | |
| HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); |
| } |
| if (fgShortGIDisabled) |
| prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); |
| |
| if (u8SupportRxSgi20 == 2) |
| prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M); |
| if (u8SupportRxSgi40 == 2) |
| prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_40M); |
| if (u8SupportRxGf == 2) |
| prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_HT_GF); |
| |
| prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; |
| |
| prSupMcsSet = &prHtCap->rSupMcsSet; |
| kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); |
| |
| prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); |
| |
| if (fg40mAllowed) |
| prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ |
| prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; |
| prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; |
| |
| prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; |
| if (!fg40mAllowed || eCurrentOPMode != OP_MODE_INFRASTRUCTURE) |
| prHtCap->u2HtExtendedCap &= ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); |
| |
| prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; |
| |
| prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; |
| |
| ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); |
| |
| return IE_SIZE(prHtCap); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_32 rlmFillHtCapIEByAdapter(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf) |
| { |
| P_IE_HT_CAP_T prHtCap; |
| P_SUP_MCS_SET_FIELD prSupMcsSet; |
| BOOLEAN fg40mAllowed; |
| |
| ASSERT(prAdapter); |
| ASSERT(prBssInfo); |
| ASSERT(pOutBuf); |
| |
| fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; |
| |
| prHtCap = (P_IE_HT_CAP_T) pOutBuf; |
| |
| /* Add HT capabilities IE */ |
| prHtCap->ucId = ELEM_ID_HT_CAP; |
| prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; |
| |
| prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; |
| if (!fg40mAllowed) { |
| prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | |
| HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); |
| } |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) |
| prHtCap->u2HtCapInfo |= (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) |
| prHtCap->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; |
| |
| if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) |
| prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_1_SS; |
| |
| prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; |
| |
| prSupMcsSet = &prHtCap->rSupMcsSet; |
| kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); |
| |
| prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); |
| |
| if (fg40mAllowed && IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucMCS32)) |
| prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ |
| prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; |
| prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; |
| |
| prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; |
| if (!fg40mAllowed || prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) |
| prHtCap->u2HtExtendedCap &= ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); |
| |
| prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; |
| |
| prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; |
| |
| ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); |
| |
| return IE_SIZE(prHtCap); |
| |
| } |
| |
| #endif |
| |
| #if CFG_SUPPORT_DFS |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will compose the TPC Report frame. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] prStaRec Pointer to the STA_RECORD_T. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static VOID |
| tpcComposeReportFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) |
| { |
| P_MSDU_INFO_T prMsduInfo; |
| P_BSS_INFO_T prBssInfo; |
| P_ACTION_TPC_REPORT_FRAME prTxFrame; |
| UINT_16 u2PayloadLen; |
| |
| ASSERT(prAdapter); |
| ASSERT(prStaRec); |
| |
| prBssInfo = &prAdapter->rWifiVar.arBssInfoPool[prStaRec->ucBssIndex]; |
| ASSERT(prBssInfo); |
| |
| prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); |
| |
| if (!prMsduInfo) |
| return; |
| |
| prTxFrame = (P_ACTION_TPC_REPORT_FRAME) |
| ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); |
| |
| prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; |
| |
| COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); |
| COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); |
| COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); |
| |
| prTxFrame->ucCategory = CATEGORY_SPEC_MGT; |
| prTxFrame->ucAction = ACTION_TPC_REPORT; |
| |
| /* 3 Compose the frame body's frame. */ |
| prTxFrame->ucDialogToken = prStaRec->ucSmDialogToken; |
| prTxFrame->ucElemId = ELEM_ID_TPC_REPORT; |
| prTxFrame->ucLength = sizeof(prTxFrame->ucLinkMargin)+sizeof(prTxFrame->ucTransPwr); |
| prTxFrame->ucTransPwr = prAdapter->u4GetTxPower; |
| prTxFrame->ucLinkMargin = prAdapter->rLinkQuality.cRssi - (0 - MIN_RCV_PWR); |
| |
| u2PayloadLen = ACTION_SM_TPC_REPORT_LEN; |
| |
| /* 4 Update information of MSDU_INFO_T */ |
| TX_SET_MMPDU(prAdapter, |
| prMsduInfo, |
| prStaRec->ucBssIndex, |
| prStaRec->ucIndex, |
| WLAN_MAC_MGMT_HEADER_LEN, |
| WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, MSDU_RATE_MODE_AUTO); |
| |
| DBGLOG(RLM, TRACE, "ucDialogToken %d ucTransPwr %d ucLinkMargin %d\n", |
| prTxFrame->ucDialogToken, prTxFrame->ucTransPwr, prTxFrame->ucLinkMargin); |
| |
| /* 4 Enqueue the frame to send this action frame. */ |
| nicTxEnqueueMsdu(prAdapter, prMsduInfo); |
| |
| return; |
| |
| } /* end of tpcComposeReportFrame() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will compose the Measurement Report frame. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] prStaRec Pointer to the STA_RECORD_T. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static VOID |
| msmtComposeReportFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) |
| { |
| P_MSDU_INFO_T prMsduInfo; |
| P_BSS_INFO_T prBssInfo; |
| P_ACTION_SM_REPORT_FRAME prTxFrame; |
| P_IE_MEASUREMENT_REPORT_T prMeasurementRepIE; |
| PUINT_8 pucIE; |
| UINT_16 u2PayloadLen; |
| |
| ASSERT(prAdapter); |
| ASSERT(prStaRec); |
| |
| prBssInfo = &prAdapter->rWifiVar.arBssInfoPool[prStaRec->ucBssIndex]; |
| ASSERT(prBssInfo); |
| |
| prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); |
| |
| if (!prMsduInfo) |
| return; |
| |
| prTxFrame = (P_ACTION_SM_REPORT_FRAME) |
| ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); |
| pucIE = prTxFrame->aucInfoElem; |
| prMeasurementRepIE = SM_MEASUREMENT_REP_IE(pucIE); |
| |
| prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; |
| |
| COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); |
| COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); |
| COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); |
| |
| prTxFrame->ucCategory = CATEGORY_SPEC_MGT; |
| prTxFrame->ucAction = ACTION_MEASUREMENT_REPORT; |
| |
| /* 3 Compose the frame body's frame. */ |
| prTxFrame->ucDialogToken = prStaRec->ucSmDialogToken; |
| prMeasurementRepIE->ucId = ELEM_ID_MEASUREMENT_REPORT; |
| |
| #if 0 |
| if (prStaRec->ucSmMsmtRequestMode == ELEM_RM_TYPE_BASIC_REQ) { |
| prMeasurementRepIE->ucLength = sizeof(SM_BASIC_REPORT_T) + 3; |
| u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ACTION_SM_BASIC_REPORT_LEN; |
| } else if (prStaRec->ucSmMsmtRequestMode == ELEM_RM_TYPE_CCA_REQ) { |
| prMeasurementRepIE->ucLength = sizeof(SM_CCA_REPORT_T) + 3; |
| u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ACTION_SM_CCA_REPORT_LEN; |
| } else if (prStaRec->ucSmMsmtRequestMode == ELEM_RM_TYPE_RPI_HISTOGRAM_REQ) { |
| prMeasurementRepIE->ucLength = sizeof(SM_RPI_REPORT_T) + 3; |
| u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ACTION_SM_PRI_REPORT_LEN; |
| } else { |
| prMeasurementRepIE->ucLength = 3; |
| u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN; |
| } |
| #else |
| prMeasurementRepIE->ucLength = 3; |
| u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN; |
| prMeasurementRepIE->ucToken = prStaRec->ucSmMsmtToken; |
| prMeasurementRepIE->ucReportMode = BIT(1); |
| prMeasurementRepIE->ucMeasurementType = prStaRec->ucSmMsmtRequestMode; |
| #endif |
| |
| /* 4 Update information of MSDU_INFO_T */ |
| TX_SET_MMPDU(prAdapter, |
| prMsduInfo, |
| prStaRec->ucBssIndex, |
| prStaRec->ucIndex, |
| WLAN_MAC_MGMT_HEADER_LEN, |
| WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, MSDU_RATE_MODE_AUTO); |
| |
| DBGLOG(RLM, TRACE, "ucDialogToken %d ucToken %d ucReportMode %d ucMeasurementType %d\n", |
| prTxFrame->ucDialogToken, prMeasurementRepIE->ucToken, |
| prMeasurementRepIE->ucReportMode, prMeasurementRepIE->ucMeasurementType); |
| |
| /* 4 Enqueue the frame to send this action frame. */ |
| nicTxEnqueueMsdu(prAdapter, prMsduInfo); |
| |
| return; |
| |
| } /* end of msmtComposeReportFrame() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function handle spectrum management action frame |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmProcessSpecMgtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) |
| { |
| PUINT_8 pucIE; |
| P_STA_RECORD_T prStaRec; |
| P_BSS_INFO_T prBssInfo; |
| UINT_16 u2IELength; |
| UINT_16 u2Offset = 0; |
| P_IE_CHANNEL_SWITCH_T prChannelSwitchAnnounceIE; |
| P_IE_SECONDARY_OFFSET_T prSecondaryOffsetIE; |
| P_IE_WIDE_BAND_CHANNEL_T prWideBandChannelIE; |
| P_IE_TPC_REQ_T prTpcReqIE; |
| P_IE_TPC_REPORT_T prTpcRepIE; |
| P_IE_MEASUREMENT_REQ_T prMeasurementReqIE; |
| P_IE_MEASUREMENT_REPORT_T prMeasurementRepIE; |
| P_ACTION_SM_REQ_FRAME prRxFrame; |
| BOOLEAN fgHasWideBandIE = FALSE; |
| BOOLEAN fgHasSCOIE = FALSE; |
| BOOLEAN fgHasChannelSwitchIE = FALSE; |
| |
| DBGLOG(RLM, INFO, "[Mgt Action]rlmProcessSpecMgtAction\n"); |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| u2IELength = prSwRfb->u2PacketLen - |
| (UINT_16) OFFSET_OF(ACTION_SM_REQ_FRAME, aucInfoElem[0]); |
| |
| prRxFrame = (P_ACTION_SM_REQ_FRAME) prSwRfb->pvHeader; |
| pucIE = prRxFrame->aucInfoElem; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); |
| if (!prStaRec) |
| return; |
| |
| if (prStaRec->ucBssIndex > MAX_BSS_INDEX) |
| return; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); |
| |
| prStaRec->ucSmDialogToken = prRxFrame->ucDialogToken; |
| |
| DBGLOG_MEM8(RLM, INFO, pucIE, u2IELength); |
| switch (prRxFrame->ucAction) { |
| case ACTION_MEASUREMENT_REQ: |
| DBGLOG(RLM, INFO, "[Mgt Action] Measure Request\n"); |
| prMeasurementReqIE = SM_MEASUREMENT_REQ_IE(pucIE); |
| if (prMeasurementReqIE->ucId == ELEM_ID_MEASUREMENT_REQ) { |
| prStaRec->ucSmMsmtRequestMode = prMeasurementReqIE->ucRequestMode; |
| prStaRec->ucSmMsmtToken = prMeasurementReqIE->ucToken; |
| msmtComposeReportFrame(prAdapter, prStaRec, NULL); |
| } |
| |
| break; |
| case ACTION_MEASUREMENT_REPORT: |
| DBGLOG(RLM, INFO, "[Mgt Action] Measure Report\n"); |
| prMeasurementRepIE = SM_MEASUREMENT_REP_IE(pucIE); |
| if (prMeasurementRepIE->ucId == ELEM_ID_MEASUREMENT_REPORT) |
| DBGLOG(RLM, TRACE, "[Mgt Action] Correct Measurement report IE !!\n"); |
| break; |
| case ACTION_TPC_REQ: |
| DBGLOG(RLM, INFO, "[Mgt Action] TPC Request\n"); |
| prTpcReqIE = SM_TPC_REQ_IE(pucIE); |
| |
| if (prTpcReqIE->ucId == ELEM_ID_TPC_REQ) |
| tpcComposeReportFrame(prAdapter, prStaRec, NULL); |
| |
| break; |
| case ACTION_TPC_REPORT: |
| DBGLOG(RLM, INFO, "[Mgt Action] TPC Report\n"); |
| prTpcRepIE = SM_TPC_REP_IE(pucIE); |
| |
| if (prTpcRepIE->ucId == ELEM_ID_TPC_REPORT) |
| DBGLOG(RLM, TRACE, "[Mgt Action] Correct TPC report IE !!\n"); |
| |
| break; |
| case ACTION_CHNL_SWITCH: |
| IE_FOR_EACH(pucIE, u2IELength, u2Offset) { |
| switch (IE_ID(pucIE)) { |
| |
| case ELEM_ID_WIDE_BAND_CHANNEL_SWITCH: |
| if (!RLM_NET_IS_11AC(prBssInfo) || |
| IE_LEN(pucIE) != (sizeof(IE_WIDE_BAND_CHANNEL_T) - 2)) { |
| DBGLOG(RLM, INFO, "[Mgt Action] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, Length\n"); |
| break; |
| } |
| DBGLOG(RLM, INFO, "[Mgt Action] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, 11AC\n"); |
| prWideBandChannelIE = (P_IE_WIDE_BAND_CHANNEL_T) pucIE; |
| prBssInfo->ucVhtChannelWidth = prWideBandChannelIE->ucNewChannelWidth; |
| prBssInfo->ucVhtChannelFrequencyS1 = prWideBandChannelIE->ucChannelS1; |
| prBssInfo->ucVhtChannelFrequencyS2 = prWideBandChannelIE->ucChannelS2; |
| fgHasWideBandIE = TRUE; |
| break; |
| |
| case ELEM_ID_CH_SW_ANNOUNCEMENT: |
| if (IE_LEN(pucIE) != (sizeof(IE_CHANNEL_SWITCH_T) - 2)) { |
| DBGLOG(RLM, INFO, "[Mgt Action] ELEM_ID_CH_SW_ANNOUNCEMENT, Length\n"); |
| break; |
| } |
| |
| prChannelSwitchAnnounceIE = (P_IE_CHANNEL_SWITCH_T) pucIE; |
| |
| if (prChannelSwitchAnnounceIE->ucChannelSwitchMode == 1) { |
| /* Need to stop data transmission immediately */ |
| if (!g_fgHasStopTx) { |
| g_fgHasStopTx = TRUE; |
| #if CFG_SUPPORT_TDLS |
| /* TDLS peers */ |
| TdlsTxCtrl(prAdapter, prBssInfo, FALSE); |
| #endif |
| /* AP */ |
| qmSetStaRecTxAllowed(prAdapter, prStaRec, FALSE); |
| DBGLOG(RLM, EVENT, "[Ch] TxAllowed = FALSE\n"); |
| } |
| |
| if (prChannelSwitchAnnounceIE->ucChannelSwitchCount <= 3) { |
| DBGLOG(RLM, INFO, |
| "[Mgt Action] switch channel [%d]->[%d]\n", |
| prBssInfo->ucPrimaryChannel, |
| prChannelSwitchAnnounceIE->ucNewChannelNum); |
| prBssInfo->ucPrimaryChannel = |
| prChannelSwitchAnnounceIE->ucNewChannelNum; |
| } |
| } else { |
| DBGLOG(RLM, INFO, "[Mgt Action] ucChannelSwitchMode = 0\n"); |
| } |
| |
| fgHasChannelSwitchIE = TRUE; |
| break; |
| case ELEM_ID_SCO: |
| if (IE_LEN(pucIE) != (sizeof(IE_SECONDARY_OFFSET_T) - 2)) { |
| DBGLOG(RLM, INFO, "[Mgt Action] ELEM_ID_SCO, Length\n"); |
| break; |
| } |
| prSecondaryOffsetIE = (P_IE_SECONDARY_OFFSET_T) pucIE; |
| DBGLOG(RLM, INFO, |
| "[Mgt Action] SCO [%d]->[%d]\n", prBssInfo->eBssSCO, |
| prSecondaryOffsetIE->ucSecondaryOffset); |
| prBssInfo->eBssSCO = prSecondaryOffsetIE->ucSecondaryOffset; |
| fgHasSCOIE = TRUE; |
| break; |
| default: |
| break; |
| } /*end of switch IE_ID */ |
| } /*end of IE_FOR_EACH */ |
| if (fgHasChannelSwitchIE != FALSE) { |
| if (fgHasWideBandIE == FALSE) { |
| prBssInfo->ucVhtChannelWidth = 0; |
| prBssInfo->ucVhtChannelFrequencyS1 = prBssInfo->ucPrimaryChannel; |
| prBssInfo->ucVhtChannelFrequencyS2 = 0; |
| } |
| if (fgHasSCOIE == FALSE) |
| prBssInfo->eBssSCO = CHNL_EXT_SCN; |
| } |
| nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| #endif |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Send OpMode Norification frame (VHT action frame) |
| * |
| * \param[in] ucChannelWidth 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz or 80+80MHz |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmSendOpModeNotificationFrame(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucChannelWidth, UINT_8 ucNss) |
| { |
| |
| P_MSDU_INFO_T prMsduInfo; |
| P_ACTION_OP_MODE_NOTIFICATION_FRAME prTxFrame; |
| P_BSS_INFO_T prBssInfo; |
| UINT_16 u2EstimatedFrameLen; |
| /* PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER) NULL; */ |
| |
| /* Sanity Check */ |
| if (!prStaRec) |
| return; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); |
| if (!prBssInfo) |
| return; |
| |
| /* Calculate MSDU buffer length */ |
| u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + sizeof(ACTION_OP_MODE_NOTIFICATION_FRAME); |
| |
| /* Alloc MSDU_INFO */ |
| prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); |
| |
| if (!prMsduInfo) |
| return; |
| |
| kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); |
| |
| prTxFrame = prMsduInfo->prPacket; |
| |
| /* Fill frame ctrl */ |
| prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; |
| |
| COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); |
| COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); |
| COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); |
| |
| /* 3 Compose the frame body's frame */ |
| prTxFrame->ucCategory = CATEGORY_VHT_ACTION; |
| prTxFrame->ucAction = ACTION_OPERATING_MODE_NOTIFICATION; |
| |
| prTxFrame->ucOperatingMode |= (ucChannelWidth & VHT_OP_MODE_CHANNEL_WIDTH); |
| |
| if (ucNss == 0) |
| ucNss = 1; |
| prTxFrame->ucOperatingMode |= (((ucNss - 1) << 4) & VHT_OP_MODE_RX_NSS); |
| prTxFrame->ucOperatingMode &= ~VHT_OP_MODE_RX_NSS_TYPE; |
| |
| /* 4 Update information of MSDU_INFO_T */ |
| TX_SET_MMPDU(prAdapter, |
| prMsduInfo, |
| prBssInfo->ucBssIndex, |
| prStaRec->ucIndex, |
| WLAN_MAC_MGMT_HEADER_LEN, sizeof(ACTION_OP_MODE_NOTIFICATION_FRAME), NULL, MSDU_RATE_MODE_AUTO); |
| |
| /* 4 Enqueue the frame to send this action frame. */ |
| nicTxEnqueueMsdu(prAdapter, prMsduInfo); |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Send SM Power Save frame (HT action frame) |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmSendSmPowerSaveFrame(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucNss) |
| { |
| P_MSDU_INFO_T prMsduInfo; |
| P_ACTION_SM_POWER_SAVE_FRAME prTxFrame; |
| P_BSS_INFO_T prBssInfo; |
| UINT_16 u2EstimatedFrameLen; |
| /* PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER) NULL; */ |
| |
| /* Sanity Check */ |
| if (!prStaRec) |
| return; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); |
| if (!prBssInfo) |
| return; |
| |
| /* Calculate MSDU buffer length */ |
| u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + sizeof(ACTION_SM_POWER_SAVE_FRAME); |
| |
| /* Alloc MSDU_INFO */ |
| prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); |
| |
| if (!prMsduInfo) |
| return; |
| |
| kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); |
| |
| prTxFrame = prMsduInfo->prPacket; |
| |
| /* Fill frame ctrl */ |
| prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; |
| |
| COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); |
| COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); |
| COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); |
| |
| /* 3 Compose the frame body's frame */ |
| prTxFrame->ucCategory = CATEGORY_HT_ACTION; |
| prTxFrame->ucAction = ACTION_HT_SM_POWER_SAVE; |
| |
| if (ucNss == 1) |
| prTxFrame->ucSmPowerCtrl |= HT_SM_POWER_SAVE_CONTROL_ENABLED; |
| else if (ucNss == 2) |
| prTxFrame->ucSmPowerCtrl &= ~HT_SM_POWER_SAVE_CONTROL_ENABLED; |
| else { |
| DBGLOG(RLM, WARN, "Can't switch to Nss = %d since we don't support.\n", ucNss); |
| return; |
| } |
| |
| prTxFrame->ucSmPowerCtrl &= (~HT_SM_POWER_SAVE_CONTROL_SM_MODE); /* Static SM power save mode */ |
| |
| /* 4 Update information of MSDU_INFO_T */ |
| TX_SET_MMPDU(prAdapter, |
| prMsduInfo, |
| prBssInfo->ucBssIndex, |
| prStaRec->ucIndex, |
| WLAN_MAC_MGMT_HEADER_LEN, sizeof(ACTION_SM_POWER_SAVE_FRAME), NULL, MSDU_RATE_MODE_AUTO); |
| |
| /* 4 Enqueue the frame to send this action frame. */ |
| nicTxEnqueueMsdu(prAdapter, prMsduInfo); |
| |
| } |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Send Notify Channel Width frame (HT action frame) |
| * |
| * \param[in] ucChannelWidth 0:20MHz, 1:Any channel width in the STA¡¦s Supported Channel Width Set subfield |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmSendNotifyChannelWidthFrame(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucChannelWidth) |
| { |
| P_MSDU_INFO_T prMsduInfo; |
| P_ACTION_NOTIFY_CHANNEL_WIDTH_FRAME prTxFrame; |
| P_BSS_INFO_T prBssInfo; |
| UINT_16 u2EstimatedFrameLen; |
| /* PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER) NULL; */ |
| |
| /* Sanity Check */ |
| if (!prStaRec) |
| return; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); |
| if (!prBssInfo) |
| return; |
| |
| /* Calculate MSDU buffer length */ |
| u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + sizeof(ACTION_NOTIFY_CHANNEL_WIDTH_FRAME); |
| |
| /* Alloc MSDU_INFO */ |
| prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); |
| |
| if (!prMsduInfo) |
| return; |
| |
| kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); |
| |
| prTxFrame = prMsduInfo->prPacket; |
| |
| /* Fill frame ctrl */ |
| prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; |
| |
| COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); |
| COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); |
| COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); |
| |
| /* 3 Compose the frame body's frame */ |
| prTxFrame->ucCategory = CATEGORY_HT_ACTION; |
| prTxFrame->ucAction = ACTION_HT_NOTIFY_CHANNEL_WIDTH; |
| |
| prTxFrame->ucChannelWidth = ucChannelWidth; |
| |
| /* 4 Update information of MSDU_INFO_T */ |
| TX_SET_MMPDU(prAdapter, |
| prMsduInfo, |
| prBssInfo->ucBssIndex, |
| prStaRec->ucIndex, |
| WLAN_MAC_MGMT_HEADER_LEN, sizeof(ACTION_NOTIFY_CHANNEL_WIDTH_FRAME), NULL, MSDU_RATE_MODE_AUTO); |
| |
| /* 4 Enqueue the frame to send this action frame. */ |
| nicTxEnqueueMsdu(prAdapter, prMsduInfo); |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Change OpMode Nss/Channel Width |
| * |
| * \param[in] ucChannelWidth 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz 4:80+80MHz |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN rlmChangeOperationMode(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 ucChannelWidth, UINT_8 ucNss) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; |
| /*BOOLEAN fgIsSuccess = FALSE;*/ |
| BOOLEAN fgIsChangeVhtBw = TRUE, fgIsChangeHtBw = TRUE; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| |
| /* No need to change BSS 4 rlm parameter */ |
| if (ucBssIndex >= HW_BSSID_NUM) |
| return FALSE; |
| |
| if (!prBssInfo) |
| return FALSE; |
| |
| DBGLOG(RLM, INFO, "Intend to change BSS[%d] OP Mode to BW[%d] Nss[%d]\n", ucBssIndex, ucChannelWidth, ucNss); |
| |
| #if CFG_SUPPORT_802_11AC |
| /* Check peer VHT/HT OP Channel Width */ |
| if (ucChannelWidth == prBssInfo->ucOpChangeChannelWidth) |
| fgIsChangeVhtBw = FALSE; |
| else if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { |
| switch (ucChannelWidth) { |
| case MAX_BW_80_80_MHZ: |
| if (prBssInfo->ucVhtPeerChannelWidth != VHT_OP_CHANNEL_WIDTH_80P80) { |
| DBGLOG(RLM, INFO, |
| "Can't change to BW80_80 due to peer VHT OP BW is BW[%d]\n" |
| , prBssInfo->ucVhtPeerChannelWidth); |
| fgIsChangeVhtBw = FALSE; |
| } |
| break; |
| case MAX_BW_160MHZ: |
| if (prBssInfo->ucVhtPeerChannelWidth != VHT_OP_CHANNEL_WIDTH_160) { |
| DBGLOG(RLM, INFO, |
| "Can't change to BW160 due to peer VHT OP BW is BW[%d]\n", |
| prBssInfo->ucVhtPeerChannelWidth); |
| fgIsChangeVhtBw = FALSE; |
| } |
| break; |
| case MAX_BW_80MHZ: |
| if (prBssInfo->ucVhtPeerChannelWidth < VHT_OP_CHANNEL_WIDTH_80) { |
| DBGLOG(RLM, INFO, |
| "Can't change to BW80 due to peer VHT OP BW is BW[%d]\n", |
| prBssInfo->ucVhtPeerChannelWidth); |
| fgIsChangeVhtBw = FALSE; |
| } |
| break; |
| case MAX_BW_40MHZ: |
| if (!(prBssInfo->ucHtPeerOpInfo1 & HT_OP_INFO1_STA_CHNL_WIDTH) || |
| (!prBssInfo->fg40mBwAllowed)) { |
| DBGLOG(RLM, INFO, |
| "Can't change to BW40: PeerOpBw[%d] fg40mBwAllowed[%d]\n", |
| (prBssInfo->ucHtPeerOpInfo1 & HT_OP_INFO1_STA_CHNL_WIDTH), |
| prBssInfo->fg40mBwAllowed); |
| fgIsChangeVhtBw = FALSE; |
| } |
| break; |
| case MAX_BW_20MHZ: |
| break; |
| default: |
| DBGLOG(RLM, WARN, "BW[%d] is invalid for OpMode change\n", ucChannelWidth); |
| fgIsChangeVhtBw = FALSE; |
| } |
| } |
| #endif |
| |
| /* Check HT OP Channel Width */ |
| if (ucChannelWidth == prBssInfo->ucOpChangeChannelWidth) |
| fgIsChangeHtBw = FALSE; |
| else if (ucChannelWidth >= MAX_BW_80MHZ) { |
| DBGLOG(RLM, WARN, "BW[%d] is invalid for HT OpMode change\n", ucChannelWidth); |
| fgIsChangeHtBw = FALSE; |
| } else if (ucChannelWidth == MAX_BW_40MHZ) { |
| if (!(prBssInfo->ucHtPeerOpInfo1 & HT_OP_INFO1_STA_CHNL_WIDTH) || |
| (!prBssInfo->fg40mBwAllowed)) { |
| DBGLOG(RLM, INFO, |
| "Can't change to BW40: PeerOpBw[%d] fg40mBwAllowed[%d]\n", |
| (prBssInfo->ucHtPeerOpInfo1 & HT_OP_INFO1_STA_CHNL_WIDTH), |
| prBssInfo->fg40mBwAllowed); |
| fgIsChangeHtBw = FALSE; |
| } |
| } |
| |
| if (fgIsChangeHtBw) { |
| /* <4>Update HT Channel Width */ |
| if (ucChannelWidth == MAX_BW_20MHZ) { |
| prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; |
| prBssInfo->eBssSCO = CHNL_EXT_SCN; |
| } else if (ucChannelWidth == MAX_BW_40MHZ) { |
| prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; |
| if ((prBssInfo->ucHtPeerOpInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) |
| prBssInfo->eBssSCO = |
| (ENUM_CHNL_EXT_T) (prBssInfo->ucHtPeerOpInfo1 & HT_OP_INFO1_SCO); |
| } else |
| fgIsChangeHtBw = FALSE; |
| } |
| |
| #if CFG_SUPPORT_802_11AC |
| if (fgIsChangeVhtBw) { |
| prBssInfo->ucOpChangeChannelWidth = ucChannelWidth; |
| prBssInfo->fgIsOpChangeChannelWidth = TRUE; |
| /* <3>Update VHT Channel Width*/ |
| rlmChangeVhtOpBwPara(prAdapter, ucBssIndex, prBssInfo->ucOpChangeChannelWidth); |
| |
| DBGLOG(RLM, INFO, "Update VHT Channel Width Info to w=%d s1=%d s2=%d\n", |
| prBssInfo->ucVhtChannelWidth, |
| prBssInfo->ucVhtChannelFrequencyS1, |
| prBssInfo->ucVhtChannelFrequencyS2); |
| } |
| #endif |
| if (fgIsChangeHtBw) { |
| prBssInfo->ucOpChangeChannelWidth = ucChannelWidth; |
| prBssInfo->fgIsOpChangeChannelWidth = TRUE; |
| |
| DBGLOG(RLM, INFO, "Update HT Channel Width Info to bw=%d s=%d\n", |
| (prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_STA_CHNL_WIDTH) >> 2, prBssInfo->eBssSCO); |
| } |
| |
| if ((prBssInfo->ucNss != ucNss) || fgIsChangeVhtBw || fgIsChangeHtBw) { |
| /* 1. Update BSS Info */ |
| prBssInfo->ucNss = ucNss; |
| rlmSyncOperationParams(prAdapter, prBssInfo); |
| |
| if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { /* For infrastructure, GC */ |
| if (prBssInfo->prStaRecOfAP) { |
| prStaRec = prBssInfo->prStaRecOfAP; |
| #if CFG_SUPPORT_802_11AC |
| /* 2. Check if we can change OpMode and Send OPmode notification frame */ |
| if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_VHT) { /*Send VHT notification frame*/ |
| /* <1> Notify VHT Nss and Channel Width change*/ |
| rlmSendOpModeNotificationFrame(prAdapter, prStaRec, ucChannelWidth, |
| prBssInfo->ucNss); |
| DBGLOG(RLM, INFO, "Send VHT OPmode notification frame, BW=%d, Nss=%d\n" |
| , ucChannelWidth, prBssInfo->ucNss); |
| } else |
| #endif |
| if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT) { /*Send HT notification frame*/ |
| /* <1> Notify HT Nss change */ |
| rlmSendSmPowerSaveFrame(prAdapter, prStaRec, prBssInfo->ucNss); |
| DBGLOG(RLM, INFO, "Send HT SM Power Save frame, Nss=%d\n", |
| prBssInfo->ucNss); |
| } |
| |
| if (fgIsChangeHtBw) { |
| /* <3> Notify HT Channel Width change */ |
| rlmSendNotifyChannelWidthFrame(prAdapter, prStaRec, ucChannelWidth); |
| DBGLOG(RLM, INFO, "Send HT Notify Channel Width frame, BW=%d\n", |
| ucChannelWidth); |
| } |
| } else |
| DBGLOG(RLM, WARN, "Can't change OpMode at legacy mode\n"); |
| } else if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { |
| P_LINK_T prClientList; |
| |
| /* 4. Update BCN/Probe Resp IE to notify peers the OP is be changed */ |
| DBGLOG(RLM, INFO, "Beacon content update with Bssidex(%d)\n", |
| prBssInfo->ucBssIndex); |
| |
| prClientList = &prBssInfo->rStaRecOfClientList; |
| |
| LINK_FOR_EACH_ENTRY(prStaRec, prClientList, rLinkEntry, STA_RECORD_T) { |
| #if CFG_SUPPORT_802_11AC |
| /* 2. Check if we can change OpMode and Send OPmode notification frame */ |
| if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_VHT) { /*Send VHT notification frame*/ |
| /* <1> Notify VHT Nss and Channel Width change*/ |
| rlmSendOpModeNotificationFrame(prAdapter, prStaRec, ucChannelWidth, |
| prBssInfo->ucNss); |
| DBGLOG(RLM, INFO, "Send VHT OPmode notification frame, BW=%d, Nss=%d\n" |
| , ucChannelWidth, prBssInfo->ucNss); |
| } else |
| #endif |
| if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT) { /*Send HT notification frame*/ |
| /* <1> Notify HT Nss change */ |
| rlmSendSmPowerSaveFrame(prAdapter, prStaRec, prBssInfo->ucNss); |
| DBGLOG(RLM, INFO, "Send HT SM Power Save frame, Nss=%d\n", |
| prBssInfo->ucNss); |
| } |
| |
| if (fgIsChangeHtBw) { |
| /* <3> Notify HT Channel Width change */ |
| rlmSendNotifyChannelWidthFrame(prAdapter, prStaRec, ucChannelWidth); |
| DBGLOG(RLM, INFO, "Send HT Notify Channel Width frame, BW=%d\n", |
| ucChannelWidth); |
| } |
| } |
| |
| bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); |
| } else |
| return FALSE; |
| } |
| return TRUE; |
| } |