Staging: rt2860: remove NATIVE_WPA_SUPPLICANT_SUPPORT ifdefs
[linux-2.6.git] / drivers / staging / rt2860 / sta / sync.c
blobfe80bb1a94f70bab93dc7c738608393b3bd02bbf
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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 *************************************************************************
27 Module Name:
28 sync.c
30 Abstract:
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
38 #include "../rt_config.h"
40 #define AC0_DEF_TXOP 0
41 #define AC1_DEF_TXOP 0
42 #define AC2_DEF_TXOP 94
43 #define AC3_DEF_TXOP 47
45 VOID AdhocTurnOnQos(
46 IN PRTMP_ADAPTER pAd)
48 // Turn on QOs if use HT rate.
49 if (pAd->CommonCfg.APEdcaParm.bValid == FALSE)
51 pAd->CommonCfg.APEdcaParm.bValid = TRUE;
52 pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3;
53 pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7;
54 pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1;
55 pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1;
57 pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4;
58 pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4;
59 pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3;
60 pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2;
62 pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10;
63 pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6;
64 pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4;
65 pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3;
67 pAd->CommonCfg.APEdcaParm.Txop[0] = 0;
68 pAd->CommonCfg.APEdcaParm.Txop[1] = 0;
69 pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP;
70 pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP;
72 AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
76 ==========================================================================
77 Description:
78 The sync state machine,
79 Parameters:
80 Sm - pointer to the state machine
81 Note:
82 the state machine looks like the following
84 ==========================================================================
86 VOID SyncStateMachineInit(
87 IN PRTMP_ADAPTER pAd,
88 IN STATE_MACHINE *Sm,
89 OUT STATE_MACHINE_FUNC Trans[])
91 StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE);
93 // column 1
94 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction);
95 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction);
96 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction);
97 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon);
98 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction);
100 //column 2
101 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
102 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
103 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
104 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction);
105 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction);
107 // column 3
108 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
109 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
110 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
111 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
112 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
113 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction);
115 // timer init
116 RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE);
117 RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE);
121 ==========================================================================
122 Description:
123 Beacon timeout handler, executed in timer thread
125 IRQL = DISPATCH_LEVEL
127 ==========================================================================
129 VOID BeaconTimeout(
130 IN PVOID SystemSpecific1,
131 IN PVOID FunctionContext,
132 IN PVOID SystemSpecific2,
133 IN PVOID SystemSpecific3)
135 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
137 DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n"));
139 // Do nothing if the driver is starting halt state.
140 // This might happen when timer already been fired before cancel timer with mlmehalt
141 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
142 return;
144 #ifdef DOT11_N_SUPPORT
145 if ((pAd->CommonCfg.BBPCurrentBW == BW_40)
148 UCHAR BBPValue = 0;
149 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
150 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
151 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
152 BBPValue &= (~0x18);
153 BBPValue |= 0x10;
154 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
155 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr));
157 #endif // DOT11_N_SUPPORT //
159 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL);
160 RT28XX_MLME_HANDLER(pAd);
164 ==========================================================================
165 Description:
166 Scan timeout handler, executed in timer thread
168 IRQL = DISPATCH_LEVEL
170 ==========================================================================
172 VOID ScanTimeout(
173 IN PVOID SystemSpecific1,
174 IN PVOID FunctionContext,
175 IN PVOID SystemSpecific2,
176 IN PVOID SystemSpecific3)
178 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
181 // Do nothing if the driver is starting halt state.
182 // This might happen when timer already been fired before cancel timer with mlmehalt
183 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
184 return;
186 if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL))
188 RT28XX_MLME_HANDLER(pAd);
190 else
192 // To prevent SyncMachine.CurrState is SCAN_LISTEN forever.
193 pAd->MlmeAux.Channel = 0;
194 ScanNextChannel(pAd);
195 if (pAd->CommonCfg.bWirelessEvent)
197 RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
203 ==========================================================================
204 Description:
205 MLME SCAN req state machine procedure
206 ==========================================================================
208 VOID MlmeScanReqAction(
209 IN PRTMP_ADAPTER pAd,
210 IN MLME_QUEUE_ELEM *Elem)
212 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0;
213 BOOLEAN TimerCancelled;
214 ULONG Now;
215 USHORT Status;
216 PHEADER_802_11 pHdr80211;
217 PUCHAR pOutBuffer = NULL;
218 NDIS_STATUS NStatus;
220 // Check the total scan tries for one single OID command
221 // If this is the CCX 2.0 Case, skip that!
222 if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
224 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n"));
225 return;
228 // Increase the scan retry counters.
229 pAd->StaCfg.ScanCnt++;
231 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
232 (IDLE_ON(pAd)) &&
233 (pAd->StaCfg.bRadio == TRUE) &&
234 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
236 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
239 // first check the parameter sanity
240 if (MlmeScanReqSanity(pAd,
241 Elem->Msg,
242 Elem->MsgLen,
243 &BssType,
244 Ssid,
245 &SsidLen,
246 &ScanType))
249 // Check for channel load and noise hist request
250 // Suspend MSDU only at scan request, not the last two mentioned
251 if ((ScanType == SCAN_CISCO_NOISE) || (ScanType == SCAN_CISCO_CHANNEL_LOAD))
253 if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
254 RTMPSuspendMsduTransmission(pAd); // Suspend MSDU transmission here
256 else
258 // Suspend MSDU transmission here
259 RTMPSuspendMsduTransmission(pAd);
263 // To prevent data lost.
264 // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress.
265 // And should send an NULL data with turned PSM bit off to AP, when scan progress done
267 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)))
269 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);
270 if (NStatus == NDIS_STATUS_SUCCESS)
272 pHdr80211 = (PHEADER_802_11) pOutBuffer;
273 MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
274 pHdr80211->Duration = 0;
275 pHdr80211->FC.Type = BTYPE_DATA;
276 pHdr80211->FC.PwrMgmt = PWR_SAVE;
278 // Send using priority queue
279 MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
280 DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n"));
281 MlmeFreeMemory(pAd, pOutBuffer);
282 RTMPusecDelay(5000);
286 NdisGetSystemUpTime(&Now);
287 pAd->StaCfg.LastScanTime = Now;
288 // reset all the timers
289 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
290 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
292 // record desired BSS parameters
293 pAd->MlmeAux.BssType = BssType;
294 pAd->MlmeAux.ScanType = ScanType;
295 pAd->MlmeAux.SsidLen = SsidLen;
296 NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
297 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
299 // start from the first channel
300 pAd->MlmeAux.Channel = FirstChannel(pAd);
302 // Change the scan channel when dealing with CCX beacon report
303 if ((ScanType == SCAN_CISCO_PASSIVE) || (ScanType == SCAN_CISCO_ACTIVE) ||
304 (ScanType == SCAN_CISCO_CHANNEL_LOAD) || (ScanType == SCAN_CISCO_NOISE))
305 pAd->MlmeAux.Channel = pAd->StaCfg.CCXScanChannel;
307 // Let BBP register at 20MHz to do scan
308 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
309 BBPValue &= (~0x18);
310 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
311 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
312 ScanNextChannel(pAd);
314 else
316 DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n"));
317 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
318 Status = MLME_INVALID_FORMAT;
319 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
324 ==========================================================================
325 Description:
326 MLME JOIN req state machine procedure
327 ==========================================================================
329 VOID MlmeJoinReqAction(
330 IN PRTMP_ADAPTER pAd,
331 IN MLME_QUEUE_ELEM *Elem)
333 UCHAR BBPValue = 0;
334 BSS_ENTRY *pBss;
335 BOOLEAN TimerCancelled;
336 HEADER_802_11 Hdr80211;
337 NDIS_STATUS NStatus;
338 ULONG FrameLen = 0;
339 PUCHAR pOutBuffer = NULL;
340 PUCHAR pSupRate = NULL;
341 UCHAR SupRateLen;
342 PUCHAR pExtRate = NULL;
343 UCHAR ExtRateLen;
344 UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C};
345 UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR);
346 MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg);
348 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx));
350 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
351 (IDLE_ON(pAd)) &&
352 (pAd->StaCfg.bRadio == TRUE) &&
353 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
355 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
358 // reset all the timers
359 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
360 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
362 pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx];
364 // record the desired SSID & BSSID we're waiting for
365 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid);
367 // If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again.
368 if (pBss->Hidden == 0)
370 NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen);
371 pAd->MlmeAux.SsidLen = pBss->SsidLen;
374 pAd->MlmeAux.BssType = pBss->BssType;
375 pAd->MlmeAux.Channel = pBss->Channel;
376 pAd->MlmeAux.CentralChannel = pBss->CentralChannel;
378 // Let BBP register at 20MHz to do scan
379 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
380 BBPValue &= (~0x18);
381 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
382 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
384 // switch channel and waiting for beacon timer
385 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
386 AsicLockChannel(pAd, pAd->MlmeAux.Channel);
387 RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT);
391 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
392 (pAd->MlmeAux.Channel > 14) &&
393 RadarChannelCheck(pAd, pAd->MlmeAux.Channel))
397 // We can't send any Probe request frame to meet 802.11h.
399 if (pBss->Hidden == 0)
400 break;
404 // send probe request
406 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
407 if (NStatus == NDIS_STATUS_SUCCESS)
409 if (pAd->MlmeAux.Channel <= 14)
411 pSupRate = pAd->CommonCfg.SupRate;
412 SupRateLen = pAd->CommonCfg.SupRateLen;
413 pExtRate = pAd->CommonCfg.ExtRate;
414 ExtRateLen = pAd->CommonCfg.ExtRateLen;
416 else
419 // Overwrite Support Rate, CCK rate are not allowed
421 pSupRate = ASupRate;
422 SupRateLen = ASupRateLen;
423 ExtRateLen = 0;
426 if (pAd->MlmeAux.BssType == BSS_INFRA)
427 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid);
428 else
429 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
431 MakeOutgoingFrame(pOutBuffer, &FrameLen,
432 sizeof(HEADER_802_11), &Hdr80211,
433 1, &SsidIe,
434 1, &pAd->MlmeAux.SsidLen,
435 pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid,
436 1, &SupRateIe,
437 1, &SupRateLen,
438 SupRateLen, pSupRate,
439 END_OF_ARGS);
441 if (ExtRateLen)
443 ULONG Tmp;
444 MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
445 1, &ExtRateIe,
446 1, &ExtRateLen,
447 ExtRateLen, pExtRate,
448 END_OF_ARGS);
449 FrameLen += Tmp;
453 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
454 MlmeFreeMemory(pAd, pOutBuffer);
456 } while (FALSE);
458 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n",
459 pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
461 pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON;
465 ==========================================================================
466 Description:
467 MLME START Request state machine procedure, starting an IBSS
468 ==========================================================================
470 VOID MlmeStartReqAction(
471 IN PRTMP_ADAPTER pAd,
472 IN MLME_QUEUE_ELEM *Elem)
474 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen;
475 BOOLEAN TimerCancelled;
477 // New for WPA security suites
478 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
479 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
480 LARGE_INTEGER TimeStamp;
481 BOOLEAN Privacy;
482 USHORT Status;
484 // Init Variable IE structure
485 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
486 pVIE->Length = 0;
487 TimeStamp.u.LowPart = 0;
488 TimeStamp.u.HighPart = 0;
490 if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, Ssid, &SsidLen))
492 // reset all the timers
493 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
494 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
497 // Start a new IBSS. All IBSS parameters are decided now....
499 DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n"));
500 pAd->MlmeAux.BssType = BSS_ADHOC;
501 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
502 pAd->MlmeAux.SsidLen = SsidLen;
504 // generate a radom number as BSSID
505 MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid);
506 DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n"));
508 Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
509 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
510 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
511 pAd->MlmeAux.CapabilityInfo = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0);
512 pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod;
513 pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin;
514 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
516 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
517 pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel;
519 pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen;
520 NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
521 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
522 pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen;
523 NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
524 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
525 #ifdef DOT11_N_SUPPORT
526 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
528 RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo);
529 pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE);
530 // Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here.
531 DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n"));
533 else
534 #endif // DOT11_N_SUPPORT //
536 pAd->MlmeAux.HtCapabilityLen = 0;
537 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
539 // temporarily not support QOS in IBSS
540 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
541 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
542 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
544 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
545 AsicLockChannel(pAd, pAd->MlmeAux.Channel);
547 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n",
548 pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
550 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
551 Status = MLME_SUCCESS;
552 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
554 else
556 DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n"));
557 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
558 Status = MLME_INVALID_FORMAT;
559 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
564 ==========================================================================
565 Description:
566 peer sends beacon back when scanning
567 ==========================================================================
569 VOID PeerBeaconAtScanAction(
570 IN PRTMP_ADAPTER pAd,
571 IN MLME_QUEUE_ELEM *Elem)
573 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
574 UCHAR Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel,
575 SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe;
576 CF_PARM CfParm;
577 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
578 PFRAME_802_11 pFrame;
579 LARGE_INTEGER TimeStamp;
580 UCHAR Erp;
581 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
582 UCHAR SupRateLen, ExtRateLen;
583 USHORT LenVIE;
584 UCHAR CkipFlag;
585 UCHAR AironetCellPowerLimit;
586 EDCA_PARM EdcaParm;
587 QBSS_LOAD_PARM QbssLoad;
588 QOS_CAPABILITY_PARM QosCapability;
589 ULONG RalinkIe;
590 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
591 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
592 HT_CAPABILITY_IE HtCapability;
593 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
594 UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
595 UCHAR AddHtInfoLen;
596 UCHAR NewExtChannelOffset = 0xff;
598 pFrame = (PFRAME_802_11) Elem->Msg;
599 // Init Variable IE structure
600 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
601 pVIE->Length = 0;
602 #ifdef DOT11_N_SUPPORT
603 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
604 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
605 #endif // DOT11_N_SUPPORT //
607 if (PeerBeaconAndProbeRspSanity(pAd,
608 Elem->Msg,
609 Elem->MsgLen,
610 Elem->Channel,
611 Addr2,
612 Bssid,
613 Ssid,
614 &SsidLen,
615 &BssType,
616 &BeaconPeriod,
617 &Channel,
618 &NewChannel,
619 &TimeStamp,
620 &CfParm,
621 &AtimWin,
622 &CapabilityInfo,
623 &Erp,
624 &DtimCount,
625 &DtimPeriod,
626 &BcastFlag,
627 &MessageToMe,
628 SupRate,
629 &SupRateLen,
630 ExtRate,
631 &ExtRateLen,
632 &CkipFlag,
633 &AironetCellPowerLimit,
634 &EdcaParm,
635 &QbssLoad,
636 &QosCapability,
637 &RalinkIe,
638 &HtCapabilityLen,
639 &PreNHtCapabilityLen,
640 &HtCapability,
641 &AddHtInfoLen,
642 &AddHtInfo,
643 &NewExtChannelOffset,
644 &LenVIE,
645 pVIE))
647 ULONG Idx;
648 CHAR Rssi = 0;
650 Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
651 if (Idx != BSS_NOT_FOUND)
652 Rssi = pAd->ScanTab.BssEntry[Idx].Rssi;
654 Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
657 #ifdef DOT11_N_SUPPORT
658 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
659 HtCapabilityLen = SIZE_HT_CAP_IE;
660 #endif // DOT11_N_SUPPORT //
661 if ((pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) && (Channel == pAd->StaCfg.CCXScanChannel))
663 Idx = BssTableSetEntry(pAd, &pAd->StaCfg.CCXBssTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
664 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen,ExtRate, ExtRateLen, &HtCapability,
665 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
666 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
667 if (Idx != BSS_NOT_FOUND)
669 NdisMoveMemory(pAd->StaCfg.CCXBssTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
670 NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
671 NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
672 if (pAd->StaCfg.CCXReqType == MSRN_TYPE_BEACON_REQ)
673 AironetAddBeaconReport(pAd, Idx, Elem);
676 else
678 Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
679 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
680 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
681 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
683 if (Idx != BSS_NOT_FOUND)
685 NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
686 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
687 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
691 // sanity check fail, ignored
695 ==========================================================================
696 Description:
697 When waiting joining the (I)BSS, beacon received from external
698 ==========================================================================
700 VOID PeerBeaconAtJoinAction(
701 IN PRTMP_ADAPTER pAd,
702 IN MLME_QUEUE_ELEM *Elem)
704 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
705 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe,
706 DtimCount, DtimPeriod, BcastFlag, NewChannel;
707 LARGE_INTEGER TimeStamp;
708 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
709 CF_PARM Cf;
710 BOOLEAN TimerCancelled;
711 UCHAR Erp;
712 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
713 UCHAR SupRateLen, ExtRateLen;
714 UCHAR CkipFlag;
715 USHORT LenVIE;
716 UCHAR AironetCellPowerLimit;
717 EDCA_PARM EdcaParm;
718 QBSS_LOAD_PARM QbssLoad;
719 QOS_CAPABILITY_PARM QosCapability;
720 USHORT Status;
721 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
722 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
723 ULONG RalinkIe;
724 ULONG Idx;
725 HT_CAPABILITY_IE HtCapability;
726 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
727 UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
728 UCHAR AddHtInfoLen;
729 UCHAR NewExtChannelOffset = 0xff;
730 #ifdef DOT11_N_SUPPORT
731 UCHAR CentralChannel;
732 #endif // DOT11_N_SUPPORT //
734 // Init Variable IE structure
735 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
736 pVIE->Length = 0;
737 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
738 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
741 if (PeerBeaconAndProbeRspSanity(pAd,
742 Elem->Msg,
743 Elem->MsgLen,
744 Elem->Channel,
745 Addr2,
746 Bssid,
747 Ssid,
748 &SsidLen,
749 &BssType,
750 &BeaconPeriod,
751 &Channel,
752 &NewChannel,
753 &TimeStamp,
754 &Cf,
755 &AtimWin,
756 &CapabilityInfo,
757 &Erp,
758 &DtimCount,
759 &DtimPeriod,
760 &BcastFlag,
761 &MessageToMe,
762 SupRate,
763 &SupRateLen,
764 ExtRate,
765 &ExtRateLen,
766 &CkipFlag,
767 &AironetCellPowerLimit,
768 &EdcaParm,
769 &QbssLoad,
770 &QosCapability,
771 &RalinkIe,
772 &HtCapabilityLen,
773 &PreNHtCapabilityLen,
774 &HtCapability,
775 &AddHtInfoLen,
776 &AddHtInfo,
777 &NewExtChannelOffset,
778 &LenVIE,
779 pVIE))
781 // Disqualify 11b only adhoc when we are in 11g only adhoc mode
782 if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12))
783 return;
785 // BEACON from desired BSS/IBSS found. We should be able to decide most
786 // BSS parameters here.
787 // Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION?
788 // Do we need to receover back all parameters belonging to previous BSS?
789 // A. Should be not. There's no back-door recover to previous AP. It still need
790 // a new JOIN-AUTH-ASSOC sequence.
791 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid))
793 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel));
794 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
796 // Update RSSI to prevent No signal display when cards first initialized
797 pAd->StaCfg.RssiSample.LastRssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0);
798 pAd->StaCfg.RssiSample.LastRssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1);
799 pAd->StaCfg.RssiSample.LastRssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2);
800 pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0;
801 pAd->StaCfg.RssiSample.AvgRssi0X8 = pAd->StaCfg.RssiSample.AvgRssi0 << 3;
802 pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1;
803 pAd->StaCfg.RssiSample.AvgRssi1X8 = pAd->StaCfg.RssiSample.AvgRssi1 << 3;
804 pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2;
805 pAd->StaCfg.RssiSample.AvgRssi2X8 = pAd->StaCfg.RssiSample.AvgRssi2 << 3;
808 // We need to check if SSID only set to any, then we can record the current SSID.
809 // Otherwise will cause hidden SSID association failed.
811 if (pAd->MlmeAux.SsidLen == 0)
813 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
814 pAd->MlmeAux.SsidLen = SsidLen;
816 else
818 Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel);
820 if (Idx != BSS_NOT_FOUND)
823 // Multiple SSID case, used correct CapabilityInfo
825 CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo;
828 NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN);
829 pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
830 pAd->MlmeAux.BssType = BssType;
831 pAd->MlmeAux.BeaconPeriod = BeaconPeriod;
832 pAd->MlmeAux.Channel = Channel;
833 pAd->MlmeAux.AtimWin = AtimWin;
834 pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod;
835 pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration;
836 pAd->MlmeAux.APRalinkIe = RalinkIe;
838 // Copy AP's supported rate to MlmeAux for creating assoication request
839 // Also filter out not supported rate
840 pAd->MlmeAux.SupRateLen = SupRateLen;
841 NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
842 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
843 pAd->MlmeAux.ExtRateLen = ExtRateLen;
844 NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
845 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
847 NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16);
848 #ifdef DOT11_N_SUPPORT
849 pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
850 pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen;
852 // filter out un-supported ht rates
853 if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
855 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
856 RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE);
858 // StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability
859 NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16);
860 pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
861 pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE;
862 pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
863 if (PreNHtCapabilityLen > 0)
864 pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE;
865 RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo);
866 // Copy AP Parameter to StaActive. This is also in LinkUp.
867 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n",
868 pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth));
870 if (AddHtInfoLen > 0)
872 CentralChannel = AddHtInfo.ControlChan;
873 // Check again the Bandwidth capability of this AP.
874 if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
876 CentralChannel = AddHtInfo.ControlChan - 2;
878 else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
880 CentralChannel = AddHtInfo.ControlChan + 2;
883 // Check Error .
884 if (pAd->MlmeAux.CentralChannel != CentralChannel)
885 DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel));
887 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, AddHtInfo.ControlChan));
892 else
893 #endif // DOT11_N_SUPPORT //
895 // To prevent error, let legacy AP must have same CentralChannel and Channel.
896 if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0))
897 pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel;
899 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
900 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
901 RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE);
904 RTMPUpdateMlmeRate(pAd);
906 // copy QOS related information
907 if ((pAd->CommonCfg.bWmmCapable)
908 #ifdef DOT11_N_SUPPORT
909 || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
910 #endif // DOT11_N_SUPPORT //
913 NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM));
914 NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
915 NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
917 else
919 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
920 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
921 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
924 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n",
925 pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
927 if (AironetCellPowerLimit != 0xFF)
929 //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power
930 ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
932 else //Used the default TX Power Percentage.
933 pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
935 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
936 Status = MLME_SUCCESS;
937 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
939 // not to me BEACON, ignored
941 // sanity check fail, ignore this frame
945 ==========================================================================
946 Description:
947 receive BEACON from peer
949 IRQL = DISPATCH_LEVEL
951 ==========================================================================
953 VOID PeerBeacon(
954 IN PRTMP_ADAPTER pAd,
955 IN MLME_QUEUE_ELEM *Elem)
957 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
958 CHAR Ssid[MAX_LEN_OF_SSID];
959 CF_PARM CfParm;
960 UCHAR SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0;
961 UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0;
962 USHORT CapabilityInfo, AtimWin, BeaconPeriod;
963 LARGE_INTEGER TimeStamp;
964 USHORT TbttNumToNextWakeUp;
965 UCHAR Erp;
966 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
967 UCHAR SupRateLen, ExtRateLen;
968 UCHAR CkipFlag;
969 USHORT LenVIE;
970 UCHAR AironetCellPowerLimit;
971 EDCA_PARM EdcaParm;
972 QBSS_LOAD_PARM QbssLoad;
973 QOS_CAPABILITY_PARM QosCapability;
974 ULONG RalinkIe;
975 // New for WPA security suites
976 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
977 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
978 HT_CAPABILITY_IE HtCapability;
979 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
980 UCHAR HtCapabilityLen, PreNHtCapabilityLen;
981 UCHAR AddHtInfoLen;
982 UCHAR NewExtChannelOffset = 0xff;
984 if (!(INFRA_ON(pAd) || ADHOC_ON(pAd)
986 return;
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));
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))
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));
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;
1043 // ignore BEACON not for my SSID
1044 if ((! is_my_ssid) && (! is_my_bssid))
1045 return;
1047 // It means STA waits disassoc completely from this AP, ignores this beacon.
1048 if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC)
1049 return;
1051 #ifdef DOT11_N_SUPPORT
1052 // Copy Control channel for this BSSID.
1053 if (AddHtInfoLen != 0)
1054 Channel = AddHtInfo.ControlChan;
1056 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
1057 HtCapabilityLen = SIZE_HT_CAP_IE;
1058 #endif // DOT11_N_SUPPORT //
1061 // Housekeeping "SsidBssTab" table for later-on ROAMing usage.
1063 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1064 if (Bssidx == BSS_NOT_FOUND)
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;
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);
1083 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
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
1094 // channel sanity check
1095 for (index = 0 ; index < pAd->ChannelListNum; index++)
1097 if (pAd->ChannelList[index].Channel == NewChannel)
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;
1108 if (index >= pAd->ChannelListNum)
1110 DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
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))
1118 INT i;
1120 // Add the safeguard against the mismatch of adhoc wep status
1121 if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus)
1123 return;
1126 // collapse into the ADHOC network which has bigger BSSID value.
1127 for (i = 0; i < 6; i++)
1129 if (Bssid[i] > pAd->CommonCfg.Bssid[i])
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;
1141 else if (Bssid[i] < pAd->CommonCfg.Bssid[i])
1142 break;
1147 NdisGetSystemUpTime(&Now);
1148 pBss = &pAd->ScanTab.BssEntry[Bssidx];
1149 pBss->Rssi = RealRssi; // lastest RSSI
1150 pBss->LastBeaconRxTime = Now; // last RX timestamp
1153 // BEACON from my BSSID - either IBSS or INFRA network
1155 if (is_my_bssid)
1157 RXWI_STRUC RxWI;
1159 pAd->StaCfg.DtimCount = DtimCount;
1160 pAd->StaCfg.DtimPeriod = DtimPeriod;
1161 pAd->StaCfg.LastBeaconRxTime = Now;
1164 RxWI.RSSI0 = Elem->Rssi0;
1165 RxWI.RSSI1 = Elem->Rssi1;
1166 RxWI.RSSI2 = Elem->Rssi2;
1168 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI);
1169 if (AironetCellPowerLimit != 0xFF)
1172 // We get the Cisco (ccx) "TxPower Limit" required
1173 // Changed to appropriate TxPower Limit for Ciso Compatible Extensions
1175 ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
1177 else
1180 // AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist.
1181 // Used the default TX Power Percentage, that set from UI.
1183 pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
1186 // at least one 11b peer joined. downgrade the MaxTxRate to 11Mbps
1187 // after last 11b peer left for several seconds, we'll auto switch back to 11G rate
1188 // in MlmePeriodicExec()
1189 if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo)))
1191 BOOLEAN bRestart;
1192 BOOLEAN bnRestart;
1194 bRestart = FALSE;
1195 bnRestart = FALSE;
1199 if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.MaxTxRate > RATE_11))
1201 if (pAd->StaCfg.AdhocBOnlyJoined == FALSE)
1203 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11b peer joined. down-grade to 11b TX rates \n"));
1204 bRestart = TRUE;
1205 NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1206 pAd->StaActive.SupRateLen = SupRateLen;
1207 NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
1208 pAd->StaActive.ExtRateLen = ExtRateLen;
1209 pAd->StaCfg.AdhocBOnlyJoined = TRUE;
1210 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
1211 AsicSetEdcaParm(pAd, NULL);
1214 // this timestamp is for MlmePeriodicExec() to check if all 11B peers have left
1215 pAd->StaCfg.Last11bBeaconRxTime = Now;
1216 break;
1218 #ifdef DOT11_N_SUPPORT
1219 // Update Ht Phy.
1220 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
1222 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
1223 !pAd->StaCfg.AdhocBGJoined &&
1224 !pAd->StaCfg.AdhocBOnlyJoined)
1225 AdhocTurnOnQos(pAd);
1227 // Handle rate switch issue when Adhoc mode
1228 if ((SupRateLen+ExtRateLen >= 8) && (HtCapability.MCSSet[0] == 0) && (HtCapability.MCSSet[1] == 0))
1230 if (pAd->StaCfg.AdhocBGJoined == FALSE)
1232 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11g peer joined. down-grade to 11g TX rates \n"));
1233 bRestart = TRUE;
1234 NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1235 pAd->StaActive.SupRateLen = SupRateLen;
1236 NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
1237 pAd->StaActive.ExtRateLen = ExtRateLen;
1238 pAd->StaCfg.AdhocBGJoined = TRUE;
1239 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
1240 AsicSetEdcaParm(pAd, NULL);
1243 // this timestamp is for MlmePeriodicExec() to check if all 11g peers have left
1244 pAd->StaCfg.Last11gBeaconRxTime = Now;
1245 break;
1247 else if (!pAd->StaCfg.AdhocBGJoined &&
1248 !pAd->StaCfg.AdhocBOnlyJoined &&
1249 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) &&
1250 (HtCapability.HtCapInfo.ChannelWidth == BW_20))
1252 if (pAd->StaCfg.Adhoc20NJoined == FALSE)
1254 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
1256 pAd->StaCfg.Adhoc20NJoined = TRUE;
1257 NdisMoveMemory(&pAd->MlmeAux.HtCapability, &HtCapability, SIZE_HT_CAP_IE);
1258 if (AddHtInfoLen != 0)
1259 NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, AddHtInfoLen);
1260 NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16);
1262 RTMPCheckHt(pAd, Elem->Wcid, &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo);
1263 COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
1264 pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
1265 bRestart = TRUE;
1266 bnRestart = TRUE;
1268 // this timestamp is for MlmePeriodicExec() to check if all 20MHz N peers have left
1269 pAd->StaCfg.Last20NBeaconRxTime = Now;
1273 else
1274 #endif // DOT11_N_SUPPORT //
1276 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
1277 RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE);
1279 }while (FALSE);
1281 // If peer Adhoc is legacy mode, I don't need to call MlmeUpdateHtTxRates no matter I support HT or not
1282 if ((bRestart == TRUE) && (bnRestart == FALSE))
1284 MlmeUpdateTxRates(pAd, FALSE, 0);
1285 MakeIbssBeacon(pAd); // re-build BEACON frame
1286 AsicEnableIbssSync(pAd); // copy to on-chip memory
1288 #ifdef DOT11_N_SUPPORT
1289 else if ((bRestart == TRUE) && (bnRestart == TRUE))
1291 MlmeUpdateTxRates(pAd, FALSE, BSS0);
1292 MlmeUpdateHtTxRates(pAd, BSS0);
1293 MakeIbssBeacon(pAd); // re-build BEACON frame
1294 AsicEnableIbssSync(pAd); // copy to on-chip memory
1296 #endif // DOT11_N_SUPPORT //
1298 // At least another peer in this IBSS, declare MediaState as CONNECTED
1299 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1301 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1303 pAd->IndicateMediaState = NdisMediaStateConnected;
1304 RTMP_IndicateMediaState(pAd);
1305 pAd->ExtraInfo = GENERAL_LINK_UP;
1306 AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1308 // 2003/03/12 - john
1309 // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that
1310 // "site survey" result should always include the current connected network.
1312 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1313 if (Bssidx == BSS_NOT_FOUND)
1315 Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1316 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
1317 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0,
1318 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
1320 DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n"));
1323 // Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon.
1324 // To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station.
1325 if (ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID))
1327 UCHAR idx;
1328 MAC_TABLE_ENTRY *pEntry;
1330 // look up the existing table
1331 pEntry = MacTableLookup(pAd, Addr2);
1332 if (pEntry == NULL)
1334 // Another adhoc joining, add to our MAC table.
1335 pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE);
1336 if (pEntry)
1338 pEntry->Sst = SST_ASSOC;
1339 idx = pAd->StaCfg.DefaultKeyId;
1340 // After InsertEntry, Write to ASIC on-chip table.
1341 RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry);
1342 DBGPRINT(RT_DEBUG_TRACE, ("ADHOC %x:%x:%x:%x:%x:%x join in.Entry=%d\n", Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5], pEntry->Aid));
1344 pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word;
1345 if (HtCapabilityLen <= 0)
1347 pEntry->HTPhyMode.field.STBC = 0;
1348 pEntry->HTPhyMode.field.BW = 0;
1349 pEntry->HTPhyMode.field.ShortGI = 0;
1350 if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.Channel <= 14))
1352 pEntry->HTPhyMode.field.MODE = MODE_CCK;
1354 else
1356 pEntry->HTPhyMode.field.MODE = MODE_OFDM;
1358 MlmeUpdateTxRates(pAd, FALSE, 0);
1360 #ifdef DOT11_N_SUPPORT
1361 else
1363 MlmeUpdateTxRates(pAd, FALSE, 0);
1364 MlmeUpdateHtTxRates(pAd, BSS0);
1366 #endif // DOT11_N_SUPPORT //
1369 union iwreq_data wrqu;
1370 wext_notify_event_assoc(pAd);
1372 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1373 memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
1374 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1382 if (INFRA_ON(pAd))
1384 BOOLEAN bUseShortSlot, bUseBGProtection;
1386 // decide to use/change to -
1387 // 1. long slot (20 us) or short slot (9 us) time
1388 // 2. turn on/off RTS/CTS and/or CTS-to-self protection
1389 // 3. short preamble
1391 //bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo);
1392 bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo);
1393 if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))
1394 AsicSetSlotTime(pAd, bUseShortSlot);
1396 bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || // always use
1397 ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp));
1399 if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP
1400 bUseBGProtection = FALSE;
1402 if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
1404 if (bUseBGProtection)
1406 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1407 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1409 else
1411 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1412 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1415 DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection));
1418 #ifdef DOT11_N_SUPPORT
1419 // check Ht protection mode. and adhere to the Non-GF device indication by AP.
1420 if ((AddHtInfoLen != 0) &&
1421 ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) ||
1422 (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent)))
1424 pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent;
1425 pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode;
1426 if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)
1428 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE);
1430 else
1431 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1433 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode));
1435 #endif // DOT11_N_SUPPORT //
1437 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) &&
1438 ERP_IS_USE_BARKER_PREAMBLE(Erp))
1440 MlmeSetTxPreamble(pAd, Rt802_11PreambleLong);
1441 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n"));
1444 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1445 (EdcaParm.bValid == TRUE) &&
1446 (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount))
1448 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n",
1449 pAd->CommonCfg.APEdcaParm.EdcaUpdateCount,
1450 EdcaParm.EdcaUpdateCount));
1451 AsicSetEdcaParm(pAd, &EdcaParm);
1454 // copy QOS related information
1455 NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
1456 NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
1459 // only INFRASTRUCTURE mode support power-saving feature
1460 if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave))
1462 UCHAR FreeNumber;
1463 // 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL
1464 // 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE
1465 // 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE
1466 // 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE
1467 // 5. otherwise, put PHY back to sleep to save battery.
1468 if (MessageToMe)
1470 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1472 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1474 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable &&
1475 pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO)
1477 pAd->CommonCfg.bNeedSendTriggerFrame = TRUE;
1479 else
1480 RT28XX_PS_POLL_ENQUEUE(pAd);
1482 else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM))
1484 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1486 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1489 else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) ||
1490 (pAd->TxSwQueue[QID_AC_BE].Number != 0) ||
1491 (pAd->TxSwQueue[QID_AC_VI].Number != 0) ||
1492 (pAd->TxSwQueue[QID_AC_VO].Number != 0) ||
1493 (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1494 (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1495 (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1496 (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1497 (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS))
1499 // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme
1500 // can we cheat here (i.e. just check MGMT & AC_BE) for better performance?
1501 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1503 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1506 else
1508 USHORT NextDtim = DtimCount;
1510 if (NextDtim == 0)
1511 NextDtim = DtimPeriod;
1513 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
1514 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
1515 TbttNumToNextWakeUp = NextDtim;
1517 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1519 // Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode.
1520 RTMP_SET_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
1521 pAd->ThisTbttNumToNextWakeUp = TbttNumToNextWakeUp;
1522 //AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
1527 // not my BSSID, ignore it
1529 // sanity check fail, ignore this frame
1533 ==========================================================================
1534 Description:
1535 Receive PROBE REQ from remote peer when operating in IBSS mode
1536 ==========================================================================
1538 VOID PeerProbeReqAction(
1539 IN PRTMP_ADAPTER pAd,
1540 IN MLME_QUEUE_ELEM *Elem)
1542 UCHAR Addr2[MAC_ADDR_LEN];
1543 CHAR Ssid[MAX_LEN_OF_SSID];
1544 UCHAR SsidLen;
1545 #ifdef DOT11_N_SUPPORT
1546 UCHAR HtLen, AddHtLen, NewExtLen;
1547 #endif // DOT11_N_SUPPORT //
1548 HEADER_802_11 ProbeRspHdr;
1549 NDIS_STATUS NStatus;
1550 PUCHAR pOutBuffer = NULL;
1551 ULONG FrameLen = 0;
1552 LARGE_INTEGER FakeTimestamp;
1553 UCHAR DsLen = 1, IbssLen = 2;
1554 UCHAR LocalErpIe[3] = {IE_ERP, 1, 0};
1555 BOOLEAN Privacy;
1556 USHORT CapabilityInfo;
1557 UCHAR RSNIe = IE_WPA;
1559 if (! ADHOC_ON(pAd))
1560 return;
1562 if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen))
1564 if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1566 // allocate and send out ProbeRsp frame
1567 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1568 if (NStatus != NDIS_STATUS_SUCCESS)
1569 return;
1571 //pAd->StaCfg.AtimWin = 0; // ??????
1573 Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
1574 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
1575 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
1576 CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0);
1578 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1579 sizeof(HEADER_802_11), &ProbeRspHdr,
1580 TIMESTAMP_LEN, &FakeTimestamp,
1581 2, &pAd->CommonCfg.BeaconPeriod,
1582 2, &CapabilityInfo,
1583 1, &SsidIe,
1584 1, &pAd->CommonCfg.SsidLen,
1585 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
1586 1, &SupRateIe,
1587 1, &pAd->StaActive.SupRateLen,
1588 pAd->StaActive.SupRateLen, pAd->StaActive.SupRate,
1589 1, &DsIe,
1590 1, &DsLen,
1591 1, &pAd->CommonCfg.Channel,
1592 1, &IbssIe,
1593 1, &IbssLen,
1594 2, &pAd->StaActive.AtimWin,
1595 END_OF_ARGS);
1597 if (pAd->StaActive.ExtRateLen)
1599 ULONG tmp;
1600 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1601 3, LocalErpIe,
1602 1, &ExtRateIe,
1603 1, &pAd->StaActive.ExtRateLen,
1604 pAd->StaActive.ExtRateLen, &pAd->StaActive.ExtRate,
1605 END_OF_ARGS);
1606 FrameLen += tmp;
1609 // If adhoc secruity is set for WPA-None, append the cipher suite IE
1610 if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
1612 ULONG tmp;
1613 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1614 1, &RSNIe,
1615 1, &pAd->StaCfg.RSNIE_Len,
1616 pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
1617 END_OF_ARGS);
1618 FrameLen += tmp;
1620 #ifdef DOT11_N_SUPPORT
1621 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1623 ULONG TmpLen;
1624 UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
1625 HtLen = sizeof(pAd->CommonCfg.HtCapability);
1626 AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo);
1627 NewExtLen = 1;
1628 //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame
1629 if (pAd->bBroadComHT == TRUE)
1631 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1632 1, &WpaIe,
1633 4, &BROADCOM[0],
1634 pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
1635 END_OF_ARGS);
1637 else
1639 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1640 1, &HtCapIe,
1641 1, &HtLen,
1642 sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability,
1643 1, &AddHtInfoIe,
1644 1, &AddHtLen,
1645 sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo,
1646 1, &NewExtChanIe,
1647 1, &NewExtLen,
1648 sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset,
1649 END_OF_ARGS);
1651 FrameLen += TmpLen;
1653 #endif // DOT11_N_SUPPORT //
1654 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1655 MlmeFreeMemory(pAd, pOutBuffer);
1660 VOID BeaconTimeoutAtJoinAction(
1661 IN PRTMP_ADAPTER pAd,
1662 IN MLME_QUEUE_ELEM *Elem)
1664 USHORT Status;
1665 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n"));
1666 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1667 Status = MLME_REJ_TIMEOUT;
1668 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1672 ==========================================================================
1673 Description:
1674 Scan timeout procedure. basically add channel index by 1 and rescan
1675 ==========================================================================
1677 VOID ScanTimeoutAction(
1678 IN PRTMP_ADAPTER pAd,
1679 IN MLME_QUEUE_ELEM *Elem)
1681 pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel);
1683 // Only one channel scanned for CISCO beacon request
1684 if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) ||
1685 (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) ||
1686 (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) ||
1687 (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD))
1688 pAd->MlmeAux.Channel = 0;
1690 // this routine will stop if pAd->MlmeAux.Channel == 0
1691 ScanNextChannel(pAd);
1695 ==========================================================================
1696 Description:
1697 ==========================================================================
1699 VOID InvalidStateWhenScan(
1700 IN PRTMP_ADAPTER pAd,
1701 IN MLME_QUEUE_ELEM *Elem)
1703 USHORT Status;
1704 DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1705 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1706 Status = MLME_STATE_MACHINE_REJECT;
1707 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
1711 ==========================================================================
1712 Description:
1713 ==========================================================================
1715 VOID InvalidStateWhenJoin(
1716 IN PRTMP_ADAPTER pAd,
1717 IN MLME_QUEUE_ELEM *Elem)
1719 USHORT Status;
1720 DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1721 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1722 Status = MLME_STATE_MACHINE_REJECT;
1723 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1727 ==========================================================================
1728 Description:
1729 ==========================================================================
1731 VOID InvalidStateWhenStart(
1732 IN PRTMP_ADAPTER pAd,
1733 IN MLME_QUEUE_ELEM *Elem)
1735 USHORT Status;
1736 DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1737 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1738 Status = MLME_STATE_MACHINE_REJECT;
1739 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
1743 ==========================================================================
1744 Description:
1746 IRQL = DISPATCH_LEVEL
1748 ==========================================================================
1750 VOID EnqueuePsPoll(
1751 IN PRTMP_ADAPTER pAd)
1753 if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP)
1754 pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE;
1755 MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
1760 ==========================================================================
1761 Description:
1762 ==========================================================================
1764 VOID EnqueueProbeRequest(
1765 IN PRTMP_ADAPTER pAd)
1767 NDIS_STATUS NState;
1768 PUCHAR pOutBuffer;
1769 ULONG FrameLen = 0;
1770 HEADER_802_11 Hdr80211;
1772 DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n"));
1774 NState = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1775 if (NState == NDIS_STATUS_SUCCESS)
1777 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
1779 // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse
1780 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1781 sizeof(HEADER_802_11), &Hdr80211,
1782 1, &SsidIe,
1783 1, &pAd->CommonCfg.SsidLen,
1784 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
1785 1, &SupRateIe,
1786 1, &pAd->StaActive.SupRateLen,
1787 pAd->StaActive.SupRateLen, pAd->StaActive.SupRate,
1788 END_OF_ARGS);
1789 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1790 MlmeFreeMemory(pAd, pOutBuffer);
1795 BOOLEAN ScanRunning(
1796 IN PRTMP_ADAPTER pAd)
1798 return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE;