First Support on Ginger and OMAP TI
[linux-ginger.git] / drivers / staging / rt2860 / sta / sync.c
bloba6e4362fc5cc19e069857bc20cbcceddfda006c8
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 #ifdef RT2860
41 #define AC0_DEF_TXOP 0
42 #define AC1_DEF_TXOP 0
43 #define AC2_DEF_TXOP 94
44 #define AC3_DEF_TXOP 47
46 VOID AdhocTurnOnQos(
47 IN PRTMP_ADAPTER pAd)
49 // Turn on QOs if use HT rate.
50 if (pAd->CommonCfg.APEdcaParm.bValid == FALSE)
52 pAd->CommonCfg.APEdcaParm.bValid = TRUE;
53 pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3;
54 pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7;
55 pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1;
56 pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1;
58 pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4;
59 pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4;
60 pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3;
61 pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2;
63 pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10;
64 pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6;
65 pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4;
66 pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3;
68 pAd->CommonCfg.APEdcaParm.Txop[0] = 0;
69 pAd->CommonCfg.APEdcaParm.Txop[1] = 0;
70 pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP;
71 pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP;
73 AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
75 #endif /* RT2860 */
76 #ifdef RT2870
77 #define ADHOC_ENTRY_BEACON_LOST_TIME (2*OS_HZ) // 2 sec
78 #endif
81 ==========================================================================
82 Description:
83 The sync state machine,
84 Parameters:
85 Sm - pointer to the state machine
86 Note:
87 the state machine looks like the following
89 ==========================================================================
91 VOID SyncStateMachineInit(
92 IN PRTMP_ADAPTER pAd,
93 IN STATE_MACHINE *Sm,
94 OUT STATE_MACHINE_FUNC Trans[])
96 StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE);
98 // column 1
99 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction);
100 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction);
101 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction);
102 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon);
103 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction);
105 //column 2
106 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
107 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
108 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
109 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction);
110 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction);
112 // column 3
113 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
114 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
115 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
116 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
117 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
118 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction);
120 // timer init
121 RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE);
122 RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE);
126 ==========================================================================
127 Description:
128 Beacon timeout handler, executed in timer thread
130 IRQL = DISPATCH_LEVEL
132 ==========================================================================
134 VOID BeaconTimeout(
135 IN PVOID SystemSpecific1,
136 IN PVOID FunctionContext,
137 IN PVOID SystemSpecific2,
138 IN PVOID SystemSpecific3)
140 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
142 DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n"));
144 // Do nothing if the driver is starting halt state.
145 // This might happen when timer already been fired before cancel timer with mlmehalt
146 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
147 return;
149 if ((pAd->CommonCfg.BBPCurrentBW == BW_40)
152 UCHAR BBPValue = 0;
153 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
154 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
155 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
156 BBPValue &= (~0x18);
157 BBPValue |= 0x10;
158 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
159 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr));
162 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL);
163 RT28XX_MLME_HANDLER(pAd);
167 ==========================================================================
168 Description:
169 Scan timeout handler, executed in timer thread
171 IRQL = DISPATCH_LEVEL
173 ==========================================================================
175 VOID ScanTimeout(
176 IN PVOID SystemSpecific1,
177 IN PVOID FunctionContext,
178 IN PVOID SystemSpecific2,
179 IN PVOID SystemSpecific3)
181 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
184 // Do nothing if the driver is starting halt state.
185 // This might happen when timer already been fired before cancel timer with mlmehalt
186 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
187 return;
189 if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL))
191 RT28XX_MLME_HANDLER(pAd);
193 else
195 // To prevent SyncMachine.CurrState is SCAN_LISTEN forever.
196 pAd->MlmeAux.Channel = 0;
197 ScanNextChannel(pAd);
198 if (pAd->CommonCfg.bWirelessEvent)
200 RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
206 ==========================================================================
207 Description:
208 MLME SCAN req state machine procedure
209 ==========================================================================
211 VOID MlmeScanReqAction(
212 IN PRTMP_ADAPTER pAd,
213 IN MLME_QUEUE_ELEM *Elem)
215 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0;
216 BOOLEAN TimerCancelled;
217 ULONG Now;
218 USHORT Status;
219 PHEADER_802_11 pHdr80211;
220 PUCHAR pOutBuffer = NULL;
221 NDIS_STATUS NStatus;
223 // Check the total scan tries for one single OID command
224 // If this is the CCX 2.0 Case, skip that!
225 if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
227 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n"));
228 return;
231 // Increase the scan retry counters.
232 pAd->StaCfg.ScanCnt++;
234 #ifdef RT2860
235 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
236 (IDLE_ON(pAd)) &&
237 (pAd->StaCfg.bRadio == TRUE) &&
238 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
240 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
242 #endif
244 // first check the parameter sanity
245 if (MlmeScanReqSanity(pAd,
246 Elem->Msg,
247 Elem->MsgLen,
248 &BssType,
249 Ssid,
250 &SsidLen,
251 &ScanType))
254 // Check for channel load and noise hist request
255 // Suspend MSDU only at scan request, not the last two mentioned
256 if ((ScanType == SCAN_CISCO_NOISE) || (ScanType == SCAN_CISCO_CHANNEL_LOAD))
258 if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
259 RTMPSuspendMsduTransmission(pAd); // Suspend MSDU transmission here
261 else
263 // Suspend MSDU transmission here
264 RTMPSuspendMsduTransmission(pAd);
268 // To prevent data lost.
269 // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress.
270 // And should send an NULL data with turned PSM bit off to AP, when scan progress done
272 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)))
274 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);
275 if (NStatus == NDIS_STATUS_SUCCESS)
277 pHdr80211 = (PHEADER_802_11) pOutBuffer;
278 MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
279 pHdr80211->Duration = 0;
280 pHdr80211->FC.Type = BTYPE_DATA;
281 pHdr80211->FC.PwrMgmt = PWR_SAVE;
283 // Send using priority queue
284 MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
285 DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n"));
286 MlmeFreeMemory(pAd, pOutBuffer);
287 RTMPusecDelay(5000);
291 NdisGetSystemUpTime(&Now);
292 pAd->StaCfg.LastScanTime = Now;
293 // reset all the timers
294 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
295 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
297 // record desired BSS parameters
298 pAd->MlmeAux.BssType = BssType;
299 pAd->MlmeAux.ScanType = ScanType;
300 pAd->MlmeAux.SsidLen = SsidLen;
301 NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
302 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
304 // start from the first channel
305 pAd->MlmeAux.Channel = FirstChannel(pAd);
307 // Change the scan channel when dealing with CCX beacon report
308 if ((ScanType == SCAN_CISCO_PASSIVE) || (ScanType == SCAN_CISCO_ACTIVE) ||
309 (ScanType == SCAN_CISCO_CHANNEL_LOAD) || (ScanType == SCAN_CISCO_NOISE))
310 pAd->MlmeAux.Channel = pAd->StaCfg.CCXScanChannel;
312 // Let BBP register at 20MHz to do scan
313 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
314 BBPValue &= (~0x18);
315 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
316 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
317 ScanNextChannel(pAd);
319 else
321 DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n"));
322 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
323 Status = MLME_INVALID_FORMAT;
324 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
329 ==========================================================================
330 Description:
331 MLME JOIN req state machine procedure
332 ==========================================================================
334 VOID MlmeJoinReqAction(
335 IN PRTMP_ADAPTER pAd,
336 IN MLME_QUEUE_ELEM *Elem)
338 UCHAR BBPValue = 0;
339 BSS_ENTRY *pBss;
340 BOOLEAN TimerCancelled;
341 HEADER_802_11 Hdr80211;
342 NDIS_STATUS NStatus;
343 ULONG FrameLen = 0;
344 PUCHAR pOutBuffer = NULL;
345 PUCHAR pSupRate = NULL;
346 UCHAR SupRateLen;
347 PUCHAR pExtRate = NULL;
348 UCHAR ExtRateLen;
349 UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C};
350 UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR);
351 MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg);
353 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx));
355 #ifdef RT2860
356 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
357 (IDLE_ON(pAd)) &&
358 (pAd->StaCfg.bRadio == TRUE) &&
359 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
361 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
363 #endif
365 // reset all the timers
366 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
367 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
369 pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx];
371 // record the desired SSID & BSSID we're waiting for
372 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid);
374 // If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again.
375 if (pBss->Hidden == 0)
377 NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen);
378 pAd->MlmeAux.SsidLen = pBss->SsidLen;
381 pAd->MlmeAux.BssType = pBss->BssType;
382 pAd->MlmeAux.Channel = pBss->Channel;
383 pAd->MlmeAux.CentralChannel = pBss->CentralChannel;
385 // Let BBP register at 20MHz to do scan
386 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
387 BBPValue &= (~0x18);
388 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
389 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
391 // switch channel and waiting for beacon timer
392 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
393 AsicLockChannel(pAd, pAd->MlmeAux.Channel);
394 RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT);
398 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
399 (pAd->MlmeAux.Channel > 14) &&
400 RadarChannelCheck(pAd, pAd->MlmeAux.Channel))
404 // We can't send any Probe request frame to meet 802.11h.
406 if (pBss->Hidden == 0)
407 break;
411 // send probe request
413 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
414 if (NStatus == NDIS_STATUS_SUCCESS)
416 if (pAd->MlmeAux.Channel <= 14)
418 pSupRate = pAd->CommonCfg.SupRate;
419 SupRateLen = pAd->CommonCfg.SupRateLen;
420 pExtRate = pAd->CommonCfg.ExtRate;
421 ExtRateLen = pAd->CommonCfg.ExtRateLen;
423 else
426 // Overwrite Support Rate, CCK rate are not allowed
428 pSupRate = ASupRate;
429 SupRateLen = ASupRateLen;
430 ExtRateLen = 0;
433 if (pAd->MlmeAux.BssType == BSS_INFRA)
434 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid);
435 else
436 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
438 MakeOutgoingFrame(pOutBuffer, &FrameLen,
439 sizeof(HEADER_802_11), &Hdr80211,
440 1, &SsidIe,
441 1, &pAd->MlmeAux.SsidLen,
442 pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid,
443 1, &SupRateIe,
444 1, &SupRateLen,
445 SupRateLen, pSupRate,
446 END_OF_ARGS);
448 if (ExtRateLen)
450 ULONG Tmp;
451 MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
452 1, &ExtRateIe,
453 1, &ExtRateLen,
454 ExtRateLen, pExtRate,
455 END_OF_ARGS);
456 FrameLen += Tmp;
460 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
461 MlmeFreeMemory(pAd, pOutBuffer);
463 } while (FALSE);
465 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n",
466 pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
468 pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON;
472 ==========================================================================
473 Description:
474 MLME START Request state machine procedure, starting an IBSS
475 ==========================================================================
477 VOID MlmeStartReqAction(
478 IN PRTMP_ADAPTER pAd,
479 IN MLME_QUEUE_ELEM *Elem)
481 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen;
482 BOOLEAN TimerCancelled;
484 // New for WPA security suites
485 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
486 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
487 LARGE_INTEGER TimeStamp;
488 BOOLEAN Privacy;
489 USHORT Status;
491 // Init Variable IE structure
492 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
493 pVIE->Length = 0;
494 TimeStamp.u.LowPart = 0;
495 TimeStamp.u.HighPart = 0;
497 if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, Ssid, &SsidLen))
499 // reset all the timers
500 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
501 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
504 // Start a new IBSS. All IBSS parameters are decided now....
506 DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n"));
507 pAd->MlmeAux.BssType = BSS_ADHOC;
508 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
509 pAd->MlmeAux.SsidLen = SsidLen;
511 // generate a radom number as BSSID
512 MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid);
513 DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n"));
515 Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
516 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
517 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
518 pAd->MlmeAux.CapabilityInfo = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0);
519 pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod;
520 pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin;
521 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
523 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
524 pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel;
526 pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen;
527 NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
528 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
529 pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen;
530 NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
531 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
533 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
535 RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo);
536 pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE);
537 // Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here.
538 DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n"));
540 else
542 pAd->MlmeAux.HtCapabilityLen = 0;
543 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
545 // temporarily not support QOS in IBSS
546 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
547 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
548 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
550 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
551 AsicLockChannel(pAd, pAd->MlmeAux.Channel);
553 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n",
554 pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
556 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
557 Status = MLME_SUCCESS;
558 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
560 else
562 DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n"));
563 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
564 Status = MLME_INVALID_FORMAT;
565 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
570 ==========================================================================
571 Description:
572 peer sends beacon back when scanning
573 ==========================================================================
575 VOID PeerBeaconAtScanAction(
576 IN PRTMP_ADAPTER pAd,
577 IN MLME_QUEUE_ELEM *Elem)
579 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
580 UCHAR Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel,
581 SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe;
582 CF_PARM CfParm;
583 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
584 PFRAME_802_11 pFrame;
585 LARGE_INTEGER TimeStamp;
586 UCHAR Erp;
587 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
588 UCHAR SupRateLen, ExtRateLen;
589 USHORT LenVIE;
590 UCHAR CkipFlag;
591 UCHAR AironetCellPowerLimit;
592 EDCA_PARM EdcaParm;
593 QBSS_LOAD_PARM QbssLoad;
594 QOS_CAPABILITY_PARM QosCapability;
595 ULONG RalinkIe;
596 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
597 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
598 HT_CAPABILITY_IE HtCapability;
599 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
600 UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
601 UCHAR AddHtInfoLen;
602 UCHAR NewExtChannelOffset = 0xff;
604 pFrame = (PFRAME_802_11) Elem->Msg;
605 // Init Variable IE structure
606 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
607 pVIE->Length = 0;
609 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
610 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
612 if (PeerBeaconAndProbeRspSanity(pAd,
613 Elem->Msg,
614 Elem->MsgLen,
615 Elem->Channel,
616 Addr2,
617 Bssid,
618 Ssid,
619 &SsidLen,
620 &BssType,
621 &BeaconPeriod,
622 &Channel,
623 &NewChannel,
624 &TimeStamp,
625 &CfParm,
626 &AtimWin,
627 &CapabilityInfo,
628 &Erp,
629 &DtimCount,
630 &DtimPeriod,
631 &BcastFlag,
632 &MessageToMe,
633 SupRate,
634 &SupRateLen,
635 ExtRate,
636 &ExtRateLen,
637 &CkipFlag,
638 &AironetCellPowerLimit,
639 &EdcaParm,
640 &QbssLoad,
641 &QosCapability,
642 &RalinkIe,
643 &HtCapabilityLen,
644 &PreNHtCapabilityLen,
645 &HtCapability,
646 &AddHtInfoLen,
647 &AddHtInfo,
648 &NewExtChannelOffset,
649 &LenVIE,
650 pVIE))
652 ULONG Idx;
653 CHAR Rssi = 0;
655 Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
656 if (Idx != BSS_NOT_FOUND)
657 Rssi = pAd->ScanTab.BssEntry[Idx].Rssi;
659 Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
661 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
662 HtCapabilityLen = SIZE_HT_CAP_IE;
664 if ((pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) && (Channel == pAd->StaCfg.CCXScanChannel))
666 Idx = BssTableSetEntry(pAd, &pAd->StaCfg.CCXBssTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
667 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen,ExtRate, ExtRateLen, &HtCapability,
668 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
669 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
670 if (Idx != BSS_NOT_FOUND)
672 NdisMoveMemory(pAd->StaCfg.CCXBssTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
673 NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
674 NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
675 if (pAd->StaCfg.CCXReqType == MSRN_TYPE_BEACON_REQ)
676 AironetAddBeaconReport(pAd, Idx, Elem);
679 else
681 Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
682 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
683 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
684 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
686 if (Idx != BSS_NOT_FOUND)
688 NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
689 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
690 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
694 // sanity check fail, ignored
698 ==========================================================================
699 Description:
700 When waiting joining the (I)BSS, beacon received from external
701 ==========================================================================
703 VOID PeerBeaconAtJoinAction(
704 IN PRTMP_ADAPTER pAd,
705 IN MLME_QUEUE_ELEM *Elem)
707 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
708 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe,
709 DtimCount, DtimPeriod, BcastFlag, NewChannel;
710 LARGE_INTEGER TimeStamp;
711 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
712 CF_PARM Cf;
713 BOOLEAN TimerCancelled;
714 UCHAR Erp;
715 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
716 UCHAR SupRateLen, ExtRateLen;
717 UCHAR CkipFlag;
718 USHORT LenVIE;
719 UCHAR AironetCellPowerLimit;
720 EDCA_PARM EdcaParm;
721 QBSS_LOAD_PARM QbssLoad;
722 QOS_CAPABILITY_PARM QosCapability;
723 USHORT Status;
724 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
725 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
726 ULONG RalinkIe;
727 ULONG Idx;
728 HT_CAPABILITY_IE HtCapability;
729 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
730 UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
731 UCHAR AddHtInfoLen;
732 UCHAR NewExtChannelOffset = 0xff;
733 UCHAR CentralChannel;
735 // Init Variable IE structure
736 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
737 pVIE->Length = 0;
738 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
739 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
742 if (PeerBeaconAndProbeRspSanity(pAd,
743 Elem->Msg,
744 Elem->MsgLen,
745 Elem->Channel,
746 Addr2,
747 Bssid,
748 Ssid,
749 &SsidLen,
750 &BssType,
751 &BeaconPeriod,
752 &Channel,
753 &NewChannel,
754 &TimeStamp,
755 &Cf,
756 &AtimWin,
757 &CapabilityInfo,
758 &Erp,
759 &DtimCount,
760 &DtimPeriod,
761 &BcastFlag,
762 &MessageToMe,
763 SupRate,
764 &SupRateLen,
765 ExtRate,
766 &ExtRateLen,
767 &CkipFlag,
768 &AironetCellPowerLimit,
769 &EdcaParm,
770 &QbssLoad,
771 &QosCapability,
772 &RalinkIe,
773 &HtCapabilityLen,
774 &PreNHtCapabilityLen,
775 &HtCapability,
776 &AddHtInfoLen,
777 &AddHtInfo,
778 &NewExtChannelOffset,
779 &LenVIE,
780 pVIE))
782 // Disqualify 11b only adhoc when we are in 11g only adhoc mode
783 if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12))
784 return;
786 // BEACON from desired BSS/IBSS found. We should be able to decide most
787 // BSS parameters here.
788 // Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION?
789 // Do we need to receover back all parameters belonging to previous BSS?
790 // A. Should be not. There's no back-door recover to previous AP. It still need
791 // a new JOIN-AUTH-ASSOC sequence.
792 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid))
794 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel));
795 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
797 // Update RSSI to prevent No signal display when cards first initialized
798 pAd->StaCfg.RssiSample.LastRssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0);
799 pAd->StaCfg.RssiSample.LastRssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1);
800 pAd->StaCfg.RssiSample.LastRssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2);
801 pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0;
802 pAd->StaCfg.RssiSample.AvgRssi0X8 = pAd->StaCfg.RssiSample.AvgRssi0 << 3;
803 pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1;
804 pAd->StaCfg.RssiSample.AvgRssi1X8 = pAd->StaCfg.RssiSample.AvgRssi1 << 3;
805 pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2;
806 pAd->StaCfg.RssiSample.AvgRssi2X8 = pAd->StaCfg.RssiSample.AvgRssi2 << 3;
809 // We need to check if SSID only set to any, then we can record the current SSID.
810 // Otherwise will cause hidden SSID association failed.
812 if (pAd->MlmeAux.SsidLen == 0)
814 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
815 pAd->MlmeAux.SsidLen = SsidLen;
817 else
819 Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel);
821 if (Idx != BSS_NOT_FOUND)
824 // Multiple SSID case, used correct CapabilityInfo
826 CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo;
829 NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN);
830 pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
831 pAd->MlmeAux.BssType = BssType;
832 pAd->MlmeAux.BeaconPeriod = BeaconPeriod;
833 pAd->MlmeAux.Channel = Channel;
834 pAd->MlmeAux.AtimWin = AtimWin;
835 pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod;
836 pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration;
837 pAd->MlmeAux.APRalinkIe = RalinkIe;
839 // Copy AP's supported rate to MlmeAux for creating assoication request
840 // Also filter out not supported rate
841 pAd->MlmeAux.SupRateLen = SupRateLen;
842 NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
843 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
844 pAd->MlmeAux.ExtRateLen = ExtRateLen;
845 NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
846 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
848 NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16);
850 pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
851 pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen;
853 // filter out un-supported ht rates
854 if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
856 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
857 RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE);
859 // StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability
860 NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16);
861 pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
862 pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE;
863 pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
864 if (PreNHtCapabilityLen > 0)
865 pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE;
866 RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo);
867 // Copy AP Parameter to StaActive. This is also in LinkUp.
868 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n",
869 pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth));
871 if (AddHtInfoLen > 0)
873 CentralChannel = AddHtInfo.ControlChan;
874 // Check again the Bandwidth capability of this AP.
875 if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
877 CentralChannel = AddHtInfo.ControlChan - 2;
879 else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
881 CentralChannel = AddHtInfo.ControlChan + 2;
884 // Check Error .
885 if (pAd->MlmeAux.CentralChannel != CentralChannel)
886 DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel));
888 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, AddHtInfo.ControlChan));
893 else
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 || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
911 NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM));
912 NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
913 NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
915 else
917 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
918 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
919 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
922 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n",
923 pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
925 if (AironetCellPowerLimit != 0xFF)
927 //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power
928 ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
930 else //Used the default TX Power Percentage.
931 pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
933 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
934 Status = MLME_SUCCESS;
935 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
937 // not to me BEACON, ignored
939 // sanity check fail, ignore this frame
943 ==========================================================================
944 Description:
945 receive BEACON from peer
947 IRQL = DISPATCH_LEVEL
949 ==========================================================================
951 VOID PeerBeacon(
952 IN PRTMP_ADAPTER pAd,
953 IN MLME_QUEUE_ELEM *Elem)
955 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
956 CHAR Ssid[MAX_LEN_OF_SSID];
957 CF_PARM CfParm;
958 UCHAR SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0;
959 UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0;
960 USHORT CapabilityInfo, AtimWin, BeaconPeriod;
961 LARGE_INTEGER TimeStamp;
962 USHORT TbttNumToNextWakeUp;
963 UCHAR Erp;
964 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
965 UCHAR SupRateLen, ExtRateLen;
966 UCHAR CkipFlag;
967 USHORT LenVIE;
968 UCHAR AironetCellPowerLimit;
969 EDCA_PARM EdcaParm;
970 QBSS_LOAD_PARM QbssLoad;
971 QOS_CAPABILITY_PARM QosCapability;
972 ULONG RalinkIe;
973 // New for WPA security suites
974 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
975 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
976 HT_CAPABILITY_IE HtCapability;
977 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
978 UCHAR HtCapabilityLen, PreNHtCapabilityLen;
979 UCHAR AddHtInfoLen;
980 UCHAR NewExtChannelOffset = 0xff;
982 if (!(INFRA_ON(pAd) || ADHOC_ON(pAd)
984 return;
986 // Init Variable IE structure
987 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
988 pVIE->Length = 0;
989 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
990 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
992 if (PeerBeaconAndProbeRspSanity(pAd,
993 Elem->Msg,
994 Elem->MsgLen,
995 Elem->Channel,
996 Addr2,
997 Bssid,
998 Ssid,
999 &SsidLen,
1000 &BssType,
1001 &BeaconPeriod,
1002 &Channel,
1003 &NewChannel,
1004 &TimeStamp,
1005 &CfParm,
1006 &AtimWin,
1007 &CapabilityInfo,
1008 &Erp,
1009 &DtimCount,
1010 &DtimPeriod,
1011 &BcastFlag,
1012 &MessageToMe,
1013 SupRate,
1014 &SupRateLen,
1015 ExtRate,
1016 &ExtRateLen,
1017 &CkipFlag,
1018 &AironetCellPowerLimit,
1019 &EdcaParm,
1020 &QbssLoad,
1021 &QosCapability,
1022 &RalinkIe,
1023 &HtCapabilityLen,
1024 &PreNHtCapabilityLen,
1025 &HtCapability,
1026 &AddHtInfoLen,
1027 &AddHtInfo,
1028 &NewExtChannelOffset,
1029 &LenVIE,
1030 pVIE))
1032 BOOLEAN is_my_bssid, is_my_ssid;
1033 ULONG Bssidx, Now;
1034 BSS_ENTRY *pBss;
1035 CHAR RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1037 is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE;
1038 is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE;
1041 // ignore BEACON not for my SSID
1042 if ((! is_my_ssid) && (! is_my_bssid))
1043 return;
1045 // It means STA waits disassoc completely from this AP, ignores this beacon.
1046 if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC)
1047 return;
1049 // Copy Control channel for this BSSID.
1050 if (AddHtInfoLen != 0)
1051 Channel = AddHtInfo.ControlChan;
1053 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
1054 HtCapabilityLen = SIZE_HT_CAP_IE;
1057 // Housekeeping "SsidBssTab" table for later-on ROAMing usage.
1059 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1060 if (Bssidx == BSS_NOT_FOUND)
1062 // discover new AP of this network, create BSS entry
1063 Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1064 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,
1065 &HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel,
1066 RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability,
1067 &QbssLoad, LenVIE, pVIE);
1068 if (Bssidx == BSS_NOT_FOUND) // return if BSS table full
1069 return;
1071 NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4);
1072 NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
1073 NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
1079 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
1081 // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
1082 // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
1083 AsicSwitchChannel(pAd, 1, FALSE);
1084 AsicLockChannel(pAd, 1);
1085 LinkDown(pAd, FALSE);
1086 MlmeQueueInit(&pAd->Mlme.Queue);
1087 BssTableInit(&pAd->ScanTab);
1088 RTMPusecDelay(1000000); // use delay to prevent STA do reassoc
1090 // channel sanity check
1091 for (index = 0 ; index < pAd->ChannelListNum; index++)
1093 if (pAd->ChannelList[index].Channel == NewChannel)
1095 pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
1096 pAd->CommonCfg.Channel = NewChannel;
1097 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1098 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1099 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
1100 break;
1104 if (index >= pAd->ChannelListNum)
1106 DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1110 // if the ssid matched & bssid unmatched, we should select the bssid with large value.
1111 // This might happened when two STA start at the same time
1112 if ((! is_my_bssid) && ADHOC_ON(pAd))
1114 INT i;
1116 // Add the safeguard against the mismatch of adhoc wep status
1117 if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus)
1119 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Not matched wep status %d %d\n", pAd->StaCfg.WepStatus, pAd->ScanTab.BssEntry[Bssidx].WepStatus));
1120 DBGPRINT(RT_DEBUG_TRACE, ("bssid=%s\n", pAd->ScanTab.BssEntry[Bssidx].Bssid));
1121 return;
1124 // collapse into the ADHOC network which has bigger BSSID value.
1125 for (i = 0; i < 6; i++)
1127 if (Bssid[i] > pAd->CommonCfg.Bssid[i])
1129 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n",
1130 Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
1131 AsicDisableSync(pAd);
1132 COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid);
1133 AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1134 MakeIbssBeacon(pAd); // re-build BEACON frame
1135 AsicEnableIbssSync(pAd); // copy BEACON frame to on-chip memory
1136 is_my_bssid = TRUE;
1137 break;
1139 else if (Bssid[i] < pAd->CommonCfg.Bssid[i])
1140 break;
1145 NdisGetSystemUpTime(&Now);
1146 pBss = &pAd->ScanTab.BssEntry[Bssidx];
1147 pBss->Rssi = RealRssi; // lastest RSSI
1148 pBss->LastBeaconRxTime = Now; // last RX timestamp
1151 // BEACON from my BSSID - either IBSS or INFRA network
1153 if (is_my_bssid)
1155 RXWI_STRUC RxWI;
1157 pAd->StaCfg.DtimCount = DtimCount;
1158 pAd->StaCfg.DtimPeriod = DtimPeriod;
1159 pAd->StaCfg.LastBeaconRxTime = Now;
1162 RxWI.RSSI0 = Elem->Rssi0;
1163 RxWI.RSSI1 = Elem->Rssi1;
1164 RxWI.RSSI2 = Elem->Rssi2;
1166 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI);
1167 if (AironetCellPowerLimit != 0xFF)
1170 // We get the Cisco (ccx) "TxPower Limit" required
1171 // Changed to appropriate TxPower Limit for Ciso Compatible Extensions
1173 ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
1175 else
1178 // AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist.
1179 // Used the default TX Power Percentage, that set from UI.
1181 pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
1184 #ifdef RT2860
1185 // at least one 11b peer joined. downgrade the MaxTxRate to 11Mbps
1186 // after last 11b peer left for several seconds, we'll auto switch back to 11G rate
1187 // in MlmePeriodicExec()
1188 #endif
1189 if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo)))
1191 #ifdef RT2860
1192 BOOLEAN bRestart;
1193 BOOLEAN bnRestart;
1195 bRestart = FALSE;
1196 bnRestart = FALSE;
1200 if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.MaxTxRate > RATE_11))
1202 if (pAd->StaCfg.AdhocBOnlyJoined == FALSE)
1204 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11b peer joined. down-grade to 11b TX rates \n"));
1205 bRestart = TRUE;
1206 NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1207 pAd->StaActive.SupRateLen = SupRateLen;
1208 NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
1209 pAd->StaActive.ExtRateLen = ExtRateLen;
1210 pAd->StaCfg.AdhocBOnlyJoined = TRUE;
1211 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
1212 AsicSetEdcaParm(pAd, NULL);
1215 // this timestamp is for MlmePeriodicExec() to check if all 11B peers have left
1216 pAd->StaCfg.Last11bBeaconRxTime = Now;
1217 break;
1220 // Update Ht Phy.
1221 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
1223 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
1224 !pAd->StaCfg.AdhocBGJoined &&
1225 !pAd->StaCfg.AdhocBOnlyJoined)
1226 AdhocTurnOnQos(pAd);
1228 // Handle rate switch issue when Adhoc mode
1229 if ((SupRateLen+ExtRateLen >= 8) && (HtCapability.MCSSet[0] == 0) && (HtCapability.MCSSet[1] == 0))
1231 if (pAd->StaCfg.AdhocBGJoined == FALSE)
1233 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11g peer joined. down-grade to 11g TX rates \n"));
1234 bRestart = TRUE;
1235 NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1236 pAd->StaActive.SupRateLen = SupRateLen;
1237 NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
1238 pAd->StaActive.ExtRateLen = ExtRateLen;
1239 pAd->StaCfg.AdhocBGJoined = TRUE;
1240 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
1241 AsicSetEdcaParm(pAd, NULL);
1244 // this timestamp is for MlmePeriodicExec() to check if all 11g peers have left
1245 pAd->StaCfg.Last11gBeaconRxTime = Now;
1246 break;
1248 else if (!pAd->StaCfg.AdhocBGJoined &&
1249 !pAd->StaCfg.AdhocBOnlyJoined &&
1250 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) &&
1251 (HtCapability.HtCapInfo.ChannelWidth == BW_20))
1253 if (pAd->StaCfg.Adhoc20NJoined == FALSE)
1255 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
1257 pAd->StaCfg.Adhoc20NJoined = TRUE;
1258 NdisMoveMemory(&pAd->MlmeAux.HtCapability, &HtCapability, SIZE_HT_CAP_IE);
1259 if (AddHtInfoLen != 0)
1260 NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, AddHtInfoLen);
1261 NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16);
1263 RTMPCheckHt(pAd, Elem->Wcid, &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo);
1264 COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
1265 pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
1266 bRestart = TRUE;
1267 bnRestart = TRUE;
1269 // this timestamp is for MlmePeriodicExec() to check if all 20MHz N peers have left
1270 pAd->StaCfg.Last20NBeaconRxTime = Now;
1274 else
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 else if ((bRestart == TRUE) && (bnRestart == TRUE))
1290 MlmeUpdateTxRates(pAd, FALSE, BSS0);
1291 MlmeUpdateHtTxRates(pAd, BSS0);
1292 MakeIbssBeacon(pAd); // re-build BEACON frame
1293 AsicEnableIbssSync(pAd); // copy to on-chip memory
1296 // At least another peer in this IBSS, declare MediaState as CONNECTED
1297 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1299 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1301 pAd->IndicateMediaState = NdisMediaStateConnected;
1302 RTMP_IndicateMediaState(pAd);
1303 pAd->ExtraInfo = GENERAL_LINK_UP;
1304 AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1306 // 2003/03/12 - john
1307 // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that
1308 // "site survey" result should always include the current connected network.
1310 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1311 if (Bssidx == BSS_NOT_FOUND)
1313 Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1314 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
1315 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0,
1316 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
1318 DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n"));
1321 // Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon.
1322 // To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station.
1323 if (ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID))
1325 UCHAR idx;
1326 MAC_TABLE_ENTRY *pEntry;
1328 // look up the existing table
1329 pEntry = MacTableLookup(pAd, Addr2);
1330 if (pEntry == NULL)
1332 // Another adhoc joining, add to our MAC table.
1333 pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE);
1334 if (pEntry)
1336 pEntry->Sst = SST_ASSOC;
1337 idx = pAd->StaCfg.DefaultKeyId;
1338 // After InsertEntry, Write to ASIC on-chip table.
1339 RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry);
1340 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));
1342 pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word;
1343 if (HtCapabilityLen <= 0)
1345 pEntry->HTPhyMode.field.STBC = 0;
1346 pEntry->HTPhyMode.field.BW = 0;
1347 pEntry->HTPhyMode.field.ShortGI = 0;
1348 if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.Channel <= 14))
1350 pEntry->HTPhyMode.field.MODE = MODE_CCK;
1352 else
1354 pEntry->HTPhyMode.field.MODE = MODE_OFDM;
1356 MlmeUpdateTxRates(pAd, FALSE, 0);
1358 else
1360 MlmeUpdateTxRates(pAd, FALSE, 0);
1361 MlmeUpdateHtTxRates(pAd, BSS0);
1365 union iwreq_data wrqu;
1366 wext_notify_event_assoc(pAd);
1368 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1369 memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
1370 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1376 #endif /* RT2860 */
1377 #ifdef RT2870
1378 UCHAR MaxSupportedRateIn500Kbps = 0;
1379 UCHAR idx;
1380 MAC_TABLE_ENTRY *pEntry;
1382 // supported rates array may not be sorted. sort it and find the maximum rate
1383 for (idx=0; idx<SupRateLen; idx++)
1385 if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f))
1386 MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f;
1389 for (idx=0; idx<ExtRateLen; idx++)
1391 if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f))
1392 MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f;
1395 // look up the existing table
1396 pEntry = MacTableLookup(pAd, Addr2);
1398 // Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon.
1399 // To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station.
1400 if ((ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID)) ||
1401 (pEntry && ((pEntry->LastBeaconRxTime + ADHOC_ENTRY_BEACON_LOST_TIME) < Now)))
1403 if (pEntry == NULL)
1404 // Another adhoc joining, add to our MAC table.
1405 pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE);
1407 if (StaAddMacTableEntry(pAd, pEntry, MaxSupportedRateIn500Kbps, &HtCapability, HtCapabilityLen, CapabilityInfo) == FALSE)
1409 DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n"));
1410 return;
1413 if (pEntry &&
1414 (Elem->Wcid == RESERVED_WCID))
1416 idx = pAd->StaCfg.DefaultKeyId;
1417 RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry);
1421 if (pEntry && pEntry->ValidAsCLI)
1422 pEntry->LastBeaconRxTime = Now;
1424 // At least another peer in this IBSS, declare MediaState as CONNECTED
1425 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1427 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1429 pAd->IndicateMediaState = NdisMediaStateConnected;
1430 RTMP_IndicateMediaState(pAd);
1431 pAd->ExtraInfo = GENERAL_LINK_UP;
1432 AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1434 // 2003/03/12 - john
1435 // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that
1436 // "site survey" result should always include the current connected network.
1438 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1439 if (Bssidx == BSS_NOT_FOUND)
1441 Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1442 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
1443 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0,
1444 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
1446 DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n"));
1448 #endif /* RT2870 */
1451 if (INFRA_ON(pAd))
1453 BOOLEAN bUseShortSlot, bUseBGProtection;
1455 // decide to use/change to -
1456 // 1. long slot (20 us) or short slot (9 us) time
1457 // 2. turn on/off RTS/CTS and/or CTS-to-self protection
1458 // 3. short preamble
1460 //bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo);
1461 bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo);
1462 if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))
1463 AsicSetSlotTime(pAd, bUseShortSlot);
1465 bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || // always use
1466 ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp));
1468 if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP
1469 bUseBGProtection = FALSE;
1471 if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
1473 if (bUseBGProtection)
1475 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1476 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1478 else
1480 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1481 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1484 DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection));
1487 // check Ht protection mode. and adhere to the Non-GF device indication by AP.
1488 if ((AddHtInfoLen != 0) &&
1489 ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) ||
1490 (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent)))
1492 pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent;
1493 pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode;
1494 if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)
1496 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE);
1498 else
1499 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1501 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode));
1504 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) &&
1505 ERP_IS_USE_BARKER_PREAMBLE(Erp))
1507 MlmeSetTxPreamble(pAd, Rt802_11PreambleLong);
1508 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n"));
1511 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1512 (EdcaParm.bValid == TRUE) &&
1513 (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount))
1515 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n",
1516 pAd->CommonCfg.APEdcaParm.EdcaUpdateCount,
1517 EdcaParm.EdcaUpdateCount));
1518 AsicSetEdcaParm(pAd, &EdcaParm);
1521 // copy QOS related information
1522 NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
1523 NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
1526 // only INFRASTRUCTURE mode support power-saving feature
1527 if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave))
1529 UCHAR FreeNumber;
1530 // 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL
1531 // 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE
1532 // 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE
1533 // 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE
1534 // 5. otherwise, put PHY back to sleep to save battery.
1535 if (MessageToMe)
1537 #ifdef RT2860
1538 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1540 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1542 #endif
1543 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable &&
1544 pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO)
1546 pAd->CommonCfg.bNeedSendTriggerFrame = TRUE;
1548 else
1549 RT28XX_PS_POLL_ENQUEUE(pAd);
1551 else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM))
1553 #ifdef RT2860
1554 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1556 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1558 #endif
1560 else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) ||
1561 (pAd->TxSwQueue[QID_AC_BE].Number != 0) ||
1562 (pAd->TxSwQueue[QID_AC_VI].Number != 0) ||
1563 (pAd->TxSwQueue[QID_AC_VO].Number != 0) ||
1564 (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1565 (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1566 (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1567 (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1568 (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS))
1570 // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme
1571 // can we cheat here (i.e. just check MGMT & AC_BE) for better performance?
1572 #ifdef RT2860
1573 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1575 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1577 #endif
1579 else
1581 USHORT NextDtim = DtimCount;
1583 if (NextDtim == 0)
1584 NextDtim = DtimPeriod;
1586 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
1587 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
1588 TbttNumToNextWakeUp = NextDtim;
1590 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1592 #ifdef RT2860
1593 // Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode.
1594 RTMP_SET_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
1595 pAd->ThisTbttNumToNextWakeUp = TbttNumToNextWakeUp;
1596 #endif
1597 #ifdef RT2870
1598 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
1599 #endif
1604 // not my BSSID, ignore it
1606 // sanity check fail, ignore this frame
1610 ==========================================================================
1611 Description:
1612 Receive PROBE REQ from remote peer when operating in IBSS mode
1613 ==========================================================================
1615 VOID PeerProbeReqAction(
1616 IN PRTMP_ADAPTER pAd,
1617 IN MLME_QUEUE_ELEM *Elem)
1619 UCHAR Addr2[MAC_ADDR_LEN];
1620 CHAR Ssid[MAX_LEN_OF_SSID];
1621 UCHAR SsidLen;
1622 UCHAR HtLen, AddHtLen, NewExtLen;
1623 HEADER_802_11 ProbeRspHdr;
1624 NDIS_STATUS NStatus;
1625 PUCHAR pOutBuffer = NULL;
1626 ULONG FrameLen = 0;
1627 LARGE_INTEGER FakeTimestamp;
1628 UCHAR DsLen = 1, IbssLen = 2;
1629 UCHAR LocalErpIe[3] = {IE_ERP, 1, 0};
1630 BOOLEAN Privacy;
1631 USHORT CapabilityInfo;
1632 UCHAR RSNIe = IE_WPA;
1634 if (! ADHOC_ON(pAd))
1635 return;
1637 if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen))
1639 if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1641 // allocate and send out ProbeRsp frame
1642 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1643 if (NStatus != NDIS_STATUS_SUCCESS)
1644 return;
1646 //pAd->StaCfg.AtimWin = 0; // ??????
1648 Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
1649 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
1650 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
1651 CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0);
1653 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1654 sizeof(HEADER_802_11), &ProbeRspHdr,
1655 TIMESTAMP_LEN, &FakeTimestamp,
1656 2, &pAd->CommonCfg.BeaconPeriod,
1657 2, &CapabilityInfo,
1658 1, &SsidIe,
1659 1, &pAd->CommonCfg.SsidLen,
1660 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
1661 1, &SupRateIe,
1662 1, &pAd->StaActive.SupRateLen,
1663 pAd->StaActive.SupRateLen, pAd->StaActive.SupRate,
1664 1, &DsIe,
1665 1, &DsLen,
1666 1, &pAd->CommonCfg.Channel,
1667 1, &IbssIe,
1668 1, &IbssLen,
1669 2, &pAd->StaActive.AtimWin,
1670 END_OF_ARGS);
1672 if (pAd->StaActive.ExtRateLen)
1674 ULONG tmp;
1675 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1676 3, LocalErpIe,
1677 1, &ExtRateIe,
1678 1, &pAd->StaActive.ExtRateLen,
1679 pAd->StaActive.ExtRateLen, &pAd->StaActive.ExtRate,
1680 END_OF_ARGS);
1681 FrameLen += tmp;
1684 // If adhoc secruity is set for WPA-None, append the cipher suite IE
1685 if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
1687 ULONG tmp;
1688 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1689 1, &RSNIe,
1690 1, &pAd->StaCfg.RSNIE_Len,
1691 pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
1692 END_OF_ARGS);
1693 FrameLen += tmp;
1696 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1698 ULONG TmpLen;
1699 UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
1700 HtLen = sizeof(pAd->CommonCfg.HtCapability);
1701 AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo);
1702 NewExtLen = 1;
1703 //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame
1704 if (pAd->bBroadComHT == TRUE)
1706 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1707 1, &WpaIe,
1708 4, &BROADCOM[0],
1709 pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
1710 END_OF_ARGS);
1712 else
1714 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1715 1, &HtCapIe,
1716 1, &HtLen,
1717 sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability,
1718 1, &AddHtInfoIe,
1719 1, &AddHtLen,
1720 sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo,
1721 1, &NewExtChanIe,
1722 1, &NewExtLen,
1723 sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset,
1724 END_OF_ARGS);
1726 FrameLen += TmpLen;
1729 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1730 MlmeFreeMemory(pAd, pOutBuffer);
1735 VOID BeaconTimeoutAtJoinAction(
1736 IN PRTMP_ADAPTER pAd,
1737 IN MLME_QUEUE_ELEM *Elem)
1739 USHORT Status;
1740 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n"));
1741 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1742 Status = MLME_REJ_TIMEOUT;
1743 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1747 ==========================================================================
1748 Description:
1749 Scan timeout procedure. basically add channel index by 1 and rescan
1750 ==========================================================================
1752 VOID ScanTimeoutAction(
1753 IN PRTMP_ADAPTER pAd,
1754 IN MLME_QUEUE_ELEM *Elem)
1756 pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel);
1758 // Only one channel scanned for CISCO beacon request
1759 if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) ||
1760 (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) ||
1761 (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) ||
1762 (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD))
1763 pAd->MlmeAux.Channel = 0;
1765 // this routine will stop if pAd->MlmeAux.Channel == 0
1766 ScanNextChannel(pAd);
1770 ==========================================================================
1771 Description:
1772 ==========================================================================
1774 VOID InvalidStateWhenScan(
1775 IN PRTMP_ADAPTER pAd,
1776 IN MLME_QUEUE_ELEM *Elem)
1778 USHORT Status;
1779 DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1780 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1781 Status = MLME_STATE_MACHINE_REJECT;
1782 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
1786 ==========================================================================
1787 Description:
1788 ==========================================================================
1790 VOID InvalidStateWhenJoin(
1791 IN PRTMP_ADAPTER pAd,
1792 IN MLME_QUEUE_ELEM *Elem)
1794 USHORT Status;
1795 DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1796 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1797 Status = MLME_STATE_MACHINE_REJECT;
1798 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1802 ==========================================================================
1803 Description:
1804 ==========================================================================
1806 VOID InvalidStateWhenStart(
1807 IN PRTMP_ADAPTER pAd,
1808 IN MLME_QUEUE_ELEM *Elem)
1810 USHORT Status;
1811 DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1812 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1813 Status = MLME_STATE_MACHINE_REJECT;
1814 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
1818 ==========================================================================
1819 Description:
1821 IRQL = DISPATCH_LEVEL
1823 ==========================================================================
1825 VOID EnqueuePsPoll(
1826 IN PRTMP_ADAPTER pAd)
1828 if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP)
1829 pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE;
1830 MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
1835 ==========================================================================
1836 Description:
1837 ==========================================================================
1839 VOID EnqueueProbeRequest(
1840 IN PRTMP_ADAPTER pAd)
1842 NDIS_STATUS NState;
1843 PUCHAR pOutBuffer;
1844 ULONG FrameLen = 0;
1845 HEADER_802_11 Hdr80211;
1847 DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n"));
1849 NState = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1850 if (NState == NDIS_STATUS_SUCCESS)
1852 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
1854 // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse
1855 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1856 sizeof(HEADER_802_11), &Hdr80211,
1857 1, &SsidIe,
1858 1, &pAd->CommonCfg.SsidLen,
1859 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
1860 1, &SupRateIe,
1861 1, &pAd->StaActive.SupRateLen,
1862 pAd->StaActive.SupRateLen, pAd->StaActive.SupRate,
1863 END_OF_ARGS);
1864 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1865 MlmeFreeMemory(pAd, pOutBuffer);
1870 BOOLEAN ScanRunning(
1871 IN PRTMP_ADAPTER pAd)
1873 return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE;