summaryrefslogtreecommitdiff
path: root/network/wlan/WDI/COMMON/VHTGen.c
diff options
context:
space:
mode:
Diffstat (limited to 'network/wlan/WDI/COMMON/VHTGen.c')
-rw-r--r--network/wlan/WDI/COMMON/VHTGen.c1302
1 files changed, 1302 insertions, 0 deletions
diff --git a/network/wlan/WDI/COMMON/VHTGen.c b/network/wlan/WDI/COMMON/VHTGen.c
new file mode 100644
index 00000000..d9c0b4b2
--- /dev/null
+++ b/network/wlan/WDI/COMMON/VHTGen.c
@@ -0,0 +1,1302 @@
+
+#include "Mp_Precomp.h"
+
+#if WPP_SOFTWARE_TRACE
+#include "VHTGen.tmh"
+#endif
+
+#if (VHT_SUPPORT == 1)
+
+// 20/40/80, ShortGI, MCS Rate
+const u2Byte VHT_MCS_DATA_RATE[3][2][30] =
+ { { {13, 26, 39, 52, 78, 104, 117, 130, 156, 156,
+ 26, 52, 78, 104, 156, 208, 234, 260, 312, 312,
+ 39, 78, 117, 156, 234, 312, 351, 390, 468, 520}, // Long GI, 20MHz
+ {14, 29, 43, 58, 87, 116, 130, 144, 173, 173,
+ 29, 58, 87, 116, 173, 231, 260, 289, 347, 347,
+ 43, 87, 130, 173, 260, 347,390, 433, 520, 578} }, // Short GI, 20MHz
+ { {27, 54, 81, 108, 162, 216, 243, 270, 324, 360,
+ 54, 108, 162, 216, 324, 432, 486, 540, 648, 720,
+ 81, 162, 243, 324, 486, 648, 729, 810, 972, 1080}, // Long GI, 40MHz
+ {30, 60, 90, 120, 180, 240, 270, 300,360, 400,
+ 60, 120, 180, 240, 360, 480, 540, 600, 720, 800,
+ 90, 180, 270, 360, 540, 720, 810, 900, 1080, 1200}}, // Short GI, 40MHz
+ { {59, 117, 176, 234, 351, 468, 527, 585, 702, 780,
+ 117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560,
+ 176, 351, 527, 702, 1053, 1404, 1580, 1755, 2106, 2340}, // Long GI, 80MHz
+ {65, 130, 195, 260, 390, 520, 585, 650, 780, 867,
+ 130, 260, 390, 520, 780, 1040, 1170, 1300, 1560,1734,
+ 195, 390, 585, 780, 1170, 1560, 1755, 1950, 2340, 2600} } // Short GI, 80MHz
+ };
+
+VOID
+VHTDebugVHTCapability(
+ u4Byte DebugLevel,
+ PADAPTER Adapter,
+ POCTET_STRING pocCap,
+ pu1Byte TitleString
+
+)
+{
+ pu1Byte pCapELE = (pu1Byte)&pocCap->Octet[0];
+ pu1Byte pMCS;
+
+ pMCS= GET_VHT_CAPABILITY_ELE_RX_MCS(pCapELE);
+
+ RT_TRACE(COMP_HT, DebugLevel, ("<Log VHT Capability>. Called by %s\n", TitleString ));
+
+ RT_TRACE(COMP_HT, DebugLevel, ("\tSupported Channel Width = %d\n", (GET_VHT_CAPABILITY_ELE_CHL_WIDTH(pCapELE) )));
+ RT_TRACE(COMP_HT, DebugLevel, ("\tSupport Short GI for 80M = %s\n", (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pCapELE))?"YES": "NO"));
+ RT_TRACE(COMP_HT, DebugLevel, ("\tSupport TX STBC = %s\n", (GET_VHT_CAPABILITY_ELE_TX_STBC(pCapELE))?"YES": "NO"));
+ RT_TRACE(COMP_HT, DebugLevel, ("\tMax MPDU Size = %s\n", (GET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pCapELE))?"3839": "7935"));
+ RT_TRACE(COMP_HT, DebugLevel, ("\tMPDU Density = %d\n", GET_HT_CAPABILITY_ELE_MPDU_DENSITY(pCapELE)));
+ RT_TRACE(COMP_HT, DebugLevel, ("\tRx MCS Rate Set = [%x][%x][%x][%x]\n", pMCS[0], pMCS[1], pMCS[2], pMCS[3]));
+ RT_TRACE(COMP_HT, DebugLevel, ("\tRx LDPC = %d\n", GET_VHT_CAPABILITY_ELE_RX_LDPC(pCapELE)));
+ RT_TRACE(COMP_HT, DebugLevel, ("\n"));
+
+}
+
+
+u2Byte
+VHTMcsToDataRate(
+ PADAPTER Adapter,
+ u2Byte VHTMcsRate
+ )
+{
+ BOOLEAN isShortGI = FALSE;
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_HIGH_THROUGHPUT pHTInfo = pMgntInfo->pHTInfo;
+ PRT_VERY_HIGH_THROUGHPUT pVHTInfo = pMgntInfo->pVHTInfo;
+
+ VHTMcsRate -=MGN_VHT1SS_MCS0;
+
+ switch(pMgntInfo->dot11CurrentChannelBandWidth){
+ case CHANNEL_WIDTH_20:
+ isShortGI = pHTInfo->bCurShortGI20MHz?1:0;
+ break;
+ case CHANNEL_WIDTH_40:
+ isShortGI = pHTInfo->bCurShortGI40MHz?1:0;
+ break;
+ case CHANNEL_WIDTH_80:
+ isShortGI = pVHTInfo->bCurShortGI80MHz?1:0;
+ break;
+ }
+
+ return VHT_MCS_DATA_RATE[pMgntInfo->dot11CurrentChannelBandWidth][isShortGI][VHTMcsRate];
+}
+
+
+BOOLEAN
+VHTFilterMCSRate(
+ IN PADAPTER Adapter,
+ IN pu1Byte pSupportMCS,
+ OUT pu1Byte pOperateMCS
+)
+{
+ u1Byte i = 0, j = 0;
+ u1Byte RegRate, dot11Rate, OpRate;
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+
+ for(i = 0; i < 2; i++)
+ {
+ pOperateMCS[i] = 0;
+
+ for(j = 0; j < 8; j+=2)
+ {
+ RegRate = (pMgntInfo->Regdot11VHTOperationalRateSet[i] >> j) & 3;
+ dot11Rate = (pSupportMCS[i] >> j) & 3;
+ if(RegRate == 3 || dot11Rate == 3) //0x3 indicates not supported that num of SS
+ OpRate = 3;
+ else if(RegRate > dot11Rate)
+ OpRate = dot11Rate;
+ else
+ OpRate = RegRate;
+
+ pOperateMCS[i] |= (OpRate << j);
+ }
+ }
+
+ return TRUE;
+}
+
+
+u1Byte
+RateToSpatialStream(
+ pu1Byte pVHTRate
+)
+{
+ u1Byte i,j , tmpRate;
+ u1Byte NumSS = 0;
+
+ for(i = 0; i < 2; i++)
+ {
+ for(j = 0; j < 8; j+=2)
+ {
+ tmpRate = (pVHTRate[i] >> j) & 3;
+
+ switch(tmpRate){
+ case 2:
+ case 1:
+ case 0:
+ NumSS++;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ }
+ RT_TRACE(COMP_HT, DBG_LOUD, ("RateToSpatialStream(): Number of Spatial Stream supported = %d\n", NumSS));
+
+ return NumSS;
+}
+
+
+VOID
+SpatialStreamToRate(
+ PADAPTER Adapter,
+ u1Byte NumSS,
+ pu1Byte pVHTRate
+)
+{
+ u1Byte i = 0, j = 0;
+ u1Byte RegRate, dot11Rate, OpRate;
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+
+ for(i = 0; i < 2; i++)
+ {
+ pVHTRate[i] = 0;
+
+ for(j = 0; j < 8; j+=2)
+ {
+ RegRate = (pMgntInfo->Regdot11VHTOperationalRateSet[i] >> j) & 3;
+ dot11Rate = (pVHTRate[i] >> j) & 3;
+ if(RegRate == 3) //0x3 indicates not supported that num of SS
+ OpRate = 3;
+ else if(NumSS <= j)
+ OpRate = 3;
+ else if(RegRate > dot11Rate)
+ OpRate = dot11Rate;
+ else
+ OpRate = RegRate;
+
+ pVHTRate[i] |= (OpRate << j);
+ }
+ }
+}
+
+
+u1Byte
+VHTIOTActIsAMsduEnable(
+ PADAPTER Adapter
+)
+{
+ HT_IOT_ACTION_E retValue = (HT_IOT_ACTION_E)0;
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+
+ if(pMgntInfo->pHTInfo->ForcedAMSDUMode == HT_AMSDU_ENABLE)
+ retValue = HT_IOT_ACT_AMSDU_ENABLE;
+ else if(pMgntInfo->pHTInfo->ForcedAMSDUMode == HT_AMSDU_WITHIN_AMPDU)
+ retValue = HT_IOT_ACT_AMSDU_AMPDU;
+
+ return retValue;
+}
+
+
+
+VOID
+VHTConstructOpModeNotification(
+ IN PADAPTER Adapter,
+ IN pu1Byte Addr,
+ OUT pu1Byte Buffer,
+ OUT pu4Byte pLength
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_VERY_HIGH_THROUGHPUT pVHTInfo = GET_VHT_INFO(pMgntInfo);
+ u1Byte opmode = 0;
+ OCTET_STRING osNotifFrame, tmp;
+
+ FillOctetString(osNotifFrame, Buffer, 0);
+ *pLength = 0;
+
+ ConstructMaFrameHdr(
+ Adapter,
+ Addr,
+ ACT_CAT_VHT,
+ ACT_VHT_OPMODE_NOTIFICATION,
+ &osNotifFrame);
+
+ // Operating Mode
+ SET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&opmode, pVHTInfo->BWToSwitch);
+
+ SET_VHT_OPERATING_MODE_FIELD_RX_NSS(&opmode, (pVHTInfo->RxSSToSwitch-1));
+ SET_VHT_OPERATING_MODE_FIELD_RX_NSS_TYPE(&opmode, pVHTInfo->RxSSTypeBfmeeToSwitch);
+
+ FillOctetString(tmp, &opmode, 1);
+ PacketAppendData(&osNotifFrame, tmp);
+
+ *pLength = osNotifFrame.Length;
+}
+
+
+/*
+ The setting used in this functoin shall be our HT Rx capability that we want to inform the peer STA.
+ Both AP and STA Attach the Capailbity Element
+ AP/STA should include this element only if HTEnable is turned on.
+*/
+VOID
+VHTConstructCapabilityElement(
+ PADAPTER Adapter,
+ POCTET_STRING posVHTCap,
+ BOOLEAN bAssoc
+)
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_VERY_HIGH_THROUGHPUT pVHTInfo = GET_VHT_INFO(pMgntInfo);
+ pu1Byte pCapELE = NULL, pCapVHTMCS;
+ u2Byte HighestRate;
+
+ u1Byte VHtSTBC = 0;
+
+ PlatformZeroMemory(posVHTCap->Octet, posVHTCap->Length);
+
+ pCapELE = (pu1Byte)posVHTCap->Octet;
+ posVHTCap->Length = 12;
+
+ // B0 B1 Maximum MPDU Length
+ // in Current AC AP, we can only declare 4K MPDU support, the performance will be better.
+ // Need to add IOT pattern later.
+ //SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pCapELE, 2);
+
+
+ // B2 B3 Supported Channel Width Set
+ SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pCapELE, 0); //indicate we don't support neither 160M nor 80+80M bandwidth. by page
+
+ // B4 Rx LDPC
+ if(TEST_FLAG(pVHTInfo->VhtLdpcCap, LDPC_VHT_ENABLE_RX))
+ {
+ SET_VHT_CAPABILITY_ELE_RX_LDPC(pCapELE, 1);
+ }
+
+ // B5 ShortGI for 80MHz
+ SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pCapELE, pVHTInfo->bRegShortGI80MHz ? 1 : 0); // We can receive Short GI of 80M
+ // B6 ShortGI for 160MHz
+ SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pCapELE, 0); // We can not receive 160M Short GI
+
+ // B7 Tx STBC
+ if(TEST_FLAG(pVHTInfo->VhtStbcCap, STBC_VHT_ENABLE_TX))
+ {
+ SET_VHT_CAPABILITY_ELE_TX_STBC(pCapELE, 1); //now HW support both tx/rx STBC. by page 20111108
+ }
+
+ // B8 B9 B10 Rx STBC
+ Adapter->HalFunc.GetHalDefVarHandler(Adapter, HAL_DEF_RX_STBC, (pu1Byte)&VHtSTBC);
+ if(TEST_FLAG(pVHTInfo->VhtStbcCap, STBC_VHT_ENABLE_RX))
+ {
+ SET_VHT_CAPABILITY_ELE_RX_STBC(pCapELE, VHtSTBC);
+ }
+
+ // B11 SU Beamformer Capable
+ if(TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_BEAMFORMER_ENABLE))
+ {
+ SET_VHT_CAPABILITY_ELE_SU_BFER(pCapELE, TRUE);
+ SET_VHT_CAPABILITY_ELE_SOUNDING_DIMENSIONS(pCapELE, HAL_QueryBeamformerCap(Adapter));
+ }
+
+ // B12 SU Beamformee Capable
+ if(TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE))
+ {
+ SET_VHT_CAPABILITY_ELE_SU_BFEE(pCapELE, TRUE);
+ SET_VHT_CAPABILITY_ELE_BFER_ANT_SUPP(pCapELE, HAL_QueryBeamformeeCap(Adapter));
+ }
+
+
+ // B19 MU Beamformer Capable
+ if (TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)){
+ SET_VHT_CAPABILITY_ELE_MU_BFER(pCapELE, TRUE);
+ SET_VHT_CAPABILITY_ELE_SOUNDING_DIMENSIONS(pCapELE, HAL_QueryBeamformerCap(Adapter));
+ }
+ // B20 MU Beamformee Capable
+ if (TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)){
+ SET_VHT_CAPABILITY_ELE_MU_BFEE(pCapELE, TRUE);
+ SET_VHT_CAPABILITY_ELE_BFER_ANT_SUPP(pCapELE, HAL_QueryBeamformeeCap(Adapter));
+ }
+ // B21 VHT TXOP PS
+ SET_VHT_CAPABILITY_ELE_TXOP_PS(pCapELE, 0);
+ // B22 +HTC-VHT Capable
+ SET_VHT_CAPABILITY_ELE_HTC_VHT(pCapELE, 1);
+ // B23 24 25 Maximum A-MPDU Length Exponent
+ if (pMgntInfo->RegAMfactor < 0x7)
+ {
+ SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pCapELE, pMgntInfo->RegAMfactor); // 8812A can receive AMPDU that has no length limit. by page, 20111111
+ }
+ else
+ {
+ SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pCapELE, 7); // 8812A can receive AMPDU that has no length limit. by page, 20111111
+ }
+
+ // B26 27 VHT Link Adaptation Capable
+ SET_VHT_CAPABILITY_ELE_LINK_ADAPTION(pCapELE, 0);
+
+ pCapVHTMCS = GET_VHT_CAPABILITY_ELE_RX_MCS(pCapELE);
+ PlatformMoveMemory(pCapVHTMCS, pMgntInfo->Regdot11VHTOperationalRateSet, 2);
+
+ pCapVHTMCS = GET_VHT_CAPABILITY_ELE_TX_MCS(pCapELE);
+ PlatformMoveMemory(pCapVHTMCS, pMgntInfo->Regdot11VHTOperationalRateSet, 2);
+
+ HighestRate = VHT_MCS_DATA_RATE[pMgntInfo->dot11CurrentChannelBandWidth][FALSE][((pMgntInfo->RegVHTHighestOperaRate - MGN_VHT1SS_MCS0)&0x3f)];
+ HighestRate = (HighestRate+1) >> 1;
+
+ SET_VHT_CAPABILITY_ELE_MCS_RX_HIGHEST_RATE(pCapELE, HighestRate); //indicate we support highest rx rate is 600Mbps.
+ if(pVHTInfo->bAssignTxLGIRate)
+ HighestRate = pVHTInfo->highestTxLGIRate;
+ SET_VHT_CAPABILITY_ELE_MCS_TX_HIGHEST_RATE(pCapELE, HighestRate); //indicate we support highest tx rate is 600Mbps.
+
+ RT_PRINT_DATA(COMP_HT, DBG_TRACE, "Construct VHTCap in Beacon/Assoc/ReAssoc", posVHTCap->Octet, posVHTCap->Length);
+ VHTDebugVHTCapability(DBG_TRACE, Adapter, posVHTCap, (pu1Byte)"VHTConstructCapability()");
+}
+
+
+VOID
+VHTConstructOperationElement(
+ PADAPTER Adapter,
+ POCTET_STRING posVHTOperation
+)
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ pu1Byte pOpELE = NULL;
+ CHANNEL_WIDTH ChnlWidth;
+
+ pOpELE = (pu1Byte)posVHTOperation->Octet;
+ posVHTOperation->Length = 5;
+
+ //Set BandWidth
+ if( (pMgntInfo->dot11CurrentChannelBandWidth == CHANNEL_WIDTH_20) ||
+ (pMgntInfo->dot11CurrentChannelBandWidth == CHANNEL_WIDTH_40) )
+ ChnlWidth = (CHANNEL_WIDTH)0;
+ else if(pMgntInfo->dot11CurrentChannelBandWidth == CHANNEL_WIDTH_80)
+ ChnlWidth = (CHANNEL_WIDTH)1;
+
+ SET_VHT_OPERATION_ELE_CHL_WIDTH(pOpELE, ChnlWidth);
+ //center frequency
+ SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(pOpELE,pMgntInfo->pChannelInfo->CurrentChannelCenterFrequency);
+ SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(pOpELE,0);
+ SET_VHT_OPERATION_ELE_BASIC_MCS_SET(pOpELE, 0xFFFF);
+}
+
+VOID
+VHTSendOperatingModeNotification(
+ IN PADAPTER Adapter,
+ IN pu1Byte Addr
+ )
+{
+ PRT_TCB pTcb;
+ PRT_TX_LOCAL_BUFFER pBuf;
+ u1Byte DataRate = MgntQuery_MgntFrameTxRate(Adapter, Addr);
+
+ RT_TRACE(COMP_HT, DBG_LOUD, ("=====>Send Operating Mode Notification()\n"));
+
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
+
+ if(MgntGetBuffer(Adapter, &pTcb, &pBuf))
+ {
+ VHTConstructOpModeNotification(Adapter, Addr, pBuf->Buffer.VirtualAddress, &pTcb->PacketLength);
+
+ if(pTcb->PacketLength != 0)
+ {
+ if(ACTING_AS_AP(Adapter))
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, BE_QUEUE, DataRate);
+ else
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, DataRate);
+ }
+ }
+
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
+}
+
+
+RT_STATUS
+VHT_OnOpModeNotify(
+ IN PADAPTER Adapter,
+ IN PRT_RFD pRfd,
+ IN POCTET_STRING posMpdu
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ pu1Byte opmodenotif = NULL;
+ CHANNEL_WIDTH targetbw = (CHANNEL_WIDTH)0;
+ u1Byte targetrxss = 0, currentrxss = 0;
+ BOOLEAN bUpdateRA = FALSE;
+
+ // CategoryCode(1) + ActionCode(1) + OpModeNotification(1)
+ if(posMpdu->Length < sMacHdrLng + 3)
+ {
+ RT_TRACE(COMP_HT, DBG_SERIOUS, ("VHT_OnOpModeNotify(): Invalid length(%d) of frame\n", posMpdu->Length));
+ return RT_STATUS_INVALID_DATA;
+ }
+
+ opmodenotif = posMpdu->Octet + sMacHdrLng + 2;
+ targetbw = (CHANNEL_WIDTH)GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(opmodenotif);
+ targetrxss = (GET_VHT_OPERATING_MODE_FIELD_RX_NSS(opmodenotif) + 1);
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("VHT_OnOpModeNotify(): bw = %d, ss = %d\n", targetbw, targetrxss));
+
+ if(targetbw != pMgntInfo->currentRABw)
+ {
+ RT_TRACE(COMP_HT, DBG_LOUD, ("VHT_OnOpModeNotify(): operating mode notification change BW\n"));
+ bUpdateRA = TRUE;
+ }
+
+ currentrxss = RateToSpatialStream(pMgntInfo->dot11VHTOperationalRateSet);
+ if( (targetrxss != currentrxss) || bUpdateRA )
+ {
+ RT_TRACE(COMP_HT, DBG_LOUD, ("VHT_OnOpModeNotify(): operating mode notification change tx spatial stream\n"));
+
+ SpatialStreamToRate(Adapter, targetrxss, pMgntInfo->dot11VHTOperationalRateSet);
+
+ pMgntInfo->Ratr_State = 0;
+ Adapter->HalFunc.UpdateHalRAMaskHandler(Adapter, pMgntInfo->mMacId, NULL, pMgntInfo->Ratr_State);
+
+ }
+ return RT_STATUS_SUCCESS;
+}
+
+VOID
+VHTOnAssocRsp(
+ IN PADAPTER Adapter,
+ IN OCTET_STRING asocpdu
+)
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_HIGH_THROUGHPUT pHTInfo = GET_HT_INFO(pMgntInfo);
+ PRT_VERY_HIGH_THROUGHPUT pVHTInfo = GET_VHT_INFO(pMgntInfo);
+ pu1Byte pPeerVHTCap, pPeerVHTInfo, pCapMCS;
+ OCTET_STRING osTmp;
+
+ RT_TRACE(COMP_MLME, DBG_LOUD,("==============>VHTOnAssocRsp \n "));
+
+ if( pVHTInfo->bCurrentVHTSupport == FALSE )
+ {
+ RT_TRACE( COMP_MLME, DBG_LOUD, ("<=== VHTOnAssocRsp(): VHT_DISABLE\n") );
+ return;
+ }
+
+ PlatformZeroMemory(pVHTInfo->PeerVHTCapBuf, sizeof(pVHTInfo->PeerVHTCapBuf));
+ PlatformZeroMemory(pVHTInfo->PeerVHTInfoBuf, sizeof(pVHTInfo->PeerVHTInfoBuf));
+
+ // Get VHT CAP and copy into buffer
+ osTmp= PacketGetElement( asocpdu, EID_VHTCapability, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE);
+
+ if(pMgntInfo->bRegIOTBcm256QAM && osTmp.Length == 0)
+ {
+ osTmp = PacketGetElement(asocpdu, EID_Vendor, OUI_SUB_11AC_EPIG_VHT_CAP, OUI_SUBTYPE_DONT_CARE);
+ if(osTmp.Length != 0)
+ {
+ osTmp.Octet += 7;
+ osTmp.Length = MAX_VHT_CAP_LEN;
+ }
+ }
+
+ osTmp.Length = osTmp.Length > sizeof(pVHTInfo->PeerVHTCapBuf)?\
+ sizeof(pVHTInfo->PeerVHTCapBuf):osTmp.Length; //prevent from overflow
+
+ if(osTmp.Length > 0)
+ CopyMem(pVHTInfo->PeerVHTCapBuf, osTmp.Octet, osTmp.Length);
+
+ // Get VHT Operation and copy into buffer
+ osTmp= PacketGetElement( asocpdu, EID_VHTOperation, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE);
+
+ if(pMgntInfo->bRegIOTBcm256QAM && osTmp.Length == 0)
+ {
+ OCTET_STRING EpigIE = PacketGetElement(asocpdu, EID_Vendor, OUI_SUB_EPIG_IE, OUI_SUBTYPE_DONT_CARE);
+ if(EpigIE.Length == 26)
+ {
+ osTmp.Octet = EpigIE.Octet+21;
+ osTmp.Length = 5;
+ }
+ }
+
+ osTmp.Length = osTmp.Length>sizeof(pVHTInfo->PeerVHTInfoBuf)?\
+ sizeof(pVHTInfo->PeerVHTInfoBuf):osTmp.Length; //prevent from overflow
+
+ if(osTmp.Length > 0)
+ CopyMem(pVHTInfo->PeerVHTInfoBuf, osTmp.Octet, osTmp.Length);
+
+ pPeerVHTCap = (pu1Byte)(pVHTInfo->PeerVHTCapBuf);
+
+ pPeerVHTInfo = (pu1Byte)(pVHTInfo->PeerVHTInfoBuf);
+
+ RT_DISP(FMLME, LINK_STS,
+ ("VHTOnAssocRsp(): call VHTSetBandWidthOnAsocRsp VHT_CAP=%04x VHT_INFO=%04x\n",
+ EF2Byte(*((UNALIGNED pu2Byte)pPeerVHTCap)), EF2Byte(*((UNALIGNED pu2Byte)pPeerVHTInfo))) );
+
+ // B4 Rx LDPC
+ if(TEST_FLAG(pVHTInfo->VhtLdpcCap, LDPC_VHT_ENABLE_TX))
+ {
+ SET_FLAG(pVHTInfo->VhtCurLdpc, GET_VHT_CAPABILITY_ELE_RX_LDPC(pPeerVHTCap) ? (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX) : 0);
+ RT_TRACE_F(COMP_HT, DBG_LOUD, ("Target BSS support VHT LDPC, enable Tx LDPC!\n"));
+ }
+
+ // B5 Short GI for 80 MHz
+ pVHTInfo->bCurShortGI80MHz = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pPeerVHTCap) & pVHTInfo->bRegShortGI80MHz) ? TRUE : FALSE;
+ RT_TRACE_F(COMP_HT, DBG_LOUD, ("Current ShortGI80MHz = %d\n", pVHTInfo->bCurShortGI80MHz));
+
+ // B8 B9 B10 Rx STBC
+ if( TEST_FLAG(pVHTInfo->VhtStbcCap, STBC_VHT_ENABLE_TX) && GET_VHT_CAPABILITY_ELE_RX_STBC(pPeerVHTCap))
+ {
+ SET_FLAG(pVHTInfo->VhtCurStbc, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX) );
+ }
+
+ // B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee
+ if( TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
+ GET_VHT_CAPABILITY_ELE_SU_BFEE(pPeerVHTCap))
+ {
+ SET_FLAG(pVHTInfo->VhtCurBeamform, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
+ // Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP
+ SET_FLAG(pVHTInfo->VhtCurBeamform, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pPeerVHTCap)<<8);
+ }
+
+ // B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer
+ if( TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
+ GET_VHT_CAPABILITY_ELE_SU_BFER(pPeerVHTCap))
+ {
+ SET_FLAG(pVHTInfo->VhtCurBeamform, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
+ // Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM
+ SET_FLAG(pVHTInfo->VhtCurBeamform, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pPeerVHTCap)<<12);
+ }
+
+ // B19 MU Beamformer Capable, the target supports Beamformer and we are Beamformee
+ if( TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE) &&
+ GET_VHT_CAPABILITY_ELE_MU_BFEE(pPeerVHTCap))
+ {
+ SET_FLAG(pVHTInfo->VhtCurBeamform, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
+ // Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP
+ SET_FLAG(pVHTInfo->VhtCurBeamform, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pPeerVHTCap)<<8);
+ }
+
+ // B20 MU Beamformee Capable, the target supports Beamformee and we are Beamformer
+ if( TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE) &&
+ GET_VHT_CAPABILITY_ELE_MU_BFER(pPeerVHTCap))
+ {
+ SET_FLAG(pVHTInfo->VhtCurBeamform, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
+ // Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM
+ SET_FLAG(pVHTInfo->VhtCurBeamform, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pPeerVHTCap)<<12);
+ }
+
+ RT_TRACE_F(COMP_HT, DBG_LOUD, ("Current VHT Beamforming Setting = %02X\n", pVHTInfo->VhtCurBeamform));
+
+ // B23 B24 B25 Maximum A-MPDU Length Exponent
+ pVHTInfo->AMPDU_Len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pPeerVHTCap);
+ if(pVHTInfo->AMPDU_Len > pHTInfo->CurrentAMPDUFactor)
+ Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_AMPDU_FACTOR, &pVHTInfo->AMPDU_Len);
+
+ pCapMCS = GET_VHT_CAPABILITY_ELE_RX_MCS(pPeerVHTCap);
+ VHTFilterMCSRate(Adapter, pCapMCS, pMgntInfo->dot11VHTOperationalRateSet);
+ pMgntInfo->VHTHighestOperaRate = VHTGetHighestMCSRate(
+ Adapter,
+ pMgntInfo->dot11VHTOperationalRateSet);
+
+ pVHTInfo->PeerChnlBW = (CHANNEL_WIDTH)GET_VHT_OPERATION_ELE_CHL_WIDTH(pVHTInfo->PeerVHTInfoBuf);
+ Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_AMPDU_MAX_TIME, &pMgntInfo->VHTHighestOperaRate);
+}
+
+
+/*
+* This function is called when
+* (1) MPInitialization Phase
+* (2) Receiving of Deauthentication from AP
+*/
+
+// TODO: Should this funciton be called when receiving of Disassociation?
+VOID
+VHTInitializeVHTInfo(
+ IN PADAPTER Adapter
+)
+{
+ PRT_VERY_HIGH_THROUGHPUT pVHTInfo = Adapter->MgntInfo.pVHTInfo;
+
+ // These parameters will be reset when receiving deauthentication packet
+ pVHTInfo->bCurrentVHTSupport = FALSE;
+
+ // LDPC support
+ CLEAR_FLAGS(pVHTInfo->VhtCurLdpc);
+
+ // STBC support
+ CLEAR_FLAGS(pVHTInfo->VhtCurStbc);
+
+ // Short GI support
+ pVHTInfo->bCurShortGI80MHz = FALSE;
+
+ // Sounding support
+ CLEAR_FLAGS(pVHTInfo->VhtCurBeamform);
+
+ // Initialize all of the parameters related to 11n
+ PlatformZeroMemory((PVOID)(&(pVHTInfo->SelfVHTCap)), sizeof(pVHTInfo->SelfVHTCap));
+ PlatformZeroMemory((PVOID)(&(pVHTInfo->SelfVHTInfo)), sizeof(pVHTInfo->SelfVHTInfo));
+ PlatformZeroMemory((PVOID)(&(pVHTInfo->PeerVHTCapBuf)), sizeof(pVHTInfo->PeerVHTCapBuf));
+ PlatformZeroMemory((PVOID)(&(pVHTInfo->PeerVHTInfoBuf)), sizeof(pVHTInfo->PeerVHTInfoBuf));
+}
+
+
+VOID
+VHTParsingVHTCapElement(
+ IN PADAPTER Adapter,
+ IN OCTET_STRING VHTCapIE,
+ OUT PRT_WLAN_BSS pBssDesc
+)
+{
+ if( VHTCapIE.Length > sizeof(pBssDesc->BssVHT.bdVHTCapBuf) )
+ {
+ RT_TRACE( COMP_HT, DBG_LOUD, ("VHTParsingVHTCapElement(): VHT Capability Element length is too long!\n") );
+ return;
+ }
+
+ VHTCapIE.Length = VHTCapIE.Length > sizeof(pBssDesc->BssVHT.bdVHTCapBuf)?\
+ sizeof(pBssDesc->BssVHT.bdVHTCapBuf):VHTCapIE.Length; //prevent from overflow
+
+ CopyMem(pBssDesc->BssVHT.bdVHTCapBuf, VHTCapIE.Octet, VHTCapIE.Length);
+ pBssDesc->BssVHT.bdVHTCapLen = VHTCapIE.Length;
+
+}
+
+VOID
+VHTParsingVHTOperationElement(
+ IN PADAPTER Adapter,
+ IN OCTET_STRING VHTOperIE,
+ OUT PRT_WLAN_BSS pBssDesc
+)
+{
+ if( VHTOperIE.Length > sizeof(pBssDesc->BssVHT.bdVHTOperBuf) )
+ {
+ RT_TRACE( COMP_HT, DBG_LOUD, ("HTParsingHTCapElement(): VHT Operation Element length is too long!\n") );
+ return;
+ }
+
+ VHTOperIE.Length = VHTOperIE.Length > sizeof(pBssDesc->BssVHT.bdVHTOperBuf)?\
+ sizeof(pBssDesc->BssVHT.bdVHTOperBuf):VHTOperIE.Length; //prevent from overflow
+
+ CopyMem(pBssDesc->BssVHT.bdVHTOperBuf, VHTOperIE.Octet, VHTOperIE.Length);
+ pBssDesc->BssVHT.bdVHTOperLen = VHTOperIE.Length;
+}
+
+
+VOID
+VHTParsingVHTOpModeNotification(
+ IN PADAPTER Adapter,
+ IN OCTET_STRING VHTNotifIE,
+ OUT PRT_WLAN_BSS pBssDesc
+)
+{
+ if( VHTNotifIE.Length > sizeof(pBssDesc->BssVHT.bdVHTOpModeNotifBuf) )
+ {
+ RT_TRACE( COMP_HT, DBG_LOUD, ("VHTParsingVHTOpModeNotification(): VHT Operating Mode Notification length is too long!\n") );
+ return;
+ }
+
+ VHTNotifIE.Length = VHTNotifIE.Length > sizeof(pBssDesc->BssVHT.bdVHTOpModeNotifBuf)?\
+ sizeof(pBssDesc->BssVHT.bdVHTOpModeNotifBuf):VHTNotifIE.Length; //prevent from overflow
+
+ CopyMem(pBssDesc->BssVHT.bdVHTOpModeNotifBuf, VHTNotifIE.Octet, VHTNotifIE.Length);
+ pBssDesc->BssVHT.bdVHTOpModeNotifLen = VHTNotifIE.Length;
+}
+
+
+VOID
+VHTUseDefaultSettingFromReg(
+ PADAPTER Adapter
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_VERY_HIGH_THROUGHPUT pVHTInfo = GET_VHT_INFO(pMgntInfo);
+
+ pVHTInfo->bCurShortGI80MHz= TRUE;
+
+ pVHTInfo->VhtCurLdpc = pVHTInfo->VhtLdpcCap;
+ pVHTInfo->VhtCurStbc = pVHTInfo->VhtStbcCap;
+ pVHTInfo->VhtCurBeamform = pVHTInfo->VhtBeamformCap;
+
+ pVHTInfo->AMPDU_Len = VHT_AGG_SIZE_1024K;
+ Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_AMPDU_FACTOR, &pVHTInfo->AMPDU_Len);
+
+ PlatformMoveMemory(pMgntInfo->dot11VHTOperationalRateSet, pMgntInfo->Regdot11VHTOperationalRateSet, 2);
+
+ pMgntInfo->VHTHighestOperaRate = pMgntInfo->RegVHTHighestOperaRate;
+
+ pMgntInfo->dot11CurrentChannelBandWidth = CHNL_GetRegBWSupport(Adapter);
+}
+
+VOID
+VHTUseDefaultSettingFromDefault(
+ PADAPTER Adapter
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_VERY_HIGH_THROUGHPUT pVHTInfo = GET_VHT_INFO(pMgntInfo);
+
+ PADAPTER DefAdapter = GetDefaultAdapter(Adapter);
+ PMGNT_INFO pDefMgntInfo = &DefAdapter->MgntInfo;
+ PRT_VERY_HIGH_THROUGHPUT pDefVHTInfo = pDefMgntInfo->pVHTInfo;
+
+ //===== The ones that not follow ======
+ pVHTInfo->bCurShortGI80MHz = TRUE;
+ pVHTInfo->VhtCurLdpc = pVHTInfo->VhtLdpcCap;
+ pVHTInfo->VhtCurStbc = pVHTInfo->VhtStbcCap;
+ pVHTInfo->VhtCurBeamform = pVHTInfo->VhtBeamformCap;
+
+ PlatformMoveMemory(pMgntInfo->dot11VHTOperationalRateSet, pMgntInfo->Regdot11VHTOperationalRateSet, 2);
+
+ pMgntInfo->VHTHighestOperaRate = pMgntInfo->RegVHTHighestOperaRate;
+ //==============================
+
+ pVHTInfo->AMPDU_Len = pDefVHTInfo->AMPDU_Len;
+ Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_AMPDU_FACTOR, &pVHTInfo->AMPDU_Len);
+
+ pMgntInfo->dot11CurrentChannelBandWidth = pDefMgntInfo->dot11CurrentChannelBandWidth;
+}
+
+
+VOID
+VHTUseDefaultSetting(
+ PADAPTER Adapter
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_VERY_HIGH_THROUGHPUT pVHTInfo = GET_VHT_INFO(pMgntInfo);
+ u1Byte TwoPortStatus =(u1Byte) TWO_PORT_STATUS__DEFAULT_ONLY;
+
+ if(pVHTInfo->bEnableVHT)
+ {
+ pVHTInfo->bCurrentVHTSupport = TRUE;
+
+ //[Win7] [Vista/XP] Cross Platform Capbility Enable!, 2009.07.31, by Bohn
+ GetTwoPortSharedResource(Adapter,TWO_PORT_SHARED_OBJECT__STATUS,NULL,&TwoPortStatus);
+
+ //[win7 Two Port BW40Mhz issue] Extention Port Use Reg's Default Value. 2009.05.20, by bohn
+ if( TwoPortStatus==TWO_PORT_STATUS__DEFAULT_ONLY ||
+ TwoPortStatus==TWO_PORT_STATUS__EXTENSION_ONLY ||
+ TwoPortStatus==TWO_PORT_STATUS__WITHOUT_ANY_ASSOCIATE)
+ {
+ VHTUseDefaultSettingFromReg(Adapter);
+ }
+ else if(TwoPortStatus==TWO_PORT_STATUS__EXTENSION_FOLLOW_DEFAULT)
+ {
+ //[win7 Two Port BW40Mhz issue] Extention Port obey the rule of Default Port. 2009.05.20, by bohn
+ VHTUseDefaultSettingFromDefault(Adapter);
+ }
+ else if( TwoPortStatus==TWO_PORT_STATUS__DEFAULT_G_EXTENSION_N20 ||
+ TwoPortStatus==TWO_PORT_STATUS__DEFAULT_A_EXTENSION_N20 ||
+ TwoPortStatus==TWO_PORT_STATUS__ADHOC)
+ {
+ //[Win7] Now is the Default-G Extension-N20 case, we need to reset all HT value and forced to N20
+ // 2009.07.09, by Bohn
+ VHTUseDefaultSettingFromReg(Adapter);
+ }
+ }
+ else
+ {
+ pVHTInfo->bCurrentVHTSupport = FALSE;
+ }
+}
+
+/*
+* Description:
+* This function will get the highest speed rate in input MCS set.
+*
+* /param Adapter Pionter to Adapter entity
+* pMCSRateSet Pointer to MCS rate bitmap
+* pMCSFilter Pointer to MCS rate filter
+*
+* /return Highest MCS rate included in pMCSRateSet and filtered by pMCSFilter.
+*
+*/
+u1Byte
+VHTGetHighestMCSRate(
+ IN PADAPTER Adapter,
+ IN pu1Byte pVHTMCSRateSet
+ )
+{
+ u1Byte i, j;
+ u1Byte bitMap;
+ u1Byte VHTMcsRate = 0;
+
+ for(i = 0; i < 2; i++)
+ {
+ if(pVHTMCSRateSet[i] != 0xff)
+ {
+ for(j = 0; j < 8; j += 2)
+ {
+ bitMap = (pVHTMCSRateSet[i] >> j) & 3;
+
+ if(bitMap != 3)
+ VHTMcsRate = MGN_VHT1SS_MCS7 + 10*j/2 + i*40 + bitMap; //VHT rate indications begin from 0x90
+ }
+ }
+ }
+ return VHTMcsRate;
+}
+
+
+VOID
+VHTCheckVHTCap(
+ IN PADAPTER Adapter,
+ IN PRT_WLAN_STA pEntry,
+ IN pu1Byte pVHTCap
+)
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_VERY_HIGH_THROUGHPUT pVHTInfo = GET_VHT_INFO(pMgntInfo);
+
+ u1Byte VHtSTBC = 0;
+
+ // B2 B3 Supported Channel Width Set
+ if(CHNL_RUN_ABOVE_80MHZ(pMgntInfo) && pEntry->BandWidth == CHANNEL_WIDTH_40)
+ pEntry->BandWidth = CHANNEL_WIDTH_80;
+
+ // B4 Rx LDPC
+ if(TEST_FLAG(pVHTInfo->VhtLdpcCap, LDPC_VHT_ENABLE_TX))
+ SET_FLAG(pEntry->VHTInfo.LDPC, GET_VHT_CAPABILITY_ELE_RX_LDPC(pVHTCap) ? (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX) : 0);
+
+ // B5 Short GI for 80 MHz
+ pEntry->VHTInfo.bShortGI80M = GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pVHTCap);
+
+ // B8 B9 B10 Rx STBC
+ Adapter->HalFunc.GetHalDefVarHandler(Adapter, HAL_DEF_TX_STBC, (pu1Byte)&VHtSTBC);
+ if(!TEST_FLAG(pVHTInfo->VhtStbcCap, STBC_VHT_ENABLE_TX))
+ VHtSTBC = 0;
+
+ if(VHtSTBC < GET_HT_CAPABILITY_ELE_RX_STBC(pVHTCap))
+ pEntry->VHTInfo.STBC = VHtSTBC;
+ else
+ pEntry->VHTInfo.STBC = GET_HT_CAPABILITY_ELE_RX_STBC(pVHTCap);
+
+ CLEAR_FLAGS(pEntry->VHTInfo.VhtCurBeamform);
+ // B11 SU Beamformer Capable, we are Beamformee
+ if( TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
+ GET_VHT_CAPABILITY_ELE_SU_BFER(pVHTCap))
+ {
+ SET_FLAG(pEntry->VHTInfo.VhtCurBeamform, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
+ // Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP
+ SET_FLAG(pVHTInfo->VhtCurBeamform, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pVHTCap)<<8);
+ }
+
+ // B12 SU Beamformee Capable, we are Beamformer
+ if( TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
+ GET_VHT_CAPABILITY_ELE_SU_BFEE(pVHTCap))
+ {
+ SET_FLAG(pEntry->VHTInfo.VhtCurBeamform, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
+ // Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM
+ SET_FLAG(pVHTInfo->VhtCurBeamform, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pVHTCap)<<12);
+ }
+
+ // B19 MU Beamformer Capable, we are Beamformee
+ if( TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE) &&
+ GET_VHT_CAPABILITY_ELE_MU_BFER(pVHTCap))
+ {
+ SET_FLAG(pEntry->VHTInfo.VhtCurBeamform, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
+ // Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP
+ SET_FLAG(pVHTInfo->VhtCurBeamform, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pVHTCap)<<8);
+ }
+
+ // B20 MU Beamformee Capable, we are Beamformer
+ if( TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE) &&
+ GET_VHT_CAPABILITY_ELE_MU_BFEE(pVHTCap))
+ {
+ SET_FLAG(pEntry->VHTInfo.VhtCurBeamform, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
+ // Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM
+ SET_FLAG(pVHTInfo->VhtCurBeamform, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pVHTCap)<<12);
+ }
+
+ RT_DISP(FBEAM, FBEAM_FUN, ("Client VHT Beaforming Cap = 0x%02X\n", pEntry->VHTInfo.VhtCurBeamform));
+
+ VHTFilterMCSRate(Adapter, GET_VHT_CAPABILITY_ELE_RX_MCS(pVHTCap), pEntry->VHTInfo.VHTRateSet);
+}
+
+
+/***********************************************************
+Function: Recovery to Initialize value
+Auther: sherry
+Date: 20111117
+************************************************************/
+VOID
+VHTInitializeBssDesc(
+ IN PBSS_VHT pBssVHT
+ )
+{
+ pBssVHT->bdSupportVHT = FALSE;
+ PlatformZeroMemory(pBssVHT->bdVHTCapBuf, sizeof(pBssVHT->bdVHTCapBuf));
+ pBssVHT->bdVHTCapLen = 0;
+ PlatformZeroMemory(pBssVHT->bdVHTOperBuf, sizeof(pBssVHT->bdVHTOperBuf));
+ pBssVHT->bdVHTOperLen = 0;
+}
+
+
+BOOLEAN
+VHTModeSupport(
+ PADAPTER Adapter,
+ POCTET_STRING pSRCmmpdu
+)
+{
+ OCTET_STRING VHTCapIE, mmpdu;
+
+ mmpdu.Octet = pSRCmmpdu->Octet;
+ mmpdu.Length = pSRCmmpdu->Length;
+ // Get VHT Capability IE:
+ VHTCapIE = PacketGetElement(mmpdu, EID_VHTCapability, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE);
+ if(VHTCapIE.Length != 0)
+ {
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+
+/***********************************************************
+Function: To parsing VHT Related IE from Beacon or ProbeRsp
+Auther: Page and sherry
+Date: 20111117
+************************************************************/
+VOID
+VHTGetValueFromBeaconOrProbeRsp(
+ PADAPTER Adapter,
+ POCTET_STRING pSRCmmpdu,
+ PRT_WLAN_BSS bssDesc
+)
+{
+ OCTET_STRING VHTCapIE, VHTOperIE, VHTNotifIE, mmpdu;
+
+ mmpdu.Octet = pSRCmmpdu->Octet;
+ mmpdu.Length = pSRCmmpdu->Length;
+
+ //Initialize VHT BSSDesc
+ VHTInitializeBssDesc(&bssDesc->BssVHT);
+
+ if(Adapter->bInHctTest)
+ return;
+
+ // Get VHT Capability IE
+ VHTCapIE = PacketGetElement(mmpdu, EID_VHTCapability, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE);
+
+ if(VHTCapIE.Length != 0)
+ VHTParsingVHTCapElement(Adapter, VHTCapIE, bssDesc);
+ else if(Adapter->MgntInfo.bRegIOTBcm256QAM)
+ {
+ VHTCapIE = PacketGetElement(mmpdu, EID_Vendor, OUI_SUB_11AC_EPIG_VHT_CAP, OUI_SUBTYPE_DONT_CARE);
+
+ if(VHTCapIE.Length != 0)
+ {
+ VHTCapIE.Octet += 7;
+ VHTCapIE.Length = MAX_VHT_CAP_LEN;
+ VHTParsingVHTCapElement(Adapter, VHTCapIE, bssDesc);
+ }
+ }
+
+ RT_DISP(FBEACON, BCN_SHOW, ("EID_VHTCapability VHTCapIE.Length=%d\r\n", VHTCapIE.Length));
+
+ // Get VHT Opration IE
+ VHTOperIE = PacketGetElement(mmpdu, EID_VHTOperation, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE);
+
+ if(VHTOperIE.Length != 0)
+ VHTParsingVHTOperationElement(Adapter, VHTOperIE, bssDesc);
+ else if(Adapter->MgntInfo.bRegIOTBcm256QAM)
+ {
+ OCTET_STRING EpigIE = PacketGetElement(mmpdu, EID_Vendor, OUI_SUB_EPIG_IE, OUI_SUBTYPE_DONT_CARE);
+ if(EpigIE.Length >= 26)
+ {
+ VHTOperIE.Octet = EpigIE.Octet+21;
+ VHTOperIE.Length = 5;
+ }
+
+ if(VHTOperIE.Length != 0)
+ VHTParsingVHTOperationElement(Adapter, VHTOperIE, bssDesc);
+ }
+
+ if(VHTCapIE.Length != 0)
+ {
+ bssDesc->BssVHT.bdSupportVHT = TRUE;
+ }
+
+ // Operating Mode Notification
+ VHTNotifIE = PacketGetElement(mmpdu, EID_OpModeNotification, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE);
+ if(VHTNotifIE.Length != 0)
+ VHTParsingVHTOpModeNotification(Adapter, VHTNotifIE, bssDesc);
+
+ //2<4>Check peer configuration
+ if(VHTOperIE.Length!=0 && VHTOperIE.Octet != NULL)
+ {
+ CHANNEL_WIDTH ChnlBW = (CHANNEL_WIDTH)(GET_VHT_OPERATION_ELE_CHL_WIDTH(VHTOperIE.Octet));
+ if(ChnlBW == 1)
+ bssDesc->bdBandWidth = CHANNEL_WIDTH_80;
+ else if(ChnlBW == 2)
+ bssDesc->bdBandWidth = CHANNEL_WIDTH_160;
+ else if(ChnlBW == 3)
+ bssDesc->bdBandWidth = CHANNEL_WIDTH_80_80;
+ }
+}
+
+/*************************************************************************
+Fuction: To Restore VHT setting
+Author: Sherry
+Date: 20111117
+*************************************************************************/
+VOID
+VHTResetSelfAndSavePeerSetting(
+ PADAPTER Adapter,
+ PRT_WLAN_BSS pBssDesc
+)
+{
+
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_VERY_HIGH_THROUGHPUT pVHTInfo = GET_VHT_INFO(pMgntInfo);
+
+ //
+ // Save Peer Setting before Association
+ //
+ if( pVHTInfo->bEnableVHT && pBssDesc->BssVHT.bdSupportVHT)
+ {
+ pVHTInfo->bCurrentVHTSupport = TRUE;
+
+ // Save VHT Cap and VHT Operation information Element
+ if(pBssDesc->BssVHT.bdVHTCapLen > 0 && pBssDesc->BssVHT.bdVHTCapLen <= sizeof(pVHTInfo->PeerVHTCapBuf))
+ CopyMem(pVHTInfo->PeerVHTCapBuf, pBssDesc->BssVHT.bdVHTCapBuf, pBssDesc->BssVHT.bdVHTCapLen);
+
+ if(pBssDesc->BssVHT.bdVHTOperLen> 0 && pBssDesc->BssVHT.bdVHTOperLen <= sizeof(pVHTInfo->PeerVHTInfoBuf))
+ CopyMem(pVHTInfo->PeerVHTInfoBuf,pBssDesc->BssVHT.bdVHTOperBuf, pBssDesc->BssVHT.bdVHTOperLen);
+
+ if(pBssDesc->BssVHT.bdVHTOperLen != 0)
+ pVHTInfo->PeerChnlBW = (CHANNEL_WIDTH)GET_VHT_OPERATION_ELE_CHL_WIDTH(pBssDesc->BssVHT.bdVHTOperBuf);
+ else
+ pVHTInfo->PeerChnlBW = (CHANNEL_WIDTH)CHANNEL_WIDTH_20;
+
+ pMgntInfo->IOTAction |= VHTIOTActIsAMsduEnable(Adapter);
+ }
+ else
+ {
+ pVHTInfo->bCurrentVHTSupport = FALSE;
+ pVHTInfo->PeerChnlBW = CHANNEL_WIDTH_20;
+ }
+}
+
+
+VOID
+VHTUpdateSelfAndPeerSetting(
+ PADAPTER Adapter,
+ PRT_WLAN_BSS pBssDesc
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_VERY_HIGH_THROUGHPUT pVHTInfo = GET_VHT_INFO(pMgntInfo);
+
+ if(pVHTInfo->bCurrentVHTSupport)
+ {
+ if(pBssDesc->BssVHT.bdVHTOperLen != 0)
+ pVHTInfo->PeerChnlBW = (CHANNEL_WIDTH)GET_VHT_OPERATION_ELE_CHL_WIDTH(pBssDesc->BssVHT.bdVHTOperBuf);
+
+ if(pBssDesc->BssVHT.bdVHTOpModeNotifLen > 0)
+ {
+ CHANNEL_WIDTH chnlBW = CHANNEL_WIDTH_20;
+ u1Byte targetrxSS, currentrxSS;
+ BOOLEAN bUpdateRA = FALSE;
+
+ chnlBW = (CHANNEL_WIDTH)GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(pBssDesc->BssVHT.bdVHTOpModeNotifBuf);
+ targetrxSS = (GET_VHT_OPERATING_MODE_FIELD_RX_NSS(pBssDesc->BssVHT.bdVHTOpModeNotifBuf) + 1);
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("VHTUpdateSelfAndPeerSetting(): bw = %d, ss = %d\n", chnlBW, targetrxSS));
+
+ if(chnlBW != pMgntInfo->currentRABw)
+ {
+ RT_TRACE(COMP_HT, DBG_LOUD, ("VHTUpdateSelfAndPeerSetting(): operating mode notification change bandwidth\n"));
+ bUpdateRA = TRUE;
+ }
+
+ currentrxSS = RateToSpatialStream(pMgntInfo->dot11VHTOperationalRateSet);
+ if(targetrxSS != currentrxSS )
+ {
+ RT_TRACE(COMP_HT, DBG_LOUD, ("VHTUpdateSelfAndPeerSetting(): operating mode notification change tx spatial stream\n"));
+
+ SpatialStreamToRate(Adapter, targetrxSS, pMgntInfo->dot11VHTOperationalRateSet);
+
+ pMgntInfo->Ratr_State = 0;
+ Adapter->HalFunc.UpdateHalRAMaskHandler(Adapter, pMgntInfo->mMacId, NULL, pMgntInfo->Ratr_State);
+
+ }
+ }
+ }
+}
+
+
+//
+// Description:
+// Update VHT Rate mask Regdot11OperationalRateSet.
+//
+// Arguments:
+// [in] pVHTRate -
+// Pointer of Regdot11OperationalRateSet
+// [in] maxSS -
+// Maximum spatial stream that will be modified
+// [in] mcsCap -
+// MCS capability of each spatial 0:0-7/1:0-8/2:0-9
+//
+VOID
+VHTMaskSuppDataRate(
+ pu1Byte pVHTRate,
+ u1Byte maxSS,
+ u1Byte mcsCap
+ )
+{
+ u1Byte i=0, j=0, nSS = 0;
+ u1Byte RegRate = 0;
+
+ for (i=0; i<2; i++)
+ {
+ for(j = 0; j < 8; j+=2)
+ {
+ RegRate = (pVHTRate[i] >> j) & 3;
+
+ if(nSS < maxSS)
+ {
+ if(RegRate != 3 && mcsCap <= RegRate)
+ pVHTRate[i] = (pVHTRate[i] & ~(0x03 << j) ) | (mcsCap << j);
+ }
+ else
+ {
+ return;
+ }
+ nSS++;
+ }
+ }
+}
+
+
+#else
+u2Byte
+VHTMcsToDataRate(
+ PADAPTER Adapter,
+ u2Byte nMcsRate
+)
+{
+ return 0;
+}
+
+
+VOID
+VHTConstructCapabilityElement(
+ PADAPTER Adapter,
+ POCTET_STRING posVHTInfo,
+ BOOLEAN bAssoc)
+{}
+
+VOID
+VHTConstructOperationElement(
+ PADAPTER Adapter,
+ POCTET_STRING posVHTOperation
+)
+{}
+
+
+u1Byte
+VHTIOTActIsAMsduEnable(
+ PADAPTER Adapter
+)
+{return 0;}
+
+
+VOID
+VHTSendOperatingModeNotification(
+ IN PADAPTER Adapter,
+ IN pu1Byte Addr
+ )
+{}
+
+RT_STATUS
+VHT_OnOpModeNotify(
+ IN PADAPTER Adapter,
+ IN PRT_RFD pRfd,
+ IN POCTET_STRING posMpdu
+ )
+{
+ return RT_STATUS_SUCCESS;
+}
+
+u1Byte
+VHTGetHighestMCSRate(
+ IN PADAPTER Adapter,
+ IN pu1Byte pMCSRateSet
+)
+{
+ return 0;
+}
+
+VOID
+VHTCheckVHTCap(
+ IN PADAPTER Adapter,
+ IN PRT_WLAN_STA pEntry,
+ IN pu1Byte pVHTCap
+)
+{
+}
+
+VOID
+VHTOnAssocRsp(
+ IN PADAPTER Adapter,
+ IN OCTET_STRING asocpdu
+)
+{}
+
+VOID
+VHTInitializeVHTInfo(
+ PADAPTER Adapter)
+{}
+
+
+VOID
+VHTGetValueFromBeaconOrProbeRsp(
+ PADAPTER Adapter,
+ POCTET_STRING pSRCmmpdu,
+ PRT_WLAN_BSS bssDesc
+)
+{}
+
+
+VOID
+VHTResetSelfAndSavePeerSetting(
+ PADAPTER Adapter,
+ PRT_WLAN_BSS pBssDesc
+)
+{}
+
+
+VOID
+VHTUseDefaultSetting(
+ PADAPTER Adapter
+)
+{}
+
+
+VOID
+VHTUpdateSelfAndPeerSetting(
+ PADAPTER Adapter,
+ PRT_WLAN_BSS pBssDesc
+)
+{}
+
+VOID
+VHTMaskSuppDataRate(
+ pu1Byte pVHTRate,
+ u1Byte maxSS,
+ u1Byte mcsCap
+ )
+{
+}
+
+BOOLEAN
+VHTModeSupport(
+ PADAPTER Adapter,
+ POCTET_STRING pSRCmmpdu
+)
+{
+ return FALSE;
+}
+
+#endif
+