/* */ #include "rt_config.h" #ifdef SCAN_SUPPORT static INT scan_ch_restore(RTMP_ADAPTER *pAd, UCHAR OpMode) { INT bw, ch; if (pAd->CommonCfg.BBPCurrentBW != pAd->hw_cfg.bbp_bw) { rtmp_bbp_set_bw(pAd, pAd->hw_cfg.bbp_bw); AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); ch = pAd->CommonCfg.CentralChannel; } else { AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.Channel); ch = pAd->CommonCfg.Channel; } switch(pAd->CommonCfg.BBPCurrentBW) { case BW_80: bw = 80; break; case BW_40: bw = 40; break; case BW_10: bw = 10; break; case BW_20: default: bw =20; break; } DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to %dMHz channel %d, Total BSS[%02d]\n", bw, ch, pAd->ScanTab.BssNr)); #ifdef CONFIG_AP_SUPPORT if (OpMode == OPMODE_AP) { pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; RTMPResumeMsduTransmission(pAd); /* iwpriv set auto channel selection*/ /* scanned all channels*/ if (pAd->ApCfg.bAutoChannelAtBootup==TRUE) { pAd->CommonCfg.Channel = SelectBestChannel(pAd, pAd->ApCfg.AutoChannelAlg); pAd->ApCfg.bAutoChannelAtBootup = FALSE; #ifdef DOT11_N_SUPPORT N_ChannelCheck(pAd); #endif /* DOT11_N_SUPPORT */ APStop(pAd); APStartUp(pAd); } if (!((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == TRUE))) AsicEnableBssSync(pAd); } #endif /* CONFIG_AP_SUPPORT */ return TRUE; } static INT scan_active(RTMP_ADAPTER *pAd, UCHAR OpMode, UCHAR ScanType) { UCHAR *frm_buf = NULL; HEADER_802_11 Hdr80211; ULONG FrameLen = 0; UCHAR SsidLen = 0; if (MlmeAllocateMemory(pAd, &frm_buf) != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n")); #ifdef CONFIG_AP_SUPPORT if (OpMode == OPMODE_AP) pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; #endif /* CONFIG_AP_SUPPORT */ return FALSE; } #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 if (ScanType == SCAN_2040_BSS_COEXIST) { DBGPRINT(RT_DEBUG_INFO, ("SYNC - SCAN_2040_BSS_COEXIST !! Prepare to send Probe Request\n")); } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ /* There is no need to send broadcast probe request if active scan is in effect.*/ SsidLen = 0; if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) #ifdef WSC_STA_SUPPORT || ((ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_STA)) #endif /* WSC_STA_SUPPORT */ ) SsidLen = pAd->MlmeAux.SsidLen; { #ifdef CONFIG_AP_SUPPORT /*IF_DEV_CONFIG_OPMODE_ON_AP(pAd) */ if (OpMode == OPMODE_AP) { MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, pAd->ApCfg.MBSSID[0].Bssid); } #endif /* CONFIG_AP_SUPPORT */ MakeOutgoingFrame(frm_buf, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, &pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, END_OF_ARGS); if (pAd->CommonCfg.ExtRateLen) { ULONG Tmp; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += Tmp; } } #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { ULONG Tmp; UCHAR HtLen; UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; #endif if (pAd->bBroadComHT == TRUE) { HtLen = pAd->MlmeAux.HtCapabilityLen + 4; #ifdef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &WpaIe, 1, &HtLen, 4, &BROADCOM[0], pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, END_OF_ARGS); #else MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &WpaIe, 1, &HtLen, 4, &BROADCOM[0], pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, END_OF_ARGS); #endif /* RT_BIG_ENDIAN */ } else { HtLen = sizeof(HT_CAPABILITY_IE); #ifdef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, END_OF_ARGS); #else MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &pAd->CommonCfg.HtCapability, END_OF_ARGS); #endif /* RT_BIG_ENDIAN */ } FrameLen += Tmp; #ifdef DOT11N_DRAFT3 if ((pAd->MlmeAux.Channel <= 14) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) { ULONG Tmp; HtLen = 1; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtHtCapIe, 1, &HtLen, 1, &pAd->CommonCfg.BSSCoexist2040.word, END_OF_ARGS); FrameLen += Tmp; } #endif /* DOT11N_DRAFT3 */ } #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->MlmeAux.Channel > 14)) { FrameLen += build_vht_ies(pAd, (UCHAR *)(frm_buf + FrameLen), SUBTYPE_PROBE_REQ); } #endif /* DOT11_VHT_AC */ #ifdef WSC_STA_SUPPORT if (OpMode == OPMODE_STA) { BOOLEAN bHasWscIe = FALSE; /* Append WSC information in probe request if WSC state is running */ if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && (pAd->StaCfg.WscControl.bWscTrigger == TRUE)) bHasWscIe = TRUE; #ifdef WSC_V2_SUPPORT else if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && (pAd->StaCfg.WscControl.WscV2Info.bEnableWpsV2)) bHasWscIe = TRUE; #endif /* WSC_V2_SUPPORT */ if (bHasWscIe) { UCHAR *pWscBuf = NULL, WscIeLen = 0; ULONG WscTmpLen = 0; os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512); if (pWscBuf != NULL) { NdisZeroMemory(pWscBuf, 512); WscBuildProbeReqIE(pAd, STA_MODE, pWscBuf, &WscIeLen); MakeOutgoingFrame(frm_buf + FrameLen, &WscTmpLen, WscIeLen, pWscBuf, END_OF_ARGS); FrameLen += WscTmpLen; os_free_mem(NULL, pWscBuf); } else DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); } } #endif /* WSC_STA_SUPPORT */ MiniportMMRequest(pAd, 0, frm_buf, FrameLen); MlmeFreeMemory(pAd, frm_buf); return TRUE; } /* ========================================================================== Description: Scan next channel ========================================================================== */ VOID ScanNextChannel( IN PRTMP_ADAPTER pAd, IN UCHAR OpMode) { UCHAR ScanType = pAd->MlmeAux.ScanType; UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; BOOLEAN ScanPending = FALSE; RALINK_TIMER_STRUCT *sc_timer; UINT stay_time = 0; UCHAR ImprovedScan_MaxScanChannelCnt; #ifdef RALINK_ATE /* Nothing to do in ATE mode. */ if (ATE_ON(pAd)) return; #endif /* RALINK_ATE */ if ((pAd->MlmeAux.Channel == 0) || ScanPending) { scan_ch_restore(pAd, OpMode); } #ifdef RTMP_MAC_USB #endif /* RTMP_MAC_USB */ else { AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE); AsicLockChannel(pAd, pAd->MlmeAux.Channel); /* Check if channel if passive scan under current regulatory domain */ if (CHAN_PropertyCheck(pAd, pAd->MlmeAux.Channel, CHANNEL_PASSIVE_SCAN) == TRUE) ScanType = SCAN_PASSIVE; if (OpMode == OPMODE_AP) sc_timer = &pAd->MlmeAux.APScanTimer; else sc_timer = &pAd->MlmeAux.ScanTimer; /* We need to shorten active scan time in order for WZC connect issue */ /* Chnage the channel scan time for CISCO stuff based on its IAPP announcement */ if (ScanType == FAST_SCAN_ACTIVE) stay_time = FAST_ACTIVE_SCAN_TIME; else /* must be SCAN_PASSIVE or SCAN_ACTIVE*/ { #ifdef CONFIG_AP_SUPPORT if ((OpMode == OPMODE_AP) && (pAd->ApCfg.bAutoChannelAtBootup)) stay_time = AUTO_CHANNEL_SEL_TIMEOUT; else #endif /* CONFIG_AP_SUPPORT */ if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode) && WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) { if (pAd->MlmeAux.Channel > 14) stay_time = ScanTimeIn5gChannel; else stay_time = MIN_CHANNEL_TIME; } #ifdef WIFI_P2P_CONCURRENT_FAST_SCAN /* If this is not PASSIVE scan && Fast scan is enabled, we shorten the chanenl dwell time */ else if (ScanType != SCAN_PASSIVE && pAd->StaCfg.bImprovedScan) stay_time = FAST_ACTIVE_SCAN_TIME; #endif /* WIFI_P2P_CONCURRENT_FAST_SCAN */ else stay_time = MAX_CHANNEL_TIME; } RTMPSetTimer(sc_timer, stay_time); if (SCAN_MODE_ACT(ScanType)) { if (scan_active(pAd, OpMode, ScanType) == FALSE) return; } /* For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse*/ #ifdef CONFIG_AP_SUPPORT if (OpMode == OPMODE_AP) pAd->Mlme.ApSyncMachine.CurrState = AP_SCAN_LISTEN; #endif /* CONFIG_AP_SUPPORT */ } } BOOLEAN ScanRunning( IN PRTMP_ADAPTER pAd) { BOOLEAN rv = FALSE; #ifdef CONFIG_AP_SUPPORT #ifdef AP_SCAN_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) rv = ((pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_LISTEN) ? TRUE : FALSE); #endif /* AP_SCAN_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ return rv; } #endif /* SCAN_SUPPORT */