2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
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. *
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. *
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. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 John 2004-9-3 porting from RT2500
37 #include "../rt_config.h"
39 UCHAR CipherWpaTemplate[] = {
42 0x00, 0x50, 0xf2, 0x01, // oui
43 0x01, 0x00, // Version
44 0x00, 0x50, 0xf2, 0x02, // Multicast
45 0x01, 0x00, // Number of unicast
46 0x00, 0x50, 0xf2, 0x02, // unicast
47 0x01, 0x00, // number of authentication method
48 0x00, 0x50, 0xf2, 0x01 // authentication
51 UCHAR CipherWpa2Template[] = {
54 0x01, 0x00, // Version
55 0x00, 0x0f, 0xac, 0x02, // group cipher, TKIP
56 0x01, 0x00, // number of pairwise
57 0x00, 0x0f, 0xac, 0x02, // unicast
58 0x01, 0x00, // number of authentication method
59 0x00, 0x0f, 0xac, 0x02, // authentication
60 0x00, 0x00, // RSN capability
63 UCHAR Ccx2IeInfo[] = { 0x00, 0x40, 0x96, 0x03, 0x02 };
66 ==========================================================================
68 association state machine init, including state transition and timer init
70 S - pointer to the association state machine
74 ==========================================================================
76 VOID AssocStateMachineInit(IN PRTMP_ADAPTER pAd,
77 IN STATE_MACHINE * S, OUT STATE_MACHINE_FUNC Trans[])
79 StateMachineInit(S, Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG,
80 (STATE_MACHINE_FUNC) Drop, ASSOC_IDLE,
84 StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_ASSOC_REQ,
85 (STATE_MACHINE_FUNC) MlmeAssocReqAction);
86 StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_REASSOC_REQ,
87 (STATE_MACHINE_FUNC) MlmeReassocReqAction);
88 StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ,
89 (STATE_MACHINE_FUNC) MlmeDisassocReqAction);
90 StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ,
91 (STATE_MACHINE_FUNC) PeerDisassocAction);
94 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ,
95 (STATE_MACHINE_FUNC) InvalidStateWhenAssoc);
96 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ,
97 (STATE_MACHINE_FUNC) InvalidStateWhenReassoc);
98 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ,
100 InvalidStateWhenDisassociate);
101 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ,
102 (STATE_MACHINE_FUNC) PeerDisassocAction);
103 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP,
104 (STATE_MACHINE_FUNC) PeerAssocRspAction);
106 // Patch 3Com AP MOde:3CRWE454G72
107 // We send Assoc request frame to this AP, it always send Reassoc Rsp not Associate Rsp.
109 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP,
110 (STATE_MACHINE_FUNC) PeerAssocRspAction);
111 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_ASSOC_TIMEOUT,
112 (STATE_MACHINE_FUNC) AssocTimeoutAction);
115 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ,
116 (STATE_MACHINE_FUNC) InvalidStateWhenAssoc);
117 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ,
118 (STATE_MACHINE_FUNC) InvalidStateWhenReassoc);
119 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ,
121 InvalidStateWhenDisassociate);
122 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ,
123 (STATE_MACHINE_FUNC) PeerDisassocAction);
124 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP,
125 (STATE_MACHINE_FUNC) PeerReassocRspAction);
127 // Patch, AP doesn't send Reassociate Rsp frame to Station.
129 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP,
130 (STATE_MACHINE_FUNC) PeerReassocRspAction);
131 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_REASSOC_TIMEOUT,
132 (STATE_MACHINE_FUNC) ReassocTimeoutAction);
135 StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ,
136 (STATE_MACHINE_FUNC) InvalidStateWhenAssoc);
137 StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ,
138 (STATE_MACHINE_FUNC) InvalidStateWhenReassoc);
139 StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ,
141 InvalidStateWhenDisassociate);
142 StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ,
143 (STATE_MACHINE_FUNC) PeerDisassocAction);
144 StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_DISASSOC_TIMEOUT,
145 (STATE_MACHINE_FUNC) DisassocTimeoutAction);
147 // initialize the timer
148 RTMPInitTimer(pAd, &pAd->MlmeAux.AssocTimer,
149 GET_TIMER_FUNCTION(AssocTimeout), pAd, FALSE);
150 RTMPInitTimer(pAd, &pAd->MlmeAux.ReassocTimer,
151 GET_TIMER_FUNCTION(ReassocTimeout), pAd, FALSE);
152 RTMPInitTimer(pAd, &pAd->MlmeAux.DisassocTimer,
153 GET_TIMER_FUNCTION(DisassocTimeout), pAd, FALSE);
157 ==========================================================================
159 Association timeout procedure. After association timeout, this function
160 will be called and it will put a message into the MLME queue
162 Standard timer parameters
164 IRQL = DISPATCH_LEVEL
166 ==========================================================================
168 VOID AssocTimeout(IN PVOID SystemSpecific1,
169 IN PVOID FunctionContext,
170 IN PVOID SystemSpecific2, IN PVOID SystemSpecific3)
172 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext;
174 // Do nothing if the driver is starting halt state.
175 // This might happen when timer already been fired before cancel timer with mlmehalt
177 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
180 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_ASSOC_TIMEOUT, 0, NULL);
181 RTMP_MLME_HANDLER(pAd);
185 ==========================================================================
187 Reassociation timeout procedure. After reassociation timeout, this
188 function will be called and put a message into the MLME queue
190 Standard timer parameters
192 IRQL = DISPATCH_LEVEL
194 ==========================================================================
196 VOID ReassocTimeout(IN PVOID SystemSpecific1,
197 IN PVOID FunctionContext,
198 IN PVOID SystemSpecific2, IN PVOID SystemSpecific3)
200 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext;
202 // Do nothing if the driver is starting halt state.
203 // This might happen when timer already been fired before cancel timer with mlmehalt
205 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
208 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_REASSOC_TIMEOUT, 0, NULL);
209 RTMP_MLME_HANDLER(pAd);
213 ==========================================================================
215 Disassociation timeout procedure. After disassociation timeout, this
216 function will be called and put a message into the MLME queue
218 Standard timer parameters
220 IRQL = DISPATCH_LEVEL
222 ==========================================================================
224 VOID DisassocTimeout(IN PVOID SystemSpecific1,
225 IN PVOID FunctionContext,
226 IN PVOID SystemSpecific2, IN PVOID SystemSpecific3)
228 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext;
230 // Do nothing if the driver is starting halt state.
231 // This might happen when timer already been fired before cancel timer with mlmehalt
233 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
236 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_DISASSOC_TIMEOUT, 0, NULL);
237 RTMP_MLME_HANDLER(pAd);
241 ==========================================================================
243 mlme assoc req handling procedure
245 Adapter - Adapter pointer
246 Elem - MLME Queue Element
248 the station has been authenticated and the following information is stored in the config
250 -# supported rates and their length
251 -# listen interval (Adapter->StaCfg.default_listen_count)
252 -# Transmit power (Adapter->StaCfg.tx_power)
254 -# An association request frame is generated and sent to the air
255 -# Association timer starts
256 -# Association state -> ASSOC_WAIT_RSP
258 IRQL = DISPATCH_LEVEL
260 ==========================================================================
262 VOID MlmeAssocReqAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
265 HEADER_802_11 AssocHdr;
267 { IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01,
271 USHORT CapabilityInfo;
272 BOOLEAN TimerCancelled;
273 PUCHAR pOutBuffer = NULL;
280 // Block all authentication request durning WPA block period
281 if (pAd->StaCfg.bBlockAssoc == TRUE) {
282 DBGPRINT(RT_DEBUG_TRACE,
283 ("ASSOC - Block Assoc request durning WPA block period!\n"));
284 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
285 Status = MLME_STATE_MACHINE_REJECT;
286 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2,
289 // check sanity first
290 else if (MlmeAssocReqSanity
291 (pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo,
292 &Timeout, &ListenIntv)) {
293 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled);
294 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr);
296 // Get an unused nonpaged memory
297 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
298 if (NStatus != NDIS_STATUS_SUCCESS) {
299 DBGPRINT(RT_DEBUG_TRACE,
300 ("ASSOC - MlmeAssocReqAction() allocate memory failed \n"));
301 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
302 Status = MLME_FAIL_NO_RESOURCE;
303 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
304 MT2_ASSOC_CONF, 2, &Status);
307 // Add by James 03/06/27
308 pAd->StaCfg.AssocInfo.Length =
309 sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
310 // Association don't need to report MAC address
311 pAd->StaCfg.AssocInfo.AvailableRequestFixedIEs =
312 NDIS_802_11_AI_REQFI_CAPABILITIES |
313 NDIS_802_11_AI_REQFI_LISTENINTERVAL;
314 pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities =
316 pAd->StaCfg.AssocInfo.RequestFixedIEs.ListenInterval =
318 // Only reassociate need this
319 //COPY_MAC_ADDR(pAd->StaCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr);
320 pAd->StaCfg.AssocInfo.OffsetRequestIEs =
321 sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
323 NdisZeroMemory(pAd->StaCfg.ReqVarIEs, MAX_VIE_LEN);
326 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SsidIe,
329 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset,
330 &pAd->MlmeAux.SsidLen, 1);
332 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset,
333 pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
334 VarIesOffset += pAd->MlmeAux.SsidLen;
336 // Second add Supported rates
337 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SupRateIe,
340 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset,
341 &pAd->MlmeAux.SupRateLen, 1);
343 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset,
344 pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen);
345 VarIesOffset += pAd->MlmeAux.SupRateLen;
348 if ((pAd->CommonCfg.Channel > 14) &&
349 (pAd->CommonCfg.bIEEE80211H == TRUE))
350 CapabilityInfo |= 0x0100;
352 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send ASSOC request...\n"));
353 MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr,
356 // Build basic frame first
357 MakeOutgoingFrame(pOutBuffer, &FrameLen,
358 sizeof(HEADER_802_11), &AssocHdr,
362 1, &pAd->MlmeAux.SsidLen,
363 pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid,
365 1, &pAd->MlmeAux.SupRateLen,
366 pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
369 if (pAd->MlmeAux.ExtRateLen != 0) {
370 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
372 1, &pAd->MlmeAux.ExtRateLen,
373 pAd->MlmeAux.ExtRateLen,
374 pAd->MlmeAux.ExtRate, END_OF_ARGS);
378 if ((pAd->MlmeAux.HtCapabilityLen > 0)
379 && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) {
382 UCHAR BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 };
383 if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) {
384 HtLen = SIZE_HT_CAP_IE + 4;
385 MakeOutgoingFrame(pOutBuffer + FrameLen,
386 &TmpLen, 1, &WpaIe, 1, &HtLen,
388 pAd->MlmeAux.HtCapabilityLen,
389 &pAd->MlmeAux.HtCapability,
392 MakeOutgoingFrame(pOutBuffer + FrameLen,
393 &TmpLen, 1, &HtCapIe, 1,
394 &pAd->MlmeAux.HtCapabilityLen,
395 pAd->MlmeAux.HtCapabilityLen,
396 &pAd->MlmeAux.HtCapability,
401 // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION
402 // Case I: (Aggregation + Piggy-Back)
403 // 1. user enable aggregation, AND
404 // 2. Mac support piggy-back
405 // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON
406 // Case II: (Aggregation)
407 // 1. user enable aggregation, AND
408 // 2. AP annouces it's AGGREGATION-capable in BEACON
409 if (pAd->CommonCfg.bAggregationCapable) {
410 if ((pAd->CommonCfg.bPiggyBackCapable)
411 && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) {
414 { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43,
415 0x03, 0x00, 0x00, 0x00 };
416 MakeOutgoingFrame(pOutBuffer + FrameLen,
417 &TmpLen, 9, RalinkIe,
420 } else if (pAd->MlmeAux.APRalinkIe & 0x00000001) {
423 { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43,
424 0x01, 0x00, 0x00, 0x00 };
425 MakeOutgoingFrame(pOutBuffer + FrameLen,
426 &TmpLen, 9, RalinkIe,
433 { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06,
435 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 9,
436 RalinkIe, END_OF_ARGS);
440 if (pAd->MlmeAux.APEdcaParm.bValid) {
441 if (pAd->CommonCfg.bAPSDCapable
442 && pAd->MlmeAux.APEdcaParm.bAPSDCapable) {
443 QBSS_STA_INFO_PARM QosInfo;
445 NdisZeroMemory(&QosInfo,
446 sizeof(QBSS_STA_INFO_PARM));
447 QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE;
448 QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK;
449 QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI;
450 QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO;
451 QosInfo.MaxSPLength =
452 pAd->CommonCfg.MaxSPLength;
453 WmeIe[8] |= *(PUCHAR) & QosInfo;
455 // The Parameter Set Count is set to ¡§0¡¨ in the association request frames
456 // WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f);
459 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
460 9, &WmeIe[0], END_OF_ARGS);
464 // Let WPA(#221) Element ID on the end of this association frame.
465 // Otherwise some AP will fail on parsing Element ID and set status fail on Assoc Rsp.
466 // For example: Put Vendor Specific IE on the front of WPA IE.
467 // This happens on AP (Model No:Linksys WRK54G)
469 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
470 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
471 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
472 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)
475 UCHAR RSNIe = IE_WPA;
477 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
478 || (pAd->StaCfg.AuthMode ==
479 Ndis802_11AuthModeWPA2)) {
483 if ((pAd->StaCfg.WpaSupplicantUP !=
484 WPA_SUPPLICANT_ENABLE)
485 && (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == FALSE))
486 RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode,
487 pAd->StaCfg.WepStatus, BSS0);
489 // Check for WPA PMK cache list
490 if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) {
492 BOOLEAN FoundPMK = FALSE;
493 // Search chched PMKID, append it if existed
494 for (idx = 0; idx < PMKID_NO; idx++) {
497 &pAd->StaCfg.SavedPMK[idx].BSSID,
505 *(PUSHORT) & pAd->StaCfg.RSN_IE[pAd->
509 NdisMoveMemory(&pAd->StaCfg.
513 SavedPMK[idx].PMKID, 16);
514 pAd->StaCfg.RSNIE_Len += 18;
518 if ((pAd->StaCfg.WpaSupplicantUP ==
519 WPA_SUPPLICANT_ENABLE)
520 && (pAd->StaCfg.bRSN_IE_FromWpaSupplicant ==
522 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
523 pAd->StaCfg.RSNIE_Len,
527 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
529 1, &pAd->StaCfg.RSNIE_Len,
530 pAd->StaCfg.RSNIE_Len,
537 if ((pAd->StaCfg.WpaSupplicantUP !=
538 WPA_SUPPLICANT_ENABLE)
539 || (pAd->StaCfg.bRSN_IE_FromWpaSupplicant ==
541 // Append Variable IE
542 NdisMoveMemory(pAd->StaCfg.ReqVarIEs +
543 VarIesOffset, &RSNIe, 1);
545 NdisMoveMemory(pAd->StaCfg.ReqVarIEs +
547 &pAd->StaCfg.RSNIE_Len, 1);
550 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset,
552 pAd->StaCfg.RSNIE_Len);
553 VarIesOffset += pAd->StaCfg.RSNIE_Len;
555 // Set Variable IEs Length
556 pAd->StaCfg.ReqVarIELen = VarIesOffset;
559 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
560 MlmeFreeMemory(pAd, pOutBuffer);
562 RTMPSetTimer(&pAd->MlmeAux.AssocTimer, Timeout);
563 pAd->Mlme.AssocMachine.CurrState = ASSOC_WAIT_RSP;
565 DBGPRINT(RT_DEBUG_TRACE,
566 ("ASSOC - MlmeAssocReqAction() sanity check failed. BUG!!!!!! \n"));
567 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
568 Status = MLME_INVALID_FORMAT;
569 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2,
576 ==========================================================================
578 mlme reassoc req handling procedure
582 -# SSID (Adapter->StaCfg.ssid[])
583 -# BSSID (AP address, Adapter->StaCfg.bssid)
584 -# Supported rates (Adapter->StaCfg.supported_rates[])
585 -# Supported rates length (Adapter->StaCfg.supported_rates_len)
586 -# Tx power (Adapter->StaCfg.tx_power)
588 IRQL = DISPATCH_LEVEL
590 ==========================================================================
592 VOID MlmeReassocReqAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
595 HEADER_802_11 ReassocHdr;
597 { IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01,
599 USHORT CapabilityInfo, ListenIntv;
602 BOOLEAN TimerCancelled;
605 PUCHAR pOutBuffer = NULL;
608 // Block all authentication request durning WPA block period
609 if (pAd->StaCfg.bBlockAssoc == TRUE) {
610 DBGPRINT(RT_DEBUG_TRACE,
611 ("ASSOC - Block ReAssoc request durning WPA block period!\n"));
612 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
613 Status = MLME_STATE_MACHINE_REJECT;
614 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2,
617 // the parameters are the same as the association
618 else if (MlmeAssocReqSanity
619 (pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo,
620 &Timeout, &ListenIntv)) {
621 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled);
623 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
624 if (NStatus != NDIS_STATUS_SUCCESS) {
625 DBGPRINT(RT_DEBUG_TRACE,
626 ("ASSOC - MlmeReassocReqAction() allocate memory failed \n"));
627 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
628 Status = MLME_FAIL_NO_RESOURCE;
629 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
630 MT2_REASSOC_CONF, 2, &Status);
634 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr);
636 // make frame, use bssid as the AP address??
637 DBGPRINT(RT_DEBUG_TRACE,
638 ("ASSOC - Send RE-ASSOC request...\n"));
639 MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0,
641 MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11),
642 &ReassocHdr, 2, &CapabilityInfo, 2,
643 &ListenIntv, MAC_ADDR_LEN, ApAddr, 1, &SsidIe,
644 1, &pAd->MlmeAux.SsidLen,
645 pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, 1,
646 &SupRateIe, 1, &pAd->MlmeAux.SupRateLen,
647 pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
650 if (pAd->MlmeAux.ExtRateLen != 0) {
651 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
653 1, &pAd->MlmeAux.ExtRateLen,
654 pAd->MlmeAux.ExtRateLen,
655 pAd->MlmeAux.ExtRate, END_OF_ARGS);
659 if (pAd->MlmeAux.APEdcaParm.bValid) {
660 if (pAd->CommonCfg.bAPSDCapable
661 && pAd->MlmeAux.APEdcaParm.bAPSDCapable) {
662 QBSS_STA_INFO_PARM QosInfo;
664 NdisZeroMemory(&QosInfo,
665 sizeof(QBSS_STA_INFO_PARM));
666 QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE;
667 QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK;
668 QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI;
669 QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO;
670 QosInfo.MaxSPLength =
671 pAd->CommonCfg.MaxSPLength;
672 WmeIe[8] |= *(PUCHAR) & QosInfo;
675 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
676 9, &WmeIe[0], END_OF_ARGS);
680 if ((pAd->MlmeAux.HtCapabilityLen > 0)
681 && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) {
684 UCHAR BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 };
685 if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) {
686 HtLen = SIZE_HT_CAP_IE + 4;
687 MakeOutgoingFrame(pOutBuffer + FrameLen,
688 &TmpLen, 1, &WpaIe, 1, &HtLen,
690 pAd->MlmeAux.HtCapabilityLen,
691 &pAd->MlmeAux.HtCapability,
694 MakeOutgoingFrame(pOutBuffer + FrameLen,
695 &TmpLen, 1, &HtCapIe, 1,
696 &pAd->MlmeAux.HtCapabilityLen,
697 pAd->MlmeAux.HtCapabilityLen,
698 &pAd->MlmeAux.HtCapability,
703 // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION
704 // Case I: (Aggregation + Piggy-Back)
705 // 1. user enable aggregation, AND
706 // 2. Mac support piggy-back
707 // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON
708 // Case II: (Aggregation)
709 // 1. user enable aggregation, AND
710 // 2. AP annouces it's AGGREGATION-capable in BEACON
711 if (pAd->CommonCfg.bAggregationCapable) {
712 if ((pAd->CommonCfg.bPiggyBackCapable)
713 && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) {
716 { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43,
717 0x03, 0x00, 0x00, 0x00 };
718 MakeOutgoingFrame(pOutBuffer + FrameLen,
719 &TmpLen, 9, RalinkIe,
722 } else if (pAd->MlmeAux.APRalinkIe & 0x00000001) {
725 { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43,
726 0x01, 0x00, 0x00, 0x00 };
727 MakeOutgoingFrame(pOutBuffer + FrameLen,
728 &TmpLen, 9, RalinkIe,
735 { IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x04,
737 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 9,
738 RalinkIe, END_OF_ARGS);
742 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
743 MlmeFreeMemory(pAd, pOutBuffer);
745 RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout); /* in mSec */
746 pAd->Mlme.AssocMachine.CurrState = REASSOC_WAIT_RSP;
748 DBGPRINT(RT_DEBUG_TRACE,
749 ("ASSOC - MlmeReassocReqAction() sanity check failed. BUG!!!! \n"));
750 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
751 Status = MLME_INVALID_FORMAT;
752 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2,
758 ==========================================================================
760 Upper layer issues disassoc request
766 ==========================================================================
768 VOID MlmeDisassocReqAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
770 PMLME_DISASSOC_REQ_STRUCT pDisassocReq;
771 HEADER_802_11 DisassocHdr;
772 PHEADER_802_11 pDisassocHdr;
773 PUCHAR pOutBuffer = NULL;
776 BOOLEAN TimerCancelled;
781 pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT) (Elem->Msg);
783 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
784 if (NStatus != NDIS_STATUS_SUCCESS) {
785 DBGPRINT(RT_DEBUG_TRACE,
786 ("ASSOC - MlmeDisassocReqAction() allocate memory failed\n"));
787 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
788 Status = MLME_FAIL_NO_RESOURCE;
789 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2,
794 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &TimerCancelled);
796 DBGPRINT(RT_DEBUG_TRACE,
797 ("ASSOC - Send DISASSOC request[BSSID::%02x:%02x:%02x:%02x:%02x:%02x (Reason=%d)\n",
798 pDisassocReq->Addr[0], pDisassocReq->Addr[1],
799 pDisassocReq->Addr[2], pDisassocReq->Addr[3],
800 pDisassocReq->Addr[4], pDisassocReq->Addr[5],
801 pDisassocReq->Reason));
802 MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr); // patch peap ttls switching issue
803 MakeOutgoingFrame(pOutBuffer, &FrameLen,
804 sizeof(HEADER_802_11), &DisassocHdr,
805 2, &pDisassocReq->Reason, END_OF_ARGS);
806 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
808 // To patch Instance and Buffalo(N) AP
809 // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine
810 // Therefore, we send both of them.
811 pDisassocHdr = (PHEADER_802_11) pOutBuffer;
812 pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH;
813 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
815 MlmeFreeMemory(pAd, pOutBuffer);
817 pAd->StaCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING;
818 COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pDisassocReq->Addr);
820 RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); /* in mSec */
821 pAd->Mlme.AssocMachine.CurrState = DISASSOC_WAIT_RSP;
823 RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0);
828 ==========================================================================
830 peer sends assoc rsp back
832 Elme - MLME message containing the received frame
834 IRQL = DISPATCH_LEVEL
836 ==========================================================================
838 VOID PeerAssocRspAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
840 USHORT CapabilityInfo, Status, Aid;
841 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen;
842 UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen;
843 UCHAR Addr2[MAC_ADDR_LEN];
844 BOOLEAN TimerCancelled;
847 HT_CAPABILITY_IE HtCapability;
848 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
849 UCHAR HtCapabilityLen = 0;
851 UCHAR NewExtChannelOffset = 0xff;
853 if (PeerAssocRspSanity
854 (pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status,
855 &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, &HtCapability,
856 &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen, &NewExtChannelOffset,
857 &EdcaParm, &CkipFlag)) {
858 // The frame is for me ?
859 if (MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) {
860 DBGPRINT(RT_DEBUG_TRACE,
861 ("PeerAssocRspAction():ASSOC - receive ASSOC_RSP to me (status=%d)\n",
863 DBGPRINT(RT_DEBUG_TRACE,
864 ("PeerAssocRspAction():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n",
866 pAd->MacTab.Content[BSSID_WCID].AMsduSize,
867 pAd->MacTab.Content[BSSID_WCID].
869 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer,
872 if (Status == MLME_SUCCESS) {
873 UCHAR MaxSupportedRateIn500Kbps = 0;
876 // supported rates array may not be sorted. sort it and find the maximum rate
877 for (idx = 0; idx < SupRateLen; idx++) {
878 if (MaxSupportedRateIn500Kbps <
879 (SupRate[idx] & 0x7f))
880 MaxSupportedRateIn500Kbps =
884 for (idx = 0; idx < ExtRateLen; idx++) {
885 if (MaxSupportedRateIn500Kbps <
886 (ExtRate[idx] & 0x7f))
887 MaxSupportedRateIn500Kbps =
890 // go to procedure listed on page 376
891 AssocPostProc(pAd, Addr2, CapabilityInfo, Aid,
892 SupRate, SupRateLen, ExtRate,
893 ExtRateLen, &EdcaParm,
894 &HtCapability, HtCapabilityLen,
897 StaAddMacTableEntry(pAd,
900 MaxSupportedRateIn500Kbps,
902 HtCapabilityLen, &AddHtInfo,
906 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
907 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
908 MT2_ASSOC_CONF, 2, &Status);
911 DBGPRINT(RT_DEBUG_TRACE,
912 ("ASSOC - PeerAssocRspAction() sanity check fail\n"));
917 ==========================================================================
919 peer sends reassoc rsp
921 Elem - MLME message cntaining the received frame
923 IRQL = DISPATCH_LEVEL
925 ==========================================================================
927 VOID PeerReassocRspAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
929 USHORT CapabilityInfo;
932 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen;
933 UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen;
934 UCHAR Addr2[MAC_ADDR_LEN];
936 BOOLEAN TimerCancelled;
938 HT_CAPABILITY_IE HtCapability;
939 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
940 UCHAR HtCapabilityLen;
942 UCHAR NewExtChannelOffset = 0xff;
944 if (PeerAssocRspSanity
945 (pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status,
946 &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, &HtCapability,
947 &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen, &NewExtChannelOffset,
948 &EdcaParm, &CkipFlag)) {
949 if (MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) // The frame is for me ?
951 DBGPRINT(RT_DEBUG_TRACE,
952 ("ASSOC - receive REASSOC_RSP to me (status=%d)\n",
954 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer,
957 if (Status == MLME_SUCCESS) {
958 // go to procedure listed on page 376
959 AssocPostProc(pAd, Addr2, CapabilityInfo, Aid,
960 SupRate, SupRateLen, ExtRate,
961 ExtRateLen, &EdcaParm,
962 &HtCapability, HtCapabilityLen,
966 wext_notify_event_assoc(pAd);
967 RtmpOSWrielessEventSend(pAd, SIOCGIWAP,
975 // CkipFlag is no use for reassociate
976 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
977 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
978 MT2_REASSOC_CONF, 2, &Status);
981 DBGPRINT(RT_DEBUG_TRACE,
982 ("ASSOC - PeerReassocRspAction() sanity check fail\n"));
988 ==========================================================================
990 procedures on IEEE 802.11/1999 p.376
993 IRQL = DISPATCH_LEVEL
995 ==========================================================================
997 VOID AssocPostProc(IN PRTMP_ADAPTER pAd, IN PUCHAR pAddr2, IN USHORT CapabilityInfo, IN USHORT Aid, IN UCHAR SupRate[], IN UCHAR SupRateLen, IN UCHAR ExtRate[], IN UCHAR ExtRateLen, IN PEDCA_PARM pEdcaParm, IN HT_CAPABILITY_IE * pHtCapability, IN UCHAR HtCapabilityLen, IN ADD_HT_INFO_IE * pAddHtInfo) // AP might use this additional ht info IE
1001 pAd->MlmeAux.BssType = BSS_INFRA;
1002 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pAddr2);
1003 pAd->MlmeAux.Aid = Aid;
1004 pAd->MlmeAux.CapabilityInfo =
1005 CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
1007 // Some HT AP might lost WMM IE. We add WMM ourselves. beacuase HT requires QoS on.
1008 if ((HtCapabilityLen > 0) && (pEdcaParm->bValid == FALSE)) {
1009 pEdcaParm->bValid = TRUE;
1010 pEdcaParm->Aifsn[0] = 3;
1011 pEdcaParm->Aifsn[1] = 7;
1012 pEdcaParm->Aifsn[2] = 2;
1013 pEdcaParm->Aifsn[3] = 2;
1015 pEdcaParm->Cwmin[0] = 4;
1016 pEdcaParm->Cwmin[1] = 4;
1017 pEdcaParm->Cwmin[2] = 3;
1018 pEdcaParm->Cwmin[3] = 2;
1020 pEdcaParm->Cwmax[0] = 10;
1021 pEdcaParm->Cwmax[1] = 10;
1022 pEdcaParm->Cwmax[2] = 4;
1023 pEdcaParm->Cwmax[3] = 3;
1025 pEdcaParm->Txop[0] = 0;
1026 pEdcaParm->Txop[1] = 0;
1027 pEdcaParm->Txop[2] = 96;
1028 pEdcaParm->Txop[3] = 48;
1032 NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
1034 // filter out un-supported rates
1035 pAd->MlmeAux.SupRateLen = SupRateLen;
1036 NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
1037 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
1039 // filter out un-supported rates
1040 pAd->MlmeAux.ExtRateLen = ExtRateLen;
1041 NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
1042 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
1044 if (HtCapabilityLen > 0) {
1045 RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo);
1047 DBGPRINT(RT_DEBUG_TRACE,
1048 ("AssocPostProc===> AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n",
1049 pAd->MacTab.Content[BSSID_WCID].AMsduSize,
1050 pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
1052 DBGPRINT(RT_DEBUG_TRACE,
1053 ("AssocPostProc===> (Mmps=%d, AmsduSize=%d, )\n",
1054 pAd->MacTab.Content[BSSID_WCID].MmpsMode,
1055 pAd->MacTab.Content[BSSID_WCID].AMsduSize));
1057 // Set New WPA information
1058 Idx = BssTableSearch(&pAd->ScanTab, pAddr2, pAd->MlmeAux.Channel);
1059 if (Idx == BSS_NOT_FOUND) {
1060 DBGPRINT_ERR(("ASSOC - Can't find BSS after receiving Assoc response\n"));
1063 pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = 0;
1064 NdisZeroMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE,
1067 // Store appropriate RSN_IE for WPA SM negotiation later
1068 if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
1069 && (pAd->ScanTab.BssEntry[Idx].VarIELen != 0)) {
1074 pVIE = pAd->ScanTab.BssEntry[Idx].VarIEs;
1075 len = pAd->ScanTab.BssEntry[Idx].VarIELen;
1076 //KH need to check again
1077 // Don't allow to go to sleep mode if authmode is WPA-related.
1078 //This can make Authentication process more smoothly.
1079 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
1082 pEid = (PEID_STRUCT) pVIE;
1084 if ((pEid->Eid == IE_WPA)
1086 (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
1087 && (pAd->StaCfg.AuthMode ==
1088 Ndis802_11AuthModeWPA
1089 || pAd->StaCfg.AuthMode ==
1090 Ndis802_11AuthModeWPAPSK)) {
1091 NdisMoveMemory(pAd->MacTab.
1092 Content[BSSID_WCID].
1095 pAd->MacTab.Content[BSSID_WCID].
1096 RSNIE_Len = (pEid->Len + 2);
1097 DBGPRINT(RT_DEBUG_TRACE,
1098 ("AssocPostProc===> Store RSN_IE for WPA SM negotiation \n"));
1101 else if ((pEid->Eid == IE_RSN)
1104 (pEid->Octet + 2, RSN_OUI, 3))
1105 && (pAd->StaCfg.AuthMode ==
1106 Ndis802_11AuthModeWPA2
1107 || pAd->StaCfg.AuthMode ==
1108 Ndis802_11AuthModeWPA2PSK)) {
1109 NdisMoveMemory(pAd->MacTab.
1110 Content[BSSID_WCID].
1113 pAd->MacTab.Content[BSSID_WCID].
1114 RSNIE_Len = (pEid->Len + 2);
1115 DBGPRINT(RT_DEBUG_TRACE,
1116 ("AssocPostProc===> Store RSN_IE for WPA2 SM negotiation \n"));
1119 pVIE += (pEid->Len + 2);
1120 len -= (pEid->Len + 2);
1125 if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0) {
1126 DBGPRINT(RT_DEBUG_TRACE,
1127 ("AssocPostProc===> no RSN_IE \n"));
1130 pAd->MacTab.Content[BSSID_WCID].RSN_IE,
1131 pAd->MacTab.Content[BSSID_WCID].RSNIE_Len);
1137 ==========================================================================
1139 left part of IEEE 802.11/1999 p.374
1141 Elem - MLME message containing the received frame
1143 IRQL = DISPATCH_LEVEL
1145 ==========================================================================
1147 VOID PeerDisassocAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
1149 UCHAR Addr2[MAC_ADDR_LEN];
1152 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction()\n"));
1153 if (PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) {
1154 DBGPRINT(RT_DEBUG_TRACE,
1155 ("ASSOC - PeerDisassocAction() Reason = %d\n",
1158 && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, Addr2)) {
1160 if (pAd->CommonCfg.bWirelessEvent) {
1161 RTMPSendWirelessEvent(pAd,
1162 IW_DISASSOC_EVENT_FLAG,
1164 Content[BSSID_WCID].Addr,
1168 LinkDown(pAd, TRUE);
1169 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1171 RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL,
1175 DBGPRINT(RT_DEBUG_TRACE,
1176 ("ASSOC - PeerDisassocAction() sanity check fail\n"));
1182 ==========================================================================
1184 what the state machine will do after assoc timeout
1188 IRQL = DISPATCH_LEVEL
1190 ==========================================================================
1192 VOID AssocTimeoutAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
1195 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - AssocTimeoutAction\n"));
1196 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1197 Status = MLME_REJ_TIMEOUT;
1198 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
1202 ==========================================================================
1204 what the state machine will do after reassoc timeout
1206 IRQL = DISPATCH_LEVEL
1208 ==========================================================================
1210 VOID ReassocTimeoutAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
1213 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - ReassocTimeoutAction\n"));
1214 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1215 Status = MLME_REJ_TIMEOUT;
1216 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
1220 ==========================================================================
1222 what the state machine will do after disassoc timeout
1224 IRQL = DISPATCH_LEVEL
1226 ==========================================================================
1228 VOID DisassocTimeoutAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
1231 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - DisassocTimeoutAction\n"));
1232 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1233 Status = MLME_SUCCESS;
1234 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2,
1238 VOID InvalidStateWhenAssoc(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
1241 DBGPRINT(RT_DEBUG_TRACE,
1242 ("ASSOC - InvalidStateWhenAssoc(state=%ld), reset ASSOC state machine\n",
1243 pAd->Mlme.AssocMachine.CurrState));
1244 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1245 Status = MLME_STATE_MACHINE_REJECT;
1246 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
1249 VOID InvalidStateWhenReassoc(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
1252 DBGPRINT(RT_DEBUG_TRACE,
1253 ("ASSOC - InvalidStateWhenReassoc(state=%ld), reset ASSOC state machine\n",
1254 pAd->Mlme.AssocMachine.CurrState));
1255 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1256 Status = MLME_STATE_MACHINE_REJECT;
1257 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
1260 VOID InvalidStateWhenDisassociate(IN PRTMP_ADAPTER pAd,
1261 IN MLME_QUEUE_ELEM * Elem)
1264 DBGPRINT(RT_DEBUG_TRACE,
1265 ("ASSOC - InvalidStateWhenDisassoc(state=%ld), reset ASSOC state machine\n",
1266 pAd->Mlme.AssocMachine.CurrState));
1267 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1268 Status = MLME_STATE_MACHINE_REJECT;
1269 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2,
1274 ==========================================================================
1276 right part of IEEE 802.11/1999 page 374
1278 This event should never cause ASSOC state machine perform state
1279 transition, and has no relationship with CNTL machine. So we separate
1280 this routine as a service outside of ASSOC state transition table.
1282 IRQL = DISPATCH_LEVEL
1284 ==========================================================================
1286 VOID Cls3errAction(IN PRTMP_ADAPTER pAd, IN PUCHAR pAddr)
1288 HEADER_802_11 DisassocHdr;
1289 PHEADER_802_11 pDisassocHdr;
1290 PUCHAR pOutBuffer = NULL;
1292 NDIS_STATUS NStatus;
1293 USHORT Reason = REASON_CLS3ERR;
1295 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1296 if (NStatus != NDIS_STATUS_SUCCESS)
1299 DBGPRINT(RT_DEBUG_TRACE,
1300 ("ASSOC - Class 3 Error, Send DISASSOC frame\n"));
1301 MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAddr, pAd->CommonCfg.Bssid); // patch peap ttls switching issue
1302 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1303 sizeof(HEADER_802_11), &DisassocHdr,
1304 2, &Reason, END_OF_ARGS);
1305 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1307 // To patch Instance and Buffalo(N) AP
1308 // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine
1309 // Therefore, we send both of them.
1310 pDisassocHdr = (PHEADER_802_11) pOutBuffer;
1311 pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH;
1312 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1314 MlmeFreeMemory(pAd, pOutBuffer);
1316 pAd->StaCfg.DisassocReason = REASON_CLS3ERR;
1317 COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pAddr);
1320 int wext_notify_event_assoc(IN RTMP_ADAPTER * pAd)
1322 char custom[IW_CUSTOM_MAX] = { 0 };
1324 if (pAd->StaCfg.ReqVarIELen <= IW_CUSTOM_MAX) {
1325 NdisMoveMemory(custom, pAd->StaCfg.ReqVarIEs,
1326 pAd->StaCfg.ReqVarIELen);
1327 RtmpOSWrielessEventSend(pAd, IWEVASSOCREQIE, -1, NULL, custom,
1328 pAd->StaCfg.ReqVarIELen);
1330 DBGPRINT(RT_DEBUG_TRACE,
1331 ("pAd->StaCfg.ReqVarIELen > MAX_CUSTOM_LEN\n"));
1337 BOOLEAN StaAddMacTableEntry(IN PRTMP_ADAPTER pAd,
1338 IN PMAC_TABLE_ENTRY pEntry,
1339 IN UCHAR MaxSupportedRateIn500Kbps,
1340 IN HT_CAPABILITY_IE * pHtCapability,
1341 IN UCHAR HtCapabilityLen,
1342 IN ADD_HT_INFO_IE * pAddHtInfo,
1343 IN UCHAR AddHtInfoLen, IN USHORT CapabilityInfo)
1345 UCHAR MaxSupportedRate = RATE_11;
1348 CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
1350 switch (MaxSupportedRateIn500Kbps) {
1352 MaxSupportedRate = RATE_54;
1355 MaxSupportedRate = RATE_48;
1358 MaxSupportedRate = RATE_36;
1361 MaxSupportedRate = RATE_24;
1364 MaxSupportedRate = RATE_18;
1367 MaxSupportedRate = RATE_12;
1370 MaxSupportedRate = RATE_9;
1373 MaxSupportedRate = RATE_6;
1376 MaxSupportedRate = RATE_11;
1379 MaxSupportedRate = RATE_5_5;
1382 MaxSupportedRate = RATE_2;
1385 MaxSupportedRate = RATE_1;
1388 MaxSupportedRate = RATE_11;
1392 if ((pAd->CommonCfg.PhyMode == PHY_11G)
1393 && (MaxSupportedRate < RATE_FIRST_OFDM_RATE))
1397 if (((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
1398 || (pAd->CommonCfg.PhyMode == PHY_11N_5G))
1399 && (HtCapabilityLen == 0))
1405 NdisAcquireSpinLock(&pAd->MacTabLock);
1407 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1408 if ((MaxSupportedRate < RATE_FIRST_OFDM_RATE) ||
1409 (pAd->CommonCfg.PhyMode == PHY_11B)) {
1410 pEntry->RateLen = 4;
1411 if (MaxSupportedRate >= RATE_FIRST_OFDM_RATE)
1412 MaxSupportedRate = RATE_11;
1414 pEntry->RateLen = 12;
1416 pEntry->MaxHTPhyMode.word = 0;
1417 pEntry->MinHTPhyMode.word = 0;
1418 pEntry->HTPhyMode.word = 0;
1419 pEntry->MaxSupportedRate = MaxSupportedRate;
1420 if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) {
1421 pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
1422 pEntry->MaxHTPhyMode.field.MCS =
1423 pEntry->MaxSupportedRate;
1424 pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
1425 pEntry->MinHTPhyMode.field.MCS =
1426 pEntry->MaxSupportedRate;
1427 pEntry->HTPhyMode.field.MODE = MODE_CCK;
1428 pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
1430 pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
1431 pEntry->MaxHTPhyMode.field.MCS =
1432 OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
1433 pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
1434 pEntry->MinHTPhyMode.field.MCS =
1435 OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
1436 pEntry->HTPhyMode.field.MODE = MODE_OFDM;
1437 pEntry->HTPhyMode.field.MCS =
1438 OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
1440 pEntry->CapabilityInfo = CapabilityInfo;
1441 CLIENT_STATUS_CLEAR_FLAG(pEntry,
1442 fCLIENT_STATUS_AGGREGATION_CAPABLE);
1443 CLIENT_STATUS_CLEAR_FLAG(pEntry,
1444 fCLIENT_STATUS_PIGGYBACK_CAPABLE);
1447 NdisZeroMemory(&pEntry->HTCapability, sizeof(pEntry->HTCapability));
1448 // If this Entry supports 802.11n, upgrade to HT rate.
1449 if ((HtCapabilityLen != 0)
1450 && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) {
1451 UCHAR j, bitmask; //k,bitmask;
1455 CLIENT_STATUS_SET_FLAG(pEntry,
1456 fCLIENT_STATUS_WMM_CAPABLE);
1457 if ((pHtCapability->HtCapInfo.GF)
1458 && (pAd->CommonCfg.DesiredHtPhy.GF)) {
1459 pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
1461 pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
1462 pAd->MacTab.fAnyStationNonGF = TRUE;
1463 pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
1466 if ((pHtCapability->HtCapInfo.ChannelWidth) &&
1467 (pAd->CommonCfg.DesiredHtPhy.ChannelWidth) &&
1468 ((pAd->StaCfg.BssType == BSS_INFRA)
1469 || ((pAd->StaCfg.BssType == BSS_ADHOC)
1470 && (pAddHtInfo->AddHtInfo.ExtChanOffset ==
1471 pAd->CommonCfg.AddHTInfo.AddHtInfo.
1473 pEntry->MaxHTPhyMode.field.BW = BW_40;
1474 pEntry->MaxHTPhyMode.field.ShortGI =
1475 ((pAd->CommonCfg.DesiredHtPhy.
1476 ShortGIfor40) & (pHtCapability->HtCapInfo.
1479 pEntry->MaxHTPhyMode.field.BW = BW_20;
1480 pEntry->MaxHTPhyMode.field.ShortGI =
1481 ((pAd->CommonCfg.DesiredHtPhy.
1482 ShortGIfor20) & (pHtCapability->HtCapInfo.
1484 pAd->MacTab.fAnyStation20Only = TRUE;
1488 if (pAd->MACVersion >= RALINK_2883_VERSION
1489 && pAd->MACVersion < RALINK_3070_VERSION)
1490 pEntry->MaxHTPhyMode.field.TxBF =
1491 pAd->CommonCfg.RegTransmitSetting.field.TxBF;
1493 // find max fixed rate
1494 for (i = 23; i >= 0; i--) // 3*3
1497 bitmask = (1 << (i - (j * 8)));
1498 if ((pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j] & bitmask)
1499 && (pHtCapability->MCSSet[j] & bitmask)) {
1500 pEntry->MaxHTPhyMode.field.MCS = i;
1507 if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) {
1508 if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) {
1509 // Fix MCS as HT Duplicated Mode
1510 pEntry->MaxHTPhyMode.field.BW = 1;
1511 pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
1512 pEntry->MaxHTPhyMode.field.STBC = 0;
1513 pEntry->MaxHTPhyMode.field.ShortGI = 0;
1514 pEntry->MaxHTPhyMode.field.MCS = 32;
1515 } else if (pEntry->MaxHTPhyMode.field.MCS >
1516 pAd->StaCfg.HTPhyMode.field.MCS) {
1517 // STA supports fixed MCS
1518 pEntry->MaxHTPhyMode.field.MCS =
1519 pAd->StaCfg.HTPhyMode.field.MCS;
1523 pEntry->MaxHTPhyMode.field.STBC =
1524 (pHtCapability->HtCapInfo.
1525 RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
1526 pEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity;
1527 pEntry->MaxRAmpduFactor =
1528 pHtCapability->HtCapParm.MaxRAmpduFactor;
1529 pEntry->MmpsMode = (UCHAR) pHtCapability->HtCapInfo.MimoPs;
1530 pEntry->AMsduSize = (UCHAR) pHtCapability->HtCapInfo.AMsduSize;
1531 pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
1533 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable
1534 && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE))
1535 CLIENT_STATUS_SET_FLAG(pEntry,
1536 fCLIENT_STATUS_AMSDU_INUSED);
1537 if (pHtCapability->HtCapInfo.ShortGIfor20)
1538 CLIENT_STATUS_SET_FLAG(pEntry,
1539 fCLIENT_STATUS_SGI20_CAPABLE);
1540 if (pHtCapability->HtCapInfo.ShortGIfor40)
1541 CLIENT_STATUS_SET_FLAG(pEntry,
1542 fCLIENT_STATUS_SGI40_CAPABLE);
1543 if (pHtCapability->HtCapInfo.TxSTBC)
1544 CLIENT_STATUS_SET_FLAG(pEntry,
1545 fCLIENT_STATUS_TxSTBC_CAPABLE);
1546 if (pHtCapability->HtCapInfo.RxSTBC)
1547 CLIENT_STATUS_SET_FLAG(pEntry,
1548 fCLIENT_STATUS_RxSTBC_CAPABLE);
1549 if (pHtCapability->ExtHtCapInfo.PlusHTC)
1550 CLIENT_STATUS_SET_FLAG(pEntry,
1551 fCLIENT_STATUS_HTC_CAPABLE);
1552 if (pAd->CommonCfg.bRdg
1553 && pHtCapability->ExtHtCapInfo.RDGSupport)
1554 CLIENT_STATUS_SET_FLAG(pEntry,
1555 fCLIENT_STATUS_RDG_CAPABLE);
1556 if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03)
1557 CLIENT_STATUS_SET_FLAG(pEntry,
1558 fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
1559 NdisMoveMemory(&pEntry->HTCapability, pHtCapability,
1562 pAd->MacTab.fAnyStationIsLegacy = TRUE;
1565 pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
1566 pEntry->CurrTxRate = pEntry->MaxSupportedRate;
1568 // Set asic auto fall back
1569 if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) {
1571 UCHAR TableSize = 0;
1573 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
1574 &pEntry->CurrTxRateIndex);
1575 pEntry->bAutoTxRateSwitch = TRUE;
1577 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1578 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1579 pEntry->bAutoTxRateSwitch = FALSE;
1581 // If the legacy mode is set, overwrite the transmit setting of this entry.
1582 RTMPUpdateLegacyTxSetting((UCHAR) pAd->StaCfg.
1583 DesiredTransmitSetting.field.
1584 FixedTxMode, pEntry);
1587 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1588 pEntry->Sst = SST_ASSOC;
1589 pEntry->AuthState = AS_AUTH_OPEN;
1590 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1591 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1593 NdisReleaseSpinLock(&pAd->MacTabLock);
1596 union iwreq_data wrqu;
1597 wext_notify_event_assoc(pAd);
1599 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1600 memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
1601 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);