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