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