• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26 
27 	Module Name:
28 	sync.c
29 
30 	Abstract:
31 
32 	Revision History:
33 	Who			When			What
34 	--------	----------		----------------------------------------------
35 	John Chang	2004-09-01      modified for rt2561/2661
36 	Jan Lee		2006-08-01      modified for rt2860 for 802.11n
37 */
38 #include "../rt_config.h"
39 
40 #define ADHOC_ENTRY_BEACON_LOST_TIME	(2*OS_HZ)	// 2 sec
41 
42 /*
43 	==========================================================================
44 	Description:
45 		The sync state machine,
46 	Parameters:
47 		Sm - pointer to the state machine
48 	Note:
49 		the state machine looks like the following
50 
51 	==========================================================================
52  */
SyncStateMachineInit(IN PRTMP_ADAPTER pAd,IN STATE_MACHINE * Sm,OUT STATE_MACHINE_FUNC Trans[])53 VOID SyncStateMachineInit(
54 	IN PRTMP_ADAPTER pAd,
55 	IN STATE_MACHINE *Sm,
56 	OUT STATE_MACHINE_FUNC Trans[])
57 {
58 	StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE);
59 
60 	// column 1
61 	StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction);
62 	StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction);
63 	StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction);
64 	StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon);
65 	StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction);
66 
67 	//column 2
68 	StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
69 	StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
70 	StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
71 	StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction);
72 	StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction);
73 
74 	// column 3
75 	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
76 	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
77 	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
78 	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
79 	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
80 	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction);
81 
82 	// timer init
83 	RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE);
84 	RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE);
85 }
86 
87 /*
88 	==========================================================================
89 	Description:
90 		Beacon timeout handler, executed in timer thread
91 
92 	IRQL = DISPATCH_LEVEL
93 
94 	==========================================================================
95  */
BeaconTimeout(IN PVOID SystemSpecific1,IN PVOID FunctionContext,IN PVOID SystemSpecific2,IN PVOID SystemSpecific3)96 VOID BeaconTimeout(
97 	IN PVOID SystemSpecific1,
98 	IN PVOID FunctionContext,
99 	IN PVOID SystemSpecific2,
100 	IN PVOID SystemSpecific3)
101 {
102 	RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
103 
104 	DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n"));
105 
106 	// Do nothing if the driver is starting halt state.
107 	// This might happen when timer already been fired before cancel timer with mlmehalt
108 	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
109 		return;
110 
111 #ifdef DOT11_N_SUPPORT
112 	if ((pAd->CommonCfg.BBPCurrentBW == BW_40)
113 		)
114 	{
115 		UCHAR        BBPValue = 0;
116 		AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
117 		AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
118 		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
119 		BBPValue &= (~0x18);
120 		BBPValue |= 0x10;
121 		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
122 		DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr));
123 	}
124 #endif // DOT11_N_SUPPORT //
125 
126 	MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL);
127 	RT28XX_MLME_HANDLER(pAd);
128 }
129 
130 /*
131 	==========================================================================
132 	Description:
133 		Scan timeout handler, executed in timer thread
134 
135 	IRQL = DISPATCH_LEVEL
136 
137 	==========================================================================
138  */
ScanTimeout(IN PVOID SystemSpecific1,IN PVOID FunctionContext,IN PVOID SystemSpecific2,IN PVOID SystemSpecific3)139 VOID ScanTimeout(
140 	IN PVOID SystemSpecific1,
141 	IN PVOID FunctionContext,
142 	IN PVOID SystemSpecific2,
143 	IN PVOID SystemSpecific3)
144 {
145 	RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
146 
147 
148 	// Do nothing if the driver is starting halt state.
149 	// This might happen when timer already been fired before cancel timer with mlmehalt
150 	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
151 		return;
152 
153 	if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL))
154 	{
155 		RT28XX_MLME_HANDLER(pAd);
156 	}
157 	else
158 	{
159 		// To prevent SyncMachine.CurrState is SCAN_LISTEN forever.
160 		pAd->MlmeAux.Channel = 0;
161 		ScanNextChannel(pAd);
162 		if (pAd->CommonCfg.bWirelessEvent)
163 		{
164 			RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
165 		}
166 	}
167 }
168 
169 /*
170 	==========================================================================
171 	Description:
172 		MLME SCAN req state machine procedure
173 	==========================================================================
174  */
MlmeScanReqAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)175 VOID MlmeScanReqAction(
176 	IN PRTMP_ADAPTER pAd,
177 	IN MLME_QUEUE_ELEM *Elem)
178 {
179 	UCHAR          Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0;
180 	BOOLEAN        TimerCancelled;
181 	ULONG		   Now;
182 	USHORT         Status;
183 	PHEADER_802_11 pHdr80211;
184 	PUCHAR         pOutBuffer = NULL;
185 	NDIS_STATUS    NStatus;
186 
187 	// Check the total scan tries for one single OID command
188 	// If this is the CCX 2.0 Case, skip that!
189 	if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
190 	{
191 		DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n"));
192 		return;
193 	}
194 
195 	// Increase the scan retry counters.
196 	pAd->StaCfg.ScanCnt++;
197 
198 
199 	// first check the parameter sanity
200 	if (MlmeScanReqSanity(pAd,
201 						  Elem->Msg,
202 						  Elem->MsgLen,
203 						  &BssType,
204 						  Ssid,
205 						  &SsidLen,
206 						  &ScanType))
207 	{
208 
209 		// Check for channel load and noise hist request
210 		// Suspend MSDU only at scan request, not the last two mentioned
211 		if ((ScanType == SCAN_CISCO_NOISE) || (ScanType == SCAN_CISCO_CHANNEL_LOAD))
212 		{
213 			if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
214 				RTMPSuspendMsduTransmission(pAd);			// Suspend MSDU transmission here
215 		}
216 		else
217 		{
218 			// Suspend MSDU transmission here
219 			RTMPSuspendMsduTransmission(pAd);
220 		}
221 
222 		//
223 		// To prevent data lost.
224 		// Send an NULL data with turned PSM bit on to current associated AP before SCAN progress.
225 		// And should send an NULL data with turned PSM bit off to AP, when scan progress done
226 		//
227 		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)))
228 		{
229 			NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);
230 			if (NStatus	== NDIS_STATUS_SUCCESS)
231 			{
232 				pHdr80211 = (PHEADER_802_11) pOutBuffer;
233 				MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
234 				pHdr80211->Duration = 0;
235 				pHdr80211->FC.Type = BTYPE_DATA;
236 				pHdr80211->FC.PwrMgmt = PWR_SAVE;
237 
238 				// Send using priority queue
239 				MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
240 				DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n"));
241 				MlmeFreeMemory(pAd, pOutBuffer);
242 				RTMPusecDelay(5000);
243 			}
244 		}
245 
246 		NdisGetSystemUpTime(&Now);
247 		pAd->StaCfg.LastScanTime = Now;
248 		// reset all the timers
249 		RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
250 		RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
251 
252 		// record desired BSS parameters
253 		pAd->MlmeAux.BssType = BssType;
254 		pAd->MlmeAux.ScanType = ScanType;
255 		pAd->MlmeAux.SsidLen = SsidLen;
256         NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
257 		NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
258 
259 		// start from the first channel
260 		pAd->MlmeAux.Channel = FirstChannel(pAd);
261 
262 		// Change the scan channel when dealing with CCX beacon report
263 		if ((ScanType == SCAN_CISCO_PASSIVE) || (ScanType == SCAN_CISCO_ACTIVE) ||
264 			(ScanType == SCAN_CISCO_CHANNEL_LOAD) || (ScanType == SCAN_CISCO_NOISE))
265 			pAd->MlmeAux.Channel = pAd->StaCfg.CCXScanChannel;
266 
267 		// Let BBP register at 20MHz to do scan
268 		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
269 		BBPValue &= (~0x18);
270 		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
271 		DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
272 		ScanNextChannel(pAd);
273 	}
274 	else
275 	{
276 		DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n"));
277 		pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
278 		Status = MLME_INVALID_FORMAT;
279 		MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
280 	}
281 }
282 
283 /*
284 	==========================================================================
285 	Description:
286 		MLME JOIN req state machine procedure
287 	==========================================================================
288  */
MlmeJoinReqAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)289 VOID MlmeJoinReqAction(
290 	IN PRTMP_ADAPTER pAd,
291 	IN MLME_QUEUE_ELEM *Elem)
292 {
293 	UCHAR        BBPValue = 0;
294 	BSS_ENTRY    *pBss;
295 	BOOLEAN       TimerCancelled;
296 	HEADER_802_11 Hdr80211;
297 	NDIS_STATUS   NStatus;
298 	ULONG         FrameLen = 0;
299 	PUCHAR        pOutBuffer = NULL;
300 	PUCHAR        pSupRate = NULL;
301 	UCHAR         SupRateLen;
302 	PUCHAR        pExtRate = NULL;
303 	UCHAR         ExtRateLen;
304 	UCHAR         ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C};
305 	UCHAR         ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR);
306 	MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg);
307 
308 	DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx));
309 
310 
311 	// reset all the timers
312 	RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
313 	RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
314 
315 	pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx];
316 
317 	// record the desired SSID & BSSID we're waiting for
318 	COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid);
319 
320 	// If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again.
321 	if (pBss->Hidden == 0)
322 	{
323 		NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen);
324 		pAd->MlmeAux.SsidLen = pBss->SsidLen;
325 	}
326 
327 	pAd->MlmeAux.BssType = pBss->BssType;
328 	pAd->MlmeAux.Channel = pBss->Channel;
329 	pAd->MlmeAux.CentralChannel = pBss->CentralChannel;
330 
331 #ifdef EXT_BUILD_CHANNEL_LIST
332 	// Country IE of the AP will be evaluated and will be used.
333 	if ((pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) &&
334 		(pBss->bHasCountryIE == TRUE))
335 	{
336 		NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pBss->CountryString[0], 2);
337 		if (pBss->CountryString[2] == 'I')
338 			pAd->CommonCfg.Geography = IDOR;
339 		else if (pBss->CountryString[2] == 'O')
340 			pAd->CommonCfg.Geography = ODOR;
341 		else
342 			pAd->CommonCfg.Geography = BOTH;
343 		BuildChannelListEx(pAd);
344 	}
345 #endif // EXT_BUILD_CHANNEL_LIST //
346 
347 	// Let BBP register at 20MHz to do scan
348 	RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
349 	BBPValue &= (~0x18);
350 	RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
351 	DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
352 
353 	// switch channel and waiting for beacon timer
354 	AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
355 	AsicLockChannel(pAd, pAd->MlmeAux.Channel);
356 	RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT);
357 
358     do
359 	{
360 		if (((pAd->CommonCfg.bIEEE80211H == 1) &&
361             (pAd->MlmeAux.Channel > 14) &&
362              RadarChannelCheck(pAd, pAd->MlmeAux.Channel))
363 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
364              || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
365 #endif // CARRIER_DETECTION_SUPPORT //
366             )
367 		{
368 			//
369 			// We can't send any Probe request frame to meet 802.11h.
370 			//
371 			if (pBss->Hidden == 0)
372 				break;
373 		}
374 
375 		//
376 		// send probe request
377 		//
378 		NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
379 		if (NStatus == NDIS_STATUS_SUCCESS)
380 		{
381 			if (pAd->MlmeAux.Channel <= 14)
382 			{
383 				pSupRate = pAd->CommonCfg.SupRate;
384 				SupRateLen = pAd->CommonCfg.SupRateLen;
385 				pExtRate = pAd->CommonCfg.ExtRate;
386 				ExtRateLen = pAd->CommonCfg.ExtRateLen;
387 			}
388 			else
389 			{
390 				//
391 				// Overwrite Support Rate, CCK rate are not allowed
392 				//
393 				pSupRate = ASupRate;
394 				SupRateLen = ASupRateLen;
395 				ExtRateLen = 0;
396 			}
397 
398 			if (pAd->MlmeAux.BssType == BSS_INFRA)
399 				MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid);
400 			else
401 				MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
402 
403 			MakeOutgoingFrame(pOutBuffer,               &FrameLen,
404 							  sizeof(HEADER_802_11),    &Hdr80211,
405 							  1,                        &SsidIe,
406 							  1,                        &pAd->MlmeAux.SsidLen,
407 							  pAd->MlmeAux.SsidLen,	    pAd->MlmeAux.Ssid,
408 							  1,                        &SupRateIe,
409 							  1,                        &SupRateLen,
410 							  SupRateLen,               pSupRate,
411 							  END_OF_ARGS);
412 
413 			if (ExtRateLen)
414 			{
415 				ULONG Tmp;
416 				MakeOutgoingFrame(pOutBuffer + FrameLen,            &Tmp,
417 								  1,                                &ExtRateIe,
418 								  1,                                &ExtRateLen,
419 								  ExtRateLen,                       pExtRate,
420 								  END_OF_ARGS);
421 				FrameLen += Tmp;
422 			}
423 
424 
425 			MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
426 			MlmeFreeMemory(pAd, pOutBuffer);
427 		}
428     } while (FALSE);
429 
430 	DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n",
431 		pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
432 
433 	pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON;
434 }
435 
436 /*
437 	==========================================================================
438 	Description:
439 		MLME START Request state machine procedure, starting an IBSS
440 	==========================================================================
441  */
MlmeStartReqAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)442 VOID MlmeStartReqAction(
443 	IN PRTMP_ADAPTER pAd,
444 	IN MLME_QUEUE_ELEM *Elem)
445 {
446 	UCHAR         Ssid[MAX_LEN_OF_SSID], SsidLen;
447 	BOOLEAN       TimerCancelled;
448 
449 	// New for WPA security suites
450 	UCHAR						VarIE[MAX_VIE_LEN]; 	// Total VIE length = MAX_VIE_LEN - -5
451 	NDIS_802_11_VARIABLE_IEs	*pVIE = NULL;
452 	LARGE_INTEGER				TimeStamp;
453 	BOOLEAN Privacy;
454 	USHORT Status;
455 
456 	// Init Variable IE structure
457 	pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
458 	pVIE->Length = 0;
459 	TimeStamp.u.LowPart  = 0;
460 	TimeStamp.u.HighPart = 0;
461 
462 	if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, Ssid, &SsidLen))
463 	{
464 		// reset all the timers
465 		RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
466 		RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
467 
468 		//
469 		// Start a new IBSS. All IBSS parameters are decided now....
470 		//
471 		DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n"));
472 		pAd->MlmeAux.BssType           = BSS_ADHOC;
473 		NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
474 		pAd->MlmeAux.SsidLen           = SsidLen;
475 
476 		// generate a radom number as BSSID
477 		MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid);
478 		DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n"));
479 
480 		Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
481 				  (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
482 				  (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
483 		pAd->MlmeAux.CapabilityInfo    = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0);
484 		pAd->MlmeAux.BeaconPeriod      = pAd->CommonCfg.BeaconPeriod;
485 		pAd->MlmeAux.AtimWin           = pAd->StaCfg.AtimWin;
486 		pAd->MlmeAux.Channel           = pAd->CommonCfg.Channel;
487 
488 		pAd->CommonCfg.CentralChannel  = pAd->CommonCfg.Channel;
489 		pAd->MlmeAux.CentralChannel    = pAd->CommonCfg.CentralChannel;
490 
491 		pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen;
492 		NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
493 		RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
494 		pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen;
495 		NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
496 		RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
497 #ifdef DOT11_N_SUPPORT
498 		if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
499 		{
500 			RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo);
501 			pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE);
502 			// Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here.
503 			DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n"));
504 		}
505 		else
506 #endif // DOT11_N_SUPPORT //
507 		{
508 			pAd->MlmeAux.HtCapabilityLen = 0;
509 			pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
510 		}
511 		// temporarily not support QOS in IBSS
512 		NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
513 		NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
514 		NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
515 
516 		AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
517 		AsicLockChannel(pAd, pAd->MlmeAux.Channel);
518 
519 		DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n",
520 			pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
521 
522 		pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
523 		Status = MLME_SUCCESS;
524 		MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
525 	}
526 	else
527 	{
528 		DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n"));
529 		pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
530 		Status = MLME_INVALID_FORMAT;
531 		MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
532 	}
533 }
534 
535 /*
536 	==========================================================================
537 	Description:
538 		peer sends beacon back when scanning
539 	==========================================================================
540  */
PeerBeaconAtScanAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)541 VOID PeerBeaconAtScanAction(
542 	IN PRTMP_ADAPTER pAd,
543 	IN MLME_QUEUE_ELEM *Elem)
544 {
545 	UCHAR           Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
546 	UCHAR           Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel,
547 					SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe;
548 	CF_PARM         CfParm;
549 	USHORT          BeaconPeriod, AtimWin, CapabilityInfo;
550 	PFRAME_802_11   pFrame;
551 	LARGE_INTEGER   TimeStamp;
552 	UCHAR           Erp;
553 	UCHAR         	SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
554 	UCHAR		  	SupRateLen, ExtRateLen;
555 	USHORT 			LenVIE;
556 	UCHAR			CkipFlag;
557 	UCHAR			AironetCellPowerLimit;
558 	EDCA_PARM       EdcaParm;
559 	QBSS_LOAD_PARM  QbssLoad;
560 	QOS_CAPABILITY_PARM QosCapability;
561 	ULONG						RalinkIe;
562 	UCHAR						VarIE[MAX_VIE_LEN];		// Total VIE length = MAX_VIE_LEN - -5
563 	NDIS_802_11_VARIABLE_IEs	*pVIE = NULL;
564 	HT_CAPABILITY_IE		HtCapability;
565 	ADD_HT_INFO_IE		AddHtInfo;	// AP might use this additional ht info IE
566 	UCHAR			HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
567 	UCHAR			AddHtInfoLen;
568 	UCHAR			NewExtChannelOffset = 0xff;
569 
570 
571 	// NdisFillMemory(Ssid, MAX_LEN_OF_SSID, 0x00);
572 	pFrame = (PFRAME_802_11) Elem->Msg;
573 	// Init Variable IE structure
574 	pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
575 	pVIE->Length = 0;
576 #ifdef DOT11_N_SUPPORT
577     RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
578 	RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
579 #endif // DOT11_N_SUPPORT //
580 
581 	if (PeerBeaconAndProbeRspSanity(pAd,
582 								Elem->Msg,
583 								Elem->MsgLen,
584 								Elem->Channel,
585 								Addr2,
586 								Bssid,
587 								Ssid,
588 								&SsidLen,
589 								&BssType,
590 								&BeaconPeriod,
591 								&Channel,
592 								&NewChannel,
593 								&TimeStamp,
594 								&CfParm,
595 								&AtimWin,
596 								&CapabilityInfo,
597 								&Erp,
598 								&DtimCount,
599 								&DtimPeriod,
600 								&BcastFlag,
601 								&MessageToMe,
602 								SupRate,
603 								&SupRateLen,
604 								ExtRate,
605 								&ExtRateLen,
606 								&CkipFlag,
607 								&AironetCellPowerLimit,
608 								&EdcaParm,
609 								&QbssLoad,
610 								&QosCapability,
611 								&RalinkIe,
612 								&HtCapabilityLen,
613 								&PreNHtCapabilityLen,
614 								&HtCapability,
615 								&AddHtInfoLen,
616 								&AddHtInfo,
617 								&NewExtChannelOffset,
618 								&LenVIE,
619 								pVIE))
620 	{
621 		ULONG Idx;
622 		CHAR Rssi = 0;
623 
624 		Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
625 		if (Idx != BSS_NOT_FOUND)
626 			Rssi = pAd->ScanTab.BssEntry[Idx].Rssi;
627 
628 		Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
629 
630 
631 #ifdef DOT11_N_SUPPORT
632 		if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
633 			HtCapabilityLen = SIZE_HT_CAP_IE;
634 #endif // DOT11_N_SUPPORT //
635 		if ((pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) && (Channel == pAd->StaCfg.CCXScanChannel))
636 		{
637 			Idx = BssTableSetEntry(pAd, &pAd->StaCfg.CCXBssTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
638 						 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen,ExtRate, ExtRateLen, &HtCapability,
639 						 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
640 						 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
641 			if (Idx != BSS_NOT_FOUND)
642 			{
643 				NdisMoveMemory(pAd->StaCfg.CCXBssTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
644 				NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
645 				NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
646 				if (pAd->StaCfg.CCXReqType == MSRN_TYPE_BEACON_REQ)
647 					AironetAddBeaconReport(pAd, Idx, Elem);
648 			}
649 		}
650 		else
651 		{
652 			Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
653 						  &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,  &HtCapability,
654 						 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
655 						 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
656 #ifdef DOT11_N_SUPPORT
657 #ifdef DOT11N_DRAFT3
658 			if (pAd->ChannelList[pAd->CommonCfg.ChannelListIdx].bEffectedChannel == TRUE)
659 			{
660 				UCHAR		RegClass;
661 				PeerBeaconAndProbeRspSanity2(pAd, Elem->Msg, Elem->MsgLen, &RegClass);
662 				TriEventTableSetEntry(pAd, &pAd->CommonCfg.TriggerEventTab, Bssid, &HtCapability, HtCapabilityLen, RegClass, Channel);
663 			}
664 #endif // DOT11N_DRAFT3 //
665 #endif // DOT11_N_SUPPORT //
666 			if (Idx != BSS_NOT_FOUND)
667 			{
668 				NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
669 				NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
670 				NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
671 			}
672 		}
673 	}
674 	// sanity check fail, ignored
675 }
676 
677 /*
678 	==========================================================================
679 	Description:
680 		When waiting joining the (I)BSS, beacon received from external
681 	==========================================================================
682  */
PeerBeaconAtJoinAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)683 VOID PeerBeaconAtJoinAction(
684 	IN PRTMP_ADAPTER pAd,
685 	IN MLME_QUEUE_ELEM *Elem)
686 {
687 	UCHAR         Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
688 	UCHAR         Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe,
689 				  DtimCount, DtimPeriod, BcastFlag, NewChannel;
690 	LARGE_INTEGER TimeStamp;
691 	USHORT        BeaconPeriod, AtimWin, CapabilityInfo;
692 	CF_PARM       Cf;
693 	BOOLEAN       TimerCancelled;
694 	UCHAR         Erp;
695 	UCHAR         SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
696 	UCHAR		  SupRateLen, ExtRateLen;
697 	UCHAR         CkipFlag;
698 	USHORT 		  LenVIE;
699 	UCHAR		  AironetCellPowerLimit;
700 	EDCA_PARM       EdcaParm;
701 	QBSS_LOAD_PARM  QbssLoad;
702 	QOS_CAPABILITY_PARM QosCapability;
703 	USHORT        Status;
704 	UCHAR						VarIE[MAX_VIE_LEN];		// Total VIE length = MAX_VIE_LEN - -5
705 	NDIS_802_11_VARIABLE_IEs	*pVIE = NULL;
706 	ULONG           RalinkIe;
707 	ULONG         Idx;
708 	HT_CAPABILITY_IE		HtCapability;
709 	ADD_HT_INFO_IE		AddHtInfo;	// AP might use this additional ht info IE
710 	UCHAR				HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
711 	UCHAR			AddHtInfoLen;
712 	UCHAR			NewExtChannelOffset = 0xff;
713 #ifdef DOT11_N_SUPPORT
714 	UCHAR			CentralChannel;
715 #endif // DOT11_N_SUPPORT //
716 
717 	// Init Variable IE structure
718 	pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
719 	pVIE->Length = 0;
720     RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
721 	RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
722 
723 
724 	if (PeerBeaconAndProbeRspSanity(pAd,
725 								Elem->Msg,
726 								Elem->MsgLen,
727 								Elem->Channel,
728 								Addr2,
729 								Bssid,
730 								Ssid,
731 								&SsidLen,
732 								&BssType,
733 								&BeaconPeriod,
734 								&Channel,
735 								&NewChannel,
736 								&TimeStamp,
737 								&Cf,
738 								&AtimWin,
739 								&CapabilityInfo,
740 								&Erp,
741 								&DtimCount,
742 								&DtimPeriod,
743 								&BcastFlag,
744 								&MessageToMe,
745 								SupRate,
746 								&SupRateLen,
747 								ExtRate,
748 								&ExtRateLen,
749 								&CkipFlag,
750 								&AironetCellPowerLimit,
751 								&EdcaParm,
752 								&QbssLoad,
753 								&QosCapability,
754 								&RalinkIe,
755 								&HtCapabilityLen,
756 								&PreNHtCapabilityLen,
757 								&HtCapability,
758 								&AddHtInfoLen,
759 								&AddHtInfo,
760 								&NewExtChannelOffset,
761 								&LenVIE,
762 								pVIE))
763 	{
764 		// Disqualify 11b only adhoc when we are in 11g only adhoc mode
765 		if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12))
766 			return;
767 
768 		// BEACON from desired BSS/IBSS found. We should be able to decide most
769 		// BSS parameters here.
770 		// Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION?
771 		//    Do we need to receover back all parameters belonging to previous BSS?
772 		// A. Should be not. There's no back-door recover to previous AP. It still need
773 		//    a new JOIN-AUTH-ASSOC sequence.
774 		if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid))
775 		{
776 			DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel));
777 			RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
778 
779 			// Update RSSI to prevent No signal display when cards first initialized
780 			pAd->StaCfg.RssiSample.LastRssi0	= ConvertToRssi(pAd, Elem->Rssi0, RSSI_0);
781 			pAd->StaCfg.RssiSample.LastRssi1	= ConvertToRssi(pAd, Elem->Rssi1, RSSI_1);
782 			pAd->StaCfg.RssiSample.LastRssi2	= ConvertToRssi(pAd, Elem->Rssi2, RSSI_2);
783 			pAd->StaCfg.RssiSample.AvgRssi0	= pAd->StaCfg.RssiSample.LastRssi0;
784 			pAd->StaCfg.RssiSample.AvgRssi0X8	= pAd->StaCfg.RssiSample.AvgRssi0 << 3;
785 			pAd->StaCfg.RssiSample.AvgRssi1	= pAd->StaCfg.RssiSample.LastRssi1;
786 			pAd->StaCfg.RssiSample.AvgRssi1X8	= pAd->StaCfg.RssiSample.AvgRssi1 << 3;
787 			pAd->StaCfg.RssiSample.AvgRssi2	= pAd->StaCfg.RssiSample.LastRssi2;
788 			pAd->StaCfg.RssiSample.AvgRssi2X8	= pAd->StaCfg.RssiSample.AvgRssi2 << 3;
789 
790 			//
791 			// We need to check if SSID only set to any, then we can record the current SSID.
792 			// Otherwise will cause hidden SSID association failed.
793 			//
794 			if (pAd->MlmeAux.SsidLen == 0)
795 			{
796 				NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
797 				pAd->MlmeAux.SsidLen = SsidLen;
798 			}
799 			else
800 			{
801 				Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel);
802 
803 				if (Idx != BSS_NOT_FOUND)
804 				{
805 					//
806 					// Multiple SSID case, used correct CapabilityInfo
807 					//
808 					CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo;
809 				}
810 			}
811 			NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN);
812 			pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
813 			pAd->MlmeAux.BssType = BssType;
814 			pAd->MlmeAux.BeaconPeriod = BeaconPeriod;
815 			pAd->MlmeAux.Channel = Channel;
816 			pAd->MlmeAux.AtimWin = AtimWin;
817 			pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod;
818 			pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration;
819 			pAd->MlmeAux.APRalinkIe = RalinkIe;
820 
821 			// Copy AP's supported rate to MlmeAux for creating assoication request
822 			// Also filter out not supported rate
823 			pAd->MlmeAux.SupRateLen = SupRateLen;
824 			NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
825 			RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
826 			pAd->MlmeAux.ExtRateLen = ExtRateLen;
827 			NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
828 			RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
829 
830             NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16);
831 #ifdef DOT11_N_SUPPORT
832 			pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
833 			pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen;
834 
835 			// filter out un-supported ht rates
836 			if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
837 			{
838 				RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
839    				RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE);
840 
841 				// StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability
842 				NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16);
843 				pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
844 				pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE;
845 				pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
846 				if (PreNHtCapabilityLen > 0)
847 					pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE;
848 				RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo);
849 				// Copy AP Parameter to StaActive.  This is also in LinkUp.
850 				DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n",
851 					pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth));
852 
853 				if (AddHtInfoLen > 0)
854 				{
855 					CentralChannel = AddHtInfo.ControlChan;
856 		 			// Check again the Bandwidth capability of this AP.
857 		 			if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
858 		 			{
859 		 				CentralChannel = AddHtInfo.ControlChan - 2;
860 		 			}
861 		 			else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
862 		 			{
863 		 				CentralChannel = AddHtInfo.ControlChan + 2;
864 		 			}
865 
866 					// Check Error .
867 					if (pAd->MlmeAux.CentralChannel != CentralChannel)
868 		 				DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel));
869 
870 		 			DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d,  .\n", CentralChannel, AddHtInfo.ControlChan));
871 
872 				}
873 
874 			}
875 			else
876 #endif // DOT11_N_SUPPORT //
877 			{
878    				// To prevent error, let legacy AP must have same CentralChannel and Channel.
879 				if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0))
880 					pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel;
881 
882 				pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
883 				RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
884 				RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE);
885 			}
886 
887 			RTMPUpdateMlmeRate(pAd);
888 
889 			// copy QOS related information
890 			if ((pAd->CommonCfg.bWmmCapable)
891 #ifdef DOT11_N_SUPPORT
892 				 || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
893 #endif // DOT11_N_SUPPORT //
894 				)
895 			{
896 				NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM));
897 				NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
898 				NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
899 			}
900 			else
901 			{
902 				NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
903 				NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
904 				NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
905 			}
906 
907 			DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n",
908 										pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
909 
910 #ifdef LEAP_SUPPORT
911 			// Update CkipFlag
912 			pAd->StaCfg.CkipFlag = CkipFlag;
913 
914 			// Keep TimeStamp for Re-Association used.
915 			if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE))
916 				pAd->StaCfg.CCKMBeaconAtJoinTimeStamp = TimeStamp;
917 #endif // LEAP_SUPPORT //
918 
919 			if (AironetCellPowerLimit != 0xFF)
920 			{
921 				//We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power
922 				ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
923 			}
924 			else  //Used the default TX Power Percentage.
925 				pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
926 
927 			pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
928 			Status = MLME_SUCCESS;
929 			MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
930 		}
931 		// not to me BEACON, ignored
932 	}
933 	// sanity check fail, ignore this frame
934 }
935 
936 /*
937 	==========================================================================
938 	Description:
939 		receive BEACON from peer
940 
941 	IRQL = DISPATCH_LEVEL
942 
943 	==========================================================================
944  */
PeerBeacon(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)945 VOID PeerBeacon(
946 	IN PRTMP_ADAPTER pAd,
947 	IN MLME_QUEUE_ELEM *Elem)
948 {
949 	UCHAR         Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
950 	CHAR          Ssid[MAX_LEN_OF_SSID];
951 	CF_PARM       CfParm;
952 	UCHAR         SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0;
953 	UCHAR         DtimCount=0, DtimPeriod=0, BcastFlag=0;
954 	USHORT        CapabilityInfo, AtimWin, BeaconPeriod;
955 	LARGE_INTEGER TimeStamp;
956 	USHORT        TbttNumToNextWakeUp;
957 	UCHAR         Erp;
958 	UCHAR         SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
959 	UCHAR		  SupRateLen, ExtRateLen;
960 	UCHAR		  CkipFlag;
961 	USHORT        LenVIE;
962 	UCHAR		  AironetCellPowerLimit;
963 	EDCA_PARM       EdcaParm;
964 	QBSS_LOAD_PARM  QbssLoad;
965 	QOS_CAPABILITY_PARM QosCapability;
966 	ULONG           RalinkIe;
967 	// New for WPA security suites
968 	UCHAR						VarIE[MAX_VIE_LEN];		// Total VIE length = MAX_VIE_LEN - -5
969 	NDIS_802_11_VARIABLE_IEs	*pVIE = NULL;
970 	HT_CAPABILITY_IE		HtCapability;
971 	ADD_HT_INFO_IE		AddHtInfo;	// AP might use this additional ht info IE
972 	UCHAR			HtCapabilityLen, PreNHtCapabilityLen;
973 	UCHAR			AddHtInfoLen;
974 	UCHAR			NewExtChannelOffset = 0xff;
975 
976 
977 #ifdef RALINK_ATE
978     if (ATE_ON(pAd))
979     {
980 		return;
981     }
982 #endif // RALINK_ATE //
983 
984 	if (!(INFRA_ON(pAd) || ADHOC_ON(pAd)
985 		))
986 		return;
987 
988 	// Init Variable IE structure
989 	pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
990 	pVIE->Length = 0;
991     RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
992 	RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
993 
994 	if (PeerBeaconAndProbeRspSanity(pAd,
995 								Elem->Msg,
996 								Elem->MsgLen,
997 								Elem->Channel,
998 								Addr2,
999 								Bssid,
1000 								Ssid,
1001 								&SsidLen,
1002 								&BssType,
1003 								&BeaconPeriod,
1004 								&Channel,
1005 								&NewChannel,
1006 								&TimeStamp,
1007 								&CfParm,
1008 								&AtimWin,
1009 								&CapabilityInfo,
1010 								&Erp,
1011 								&DtimCount,
1012 								&DtimPeriod,
1013 								&BcastFlag,
1014 								&MessageToMe,
1015 								SupRate,
1016 								&SupRateLen,
1017 								ExtRate,
1018 								&ExtRateLen,
1019 								&CkipFlag,
1020 								&AironetCellPowerLimit,
1021 								&EdcaParm,
1022 								&QbssLoad,
1023 								&QosCapability,
1024 								&RalinkIe,
1025 								&HtCapabilityLen,
1026 								&PreNHtCapabilityLen,
1027 								&HtCapability,
1028 								&AddHtInfoLen,
1029 								&AddHtInfo,
1030 								&NewExtChannelOffset,
1031 								&LenVIE,
1032 								pVIE))
1033 	{
1034 		BOOLEAN is_my_bssid, is_my_ssid;
1035 		ULONG   Bssidx, Now;
1036 		BSS_ENTRY *pBss;
1037 		CHAR		RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1038 
1039 		is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE;
1040 		is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE;
1041 
1042 
1043 		// ignore BEACON not for my SSID
1044 		if ((! is_my_ssid) && (! is_my_bssid))
1045 			return;
1046 
1047 		// It means STA waits disassoc completely from this AP, ignores this beacon.
1048 		if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC)
1049 			return;
1050 
1051 #ifdef DOT11_N_SUPPORT
1052 		// Copy Control channel for this BSSID.
1053 		if (AddHtInfoLen != 0)
1054 			Channel = AddHtInfo.ControlChan;
1055 
1056 		if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
1057 			HtCapabilityLen = SIZE_HT_CAP_IE;
1058 #endif // DOT11_N_SUPPORT //
1059 
1060 		//
1061 		// Housekeeping "SsidBssTab" table for later-on ROAMing usage.
1062 		//
1063 		Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1064 		if (Bssidx == BSS_NOT_FOUND)
1065 		{
1066 			// discover new AP of this network, create BSS entry
1067 			Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1068 						 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,
1069 						&HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel,
1070 						RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability,
1071 						&QbssLoad, LenVIE, pVIE);
1072 			if (Bssidx == BSS_NOT_FOUND) // return if BSS table full
1073 				return;
1074 
1075 			NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4);
1076 			NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
1077 			NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
1078 
1079 
1080 
1081 		}
1082 
1083 		if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
1084 		{
1085 			// Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
1086 			// In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
1087 			AsicSwitchChannel(pAd, 1, FALSE);
1088 			AsicLockChannel(pAd, 1);
1089 		    LinkDown(pAd, FALSE);
1090 			MlmeQueueInit(&pAd->Mlme.Queue);
1091 			BssTableInit(&pAd->ScanTab);
1092 		    RTMPusecDelay(1000000);		// use delay to prevent STA do reassoc
1093 
1094 			// channel sanity check
1095 			for (index = 0 ; index < pAd->ChannelListNum; index++)
1096 			{
1097 				if (pAd->ChannelList[index].Channel == NewChannel)
1098 				{
1099 					pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
1100 					pAd->CommonCfg.Channel = NewChannel;
1101 					AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1102 					AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1103 					DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
1104 					break;
1105 				}
1106 			}
1107 
1108 			if (index >= pAd->ChannelListNum)
1109 			{
1110 				DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1111 			}
1112 		}
1113 
1114 		// if the ssid matched & bssid unmatched, we should select the bssid with large value.
1115 		// This might happened when two STA start at the same time
1116 		if ((! is_my_bssid) && ADHOC_ON(pAd))
1117 		{
1118 			INT	i;
1119 
1120 			// Add the safeguard against the mismatch of adhoc wep status
1121 			if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus)
1122 			{
1123 				return;
1124 			}
1125 
1126 			// collapse into the ADHOC network which has bigger BSSID value.
1127 			for (i = 0; i < 6; i++)
1128 			{
1129 				if (Bssid[i] > pAd->CommonCfg.Bssid[i])
1130 				{
1131 					DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n",
1132 						Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
1133 					AsicDisableSync(pAd);
1134 					COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid);
1135 					AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1136 					MakeIbssBeacon(pAd);        // re-build BEACON frame
1137 					AsicEnableIbssSync(pAd);    // copy BEACON frame to on-chip memory
1138 					is_my_bssid = TRUE;
1139 					break;
1140 				}
1141 				else if (Bssid[i] < pAd->CommonCfg.Bssid[i])
1142 					break;
1143 			}
1144 		}
1145 
1146 
1147 		NdisGetSystemUpTime(&Now);
1148 		pBss = &pAd->ScanTab.BssEntry[Bssidx];
1149 		pBss->Rssi = RealRssi;       // lastest RSSI
1150 		pBss->LastBeaconRxTime = Now;   // last RX timestamp
1151 
1152 		//
1153 		// BEACON from my BSSID - either IBSS or INFRA network
1154 		//
1155 		if (is_my_bssid)
1156 		{
1157 			RXWI_STRUC	RxWI;
1158 
1159 			pAd->StaCfg.DtimCount = DtimCount;
1160 			pAd->StaCfg.DtimPeriod = DtimPeriod;
1161 			pAd->StaCfg.LastBeaconRxTime = Now;
1162 
1163 
1164 			RxWI.RSSI0 = Elem->Rssi0;
1165 			RxWI.RSSI1 = Elem->Rssi1;
1166 			RxWI.RSSI2 = Elem->Rssi2;
1167 
1168 			Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI);
1169 			if (AironetCellPowerLimit != 0xFF)
1170 			{
1171 				//
1172 				// We get the Cisco (ccx) "TxPower Limit" required
1173 				// Changed to appropriate TxPower Limit for Ciso Compatible Extensions
1174 				//
1175 				ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
1176 			}
1177 			else
1178 			{
1179 				//
1180 				// AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist.
1181 				// Used the default TX Power Percentage, that set from UI.
1182 				//
1183 				pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
1184 			}
1185 
1186 			if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo)))
1187 			{
1188 				UCHAR			MaxSupportedRateIn500Kbps = 0;
1189 				UCHAR			idx;
1190 				MAC_TABLE_ENTRY *pEntry;
1191 
1192 				// supported rates array may not be sorted. sort it and find the maximum rate
1193 			    for (idx=0; idx<SupRateLen; idx++)
1194 			    {
1195 			        if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f))
1196 			            MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f;
1197 			    }
1198 
1199 				for (idx=0; idx<ExtRateLen; idx++)
1200 			    {
1201 			        if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f))
1202 			            MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f;
1203 			    }
1204 
1205 				// look up the existing table
1206 				pEntry = MacTableLookup(pAd, Addr2);
1207 
1208 				// Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon.
1209 				// To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station.
1210 				if ((ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID)) ||
1211 					(pEntry && ((pEntry->LastBeaconRxTime + ADHOC_ENTRY_BEACON_LOST_TIME) < Now)))
1212 				{
1213 					if (pEntry == NULL)
1214 						// Another adhoc joining, add to our MAC table.
1215 						pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE);
1216 
1217 					if (StaAddMacTableEntry(pAd, pEntry, MaxSupportedRateIn500Kbps, &HtCapability, HtCapabilityLen, CapabilityInfo) == FALSE)
1218 					{
1219 						DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n"));
1220 						return;
1221 					}
1222 
1223 					if (pEntry &&
1224 						(Elem->Wcid == RESERVED_WCID))
1225 					{
1226 						idx = pAd->StaCfg.DefaultKeyId;
1227 						RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry);
1228 					}
1229 				}
1230 
1231 				if (pEntry && pEntry->ValidAsCLI)
1232 					pEntry->LastBeaconRxTime = Now;
1233 
1234 				// At least another peer in this IBSS, declare MediaState as CONNECTED
1235 				if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1236 				{
1237 					OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1238 
1239 					pAd->IndicateMediaState = NdisMediaStateConnected;
1240 					RTMP_IndicateMediaState(pAd);
1241 	                pAd->ExtraInfo = GENERAL_LINK_UP;
1242 					AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1243 
1244 					// 2003/03/12 - john
1245 					// Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that
1246 					// "site survey" result should always include the current connected network.
1247 					//
1248 					Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1249 					if (Bssidx == BSS_NOT_FOUND)
1250 					{
1251 						Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1252 									&CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
1253 									&AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0,
1254 									&EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
1255 					}
1256 					DBGPRINT(RT_DEBUG_TRACE, ("ADHOC  fOP_STATUS_MEDIA_STATE_CONNECTED.\n"));
1257 				}
1258 			}
1259 
1260 			if (INFRA_ON(pAd))
1261 			{
1262 				BOOLEAN bUseShortSlot, bUseBGProtection;
1263 
1264 				// decide to use/change to -
1265 				//      1. long slot (20 us) or short slot (9 us) time
1266 				//      2. turn on/off RTS/CTS and/or CTS-to-self protection
1267 				//      3. short preamble
1268 
1269 				//bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo);
1270 				bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo);
1271 				if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))
1272 					AsicSetSlotTime(pAd, bUseShortSlot);
1273 
1274 				bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) ||    // always use
1275 								   ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp));
1276 
1277 				if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP
1278 					bUseBGProtection = FALSE;
1279 
1280 				if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
1281 				{
1282 					if (bUseBGProtection)
1283 					{
1284 						OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1285 						AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1286 					}
1287 					else
1288 					{
1289 						OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1290 						AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1291 					}
1292 
1293 					DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection));
1294 				}
1295 
1296 #ifdef DOT11_N_SUPPORT
1297 				// check Ht protection mode. and adhere to the Non-GF device indication by AP.
1298 				if ((AddHtInfoLen != 0) &&
1299 					((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) ||
1300 					(AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent)))
1301 				{
1302 					pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent;
1303 					pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode;
1304 					if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)
1305 				{
1306 						AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE);
1307 					}
1308 					else
1309 						AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1310 
1311 					DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode));
1312 				}
1313 #endif // DOT11_N_SUPPORT //
1314 
1315 				if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) &&
1316 					ERP_IS_USE_BARKER_PREAMBLE(Erp))
1317 				{
1318 					MlmeSetTxPreamble(pAd, Rt802_11PreambleLong);
1319 					DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n"));
1320 				}
1321 
1322 				if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)    &&
1323 					(EdcaParm.bValid == TRUE)                          &&
1324 					(EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount))
1325 				{
1326 					DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n",
1327 						pAd->CommonCfg.APEdcaParm.EdcaUpdateCount,
1328 						EdcaParm.EdcaUpdateCount));
1329 					AsicSetEdcaParm(pAd, &EdcaParm);
1330 				}
1331 
1332 				// copy QOS related information
1333 				NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
1334 				NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
1335 			}
1336 
1337 			// only INFRASTRUCTURE mode support power-saving feature
1338 			if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave))
1339 			{
1340 				UCHAR FreeNumber;
1341 				//  1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL
1342 				//  2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE
1343 				//  3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE
1344 				//  4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE
1345 				//  5. otherwise, put PHY back to sleep to save battery.
1346 				if (MessageToMe)
1347 				{
1348 					if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable &&
1349 						pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO)
1350 					{
1351 						pAd->CommonCfg.bNeedSendTriggerFrame = TRUE;
1352 					}
1353 					else
1354 						RT28XX_PS_POLL_ENQUEUE(pAd);
1355 				}
1356 				else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM))
1357 				{
1358 				}
1359 				else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0)													||
1360 						(pAd->TxSwQueue[QID_AC_BE].Number != 0)														||
1361 						(pAd->TxSwQueue[QID_AC_VI].Number != 0)														||
1362 						(pAd->TxSwQueue[QID_AC_VO].Number != 0)														||
1363 						(RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)	||
1364 						(RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)	||
1365 						(RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)	||
1366 						(RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)	||
1367 						(RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS))
1368 				{
1369 					// TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme
1370 					// can we cheat here (i.e. just check MGMT & AC_BE) for better performance?
1371 				}
1372 				else
1373 				{
1374 					USHORT NextDtim = DtimCount;
1375 
1376 					if (NextDtim == 0)
1377 						NextDtim = DtimPeriod;
1378 
1379 					TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
1380 					if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
1381 						TbttNumToNextWakeUp = NextDtim;
1382 
1383 					if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1384 					{
1385 						AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
1386 					}
1387 				}
1388 			}
1389 		}
1390 		// not my BSSID, ignore it
1391 	}
1392 	// sanity check fail, ignore this frame
1393 }
1394 
1395 /*
1396 	==========================================================================
1397 	Description:
1398 		Receive PROBE REQ from remote peer when operating in IBSS mode
1399 	==========================================================================
1400  */
PeerProbeReqAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1401 VOID PeerProbeReqAction(
1402 	IN PRTMP_ADAPTER pAd,
1403 	IN MLME_QUEUE_ELEM *Elem)
1404 {
1405 	UCHAR         Addr2[MAC_ADDR_LEN];
1406 	CHAR          Ssid[MAX_LEN_OF_SSID];
1407 	UCHAR         SsidLen;
1408 #ifdef DOT11_N_SUPPORT
1409 	UCHAR		  HtLen, AddHtLen, NewExtLen;
1410 #endif // DOT11_N_SUPPORT //
1411 	HEADER_802_11 ProbeRspHdr;
1412 	NDIS_STATUS   NStatus;
1413 	PUCHAR        pOutBuffer = NULL;
1414 	ULONG         FrameLen = 0;
1415 	LARGE_INTEGER FakeTimestamp;
1416 	UCHAR         DsLen = 1, IbssLen = 2;
1417 	UCHAR         LocalErpIe[3] = {IE_ERP, 1, 0};
1418 	BOOLEAN       Privacy;
1419 	USHORT        CapabilityInfo;
1420 	UCHAR		  RSNIe = IE_WPA;
1421 
1422 	if (! ADHOC_ON(pAd))
1423 		return;
1424 
1425 	if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen))
1426 	{
1427 		if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1428 		{
1429 			// allocate and send out ProbeRsp frame
1430 			NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
1431 			if (NStatus != NDIS_STATUS_SUCCESS)
1432 				return;
1433 
1434 			//pAd->StaCfg.AtimWin = 0;  // ??????
1435 
1436 			Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
1437 					  (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
1438 					  (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
1439 			CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0);
1440 
1441 			MakeOutgoingFrame(pOutBuffer,                   &FrameLen,
1442 							  sizeof(HEADER_802_11),        &ProbeRspHdr,
1443 							  TIMESTAMP_LEN,                &FakeTimestamp,
1444 							  2,                            &pAd->CommonCfg.BeaconPeriod,
1445 							  2,                            &CapabilityInfo,
1446 							  1,                            &SsidIe,
1447 							  1,                            &pAd->CommonCfg.SsidLen,
1448 							  pAd->CommonCfg.SsidLen,       pAd->CommonCfg.Ssid,
1449 							  1,                            &SupRateIe,
1450 							  1,                            &pAd->StaActive.SupRateLen,
1451 							  pAd->StaActive.SupRateLen,    pAd->StaActive.SupRate,
1452 							  1,                            &DsIe,
1453 							  1,                            &DsLen,
1454 							  1,                            &pAd->CommonCfg.Channel,
1455 							  1,                            &IbssIe,
1456 							  1,                            &IbssLen,
1457 							  2,                            &pAd->StaActive.AtimWin,
1458 							  END_OF_ARGS);
1459 
1460 			if (pAd->StaActive.ExtRateLen)
1461 			{
1462 				ULONG tmp;
1463 				MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
1464 								  3,                            LocalErpIe,
1465 								  1,                            &ExtRateIe,
1466 								  1,                            &pAd->StaActive.ExtRateLen,
1467 								  pAd->StaActive.ExtRateLen,    &pAd->StaActive.ExtRate,
1468 								  END_OF_ARGS);
1469 				FrameLen += tmp;
1470 			}
1471 
1472 			// If adhoc secruity is set for WPA-None, append the cipher suite IE
1473 			if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
1474 			{
1475 				ULONG tmp;
1476 				MakeOutgoingFrame(pOutBuffer + FrameLen,        	&tmp,
1477 						  			1,                              &RSNIe,
1478 						  			1,                            	&pAd->StaCfg.RSNIE_Len,
1479 						  			pAd->StaCfg.RSNIE_Len,      	pAd->StaCfg.RSN_IE,
1480 						  			END_OF_ARGS);
1481 				FrameLen += tmp;
1482 			}
1483 #ifdef DOT11_N_SUPPORT
1484 			if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1485 			{
1486 				ULONG TmpLen;
1487 				UCHAR	BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
1488 				HtLen = sizeof(pAd->CommonCfg.HtCapability);
1489 				AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo);
1490 				NewExtLen = 1;
1491 				//New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame
1492 				if (pAd->bBroadComHT == TRUE)
1493 				{
1494 					MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
1495 								  1,                                &WpaIe,
1496 								  4,                                &BROADCOM[0],
1497 								 pAd->MlmeAux.HtCapabilityLen,          &pAd->MlmeAux.HtCapability,
1498 								  END_OF_ARGS);
1499 				}
1500 				else
1501 				{
1502 				MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
1503 								  1,                                &HtCapIe,
1504 								  1,                                &HtLen,
1505 								 sizeof(HT_CAPABILITY_IE),          &pAd->CommonCfg.HtCapability,
1506 								  1,                                &AddHtInfoIe,
1507 								  1,                                &AddHtLen,
1508 								 sizeof(ADD_HT_INFO_IE),          &pAd->CommonCfg.AddHTInfo,
1509 								  1,                                &NewExtChanIe,
1510 								  1,                                &NewExtLen,
1511 								 sizeof(NEW_EXT_CHAN_IE),          &pAd->CommonCfg.NewExtChanOffset,
1512 								  END_OF_ARGS);
1513 				}
1514 				FrameLen += TmpLen;
1515 			}
1516 #endif // DOT11_N_SUPPORT //
1517 			MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1518 			MlmeFreeMemory(pAd, pOutBuffer);
1519 		}
1520 	}
1521 }
1522 
BeaconTimeoutAtJoinAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1523 VOID BeaconTimeoutAtJoinAction(
1524 	IN PRTMP_ADAPTER pAd,
1525 	IN MLME_QUEUE_ELEM *Elem)
1526 {
1527 	USHORT Status;
1528 	DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n"));
1529 	pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1530 	Status = MLME_REJ_TIMEOUT;
1531 	MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1532 }
1533 
1534 /*
1535 	==========================================================================
1536 	Description:
1537 		Scan timeout procedure. basically add channel index by 1 and rescan
1538 	==========================================================================
1539  */
ScanTimeoutAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1540 VOID ScanTimeoutAction(
1541 	IN PRTMP_ADAPTER pAd,
1542 	IN MLME_QUEUE_ELEM *Elem)
1543 {
1544 	pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel);
1545 
1546 	// Only one channel scanned for CISCO beacon request
1547 	if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) ||
1548 		(pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) ||
1549 		(pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) ||
1550 		(pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD))
1551 		pAd->MlmeAux.Channel = 0;
1552 
1553 	// this routine will stop if pAd->MlmeAux.Channel == 0
1554 	ScanNextChannel(pAd);
1555 }
1556 
1557 /*
1558 	==========================================================================
1559 	Description:
1560 	==========================================================================
1561  */
InvalidStateWhenScan(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1562 VOID InvalidStateWhenScan(
1563 	IN PRTMP_ADAPTER pAd,
1564 	IN MLME_QUEUE_ELEM *Elem)
1565 {
1566 	USHORT Status;
1567 	DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1568 	pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1569 	Status = MLME_STATE_MACHINE_REJECT;
1570 	MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
1571 }
1572 
1573 /*
1574 	==========================================================================
1575 	Description:
1576 	==========================================================================
1577  */
InvalidStateWhenJoin(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1578 VOID InvalidStateWhenJoin(
1579 	IN PRTMP_ADAPTER pAd,
1580 	IN MLME_QUEUE_ELEM *Elem)
1581 {
1582 	USHORT Status;
1583 	DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1584 	pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1585 	Status = MLME_STATE_MACHINE_REJECT;
1586 	MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1587 }
1588 
1589 /*
1590 	==========================================================================
1591 	Description:
1592 	==========================================================================
1593  */
InvalidStateWhenStart(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1594 VOID InvalidStateWhenStart(
1595 	IN PRTMP_ADAPTER pAd,
1596 	IN MLME_QUEUE_ELEM *Elem)
1597 {
1598 	USHORT Status;
1599 	DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1600 	pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1601 	Status = MLME_STATE_MACHINE_REJECT;
1602 	MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
1603 }
1604 
1605 /*
1606 	==========================================================================
1607 	Description:
1608 
1609 	IRQL = DISPATCH_LEVEL
1610 
1611 	==========================================================================
1612  */
EnqueuePsPoll(IN PRTMP_ADAPTER pAd)1613 VOID EnqueuePsPoll(
1614 	IN PRTMP_ADAPTER pAd)
1615 {
1616 #ifdef RALINK_ATE
1617     if (ATE_ON(pAd))
1618     {
1619 		return;
1620     }
1621 #endif // RALINK_ATE //
1622 
1623 
1624 	if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP)
1625     	pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE;
1626 	MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
1627 }
1628 
1629 
1630 /*
1631 	==========================================================================
1632 	Description:
1633 	==========================================================================
1634  */
EnqueueProbeRequest(IN PRTMP_ADAPTER pAd)1635 VOID EnqueueProbeRequest(
1636 	IN PRTMP_ADAPTER pAd)
1637 {
1638 	NDIS_STATUS     NState;
1639 	PUCHAR          pOutBuffer;
1640 	ULONG           FrameLen = 0;
1641 	HEADER_802_11   Hdr80211;
1642 
1643 	DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n"));
1644 
1645 	NState = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
1646 	if (NState == NDIS_STATUS_SUCCESS)
1647 	{
1648 		MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
1649 
1650 		// this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse
1651 		MakeOutgoingFrame(pOutBuffer,                     &FrameLen,
1652 						  sizeof(HEADER_802_11),          &Hdr80211,
1653 						  1,                              &SsidIe,
1654 						  1,                              &pAd->CommonCfg.SsidLen,
1655 						  pAd->CommonCfg.SsidLen,		  pAd->CommonCfg.Ssid,
1656 						  1,                              &SupRateIe,
1657 						  1,                              &pAd->StaActive.SupRateLen,
1658 						  pAd->StaActive.SupRateLen,      pAd->StaActive.SupRate,
1659 						  END_OF_ARGS);
1660 		MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1661 		MlmeFreeMemory(pAd, pOutBuffer);
1662 	}
1663 
1664 }
1665 
1666 #ifdef DOT11_N_SUPPORT
1667 #ifdef DOT11N_DRAFT3
BuildEffectedChannelList(IN PRTMP_ADAPTER pAd)1668 VOID BuildEffectedChannelList(
1669 	IN PRTMP_ADAPTER pAd)
1670 {
1671 	UCHAR		EChannel[11];
1672 	UCHAR		i, j, k;
1673 	UCHAR		UpperChannel = 0, LowerChannel = 0;
1674 
1675 	RTMPZeroMemory(EChannel, 11);
1676 	i = 0;
1677 	// Find upper channel and lower channel.
1678 	if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
1679 	{
1680 		UpperChannel = pAd->CommonCfg.Channel;
1681 		LowerChannel = pAd->CommonCfg.CentralChannel;
1682 	}
1683 	else if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
1684 	{
1685 		UpperChannel = pAd->CommonCfg.CentralChannel;
1686 		LowerChannel = pAd->CommonCfg.Channel;
1687 	}
1688 	else
1689 	{
1690 		return;
1691 	}
1692 
1693 	// Record channels that is below lower channel..
1694 	if (LowerChannel > 1)
1695 	{
1696 		EChannel[0] = LowerChannel - 1;
1697 		i = 1;
1698 		if (LowerChannel > 2)
1699 		{
1700 			EChannel[1] = LowerChannel - 2;
1701 			i = 2;
1702 			if (LowerChannel > 3)
1703 			{
1704 				EChannel[2] = LowerChannel - 3;
1705 				i = 3;
1706 			}
1707 		}
1708 	}
1709 	// Record channels that is between  lower channel and upper channel.
1710 	for (k = LowerChannel;k < UpperChannel;k++)
1711 	{
1712 		EChannel[i] = k;
1713 		i++;
1714 	}
1715 	// Record channels that is above upper channel..
1716 	if (LowerChannel < 11)
1717 	{
1718 		EChannel[i] = UpperChannel + 1;
1719 		i++;
1720 		if (LowerChannel < 10)
1721 		{
1722 			EChannel[i] = LowerChannel + 2;
1723 			i++;
1724 			if (LowerChannel < 9)
1725 			{
1726 				EChannel[i] = LowerChannel + 3;
1727 				i++;
1728 			}
1729 		}
1730 	}
1731 	//
1732 	for (j = 0;j < i;j++)
1733 	{
1734 		for (k = 0;k < pAd->ChannelListNum;k++)
1735 		{
1736 			if (pAd->ChannelList[k].Channel == EChannel[j])
1737 			{
1738 				pAd->ChannelList[k].bEffectedChannel = TRUE;
1739 				DBGPRINT(RT_DEBUG_TRACE,(" EffectedChannel( =%d)\n", EChannel[j]));
1740 				break;
1741 			}
1742 		}
1743 	}
1744 }
1745 #endif // DOT11N_DRAFT3 //
1746 #endif // DOT11_N_SUPPORT //
1747 
ScanRunning(IN PRTMP_ADAPTER pAd)1748 BOOLEAN ScanRunning(
1749 		IN PRTMP_ADAPTER pAd)
1750 {
1751 	return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE;
1752 }
1753 
1754