/* ************************************************************************* * Ralink Tech Inc. * 5F., No.36, Taiyuan St., Jhubei City, * Hsinchu County 302, * Taiwan, R.O.C. * * (c) Copyright 2002-2007, Ralink Technology, Inc. * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * 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 the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* Module Name: sync.c Abstract: Revision History: Who When What -------- ---------- ---------------------------------------------- John Chang 2004-09-01 modified for rt2561/2661 Jan Lee 2006-08-01 modified for rt2860 for 802.11n */ #include "../rt_config.h" #define AC0_DEF_TXOP 0 #define AC1_DEF_TXOP 0 #define AC2_DEF_TXOP 94 #define AC3_DEF_TXOP 47 VOID AdhocTurnOnQos( IN PRTMP_ADAPTER pAd) { // Turn on QOs if use HT rate. if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) { pAd->CommonCfg.APEdcaParm.bValid = TRUE; pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10; pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6; pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; pAd->CommonCfg.APEdcaParm.Txop[0] = 0; pAd->CommonCfg.APEdcaParm.Txop[1] = 0; pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP; pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP; } AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); } /* ========================================================================== Description: The sync state machine, Parameters: Sm - pointer to the state machine Note: the state machine looks like the following ========================================================================== */ VOID SyncStateMachineInit( IN PRTMP_ADAPTER pAd, IN STATE_MACHINE *Sm, OUT STATE_MACHINE_FUNC Trans[]) { StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE); // column 1 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction); StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction); StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction); StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon); StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction); //column 2 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan); StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin); StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction); StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction); // column 3 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan); StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin); StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction); // timer init RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE); RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE); } /* ========================================================================== Description: Beacon timeout handler, executed in timer thread IRQL = DISPATCH_LEVEL ========================================================================== */ VOID BeaconTimeout( IN PVOID SystemSpecific1, IN PVOID FunctionContext, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3) { RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n")); // Do nothing if the driver is starting halt state. // This might happen when timer already been fired before cancel timer with mlmehalt if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) return; #ifdef DOT11_N_SUPPORT if ((pAd->CommonCfg.BBPCurrentBW == BW_40) ) { UCHAR BBPValue = 0; AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); BBPValue |= 0x10; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); } #endif // DOT11_N_SUPPORT // MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL); RT28XX_MLME_HANDLER(pAd); } /* ========================================================================== Description: Scan timeout handler, executed in timer thread IRQL = DISPATCH_LEVEL ========================================================================== */ VOID ScanTimeout( IN PVOID SystemSpecific1, IN PVOID FunctionContext, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3) { RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; // Do nothing if the driver is starting halt state. // This might happen when timer already been fired before cancel timer with mlmehalt if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) return; if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL)) { RT28XX_MLME_HANDLER(pAd); } else { // To prevent SyncMachine.CurrState is SCAN_LISTEN forever. pAd->MlmeAux.Channel = 0; ScanNextChannel(pAd); if (pAd->CommonCfg.bWirelessEvent) { RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); } } } /* ========================================================================== Description: MLME SCAN req state machine procedure ========================================================================== */ VOID MlmeScanReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0; BOOLEAN TimerCancelled; ULONG Now; USHORT Status; PHEADER_802_11 pHdr80211; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; // Check the total scan tries for one single OID command // If this is the CCX 2.0 Case, skip that! if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n")); return; } // Increase the scan retry counters. pAd->StaCfg.ScanCnt++; #ifdef RT2860 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && (IDLE_ON(pAd)) && (pAd->StaCfg.bRadio == TRUE) && (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) { RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); } #endif // RT2860 // // first check the parameter sanity if (MlmeScanReqSanity(pAd, Elem->Msg, Elem->MsgLen, &BssType, Ssid, &SsidLen, &ScanType)) { // Check for channel load and noise hist request // Suspend MSDU only at scan request, not the last two mentioned if ((ScanType == SCAN_CISCO_NOISE) || (ScanType == SCAN_CISCO_CHANNEL_LOAD)) { if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) RTMPSuspendMsduTransmission(pAd); // Suspend MSDU transmission here } else { // Suspend MSDU transmission here RTMPSuspendMsduTransmission(pAd); } // // To prevent data lost. // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. // And should send an NULL data with turned PSM bit off to AP, when scan progress done // if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) { NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); if (NStatus == NDIS_STATUS_SUCCESS) { pHdr80211 = (PHEADER_802_11) pOutBuffer; MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); pHdr80211->Duration = 0; pHdr80211->FC.Type = BTYPE_DATA; pHdr80211->FC.PwrMgmt = PWR_SAVE; // Send using priority queue MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n")); MlmeFreeMemory(pAd, pOutBuffer); RTMPusecDelay(5000); } } NdisGetSystemUpTime(&Now); pAd->StaCfg.LastScanTime = Now; // reset all the timers RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); // record desired BSS parameters pAd->MlmeAux.BssType = BssType; pAd->MlmeAux.ScanType = ScanType; pAd->MlmeAux.SsidLen = SsidLen; NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); // start from the first channel pAd->MlmeAux.Channel = FirstChannel(pAd); // Change the scan channel when dealing with CCX beacon report if ((ScanType == SCAN_CISCO_PASSIVE) || (ScanType == SCAN_CISCO_ACTIVE) || (ScanType == SCAN_CISCO_CHANNEL_LOAD) || (ScanType == SCAN_CISCO_NOISE)) pAd->MlmeAux.Channel = pAd->StaCfg.CCXScanChannel; // Let BBP register at 20MHz to do scan RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); ScanNextChannel(pAd); } else { DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n")); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_INVALID_FORMAT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); } } /* ========================================================================== Description: MLME JOIN req state machine procedure ========================================================================== */ VOID MlmeJoinReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR BBPValue = 0; BSS_ENTRY *pBss; BOOLEAN TimerCancelled; HEADER_802_11 Hdr80211; NDIS_STATUS NStatus; ULONG FrameLen = 0; PUCHAR pOutBuffer = NULL; PUCHAR pSupRate = NULL; UCHAR SupRateLen; PUCHAR pExtRate = NULL; UCHAR ExtRateLen; UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C}; UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR); MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx)); #ifdef RT2860 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && (IDLE_ON(pAd)) && (pAd->StaCfg.bRadio == TRUE) && (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) { RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); } #endif // RT2860 // // reset all the timers RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx]; // record the desired SSID & BSSID we're waiting for COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid); // If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again. if (pBss->Hidden == 0) { NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen); pAd->MlmeAux.SsidLen = pBss->SsidLen; } pAd->MlmeAux.BssType = pBss->BssType; pAd->MlmeAux.Channel = pBss->Channel; pAd->MlmeAux.CentralChannel = pBss->CentralChannel; #ifdef EXT_BUILD_CHANNEL_LIST // Country IE of the AP will be evaluated and will be used. if ((pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) && (pBss->bHasCountryIE == TRUE)) { NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pBss->CountryString[0], 2); if (pBss->CountryString[2] == 'I') pAd->CommonCfg.Geography = IDOR; else if (pBss->CountryString[2] == 'O') pAd->CommonCfg.Geography = ODOR; else pAd->CommonCfg.Geography = BOTH; BuildChannelListEx(pAd); } #endif // EXT_BUILD_CHANNEL_LIST // // Let BBP register at 20MHz to do scan RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); // switch channel and waiting for beacon timer AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); AsicLockChannel(pAd, pAd->MlmeAux.Channel); RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT); do { if (((pAd->CommonCfg.bIEEE80211H == 1) && (pAd->MlmeAux.Channel > 14) && RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier || (pAd->CommonCfg.CarrierDetect.Enable == TRUE) #endif // CARRIER_DETECTION_SUPPORT // ) { // // We can't send any Probe request frame to meet 802.11h. // if (pBss->Hidden == 0) break; } // // send probe request // NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus == NDIS_STATUS_SUCCESS) { if (pAd->MlmeAux.Channel <= 14) { pSupRate = pAd->CommonCfg.SupRate; SupRateLen = pAd->CommonCfg.SupRateLen; pExtRate = pAd->CommonCfg.ExtRate; ExtRateLen = pAd->CommonCfg.ExtRateLen; } else { // // Overwrite Support Rate, CCK rate are not allowed // pSupRate = ASupRate; SupRateLen = ASupRateLen; ExtRateLen = 0; } if (pAd->MlmeAux.BssType == BSS_INFRA) MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid); else MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &pAd->MlmeAux.SsidLen, pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pSupRate, END_OF_ARGS); if (ExtRateLen) { ULONG Tmp; MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, 1, &ExtRateIe, 1, &ExtRateLen, ExtRateLen, pExtRate, END_OF_ARGS); FrameLen += Tmp; } MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } } while (FALSE); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n", pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON; } /* ========================================================================== Description: MLME START Request state machine procedure, starting an IBSS ========================================================================== */ VOID MlmeStartReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen; BOOLEAN TimerCancelled; // New for WPA security suites UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 NDIS_802_11_VARIABLE_IEs *pVIE = NULL; LARGE_INTEGER TimeStamp; BOOLEAN Privacy; USHORT Status; // Init Variable IE structure pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; pVIE->Length = 0; TimeStamp.u.LowPart = 0; TimeStamp.u.HighPart = 0; if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, Ssid, &SsidLen)) { // reset all the timers RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); // // Start a new IBSS. All IBSS parameters are decided now.... // DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n")); pAd->MlmeAux.BssType = BSS_ADHOC; NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); pAd->MlmeAux.SsidLen = SsidLen; // generate a radom number as BSSID MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid); DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n")); Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); pAd->MlmeAux.CapabilityInfo = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0); pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod; pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin; pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel; pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen; NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo); pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE); // Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here. DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n")); } else #endif // DOT11_N_SUPPORT // { pAd->MlmeAux.HtCapabilityLen = 0; pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; } // temporarily not support QOS in IBSS NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); AsicLockChannel(pAd, pAd->MlmeAux.Channel); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n", pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_SUCCESS; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); } else { DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n")); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_INVALID_FORMAT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); } } /* ========================================================================== Description: peer sends beacon back when scanning ========================================================================== */ VOID PeerBeaconAtScanAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; UCHAR Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel, SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe; CF_PARM CfParm; USHORT BeaconPeriod, AtimWin, CapabilityInfo; PFRAME_802_11 pFrame; LARGE_INTEGER TimeStamp; UCHAR Erp; UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; UCHAR SupRateLen, ExtRateLen; USHORT LenVIE; UCHAR CkipFlag; UCHAR AironetCellPowerLimit; EDCA_PARM EdcaParm; QBSS_LOAD_PARM QbssLoad; QOS_CAPABILITY_PARM QosCapability; ULONG RalinkIe; UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 NDIS_802_11_VARIABLE_IEs *pVIE = NULL; HT_CAPABILITY_IE HtCapability; ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0; UCHAR AddHtInfoLen; UCHAR NewExtChannelOffset = 0xff; pFrame = (PFRAME_802_11) Elem->Msg; // Init Variable IE structure pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; pVIE->Length = 0; #ifdef DOT11_N_SUPPORT RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); #endif // DOT11_N_SUPPORT // if (PeerBeaconAndProbeRspSanity(pAd, Elem->Msg, Elem->MsgLen, Elem->Channel, Addr2, Bssid, Ssid, &SsidLen, &BssType, &BeaconPeriod, &Channel, &NewChannel, &TimeStamp, &CfParm, &AtimWin, &CapabilityInfo, &Erp, &DtimCount, &DtimPeriod, &BcastFlag, &MessageToMe, SupRate, &SupRateLen, ExtRate, &ExtRateLen, &CkipFlag, &AironetCellPowerLimit, &EdcaParm, &QbssLoad, &QosCapability, &RalinkIe, &HtCapabilityLen, &PreNHtCapabilityLen, &HtCapability, &AddHtInfoLen, &AddHtInfo, &NewExtChannelOffset, &LenVIE, pVIE)) { ULONG Idx; CHAR Rssi = 0; Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); if (Idx != BSS_NOT_FOUND) Rssi = pAd->ScanTab.BssEntry[Idx].Rssi; Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); #ifdef DOT11_N_SUPPORT if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) HtCapabilityLen = SIZE_HT_CAP_IE; #endif // DOT11_N_SUPPORT // if ((pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) && (Channel == pAd->StaCfg.CCXScanChannel)) { Idx = BssTableSetEntry(pAd, &pAd->StaCfg.CCXBssTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen,ExtRate, ExtRateLen, &HtCapability, &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); if (Idx != BSS_NOT_FOUND) { NdisMoveMemory(pAd->StaCfg.CCXBssTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); if (pAd->StaCfg.CCXReqType == MSRN_TYPE_BEACON_REQ) AironetAddBeaconReport(pAd, Idx, Elem); } } else { Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 if (pAd->ChannelList[pAd->CommonCfg.ChannelListIdx].bEffectedChannel == TRUE) { UCHAR RegClass; PeerBeaconAndProbeRspSanity2(pAd, Elem->Msg, Elem->MsgLen, &RegClass); TriEventTableSetEntry(pAd, &pAd->CommonCfg.TriggerEventTab, Bssid, &HtCapability, HtCapabilityLen, RegClass, Channel); } #endif // DOT11N_DRAFT3 // #endif // DOT11_N_SUPPORT // if (Idx != BSS_NOT_FOUND) { NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); } } } // sanity check fail, ignored } /* ========================================================================== Description: When waiting joining the (I)BSS, beacon received from external ========================================================================== */ VOID PeerBeaconAtJoinAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe, DtimCount, DtimPeriod, BcastFlag, NewChannel; LARGE_INTEGER TimeStamp; USHORT BeaconPeriod, AtimWin, CapabilityInfo; CF_PARM Cf; BOOLEAN TimerCancelled; UCHAR Erp; UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; UCHAR SupRateLen, ExtRateLen; UCHAR CkipFlag; USHORT LenVIE; UCHAR AironetCellPowerLimit; EDCA_PARM EdcaParm; QBSS_LOAD_PARM QbssLoad; QOS_CAPABILITY_PARM QosCapability; USHORT Status; UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 NDIS_802_11_VARIABLE_IEs *pVIE = NULL; ULONG RalinkIe; ULONG Idx; HT_CAPABILITY_IE HtCapability; ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0; UCHAR AddHtInfoLen; UCHAR NewExtChannelOffset = 0xff; #ifdef DOT11_N_SUPPORT UCHAR CentralChannel; #endif // DOT11_N_SUPPORT // // Init Variable IE structure pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; pVIE->Length = 0; RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); if (PeerBeaconAndProbeRspSanity(pAd, Elem->Msg, Elem->MsgLen, Elem->Channel, Addr2, Bssid, Ssid, &SsidLen, &BssType, &BeaconPeriod, &Channel, &NewChannel, &TimeStamp, &Cf, &AtimWin, &CapabilityInfo, &Erp, &DtimCount, &DtimPeriod, &BcastFlag, &MessageToMe, SupRate, &SupRateLen, ExtRate, &ExtRateLen, &CkipFlag, &AironetCellPowerLimit, &EdcaParm, &QbssLoad, &QosCapability, &RalinkIe, &HtCapabilityLen, &PreNHtCapabilityLen, &HtCapability, &AddHtInfoLen, &AddHtInfo, &NewExtChannelOffset, &LenVIE, pVIE)) { // Disqualify 11b only adhoc when we are in 11g only adhoc mode if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12)) return; // BEACON from desired BSS/IBSS found. We should be able to decide most // BSS parameters here. // Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION? // Do we need to receover back all parameters belonging to previous BSS? // A. Should be not. There's no back-door recover to previous AP. It still need // a new JOIN-AUTH-ASSOC sequence. if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid)) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel)); RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); // Update RSSI to prevent No signal display when cards first initialized pAd->StaCfg.RssiSample.LastRssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0); pAd->StaCfg.RssiSample.LastRssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1); pAd->StaCfg.RssiSample.LastRssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2); pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0; pAd->StaCfg.RssiSample.AvgRssi0X8 = pAd->StaCfg.RssiSample.AvgRssi0 << 3; pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1; pAd->StaCfg.RssiSample.AvgRssi1X8 = pAd->StaCfg.RssiSample.AvgRssi1 << 3; pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2; pAd->StaCfg.RssiSample.AvgRssi2X8 = pAd->StaCfg.RssiSample.AvgRssi2 << 3; // // We need to check if SSID only set to any, then we can record the current SSID. // Otherwise will cause hidden SSID association failed. // if (pAd->MlmeAux.SsidLen == 0) { NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); pAd->MlmeAux.SsidLen = SsidLen; } else { Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel); if (Idx != BSS_NOT_FOUND) { // // Multiple SSID case, used correct CapabilityInfo // CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo; } } NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN); pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; pAd->MlmeAux.BssType = BssType; pAd->MlmeAux.BeaconPeriod = BeaconPeriod; pAd->MlmeAux.Channel = Channel; pAd->MlmeAux.AtimWin = AtimWin; pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod; pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration; pAd->MlmeAux.APRalinkIe = RalinkIe; // Copy AP's supported rate to MlmeAux for creating assoication request // Also filter out not supported rate pAd->MlmeAux.SupRateLen = SupRateLen; NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen); RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); pAd->MlmeAux.ExtRateLen = ExtRateLen; NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen); RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16); #ifdef DOT11_N_SUPPORT pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen; // filter out un-supported ht rates if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) { RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE); // StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16); pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE; pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; if (PreNHtCapabilityLen > 0) pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE; RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo); // Copy AP Parameter to StaActive. This is also in LinkUp. DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n", pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth)); if (AddHtInfoLen > 0) { CentralChannel = AddHtInfo.ControlChan; // Check again the Bandwidth capability of this AP. if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40)) { CentralChannel = AddHtInfo.ControlChan - 2; } else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40)) { CentralChannel = AddHtInfo.ControlChan + 2; } // Check Error . if (pAd->MlmeAux.CentralChannel != CentralChannel) DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel)); DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, AddHtInfo.ControlChan)); } } else #endif // DOT11_N_SUPPORT // { // To prevent error, let legacy AP must have same CentralChannel and Channel. if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0)) pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel; pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); } RTMPUpdateMlmeRate(pAd); // copy QOS related information if ((pAd->CommonCfg.bWmmCapable) #ifdef DOT11_N_SUPPORT || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) #endif // DOT11_N_SUPPORT // ) { NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM)); NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)); } else { NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); } DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); #ifdef LEAP_SUPPORT // Update CkipFlag pAd->StaCfg.CkipFlag = CkipFlag; // Keep TimeStamp for Re-Association used. if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE)) pAd->StaCfg.CCKMBeaconAtJoinTimeStamp = TimeStamp; #endif // LEAP_SUPPORT // if (AironetCellPowerLimit != 0xFF) { //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); } else //Used the default TX Power Percentage. pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_SUCCESS; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); } // not to me BEACON, ignored } // sanity check fail, ignore this frame } /* ========================================================================== Description: receive BEACON from peer IRQL = DISPATCH_LEVEL ========================================================================== */ VOID PeerBeacon( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; CHAR Ssid[MAX_LEN_OF_SSID]; CF_PARM CfParm; UCHAR SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0; UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0; USHORT CapabilityInfo, AtimWin, BeaconPeriod; LARGE_INTEGER TimeStamp; USHORT TbttNumToNextWakeUp; UCHAR Erp; UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; UCHAR SupRateLen, ExtRateLen; UCHAR CkipFlag; USHORT LenVIE; UCHAR AironetCellPowerLimit; EDCA_PARM EdcaParm; QBSS_LOAD_PARM QbssLoad; QOS_CAPABILITY_PARM QosCapability; ULONG RalinkIe; // New for WPA security suites UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 NDIS_802_11_VARIABLE_IEs *pVIE = NULL; HT_CAPABILITY_IE HtCapability; ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE UCHAR HtCapabilityLen, PreNHtCapabilityLen; UCHAR AddHtInfoLen; UCHAR NewExtChannelOffset = 0xff; #ifdef RALINK_ATE if (ATE_ON(pAd)) { return; } #endif // RALINK_ATE // if (!(INFRA_ON(pAd) || ADHOC_ON(pAd) )) return; // Init Variable IE structure pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; pVIE->Length = 0; RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); if (PeerBeaconAndProbeRspSanity(pAd, Elem->Msg, Elem->MsgLen, Elem->Channel, Addr2, Bssid, Ssid, &SsidLen, &BssType, &BeaconPeriod, &Channel, &NewChannel, &TimeStamp, &CfParm, &AtimWin, &CapabilityInfo, &Erp, &DtimCount, &DtimPeriod, &BcastFlag, &MessageToMe, SupRate, &SupRateLen, ExtRate, &ExtRateLen, &CkipFlag, &AironetCellPowerLimit, &EdcaParm, &QbssLoad, &QosCapability, &RalinkIe, &HtCapabilityLen, &PreNHtCapabilityLen, &HtCapability, &AddHtInfoLen, &AddHtInfo, &NewExtChannelOffset, &LenVIE, pVIE)) { BOOLEAN is_my_bssid, is_my_ssid; ULONG Bssidx, Now; BSS_ENTRY *pBss; CHAR RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE; is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE; // ignore BEACON not for my SSID if ((! is_my_ssid) && (! is_my_bssid)) return; // It means STA waits disassoc completely from this AP, ignores this beacon. if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC) return; #ifdef DOT11_N_SUPPORT // Copy Control channel for this BSSID. if (AddHtInfoLen != 0) Channel = AddHtInfo.ControlChan; if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) HtCapabilityLen = SIZE_HT_CAP_IE; #endif // DOT11_N_SUPPORT // // // Housekeeping "SsidBssTab" table for later-on ROAMing usage. // Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); if (Bssidx == BSS_NOT_FOUND) { // discover new AP of this network, create BSS entry Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel, RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); if (Bssidx == BSS_NOT_FOUND) // return if BSS table full return; NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4); NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); } if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) { // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. AsicSwitchChannel(pAd, 1, FALSE); AsicLockChannel(pAd, 1); LinkDown(pAd, FALSE); MlmeQueueInit(&pAd->Mlme.Queue); BssTableInit(&pAd->ScanTab); RTMPusecDelay(1000000); // use delay to prevent STA do reassoc // channel sanity check for (index = 0 ; index < pAd->ChannelListNum; index++) { if (pAd->ChannelList[index].Channel == NewChannel) { pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; pAd->CommonCfg.Channel = NewChannel; AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.Channel); DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); break; } } if (index >= pAd->ChannelListNum) { DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); } } // if the ssid matched & bssid unmatched, we should select the bssid with large value. // This might happened when two STA start at the same time if ((! is_my_bssid) && ADHOC_ON(pAd)) { INT i; // Add the safeguard against the mismatch of adhoc wep status if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus) { return; } // collapse into the ADHOC network which has bigger BSSID value. for (i = 0; i < 6; i++) { if (Bssid[i] > pAd->CommonCfg.Bssid[i]) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); AsicDisableSync(pAd); COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid); AsicSetBssid(pAd, pAd->CommonCfg.Bssid); MakeIbssBeacon(pAd); // re-build BEACON frame AsicEnableIbssSync(pAd); // copy BEACON frame to on-chip memory is_my_bssid = TRUE; break; } else if (Bssid[i] < pAd->CommonCfg.Bssid[i]) break; } } NdisGetSystemUpTime(&Now); pBss = &pAd->ScanTab.BssEntry[Bssidx]; pBss->Rssi = RealRssi; // lastest RSSI pBss->LastBeaconRxTime = Now; // last RX timestamp // // BEACON from my BSSID - either IBSS or INFRA network // if (is_my_bssid) { RXWI_STRUC RxWI; pAd->StaCfg.DtimCount = DtimCount; pAd->StaCfg.DtimPeriod = DtimPeriod; pAd->StaCfg.LastBeaconRxTime = Now; RxWI.RSSI0 = Elem->Rssi0; RxWI.RSSI1 = Elem->Rssi1; RxWI.RSSI2 = Elem->Rssi2; Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI); if (AironetCellPowerLimit != 0xFF) { // // We get the Cisco (ccx) "TxPower Limit" required // Changed to appropriate TxPower Limit for Ciso Compatible Extensions // ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); } else { // // AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist. // Used the default TX Power Percentage, that set from UI. // pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; } // at least one 11b peer joined. downgrade the MaxTxRate to 11Mbps // after last 11b peer left for several seconds, we'll auto switch back to 11G rate // in MlmePeriodicExec() if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo))) { BOOLEAN bRestart; BOOLEAN bnRestart; bRestart = FALSE; bnRestart = FALSE; do { if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.MaxTxRate > RATE_11)) { if (pAd->StaCfg.AdhocBOnlyJoined == FALSE) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11b peer joined. down-grade to 11b TX rates \n")); bRestart = TRUE; NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); pAd->StaActive.SupRateLen = SupRateLen; NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES); pAd->StaActive.ExtRateLen = ExtRateLen; pAd->StaCfg.AdhocBOnlyJoined = TRUE; pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; AsicSetEdcaParm(pAd, NULL); } // this timestamp is for MlmePeriodicExec() to check if all 11B peers have left pAd->StaCfg.Last11bBeaconRxTime = Now; break; } #ifdef DOT11_N_SUPPORT // Update Ht Phy. if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) { if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && !pAd->StaCfg.AdhocBGJoined && !pAd->StaCfg.AdhocBOnlyJoined) AdhocTurnOnQos(pAd); // Handle rate switch issue when Adhoc mode if ((SupRateLen+ExtRateLen >= 8) && (HtCapability.MCSSet[0] == 0) && (HtCapability.MCSSet[1] == 0)) { if (pAd->StaCfg.AdhocBGJoined == FALSE) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11g peer joined. down-grade to 11g TX rates \n")); bRestart = TRUE; NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); pAd->StaActive.SupRateLen = SupRateLen; NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES); pAd->StaActive.ExtRateLen = ExtRateLen; pAd->StaCfg.AdhocBGJoined = TRUE; pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; AsicSetEdcaParm(pAd, NULL); } // this timestamp is for MlmePeriodicExec() to check if all 11g peers have left pAd->StaCfg.Last11gBeaconRxTime = Now; break; } else if (!pAd->StaCfg.AdhocBGJoined && !pAd->StaCfg.AdhocBOnlyJoined && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) && (HtCapability.HtCapInfo.ChannelWidth == BW_20)) { if (pAd->StaCfg.Adhoc20NJoined == FALSE) { pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; pAd->StaCfg.Adhoc20NJoined = TRUE; NdisMoveMemory(&pAd->MlmeAux.HtCapability, &HtCapability, SIZE_HT_CAP_IE); if (AddHtInfoLen != 0) NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, AddHtInfoLen); NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16); RTMPCheckHt(pAd, Elem->Wcid, &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo); COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; bRestart = TRUE; bnRestart = TRUE; } // this timestamp is for MlmePeriodicExec() to check if all 20MHz N peers have left pAd->StaCfg.Last20NBeaconRxTime = Now; } } else #endif // DOT11_N_SUPPORT // { RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); } }while (FALSE); // If peer Adhoc is legacy mode, I don't need to call MlmeUpdateHtTxRates no matter I support HT or not if ((bRestart == TRUE) && (bnRestart == FALSE)) { MlmeUpdateTxRates(pAd, FALSE, 0); MakeIbssBeacon(pAd); // re-build BEACON frame AsicEnableIbssSync(pAd); // copy to on-chip memory } #ifdef DOT11_N_SUPPORT else if ((bRestart == TRUE) && (bnRestart == TRUE)) { MlmeUpdateTxRates(pAd, FALSE, BSS0); MlmeUpdateHtTxRates(pAd, BSS0); MakeIbssBeacon(pAd); // re-build BEACON frame AsicEnableIbssSync(pAd); // copy to on-chip memory } #endif // DOT11_N_SUPPORT // // At least another peer in this IBSS, declare MediaState as CONNECTED if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); pAd->IndicateMediaState = NdisMediaStateConnected; RTMP_IndicateMediaState(pAd); pAd->ExtraInfo = GENERAL_LINK_UP; AsicSetBssid(pAd, pAd->CommonCfg.Bssid); // 2003/03/12 - john // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that // "site survey" result should always include the current connected network. // Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); if (Bssidx == BSS_NOT_FOUND) { Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0, &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); } DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n")); } // Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon. // To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station. if (ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID)) { UCHAR idx; MAC_TABLE_ENTRY *pEntry; // look up the existing table pEntry = MacTableLookup(pAd, Addr2); if (pEntry == NULL) { // Another adhoc joining, add to our MAC table. pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE); if (pEntry) { pEntry->Sst = SST_ASSOC; idx = pAd->StaCfg.DefaultKeyId; // After InsertEntry, Write to ASIC on-chip table. RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry); DBGPRINT(RT_DEBUG_TRACE, ("ADHOC %x:%x:%x:%x:%x:%x join in.Entry=%d\n", Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5], pEntry->Aid)); pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word; if (HtCapabilityLen <= 0) { pEntry->HTPhyMode.field.STBC = 0; pEntry->HTPhyMode.field.BW = 0; pEntry->HTPhyMode.field.ShortGI = 0; if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.Channel <= 14)) { pEntry->HTPhyMode.field.MODE = MODE_CCK; } else { pEntry->HTPhyMode.field.MODE = MODE_OFDM; } MlmeUpdateTxRates(pAd, FALSE, 0); } #ifdef DOT11_N_SUPPORT else { MlmeUpdateTxRates(pAd, FALSE, 0); MlmeUpdateHtTxRates(pAd, BSS0); } #endif // DOT11_N_SUPPORT // #ifdef WPA_SUPPLICANT_SUPPORT #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT if (pAd->StaCfg.WpaSupplicantUP) { union iwreq_data wrqu; SendAssocIEsToWpaSupplicant(pAd); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.flags = RT_ASSOC_EVENT_FLAG; wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); } #endif // NATIVE_WPA_SUPPLICANT_SUPPORT // #endif // WPA_SUPPLICANT_SUPPORT // #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT { union iwreq_data wrqu; wext_notify_event_assoc(pAd); memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); } #endif // NATIVE_WPA_SUPPLICANT_SUPPORT // } } } } if (INFRA_ON(pAd)) { BOOLEAN bUseShortSlot, bUseBGProtection; // decide to use/change to - // 1. long slot (20 us) or short slot (9 us) time // 2. turn on/off RTS/CTS and/or CTS-to-self protection // 3. short preamble //bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo); bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo); if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) AsicSetSlotTime(pAd, bUseShortSlot); bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || // always use ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp)); if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP bUseBGProtection = FALSE; if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) { if (bUseBGProtection) { OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); } else { OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); } DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection)); } #ifdef DOT11_N_SUPPORT // check Ht protection mode. and adhere to the Non-GF device indication by AP. if ((AddHtInfoLen != 0) && ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) || (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent))) { pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent; pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode; if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) { AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE); } else AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode)); } #endif // DOT11_N_SUPPORT // if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) && ERP_IS_USE_BARKER_PREAMBLE(Erp)) { MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n")); } if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && (EdcaParm.bValid == TRUE) && (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount)) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n", pAd->CommonCfg.APEdcaParm.EdcaUpdateCount, EdcaParm.EdcaUpdateCount)); AsicSetEdcaParm(pAd, &EdcaParm); } // copy QOS related information NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)); } // only INFRASTRUCTURE mode support power-saving feature if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave)) { UCHAR FreeNumber; // 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL // 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE // 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE // 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE // 5. otherwise, put PHY back to sleep to save battery. if (MessageToMe) { #ifdef RT2860 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); // Turn clk to 80Mhz. } #endif // RT2860 // if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO) { pAd->CommonCfg.bNeedSendTriggerFrame = TRUE; } else RT28XX_PS_POLL_ENQUEUE(pAd); } else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM)) { #ifdef RT2860 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); } #endif // RT2860 // } else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) || (pAd->TxSwQueue[QID_AC_BE].Number != 0) || (pAd->TxSwQueue[QID_AC_VI].Number != 0) || (pAd->TxSwQueue[QID_AC_VO].Number != 0) || (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)) { // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme // can we cheat here (i.e. just check MGMT & AC_BE) for better performance? #ifdef RT2860 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); } #endif // RT2860 // } else { USHORT NextDtim = DtimCount; if (NextDtim == 0) NextDtim = DtimPeriod; TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) TbttNumToNextWakeUp = NextDtim; if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); } } } } // not my BSSID, ignore it } // sanity check fail, ignore this frame } /* ========================================================================== Description: Receive PROBE REQ from remote peer when operating in IBSS mode ========================================================================== */ VOID PeerProbeReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Addr2[MAC_ADDR_LEN]; CHAR Ssid[MAX_LEN_OF_SSID]; UCHAR SsidLen; #ifdef DOT11_N_SUPPORT UCHAR HtLen, AddHtLen, NewExtLen; #endif // DOT11_N_SUPPORT // HEADER_802_11 ProbeRspHdr; NDIS_STATUS NStatus; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0; LARGE_INTEGER FakeTimestamp; UCHAR DsLen = 1, IbssLen = 2; UCHAR LocalErpIe[3] = {IE_ERP, 1, 0}; BOOLEAN Privacy; USHORT CapabilityInfo; UCHAR RSNIe = IE_WPA; if (! ADHOC_ON(pAd)) return; if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen)) { if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) { // allocate and send out ProbeRsp frame NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) return; //pAd->StaCfg.AtimWin = 0; // ?????? Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &ProbeRspHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &CapabilityInfo, 1, &SsidIe, 1, &pAd->CommonCfg.SsidLen, pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, 1, &SupRateIe, 1, &pAd->StaActive.SupRateLen, pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, 1, &IbssIe, 1, &IbssLen, 2, &pAd->StaActive.AtimWin, END_OF_ARGS); if (pAd->StaActive.ExtRateLen) { ULONG tmp; MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 3, LocalErpIe, 1, &ExtRateIe, 1, &pAd->StaActive.ExtRateLen, pAd->StaActive.ExtRateLen, &pAd->StaActive.ExtRate, END_OF_ARGS); FrameLen += tmp; } // If adhoc secruity is set for WPA-None, append the cipher suite IE if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) { ULONG tmp; MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 1, &RSNIe, 1, &pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, END_OF_ARGS); FrameLen += tmp; } #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { ULONG TmpLen; UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; HtLen = sizeof(pAd->CommonCfg.HtCapability); AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); NewExtLen = 1; //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame if (pAd->bBroadComHT == TRUE) { MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 4, &BROADCOM[0], pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, END_OF_ARGS); } else { MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, 1, &AddHtInfoIe, 1, &AddHtLen, sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, 1, &NewExtChanIe, 1, &NewExtLen, sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset, END_OF_ARGS); } FrameLen += TmpLen; } #endif // DOT11_N_SUPPORT // MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } } } VOID BeaconTimeoutAtJoinAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { USHORT Status; DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n")); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_REJ_TIMEOUT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); } /* ========================================================================== Description: Scan timeout procedure. basically add channel index by 1 and rescan ========================================================================== */ VOID ScanTimeoutAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel); // Only one channel scanned for CISCO beacon request if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) || (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) || (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) || (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD)) pAd->MlmeAux.Channel = 0; // this routine will stop if pAd->MlmeAux.Channel == 0 ScanNextChannel(pAd); } /* ========================================================================== Description: ========================================================================== */ VOID InvalidStateWhenScan( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { USHORT Status; DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); } /* ========================================================================== Description: ========================================================================== */ VOID InvalidStateWhenJoin( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { USHORT Status; DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); } /* ========================================================================== Description: ========================================================================== */ VOID InvalidStateWhenStart( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { USHORT Status; DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); } /* ========================================================================== Description: IRQL = DISPATCH_LEVEL ========================================================================== */ VOID EnqueuePsPoll( IN PRTMP_ADAPTER pAd) { #ifdef RALINK_ATE if (ATE_ON(pAd)) { return; } #endif // RALINK_ATE // if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP) pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE; MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); } /* ========================================================================== Description: ========================================================================== */ VOID EnqueueProbeRequest( IN PRTMP_ADAPTER pAd) { NDIS_STATUS NState; PUCHAR pOutBuffer; ULONG FrameLen = 0; HEADER_802_11 Hdr80211; DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); NState = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory if (NState == NDIS_STATUS_SUCCESS) { MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &pAd->CommonCfg.SsidLen, pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, 1, &SupRateIe, 1, &pAd->StaActive.SupRateLen, pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } } #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 VOID BuildEffectedChannelList( IN PRTMP_ADAPTER pAd) { UCHAR EChannel[11]; UCHAR i, j, k; UCHAR UpperChannel = 0, LowerChannel = 0; RTMPZeroMemory(EChannel, 11); i = 0; // Find upper channel and lower channel. if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) { UpperChannel = pAd->CommonCfg.Channel; LowerChannel = pAd->CommonCfg.CentralChannel; } else if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) { UpperChannel = pAd->CommonCfg.CentralChannel; LowerChannel = pAd->CommonCfg.Channel; } else { return; } // Record channels that is below lower channel.. if (LowerChannel > 1) { EChannel[0] = LowerChannel - 1; i = 1; if (LowerChannel > 2) { EChannel[1] = LowerChannel - 2; i = 2; if (LowerChannel > 3) { EChannel[2] = LowerChannel - 3; i = 3; } } } // Record channels that is between lower channel and upper channel. for (k = LowerChannel;k < UpperChannel;k++) { EChannel[i] = k; i++; } // Record channels that is above upper channel.. if (LowerChannel < 11) { EChannel[i] = UpperChannel + 1; i++; if (LowerChannel < 10) { EChannel[i] = LowerChannel + 2; i++; if (LowerChannel < 9) { EChannel[i] = LowerChannel + 3; i++; } } } // for (j = 0;j < i;j++) { for (k = 0;k < pAd->ChannelListNum;k++) { if (pAd->ChannelList[k].Channel == EChannel[j]) { pAd->ChannelList[k].bEffectedChannel = TRUE; DBGPRINT(RT_DEBUG_TRACE,(" EffectedChannel( =%d)\n", EChannel[j])); break; } } } } #endif // DOT11N_DRAFT3 // #endif // DOT11_N_SUPPORT // BOOLEAN ScanRunning( IN PRTMP_ADAPTER pAd) { return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE; }