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