1/* 2 * Copyright (c) 2007-2008 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17#include "cprecomp.h" 18 19void zfScanMgrInit(zdev_t* dev) 20{ 21 zmw_get_wlan_dev(dev); 22 23 wd->sta.scanMgr.scanReqs[0] = 0; 24 wd->sta.scanMgr.scanReqs[1] = 0; 25 26 wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE; 27 wd->sta.scanMgr.scanStartDelay = 3; 28 //wd->sta.scanMgr.scanStartDelay = 0; 29} 30 31u8_t zfScanMgrScanStart(zdev_t* dev, u8_t scanType) 32{ 33 u8_t i; 34 35 zmw_get_wlan_dev(dev); 36 37 zm_debug_msg1("scanType = ", scanType); 38 39 zmw_declare_for_critical_section(); 40 41 if ( scanType != ZM_SCAN_MGR_SCAN_INTERNAL && 42 scanType != ZM_SCAN_MGR_SCAN_EXTERNAL ) 43 { 44 zm_debug_msg0("unknown scanType"); 45 return 1; 46 } 47 else if (zfStaIsConnecting(dev)) 48 { 49 zm_debug_msg0("reject scan request due to connecting"); 50 return 1; 51 } 52 53 i = scanType - 1; 54 55 zmw_enter_critical_section(dev); 56 57 if ( wd->sta.scanMgr.scanReqs[i] == 1 ) 58 { 59 zm_debug_msg1("scan rescheduled", scanType); 60 goto scan_done; 61 } 62 63 wd->sta.scanMgr.scanReqs[i] = 1; 64 zm_debug_msg1("scan scheduled: ", scanType); 65 66 // If there's no scan pending, we do the scan right away. 67 // If there's an internal scan and the new scan request is external one, 68 // we will restart the scan. 69 if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE ) 70 { 71 goto schedule_scan; 72 } 73 else if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_INTERNAL && 74 scanType == ZM_SCAN_MGR_SCAN_EXTERNAL ) 75 { 76 // Stop the internal scan & schedule external scan first 77 zfTimerCancel(dev, ZM_EVENT_SCAN); 78 79 /* Fix for WHQL sendrecv => we do not apply delay time in which the device 80 stop transmitting packet when we already connect to some AP */ 81 wd->sta.bScheduleScan = FALSE; 82 83 zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN); 84 zfTimerCancel(dev, ZM_EVENT_IN_SCAN); 85 86 wd->sta.bChannelScan = FALSE; 87 goto schedule_scan; 88 } 89 else 90 { 91 zm_debug_msg0("Scan is busy...waiting later to start\n"); 92 } 93 94 zmw_leave_critical_section(dev); 95 return 0; 96 97scan_done: 98 zmw_leave_critical_section(dev); 99 return 1; 100 101schedule_scan: 102 103 wd->sta.bScheduleScan = TRUE; 104 105 zfTimerSchedule(dev, ZM_EVENT_SCAN, wd->sta.scanMgr.scanStartDelay); 106 wd->sta.scanMgr.scanStartDelay = 3; 107 //wd->sta.scanMgr.scanStartDelay = 0; 108 wd->sta.scanMgr.currScanType = scanType; 109 zmw_leave_critical_section(dev); 110 111 if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev))) 112 { 113 zfSendNullData(dev, 1); 114 } 115 return 0; 116} 117 118void zfScanMgrScanStop(zdev_t* dev, u8_t scanType) 119{ 120 u8_t scanNotifyRequired = 0; 121 u8_t theOtherScan = ZM_SCAN_MGR_SCAN_NONE; 122 123 zmw_get_wlan_dev(dev); 124 125 zmw_declare_for_critical_section(); 126 127 zmw_enter_critical_section(dev); 128 129 if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE ) 130 { 131 zm_assert(wd->sta.scanMgr.scanReqs[0] == 0); 132 zm_assert(wd->sta.scanMgr.scanReqs[1] == 0); 133 goto done; 134 } 135 136 switch(scanType) 137 { 138 case ZM_SCAN_MGR_SCAN_EXTERNAL: 139 scanNotifyRequired = 1; 140 theOtherScan = ZM_SCAN_MGR_SCAN_INTERNAL; 141 break; 142 143 case ZM_SCAN_MGR_SCAN_INTERNAL: 144 theOtherScan = ZM_SCAN_MGR_SCAN_EXTERNAL; 145 break; 146 147 default: 148 goto done; 149 } 150 151 if ( wd->sta.scanMgr.currScanType != scanType ) 152 { 153 goto stop_done; 154 } 155 156 zfTimerCancel(dev, ZM_EVENT_SCAN); 157 158 /* Fix for WHQL sendrecv => we do not apply delay time in which the device 159 stop transmitting packet when we already connect to some AP */ 160 wd->sta.bScheduleScan = FALSE; 161 162 zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN); 163 zfTimerCancel(dev, ZM_EVENT_IN_SCAN); 164 165 wd->sta.bChannelScan = FALSE; 166 wd->sta.scanFrequency = 0; 167 168 if ( wd->sta.scanMgr.scanReqs[theOtherScan - 1] ) 169 { 170 wd->sta.scanMgr.currScanType = theOtherScan; 171 172 // Schedule the other scan after 1 second later 173 zfTimerSchedule(dev, ZM_EVENT_SCAN, 100); 174 } 175 else 176 { 177 wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE; 178 } 179 180stop_done: 181 wd->sta.scanMgr.scanReqs[scanType - 1] = 0; 182 183 zmw_leave_critical_section(dev); 184 185 /* avoid lose receive packet when site survey */ 186 if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev))) 187 { 188 zfSendNullData(dev, 0); 189 } 190 191 if ( scanNotifyRequired ) 192 { 193 zm_debug_msg0("Scan notify after reset"); 194 if (wd->zfcbScanNotify != NULL) 195 { 196 wd->zfcbScanNotify(dev, NULL); 197 } 198 } 199 200 return; 201 202done: 203 zmw_leave_critical_section(dev); 204 return; 205} 206 207void zfScanMgrScanAck(zdev_t* dev) 208{ 209 zmw_get_wlan_dev(dev); 210 211 zmw_declare_for_critical_section(); 212 213 zmw_enter_critical_section(dev); 214 215 wd->sta.scanMgr.scanStartDelay = 3; 216 //wd->sta.scanMgr.scanStartDelay = 0; 217 218 zmw_leave_critical_section(dev); 219 return; 220} 221 222extern void zfStaReconnect(zdev_t* dev); 223 224static void zfScanSendProbeRequest(zdev_t* dev) 225{ 226 u8_t k; 227 u16_t dst[3] = { 0xffff, 0xffff, 0xffff }; 228 229 zmw_get_wlan_dev(dev); 230 231 /* Increase rxBeaconCount to prevent beacon lost */ 232 if (zfStaIsConnected(dev)) 233 { 234 wd->sta.rxBeaconCount++; 235 } 236 237 if ( wd->sta.bPassiveScan ) 238 { 239 return; 240 } 241 /* enable 802.l11h and in DFS Band , disable sending probe request */ 242 if (wd->sta.DFSEnable) 243 { 244 if (zfHpIsDfsChannel(dev, wd->sta.scanFrequency)) 245 { 246 return; 247 } 248 } 249 250 zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBEREQ, dst, 0, 0, 0); 251 252 if ( wd->sta.disableProbingWithSsid ) 253 { 254 return; 255 } 256 257 for (k=1; k<=ZM_MAX_PROBE_HIDDEN_SSID_SIZE; k++) 258 { 259 if ( wd->ws.probingSsidList[k-1].ssidLen != 0 ) 260 { 261 zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBEREQ, dst, k, 0, 0); 262 } 263 } 264} 265 266static void zfScanMgrEventSetFreqCompleteCb(zdev_t* dev) 267{ 268 zmw_get_wlan_dev(dev); 269 270 zmw_declare_for_critical_section(); 271 272//printk("zfScanMgrEventSetFreqCompleteCb #1\n"); 273 274 zmw_enter_critical_section(dev); 275 zfTimerSchedule(dev, ZM_EVENT_IN_SCAN, ZM_TICK_IN_SCAN); 276 if (wd->sta.bPassiveScan) 277 { 278 zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_SCAN, wd->sta.passiveScanTickPerChannel); 279 } 280 else 281 { 282 zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_SCAN, wd->sta.activescanTickPerChannel); 283 } 284 zmw_leave_critical_section(dev); 285 286 zfScanSendProbeRequest(dev); 287} 288 289 290static void zfScanMgrEventScanCompleteCb(zdev_t* dev) 291{ 292 if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev))) 293 { 294 zfSendNullData(dev, 0); 295 } 296 return; 297} 298 299 300void zfScanMgrScanEventRetry(zdev_t* dev) 301{ 302 zmw_get_wlan_dev(dev); 303 304 if ( !wd->sta.bChannelScan ) 305 { 306 return; 307 } 308 309 if ( !wd->sta.bPassiveScan ) 310 { 311 zfScanSendProbeRequest(dev); 312 } 313} 314 315u8_t zfScanMgrScanEventTimeout(zdev_t* dev) 316{ 317 u16_t nextScanFrequency = 0; 318 u8_t temp; 319 320 zmw_get_wlan_dev(dev); 321 322 zmw_declare_for_critical_section(); 323 324 zmw_enter_critical_section(dev); 325 if ( wd->sta.scanFrequency == 0 ) 326 { 327 zmw_leave_critical_section(dev); 328 return -1; 329 } 330 331 nextScanFrequency = zfChGetNextChannel(dev, wd->sta.scanFrequency, 332 &wd->sta.bPassiveScan); 333 334 if ( (nextScanFrequency == 0xffff) 335 || (wd->sta.scanFrequency == zfChGetLastChannel(dev, &temp)) ) 336 { 337 u8_t currScanType; 338 u8_t isExternalScan = 0; 339 u8_t isInternalScan = 0; 340 341 //zm_debug_msg1("end scan = ", KeQueryInterruptTime()); 342 wd->sta.scanFrequency = 0; 343 344 zm_debug_msg1("scan 1 type: ", wd->sta.scanMgr.currScanType); 345 zm_debug_msg1("scan channel count = ", wd->regulationTable.allowChannelCnt); 346 347 //zfBssInfoRefresh(dev); 348 zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN); 349 350 if ( wd->sta.bChannelScan == FALSE ) 351 { 352 zm_debug_msg0("WOW!! scan is cancelled\n"); 353 zmw_leave_critical_section(dev); 354 goto report_scan_result; 355 } 356 357 358 currScanType = wd->sta.scanMgr.currScanType; 359 switch(currScanType) 360 { 361 case ZM_SCAN_MGR_SCAN_EXTERNAL: 362 isExternalScan = 1; 363 364 if ( wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_INTERNAL - 1] ) 365 { 366 wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_INTERNAL - 1] = 0; 367 isInternalScan = 1; 368 } 369 370 break; 371 372 case ZM_SCAN_MGR_SCAN_INTERNAL: 373 isInternalScan = 1; 374 375 if ( wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_EXTERNAL - 1] ) 376 { 377 // Because the external scan should pre-empts internal scan. 378 // So this shall not be happened!! 379 zm_assert(0); 380 } 381 382 break; 383 384 default: 385 zm_assert(0); 386 break; 387 } 388 389 wd->sta.scanMgr.scanReqs[currScanType - 1] = 0; 390 wd->sta.scanMgr.scanStartDelay = 100; 391 wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE; 392 zmw_leave_critical_section(dev); 393 394 //Set channel according to AP's configuration 395 zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40, 396 wd->ExtOffset, zfScanMgrEventScanCompleteCb); 397 398 wd->sta.bChannelScan = FALSE; 399 400 if (zfStaIsConnected(dev)) 401 { // Finish site survey, reset the variable to detect using wrong frequency ! 402 zfHpFinishSiteSurvey(dev, 1); 403 zmw_enter_critical_section(dev); 404 wd->sta.ibssSiteSurveyStatus = 2; 405 wd->tickIbssReceiveBeacon = 0; 406 wd->sta.ibssReceiveBeaconCount = 0; 407 zmw_leave_critical_section(dev); 408 409 /* #5 Re-enable RIFS function after the site survey ! */ 410 /* This is because switch band will reset the BB register to initial value */ 411 if( wd->sta.rifsState == ZM_RIFS_STATE_DETECTED ) 412 { 413 zfHpEnableRifs(dev, ((wd->sta.currentFrequency<3000)?1:0), wd->sta.EnableHT, wd->sta.HT2040); 414 } 415 } 416 else 417 { 418 zfHpFinishSiteSurvey(dev, 0); 419 zmw_enter_critical_section(dev); 420 wd->sta.ibssSiteSurveyStatus = 0; 421 zmw_leave_critical_section(dev); 422 } 423 424report_scan_result: 425 /* avoid lose receive packet when site survey */ 426 //if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev))) 427 //{ 428 // zfSendNullData(dev, 0); 429 //} 430 431 if ( isExternalScan )//Quickly reboot 432 { 433 if (wd->zfcbScanNotify != NULL) 434 { 435 wd->zfcbScanNotify(dev, NULL); 436 } 437 } 438 439 if ( isInternalScan ) 440 { 441 //wd->sta.InternalScanReq = 0; 442 zfStaReconnect(dev); 443 } 444 445 return 0; 446 } 447 else 448 { 449 wd->sta.scanFrequency = nextScanFrequency; 450 451 //zmw_enter_critical_section(dev); 452 zfTimerCancel(dev, ZM_EVENT_IN_SCAN); 453 zmw_leave_critical_section(dev); 454 455 zm_debug_msg0("scan 2"); 456 zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb); 457 458 return 1; 459 } 460} 461 462void zfScanMgrScanEventStart(zdev_t* dev) 463{ 464 zmw_get_wlan_dev(dev); 465 466 zmw_declare_for_critical_section(); 467 468 if ( wd->sta.bChannelScan ) 469 { 470 return; 471 } 472 473 zfPowerSavingMgrWakeup(dev); 474 475 zmw_enter_critical_section(dev); 476 477 if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE ) 478 { 479 goto no_scan; 480 } 481 482 //zfBssInfoRefresh(dev); 483 zfBssInfoRefresh(dev, 0); 484 wd->sta.bChannelScan = TRUE; 485 wd->sta.bScheduleScan = FALSE; 486 zfTimerCancel(dev, ZM_EVENT_IN_SCAN); 487 zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN); 488 489 //zm_debug_msg1("start scan = ", KeQueryInterruptTime()); 490 wd->sta.scanFrequency = zfChGetFirstChannel(dev, &wd->sta.bPassiveScan); 491 zmw_leave_critical_section(dev); 492 493 /* avoid lose receive packet when site survey */ 494 //if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev))) 495 //{ 496 // zfSendNullData(dev, 1); 497 //} 498// zm_debug_msg0("scan 0"); 499// zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb); 500 501 if (zfStaIsConnected(dev)) 502 {// If doing site survey ! 503 zfHpBeginSiteSurvey(dev, 1); 504 zmw_enter_critical_section(dev); 505 wd->sta.ibssSiteSurveyStatus = 1; 506 zmw_leave_critical_section(dev); 507 } 508 else 509 { 510 zfHpBeginSiteSurvey(dev, 0); 511 zmw_enter_critical_section(dev); 512 wd->sta.ibssSiteSurveyStatus = 0; 513 zmw_leave_critical_section(dev); 514 } 515 516 zm_debug_msg0("scan 0"); 517 zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb); 518 519 return; 520 521no_scan: 522 zmw_leave_critical_section(dev); 523 return; 524} 525