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