bdc0a1739f
Removed the CFLAG RT2860 from Makefile and dependency on it in the driver code. Signed-off-by: Mark Einon <mark.einon@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
1952 lines
68 KiB
C
1952 lines
68 KiB
C
/*
|
|
*************************************************************************
|
|
* 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++;
|
|
|
|
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);
|
|
}
|
|
|
|
// 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));
|
|
|
|
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);
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
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);
|
|
}
|
|
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))
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
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?
|
|
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);
|
|
}
|
|
}
|
|
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))
|
|
{
|
|
// Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode.
|
|
RTMP_SET_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
|
|
pAd->ThisTbttNumToNextWakeUp = TbttNumToNextWakeUp;
|
|
//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;
|
|
}
|
|
|