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  */
AssocStateMachineInit(struct rt_rtmp_adapter * pAd,struct rt_state_machine * S,OUT STATE_MACHINE_FUNC Trans[])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  */
AssocTimeout(void * SystemSpecific1,void * FunctionContext,void * SystemSpecific2,void * SystemSpecific3)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  */
ReassocTimeout(void * SystemSpecific1,void * FunctionContext,void * SystemSpecific2,void * SystemSpecific3)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  */
DisassocTimeout(void * SystemSpecific1,void * FunctionContext,void * SystemSpecific2,void * SystemSpecific3)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  */
MlmeAssocReqAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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  */
MlmeReassocReqAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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  */
MlmeDisassocReqAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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  */
PeerAssocRspAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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  */
PeerReassocRspAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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  */
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)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  */
PeerDisassocAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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  */
AssocTimeoutAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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  */
ReassocTimeoutAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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  */
DisassocTimeoutAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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 
InvalidStateWhenAssoc(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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 
InvalidStateWhenReassoc(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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 
InvalidStateWhenDisassociate(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)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  */
Cls3errAction(struct rt_rtmp_adapter * pAd,u8 * pAddr)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 
wext_notify_event_assoc(struct rt_rtmp_adapter * pAd)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 
StaAddMacTableEntry(struct rt_rtmp_adapter * pAd,struct rt_mac_table_entry * pEntry,u8 MaxSupportedRateIn500Kbps,struct rt_ht_capability_ie * pHtCapability,u8 HtCapabilityLen,struct rt_add_ht_info_ie * pAddHtInfo,u8 AddHtInfoLen,u16 CapabilityInfo)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 }
1603