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