]> Pileus Git - ~andy/linux/blob - drivers/staging/rt2860/sta/assoc.c
Staging: rt2860: add RT3090 chipset support
[~andy/linux] / drivers / staging / rt2860 / sta / assoc.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26
27         Module Name:
28         assoc.c
29
30         Abstract:
31
32         Revision History:
33         Who                     When                    What
34         --------        ----------              ----------------------------------------------
35         John            2004-9-3                porting from RT2500
36 */
37 #include "../rt_config.h"
38
39 UCHAR   CipherWpaTemplate[] = {
40                 0xdd,                                   // WPA IE
41                 0x16,                                   // Length
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
49                 };
50
51 UCHAR   CipherWpa2Template[] = {
52                 0x30,                                   // RSN IE
53                 0x14,                                   // Length
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
61                 };
62
63 UCHAR   Ccx2IeInfo[] = { 0x00, 0x40, 0x96, 0x03, 0x02};
64
65 /*
66         ==========================================================================
67         Description:
68                 association state machine init, including state transition and timer init
69         Parameters:
70                 S - pointer to the association state machine
71
72         IRQL = PASSIVE_LEVEL
73
74         ==========================================================================
75  */
76 VOID AssocStateMachineInit(
77         IN      PRTMP_ADAPTER   pAd,
78         IN  STATE_MACHINE *S,
79         OUT STATE_MACHINE_FUNC Trans[])
80 {
81         StateMachineInit(S, Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG, (STATE_MACHINE_FUNC)Drop, ASSOC_IDLE, ASSOC_MACHINE_BASE);
82
83         // first column
84         StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)MlmeAssocReqAction);
85         StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)MlmeReassocReqAction);
86         StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)MlmeDisassocReqAction);
87         StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
88
89         // second column
90         StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
91         StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
92         StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
93         StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
94         StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction);
95         //
96         // Patch 3Com AP MOde:3CRWE454G72
97         // We send Assoc request frame to this AP, it always send Reassoc Rsp not Associate Rsp.
98         //
99         StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction);
100         StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_ASSOC_TIMEOUT, (STATE_MACHINE_FUNC)AssocTimeoutAction);
101
102         // third column
103         StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
104         StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
105         StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
106         StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
107         StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction);
108         //
109         // Patch, AP doesn't send Reassociate Rsp frame to Station.
110         //
111         StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction);
112         StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_REASSOC_TIMEOUT, (STATE_MACHINE_FUNC)ReassocTimeoutAction);
113
114         // fourth column
115         StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
116         StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
117         StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
118         StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
119         StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_DISASSOC_TIMEOUT, (STATE_MACHINE_FUNC)DisassocTimeoutAction);
120
121         // initialize the timer
122         RTMPInitTimer(pAd, &pAd->MlmeAux.AssocTimer, GET_TIMER_FUNCTION(AssocTimeout), pAd, FALSE);
123         RTMPInitTimer(pAd, &pAd->MlmeAux.ReassocTimer, GET_TIMER_FUNCTION(ReassocTimeout), pAd, FALSE);
124         RTMPInitTimer(pAd, &pAd->MlmeAux.DisassocTimer, GET_TIMER_FUNCTION(DisassocTimeout), pAd, FALSE);
125 }
126
127 /*
128         ==========================================================================
129         Description:
130                 Association timeout procedure. After association timeout, this function
131                 will be called and it will put a message into the MLME queue
132         Parameters:
133                 Standard timer parameters
134
135         IRQL = DISPATCH_LEVEL
136
137         ==========================================================================
138  */
139 VOID AssocTimeout(IN PVOID SystemSpecific1,
140                                  IN PVOID FunctionContext,
141                                  IN PVOID SystemSpecific2,
142                                  IN PVOID SystemSpecific3)
143 {
144         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
145
146         // Do nothing if the driver is starting halt state.
147         // This might happen when timer already been fired before cancel timer with mlmehalt
148         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
149                 return;
150
151         MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_ASSOC_TIMEOUT, 0, NULL);
152         RTMP_MLME_HANDLER(pAd);
153 }
154
155 /*
156         ==========================================================================
157         Description:
158                 Reassociation timeout procedure. After reassociation timeout, this
159                 function will be called and put a message into the MLME queue
160         Parameters:
161                 Standard timer parameters
162
163         IRQL = DISPATCH_LEVEL
164
165         ==========================================================================
166  */
167 VOID ReassocTimeout(IN PVOID SystemSpecific1,
168                                         IN PVOID FunctionContext,
169                                         IN PVOID SystemSpecific2,
170                                         IN PVOID SystemSpecific3)
171 {
172         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
173
174         // Do nothing if the driver is starting halt state.
175         // This might happen when timer already been fired before cancel timer with mlmehalt
176         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
177                 return;
178
179         MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_REASSOC_TIMEOUT, 0, NULL);
180         RTMP_MLME_HANDLER(pAd);
181 }
182
183 /*
184         ==========================================================================
185         Description:
186                 Disassociation timeout procedure. After disassociation timeout, this
187                 function will be called and put a message into the MLME queue
188         Parameters:
189                 Standard timer parameters
190
191         IRQL = DISPATCH_LEVEL
192
193         ==========================================================================
194  */
195 VOID DisassocTimeout(IN PVOID SystemSpecific1,
196                                         IN PVOID FunctionContext,
197                                         IN PVOID SystemSpecific2,
198                                         IN PVOID SystemSpecific3)
199 {
200         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
201
202         // Do nothing if the driver is starting halt state.
203         // This might happen when timer already been fired before cancel timer with mlmehalt
204         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
205                 return;
206
207         MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_DISASSOC_TIMEOUT, 0, NULL);
208         RTMP_MLME_HANDLER(pAd);
209 }
210
211 /*
212         ==========================================================================
213         Description:
214                 mlme assoc req handling procedure
215         Parameters:
216                 Adapter - Adapter pointer
217                 Elem - MLME Queue Element
218         Pre:
219                 the station has been authenticated and the following information is stored in the config
220                         -# SSID
221                         -# supported rates and their length
222                         -# listen interval (Adapter->StaCfg.default_listen_count)
223                         -# Transmit power  (Adapter->StaCfg.tx_power)
224         Post  :
225                 -# An association request frame is generated and sent to the air
226                 -# Association timer starts
227                 -# Association state -> ASSOC_WAIT_RSP
228
229         IRQL = DISPATCH_LEVEL
230
231         ==========================================================================
232  */
233 VOID MlmeAssocReqAction(
234         IN PRTMP_ADAPTER pAd,
235         IN MLME_QUEUE_ELEM *Elem)
236 {
237         UCHAR                   ApAddr[6];
238         HEADER_802_11   AssocHdr;
239         UCHAR                   WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
240         USHORT                  ListenIntv;
241         ULONG                   Timeout;
242         USHORT                  CapabilityInfo;
243         BOOLEAN                 TimerCancelled;
244         PUCHAR                  pOutBuffer = NULL;
245         NDIS_STATUS             NStatus;
246         ULONG                   FrameLen = 0;
247         ULONG                   tmp;
248         USHORT                  VarIesOffset;
249         USHORT                  Status;
250
251         // Block all authentication request durning WPA block period
252         if (pAd->StaCfg.bBlockAssoc == TRUE)
253         {
254                 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block Assoc request durning WPA block period!\n"));
255                 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
256                 Status = MLME_STATE_MACHINE_REJECT;
257                 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
258         }
259         // check sanity first
260         else if (MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv))
261         {
262                 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled);
263                 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr);
264
265                 // Get an unused nonpaged memory
266                 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
267                 if (NStatus != NDIS_STATUS_SUCCESS)
268                 {
269                         DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() allocate memory failed \n"));
270                         pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
271                         Status = MLME_FAIL_NO_RESOURCE;
272                         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
273                         return;
274                 }
275
276                 // Add by James 03/06/27
277                 pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
278                 // Association don't need to report MAC address
279                 pAd->StaCfg.AssocInfo.AvailableRequestFixedIEs =
280                         NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL;
281                 pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities = CapabilityInfo;
282                 pAd->StaCfg.AssocInfo.RequestFixedIEs.ListenInterval = ListenIntv;
283                 // Only reassociate need this
284                 //COPY_MAC_ADDR(pAd->StaCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr);
285                 pAd->StaCfg.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
286
287         NdisZeroMemory(pAd->StaCfg.ReqVarIEs, MAX_VIE_LEN);
288                 // First add SSID
289                 VarIesOffset = 0;
290                 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SsidIe, 1);
291                 VarIesOffset += 1;
292                 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SsidLen, 1);
293                 VarIesOffset += 1;
294                 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
295                 VarIesOffset += pAd->MlmeAux.SsidLen;
296
297                 // Second add Supported rates
298                 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SupRateIe, 1);
299                 VarIesOffset += 1;
300                 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SupRateLen, 1);
301                 VarIesOffset += 1;
302                 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen);
303                 VarIesOffset += pAd->MlmeAux.SupRateLen;
304                 // End Add by James
305
306         if ((pAd->CommonCfg.Channel > 14) &&
307             (pAd->CommonCfg.bIEEE80211H == TRUE))
308             CapabilityInfo |= 0x0100;
309
310                 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send ASSOC request...\n"));
311                 MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr);
312
313                 // Build basic frame first
314                 MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
315                                                   sizeof(HEADER_802_11),        &AssocHdr,
316                                                   2,                                            &CapabilityInfo,
317                                                   2,                                            &ListenIntv,
318                                                   1,                                            &SsidIe,
319                                                   1,                                            &pAd->MlmeAux.SsidLen,
320                                                   pAd->MlmeAux.SsidLen,         pAd->MlmeAux.Ssid,
321                                                   1,                                            &SupRateIe,
322                                                   1,                                            &pAd->MlmeAux.SupRateLen,
323                                                   pAd->MlmeAux.SupRateLen,  pAd->MlmeAux.SupRate,
324                                                   END_OF_ARGS);
325
326                 if (pAd->MlmeAux.ExtRateLen != 0)
327                 {
328                         MakeOutgoingFrame(pOutBuffer + FrameLen,    &tmp,
329                                                           1,                        &ExtRateIe,
330                                                           1,                        &pAd->MlmeAux.ExtRateLen,
331                                                           pAd->MlmeAux.ExtRateLen,  pAd->MlmeAux.ExtRate,
332                                                           END_OF_ARGS);
333                         FrameLen += tmp;
334                 }
335
336                 // HT
337                 if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
338                 {
339                         ULONG TmpLen;
340                         UCHAR HtLen;
341                         UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
342                         if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE)
343                         {
344                                 HtLen = SIZE_HT_CAP_IE + 4;
345                                 MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
346                                                           1,                                &WpaIe,
347                                                           1,                                &HtLen,
348                                                           4,                                &BROADCOM[0],
349                                                          pAd->MlmeAux.HtCapabilityLen,          &pAd->MlmeAux.HtCapability,
350                                                           END_OF_ARGS);
351                         }
352                         else
353                         {
354                                 MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
355                                                           1,                                &HtCapIe,
356                                                           1,                                &pAd->MlmeAux.HtCapabilityLen,
357                                                          pAd->MlmeAux.HtCapabilityLen,          &pAd->MlmeAux.HtCapability,
358                                                           END_OF_ARGS);
359                         }
360                         FrameLen += TmpLen;
361                 }
362
363                 // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION
364                 // Case I: (Aggregation + Piggy-Back)
365                 // 1. user enable aggregation, AND
366                 // 2. Mac support piggy-back
367                 // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON
368                 // Case II: (Aggregation)
369                 // 1. user enable aggregation, AND
370                 // 2. AP annouces it's AGGREGATION-capable in BEACON
371                 if (pAd->CommonCfg.bAggregationCapable)
372                 {
373                         if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3))
374                         {
375                                 ULONG TmpLen;
376                                 UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00};
377                                 MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
378                                                                   9,                             RalinkIe,
379                                                                   END_OF_ARGS);
380                                 FrameLen += TmpLen;
381                         }
382                         else if (pAd->MlmeAux.APRalinkIe & 0x00000001)
383                         {
384                                 ULONG TmpLen;
385                                 UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00};
386                                 MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
387                                                                   9,                             RalinkIe,
388                                                                   END_OF_ARGS);
389                                 FrameLen += TmpLen;
390                         }
391                 }
392                 else
393                 {
394                         ULONG TmpLen;
395                         UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00};
396                         MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
397                                                           9,                                             RalinkIe,
398                                                           END_OF_ARGS);
399                         FrameLen += TmpLen;
400                 }
401
402                 if (pAd->MlmeAux.APEdcaParm.bValid)
403                 {
404                         if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable)
405                         {
406                                 QBSS_STA_INFO_PARM QosInfo;
407
408                                 NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM));
409                                 QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE;
410                                 QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK;
411                                 QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI;
412                                 QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO;
413                                 QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength;
414                                 WmeIe[8] |= *(PUCHAR)&QosInfo;
415                         }
416                         else
417                         {
418                 // The Parameter Set Count is set to Â¡Â§0¡¨ in the association request frames
419                 // WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f);
420                         }
421
422                         MakeOutgoingFrame(pOutBuffer + FrameLen,    &tmp,
423                                                           9,                        &WmeIe[0],
424                                                           END_OF_ARGS);
425                         FrameLen += tmp;
426                 }
427
428                 //
429                 // Let WPA(#221) Element ID on the end of this association frame.
430                 // Otherwise some AP will fail on parsing Element ID and set status fail on Assoc Rsp.
431                 // For example: Put Vendor Specific IE on the front of WPA IE.
432                 // This happens on AP (Model No:Linksys WRK54G)
433                 //
434                 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
435             (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
436             (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
437             (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)
438                         )
439             )
440                 {
441                         UCHAR RSNIe = IE_WPA;
442
443                         if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
444                 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2))
445                         {
446                                 RSNIe = IE_WPA2;
447                         }
448
449                         if ((pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE) &&
450                                 (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == FALSE))
451             RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0);
452
453             // Check for WPA PMK cache list
454                         if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)
455                         {
456                             INT     idx;
457                 BOOLEAN FoundPMK = FALSE;
458                                 // Search chched PMKID, append it if existed
459                                 for (idx = 0; idx < PMKID_NO; idx++)
460                                 {
461                                         if (NdisEqualMemory(ApAddr, &pAd->StaCfg.SavedPMK[idx].BSSID, 6))
462                                         {
463                                                 FoundPMK = TRUE;
464                                                 break;
465                                         }
466                                 }
467                                 if (FoundPMK)
468                                 {
469                                         // Set PMK number
470                                         *(PUSHORT) &pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len] = 1;
471                                         NdisMoveMemory(&pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len + 2], &pAd->StaCfg.SavedPMK[idx].PMKID, 16);
472                     pAd->StaCfg.RSNIE_Len += 18;
473                                 }
474                         }
475
476                         if ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) &&
477                                 (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == TRUE))
478                         {
479                                 MakeOutgoingFrame(pOutBuffer + FrameLen,                &tmp,
480                                                 pAd->StaCfg.RSNIE_Len,                  pAd->StaCfg.RSN_IE,
481                                                 END_OF_ARGS);
482                         }
483                         else
484                         {
485                                 MakeOutgoingFrame(pOutBuffer + FrameLen,                &tmp,
486                                                         1,                              &RSNIe,
487                                                 1,                              &pAd->StaCfg.RSNIE_Len,
488                                                 pAd->StaCfg.RSNIE_Len,                  pAd->StaCfg.RSN_IE,
489                                                 END_OF_ARGS);
490                         }
491
492                         FrameLen += tmp;
493
494                         if ((pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE) ||
495                                 (pAd->StaCfg.bRSN_IE_FromWpaSupplicant == FALSE))
496                         {
497                     // Append Variable IE
498                     NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &RSNIe, 1);
499                     VarIesOffset += 1;
500                     NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->StaCfg.RSNIE_Len, 1);
501                     VarIesOffset += 1;
502                         }
503                         NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len);
504                         VarIesOffset += pAd->StaCfg.RSNIE_Len;
505
506                         // Set Variable IEs Length
507                         pAd->StaCfg.ReqVarIELen = VarIesOffset;
508                 }
509
510
511                 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
512                 MlmeFreeMemory(pAd, pOutBuffer);
513
514                 RTMPSetTimer(&pAd->MlmeAux.AssocTimer, Timeout);
515                 pAd->Mlme.AssocMachine.CurrState = ASSOC_WAIT_RSP;
516         }
517         else
518         {
519                 DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() sanity check failed. BUG!!!!!! \n"));
520                 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
521                 Status = MLME_INVALID_FORMAT;
522                 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
523         }
524
525 }
526
527 /*
528         ==========================================================================
529         Description:
530                 mlme reassoc req handling procedure
531         Parameters:
532                 Elem -
533         Pre:
534                 -# SSID  (Adapter->StaCfg.ssid[])
535                 -# BSSID (AP address, Adapter->StaCfg.bssid)
536                 -# Supported rates (Adapter->StaCfg.supported_rates[])
537                 -# Supported rates length (Adapter->StaCfg.supported_rates_len)
538                 -# Tx power (Adapter->StaCfg.tx_power)
539
540         IRQL = DISPATCH_LEVEL
541
542         ==========================================================================
543  */
544 VOID MlmeReassocReqAction(
545         IN PRTMP_ADAPTER pAd,
546         IN MLME_QUEUE_ELEM *Elem)
547 {
548         UCHAR                   ApAddr[6];
549         HEADER_802_11   ReassocHdr;
550         UCHAR                   WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
551         USHORT                  CapabilityInfo, ListenIntv;
552         ULONG                   Timeout;
553         ULONG                   FrameLen = 0;
554         BOOLEAN                 TimerCancelled;
555         NDIS_STATUS             NStatus;
556         ULONG                   tmp;
557         PUCHAR                  pOutBuffer = NULL;
558         USHORT                  Status;
559
560         // Block all authentication request durning WPA block period
561         if (pAd->StaCfg.bBlockAssoc == TRUE)
562         {
563                 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block ReAssoc request durning WPA block period!\n"));
564                 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
565                 Status = MLME_STATE_MACHINE_REJECT;
566                 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
567         }
568         // the parameters are the same as the association
569         else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv))
570         {
571                 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled);
572
573                 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
574                 if(NStatus != NDIS_STATUS_SUCCESS)
575                 {
576                         DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() allocate memory failed \n"));
577                         pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
578                         Status = MLME_FAIL_NO_RESOURCE;
579                         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
580                         return;
581                 }
582
583                 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr);
584
585                 // make frame, use bssid as the AP address??
586                 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send RE-ASSOC request...\n"));
587                 MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0, ApAddr, ApAddr);
588                 MakeOutgoingFrame(pOutBuffer,               &FrameLen,
589                                                   sizeof(HEADER_802_11),    &ReassocHdr,
590                                                   2,                        &CapabilityInfo,
591                                                   2,                        &ListenIntv,
592                                                   MAC_ADDR_LEN,             ApAddr,
593                                                   1,                        &SsidIe,
594                                                   1,                        &pAd->MlmeAux.SsidLen,
595                                                   pAd->MlmeAux.SsidLen,     pAd->MlmeAux.Ssid,
596                                                   1,                        &SupRateIe,
597                                                   1,                                            &pAd->MlmeAux.SupRateLen,
598                                                   pAd->MlmeAux.SupRateLen,  pAd->MlmeAux.SupRate,
599                                                   END_OF_ARGS);
600
601                 if (pAd->MlmeAux.ExtRateLen != 0)
602                 {
603                         MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
604                                                           1,                            &ExtRateIe,
605                                                           1,                            &pAd->MlmeAux.ExtRateLen,
606                                                           pAd->MlmeAux.ExtRateLen,          pAd->MlmeAux.ExtRate,
607                                                           END_OF_ARGS);
608                         FrameLen += tmp;
609                 }
610
611                 if (pAd->MlmeAux.APEdcaParm.bValid)
612                 {
613                         if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable)
614                         {
615                                 QBSS_STA_INFO_PARM QosInfo;
616
617                                 NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM));
618                                 QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE;
619                                 QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK;
620                                 QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI;
621                                 QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO;
622                                 QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength;
623                                 WmeIe[8] |= *(PUCHAR)&QosInfo;
624                         }
625
626                         MakeOutgoingFrame(pOutBuffer + FrameLen,    &tmp,
627                                                           9,                        &WmeIe[0],
628                                                           END_OF_ARGS);
629                         FrameLen += tmp;
630                 }
631
632                 // HT
633                 if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
634                 {
635                         ULONG TmpLen;
636                         UCHAR HtLen;
637                         UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
638                         if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE)
639                         {
640                                 HtLen = SIZE_HT_CAP_IE + 4;
641                                 MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
642                                                           1,                                &WpaIe,
643                                                           1,                                &HtLen,
644                                                           4,                                &BROADCOM[0],
645                                                          pAd->MlmeAux.HtCapabilityLen,          &pAd->MlmeAux.HtCapability,
646                                                           END_OF_ARGS);
647                         }
648                         else
649                         {
650                                 MakeOutgoingFrame(pOutBuffer + FrameLen,            &TmpLen,
651                                                           1,                                &HtCapIe,
652                                                           1,                                &pAd->MlmeAux.HtCapabilityLen,
653                                                          pAd->MlmeAux.HtCapabilityLen,          &pAd->MlmeAux.HtCapability,
654                                                           END_OF_ARGS);
655                         }
656                         FrameLen += TmpLen;
657                 }
658
659                 // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION
660                 // Case I: (Aggregation + Piggy-Back)
661                 // 1. user enable aggregation, AND
662                 // 2. Mac support piggy-back
663                 // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON
664                 // Case II: (Aggregation)
665                 // 1. user enable aggregation, AND
666                 // 2. AP annouces it's AGGREGATION-capable in BEACON
667                 if (pAd->CommonCfg.bAggregationCapable)
668                 {
669                         if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3))
670                         {
671                                 ULONG TmpLen;
672                                 UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00};
673                                 MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
674                                                                   9,                             RalinkIe,
675                                                                   END_OF_ARGS);
676                                 FrameLen += TmpLen;
677                         }
678                         else if (pAd->MlmeAux.APRalinkIe & 0x00000001)
679                         {
680                                 ULONG TmpLen;
681                                 UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00};
682                                 MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
683                                                                   9,                             RalinkIe,
684                                                                   END_OF_ARGS);
685                                 FrameLen += TmpLen;
686                         }
687                 }
688                 else
689                 {
690                         ULONG TmpLen;
691                         UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x04, 0x00, 0x00, 0x00};
692                         MakeOutgoingFrame(pOutBuffer+FrameLen,           &TmpLen,
693                                                           9,                                             RalinkIe,
694                                                           END_OF_ARGS);
695                         FrameLen += TmpLen;
696                 }
697
698                 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
699                 MlmeFreeMemory(pAd, pOutBuffer);
700
701                 RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout); /* in mSec */
702                 pAd->Mlme.AssocMachine.CurrState = REASSOC_WAIT_RSP;
703         }
704         else
705         {
706                 DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() sanity check failed. BUG!!!! \n"));
707                 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
708                 Status = MLME_INVALID_FORMAT;
709                 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
710         }
711 }
712
713 /*
714         ==========================================================================
715         Description:
716                 Upper layer issues disassoc request
717         Parameters:
718                 Elem -
719
720         IRQL = PASSIVE_LEVEL
721
722         ==========================================================================
723  */
724 VOID MlmeDisassocReqAction(
725         IN PRTMP_ADAPTER pAd,
726         IN MLME_QUEUE_ELEM *Elem)
727 {
728         PMLME_DISASSOC_REQ_STRUCT pDisassocReq;
729         HEADER_802_11         DisassocHdr;
730         PHEADER_802_11        pDisassocHdr;
731         PUCHAR                pOutBuffer = NULL;
732         ULONG                 FrameLen = 0;
733         NDIS_STATUS           NStatus;
734         BOOLEAN               TimerCancelled;
735         ULONG                 Timeout = 500;
736         USHORT                Status;
737
738
739         // skip sanity check
740         pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT)(Elem->Msg);
741
742         NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
743         if (NStatus != NDIS_STATUS_SUCCESS)
744         {
745                 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - MlmeDisassocReqAction() allocate memory failed\n"));
746                 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
747                 Status = MLME_FAIL_NO_RESOURCE;
748                 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
749                 return;
750         }
751
752
753
754         RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &TimerCancelled);
755
756         DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send DISASSOC request[BSSID::%02x:%02x:%02x:%02x:%02x:%02x (Reason=%d)\n",
757                                 pDisassocReq->Addr[0], pDisassocReq->Addr[1], pDisassocReq->Addr[2],
758                                 pDisassocReq->Addr[3], pDisassocReq->Addr[4], pDisassocReq->Addr[5], pDisassocReq->Reason));
759         MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr);       // patch peap ttls switching issue
760         MakeOutgoingFrame(pOutBuffer,           &FrameLen,
761                                           sizeof(HEADER_802_11),&DisassocHdr,
762                                           2,                    &pDisassocReq->Reason,
763                                           END_OF_ARGS);
764         MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
765
766         // To patch Instance and Buffalo(N) AP
767         // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine
768         // Therefore, we send both of them.
769         pDisassocHdr = (PHEADER_802_11)pOutBuffer;
770         pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH;
771         MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
772
773         MlmeFreeMemory(pAd, pOutBuffer);
774
775         pAd->StaCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING;
776         COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pDisassocReq->Addr);
777
778         RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); /* in mSec */
779         pAd->Mlme.AssocMachine.CurrState = DISASSOC_WAIT_RSP;
780
781
782         RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0);
783
784 }
785
786 /*
787         ==========================================================================
788         Description:
789                 peer sends assoc rsp back
790         Parameters:
791                 Elme - MLME message containing the received frame
792
793         IRQL = DISPATCH_LEVEL
794
795         ==========================================================================
796  */
797 VOID PeerAssocRspAction(
798         IN PRTMP_ADAPTER pAd,
799         IN MLME_QUEUE_ELEM *Elem)
800 {
801         USHORT        CapabilityInfo, Status, Aid;
802         UCHAR         SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen;
803         UCHAR         ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen;
804         UCHAR         Addr2[MAC_ADDR_LEN];
805         BOOLEAN       TimerCancelled;
806         UCHAR         CkipFlag;
807         EDCA_PARM     EdcaParm;
808         HT_CAPABILITY_IE                HtCapability;
809         ADD_HT_INFO_IE          AddHtInfo;      // AP might use this additional ht info IE
810         UCHAR                   HtCapabilityLen = 0;
811         UCHAR                   AddHtInfoLen;
812         UCHAR                   NewExtChannelOffset = 0xff;
813
814         if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen,
815                 &HtCapability,&AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag))
816         {
817                 // The frame is for me ?
818                 if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid))
819                 {
820                         DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status));
821                         DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n",Elem->Wcid, pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
822                         RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled);
823
824
825                         if(Status == MLME_SUCCESS)
826                         {
827                                 UCHAR                   MaxSupportedRateIn500Kbps = 0;
828                                 UCHAR                   idx;
829
830                                 // supported rates array may not be sorted. sort it and find the maximum rate
831                             for (idx=0; idx<SupRateLen; idx++)
832                 {
833                                 if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f))
834                                     MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f;
835                             }
836
837                                 for (idx=0; idx<ExtRateLen; idx++)
838                             {
839                                 if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f))
840                                     MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f;
841                 }
842                                 // go to procedure listed on page 376
843                                 AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen,
844                                         &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo);
845
846                                 StaAddMacTableEntry(pAd,
847                                                                         &pAd->MacTab.Content[BSSID_WCID],
848                                                                         MaxSupportedRateIn500Kbps,
849                                                                         &HtCapability,
850                                                                         HtCapabilityLen,
851                                                                         &AddHtInfo,
852                                                                         AddHtInfoLen,
853                                                                         CapabilityInfo);
854                         }
855                         pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
856                         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
857                 }
858         }
859         else
860         {
861                 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerAssocRspAction() sanity check fail\n"));
862         }
863 }
864
865 /*
866         ==========================================================================
867         Description:
868                 peer sends reassoc rsp
869         Parametrs:
870                 Elem - MLME message cntaining the received frame
871
872         IRQL = DISPATCH_LEVEL
873
874         ==========================================================================
875  */
876 VOID PeerReassocRspAction(
877         IN PRTMP_ADAPTER pAd,
878         IN MLME_QUEUE_ELEM *Elem)
879 {
880         USHORT      CapabilityInfo;
881         USHORT      Status;
882         USHORT      Aid;
883         UCHAR       SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen;
884         UCHAR       ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen;
885         UCHAR       Addr2[MAC_ADDR_LEN];
886         UCHAR       CkipFlag;
887         BOOLEAN     TimerCancelled;
888         EDCA_PARM   EdcaParm;
889         HT_CAPABILITY_IE                HtCapability;
890         ADD_HT_INFO_IE          AddHtInfo;      // AP might use this additional ht info IE
891         UCHAR                   HtCapabilityLen;
892         UCHAR                   AddHtInfoLen;
893         UCHAR                   NewExtChannelOffset = 0xff;
894
895         if(PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen,
896                                                                 &HtCapability,  &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag))
897         {
898                 if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) // The frame is for me ?
899                 {
900                         DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - receive REASSOC_RSP to me (status=%d)\n", Status));
901                         RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled);
902
903                         if(Status == MLME_SUCCESS)
904                         {
905                                 // go to procedure listed on page 376
906                                 AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen,
907                                          &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo);
908
909
910                 {
911                     wext_notify_event_assoc(pAd);
912                     RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, &pAd->MlmeAux.Bssid[0], NULL, 0);
913                 }
914
915                         }
916
917                                 // CkipFlag is no use for reassociate
918                                 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
919                                 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
920                         }
921                 }
922         else
923         {
924                 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerReassocRspAction() sanity check fail\n"));
925         }
926
927 }
928
929 /*
930         ==========================================================================
931         Description:
932                 procedures on IEEE 802.11/1999 p.376
933         Parametrs:
934
935         IRQL = DISPATCH_LEVEL
936
937         ==========================================================================
938  */
939 VOID AssocPostProc(
940         IN PRTMP_ADAPTER pAd,
941         IN PUCHAR pAddr2,
942         IN USHORT CapabilityInfo,
943         IN USHORT Aid,
944         IN UCHAR SupRate[],
945         IN UCHAR SupRateLen,
946         IN UCHAR ExtRate[],
947         IN UCHAR ExtRateLen,
948         IN PEDCA_PARM pEdcaParm,
949         IN HT_CAPABILITY_IE             *pHtCapability,
950         IN UCHAR HtCapabilityLen,
951         IN ADD_HT_INFO_IE               *pAddHtInfo)    // AP might use this additional ht info IE
952 {
953         ULONG Idx;
954
955         pAd->MlmeAux.BssType = BSS_INFRA;
956         COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pAddr2);
957         pAd->MlmeAux.Aid = Aid;
958         pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
959
960         // Some HT AP might lost WMM IE. We add WMM ourselves. beacuase HT requires QoS on.
961         if ((HtCapabilityLen > 0) && (pEdcaParm->bValid == FALSE))
962         {
963                 pEdcaParm->bValid = TRUE;
964                 pEdcaParm->Aifsn[0] = 3;
965                 pEdcaParm->Aifsn[1] = 7;
966                 pEdcaParm->Aifsn[2] = 2;
967                 pEdcaParm->Aifsn[3] = 2;
968
969                 pEdcaParm->Cwmin[0] = 4;
970                 pEdcaParm->Cwmin[1] = 4;
971                 pEdcaParm->Cwmin[2] = 3;
972                 pEdcaParm->Cwmin[3] = 2;
973
974                 pEdcaParm->Cwmax[0] = 10;
975                 pEdcaParm->Cwmax[1] = 10;
976                 pEdcaParm->Cwmax[2] = 4;
977                 pEdcaParm->Cwmax[3] = 3;
978
979                 pEdcaParm->Txop[0]  = 0;
980                 pEdcaParm->Txop[1]  = 0;
981                 pEdcaParm->Txop[2]  = 96;
982                 pEdcaParm->Txop[3]  = 48;
983
984         }
985
986         NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
987
988         // filter out un-supported rates
989         pAd->MlmeAux.SupRateLen = SupRateLen;
990         NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
991         RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
992
993         // filter out un-supported rates
994         pAd->MlmeAux.ExtRateLen = ExtRateLen;
995         NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
996         RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
997
998         if (HtCapabilityLen > 0)
999         {
1000                 RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo);
1001         }
1002         DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===>  AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n", pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
1003
1004         DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===>    (Mmps=%d, AmsduSize=%d, )\n",
1005                 pAd->MacTab.Content[BSSID_WCID].MmpsMode, pAd->MacTab.Content[BSSID_WCID].AMsduSize));
1006
1007         // Set New WPA information
1008         Idx = BssTableSearch(&pAd->ScanTab, pAddr2, pAd->MlmeAux.Channel);
1009         if (Idx == BSS_NOT_FOUND)
1010         {
1011                 DBGPRINT_ERR(("ASSOC - Can't find BSS after receiving Assoc response\n"));
1012         }
1013         else
1014         {
1015                 // Init variable
1016                 pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = 0;
1017                 NdisZeroMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, MAX_LEN_OF_RSNIE);
1018
1019                 // Store appropriate RSN_IE for WPA SM negotiation later
1020                 if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAd->ScanTab.BssEntry[Idx].VarIELen != 0))
1021                 {
1022                         PUCHAR              pVIE;
1023                         USHORT              len;
1024                         PEID_STRUCT         pEid;
1025
1026                         pVIE = pAd->ScanTab.BssEntry[Idx].VarIEs;
1027                         len      = pAd->ScanTab.BssEntry[Idx].VarIELen;
1028                         //KH need to check again
1029                         // Don't allow to go to sleep mode if authmode is WPA-related.
1030                         //This can make Authentication process more smoothly.
1031                         RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
1032
1033                         while (len > 0)
1034                         {
1035                                 pEid = (PEID_STRUCT) pVIE;
1036                                 // For WPA/WPAPSK
1037                                 if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
1038                                         && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
1039                                 {
1040                                         NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2));
1041                                         pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2);
1042                                         DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA SM negotiation \n"));
1043                                 }
1044                                 // For WPA2/WPA2PSK
1045                                 else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
1046                                         && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
1047                                 {
1048                                         NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2));
1049                                         pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2);
1050                                         DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA2 SM negotiation \n"));
1051                                 }
1052
1053                                 pVIE += (pEid->Len + 2);
1054                                 len  -= (pEid->Len + 2);
1055                         }
1056
1057
1058                 }
1059
1060                 if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0)
1061                 {
1062                         DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> no RSN_IE \n"));
1063                 }
1064                 else
1065                 {
1066                         hex_dump("RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len);
1067                 }
1068         }
1069 }
1070
1071 /*
1072         ==========================================================================
1073         Description:
1074                 left part of IEEE 802.11/1999 p.374
1075         Parameters:
1076                 Elem - MLME message containing the received frame
1077
1078         IRQL = DISPATCH_LEVEL
1079
1080         ==========================================================================
1081  */
1082 VOID PeerDisassocAction(
1083         IN PRTMP_ADAPTER pAd,
1084         IN MLME_QUEUE_ELEM *Elem)
1085 {
1086         UCHAR         Addr2[MAC_ADDR_LEN];
1087         USHORT        Reason;
1088
1089         DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction()\n"));
1090         if(PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason))
1091         {
1092                 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() Reason = %d\n", Reason));
1093                 if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, Addr2))
1094                 {
1095
1096                         if (pAd->CommonCfg.bWirelessEvent)
1097                         {
1098                                 RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1099                         }
1100
1101
1102                         LinkDown(pAd, TRUE);
1103                         pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1104
1105
1106                         RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0);
1107                 }
1108         }
1109         else
1110         {
1111                 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() sanity check fail\n"));
1112         }
1113
1114 }
1115
1116 /*
1117         ==========================================================================
1118         Description:
1119                 what the state machine will do after assoc timeout
1120         Parameters:
1121                 Elme -
1122
1123         IRQL = DISPATCH_LEVEL
1124
1125         ==========================================================================
1126  */
1127 VOID AssocTimeoutAction(
1128         IN PRTMP_ADAPTER pAd,
1129         IN MLME_QUEUE_ELEM *Elem)
1130 {
1131         USHORT  Status;
1132         DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - AssocTimeoutAction\n"));
1133         pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1134         Status = MLME_REJ_TIMEOUT;
1135         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
1136 }
1137
1138 /*
1139         ==========================================================================
1140         Description:
1141                 what the state machine will do after reassoc timeout
1142
1143         IRQL = DISPATCH_LEVEL
1144
1145         ==========================================================================
1146  */
1147 VOID ReassocTimeoutAction(
1148         IN PRTMP_ADAPTER pAd,
1149         IN MLME_QUEUE_ELEM *Elem)
1150 {
1151         USHORT  Status;
1152         DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - ReassocTimeoutAction\n"));
1153         pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1154         Status = MLME_REJ_TIMEOUT;
1155         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
1156 }
1157
1158 /*
1159         ==========================================================================
1160         Description:
1161                 what the state machine will do after disassoc timeout
1162
1163         IRQL = DISPATCH_LEVEL
1164
1165         ==========================================================================
1166  */
1167 VOID DisassocTimeoutAction(
1168         IN PRTMP_ADAPTER pAd,
1169         IN MLME_QUEUE_ELEM *Elem)
1170 {
1171         USHORT  Status;
1172         DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - DisassocTimeoutAction\n"));
1173         pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1174         Status = MLME_SUCCESS;
1175         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
1176 }
1177
1178 VOID InvalidStateWhenAssoc(
1179         IN PRTMP_ADAPTER pAd,
1180         IN MLME_QUEUE_ELEM *Elem)
1181 {
1182         USHORT  Status;
1183         DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenAssoc(state=%ld), reset ASSOC state machine\n",
1184                 pAd->Mlme.AssocMachine.CurrState));
1185         pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1186         Status = MLME_STATE_MACHINE_REJECT;
1187         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
1188 }
1189
1190 VOID InvalidStateWhenReassoc(
1191         IN PRTMP_ADAPTER pAd,
1192         IN MLME_QUEUE_ELEM *Elem)
1193 {
1194         USHORT Status;
1195         DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenReassoc(state=%ld), reset ASSOC state machine\n",
1196                 pAd->Mlme.AssocMachine.CurrState));
1197         pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1198         Status = MLME_STATE_MACHINE_REJECT;
1199         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
1200 }
1201
1202 VOID InvalidStateWhenDisassociate(
1203         IN PRTMP_ADAPTER pAd,
1204         IN MLME_QUEUE_ELEM *Elem)
1205 {
1206         USHORT Status;
1207         DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenDisassoc(state=%ld), reset ASSOC state machine\n",
1208                 pAd->Mlme.AssocMachine.CurrState));
1209         pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1210         Status = MLME_STATE_MACHINE_REJECT;
1211         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
1212 }
1213
1214 /*
1215         ==========================================================================
1216         Description:
1217                 right part of IEEE 802.11/1999 page 374
1218         Note:
1219                 This event should never cause ASSOC state machine perform state
1220                 transition, and has no relationship with CNTL machine. So we separate
1221                 this routine as a service outside of ASSOC state transition table.
1222
1223         IRQL = DISPATCH_LEVEL
1224
1225         ==========================================================================
1226  */
1227 VOID Cls3errAction(
1228         IN PRTMP_ADAPTER pAd,
1229         IN PUCHAR        pAddr)
1230 {
1231         HEADER_802_11         DisassocHdr;
1232         PHEADER_802_11        pDisassocHdr;
1233         PUCHAR                pOutBuffer = NULL;
1234         ULONG                 FrameLen = 0;
1235         NDIS_STATUS           NStatus;
1236         USHORT                Reason = REASON_CLS3ERR;
1237
1238         NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
1239         if (NStatus != NDIS_STATUS_SUCCESS)
1240                 return;
1241
1242         DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Class 3 Error, Send DISASSOC frame\n"));
1243         MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAddr, pAd->CommonCfg.Bssid);  // patch peap ttls switching issue
1244         MakeOutgoingFrame(pOutBuffer,           &FrameLen,
1245                                           sizeof(HEADER_802_11),&DisassocHdr,
1246                                           2,                    &Reason,
1247                                           END_OF_ARGS);
1248         MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1249
1250         // To patch Instance and Buffalo(N) AP
1251         // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine
1252         // Therefore, we send both of them.
1253         pDisassocHdr = (PHEADER_802_11)pOutBuffer;
1254         pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH;
1255         MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1256
1257         MlmeFreeMemory(pAd, pOutBuffer);
1258
1259         pAd->StaCfg.DisassocReason = REASON_CLS3ERR;
1260         COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pAddr);
1261 }
1262
1263
1264 int wext_notify_event_assoc(
1265         IN  RTMP_ADAPTER *pAd)
1266 {
1267     char custom[IW_CUSTOM_MAX] = {0};
1268
1269     if (pAd->StaCfg.ReqVarIELen <= IW_CUSTOM_MAX)
1270     {
1271                 NdisMoveMemory(custom, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen);
1272                 RtmpOSWrielessEventSend(pAd, IWEVASSOCREQIE, -1, NULL, custom, pAd->StaCfg.ReqVarIELen);
1273     }
1274     else
1275         DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen > MAX_CUSTOM_LEN\n"));
1276
1277         return 0;
1278
1279 }
1280
1281
1282 BOOLEAN StaAddMacTableEntry(
1283         IN  PRTMP_ADAPTER               pAd,
1284         IN  PMAC_TABLE_ENTRY    pEntry,
1285         IN  UCHAR                               MaxSupportedRateIn500Kbps,
1286         IN  HT_CAPABILITY_IE    *pHtCapability,
1287         IN  UCHAR                               HtCapabilityLen,
1288         IN  ADD_HT_INFO_IE              *pAddHtInfo,
1289         IN  UCHAR                               AddHtInfoLen,
1290         IN  USHORT                      CapabilityInfo)
1291 {
1292         UCHAR            MaxSupportedRate = RATE_11;
1293
1294         if (ADHOC_ON(pAd))
1295                 CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
1296
1297         switch (MaxSupportedRateIn500Kbps)
1298     {
1299         case 108: MaxSupportedRate = RATE_54;   break;
1300         case 96:  MaxSupportedRate = RATE_48;   break;
1301         case 72:  MaxSupportedRate = RATE_36;   break;
1302         case 48:  MaxSupportedRate = RATE_24;   break;
1303         case 36:  MaxSupportedRate = RATE_18;   break;
1304         case 24:  MaxSupportedRate = RATE_12;   break;
1305         case 18:  MaxSupportedRate = RATE_9;    break;
1306         case 12:  MaxSupportedRate = RATE_6;    break;
1307         case 22:  MaxSupportedRate = RATE_11;   break;
1308         case 11:  MaxSupportedRate = RATE_5_5;  break;
1309         case 4:   MaxSupportedRate = RATE_2;    break;
1310         case 2:   MaxSupportedRate = RATE_1;    break;
1311         default:  MaxSupportedRate = RATE_11;   break;
1312     }
1313
1314     if ((pAd->CommonCfg.PhyMode == PHY_11G) && (MaxSupportedRate < RATE_FIRST_OFDM_RATE))
1315         return FALSE;
1316
1317         // 11n only
1318         if (((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))&& (HtCapabilityLen == 0))
1319                 return FALSE;
1320
1321         if (!pEntry)
1322         return FALSE;
1323
1324         NdisAcquireSpinLock(&pAd->MacTabLock);
1325         if (pEntry)
1326         {
1327                 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1328                 if ((MaxSupportedRate < RATE_FIRST_OFDM_RATE) ||
1329                         (pAd->CommonCfg.PhyMode == PHY_11B))
1330                 {
1331                         pEntry->RateLen = 4;
1332                         if (MaxSupportedRate >= RATE_FIRST_OFDM_RATE)
1333                                 MaxSupportedRate = RATE_11;
1334                 }
1335                 else
1336                         pEntry->RateLen = 12;
1337
1338                 pEntry->MaxHTPhyMode.word = 0;
1339                 pEntry->MinHTPhyMode.word = 0;
1340                 pEntry->HTPhyMode.word = 0;
1341                 pEntry->MaxSupportedRate = MaxSupportedRate;
1342                 if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
1343                 {
1344                         pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
1345                         pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
1346                         pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
1347                         pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
1348                         pEntry->HTPhyMode.field.MODE = MODE_CCK;
1349                         pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
1350                 }
1351                 else
1352                 {
1353                         pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
1354                         pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
1355                         pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
1356                         pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
1357                         pEntry->HTPhyMode.field.MODE = MODE_OFDM;
1358                         pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
1359                 }
1360                 pEntry->CapabilityInfo = CapabilityInfo;
1361                 CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE);
1362                 CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE);
1363         }
1364
1365         NdisZeroMemory(&pEntry->HTCapability, sizeof(pEntry->HTCapability));
1366         // If this Entry supports 802.11n, upgrade to HT rate.
1367         if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
1368         {
1369                 UCHAR   j, bitmask; //k,bitmask;
1370                 CHAR    i;
1371
1372                 if (ADHOC_ON(pAd))
1373                         CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
1374                 if ((pHtCapability->HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
1375                 {
1376                         pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
1377                 }
1378                 else
1379                 {
1380                         pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
1381                         pAd->MacTab.fAnyStationNonGF = TRUE;
1382                         pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
1383                 }
1384
1385                 if ((pHtCapability->HtCapInfo.ChannelWidth) &&
1386                         (pAd->CommonCfg.DesiredHtPhy.ChannelWidth) &&
1387                         ((pAd->StaCfg.BssType == BSS_INFRA) || ((pAd->StaCfg.BssType == BSS_ADHOC) && (pAddHtInfo->AddHtInfo.ExtChanOffset == pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset))))
1388                 {
1389                         pEntry->MaxHTPhyMode.field.BW= BW_40;
1390                         pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pHtCapability->HtCapInfo.ShortGIfor40));
1391                 }
1392                 else
1393                 {
1394                         pEntry->MaxHTPhyMode.field.BW = BW_20;
1395                         pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(pHtCapability->HtCapInfo.ShortGIfor20));
1396                         pAd->MacTab.fAnyStation20Only = TRUE;
1397                 }
1398
1399                 // 3*3
1400                 if (pAd->MACVersion >= RALINK_2883_VERSION && pAd->MACVersion < RALINK_3070_VERSION)
1401                         pEntry->MaxHTPhyMode.field.TxBF = pAd->CommonCfg.RegTransmitSetting.field.TxBF;
1402
1403                 // find max fixed rate
1404                 for (i=23; i>=0; i--) // 3*3
1405                 {
1406                         j = i/8;
1407                         bitmask = (1<<(i-(j*8)));
1408                         if ((pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j] & bitmask) && (pHtCapability->MCSSet[j] & bitmask))
1409                         {
1410                                 pEntry->MaxHTPhyMode.field.MCS = i;
1411                                 break;
1412                         }
1413                         if (i==0)
1414                                 break;
1415                 }
1416
1417
1418                 if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
1419                 {
1420                         if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
1421                         {
1422                                 // Fix MCS as HT Duplicated Mode
1423                                 pEntry->MaxHTPhyMode.field.BW = 1;
1424                                 pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
1425                                 pEntry->MaxHTPhyMode.field.STBC = 0;
1426                                 pEntry->MaxHTPhyMode.field.ShortGI = 0;
1427                                 pEntry->MaxHTPhyMode.field.MCS = 32;
1428                         }
1429                         else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
1430                         {
1431                                 // STA supports fixed MCS
1432                                 pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1433                         }
1434                 }
1435
1436                 pEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
1437                 pEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity;
1438                 pEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor;
1439                 pEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs;
1440                 pEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize;
1441                 pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
1442
1443                 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE))
1444                         CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED);
1445                 if (pHtCapability->HtCapInfo.ShortGIfor20)
1446                         CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
1447                 if (pHtCapability->HtCapInfo.ShortGIfor40)
1448                         CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
1449                 if (pHtCapability->HtCapInfo.TxSTBC)
1450                         CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
1451                 if (pHtCapability->HtCapInfo.RxSTBC)
1452                         CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
1453                 if (pHtCapability->ExtHtCapInfo.PlusHTC)
1454                         CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
1455                 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
1456                         CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
1457                 if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03)
1458                         CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
1459                 NdisMoveMemory(&pEntry->HTCapability, pHtCapability, HtCapabilityLen);
1460         }
1461         else
1462         {
1463                 pAd->MacTab.fAnyStationIsLegacy = TRUE;
1464         }
1465
1466         pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
1467         pEntry->CurrTxRate = pEntry->MaxSupportedRate;
1468
1469         // Set asic auto fall back
1470         if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1471         {
1472                 PUCHAR                                  pTable;
1473                 UCHAR                                   TableSize = 0;
1474
1475                 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
1476                 pEntry->bAutoTxRateSwitch = TRUE;
1477         }
1478         else
1479         {
1480                 pEntry->HTPhyMode.field.MODE    = pAd->StaCfg.HTPhyMode.field.MODE;
1481                 pEntry->HTPhyMode.field.MCS     = pAd->StaCfg.HTPhyMode.field.MCS;
1482                 pEntry->bAutoTxRateSwitch = FALSE;
1483
1484                 // If the legacy mode is set, overwrite the transmit setting of this entry.
1485                 RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
1486         }
1487
1488         pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1489         pEntry->Sst = SST_ASSOC;
1490         pEntry->AuthState = AS_AUTH_OPEN;
1491         pEntry->AuthMode = pAd->StaCfg.AuthMode;
1492         pEntry->WepStatus = pAd->StaCfg.WepStatus;
1493
1494         NdisReleaseSpinLock(&pAd->MacTabLock);
1495
1496     {
1497         union iwreq_data    wrqu;
1498         wext_notify_event_assoc(pAd);
1499
1500         memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1501         memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
1502         wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1503
1504     }
1505         return TRUE;
1506 }