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 sync.c 29 30 Abstract: 31 32 Revision History: 33 Who When What 34 -------- ---------- ---------------------------------------------- 35 John Chang 2004-09-01 modified for rt2561/2661 36 Jan Lee 2006-08-01 modified for rt2860 for 802.11n 37*/ 38#include "../rt_config.h" 39 40#define ADHOC_ENTRY_BEACON_LOST_TIME (2*OS_HZ) /* 2 sec */ 41 42/* 43 ========================================================================== 44 Description: 45 The sync state machine, 46 Parameters: 47 Sm - pointer to the state machine 48 Note: 49 the state machine looks like the following 50 51 ========================================================================== 52 */ 53void SyncStateMachineInit(struct rt_rtmp_adapter *pAd, 54 struct rt_state_machine *Sm, OUT STATE_MACHINE_FUNC Trans[]) 55{ 56 StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, 57 (STATE_MACHINE_FUNC) Drop, SYNC_IDLE, 58 SYNC_MACHINE_BASE); 59 60 /* column 1 */ 61 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, 62 (STATE_MACHINE_FUNC) MlmeScanReqAction); 63 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, 64 (STATE_MACHINE_FUNC) MlmeJoinReqAction); 65 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, 66 (STATE_MACHINE_FUNC) MlmeStartReqAction); 67 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, 68 (STATE_MACHINE_FUNC) PeerBeacon); 69 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, 70 (STATE_MACHINE_FUNC) PeerProbeReqAction); 71 72 /*column 2 */ 73 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, 74 (STATE_MACHINE_FUNC) InvalidStateWhenScan); 75 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, 76 (STATE_MACHINE_FUNC) InvalidStateWhenJoin); 77 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, 78 (STATE_MACHINE_FUNC) InvalidStateWhenStart); 79 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, 80 (STATE_MACHINE_FUNC) PeerBeaconAtJoinAction); 81 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, 82 (STATE_MACHINE_FUNC) BeaconTimeoutAtJoinAction); 83 84 /* column 3 */ 85 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, 86 (STATE_MACHINE_FUNC) InvalidStateWhenScan); 87 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, 88 (STATE_MACHINE_FUNC) InvalidStateWhenJoin); 89 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, 90 (STATE_MACHINE_FUNC) InvalidStateWhenStart); 91 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, 92 (STATE_MACHINE_FUNC) PeerBeaconAtScanAction); 93 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, 94 (STATE_MACHINE_FUNC) PeerBeaconAtScanAction); 95 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, 96 (STATE_MACHINE_FUNC) ScanTimeoutAction); 97 98 /* timer init */ 99 RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, 100 GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE); 101 RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, 102 GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE); 103} 104 105/* 106 ========================================================================== 107 Description: 108 Beacon timeout handler, executed in timer thread 109 110 IRQL = DISPATCH_LEVEL 111 112 ========================================================================== 113 */ 114void BeaconTimeout(void *SystemSpecific1, 115 void *FunctionContext, 116 void *SystemSpecific2, void *SystemSpecific3) 117{ 118 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; 119 120 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeout\n")); 121 122 /* Do nothing if the driver is starting halt state. */ 123 /* This might happen when timer already been fired before cancel timer with mlmehalt */ 124 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) 125 return; 126 127 if ((pAd->CommonCfg.BBPCurrentBW == BW_40) 128 ) { 129 u8 BBPValue = 0; 130 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); 131 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); 132 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); 133 BBPValue &= (~0x18); 134 BBPValue |= 0x10; 135 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); 136 DBGPRINT(RT_DEBUG_TRACE, 137 ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n", 138 pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); 139 } 140 141 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL); 142 RTMP_MLME_HANDLER(pAd); 143} 144 145/* 146 ========================================================================== 147 Description: 148 Scan timeout handler, executed in timer thread 149 150 IRQL = DISPATCH_LEVEL 151 152 ========================================================================== 153 */ 154void ScanTimeout(void *SystemSpecific1, 155 void *FunctionContext, 156 void *SystemSpecific2, void *SystemSpecific3) 157{ 158 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; 159 160 /* Do nothing if the driver is starting halt state. */ 161 /* This might happen when timer already been fired before cancel timer with mlmehalt */ 162 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) 163 return; 164 165 if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL)) { 166 RTMP_MLME_HANDLER(pAd); 167 } else { 168 /* To prevent SyncMachine.CurrState is SCAN_LISTEN forever. */ 169 pAd->MlmeAux.Channel = 0; 170 ScanNextChannel(pAd); 171 if (pAd->CommonCfg.bWirelessEvent) { 172 RTMPSendWirelessEvent(pAd, 173 IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, 174 pAd->MacTab.Content[BSSID_WCID]. 175 Addr, BSS0, 0); 176 } 177 } 178} 179 180/* 181 ========================================================================== 182 Description: 183 MLME SCAN req state machine procedure 184 ========================================================================== 185 */ 186void MlmeScanReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 187{ 188 u8 Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0; 189 BOOLEAN TimerCancelled; 190 unsigned long Now; 191 u16 Status; 192 struct rt_header_802_11 * pHdr80211; 193 u8 *pOutBuffer = NULL; 194 int NStatus; 195 196 /* Check the total scan tries for one single OID command */ 197 /* If this is the CCX 2.0 Case, skip that! */ 198 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) { 199 DBGPRINT(RT_DEBUG_TRACE, 200 ("SYNC - MlmeScanReqAction before Startup\n")); 201 return; 202 } 203 /* Increase the scan retry counters. */ 204 pAd->StaCfg.ScanCnt++; 205 206#ifdef RTMP_MAC_PCI 207 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) && 208 (IDLE_ON(pAd)) && 209 (pAd->StaCfg.bRadio == TRUE) && 210 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) { 211 if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) { 212 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 213 0x02); 214 AsicCheckCommanOk(pAd, PowerWakeCID); 215 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); 216 DBGPRINT(RT_DEBUG_TRACE, 217 ("PSM - Issue Wake up command \n")); 218 } else { 219 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); 220 } 221 } 222#endif /* RTMP_MAC_PCI // */ 223 224 /* first check the parameter sanity */ 225 if (MlmeScanReqSanity(pAd, 226 Elem->Msg, 227 Elem->MsgLen, 228 &BssType, (char *)Ssid, &SsidLen, &ScanType)) { 229 230 /* Check for channel load and noise hist request */ 231 /* Suspend MSDU only at scan request, not the last two mentioned */ 232 /* Suspend MSDU transmission here */ 233 RTMPSuspendMsduTransmission(pAd); 234 235 /* */ 236 /* To prevent data lost. */ 237 /* Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. */ 238 /* And should send an NULL data with turned PSM bit off to AP, when scan progress done */ 239 /* */ 240 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) 241 && (INFRA_ON(pAd))) { 242 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); 243 if (NStatus == NDIS_STATUS_SUCCESS) { 244 pHdr80211 = (struct rt_header_802_11 *) pOutBuffer; 245 MgtMacHeaderInit(pAd, pHdr80211, 246 SUBTYPE_NULL_FUNC, 1, 247 pAd->CommonCfg.Bssid, 248 pAd->CommonCfg.Bssid); 249 pHdr80211->Duration = 0; 250 pHdr80211->FC.Type = BTYPE_DATA; 251 pHdr80211->FC.PwrMgmt = PWR_SAVE; 252 253 /* Send using priority queue */ 254 MiniportMMRequest(pAd, 0, pOutBuffer, 255 sizeof(struct rt_header_802_11)); 256 DBGPRINT(RT_DEBUG_TRACE, 257 ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n")); 258 MlmeFreeMemory(pAd, pOutBuffer); 259 RTMPusecDelay(5000); 260 } 261 } 262 263 NdisGetSystemUpTime(&Now); 264 pAd->StaCfg.LastScanTime = Now; 265 /* reset all the timers */ 266 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); 267 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); 268 269 /* record desired BSS parameters */ 270 pAd->MlmeAux.BssType = BssType; 271 pAd->MlmeAux.ScanType = ScanType; 272 pAd->MlmeAux.SsidLen = SsidLen; 273 NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); 274 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); 275 276 /* start from the first channel */ 277 pAd->MlmeAux.Channel = FirstChannel(pAd); 278 279 /* Let BBP register at 20MHz to do scan */ 280 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); 281 BBPValue &= (~0x18); 282 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); 283 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); 284 ScanNextChannel(pAd); 285 } else { 286 DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n")); 287 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; 288 Status = MLME_INVALID_FORMAT; 289 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, 290 &Status); 291 } 292} 293 294/* 295 ========================================================================== 296 Description: 297 MLME JOIN req state machine procedure 298 ========================================================================== 299 */ 300void MlmeJoinReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 301{ 302 u8 BBPValue = 0; 303 struct rt_bss_entry *pBss; 304 BOOLEAN TimerCancelled; 305 struct rt_header_802_11 Hdr80211; 306 int NStatus; 307 unsigned long FrameLen = 0; 308 u8 *pOutBuffer = NULL; 309 u8 *pSupRate = NULL; 310 u8 SupRateLen; 311 u8 *pExtRate = NULL; 312 u8 ExtRateLen; 313 u8 ASupRate[] = { 0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C }; 314 u8 ASupRateLen = sizeof(ASupRate) / sizeof(u8); 315 struct rt_mlme_join_req *pInfo = (struct rt_mlme_join_req *)(Elem->Msg); 316 317 DBGPRINT(RT_DEBUG_TRACE, 318 ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx)); 319 320#ifdef RTMP_MAC_PCI 321 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) && 322 (IDLE_ON(pAd)) && 323 (pAd->StaCfg.bRadio == TRUE) && 324 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) { 325 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); 326 } 327#endif /* RTMP_MAC_PCI // */ 328 329 /* reset all the timers */ 330 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); 331 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); 332 333 pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx]; 334 335 /* record the desired SSID & BSSID we're waiting for */ 336 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid); 337 338 /* If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again. */ 339 if (pBss->Hidden == 0) { 340 RTMPZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); 341 NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen); 342 pAd->MlmeAux.SsidLen = pBss->SsidLen; 343 } 344 345 pAd->MlmeAux.BssType = pBss->BssType; 346 pAd->MlmeAux.Channel = pBss->Channel; 347 pAd->MlmeAux.CentralChannel = pBss->CentralChannel; 348 349 /* Let BBP register at 20MHz to do scan */ 350 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); 351 BBPValue &= (~0x18); 352 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); 353 354 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); 355 356 /* switch channel and waiting for beacon timer */ 357 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); 358 AsicLockChannel(pAd, pAd->MlmeAux.Channel); 359 RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT); 360 361 do { 362 if (((pAd->CommonCfg.bIEEE80211H == 1) && 363 (pAd->MlmeAux.Channel > 14) && 364 RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) 365 ) { 366 /* */ 367 /* We can't send any Probe request frame to meet 802.11h. */ 368 /* */ 369 if (pBss->Hidden == 0) 370 break; 371 } 372 /* */ 373 /* send probe request */ 374 /* */ 375 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); 376 if (NStatus == NDIS_STATUS_SUCCESS) { 377 if (pAd->MlmeAux.Channel <= 14) { 378 pSupRate = pAd->CommonCfg.SupRate; 379 SupRateLen = pAd->CommonCfg.SupRateLen; 380 pExtRate = pAd->CommonCfg.ExtRate; 381 ExtRateLen = pAd->CommonCfg.ExtRateLen; 382 } else { 383 /* */ 384 /* Overwrite Support Rate, CCK rate are not allowed */ 385 /* */ 386 pSupRate = ASupRate; 387 SupRateLen = ASupRateLen; 388 ExtRateLen = 0; 389 } 390 391 if (pAd->MlmeAux.BssType == BSS_INFRA) 392 MgtMacHeaderInit(pAd, &Hdr80211, 393 SUBTYPE_PROBE_REQ, 0, 394 pAd->MlmeAux.Bssid, 395 pAd->MlmeAux.Bssid); 396 else 397 MgtMacHeaderInit(pAd, &Hdr80211, 398 SUBTYPE_PROBE_REQ, 0, 399 BROADCAST_ADDR, 400 BROADCAST_ADDR); 401 402 MakeOutgoingFrame(pOutBuffer, &FrameLen, 403 sizeof(struct rt_header_802_11), &Hdr80211, 404 1, &SsidIe, 405 1, &pAd->MlmeAux.SsidLen, 406 pAd->MlmeAux.SsidLen, 407 pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, 408 &SupRateLen, SupRateLen, pSupRate, 409 END_OF_ARGS); 410 411 if (ExtRateLen) { 412 unsigned long Tmp; 413 MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, 414 1, &ExtRateIe, 415 1, &ExtRateLen, 416 ExtRateLen, pExtRate, 417 END_OF_ARGS); 418 FrameLen += Tmp; 419 } 420 421 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); 422 MlmeFreeMemory(pAd, pOutBuffer); 423 } 424 } while (FALSE); 425 426 DBGPRINT(RT_DEBUG_TRACE, 427 ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n", 428 pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], 429 pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); 430 431 pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON; 432} 433 434/* 435 ========================================================================== 436 Description: 437 MLME START Request state machine procedure, starting an IBSS 438 ========================================================================== 439 */ 440void MlmeStartReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 441{ 442 u8 Ssid[MAX_LEN_OF_SSID], SsidLen; 443 BOOLEAN TimerCancelled; 444 445 /* New for WPA security suites */ 446 u8 VarIE[MAX_VIE_LEN]; /* Total VIE length = MAX_VIE_LEN - -5 */ 447 struct rt_ndis_802_11_variable_ies *pVIE = NULL; 448 LARGE_INTEGER TimeStamp; 449 BOOLEAN Privacy; 450 u16 Status; 451 452 /* Init Variable IE structure */ 453 pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE; 454 pVIE->Length = 0; 455 TimeStamp.u.LowPart = 0; 456 TimeStamp.u.HighPart = 0; 457 458 if (MlmeStartReqSanity 459 (pAd, Elem->Msg, Elem->MsgLen, (char *)Ssid, &SsidLen)) { 460 /* reset all the timers */ 461 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); 462 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); 463 464 /* */ 465 /* Start a new IBSS. All IBSS parameters are decided now.... */ 466 /* */ 467 DBGPRINT(RT_DEBUG_TRACE, 468 ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n")); 469 pAd->MlmeAux.BssType = BSS_ADHOC; 470 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); 471 pAd->MlmeAux.SsidLen = SsidLen; 472 473 /* generate a radom number as BSSID */ 474 MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid); 475 DBGPRINT(RT_DEBUG_TRACE, 476 ("MlmeStartReqAction - generate a radom number as BSSID \n")); 477 478 Privacy = 479 (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) 480 || (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) 481 || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); 482 pAd->MlmeAux.CapabilityInfo = 483 CAP_GENERATE(0, 1, Privacy, 484 (pAd->CommonCfg.TxPreamble == 485 Rt802_11PreambleShort), 1, 0); 486 pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod; 487 pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin; 488 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; 489 490 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; 491 pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel; 492 493 pAd->MlmeAux.SupRateLen = pAd->CommonCfg.SupRateLen; 494 NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, 495 MAX_LEN_OF_SUPPORTED_RATES); 496 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, 497 &pAd->MlmeAux.SupRateLen); 498 pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; 499 NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, 500 MAX_LEN_OF_SUPPORTED_RATES); 501 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, 502 &pAd->MlmeAux.ExtRateLen); 503 504 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { 505 RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, 506 &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], 507 &pAd->MlmeAux.HtCapability, 508 &pAd->MlmeAux.AddHtInfo); 509 pAd->MlmeAux.HtCapabilityLen = sizeof(struct rt_ht_capability_ie); 510 /* Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here. */ 511 DBGPRINT(RT_DEBUG_TRACE, 512 ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n")); 513 } else { 514 pAd->MlmeAux.HtCapabilityLen = 0; 515 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; 516 NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo. 517 MCSSet[0], 16); 518 } 519 /* temporarily not support QOS in IBSS */ 520 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(struct rt_edca_parm)); 521 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, 522 sizeof(struct rt_qbss_load_parm)); 523 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, 524 sizeof(struct rt_qos_capability_parm)); 525 526 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); 527 AsicLockChannel(pAd, pAd->MlmeAux.Channel); 528 529 DBGPRINT(RT_DEBUG_TRACE, 530 ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n", 531 pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, 532 pAd->MlmeAux.ExtRateLen)); 533 534 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; 535 Status = MLME_SUCCESS; 536 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, 537 &Status); 538 } else { 539 DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n")); 540 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; 541 Status = MLME_INVALID_FORMAT; 542 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, 543 &Status); 544 } 545} 546 547/* 548 ========================================================================== 549 Description: 550 peer sends beacon back when scanning 551 ========================================================================== 552 */ 553void PeerBeaconAtScanAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 554{ 555 u8 Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; 556 u8 Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel, 557 SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe; 558 struct rt_cf_parm CfParm; 559 u16 BeaconPeriod, AtimWin, CapabilityInfo; 560 struct rt_frame_802_11 * pFrame; 561 LARGE_INTEGER TimeStamp; 562 u8 Erp; 563 u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES], 564 ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; 565 u8 SupRateLen, ExtRateLen; 566 u16 LenVIE; 567 u8 CkipFlag; 568 u8 AironetCellPowerLimit; 569 struct rt_edca_parm EdcaParm; 570 struct rt_qbss_load_parm QbssLoad; 571 struct rt_qos_capability_parm QosCapability; 572 unsigned long RalinkIe; 573 u8 VarIE[MAX_VIE_LEN]; /* Total VIE length = MAX_VIE_LEN - -5 */ 574 struct rt_ndis_802_11_variable_ies *pVIE = NULL; 575 struct rt_ht_capability_ie HtCapability; 576 struct rt_add_ht_info_ie AddHtInfo; /* AP might use this additional ht info IE */ 577 u8 HtCapabilityLen = 0, PreNHtCapabilityLen = 0; 578 u8 AddHtInfoLen; 579 u8 NewExtChannelOffset = 0xff; 580 581 /* NdisFillMemory(Ssid, MAX_LEN_OF_SSID, 0x00); */ 582 pFrame = (struct rt_frame_802_11 *) Elem->Msg; 583 /* Init Variable IE structure */ 584 pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE; 585 pVIE->Length = 0; 586 587 RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); 588 RTMPZeroMemory(&AddHtInfo, sizeof(struct rt_add_ht_info_ie)); 589 590 if (PeerBeaconAndProbeRspSanity(pAd, 591 Elem->Msg, 592 Elem->MsgLen, 593 Elem->Channel, 594 Addr2, 595 Bssid, 596 (char *)Ssid, 597 &SsidLen, 598 &BssType, 599 &BeaconPeriod, 600 &Channel, 601 &NewChannel, 602 &TimeStamp, 603 &CfParm, 604 &AtimWin, 605 &CapabilityInfo, 606 &Erp, 607 &DtimCount, 608 &DtimPeriod, 609 &BcastFlag, 610 &MessageToMe, 611 SupRate, 612 &SupRateLen, 613 ExtRate, 614 &ExtRateLen, 615 &CkipFlag, 616 &AironetCellPowerLimit, 617 &EdcaParm, 618 &QbssLoad, 619 &QosCapability, 620 &RalinkIe, 621 &HtCapabilityLen, 622 &PreNHtCapabilityLen, 623 &HtCapability, 624 &AddHtInfoLen, 625 &AddHtInfo, 626 &NewExtChannelOffset, &LenVIE, pVIE)) { 627 unsigned long Idx; 628 char Rssi = 0; 629 630 Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); 631 if (Idx != BSS_NOT_FOUND) 632 Rssi = pAd->ScanTab.BssEntry[Idx].Rssi; 633 634 Rssi = 635 RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), 636 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), 637 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); 638 639 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) 640 HtCapabilityLen = SIZE_HT_CAP_IE; 641 642 Idx = 643 BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, (char *)Ssid, 644 SsidLen, BssType, BeaconPeriod, &CfParm, 645 AtimWin, CapabilityInfo, SupRate, 646 SupRateLen, ExtRate, ExtRateLen, 647 &HtCapability, &AddHtInfo, HtCapabilityLen, 648 AddHtInfoLen, NewExtChannelOffset, Channel, 649 Rssi, TimeStamp, CkipFlag, &EdcaParm, 650 &QosCapability, &QbssLoad, LenVIE, pVIE); 651 652 if (Idx != BSS_NOT_FOUND) { 653 NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, 654 &Elem->Msg[24], 4); 655 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], 656 &Elem->TimeStamp.u.LowPart, 4); 657 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], 658 &Elem->TimeStamp.u.LowPart, 4); 659 } 660 661 } 662 /* sanity check fail, ignored */ 663} 664 665/* 666 ========================================================================== 667 Description: 668 When waiting joining the (I)BSS, beacon received from external 669 ========================================================================== 670 */ 671void PeerBeaconAtJoinAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 672{ 673 u8 Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; 674 u8 Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe, 675 DtimCount, DtimPeriod, BcastFlag, NewChannel; 676 LARGE_INTEGER TimeStamp; 677 u16 BeaconPeriod, AtimWin, CapabilityInfo; 678 struct rt_cf_parm Cf; 679 BOOLEAN TimerCancelled; 680 u8 Erp; 681 u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES], 682 ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; 683 u8 SupRateLen, ExtRateLen; 684 u8 CkipFlag; 685 u16 LenVIE; 686 u8 AironetCellPowerLimit; 687 struct rt_edca_parm EdcaParm; 688 struct rt_qbss_load_parm QbssLoad; 689 struct rt_qos_capability_parm QosCapability; 690 u16 Status; 691 u8 VarIE[MAX_VIE_LEN]; /* Total VIE length = MAX_VIE_LEN - -5 */ 692 struct rt_ndis_802_11_variable_ies *pVIE = NULL; 693 unsigned long RalinkIe; 694 unsigned long Idx; 695 struct rt_ht_capability_ie HtCapability; 696 struct rt_add_ht_info_ie AddHtInfo; /* AP might use this additional ht info IE */ 697 u8 HtCapabilityLen = 0, PreNHtCapabilityLen = 0; 698 u8 AddHtInfoLen; 699 u8 NewExtChannelOffset = 0xff; 700 u8 CentralChannel; 701 BOOLEAN bAllowNrate = FALSE; 702 703 /* Init Variable IE structure */ 704 pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE; 705 pVIE->Length = 0; 706 RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); 707 RTMPZeroMemory(&AddHtInfo, sizeof(struct rt_add_ht_info_ie)); 708 709 if (PeerBeaconAndProbeRspSanity(pAd, 710 Elem->Msg, 711 Elem->MsgLen, 712 Elem->Channel, 713 Addr2, 714 Bssid, 715 (char *)Ssid, 716 &SsidLen, 717 &BssType, 718 &BeaconPeriod, 719 &Channel, 720 &NewChannel, 721 &TimeStamp, 722 &Cf, 723 &AtimWin, 724 &CapabilityInfo, 725 &Erp, 726 &DtimCount, 727 &DtimPeriod, 728 &BcastFlag, 729 &MessageToMe, 730 SupRate, 731 &SupRateLen, 732 ExtRate, 733 &ExtRateLen, 734 &CkipFlag, 735 &AironetCellPowerLimit, 736 &EdcaParm, 737 &QbssLoad, 738 &QosCapability, 739 &RalinkIe, 740 &HtCapabilityLen, 741 &PreNHtCapabilityLen, 742 &HtCapability, 743 &AddHtInfoLen, 744 &AddHtInfo, 745 &NewExtChannelOffset, &LenVIE, pVIE)) { 746 /* Disqualify 11b only adhoc when we are in 11g only adhoc mode */ 747 if ((BssType == BSS_ADHOC) 748 && (pAd->CommonCfg.PhyMode == PHY_11G) 749 && ((SupRateLen + ExtRateLen) < 12)) 750 return; 751 752 /* BEACON from desired BSS/IBSS found. We should be able to decide most */ 753 /* BSS parameters here. */ 754 /* Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION? */ 755 /* Do we need to receover back all parameters belonging to previous BSS? */ 756 /* A. Should be not. There's no back-door recover to previous AP. It still need */ 757 /* a new JOIN-AUTH-ASSOC sequence. */ 758 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid)) { 759 DBGPRINT(RT_DEBUG_TRACE, 760 ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", 761 Channel)); 762 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, 763 &TimerCancelled); 764 765 /* Update RSSI to prevent No signal display when cards first initialized */ 766 pAd->StaCfg.RssiSample.LastRssi0 = 767 ConvertToRssi(pAd, Elem->Rssi0, RSSI_0); 768 pAd->StaCfg.RssiSample.LastRssi1 = 769 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1); 770 pAd->StaCfg.RssiSample.LastRssi2 = 771 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2); 772 pAd->StaCfg.RssiSample.AvgRssi0 = 773 pAd->StaCfg.RssiSample.LastRssi0; 774 pAd->StaCfg.RssiSample.AvgRssi0X8 = 775 pAd->StaCfg.RssiSample.AvgRssi0 << 3; 776 pAd->StaCfg.RssiSample.AvgRssi1 = 777 pAd->StaCfg.RssiSample.LastRssi1; 778 pAd->StaCfg.RssiSample.AvgRssi1X8 = 779 pAd->StaCfg.RssiSample.AvgRssi1 << 3; 780 pAd->StaCfg.RssiSample.AvgRssi2 = 781 pAd->StaCfg.RssiSample.LastRssi2; 782 pAd->StaCfg.RssiSample.AvgRssi2X8 = 783 pAd->StaCfg.RssiSample.AvgRssi2 << 3; 784 785 /* */ 786 /* We need to check if SSID only set to any, then we can record the current SSID. */ 787 /* Otherwise will cause hidden SSID association failed. */ 788 /* */ 789 if (pAd->MlmeAux.SsidLen == 0) { 790 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, 791 SsidLen); 792 pAd->MlmeAux.SsidLen = SsidLen; 793 } else { 794 Idx = 795 BssSsidTableSearch(&pAd->ScanTab, Bssid, 796 pAd->MlmeAux.Ssid, 797 pAd->MlmeAux.SsidLen, 798 Channel); 799 800 if (Idx == BSS_NOT_FOUND) { 801 char Rssi = 0; 802 Rssi = 803 RTMPMaxRssi(pAd, 804 ConvertToRssi(pAd, 805 Elem-> 806 Rssi0, 807 RSSI_0), 808 ConvertToRssi(pAd, 809 Elem-> 810 Rssi1, 811 RSSI_1), 812 ConvertToRssi(pAd, 813 Elem-> 814 Rssi2, 815 RSSI_2)); 816 Idx = 817 BssTableSetEntry(pAd, &pAd->ScanTab, 818 Bssid, 819 (char *) Ssid, 820 SsidLen, BssType, 821 BeaconPeriod, &Cf, 822 AtimWin, 823 CapabilityInfo, 824 SupRate, 825 SupRateLen, 826 ExtRate, 827 ExtRateLen, 828 &HtCapability, 829 &AddHtInfo, 830 HtCapabilityLen, 831 AddHtInfoLen, 832 NewExtChannelOffset, 833 Channel, Rssi, 834 TimeStamp, 835 CkipFlag, 836 &EdcaParm, 837 &QosCapability, 838 &QbssLoad, LenVIE, 839 pVIE); 840 if (Idx != BSS_NOT_FOUND) { 841 NdisMoveMemory(pAd->ScanTab. 842 BssEntry[Idx]. 843 PTSF, 844 &Elem->Msg[24], 845 4); 846 NdisMoveMemory(&pAd->ScanTab. 847 BssEntry[Idx]. 848 TTSF[0], 849 &Elem->TimeStamp. 850 u.LowPart, 4); 851 NdisMoveMemory(&pAd->ScanTab. 852 BssEntry[Idx]. 853 TTSF[4], 854 &Elem->TimeStamp. 855 u.LowPart, 4); 856 CapabilityInfo = 857 pAd->ScanTab.BssEntry[Idx]. 858 CapabilityInfo; 859 } 860 } else { 861 /* */ 862 /* Multiple SSID case, used correct CapabilityInfo */ 863 /* */ 864 CapabilityInfo = 865 pAd->ScanTab.BssEntry[Idx]. 866 CapabilityInfo; 867 } 868 } 869 NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN); 870 pAd->MlmeAux.CapabilityInfo = 871 CapabilityInfo & SUPPORTED_CAPABILITY_INFO; 872 pAd->MlmeAux.BssType = BssType; 873 pAd->MlmeAux.BeaconPeriod = BeaconPeriod; 874 pAd->MlmeAux.Channel = Channel; 875 pAd->MlmeAux.AtimWin = AtimWin; 876 pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod; 877 pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration; 878 pAd->MlmeAux.APRalinkIe = RalinkIe; 879 880 /* Copy AP's supported rate to MlmeAux for creating assoication request */ 881 /* Also filter out not supported rate */ 882 pAd->MlmeAux.SupRateLen = SupRateLen; 883 NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, 884 SupRateLen); 885 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, 886 &pAd->MlmeAux.SupRateLen); 887 pAd->MlmeAux.ExtRateLen = ExtRateLen; 888 NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, 889 ExtRateLen); 890 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, 891 &pAd->MlmeAux.ExtRateLen); 892 893 NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 894 16); 895 896 if (((pAd->StaCfg.WepStatus != Ndis802_11WEPEnabled) 897 && (pAd->StaCfg.WepStatus != 898 Ndis802_11Encryption2Enabled)) 899 || (pAd->CommonCfg.HT_DisallowTKIP == FALSE)) { 900 bAllowNrate = TRUE; 901 } 902 903 pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; 904 pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen; 905 906 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, 907 SIZE_HT_CAP_IE); 908 /* filter out un-supported ht rates */ 909 if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) 910 && ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) 911 && (bAllowNrate))) { 912 RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, 913 &AddHtInfo, SIZE_ADD_HT_INFO_IE); 914 915 /* StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability */ 916 NdisMoveMemory(pAd->StaActive.SupportedPhyInfo. 917 MCSSet, HtCapability.MCSSet, 16); 918 pAd->MlmeAux.NewExtChannelOffset = 919 NewExtChannelOffset; 920 pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE; 921 pAd->StaActive.SupportedPhyInfo.bHtEnable = 922 TRUE; 923 if (PreNHtCapabilityLen > 0) 924 pAd->StaActive.SupportedPhyInfo. 925 bPreNHt = TRUE; 926 RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, 927 &AddHtInfo); 928 /* Copy AP Parameter to StaActive. This is also in LinkUp. */ 929 DBGPRINT(RT_DEBUG_TRACE, 930 ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n", 931 pAd->StaActive.SupportedHtPhy. 932 MpduDensity, 933 pAd->StaActive.SupportedHtPhy. 934 MaxRAmpduFactor, 935 HtCapability.HtCapInfo.ChannelWidth)); 936 937 if (AddHtInfoLen > 0) { 938 CentralChannel = AddHtInfo.ControlChan; 939 /* Check again the Bandwidth capability of this AP. */ 940 if ((AddHtInfo.ControlChan > 2) 941 && (AddHtInfo.AddHtInfo. 942 ExtChanOffset == EXTCHA_BELOW) 943 && (HtCapability.HtCapInfo. 944 ChannelWidth == BW_40)) { 945 CentralChannel = 946 AddHtInfo.ControlChan - 2; 947 } else 948 if ((AddHtInfo.AddHtInfo. 949 ExtChanOffset == EXTCHA_ABOVE) 950 && (HtCapability.HtCapInfo. 951 ChannelWidth == BW_40)) { 952 CentralChannel = 953 AddHtInfo.ControlChan + 2; 954 } 955 /* Check Error . */ 956 if (pAd->MlmeAux.CentralChannel != 957 CentralChannel) 958 DBGPRINT(RT_DEBUG_ERROR, 959 ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", 960 CentralChannel, 961 AddHtInfo.ControlChan, 962 pAd->MlmeAux. 963 CentralChannel)); 964 965 DBGPRINT(RT_DEBUG_TRACE, 966 ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", 967 CentralChannel, 968 AddHtInfo.ControlChan)); 969 970 } 971 972 } else { 973 /* To prevent error, let legacy AP must have same CentralChannel and Channel. */ 974 if ((HtCapabilityLen == 0) 975 && (PreNHtCapabilityLen == 0)) 976 pAd->MlmeAux.CentralChannel = 977 pAd->MlmeAux.Channel; 978 979 pAd->StaActive.SupportedPhyInfo.bHtEnable = 980 FALSE; 981 pAd->MlmeAux.NewExtChannelOffset = 0xff; 982 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, 983 SIZE_HT_CAP_IE); 984 pAd->MlmeAux.HtCapabilityLen = 0; 985 RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, 986 SIZE_ADD_HT_INFO_IE); 987 } 988 989 RTMPUpdateMlmeRate(pAd); 990 991 /* copy QOS related information */ 992 if ((pAd->CommonCfg.bWmmCapable) 993 || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) 994 ) { 995 NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, 996 &EdcaParm, sizeof(struct rt_edca_parm)); 997 NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, 998 &QbssLoad, 999 sizeof(struct rt_qbss_load_parm)); 1000 NdisMoveMemory(&pAd->MlmeAux.APQosCapability, 1001 &QosCapability, 1002 sizeof(struct rt_qos_capability_parm)); 1003 } else { 1004 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, 1005 sizeof(struct rt_edca_parm)); 1006 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, 1007 sizeof(struct rt_qbss_load_parm)); 1008 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, 1009 sizeof(struct rt_qos_capability_parm)); 1010 } 1011 1012 DBGPRINT(RT_DEBUG_TRACE, 1013 ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", 1014 pAd->MlmeAux.SupRateLen, 1015 pAd->MlmeAux.ExtRateLen)); 1016 1017 if (AironetCellPowerLimit != 0xFF) { 1018 /*We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power */ 1019 ChangeToCellPowerLimit(pAd, 1020 AironetCellPowerLimit); 1021 } else /*Used the default TX Power Percentage. */ 1022 pAd->CommonCfg.TxPowerPercentage = 1023 pAd->CommonCfg.TxPowerDefault; 1024 1025 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; 1026 Status = MLME_SUCCESS; 1027 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 1028 2, &Status); 1029 } 1030 /* not to me BEACON, ignored */ 1031 } 1032 /* sanity check fail, ignore this frame */ 1033} 1034 1035/* 1036 ========================================================================== 1037 Description: 1038 receive BEACON from peer 1039 1040 IRQL = DISPATCH_LEVEL 1041 1042 ========================================================================== 1043 */ 1044void PeerBeacon(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1045{ 1046 u8 Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; 1047 char Ssid[MAX_LEN_OF_SSID]; 1048 struct rt_cf_parm CfParm; 1049 u8 SsidLen, MessageToMe = 0, BssType, Channel, NewChannel, index = 0; 1050 u8 DtimCount = 0, DtimPeriod = 0, BcastFlag = 0; 1051 u16 CapabilityInfo, AtimWin, BeaconPeriod; 1052 LARGE_INTEGER TimeStamp; 1053 u16 TbttNumToNextWakeUp; 1054 u8 Erp; 1055 u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES], 1056 ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; 1057 u8 SupRateLen, ExtRateLen; 1058 u8 CkipFlag; 1059 u16 LenVIE; 1060 u8 AironetCellPowerLimit; 1061 struct rt_edca_parm EdcaParm; 1062 struct rt_qbss_load_parm QbssLoad; 1063 struct rt_qos_capability_parm QosCapability; 1064 unsigned long RalinkIe; 1065 /* New for WPA security suites */ 1066 u8 VarIE[MAX_VIE_LEN]; /* Total VIE length = MAX_VIE_LEN - -5 */ 1067 struct rt_ndis_802_11_variable_ies *pVIE = NULL; 1068 struct rt_ht_capability_ie HtCapability; 1069 struct rt_add_ht_info_ie AddHtInfo; /* AP might use this additional ht info IE */ 1070 u8 HtCapabilityLen, PreNHtCapabilityLen; 1071 u8 AddHtInfoLen; 1072 u8 NewExtChannelOffset = 0xff; 1073 1074 if (!(INFRA_ON(pAd) || ADHOC_ON(pAd) 1075 )) 1076 return; 1077 1078 /* Init Variable IE structure */ 1079 pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE; 1080 pVIE->Length = 0; 1081 RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); 1082 RTMPZeroMemory(&AddHtInfo, sizeof(struct rt_add_ht_info_ie)); 1083 1084 if (PeerBeaconAndProbeRspSanity(pAd, 1085 Elem->Msg, 1086 Elem->MsgLen, 1087 Elem->Channel, 1088 Addr2, 1089 Bssid, 1090 Ssid, 1091 &SsidLen, 1092 &BssType, 1093 &BeaconPeriod, 1094 &Channel, 1095 &NewChannel, 1096 &TimeStamp, 1097 &CfParm, 1098 &AtimWin, 1099 &CapabilityInfo, 1100 &Erp, 1101 &DtimCount, 1102 &DtimPeriod, 1103 &BcastFlag, 1104 &MessageToMe, 1105 SupRate, 1106 &SupRateLen, 1107 ExtRate, 1108 &ExtRateLen, 1109 &CkipFlag, 1110 &AironetCellPowerLimit, 1111 &EdcaParm, 1112 &QbssLoad, 1113 &QosCapability, 1114 &RalinkIe, 1115 &HtCapabilityLen, 1116 &PreNHtCapabilityLen, 1117 &HtCapability, 1118 &AddHtInfoLen, 1119 &AddHtInfo, 1120 &NewExtChannelOffset, &LenVIE, pVIE)) { 1121 BOOLEAN is_my_bssid, is_my_ssid; 1122 unsigned long Bssidx, Now; 1123 struct rt_bss_entry *pBss; 1124 char RealRssi = 1125 RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), 1126 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), 1127 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); 1128 1129 is_my_bssid = 1130 MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid) ? TRUE : FALSE; 1131 is_my_ssid = 1132 SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, 1133 pAd->CommonCfg.SsidLen) ? TRUE : FALSE; 1134 1135 /* ignore BEACON not for my SSID */ 1136 if ((!is_my_ssid) && (!is_my_bssid)) 1137 return; 1138 1139 /* It means STA waits disassoc completely from this AP, ignores this beacon. */ 1140 if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC) 1141 return; 1142 1143 /* Copy Control channel for this BSSID. */ 1144 if (AddHtInfoLen != 0) 1145 Channel = AddHtInfo.ControlChan; 1146 1147 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) 1148 HtCapabilityLen = SIZE_HT_CAP_IE; 1149 1150 /* */ 1151 /* Housekeeping "SsidBssTab" table for later-on ROAMing usage. */ 1152 /* */ 1153 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); 1154 if (Bssidx == BSS_NOT_FOUND) { 1155 /* discover new AP of this network, create BSS entry */ 1156 Bssidx = 1157 BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, 1158 SsidLen, BssType, BeaconPeriod, 1159 &CfParm, AtimWin, CapabilityInfo, 1160 SupRate, SupRateLen, ExtRate, 1161 ExtRateLen, &HtCapability, 1162 &AddHtInfo, HtCapabilityLen, 1163 AddHtInfoLen, NewExtChannelOffset, 1164 Channel, RealRssi, TimeStamp, 1165 CkipFlag, &EdcaParm, 1166 &QosCapability, &QbssLoad, LenVIE, 1167 pVIE); 1168 if (Bssidx == BSS_NOT_FOUND) /* return if BSS table full */ 1169 return; 1170 1171 NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, 1172 &Elem->Msg[24], 4); 1173 NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], 1174 &Elem->TimeStamp.u.LowPart, 4); 1175 NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], 1176 &Elem->TimeStamp.u.LowPart, 4); 1177 1178 } 1179 1180 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) 1181 && (Channel != NewChannel)) { 1182 /* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */ 1183 /* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */ 1184 AsicSwitchChannel(pAd, 1, FALSE); 1185 AsicLockChannel(pAd, 1); 1186 LinkDown(pAd, FALSE); 1187 MlmeQueueInit(&pAd->Mlme.Queue); 1188 BssTableInit(&pAd->ScanTab); 1189 RTMPusecDelay(1000000); /* use delay to prevent STA do reassoc */ 1190 1191 /* channel sanity check */ 1192 for (index = 0; index < pAd->ChannelListNum; index++) { 1193 if (pAd->ChannelList[index].Channel == 1194 NewChannel) { 1195 pAd->ScanTab.BssEntry[Bssidx].Channel = 1196 NewChannel; 1197 pAd->CommonCfg.Channel = NewChannel; 1198 AsicSwitchChannel(pAd, 1199 pAd->CommonCfg. 1200 Channel, FALSE); 1201 AsicLockChannel(pAd, 1202 pAd->CommonCfg.Channel); 1203 DBGPRINT(RT_DEBUG_TRACE, 1204 ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", 1205 NewChannel)); 1206 break; 1207 } 1208 } 1209 1210 if (index >= pAd->ChannelListNum) { 1211 DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); 1212 } 1213 } 1214 /* if the ssid matched & bssid unmatched, we should select the bssid with large value. */ 1215 /* This might happened when two STA start at the same time */ 1216 if ((!is_my_bssid) && ADHOC_ON(pAd)) { 1217 int i; 1218 1219 /* Add the safeguard against the mismatch of adhoc wep status */ 1220 if (pAd->StaCfg.WepStatus != 1221 pAd->ScanTab.BssEntry[Bssidx].WepStatus) { 1222 return; 1223 } 1224 /* collapse into the ADHOC network which has bigger BSSID value. */ 1225 for (i = 0; i < 6; i++) { 1226 if (Bssid[i] > pAd->CommonCfg.Bssid[i]) { 1227 DBGPRINT(RT_DEBUG_TRACE, 1228 ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", 1229 Bssid[0], Bssid[1], Bssid[2], 1230 Bssid[3], Bssid[4], 1231 Bssid[5])); 1232 AsicDisableSync(pAd); 1233 COPY_MAC_ADDR(pAd->CommonCfg.Bssid, 1234 Bssid); 1235 AsicSetBssid(pAd, pAd->CommonCfg.Bssid); 1236 MakeIbssBeacon(pAd); /* re-build BEACON frame */ 1237 AsicEnableIbssSync(pAd); /* copy BEACON frame to on-chip memory */ 1238 is_my_bssid = TRUE; 1239 break; 1240 } else if (Bssid[i] < pAd->CommonCfg.Bssid[i]) 1241 break; 1242 } 1243 } 1244 1245 NdisGetSystemUpTime(&Now); 1246 pBss = &pAd->ScanTab.BssEntry[Bssidx]; 1247 pBss->Rssi = RealRssi; /* lastest RSSI */ 1248 pBss->LastBeaconRxTime = Now; /* last RX timestamp */ 1249 1250 /* */ 1251 /* BEACON from my BSSID - either IBSS or INFRA network */ 1252 /* */ 1253 if (is_my_bssid) { 1254 struct rt_rxwi RxWI; 1255 1256 pAd->StaCfg.DtimCount = DtimCount; 1257 pAd->StaCfg.DtimPeriod = DtimPeriod; 1258 pAd->StaCfg.LastBeaconRxTime = Now; 1259 1260 RxWI.RSSI0 = Elem->Rssi0; 1261 RxWI.RSSI1 = Elem->Rssi1; 1262 RxWI.RSSI2 = Elem->Rssi2; 1263 1264 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI); 1265 if (AironetCellPowerLimit != 0xFF) { 1266 /* */ 1267 /* We get the Cisco (ccx) "TxPower Limit" required */ 1268 /* Changed to appropriate TxPower Limit for Ciso Compatible Extensions */ 1269 /* */ 1270 ChangeToCellPowerLimit(pAd, 1271 AironetCellPowerLimit); 1272 } else { 1273 /* */ 1274 /* AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist. */ 1275 /* Used the default TX Power Percentage, that set from UI. */ 1276 /* */ 1277 pAd->CommonCfg.TxPowerPercentage = 1278 pAd->CommonCfg.TxPowerDefault; 1279 } 1280 1281 if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo))) { 1282 u8 MaxSupportedRateIn500Kbps = 0; 1283 u8 idx; 1284 struct rt_mac_table_entry *pEntry; 1285 1286 /* supported rates array may not be sorted. sort it and find the maximum rate */ 1287 for (idx = 0; idx < SupRateLen; idx++) { 1288 if (MaxSupportedRateIn500Kbps < 1289 (SupRate[idx] & 0x7f)) 1290 MaxSupportedRateIn500Kbps = 1291 SupRate[idx] & 0x7f; 1292 } 1293 1294 for (idx = 0; idx < ExtRateLen; idx++) { 1295 if (MaxSupportedRateIn500Kbps < 1296 (ExtRate[idx] & 0x7f)) 1297 MaxSupportedRateIn500Kbps = 1298 ExtRate[idx] & 0x7f; 1299 } 1300 1301 /* look up the existing table */ 1302 pEntry = MacTableLookup(pAd, Addr2); 1303 1304 /* Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon. */ 1305 /* To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station. */ 1306 if ((ADHOC_ON(pAd) 1307 && (Elem->Wcid == RESERVED_WCID)) 1308 || (pEntry 1309 && 1310 ((pEntry->LastBeaconRxTime + 1311 ADHOC_ENTRY_BEACON_LOST_TIME) < 1312 Now))) { 1313 if (pEntry == NULL) 1314 /* Another adhoc joining, add to our MAC table. */ 1315 pEntry = 1316 MacTableInsertEntry(pAd, 1317 Addr2, 1318 BSS0, 1319 FALSE); 1320 1321 if (StaAddMacTableEntry(pAd, 1322 pEntry, 1323 MaxSupportedRateIn500Kbps, 1324 &HtCapability, 1325 HtCapabilityLen, 1326 &AddHtInfo, 1327 AddHtInfoLen, 1328 CapabilityInfo) 1329 == FALSE) { 1330 DBGPRINT(RT_DEBUG_TRACE, 1331 ("ADHOC - Add Entry failed.\n")); 1332 return; 1333 } 1334 1335 if (pEntry && 1336 (Elem->Wcid == RESERVED_WCID)) { 1337 idx = pAd->StaCfg.DefaultKeyId; 1338 RTMP_STA_SECURITY_INFO_ADD(pAd, 1339 BSS0, 1340 idx, 1341 pEntry); 1342 } 1343 } 1344 1345 if (pEntry && pEntry->ValidAsCLI) 1346 pEntry->LastBeaconRxTime = Now; 1347 1348 /* At least another peer in this IBSS, declare MediaState as CONNECTED */ 1349 if (!OPSTATUS_TEST_FLAG 1350 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { 1351 OPSTATUS_SET_FLAG(pAd, 1352 fOP_STATUS_MEDIA_STATE_CONNECTED); 1353 1354 pAd->IndicateMediaState = 1355 NdisMediaStateConnected; 1356 RTMP_IndicateMediaState(pAd); 1357 pAd->ExtraInfo = GENERAL_LINK_UP; 1358 AsicSetBssid(pAd, pAd->CommonCfg.Bssid); 1359 1360 /* 2003/03/12 - john */ 1361 /* Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that */ 1362 /* "site survey" result should always include the current connected network. */ 1363 /* */ 1364 Bssidx = 1365 BssTableSearch(&pAd->ScanTab, Bssid, 1366 Channel); 1367 if (Bssidx == BSS_NOT_FOUND) { 1368 Bssidx = 1369 BssTableSetEntry(pAd, 1370 &pAd-> 1371 ScanTab, 1372 Bssid, 1373 Ssid, 1374 SsidLen, 1375 BssType, 1376 BeaconPeriod, 1377 &CfParm, 1378 AtimWin, 1379 CapabilityInfo, 1380 SupRate, 1381 SupRateLen, 1382 ExtRate, 1383 ExtRateLen, 1384 &HtCapability, 1385 &AddHtInfo, 1386 HtCapabilityLen, 1387 AddHtInfoLen, 1388 NewExtChannelOffset, 1389 Channel, 1390 RealRssi, 1391 TimeStamp, 1392 0, 1393 &EdcaParm, 1394 &QosCapability, 1395 &QbssLoad, 1396 LenVIE, 1397 pVIE); 1398 } 1399 DBGPRINT(RT_DEBUG_TRACE, 1400 ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n")); 1401 } 1402 } 1403 1404 if (INFRA_ON(pAd)) { 1405 BOOLEAN bUseShortSlot, bUseBGProtection; 1406 1407 /* decide to use/change to - */ 1408 /* 1. long slot (20 us) or short slot (9 us) time */ 1409 /* 2. turn on/off RTS/CTS and/or CTS-to-self protection */ 1410 /* 3. short preamble */ 1411 1412 /*bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo); */ 1413 bUseShortSlot = 1414 CAP_IS_SHORT_SLOT(CapabilityInfo); 1415 if (bUseShortSlot != 1416 OPSTATUS_TEST_FLAG(pAd, 1417 fOP_STATUS_SHORT_SLOT_INUSED)) 1418 AsicSetSlotTime(pAd, bUseShortSlot); 1419 1420 bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || /* always use */ 1421 ((pAd->CommonCfg.UseBGProtection == 0) 1422 && ERP_IS_USE_PROTECTION(Erp)); 1423 1424 if (pAd->CommonCfg.Channel > 14) /* always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP */ 1425 bUseBGProtection = FALSE; 1426 1427 if (bUseBGProtection != 1428 OPSTATUS_TEST_FLAG(pAd, 1429 fOP_STATUS_BG_PROTECTION_INUSED)) 1430 { 1431 if (bUseBGProtection) { 1432 OPSTATUS_SET_FLAG(pAd, 1433 fOP_STATUS_BG_PROTECTION_INUSED); 1434 AsicUpdateProtect(pAd, 1435 pAd->MlmeAux. 1436 AddHtInfo. 1437 AddHtInfo2. 1438 OperaionMode, 1439 (OFDMSETPROTECT 1440 | 1441 CCKSETPROTECT 1442 | 1443 ALLN_SETPROTECT), 1444 FALSE, 1445 (pAd->MlmeAux. 1446 AddHtInfo. 1447 AddHtInfo2. 1448 NonGfPresent 1449 == 1)); 1450 } else { 1451 OPSTATUS_CLEAR_FLAG(pAd, 1452 fOP_STATUS_BG_PROTECTION_INUSED); 1453 AsicUpdateProtect(pAd, 1454 pAd->MlmeAux. 1455 AddHtInfo. 1456 AddHtInfo2. 1457 OperaionMode, 1458 (OFDMSETPROTECT 1459 | 1460 CCKSETPROTECT 1461 | 1462 ALLN_SETPROTECT), 1463 TRUE, 1464 (pAd->MlmeAux. 1465 AddHtInfo. 1466 AddHtInfo2. 1467 NonGfPresent 1468 == 1)); 1469 } 1470 1471 DBGPRINT(RT_DEBUG_WARN, 1472 ("SYNC - AP changed B/G protection to %d\n", 1473 bUseBGProtection)); 1474 } 1475 /* check Ht protection mode. and adhere to the Non-GF device indication by AP. */ 1476 if ((AddHtInfoLen != 0) && 1477 ((AddHtInfo.AddHtInfo2.OperaionMode != 1478 pAd->MlmeAux.AddHtInfo.AddHtInfo2. 1479 OperaionMode) 1480 || (AddHtInfo.AddHtInfo2.NonGfPresent != 1481 pAd->MlmeAux.AddHtInfo.AddHtInfo2. 1482 NonGfPresent))) { 1483 pAd->MlmeAux.AddHtInfo.AddHtInfo2. 1484 NonGfPresent = 1485 AddHtInfo.AddHtInfo2.NonGfPresent; 1486 pAd->MlmeAux.AddHtInfo.AddHtInfo2. 1487 OperaionMode = 1488 AddHtInfo.AddHtInfo2.OperaionMode; 1489 if (pAd->MlmeAux.AddHtInfo.AddHtInfo2. 1490 NonGfPresent == 1) { 1491 AsicUpdateProtect(pAd, 1492 pAd->MlmeAux. 1493 AddHtInfo. 1494 AddHtInfo2. 1495 OperaionMode, 1496 ALLN_SETPROTECT, 1497 FALSE, TRUE); 1498 } else 1499 AsicUpdateProtect(pAd, 1500 pAd->MlmeAux. 1501 AddHtInfo. 1502 AddHtInfo2. 1503 OperaionMode, 1504 ALLN_SETPROTECT, 1505 FALSE, FALSE); 1506 1507 DBGPRINT(RT_DEBUG_TRACE, 1508 ("SYNC - AP changed N OperaionMode to %d\n", 1509 pAd->MlmeAux.AddHtInfo. 1510 AddHtInfo2.OperaionMode)); 1511 } 1512 1513 if (OPSTATUS_TEST_FLAG 1514 (pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) 1515 && ERP_IS_USE_BARKER_PREAMBLE(Erp)) { 1516 MlmeSetTxPreamble(pAd, 1517 Rt802_11PreambleLong); 1518 DBGPRINT(RT_DEBUG_TRACE, 1519 ("SYNC - AP forced to use long preamble\n")); 1520 } 1521 1522 if (OPSTATUS_TEST_FLAG 1523 (pAd, fOP_STATUS_WMM_INUSED) 1524 && (EdcaParm.bValid == TRUE) 1525 && (EdcaParm.EdcaUpdateCount != 1526 pAd->CommonCfg.APEdcaParm. 1527 EdcaUpdateCount)) { 1528 DBGPRINT(RT_DEBUG_TRACE, 1529 ("SYNC - AP change EDCA parameters(from %d to %d)\n", 1530 pAd->CommonCfg.APEdcaParm. 1531 EdcaUpdateCount, 1532 EdcaParm.EdcaUpdateCount)); 1533 AsicSetEdcaParm(pAd, &EdcaParm); 1534 } 1535 /* copy QOS related information */ 1536 NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, 1537 &QbssLoad, 1538 sizeof(struct rt_qbss_load_parm)); 1539 NdisMoveMemory(&pAd->CommonCfg.APQosCapability, 1540 &QosCapability, 1541 sizeof(struct rt_qos_capability_parm)); 1542 } 1543 /* only INFRASTRUCTURE mode support power-saving feature */ 1544 if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) 1545 || (pAd->CommonCfg.bAPSDForcePowerSave)) { 1546 u8 FreeNumber; 1547 /* 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL */ 1548 /* 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE */ 1549 /* 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE */ 1550 /* 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE */ 1551 /* 5. otherwise, put PHY back to sleep to save battery. */ 1552 if (MessageToMe) { 1553#ifdef RTMP_MAC_PCI 1554 if (OPSTATUS_TEST_FLAG 1555 (pAd, fOP_STATUS_PCIE_DEVICE)) { 1556 /* Restore to correct BBP R3 value */ 1557 if (pAd->Antenna.field.RxPath > 1558 1) 1559 RTMP_BBP_IO_WRITE8_BY_REG_ID 1560 (pAd, BBP_R3, 1561 pAd->StaCfg.BBPR3); 1562 /* Turn clk to 80Mhz. */ 1563 } 1564#endif /* RTMP_MAC_PCI // */ 1565 if (pAd->CommonCfg.bAPSDCapable 1566 && pAd->CommonCfg.APEdcaParm. 1567 bAPSDCapable 1568 && pAd->CommonCfg.bAPSDAC_BE 1569 && pAd->CommonCfg.bAPSDAC_BK 1570 && pAd->CommonCfg.bAPSDAC_VI 1571 && pAd->CommonCfg.bAPSDAC_VO) { 1572 pAd->CommonCfg. 1573 bNeedSendTriggerFrame = 1574 TRUE; 1575 } else 1576 RTMP_PS_POLL_ENQUEUE(pAd); 1577 } else if (BcastFlag && (DtimCount == 0) 1578 && OPSTATUS_TEST_FLAG(pAd, 1579 fOP_STATUS_RECEIVE_DTIM)) 1580 { 1581#ifdef RTMP_MAC_PCI 1582 if (OPSTATUS_TEST_FLAG 1583 (pAd, fOP_STATUS_PCIE_DEVICE)) { 1584 if (pAd->Antenna.field.RxPath > 1585 1) 1586 RTMP_BBP_IO_WRITE8_BY_REG_ID 1587 (pAd, BBP_R3, 1588 pAd->StaCfg.BBPR3); 1589 } 1590#endif /* RTMP_MAC_PCI // */ 1591 } else 1592 if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) 1593 || (pAd->TxSwQueue[QID_AC_BE].Number != 1594 0) 1595 || (pAd->TxSwQueue[QID_AC_VI].Number != 1596 0) 1597 || (pAd->TxSwQueue[QID_AC_VO].Number != 1598 0) 1599 || 1600 (RTMPFreeTXDRequest 1601 (pAd, QID_AC_BK, TX_RING_SIZE - 1, 1602 &FreeNumber) != NDIS_STATUS_SUCCESS) 1603 || 1604 (RTMPFreeTXDRequest 1605 (pAd, QID_AC_BE, TX_RING_SIZE - 1, 1606 &FreeNumber) != NDIS_STATUS_SUCCESS) 1607 || 1608 (RTMPFreeTXDRequest 1609 (pAd, QID_AC_VI, TX_RING_SIZE - 1, 1610 &FreeNumber) != NDIS_STATUS_SUCCESS) 1611 || 1612 (RTMPFreeTXDRequest 1613 (pAd, QID_AC_VO, TX_RING_SIZE - 1, 1614 &FreeNumber) != NDIS_STATUS_SUCCESS) 1615 || 1616 (RTMPFreeTXDRequest 1617 (pAd, QID_MGMT, MGMT_RING_SIZE - 1, 1618 &FreeNumber) != 1619 NDIS_STATUS_SUCCESS)) { 1620 /* TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme */ 1621 /* can we cheat here (i.e. just check MGMT & AC_BE) for better performance? */ 1622#ifdef RTMP_MAC_PCI 1623 if (OPSTATUS_TEST_FLAG 1624 (pAd, fOP_STATUS_PCIE_DEVICE)) { 1625 if (pAd->Antenna.field.RxPath > 1626 1) 1627 RTMP_BBP_IO_WRITE8_BY_REG_ID 1628 (pAd, BBP_R3, 1629 pAd->StaCfg.BBPR3); 1630 } 1631#endif /* RTMP_MAC_PCI // */ 1632 } else { 1633 if ((pAd->CommonCfg. 1634 bACMAPSDTr[QID_AC_VO]) 1635 || (pAd->CommonCfg. 1636 bACMAPSDTr[QID_AC_VI]) 1637 || (pAd->CommonCfg. 1638 bACMAPSDTr[QID_AC_BK]) 1639 || (pAd->CommonCfg. 1640 bACMAPSDTr[QID_AC_BE])) { 1641 /* 1642 WMM Spec v1.0 3.6.2.4, 1643 The WMM STA shall remain awake until it receives a 1644 QoS Data or Null frame addressed to it, with the 1645 EOSP subfield in QoS Control field set to 1. 1646 1647 So we can not sleep here or we will suffer a case: 1648 1649 PS Management Frame --> 1650 Trigger frame --> 1651 Beacon (TIM=0) (Beacon is closer to Trig frame) --> 1652 Station goes to sleep --> 1653 AP delivery queued UAPSD packets --> 1654 Station can NOT receive the reply 1655 1656 Maybe we need a timeout timer to avoid that we do 1657 NOT receive the EOSP frame. 1658 1659 We can not use More Data to check if SP is ended 1660 due to MaxSPLength. 1661 */ 1662 } else { 1663 u16 NextDtim = DtimCount; 1664 1665 if (NextDtim == 0) 1666 NextDtim = DtimPeriod; 1667 1668 TbttNumToNextWakeUp = 1669 pAd->StaCfg. 1670 DefaultListenCount; 1671 if (OPSTATUS_TEST_FLAG 1672 (pAd, 1673 fOP_STATUS_RECEIVE_DTIM) 1674 && (TbttNumToNextWakeUp > 1675 NextDtim)) 1676 TbttNumToNextWakeUp = 1677 NextDtim; 1678 1679 if (!OPSTATUS_TEST_FLAG 1680 (pAd, fOP_STATUS_DOZE)) { 1681 /* Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode. */ 1682 pAd-> 1683 ThisTbttNumToNextWakeUp 1684 = 1685 TbttNumToNextWakeUp; 1686 AsicSleepThenAutoWakeup 1687 (pAd, 1688 pAd-> 1689 ThisTbttNumToNextWakeUp); 1690 } 1691 } 1692 } 1693 } 1694 } 1695 /* not my BSSID, ignore it */ 1696 } 1697 /* sanity check fail, ignore this frame */ 1698} 1699 1700/* 1701 ========================================================================== 1702 Description: 1703 Receive PROBE REQ from remote peer when operating in IBSS mode 1704 ========================================================================== 1705 */ 1706void PeerProbeReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1707{ 1708 u8 Addr2[MAC_ADDR_LEN]; 1709 char Ssid[MAX_LEN_OF_SSID]; 1710 u8 SsidLen; 1711 u8 HtLen, AddHtLen, NewExtLen; 1712 struct rt_header_802_11 ProbeRspHdr; 1713 int NStatus; 1714 u8 *pOutBuffer = NULL; 1715 unsigned long FrameLen = 0; 1716 LARGE_INTEGER FakeTimestamp; 1717 u8 DsLen = 1, IbssLen = 2; 1718 u8 LocalErpIe[3] = { IE_ERP, 1, 0 }; 1719 BOOLEAN Privacy; 1720 u16 CapabilityInfo; 1721 u8 RSNIe = IE_WPA; 1722 1723 if (!ADHOC_ON(pAd)) 1724 return; 1725 1726 if (PeerProbeReqSanity 1727 (pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen)) { 1728 if ((SsidLen == 0) 1729 || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, 1730 pAd->CommonCfg.SsidLen)) { 1731 /* allocate and send out ProbeRsp frame */ 1732 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ 1733 if (NStatus != NDIS_STATUS_SUCCESS) 1734 return; 1735 1736 /*pAd->StaCfg.AtimWin = 0; // ?????? */ 1737 1738 Privacy = 1739 (pAd->StaCfg.WepStatus == 1740 Ndis802_11Encryption1Enabled) 1741 || (pAd->StaCfg.WepStatus == 1742 Ndis802_11Encryption2Enabled) 1743 || (pAd->StaCfg.WepStatus == 1744 Ndis802_11Encryption3Enabled); 1745 CapabilityInfo = 1746 CAP_GENERATE(0, 1, Privacy, 1747 (pAd->CommonCfg.TxPreamble == 1748 Rt802_11PreambleShort), 0, 0); 1749 1750 MakeOutgoingFrame(pOutBuffer, &FrameLen, 1751 sizeof(struct rt_header_802_11), &ProbeRspHdr, 1752 TIMESTAMP_LEN, &FakeTimestamp, 1753 2, &pAd->CommonCfg.BeaconPeriod, 1754 2, &CapabilityInfo, 1755 1, &SsidIe, 1756 1, &pAd->CommonCfg.SsidLen, 1757 pAd->CommonCfg.SsidLen, 1758 pAd->CommonCfg.Ssid, 1, &SupRateIe, 1, 1759 &pAd->StaActive.SupRateLen, 1760 pAd->StaActive.SupRateLen, 1761 pAd->StaActive.SupRate, 1, &DsIe, 1, 1762 &DsLen, 1, &pAd->CommonCfg.Channel, 1, 1763 &IbssIe, 1, &IbssLen, 2, 1764 &pAd->StaActive.AtimWin, END_OF_ARGS); 1765 1766 if (pAd->StaActive.ExtRateLen) { 1767 unsigned long tmp; 1768 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 1769 3, LocalErpIe, 1770 1, &ExtRateIe, 1771 1, &pAd->StaActive.ExtRateLen, 1772 pAd->StaActive.ExtRateLen, 1773 &pAd->StaActive.ExtRate, 1774 END_OF_ARGS); 1775 FrameLen += tmp; 1776 } 1777 /* If adhoc secruity is set for WPA-None, append the cipher suite IE */ 1778 if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) { 1779 unsigned long tmp; 1780 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 1781 1, &RSNIe, 1782 1, &pAd->StaCfg.RSNIE_Len, 1783 pAd->StaCfg.RSNIE_Len, 1784 pAd->StaCfg.RSN_IE, 1785 END_OF_ARGS); 1786 FrameLen += tmp; 1787 } 1788 1789 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { 1790 unsigned long TmpLen; 1791 u8 BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 }; 1792 HtLen = sizeof(pAd->CommonCfg.HtCapability); 1793 AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); 1794 NewExtLen = 1; 1795 /*New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame */ 1796 if (pAd->bBroadComHT == TRUE) { 1797 MakeOutgoingFrame(pOutBuffer + FrameLen, 1798 &TmpLen, 1, &WpaIe, 4, 1799 &BROADCOM[0], 1800 pAd->MlmeAux. 1801 HtCapabilityLen, 1802 &pAd->MlmeAux. 1803 HtCapability, 1804 END_OF_ARGS); 1805 } else { 1806 MakeOutgoingFrame(pOutBuffer + FrameLen, 1807 &TmpLen, 1, &HtCapIe, 1808 1, &HtLen, 1809 sizeof 1810 (struct rt_ht_capability_ie), 1811 &pAd->CommonCfg. 1812 HtCapability, 1, 1813 &AddHtInfoIe, 1, 1814 &AddHtLen, 1815 sizeof 1816 (struct rt_add_ht_info_ie), 1817 &pAd->CommonCfg. 1818 AddHTInfo, 1, 1819 &NewExtChanIe, 1, 1820 &NewExtLen, 1821 sizeof 1822 (struct rt_new_ext_chan_ie), 1823 &pAd->CommonCfg. 1824 NewExtChanOffset, 1825 END_OF_ARGS); 1826 } 1827 FrameLen += TmpLen; 1828 } 1829 1830 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); 1831 MlmeFreeMemory(pAd, pOutBuffer); 1832 } 1833 } 1834} 1835 1836void BeaconTimeoutAtJoinAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1837{ 1838 u16 Status; 1839 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n")); 1840 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; 1841 Status = MLME_REJ_TIMEOUT; 1842 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); 1843} 1844 1845/* 1846 ========================================================================== 1847 Description: 1848 Scan timeout procedure. basically add channel index by 1 and rescan 1849 ========================================================================== 1850 */ 1851void ScanTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1852{ 1853 pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel); 1854 1855 /* Only one channel scanned for CISCO beacon request */ 1856 if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) || 1857 (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) || 1858 (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) || 1859 (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD)) 1860 pAd->MlmeAux.Channel = 0; 1861 1862 /* this routine will stop if pAd->MlmeAux.Channel == 0 */ 1863 ScanNextChannel(pAd); 1864} 1865 1866/* 1867 ========================================================================== 1868 Description: 1869 ========================================================================== 1870 */ 1871void InvalidStateWhenScan(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1872{ 1873 u16 Status; 1874 DBGPRINT(RT_DEBUG_TRACE, 1875 ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", 1876 pAd->Mlme.SyncMachine.CurrState)); 1877 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; 1878 Status = MLME_STATE_MACHINE_REJECT; 1879 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); 1880} 1881 1882/* 1883 ========================================================================== 1884 Description: 1885 ========================================================================== 1886 */ 1887void InvalidStateWhenJoin(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1888{ 1889 u16 Status; 1890 DBGPRINT(RT_DEBUG_TRACE, 1891 ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", 1892 pAd->Mlme.SyncMachine.CurrState)); 1893 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; 1894 Status = MLME_STATE_MACHINE_REJECT; 1895 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); 1896} 1897 1898/* 1899 ========================================================================== 1900 Description: 1901 ========================================================================== 1902 */ 1903void InvalidStateWhenStart(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1904{ 1905 u16 Status; 1906 DBGPRINT(RT_DEBUG_TRACE, 1907 ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", 1908 pAd->Mlme.SyncMachine.CurrState)); 1909 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; 1910 Status = MLME_STATE_MACHINE_REJECT; 1911 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); 1912} 1913 1914/* 1915 ========================================================================== 1916 Description: 1917 1918 IRQL = DISPATCH_LEVEL 1919 1920 ========================================================================== 1921 */ 1922void EnqueuePsPoll(struct rt_rtmp_adapter *pAd) 1923{ 1924 1925 if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP) 1926 pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE; 1927 MiniportMMRequest(pAd, 0, (u8 *)& pAd->PsPollFrame, 1928 sizeof(struct rt_pspoll_frame)); 1929} 1930 1931/* 1932 ========================================================================== 1933 Description: 1934 ========================================================================== 1935 */ 1936void EnqueueProbeRequest(struct rt_rtmp_adapter *pAd) 1937{ 1938 int NState; 1939 u8 *pOutBuffer; 1940 unsigned long FrameLen = 0; 1941 struct rt_header_802_11 Hdr80211; 1942 1943 DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); 1944 1945 NState = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ 1946 if (NState == NDIS_STATUS_SUCCESS) { 1947 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, 1948 BROADCAST_ADDR, BROADCAST_ADDR); 1949 1950 /* this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse */ 1951 MakeOutgoingFrame(pOutBuffer, &FrameLen, 1952 sizeof(struct rt_header_802_11), &Hdr80211, 1953 1, &SsidIe, 1954 1, &pAd->CommonCfg.SsidLen, 1955 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, 1956 1, &SupRateIe, 1957 1, &pAd->StaActive.SupRateLen, 1958 pAd->StaActive.SupRateLen, 1959 pAd->StaActive.SupRate, END_OF_ARGS); 1960 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); 1961 MlmeFreeMemory(pAd, pOutBuffer); 1962 } 1963 1964} 1965 1966BOOLEAN ScanRunning(struct rt_rtmp_adapter *pAd) 1967{ 1968 return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE; 1969} 1970