First Support on Ginger and OMAP TI
[linux-ginger.git] / drivers / staging / rt3090 / sta / sync.c
blob2520e038cb82b2d98e2c3a621fda0d73be41da8f
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
39 #include "../rt_config.h"
42 #define ADHOC_ENTRY_BEACON_LOST_TIME (2*OS_HZ) // 2 sec
45 ==========================================================================
46 Description:
47 The sync state machine,
48 Parameters:
49 Sm - pointer to the state machine
50 Note:
51 the state machine looks like the following
53 ==========================================================================
55 VOID SyncStateMachineInit(
56 IN PRTMP_ADAPTER pAd,
57 IN STATE_MACHINE *Sm,
58 OUT STATE_MACHINE_FUNC Trans[])
60 StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE);
62 // column 1
63 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction);
64 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction);
65 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction);
66 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon);
67 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction);
69 //column 2
70 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
71 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
72 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
73 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction);
74 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction);
76 // column 3
77 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
78 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
79 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
80 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
81 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
82 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction);
84 // timer init
85 RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE);
86 RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE);
90 ==========================================================================
91 Description:
92 Beacon timeout handler, executed in timer thread
94 IRQL = DISPATCH_LEVEL
96 ==========================================================================
98 VOID BeaconTimeout(
99 IN PVOID SystemSpecific1,
100 IN PVOID FunctionContext,
101 IN PVOID SystemSpecific2,
102 IN PVOID SystemSpecific3)
104 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
106 DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n"));
108 // Do nothing if the driver is starting halt state.
109 // This might happen when timer already been fired before cancel timer with mlmehalt
110 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
111 return;
113 #ifdef DOT11_N_SUPPORT
114 if ((pAd->CommonCfg.BBPCurrentBW == BW_40)
117 UCHAR BBPValue = 0;
118 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
119 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
120 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
121 BBPValue &= (~0x18);
122 BBPValue |= 0x10;
123 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
124 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr));
126 #endif // DOT11_N_SUPPORT //
128 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL);
129 RTMP_MLME_HANDLER(pAd);
133 ==========================================================================
134 Description:
135 Scan timeout handler, executed in timer thread
137 IRQL = DISPATCH_LEVEL
139 ==========================================================================
141 VOID ScanTimeout(
142 IN PVOID SystemSpecific1,
143 IN PVOID FunctionContext,
144 IN PVOID SystemSpecific2,
145 IN PVOID SystemSpecific3)
147 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
150 // Do nothing if the driver is starting halt state.
151 // This might happen when timer already been fired before cancel timer with mlmehalt
152 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
153 return;
155 if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL))
157 RTMP_MLME_HANDLER(pAd);
159 else
161 // To prevent SyncMachine.CurrState is SCAN_LISTEN forever.
162 pAd->MlmeAux.Channel = 0;
163 ScanNextChannel(pAd);
164 if (pAd->CommonCfg.bWirelessEvent)
166 RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
172 ==========================================================================
173 Description:
174 MLME SCAN req state machine procedure
175 ==========================================================================
177 VOID MlmeScanReqAction(
178 IN PRTMP_ADAPTER pAd,
179 IN MLME_QUEUE_ELEM *Elem)
181 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0;
182 BOOLEAN TimerCancelled;
183 ULONG Now;
184 USHORT Status;
185 PHEADER_802_11 pHdr80211;
186 PUCHAR pOutBuffer = NULL;
187 NDIS_STATUS NStatus;
189 // Check the total scan tries for one single OID command
190 // If this is the CCX 2.0 Case, skip that!
191 if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
193 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n"));
194 return;
197 // Increase the scan retry counters.
198 pAd->StaCfg.ScanCnt++;
200 #ifdef RTMP_MAC_PCI
201 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) &&
202 (IDLE_ON(pAd)) &&
203 (pAd->StaCfg.bRadio == TRUE) &&
204 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
206 if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE)
208 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
209 AsicCheckCommanOk(pAd, PowerWakeCID);
210 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
211 DBGPRINT(RT_DEBUG_TRACE, ("PSM - Issue Wake up command \n"));
213 else
215 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
218 #endif // RTMP_MAC_PCI //
220 // first check the parameter sanity
221 if (MlmeScanReqSanity(pAd,
222 Elem->Msg,
223 Elem->MsgLen,
224 &BssType,
225 (PCHAR)Ssid,
226 &SsidLen,
227 &ScanType))
230 // Check for channel load and noise hist request
231 // Suspend MSDU only at scan request, not the last two mentioned
232 // Suspend MSDU transmission here
233 RTMPSuspendMsduTransmission(pAd);
236 // To prevent data lost.
237 // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress.
238 // And should send an NULL data with turned PSM bit off to AP, when scan progress done
240 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)))
242 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);
243 if (NStatus == NDIS_STATUS_SUCCESS)
245 pHdr80211 = (PHEADER_802_11) pOutBuffer;
246 MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
247 pHdr80211->Duration = 0;
248 pHdr80211->FC.Type = BTYPE_DATA;
249 pHdr80211->FC.PwrMgmt = PWR_SAVE;
251 // Send using priority queue
252 MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
253 DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n"));
254 MlmeFreeMemory(pAd, pOutBuffer);
255 RTMPusecDelay(5000);
259 NdisGetSystemUpTime(&Now);
260 pAd->StaCfg.LastScanTime = Now;
261 // reset all the timers
262 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
263 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
265 // record desired BSS parameters
266 pAd->MlmeAux.BssType = BssType;
267 pAd->MlmeAux.ScanType = ScanType;
268 pAd->MlmeAux.SsidLen = SsidLen;
269 NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
270 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
272 // start from the first channel
273 pAd->MlmeAux.Channel = FirstChannel(pAd);
275 // Let BBP register at 20MHz to do scan
276 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
277 BBPValue &= (~0x18);
278 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
279 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
280 ScanNextChannel(pAd);
282 else
284 DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n"));
285 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
286 Status = MLME_INVALID_FORMAT;
287 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
292 ==========================================================================
293 Description:
294 MLME JOIN req state machine procedure
295 ==========================================================================
297 VOID MlmeJoinReqAction(
298 IN PRTMP_ADAPTER pAd,
299 IN MLME_QUEUE_ELEM *Elem)
301 UCHAR BBPValue = 0;
302 BSS_ENTRY *pBss;
303 BOOLEAN TimerCancelled;
304 HEADER_802_11 Hdr80211;
305 NDIS_STATUS NStatus;
306 ULONG FrameLen = 0;
307 PUCHAR pOutBuffer = NULL;
308 PUCHAR pSupRate = NULL;
309 UCHAR SupRateLen;
310 PUCHAR pExtRate = NULL;
311 UCHAR ExtRateLen;
312 UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C};
313 UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR);
314 MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg);
316 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx));
318 #ifdef RTMP_MAC_PCI
319 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) &&
320 (IDLE_ON(pAd)) &&
321 (pAd->StaCfg.bRadio == TRUE) &&
322 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
324 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
326 #endif // RTMP_MAC_PCI //
328 // reset all the timers
329 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
330 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
332 pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx];
334 // record the desired SSID & BSSID we're waiting for
335 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid);
337 // If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again.
338 if (pBss->Hidden == 0)
340 RTMPZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
341 NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen);
342 pAd->MlmeAux.SsidLen = pBss->SsidLen;
345 pAd->MlmeAux.BssType = pBss->BssType;
346 pAd->MlmeAux.Channel = pBss->Channel;
347 pAd->MlmeAux.CentralChannel = pBss->CentralChannel;
349 #ifdef EXT_BUILD_CHANNEL_LIST
350 // Country IE of the AP will be evaluated and will be used.
351 if ((pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) &&
352 (pBss->bHasCountryIE == TRUE))
354 NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pBss->CountryString[0], 2);
355 if (pBss->CountryString[2] == 'I')
356 pAd->CommonCfg.Geography = IDOR;
357 else if (pBss->CountryString[2] == 'O')
358 pAd->CommonCfg.Geography = ODOR;
359 else
360 pAd->CommonCfg.Geography = BOTH;
361 BuildChannelListEx(pAd);
363 #endif // EXT_BUILD_CHANNEL_LIST //
365 // Let BBP register at 20MHz to do scan
366 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
367 BBPValue &= (~0x18);
368 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
369 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
371 // switch channel and waiting for beacon timer
372 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
373 AsicLockChannel(pAd, pAd->MlmeAux.Channel);
376 RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT);
380 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
381 (pAd->MlmeAux.Channel > 14) &&
382 RadarChannelCheck(pAd, pAd->MlmeAux.Channel))
383 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
384 || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
385 #endif // CARRIER_DETECTION_SUPPORT //
389 // We can't send any Probe request frame to meet 802.11h.
391 if (pBss->Hidden == 0)
392 break;
396 // send probe request
398 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
399 if (NStatus == NDIS_STATUS_SUCCESS)
401 if (pAd->MlmeAux.Channel <= 14)
403 pSupRate = pAd->CommonCfg.SupRate;
404 SupRateLen = pAd->CommonCfg.SupRateLen;
405 pExtRate = pAd->CommonCfg.ExtRate;
406 ExtRateLen = pAd->CommonCfg.ExtRateLen;
408 else
411 // Overwrite Support Rate, CCK rate are not allowed
413 pSupRate = ASupRate;
414 SupRateLen = ASupRateLen;
415 ExtRateLen = 0;
418 if (pAd->MlmeAux.BssType == BSS_INFRA)
419 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid);
420 else
421 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
423 MakeOutgoingFrame(pOutBuffer, &FrameLen,
424 sizeof(HEADER_802_11), &Hdr80211,
425 1, &SsidIe,
426 1, &pAd->MlmeAux.SsidLen,
427 pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid,
428 1, &SupRateIe,
429 1, &SupRateLen,
430 SupRateLen, pSupRate,
431 END_OF_ARGS);
433 if (ExtRateLen)
435 ULONG Tmp;
436 MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
437 1, &ExtRateIe,
438 1, &ExtRateLen,
439 ExtRateLen, pExtRate,
440 END_OF_ARGS);
441 FrameLen += Tmp;
445 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
446 MlmeFreeMemory(pAd, pOutBuffer);
448 } while (FALSE);
450 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n",
451 pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
453 pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON;
457 ==========================================================================
458 Description:
459 MLME START Request state machine procedure, starting an IBSS
460 ==========================================================================
462 VOID MlmeStartReqAction(
463 IN PRTMP_ADAPTER pAd,
464 IN MLME_QUEUE_ELEM *Elem)
466 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen;
467 BOOLEAN TimerCancelled;
469 // New for WPA security suites
470 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
471 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
472 LARGE_INTEGER TimeStamp;
473 BOOLEAN Privacy;
474 USHORT Status;
476 // Init Variable IE structure
477 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
478 pVIE->Length = 0;
479 TimeStamp.u.LowPart = 0;
480 TimeStamp.u.HighPart = 0;
482 if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, (PCHAR)Ssid, &SsidLen))
484 // reset all the timers
485 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
486 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
489 // Start a new IBSS. All IBSS parameters are decided now....
491 DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n"));
492 pAd->MlmeAux.BssType = BSS_ADHOC;
493 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
494 pAd->MlmeAux.SsidLen = SsidLen;
496 // generate a radom number as BSSID
497 MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid);
498 DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n"));
500 Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
501 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
502 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
503 pAd->MlmeAux.CapabilityInfo = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0);
504 pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod;
505 pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin;
506 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
508 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
509 pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel;
511 pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen;
512 NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
513 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
514 pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen;
515 NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
516 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
517 #ifdef DOT11_N_SUPPORT
518 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
520 RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo);
521 pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE);
522 // Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here.
523 DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n"));
525 else
526 #endif // DOT11_N_SUPPORT //
528 pAd->MlmeAux.HtCapabilityLen = 0;
529 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
530 NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], 16);
532 // temporarily not support QOS in IBSS
533 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
534 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
535 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
537 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
538 AsicLockChannel(pAd, pAd->MlmeAux.Channel);
540 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n",
541 pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
543 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
544 Status = MLME_SUCCESS;
545 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
547 else
549 DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n"));
550 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
551 Status = MLME_INVALID_FORMAT;
552 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
557 ==========================================================================
558 Description:
559 peer sends beacon back when scanning
560 ==========================================================================
562 VOID PeerBeaconAtScanAction(
563 IN PRTMP_ADAPTER pAd,
564 IN MLME_QUEUE_ELEM *Elem)
566 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
567 UCHAR Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel,
568 SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe;
569 CF_PARM CfParm;
570 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
571 PFRAME_802_11 pFrame;
572 LARGE_INTEGER TimeStamp;
573 UCHAR Erp;
574 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
575 UCHAR SupRateLen, ExtRateLen;
576 USHORT LenVIE;
577 UCHAR CkipFlag;
578 UCHAR AironetCellPowerLimit;
579 EDCA_PARM EdcaParm;
580 QBSS_LOAD_PARM QbssLoad;
581 QOS_CAPABILITY_PARM QosCapability;
582 ULONG RalinkIe;
583 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
584 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
585 HT_CAPABILITY_IE HtCapability;
586 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
587 UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
588 UCHAR AddHtInfoLen;
589 UCHAR NewExtChannelOffset = 0xff;
592 // NdisFillMemory(Ssid, MAX_LEN_OF_SSID, 0x00);
593 pFrame = (PFRAME_802_11) Elem->Msg;
594 // Init Variable IE structure
595 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
596 pVIE->Length = 0;
597 #ifdef DOT11_N_SUPPORT
598 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
599 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
600 #endif // DOT11_N_SUPPORT //
602 if (PeerBeaconAndProbeRspSanity(pAd,
603 Elem->Msg,
604 Elem->MsgLen,
605 Elem->Channel,
606 Addr2,
607 Bssid,
608 (PCHAR)Ssid,
609 &SsidLen,
610 &BssType,
611 &BeaconPeriod,
612 &Channel,
613 &NewChannel,
614 &TimeStamp,
615 &CfParm,
616 &AtimWin,
617 &CapabilityInfo,
618 &Erp,
619 &DtimCount,
620 &DtimPeriod,
621 &BcastFlag,
622 &MessageToMe,
623 SupRate,
624 &SupRateLen,
625 ExtRate,
626 &ExtRateLen,
627 &CkipFlag,
628 &AironetCellPowerLimit,
629 &EdcaParm,
630 &QbssLoad,
631 &QosCapability,
632 &RalinkIe,
633 &HtCapabilityLen,
634 &PreNHtCapabilityLen,
635 &HtCapability,
636 &AddHtInfoLen,
637 &AddHtInfo,
638 &NewExtChannelOffset,
639 &LenVIE,
640 pVIE))
642 ULONG Idx;
643 CHAR Rssi = 0;
645 Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
646 if (Idx != BSS_NOT_FOUND)
647 Rssi = pAd->ScanTab.BssEntry[Idx].Rssi;
649 Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
652 #ifdef DOT11_N_SUPPORT
653 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
654 HtCapabilityLen = SIZE_HT_CAP_IE;
655 #endif // DOT11_N_SUPPORT //
657 Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, (PCHAR)Ssid, SsidLen, BssType, BeaconPeriod,
658 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
659 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
660 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
661 #ifdef DOT11_N_SUPPORT
662 #ifdef DOT11N_DRAFT3
663 if (pAd->ChannelList[pAd->CommonCfg.ChannelListIdx].bEffectedChannel == TRUE)
665 UCHAR RegClass;
666 PeerBeaconAndProbeRspSanity2(pAd, Elem->Msg, Elem->MsgLen, &RegClass);
667 TriEventTableSetEntry(pAd, &pAd->CommonCfg.TriggerEventTab, Bssid, &HtCapability, HtCapabilityLen, RegClass, Channel);
669 #endif // DOT11N_DRAFT3 //
670 #endif // DOT11_N_SUPPORT //
671 if (Idx != BSS_NOT_FOUND)
673 NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
674 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
675 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
679 // sanity check fail, ignored
683 ==========================================================================
684 Description:
685 When waiting joining the (I)BSS, beacon received from external
686 ==========================================================================
688 VOID PeerBeaconAtJoinAction(
689 IN PRTMP_ADAPTER pAd,
690 IN MLME_QUEUE_ELEM *Elem)
692 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
693 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe,
694 DtimCount, DtimPeriod, BcastFlag, NewChannel;
695 LARGE_INTEGER TimeStamp;
696 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
697 CF_PARM Cf;
698 BOOLEAN TimerCancelled;
699 UCHAR Erp;
700 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
701 UCHAR SupRateLen, ExtRateLen;
702 UCHAR CkipFlag;
703 USHORT LenVIE;
704 UCHAR AironetCellPowerLimit;
705 EDCA_PARM EdcaParm;
706 QBSS_LOAD_PARM QbssLoad;
707 QOS_CAPABILITY_PARM QosCapability;
708 USHORT Status;
709 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
710 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
711 ULONG RalinkIe;
712 ULONG Idx;
713 HT_CAPABILITY_IE HtCapability;
714 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
715 UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
716 UCHAR AddHtInfoLen;
717 UCHAR NewExtChannelOffset = 0xff;
718 #ifdef DOT11_N_SUPPORT
719 UCHAR CentralChannel;
720 BOOLEAN bAllowNrate = FALSE;
721 #endif // DOT11_N_SUPPORT //
723 // Init Variable IE structure
724 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
725 pVIE->Length = 0;
726 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
727 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
730 if (PeerBeaconAndProbeRspSanity(pAd,
731 Elem->Msg,
732 Elem->MsgLen,
733 Elem->Channel,
734 Addr2,
735 Bssid,
736 (PCHAR)Ssid,
737 &SsidLen,
738 &BssType,
739 &BeaconPeriod,
740 &Channel,
741 &NewChannel,
742 &TimeStamp,
743 &Cf,
744 &AtimWin,
745 &CapabilityInfo,
746 &Erp,
747 &DtimCount,
748 &DtimPeriod,
749 &BcastFlag,
750 &MessageToMe,
751 SupRate,
752 &SupRateLen,
753 ExtRate,
754 &ExtRateLen,
755 &CkipFlag,
756 &AironetCellPowerLimit,
757 &EdcaParm,
758 &QbssLoad,
759 &QosCapability,
760 &RalinkIe,
761 &HtCapabilityLen,
762 &PreNHtCapabilityLen,
763 &HtCapability,
764 &AddHtInfoLen,
765 &AddHtInfo,
766 &NewExtChannelOffset,
767 &LenVIE,
768 pVIE))
770 // Disqualify 11b only adhoc when we are in 11g only adhoc mode
771 if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12))
772 return;
774 // BEACON from desired BSS/IBSS found. We should be able to decide most
775 // BSS parameters here.
776 // Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION?
777 // Do we need to receover back all parameters belonging to previous BSS?
778 // A. Should be not. There's no back-door recover to previous AP. It still need
779 // a new JOIN-AUTH-ASSOC sequence.
780 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid))
782 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel));
783 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
785 // Update RSSI to prevent No signal display when cards first initialized
786 pAd->StaCfg.RssiSample.LastRssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0);
787 pAd->StaCfg.RssiSample.LastRssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1);
788 pAd->StaCfg.RssiSample.LastRssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2);
789 pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0;
790 pAd->StaCfg.RssiSample.AvgRssi0X8 = pAd->StaCfg.RssiSample.AvgRssi0 << 3;
791 pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1;
792 pAd->StaCfg.RssiSample.AvgRssi1X8 = pAd->StaCfg.RssiSample.AvgRssi1 << 3;
793 pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2;
794 pAd->StaCfg.RssiSample.AvgRssi2X8 = pAd->StaCfg.RssiSample.AvgRssi2 << 3;
797 // We need to check if SSID only set to any, then we can record the current SSID.
798 // Otherwise will cause hidden SSID association failed.
800 if (pAd->MlmeAux.SsidLen == 0)
802 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
803 pAd->MlmeAux.SsidLen = SsidLen;
805 else
807 Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel);
809 if (Idx == BSS_NOT_FOUND)
811 CHAR Rssi = 0;
812 Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
813 Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, (CHAR *) Ssid, SsidLen, BssType, BeaconPeriod,
814 &Cf, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
815 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
816 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
817 if (Idx != BSS_NOT_FOUND)
819 NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
820 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
821 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
822 CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo;
825 else
828 // Multiple SSID case, used correct CapabilityInfo
830 CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo;
833 NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN);
834 pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
835 pAd->MlmeAux.BssType = BssType;
836 pAd->MlmeAux.BeaconPeriod = BeaconPeriod;
837 pAd->MlmeAux.Channel = Channel;
838 pAd->MlmeAux.AtimWin = AtimWin;
839 pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod;
840 pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration;
841 pAd->MlmeAux.APRalinkIe = RalinkIe;
843 // Copy AP's supported rate to MlmeAux for creating assoication request
844 // Also filter out not supported rate
845 pAd->MlmeAux.SupRateLen = SupRateLen;
846 NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
847 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
848 pAd->MlmeAux.ExtRateLen = ExtRateLen;
849 NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
850 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
852 NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16);
855 #ifdef DOT11_N_SUPPORT
856 if (((pAd->StaCfg.WepStatus != Ndis802_11WEPEnabled) && (pAd->StaCfg.WepStatus != Ndis802_11Encryption2Enabled))
857 || (pAd->CommonCfg.HT_DisallowTKIP == FALSE))
859 bAllowNrate = TRUE;
862 pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
863 pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen;
865 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
866 // filter out un-supported ht rates
867 if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) &&
868 ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (bAllowNrate)))
870 RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE);
872 // StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability
873 NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16);
874 pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
875 pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE;
876 pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
877 if (PreNHtCapabilityLen > 0)
878 pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE;
879 RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo);
880 // Copy AP Parameter to StaActive. This is also in LinkUp.
881 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n",
882 pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth));
884 if (AddHtInfoLen > 0)
886 CentralChannel = AddHtInfo.ControlChan;
887 // Check again the Bandwidth capability of this AP.
888 if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
890 CentralChannel = AddHtInfo.ControlChan - 2;
892 else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
894 CentralChannel = AddHtInfo.ControlChan + 2;
897 // Check Error .
898 if (pAd->MlmeAux.CentralChannel != CentralChannel)
899 DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel));
901 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, AddHtInfo.ControlChan));
906 else
907 #endif // DOT11_N_SUPPORT //
909 // To prevent error, let legacy AP must have same CentralChannel and Channel.
910 if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0))
911 pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel;
913 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
914 pAd->MlmeAux.NewExtChannelOffset = 0xff;
915 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
916 pAd->MlmeAux.HtCapabilityLen = 0;
917 RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE);
920 RTMPUpdateMlmeRate(pAd);
922 // copy QOS related information
923 if ((pAd->CommonCfg.bWmmCapable)
924 #ifdef DOT11_N_SUPPORT
925 || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
926 #endif // DOT11_N_SUPPORT //
929 NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM));
930 NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
931 NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
933 else
935 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
936 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
937 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
940 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n",
941 pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
943 if (AironetCellPowerLimit != 0xFF)
945 //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power
946 ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
948 else //Used the default TX Power Percentage.
949 pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
951 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
952 Status = MLME_SUCCESS;
953 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
955 // not to me BEACON, ignored
957 // sanity check fail, ignore this frame
961 ==========================================================================
962 Description:
963 receive BEACON from peer
965 IRQL = DISPATCH_LEVEL
967 ==========================================================================
969 VOID PeerBeacon(
970 IN PRTMP_ADAPTER pAd,
971 IN MLME_QUEUE_ELEM *Elem)
973 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
974 CHAR Ssid[MAX_LEN_OF_SSID];
975 CF_PARM CfParm;
976 UCHAR SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0;
977 UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0;
978 USHORT CapabilityInfo, AtimWin, BeaconPeriod;
979 LARGE_INTEGER TimeStamp;
980 USHORT TbttNumToNextWakeUp;
981 UCHAR Erp;
982 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
983 UCHAR SupRateLen, ExtRateLen;
984 UCHAR CkipFlag;
985 USHORT LenVIE;
986 UCHAR AironetCellPowerLimit;
987 EDCA_PARM EdcaParm;
988 QBSS_LOAD_PARM QbssLoad;
989 QOS_CAPABILITY_PARM QosCapability;
990 ULONG RalinkIe;
991 // New for WPA security suites
992 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
993 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
994 HT_CAPABILITY_IE HtCapability;
995 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
996 UCHAR HtCapabilityLen, PreNHtCapabilityLen;
997 UCHAR AddHtInfoLen;
998 UCHAR NewExtChannelOffset = 0xff;
1001 #ifdef RALINK_ATE
1002 if (ATE_ON(pAd))
1004 return;
1006 #endif // RALINK_ATE //
1008 if (!(INFRA_ON(pAd) || ADHOC_ON(pAd)
1010 return;
1012 // Init Variable IE structure
1013 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
1014 pVIE->Length = 0;
1015 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
1016 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
1018 if (PeerBeaconAndProbeRspSanity(pAd,
1019 Elem->Msg,
1020 Elem->MsgLen,
1021 Elem->Channel,
1022 Addr2,
1023 Bssid,
1024 Ssid,
1025 &SsidLen,
1026 &BssType,
1027 &BeaconPeriod,
1028 &Channel,
1029 &NewChannel,
1030 &TimeStamp,
1031 &CfParm,
1032 &AtimWin,
1033 &CapabilityInfo,
1034 &Erp,
1035 &DtimCount,
1036 &DtimPeriod,
1037 &BcastFlag,
1038 &MessageToMe,
1039 SupRate,
1040 &SupRateLen,
1041 ExtRate,
1042 &ExtRateLen,
1043 &CkipFlag,
1044 &AironetCellPowerLimit,
1045 &EdcaParm,
1046 &QbssLoad,
1047 &QosCapability,
1048 &RalinkIe,
1049 &HtCapabilityLen,
1050 &PreNHtCapabilityLen,
1051 &HtCapability,
1052 &AddHtInfoLen,
1053 &AddHtInfo,
1054 &NewExtChannelOffset,
1055 &LenVIE,
1056 pVIE))
1058 BOOLEAN is_my_bssid, is_my_ssid;
1059 ULONG Bssidx, Now;
1060 BSS_ENTRY *pBss;
1061 CHAR RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1063 is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE;
1064 is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE;
1067 // ignore BEACON not for my SSID
1068 if ((! is_my_ssid) && (! is_my_bssid))
1069 return;
1071 // It means STA waits disassoc completely from this AP, ignores this beacon.
1072 if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC)
1073 return;
1075 #ifdef DOT11_N_SUPPORT
1076 // Copy Control channel for this BSSID.
1077 if (AddHtInfoLen != 0)
1078 Channel = AddHtInfo.ControlChan;
1080 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
1081 HtCapabilityLen = SIZE_HT_CAP_IE;
1082 #endif // DOT11_N_SUPPORT //
1085 // Housekeeping "SsidBssTab" table for later-on ROAMing usage.
1087 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1088 if (Bssidx == BSS_NOT_FOUND)
1090 // discover new AP of this network, create BSS entry
1091 Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1092 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,
1093 &HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel,
1094 RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability,
1095 &QbssLoad, LenVIE, pVIE);
1096 if (Bssidx == BSS_NOT_FOUND) // return if BSS table full
1097 return;
1099 NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4);
1100 NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
1101 NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
1107 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
1109 // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
1110 // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
1111 AsicSwitchChannel(pAd, 1, FALSE);
1112 AsicLockChannel(pAd, 1);
1113 LinkDown(pAd, FALSE);
1114 MlmeQueueInit(&pAd->Mlme.Queue);
1115 BssTableInit(&pAd->ScanTab);
1116 RTMPusecDelay(1000000); // use delay to prevent STA do reassoc
1118 // channel sanity check
1119 for (index = 0 ; index < pAd->ChannelListNum; index++)
1121 if (pAd->ChannelList[index].Channel == NewChannel)
1123 pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
1124 pAd->CommonCfg.Channel = NewChannel;
1125 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1126 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1127 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
1128 break;
1132 if (index >= pAd->ChannelListNum)
1134 DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1138 // if the ssid matched & bssid unmatched, we should select the bssid with large value.
1139 // This might happened when two STA start at the same time
1140 if ((! is_my_bssid) && ADHOC_ON(pAd))
1142 INT i;
1144 // Add the safeguard against the mismatch of adhoc wep status
1145 if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus)
1147 return;
1150 // collapse into the ADHOC network which has bigger BSSID value.
1151 for (i = 0; i < 6; i++)
1153 if (Bssid[i] > pAd->CommonCfg.Bssid[i])
1155 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n",
1156 Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
1157 AsicDisableSync(pAd);
1158 COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid);
1159 AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1160 MakeIbssBeacon(pAd); // re-build BEACON frame
1161 AsicEnableIbssSync(pAd); // copy BEACON frame to on-chip memory
1162 is_my_bssid = TRUE;
1163 break;
1165 else if (Bssid[i] < pAd->CommonCfg.Bssid[i])
1166 break;
1171 NdisGetSystemUpTime(&Now);
1172 pBss = &pAd->ScanTab.BssEntry[Bssidx];
1173 pBss->Rssi = RealRssi; // lastest RSSI
1174 pBss->LastBeaconRxTime = Now; // last RX timestamp
1177 // BEACON from my BSSID - either IBSS or INFRA network
1179 if (is_my_bssid)
1181 RXWI_STRUC RxWI;
1183 pAd->StaCfg.DtimCount = DtimCount;
1184 pAd->StaCfg.DtimPeriod = DtimPeriod;
1185 pAd->StaCfg.LastBeaconRxTime = Now;
1188 RxWI.RSSI0 = Elem->Rssi0;
1189 RxWI.RSSI1 = Elem->Rssi1;
1190 RxWI.RSSI2 = Elem->Rssi2;
1192 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI);
1193 if (AironetCellPowerLimit != 0xFF)
1196 // We get the Cisco (ccx) "TxPower Limit" required
1197 // Changed to appropriate TxPower Limit for Ciso Compatible Extensions
1199 ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
1201 else
1204 // AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist.
1205 // Used the default TX Power Percentage, that set from UI.
1207 pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
1210 if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo)))
1212 UCHAR MaxSupportedRateIn500Kbps = 0;
1213 UCHAR idx;
1214 MAC_TABLE_ENTRY *pEntry;
1216 // supported rates array may not be sorted. sort it and find the maximum rate
1217 for (idx=0; idx<SupRateLen; idx++)
1219 if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f))
1220 MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f;
1223 for (idx=0; idx<ExtRateLen; idx++)
1225 if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f))
1226 MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f;
1229 // look up the existing table
1230 pEntry = MacTableLookup(pAd, Addr2);
1232 // Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon.
1233 // To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station.
1234 if ((ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID)) ||
1235 (pEntry && ((pEntry->LastBeaconRxTime + ADHOC_ENTRY_BEACON_LOST_TIME) < Now)))
1237 if (pEntry == NULL)
1238 // Another adhoc joining, add to our MAC table.
1239 pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE);
1241 if (StaAddMacTableEntry(pAd,
1242 pEntry,
1243 MaxSupportedRateIn500Kbps,
1244 &HtCapability,
1245 HtCapabilityLen,
1246 &AddHtInfo,
1247 AddHtInfoLen,
1248 CapabilityInfo) == FALSE)
1250 DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n"));
1251 return;
1254 if (pEntry &&
1255 (Elem->Wcid == RESERVED_WCID))
1257 idx = pAd->StaCfg.DefaultKeyId;
1258 RTMP_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry);
1262 if (pEntry && pEntry->ValidAsCLI)
1263 pEntry->LastBeaconRxTime = Now;
1265 // At least another peer in this IBSS, declare MediaState as CONNECTED
1266 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1268 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1270 pAd->IndicateMediaState = NdisMediaStateConnected;
1271 RTMP_IndicateMediaState(pAd);
1272 pAd->ExtraInfo = GENERAL_LINK_UP;
1273 AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1275 // 2003/03/12 - john
1276 // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that
1277 // "site survey" result should always include the current connected network.
1279 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1280 if (Bssidx == BSS_NOT_FOUND)
1282 Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1283 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
1284 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0,
1285 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
1287 DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n"));
1291 if (INFRA_ON(pAd))
1293 BOOLEAN bUseShortSlot, bUseBGProtection;
1295 // decide to use/change to -
1296 // 1. long slot (20 us) or short slot (9 us) time
1297 // 2. turn on/off RTS/CTS and/or CTS-to-self protection
1298 // 3. short preamble
1300 //bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo);
1301 bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo);
1302 if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))
1303 AsicSetSlotTime(pAd, bUseShortSlot);
1305 bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || // always use
1306 ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp));
1308 if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP
1309 bUseBGProtection = FALSE;
1311 if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
1313 if (bUseBGProtection)
1315 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1316 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1318 else
1320 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1321 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1324 DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection));
1327 #ifdef DOT11_N_SUPPORT
1328 // check Ht protection mode. and adhere to the Non-GF device indication by AP.
1329 if ((AddHtInfoLen != 0) &&
1330 ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) ||
1331 (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent)))
1333 pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent;
1334 pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode;
1335 if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)
1337 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE);
1339 else
1340 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1342 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode));
1344 #endif // DOT11_N_SUPPORT //
1346 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) &&
1347 ERP_IS_USE_BARKER_PREAMBLE(Erp))
1349 MlmeSetTxPreamble(pAd, Rt802_11PreambleLong);
1350 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n"));
1353 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1354 (EdcaParm.bValid == TRUE) &&
1355 (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount))
1357 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n",
1358 pAd->CommonCfg.APEdcaParm.EdcaUpdateCount,
1359 EdcaParm.EdcaUpdateCount));
1360 AsicSetEdcaParm(pAd, &EdcaParm);
1363 // copy QOS related information
1364 NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
1365 NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
1368 // only INFRASTRUCTURE mode support power-saving feature
1369 if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave))
1371 UCHAR FreeNumber;
1372 // 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL
1373 // 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE
1374 // 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE
1375 // 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE
1376 // 5. otherwise, put PHY back to sleep to save battery.
1377 if (MessageToMe)
1379 #ifdef RTMP_MAC_PCI
1380 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1382 // Restore to correct BBP R3 value
1383 if (pAd->Antenna.field.RxPath > 1)
1384 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1385 // Turn clk to 80Mhz.
1387 #endif // RTMP_MAC_PCI //
1388 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable &&
1389 pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO)
1391 pAd->CommonCfg.bNeedSendTriggerFrame = TRUE;
1393 else
1394 RTMP_PS_POLL_ENQUEUE(pAd);
1396 else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM))
1398 #ifdef RTMP_MAC_PCI
1399 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1401 if (pAd->Antenna.field.RxPath > 1)
1402 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1404 #endif // RTMP_MAC_PCI //
1406 else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) ||
1407 (pAd->TxSwQueue[QID_AC_BE].Number != 0) ||
1408 (pAd->TxSwQueue[QID_AC_VI].Number != 0) ||
1409 (pAd->TxSwQueue[QID_AC_VO].Number != 0) ||
1410 (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1411 (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1412 (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1413 (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1414 (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS))
1416 // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme
1417 // can we cheat here (i.e. just check MGMT & AC_BE) for better performance?
1418 #ifdef RTMP_MAC_PCI
1419 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1421 if (pAd->Antenna.field.RxPath > 1)
1422 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1424 #endif // RTMP_MAC_PCI //
1426 else
1428 if ((pAd->CommonCfg.bACMAPSDTr[QID_AC_VO]) ||
1429 (pAd->CommonCfg.bACMAPSDTr[QID_AC_VI]) ||
1430 (pAd->CommonCfg.bACMAPSDTr[QID_AC_BK]) ||
1431 (pAd->CommonCfg.bACMAPSDTr[QID_AC_BE]))
1434 WMM Spec v1.0 3.6.2.4,
1435 The WMM STA shall remain awake until it receives a
1436 QoS Data or Null frame addressed to it, with the
1437 EOSP subfield in QoS Control field set to 1.
1439 So we can not sleep here or we will suffer a case:
1441 PS Management Frame -->
1442 Trigger frame -->
1443 Beacon (TIM=0) (Beacon is closer to Trig frame) -->
1444 Station goes to sleep -->
1445 AP delivery queued UAPSD packets -->
1446 Station can NOT receive the reply
1448 Maybe we need a timeout timer to avoid that we do
1449 NOT receive the EOSP frame.
1451 We can not use More Data to check if SP is ended
1452 due to MaxSPLength.
1455 else
1457 USHORT NextDtim = DtimCount;
1460 if (NextDtim == 0)
1461 NextDtim = DtimPeriod;
1463 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
1464 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
1465 TbttNumToNextWakeUp = NextDtim;
1467 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1469 // Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode.
1470 pAd->ThisTbttNumToNextWakeUp = TbttNumToNextWakeUp;
1471 AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp);
1478 // not my BSSID, ignore it
1480 // sanity check fail, ignore this frame
1484 ==========================================================================
1485 Description:
1486 Receive PROBE REQ from remote peer when operating in IBSS mode
1487 ==========================================================================
1489 VOID PeerProbeReqAction(
1490 IN PRTMP_ADAPTER pAd,
1491 IN MLME_QUEUE_ELEM *Elem)
1493 UCHAR Addr2[MAC_ADDR_LEN];
1494 CHAR Ssid[MAX_LEN_OF_SSID];
1495 UCHAR SsidLen;
1496 #ifdef DOT11_N_SUPPORT
1497 UCHAR HtLen, AddHtLen, NewExtLen;
1498 #endif // DOT11_N_SUPPORT //
1499 HEADER_802_11 ProbeRspHdr;
1500 NDIS_STATUS NStatus;
1501 PUCHAR pOutBuffer = NULL;
1502 ULONG FrameLen = 0;
1503 LARGE_INTEGER FakeTimestamp;
1504 UCHAR DsLen = 1, IbssLen = 2;
1505 UCHAR LocalErpIe[3] = {IE_ERP, 1, 0};
1506 BOOLEAN Privacy;
1507 USHORT CapabilityInfo;
1508 UCHAR RSNIe = IE_WPA;
1510 if (! ADHOC_ON(pAd))
1511 return;
1513 if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen))
1515 if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1517 // allocate and send out ProbeRsp frame
1518 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1519 if (NStatus != NDIS_STATUS_SUCCESS)
1520 return;
1522 //pAd->StaCfg.AtimWin = 0; // ??????
1524 Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
1525 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
1526 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
1527 CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0);
1529 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1530 sizeof(HEADER_802_11), &ProbeRspHdr,
1531 TIMESTAMP_LEN, &FakeTimestamp,
1532 2, &pAd->CommonCfg.BeaconPeriod,
1533 2, &CapabilityInfo,
1534 1, &SsidIe,
1535 1, &pAd->CommonCfg.SsidLen,
1536 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
1537 1, &SupRateIe,
1538 1, &pAd->StaActive.SupRateLen,
1539 pAd->StaActive.SupRateLen, pAd->StaActive.SupRate,
1540 1, &DsIe,
1541 1, &DsLen,
1542 1, &pAd->CommonCfg.Channel,
1543 1, &IbssIe,
1544 1, &IbssLen,
1545 2, &pAd->StaActive.AtimWin,
1546 END_OF_ARGS);
1548 if (pAd->StaActive.ExtRateLen)
1550 ULONG tmp;
1551 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1552 3, LocalErpIe,
1553 1, &ExtRateIe,
1554 1, &pAd->StaActive.ExtRateLen,
1555 pAd->StaActive.ExtRateLen, &pAd->StaActive.ExtRate,
1556 END_OF_ARGS);
1557 FrameLen += tmp;
1560 // If adhoc secruity is set for WPA-None, append the cipher suite IE
1561 if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
1563 ULONG tmp;
1564 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1565 1, &RSNIe,
1566 1, &pAd->StaCfg.RSNIE_Len,
1567 pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
1568 END_OF_ARGS);
1569 FrameLen += tmp;
1571 #ifdef DOT11_N_SUPPORT
1572 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1574 ULONG TmpLen;
1575 UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
1576 HtLen = sizeof(pAd->CommonCfg.HtCapability);
1577 AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo);
1578 NewExtLen = 1;
1579 //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame
1580 if (pAd->bBroadComHT == TRUE)
1582 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1583 1, &WpaIe,
1584 4, &BROADCOM[0],
1585 pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
1586 END_OF_ARGS);
1588 else
1590 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1591 1, &HtCapIe,
1592 1, &HtLen,
1593 sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability,
1594 1, &AddHtInfoIe,
1595 1, &AddHtLen,
1596 sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo,
1597 1, &NewExtChanIe,
1598 1, &NewExtLen,
1599 sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset,
1600 END_OF_ARGS);
1602 FrameLen += TmpLen;
1604 #endif // DOT11_N_SUPPORT //
1605 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1606 MlmeFreeMemory(pAd, pOutBuffer);
1611 VOID BeaconTimeoutAtJoinAction(
1612 IN PRTMP_ADAPTER pAd,
1613 IN MLME_QUEUE_ELEM *Elem)
1615 USHORT Status;
1616 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n"));
1617 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1618 Status = MLME_REJ_TIMEOUT;
1619 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1623 ==========================================================================
1624 Description:
1625 Scan timeout procedure. basically add channel index by 1 and rescan
1626 ==========================================================================
1628 VOID ScanTimeoutAction(
1629 IN PRTMP_ADAPTER pAd,
1630 IN MLME_QUEUE_ELEM *Elem)
1632 pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel);
1634 // Only one channel scanned for CISCO beacon request
1635 if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) ||
1636 (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) ||
1637 (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) ||
1638 (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD))
1639 pAd->MlmeAux.Channel = 0;
1641 // this routine will stop if pAd->MlmeAux.Channel == 0
1642 ScanNextChannel(pAd);
1646 ==========================================================================
1647 Description:
1648 ==========================================================================
1650 VOID InvalidStateWhenScan(
1651 IN PRTMP_ADAPTER pAd,
1652 IN MLME_QUEUE_ELEM *Elem)
1654 USHORT Status;
1655 DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1656 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1657 Status = MLME_STATE_MACHINE_REJECT;
1658 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
1662 ==========================================================================
1663 Description:
1664 ==========================================================================
1666 VOID InvalidStateWhenJoin(
1667 IN PRTMP_ADAPTER pAd,
1668 IN MLME_QUEUE_ELEM *Elem)
1670 USHORT Status;
1671 DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1672 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1673 Status = MLME_STATE_MACHINE_REJECT;
1674 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1678 ==========================================================================
1679 Description:
1680 ==========================================================================
1682 VOID InvalidStateWhenStart(
1683 IN PRTMP_ADAPTER pAd,
1684 IN MLME_QUEUE_ELEM *Elem)
1686 USHORT Status;
1687 DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1688 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1689 Status = MLME_STATE_MACHINE_REJECT;
1690 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
1694 ==========================================================================
1695 Description:
1697 IRQL = DISPATCH_LEVEL
1699 ==========================================================================
1701 VOID EnqueuePsPoll(
1702 IN PRTMP_ADAPTER pAd)
1704 #ifdef RALINK_ATE
1705 if (ATE_ON(pAd))
1707 return;
1709 #endif // RALINK_ATE //
1712 if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP)
1713 pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE;
1714 MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
1719 ==========================================================================
1720 Description:
1721 ==========================================================================
1723 VOID EnqueueProbeRequest(
1724 IN PRTMP_ADAPTER pAd)
1726 NDIS_STATUS NState;
1727 PUCHAR pOutBuffer;
1728 ULONG FrameLen = 0;
1729 HEADER_802_11 Hdr80211;
1731 DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n"));
1733 NState = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1734 if (NState == NDIS_STATUS_SUCCESS)
1736 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
1738 // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse
1739 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1740 sizeof(HEADER_802_11), &Hdr80211,
1741 1, &SsidIe,
1742 1, &pAd->CommonCfg.SsidLen,
1743 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
1744 1, &SupRateIe,
1745 1, &pAd->StaActive.SupRateLen,
1746 pAd->StaActive.SupRateLen, pAd->StaActive.SupRate,
1747 END_OF_ARGS);
1748 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1749 MlmeFreeMemory(pAd, pOutBuffer);
1754 #ifdef DOT11_N_SUPPORT
1755 #ifdef DOT11N_DRAFT3
1756 VOID BuildEffectedChannelList(
1757 IN PRTMP_ADAPTER pAd)
1759 UCHAR EChannel[11];
1760 UCHAR i, j, k;
1761 UCHAR UpperChannel = 0, LowerChannel = 0;
1763 RTMPZeroMemory(EChannel, 11);
1764 i = 0;
1765 // Find upper channel and lower channel.
1766 if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
1768 UpperChannel = pAd->CommonCfg.Channel;
1769 LowerChannel = pAd->CommonCfg.CentralChannel;
1771 else if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
1773 UpperChannel = pAd->CommonCfg.CentralChannel;
1774 LowerChannel = pAd->CommonCfg.Channel;
1776 else
1778 return;
1781 // Record channels that is below lower channel..
1782 if (LowerChannel > 1)
1784 EChannel[0] = LowerChannel - 1;
1785 i = 1;
1786 if (LowerChannel > 2)
1788 EChannel[1] = LowerChannel - 2;
1789 i = 2;
1790 if (LowerChannel > 3)
1792 EChannel[2] = LowerChannel - 3;
1793 i = 3;
1797 // Record channels that is between lower channel and upper channel.
1798 for (k = LowerChannel;k < UpperChannel;k++)
1800 EChannel[i] = k;
1801 i++;
1803 // Record channels that is above upper channel..
1804 if (LowerChannel < 11)
1806 EChannel[i] = UpperChannel + 1;
1807 i++;
1808 if (LowerChannel < 10)
1810 EChannel[i] = LowerChannel + 2;
1811 i++;
1812 if (LowerChannel < 9)
1814 EChannel[i] = LowerChannel + 3;
1815 i++;
1820 for (j = 0;j < i;j++)
1822 for (k = 0;k < pAd->ChannelListNum;k++)
1824 if (pAd->ChannelList[k].Channel == EChannel[j])
1826 pAd->ChannelList[k].bEffectedChannel = TRUE;
1827 DBGPRINT(RT_DEBUG_TRACE,(" EffectedChannel( =%d)\n", EChannel[j]));
1828 break;
1833 #endif // DOT11N_DRAFT3 //
1834 #endif // DOT11_N_SUPPORT //
1836 BOOLEAN ScanRunning(
1837 IN PRTMP_ADAPTER pAd)
1839 return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE;