diff options
Diffstat (limited to 'network/wlan/WDI/COMMON/BssCoexistence.c')
| -rw-r--r-- | network/wlan/WDI/COMMON/BssCoexistence.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/network/wlan/WDI/COMMON/BssCoexistence.c b/network/wlan/WDI/COMMON/BssCoexistence.c new file mode 100644 index 00000000..9335c634 --- /dev/null +++ b/network/wlan/WDI/COMMON/BssCoexistence.c @@ -0,0 +1,331 @@ +#include "Mp_Precomp.h" + + +#if WPP_SOFTWARE_TRACE +#include "BssCoexistence.tmh" +#endif + +VOID +BSS_ParsingOBSSInfoElement( + PADAPTER Adapter, + OCTET_STRING osFrame, + PRT_WLAN_BSS pBssDesc + ) +{ + pBssDesc->BssHT.OBSSScanInterval = + GET_OBSS_PARAM_ELE_SCAN_INTERVAL(osFrame.Octet); +} + +VOID +BSS_ParsingBSSCoexistElement( + PADAPTER Adapter, + OCTET_STRING osFrame, + PRT_WLAN_BSS pBssDesc + ) +{ + pBssDesc->BssHT.bdOBSSExemption = + GET_BSS_COEXISTENCE_ELE_OBSS_EXEMPTION_GRT(osFrame.Octet); +} + +VOID +BSS_AppendExentedCapElement( + PADAPTER pAdapter, + POCTET_STRING posFrame + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + PRT_HIGH_THROUGHPUT pHTInfo = GET_HT_INFO(pMgntInfo); + OCTET_STRING Info; + u1Byte InfoContent[8] = {0}; + + FillOctetString(Info, InfoContent, sizeof(InfoContent)); + + if(pHTInfo->bBssCoexist) + { + SET_EXT_CAPABILITY_ELE_BSS_COEXIST(InfoContent, 1); + } + + if(pMgntInfo->pVHTInfo->bCurrentVHTSupport) + { + SET_EXT_CAPABILITY_ELE_OP_MODE_NOTIF(InfoContent, 1); + } + + PacketMakeElement( posFrame, EID_EXTCapability, Info); +} + + +VOID +BSS_AppendBSSCoexistReportElement( + PADAPTER Adapter, + POCTET_STRING posFrame + ) +{ + u2Byte i,j,k; + PRT_WLAN_BSS pRtBss = NULL; + PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); + OCTET_STRING Info; + u1Byte InfoContent[16] = {0}; +// u1Byte ICS[255][15]; + //pu1Byte *ICS; + pu1Byte ICS; + PRT_GEN_TEMP_BUFFER pGenBufICS; + + // + // 2011/05/25 Justin/MH Two dimenssion array can not use below method. You need + // to allocate two layers pointer for array ICS[255][15]. To simplize the problem. We will only + // support one dimenssion arry to simulate 2/3/.. layer array as below. + // + + pGenBufICS = GetGenTempBuffer (Adapter, 255*15); + //ICS = (u1Byte **)pGenBufICS->Buffer.Ptr; + ICS = (u1Byte *)pGenBufICS->Buffer.Ptr; + + //PlatformZeroMemory (*ICS, 255*15); + for (i=0; i<pMgntInfo->NumBssDesc4Query; i++) + { + pRtBss = pMgntInfo->bssDesc4Query+i; + + if(pRtBss->BssHT.bdSupportHT == FALSE) + { + //ICS[pRtBss->RegulatoryClass][pRtBss->ChannelNumber]=1; + //if(ICS[pRtBss->RegulatoryClass][0] == 0) + //ICS[pRtBss->RegulatoryClass][0] = 1; + ICS[pRtBss->RegulatoryClass*15+pRtBss->ChannelNumber]=1; + if(ICS[pRtBss->RegulatoryClass*15+0] == 0) + ICS[pRtBss->RegulatoryClass*15+0] = 1; + } + } + + for(i= 0;i<255;i++) + { + if(posFrame->Length > sMaxMpduLng) + break; + //if(ICS[i][0] == 1) + if(ICS[i*15+0] == 1) + { + k = 0; + SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent,i); + for(j=1;j<=14;j++) + { + //if(ICS[i][j]==1) + if(ICS[i*15+j]==1) + { + if(k<16) + { + SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); + k++; + } + } + } + FillOctetString(Info, InfoContent, 2+k-1); + //PRINT_DATA("", Info.Octet, Info.Length); + PacketMakeElement(posFrame, EID_BSSIntolerantChlReport, Info); + } + } + ReturnGenTempBuffer (Adapter, pGenBufICS); +} + + +VOID +ConstructBSSCoexistPacket( + PADAPTER Adapter, + pu1Byte Buffer, + pu4Byte pLength, + BOOLEAN TE_A, + BOOLEAN TE_B + ) +{ + PMGNT_INFO pMgntInfo = &Adapter->MgntInfo; + PRT_HIGH_THROUGHPUT pHTInfo = GET_HT_INFO(pMgntInfo); + OCTET_STRING osBSSCOEXISTFrame; + OCTET_STRING Info; + u1Byte InfoContent[1] = {0}; + + FillOctetString(osBSSCOEXISTFrame, Buffer, 0); + *pLength = 0; + + ConstructMaFrameHdr( + Adapter, + Adapter->MgntInfo.Bssid, + ACT_CAT_PUBLIC, + ACT_PUBLIC_BSSCOEXIST, + &osBSSCOEXISTFrame); + + if(IS_WIRELESS_MODE_5G(Adapter)) + { + SET_BSS_COEXISTENCE_ELE_FORTY_INTOLERANT(InfoContent, 0); + } + else + { + SET_BSS_COEXISTENCE_ELE_FORTY_INTOLERANT(InfoContent, pHTInfo->b40Intolerant); + } + + if(TE_B) + SET_BSS_COEXISTENCE_ELE_20_WIDTH_REQ(InfoContent, 1); + + FillOctetString(Info, InfoContent, 1); + PacketMakeElement(&osBSSCOEXISTFrame, EID_BSSCoexistence, Info); + + if(TE_A) + BSS_AppendBSSCoexistReportElement(Adapter, &osBSSCOEXISTFrame); + + *pLength = osBSSCOEXISTFrame.Length; +} + + +VOID +SendBSSCoexistPacket( + PADAPTER Adapter, + BOOLEAN TE_A, + BOOLEAN TE_B + ) +{ + PRT_TCB pTcb; + PRT_TX_LOCAL_BUFFER pBuf; + u1Byte DataRate = MgntQuery_MgntFrameTxRate(Adapter, Adapter->MgntInfo.Bssid); + + PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK); + + if(MgntGetBuffer(Adapter, &pTcb, &pBuf)) + { + ConstructBSSCoexistPacket( + Adapter, + pBuf->Buffer.VirtualAddress, + &pTcb->PacketLength, + TE_A, + TE_B + ); + + if(pTcb->PacketLength != 0) + MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, DataRate); + } + + PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK); +} + +RT_STATUS +OnBssCoexistence( + IN PADAPTER Adapter, + IN PRT_RFD pRfd, + IN POCTET_STRING posMpdu + ) +{ + return RT_STATUS_NOT_SUPPORT; +} + +VOID +BSS_OnScanComplete( + IN PADAPTER Adapter + ) +{ + u2Byte i; + PRT_WLAN_BSS pRtBss = NULL; + BOOLEAN TE_A = FALSE, TE_B = FALSE; + PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); + PRT_HIGH_THROUGHPUT pHTInfo = GET_HT_INFO(pMgntInfo); + u8Byte curSystemTimeUs = 0; + + RT_TRACE(COMP_SCAN, DBG_LOUD, ("bCurrentHTSupport %d bPeerBssCoexistence %d, bPeer40MHzIntolerant %d, bCurOBSSScanExemptionGrt %d CurOBSSScanInterval %d\n", pHTInfo->bCurrentHTSupport, pHTInfo->bPeerBssCoexistence, pHTInfo->bPeer40MHzIntolerant, pHTInfo->bCurOBSSScanExemptionGrt, pHTInfo->CurOBSSScanInterval)); + + do + { + // Only collect information to associated ap + if(!pMgntInfo->mAssoc) + break; + // Only sent message to FC HT AP + else if(pHTInfo->bCurrentHTSupport == FALSE || pHTInfo->bPeer40MHzCap == FALSE) + break; + else if(pHTInfo->bBssCoexist == FALSE || pHTInfo->bPeerBssCoexistence == FALSE) + break; + else if(!CHNL_GetRegBWSupport(Adapter)) + break; + else if(TRUE == pHTInfo->bCurOBSSScanExemptionGrt) + break; + + for (i=0; i<pMgntInfo->NumBssDesc4Query; i++) + { + pRtBss = pMgntInfo->bssDesc4Query+i; + + if(pRtBss->BssHT.bdSupportHT == FALSE) + TE_A = TRUE; + else if(pRtBss->BssHT.bd40Intolerant == TRUE) + TE_B = TRUE; + + if(TE_A && TE_B) + break; + } + + pHTInfo->IdleOBSSScanCnt = 0; + curSystemTimeUs = PlatformGetCurrentTime(); + + // Check the conditions and the interval to send the report (we don't send the report repeatly as soon) + if((TE_A || TE_B) && + (0 == pHTInfo->lastTimeSentObssRptUs || + ((curSystemTimeUs - pHTInfo->lastTimeSentObssRptUs) > ((pHTInfo->CurOBSSScanInterval * 2 / 3) * 1000000)))) + { + RT_TRACE_F(COMP_HT, DBG_LOUD, + ("SendBSSCoexistPacket() TE_A(%d), TE_B(%d), (curSystemTimeUs - pHTInfo->lastTimeSentObssRptUs) = %d \n", TE_A, TE_B, (u4Byte)(curSystemTimeUs - pHTInfo->lastTimeSentObssRptUs))); + pHTInfo->lastTimeSentObssRptUs = curSystemTimeUs; + SendBSSCoexistPacket(Adapter, TE_A, TE_B); + } + }while(FALSE); + + RT_TRACE_F(COMP_HT, DBG_LOUD, ("<== IdleOBSSScanCnt = %d, pHTInfo->lastTimeSentObssRptUs = %d\n", pHTInfo->IdleOBSSScanCnt, (u4Byte)pHTInfo->lastTimeSentObssRptUs)); +} + +// +// Description: +// The wachdog monitor the BSS coexistance in 40MHz. The OBSS information asks the client +// to periodically scan the 40MHz intolerant APs. +// Arguments: +// [in] pAdapter - +// The current Adapter context. +// Return: +// None +// By Bruce, 2011-07-29. +// +VOID +BSS_IdleScanWatchDog( + IN PADAPTER pAdapter + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + PRT_HIGH_THROUGHPUT pHTInfo = GET_HT_INFO(pMgntInfo); + u2Byte ObssScanInterfaval = 0; + + // Only collect information to associated ap + if(!pMgntInfo->mAssoc) + return; + + // Only sent message to FC HT AP + if(pHTInfo->bCurrentHTSupport == FALSE) + return; + // We are not in 40MHz + else if(!CHNL_RUN_ABOVE_40MHZ(pMgntInfo)) + return; + else if(pHTInfo->bBssCoexist == FALSE || pHTInfo->bPeerBssCoexistence == FALSE) + return; + else if(pHTInfo->bCurOBSSScanExemptionGrt == TRUE) + return; + else if(0 == pHTInfo->CurOBSSScanInterval) + return; + else if(pMgntInfo->LinkDetectInfo.bHigherBusyTraffic) + return; + + // We don't want the scan interval too small. + // By Bruce, 2011-07-28. + if(pHTInfo->CurOBSSScanInterval < RT_OBSS_MIN_TRIGGER_SCAN_INTERVAL) + ObssScanInterfaval = RT_OBSS_MIN_TRIGGER_SCAN_INTERVAL; + else + ObssScanInterfaval = pHTInfo->CurOBSSScanInterval; + + pHTInfo->IdleOBSSScanCnt ++; + + if((pHTInfo->IdleOBSSScanCnt * RT_CHECK_FOR_HANG_PERIOD) >= ObssScanInterfaval) + { + RT_TRACE_F(COMP_HT, DBG_LOUD, ("Reaches the OBSS scan interval, start to scan....\n")); + pHTInfo->IdleOBSSScanCnt = 0; + + MgntActSet_802_11_BSSID_LIST_SCAN(pAdapter); + } +} |
