1 /** \file scanMngr.c 2 * \brief This file include the scan manager module implementation 3 * \author Ronen Kalish 4 * \date 01-Mar-2005 5 */ 6 /**************************************************************************** 7 **+-----------------------------------------------------------------------+** 8 **| |** 9 **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** 10 **| All rights reserved. |** 11 **| |** 12 **| Redistribution and use in source and binary forms, with or without |** 13 **| modification, are permitted provided that the following conditions |** 14 **| are met: |** 15 **| |** 16 **| * Redistributions of source code must retain the above copyright |** 17 **| notice, this list of conditions and the following disclaimer. |** 18 **| * Redistributions in binary form must reproduce the above copyright |** 19 **| notice, this list of conditions and the following disclaimer in |** 20 **| the documentation and/or other materials provided with the |** 21 **| distribution. |** 22 **| * Neither the name Texas Instruments nor the names of its |** 23 **| contributors may be used to endorse or promote products derived |** 24 **| from this software without specific prior written permission. |** 25 **| |** 26 **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** 27 **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** 28 **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** 29 **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** 30 **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** 31 **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** 32 **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** 33 **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** 34 **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** 35 **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** 36 **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** 37 **| |** 38 **+-----------------------------------------------------------------------+** 39 ****************************************************************************/ 40 41 #include "802_11Defs.h" 42 #include "scanMngr.h" 43 #include "roamingMngr.h" 44 #include "osApi.h" 45 #include "ScanCncnApi.h" 46 #include "report.h" 47 #include "regulatoryDomainApi.h" 48 #include "utils.h" 49 #include "roamingMngr.h" 50 #include "siteMgrApi.h" 51 52 /** 53 * \author Ronen Kalish\n 54 * \date 01-Mar-2005\n 55 * \brief Creates the scan manager object.\n 56 * 57 * Function Scope \e Public.\n 58 * \param hScanMngr - handle to the OS object.\n 59 * \return a pointer to the scan manager object if successfull, NULL otherwise.\n 60 */ 61 TI_HANDLE scanMngr_create( TI_HANDLE hOS ) 62 { 63 int i,j,allocVector = 0; 64 scanMngr_t* pScanMngr ; 65 66 /* allocate the scan manager object */ 67 pScanMngr = os_memoryAlloc( hOS, sizeof(scanMngr_t) ); 68 if ( NULL == pScanMngr ) 69 { 70 WLAN_OS_REPORT( ("scanMngr_create: Failed allocating scan manager object storage.\n") ); 71 return NULL; 72 } 73 pScanMngr->hOS = hOS; 74 allocVector |= SCAN_MNGR_ALLOC_VECTOR_OBJECT; 75 76 /* create timer */ 77 pScanMngr->hContinuousScanTimer = os_timerCreate( hOS, scanMngr_GetUpdatedTsfDtimMibForScan, (TI_HANDLE)pScanMngr ); 78 79 if ( NULL == pScanMngr->hContinuousScanTimer ) 80 { 81 WLAN_OS_REPORT( ("scanMngr_create: Failed creating continuous scan timer.\n") ); 82 scanMngrFreeMem( (TI_HANDLE)pScanMngr, allocVector ); 83 return NULL; 84 } 85 86 allocVector |= SCAN_MNGR_ALLOC_VECTOR_TIMER; 87 88 /* allocate frame storage space for BSS list */ 89 for ( i = 0; i < MAX_SIZE_OF_BSS_TRACK_LIST; i++ ) 90 { 91 pScanMngr->BSSList.BSSList[ i ].pBuffer = os_memoryAlloc( hOS, MAX_BEACON_BODY_LENGTH ); 92 if ( NULL == pScanMngr->BSSList.BSSList[ i ].pBuffer ) 93 { 94 WLAN_OS_REPORT( ("scanMngr_create: Failed allocating scan result buffer for index %d.\n", i) ); 95 /* failed to allocate a buffer - release all buffers that were allocated by now */ 96 for ( j = i-1; j >= 0; j-- ) 97 { 98 os_memoryFree( hOS, pScanMngr->BSSList.BSSList[ j ].pBuffer, MAX_BEACON_BODY_LENGTH ); 99 } 100 /* release the rest of the module */ 101 scanMngrFreeMem( (TI_HANDLE)pScanMngr, allocVector ); 102 return NULL; 103 } 104 } 105 allocVector |= SCAN_MNGR_ALLOC_VECTOR_FRAME; 106 107 return (TI_HANDLE)pScanMngr; 108 } 109 110 /** 111 * \author Ronen Kalish\n 112 * \date 01-Mar-2005\n 113 * \brief Initializes the scan manager.\n 114 * 115 * Function Scope \e Public.\n 116 * \param hScanMngr - handle to the scan manager object.\n 117 * \param hReport - handle to the report object.\n 118 * \param hRegDomain - handle to the regulatory domain object.\n 119 * \param hScanCncn - handle to the scan concentrator object.\n 120 * \param hRoamMngr - handle to the roaming manager object.\n 121 * \param hSiteMngr - handle to the site manager object.\n 122 */ 123 void scanMngr_init( TI_HANDLE hScanMngr, TI_HANDLE hReport, TI_HANDLE hRegDomain, 124 TI_HANDLE hScanCncn, TI_HANDLE hRoamMngr, TI_HANDLE hSiteMngr, 125 TI_HANDLE hHalCtrl) 126 { 127 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 128 int i; 129 130 WLAN_REPORT_INFORMATION( hReport, SCAN_MNGR_MODULE_LOG, 131 ("scanMngr_init called, hScanMngr=0x%x, hReport=0x%x, hRegDomain=0x%x, " 132 "hScanCncn=0x%x, hRaomMngr=0x%x.\n", 133 hScanMngr, hReport, hRegDomain, hScanCncn, hRoamMngr) ); 134 135 /* store handles */ 136 pScanMngr->hReport = hReport; 137 pScanMngr->hRegulatoryDomain = hRegDomain; 138 pScanMngr->hScanCncn = hScanCncn; 139 pScanMngr->hRoamingMngr = hRoamMngr; 140 pScanMngr->hSiteMngr = hSiteMngr; 141 pScanMngr->hHalCtrl = hHalCtrl; 142 143 /* mark that continuous scan timer is not running */ 144 pScanMngr->bTimerRunning = FALSE; 145 146 /* mark that continuous scan process is not running */ 147 pScanMngr->bContinuousScanStarted = FALSE; 148 149 /* nullify scan policy */ 150 os_memoryZero( pScanMngr->hOS, &(pScanMngr->scanPolicy), sizeof(scan_Policy_t) ); 151 152 /* initialize the BSS list to empty list */ 153 pScanMngr->BSSList.numOfEntries = 0; 154 155 /* mark no continuous and immediate scans are currently running */ 156 pScanMngr->contScanState = SCAN_CSS_IDLE; 157 pScanMngr->immedScanState = SCAN_ISS_IDLE; 158 pScanMngr->bNewBSSFound = FALSE; 159 pScanMngr->consecNotFound = 0; 160 161 /* mark no AP recovery occured */ 162 pScanMngr->bSynchronized = TRUE; 163 164 /* mark no neighbor APs */ 165 pScanMngr->neighborAPsDiscoveryList[ RADIO_BAND_2_4_GHZ ].numOfEntries = 0; 166 pScanMngr->neighborAPsDiscoveryList[ RADIO_BAND_5_0_GHZ ].numOfEntries = 0; 167 168 /* mark no discovery process */ 169 pScanMngr->currentDiscoveryPart = SCAN_SDP_NO_DISCOVERY; 170 171 /* initialize the low quality indication to indicate that normal quality interval should be used */ 172 pScanMngr->bLowQuality = FALSE; 173 174 /* clear current BSS field (put broadcast MAC) */ 175 for ( i = 0; i < MAC_ADDR_LEN; i++ ) 176 { 177 pScanMngr->currentBSS.addr[ i ] = 0xff; 178 } 179 pScanMngr->currentBSSBand = RADIO_BAND_2_4_GHZ; 180 181 /* register scan concentrator callbacks */ 182 scanConcentrator_registerScanResultCB( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_CONT, 183 scanMngr_contScanCB, hScanMngr ); 184 scanConcentrator_registerScanResultCB( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_IMMED, 185 scanMngr_immedScanCB, hScanMngr ); 186 187 #ifdef TI_DBG 188 /* nullify statistics */ 189 os_memoryZero( pScanMngr->hOS, &(pScanMngr->stats), sizeof(scan_mngrStat_t) ); 190 /* nullify scan parameters - for debug prints before start */ 191 os_memoryZero( pScanMngr->hOS, &(pScanMngr->scanParams), sizeof(scan_Params_t) ); 192 /* initialize other variables for debug print */ 193 pScanMngr->bImmedNeighborAPsOnly = FALSE; 194 pScanMngr->bNewBSSFound = FALSE; 195 #endif 196 } 197 198 /** 199 * \author Ronen Kalish\n 200 * \date 01-Mar-2005\n 201 * \brief unloads the scan manager object.\n 202 * 203 * Function Scope \e Public.\n 204 * \param hScanMngr - handle to the scan manager object.\n 205 */ 206 void scanMngr_unload( TI_HANDLE hScanMngr ) 207 { 208 scanMngrFreeMem( hScanMngr, 0xff ); 209 } 210 211 /** 212 * \author Ronen Kalish\n 213 * \date 01-Mar-2005\n 214 * \brief Frees scan manager resources.\n 215 * 216 * Function Scope \e Private.\n 217 * \param hScanMngr - handle to the scan manager object.\n 218 * \param allocVector - bit vector indicating which resources were allocated.\n 219 */ 220 void scanMngrFreeMem( TI_HANDLE hScanMngr, UINT8 allocVector ) 221 { 222 scanMngr_t* pScanMngr = hScanMngr; 223 UINT8 i; 224 225 /* free frame storage space */ 226 if ( SCAN_MNGR_ALLOC_VECTOR_FRAME & allocVector ) 227 { 228 for ( i = 0; i < MAX_SIZE_OF_BSS_TRACK_LIST; i++ ) 229 { 230 os_memoryFree( pScanMngr->hOS, pScanMngr->BSSList.BSSList[ i ].pBuffer, MAX_BEACON_BODY_LENGTH ); 231 } 232 } 233 234 /* free the timer */ 235 if ( SCAN_MNGR_ALLOC_VECTOR_TIMER & allocVector ) 236 { 237 os_timerStop( pScanMngr->hOS, pScanMngr->hContinuousScanTimer ); 238 os_timerDestroy( pScanMngr->hOS, pScanMngr->hContinuousScanTimer ); 239 } 240 241 /* free the scan manager object */ 242 if ( SCAN_MNGR_ALLOC_VECTOR_OBJECT & allocVector ) 243 { 244 os_memoryFree( pScanMngr->hOS, hScanMngr, sizeof(scanMngr_t) ); 245 } 246 } 247 248 /** 249 * \author Ronen Kalish\n 250 * \date 01-Mar-2005\n 251 * \brief Starts an immediate scan operation.\n 252 * 253 * Function Scope \e Public.\n 254 * \param hScanMngr - handle to the scan manager object.\n 255 * \param pNeighborAPsOnly - TRUE if scan for neighbor APs only, FALSE if scan on all channels.\n 256 * \return status indication.\n 257 * \retval SCAN_MRS_SCAN_RUNNING - the scan started successfully and is now running.\n 258 * \retval SCAN_MRS_SCAN_NOT_ATTEMPTED_ALREADY_RUNNING - scan was not attempted because it is already running.\n 259 * \retval SCAN_MRS_SCAN_NOT_ATTEMPTED_EMPTY_POLICY - scan was not attempted because NULL policy defined.\n 260 * \retval SCAN_MRS_SCAN_NOT_ATTEMPTED_NO_CHANNLES_AVAILABLE - scan was not attempted because no channels were available.\n 261 * \retval SCAN_MRS_SCAN_FAILED - scan failed to start at lower levels.\n 262 */ 263 scan_mngrResultStatus_e scanMngr_startImmediateScan( TI_HANDLE hScanMngr, BOOLEAN bNeighborAPsOnly) 264 { 265 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 266 scan_bandPolicy_t *gPolicy, *aPolicy; 267 scan_cncnResultStatus_e resultStatus; 268 269 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 270 ("scanMngr_startImmediateScan called, hScanMngr=0x%x, bNeighborAPsOnly=%s.\n", 271 hScanMngr, 272 (TRUE == bNeighborAPsOnly ? "TRUE" : "FALSE")) ); 273 274 /* sanity check - whether immediate scan is already running */ 275 if ( SCAN_ISS_IDLE != pScanMngr->immedScanState ) 276 { 277 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 278 ("Immediate scan attempted while it is already running, in state:%d.\n", pScanMngr->immedScanState) ); 279 return SCAN_MRS_SCAN_NOT_ATTEMPTED_ALREADY_RUNNING; 280 } 281 282 /* get policies by band */ 283 gPolicy = scanMngrGetPolicyByBand( hScanMngr, RADIO_BAND_2_4_GHZ ); 284 aPolicy = scanMngrGetPolicyByBand( hScanMngr, RADIO_BAND_5_0_GHZ ); 285 286 /* check whether a policy is defined for at least one band */ 287 if ( ((NULL == gPolicy) || (SCAN_TYPE_NO_SCAN == gPolicy->immediateScanMethod.scanType)) && /* no policy for G band */ 288 ((NULL == aPolicy) || (SCAN_TYPE_NO_SCAN == aPolicy->immediateScanMethod.scanType)) ) /* no policy for A band */ 289 { 290 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 291 ("Immediatse scan attempted when no policy is defined.\n") ); 292 return SCAN_MRS_SCAN_NOT_ATTEMPTED_EMPTY_POLICY; 293 } 294 295 /* First try to scan on G band - if a policy is defined and channels are available */ 296 if ( (NULL != gPolicy) && /* policy is defined for G */ 297 (SCAN_TYPE_NO_SCAN != gPolicy->immediateScanMethod.scanType) ) 298 { 299 /* build scan command */ 300 scanMngrBuildImmediateScanCommand( hScanMngr, gPolicy, bNeighborAPsOnly ); 301 302 /* if no channels are available, proceed to band A */ 303 if ( 0 < pScanMngr->scanParams.numOfChannels ) 304 { 305 /* mark that immediate scan is running on band G */ 306 pScanMngr->immedScanState = SCAN_ISS_G_BAND; 307 pScanMngr->bImmedNeighborAPsOnly = bNeighborAPsOnly; 308 309 /* if continuous scan is running, mark that it should quit */ 310 if ( SCAN_CSS_IDLE != pScanMngr->contScanState ) 311 { 312 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 313 ("scanMngr_startImmediateScan called 1, switched to STOPPING state \n")); 314 315 pScanMngr->contScanState = SCAN_CSS_STOPPING; 316 } 317 318 /* send scan command to scan concentrator */ 319 resultStatus = scanConcentrator_scan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_IMMED, &(pScanMngr->scanParams) ); 320 if ( SCAN_CRS_SCAN_RUNNING != resultStatus ) 321 { 322 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 323 ("Failed to start immediate scan on band G, return code %d.\n", resultStatus) ); 324 #ifdef TI_DBG 325 pScanMngr->stats.ImmediateGByStatus[ resultStatus ]++; 326 #endif 327 return SCAN_MRS_SCAN_FAILED; 328 } 329 return SCAN_MRS_SCAN_RUNNING; 330 } 331 } 332 333 /* if G scan did not start (because no policy is configured or no channels are available, try A band */ 334 if ( (NULL != aPolicy) && 335 (SCAN_TYPE_NO_SCAN != aPolicy->immediateScanMethod.scanType) ) 336 { 337 /* build scan command */ 338 scanMngrBuildImmediateScanCommand( hScanMngr, aPolicy, bNeighborAPsOnly ); 339 340 /* if no channels are available, report error */ 341 if ( 0 == pScanMngr->scanParams.numOfChannels ) 342 { 343 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 344 ("No channels available for scan operation.\n") ); 345 return SCAN_MRS_SCAN_NOT_ATTEMPTED_NO_CHANNLES_AVAILABLE; 346 } 347 else 348 { 349 /* mark that immediate scan is running on band A */ 350 pScanMngr->immedScanState = SCAN_ISS_A_BAND; 351 352 /* if continuous scan is running, mark that it should quit */ 353 if ( SCAN_CSS_IDLE != pScanMngr->contScanState ) 354 { 355 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 356 ("scanMngr_startImmediateScan called 2, switched to STOPPING state \n")); 357 358 pScanMngr->contScanState = SCAN_CSS_STOPPING; 359 } 360 361 /* send scan command to scan concentrator */ 362 resultStatus = scanConcentrator_scan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_IMMED, &(pScanMngr->scanParams) ); 363 if ( SCAN_CRS_SCAN_RUNNING != resultStatus ) 364 { 365 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 366 ("Failed to start immediate scan on band A, return code %d.\n", resultStatus) ); 367 #ifdef TI_DBG 368 pScanMngr->stats.ImmediateAByStatus[ resultStatus ]++; 369 #endif 370 return SCAN_MRS_SCAN_FAILED; 371 } 372 return SCAN_MRS_SCAN_RUNNING; 373 } 374 } 375 else 376 { 377 /* since we passed the policy check, we arrived here because we didn't had channel on G and policy on A */ 378 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 379 ("No channels available for scan operation.\n") ); 380 return SCAN_MRS_SCAN_NOT_ATTEMPTED_NO_CHANNLES_AVAILABLE; 381 } 382 } 383 384 /** 385 * \author Ronen Kalish\n 386 * \date 01-Mar-2005\n 387 * \brief Stops an immediate scan operation.\n 388 * 389 * Function Scope \e Public.\n 390 * \param hScanMngr - handle to the scan manager object.\n 391 */ 392 void scanMngr_stopImmediateScan( TI_HANDLE hScanMngr ) 393 { 394 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 395 396 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 397 ("scanMngrStopImmediateScan called, hScanMngr=0x%x", hScanMngr) ); 398 399 /* check that immediate scan is running */ 400 if ( (SCAN_ISS_A_BAND != pScanMngr->immedScanState) && (SCAN_ISS_G_BAND != pScanMngr->immedScanState) ) 401 { 402 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 403 ("Immediate scan stop request when immediate scan is in state:%d", pScanMngr->immedScanState) ); 404 return; 405 } 406 407 #ifdef TI_DBG 408 switch ( pScanMngr->immedScanState ) 409 { 410 case SCAN_ISS_G_BAND: 411 pScanMngr->stats.ImmediateGByStatus[ SCAN_CRS_SCAN_STOPPED ]++; 412 break; 413 414 case SCAN_ISS_A_BAND: 415 pScanMngr->stats.ImmediateAByStatus[ SCAN_CRS_SCAN_STOPPED ]++; 416 break; 417 418 default: 419 break; 420 } 421 #endif 422 /* mark immediate scan status as stopping */ 423 pScanMngr->immedScanState = SCAN_ISS_STOPPING; 424 425 /* send a stop command to scan concentrator */ 426 scanConcentrator_stopScan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_IMMED ); 427 } 428 429 /** 430 * \author Ronen Kalish\n 431 * \date 01-Mar-2005\n 432 * \brief Starts the continuous scan timer.\n 433 * 434 * Function Scope \e Public.\n 435 * \param hScanMngr - handle to the scan manager object.\n 436 * \param currentBSS - the AP we are currently connected to.\n 437 * \currentBSSBand - the band of the current BSS.\n 438 */ 439 void scanMngr_startContScan( TI_HANDLE hScanMngr, macAddress_t* currentBSS, radioBand_e currentBSSBand ) 440 { 441 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 442 int currentBSSNeighborIndex; 443 444 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 445 ("scanMngr_StartContScan called, hScanMngr=0x%x.\n", hScanMngr) ); 446 447 /* if continuous scan is already running, it means we get a start command w/o stop */ 448 if ( TRUE == pScanMngr->bContinuousScanStarted ) 449 { 450 WLAN_REPORT_WARNING( pScanMngr->hOS, SCAN_MNGR_MODULE_LOG, 451 ("Start continuous scan requested when continuous scan is running.\n") ); 452 return; 453 } 454 455 /* mark that continuous scan was started */ 456 pScanMngr->bContinuousScanStarted = TRUE; 457 458 /* before reading and marking the new BSS - make sure that the old one is marked as NOT DISCOVERED */ 459 currentBSSNeighborIndex = scanMngrGetNeighborAPIndex( hScanMngr, pScanMngr->currentBSSBand, &(pScanMngr->currentBSS) ); 460 if ( -1 != currentBSSNeighborIndex ) 461 { 462 pScanMngr->neighborAPsDiscoveryList[ pScanMngr->currentBSSBand ].trackStatusList[ currentBSSNeighborIndex ] = 463 SCAN_NDS_NOT_DISCOVERED; 464 } 465 466 /* Now copy current BSS - to be used when setting neighbor APs */ 467 pScanMngr->currentBSSBand = currentBSSBand; 468 os_memoryCopy( pScanMngr->hOS, &(pScanMngr->currentBSS), currentBSS, MAC_ADDR_LEN ); 469 470 /* if current BSS is in the neighbor AP list, mark it as current BSS */ 471 currentBSSNeighborIndex = scanMngrGetNeighborAPIndex( hScanMngr, currentBSSBand, currentBSS ); 472 if ( -1 != currentBSSNeighborIndex ) 473 { 474 pScanMngr->neighborAPsDiscoveryList[ currentBSSBand ].trackStatusList[ currentBSSNeighborIndex ] = 475 SCAN_NDS_CURRENT_AP; 476 } 477 478 /* reset discovery cycle */ 479 pScanMngr->neighborAPsDiscoveryIndex[ RADIO_BAND_2_4_GHZ ] = 0; 480 pScanMngr->neighborAPsDiscoveryIndex[ RADIO_BAND_5_0_GHZ ] = 0; 481 pScanMngr->channelDiscoveryIndex[ RADIO_BAND_2_4_GHZ ] = 0; 482 pScanMngr->channelDiscoveryIndex[ RADIO_BAND_5_0_GHZ ] = 0; 483 pScanMngr->currentDiscoveryPart = SCAN_SDP_NEIGHBOR_G; 484 scanMngrSetNextDiscoveryPart( hScanMngr ); 485 486 /* clear the BSS tracking list */ 487 pScanMngr->BSSList.numOfEntries = 0; 488 489 /* start timer (if timeout is configured) */ 490 if ( ((TRUE == pScanMngr->bLowQuality) && (0 < pScanMngr->scanPolicy.normalScanInterval)) || 491 ((FALSE == pScanMngr->bLowQuality) && (0 < pScanMngr->scanPolicy.deterioratingScanInterval)) ) 492 { 493 pScanMngr->bTimerRunning = TRUE; 494 os_timerStart( pScanMngr->hOS, 495 pScanMngr->hContinuousScanTimer, 496 (FALSE == pScanMngr->bLowQuality ? 497 pScanMngr->scanPolicy.normalScanInterval : 498 pScanMngr->scanPolicy.deterioratingScanInterval), 499 TRUE ); 500 } 501 } 502 503 /** 504 * \author Ronen Kalish\n 505 * \date 01-Mar-2005\n 506 * \brief Stops the continuous scan timer.\n 507 * 508 * Function Scope \e Public.\n 509 * \param hScanMngr - handle to the scan manager object.\n 510 */ 511 void scanMngr_stopContScan( TI_HANDLE hScanMngr ) 512 { 513 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 514 UINT8 i; 515 516 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 517 ("scanMngr_stopContScan called, hScanMngr=0x%x, state =%d\n", 518 hScanMngr, pScanMngr->contScanState) ); 519 520 /* if continuous scan is not running, it means we get a stop command w/o start */ 521 if ( FALSE == pScanMngr->bContinuousScanStarted ) 522 { 523 WLAN_REPORT_WARNING( pScanMngr->hOS, SCAN_MNGR_MODULE_LOG, 524 ("Stop continuous scan when continuous scan is not running.\n") ); 525 return; 526 } 527 528 /* mark that continuous scan is not running */ 529 pScanMngr->bContinuousScanStarted = FALSE; 530 531 /* stop timer */ 532 if ( TRUE == pScanMngr->bTimerRunning ) 533 { 534 os_timerStop( pScanMngr->hOS, pScanMngr->hContinuousScanTimer ); 535 pScanMngr->bTimerRunning = FALSE; 536 } 537 538 /* if continuous scan is currently running */ 539 if ( (SCAN_CSS_IDLE != pScanMngr->contScanState) && 540 (SCAN_CSS_STOPPING != pScanMngr->contScanState) ) 541 { 542 /* send a stop scan command to the scan concentartor */ 543 scanConcentrator_stopScan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_CONT ); 544 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 545 ("scanMngr_stopContScan called, switched to STOPPING state \n")); 546 547 #ifdef TI_DBG 548 switch ( pScanMngr->contScanState ) 549 { 550 case SCAN_CSS_TRACKING_G_BAND: 551 pScanMngr->stats.TrackingGByStatus[ SCAN_CRS_SCAN_STOPPED ]++; 552 break; 553 554 case SCAN_CSS_TRACKING_A_BAND: 555 pScanMngr->stats.TrackingAByStatus[ SCAN_CRS_SCAN_STOPPED ]++; 556 break; 557 558 case SCAN_CSS_DISCOVERING: 559 if ( RADIO_BAND_2_4_GHZ == pScanMngr->statsLastDiscoveryBand ) 560 { 561 pScanMngr->stats.DiscoveryGByStatus[ SCAN_CRS_SCAN_STOPPED ]++; 562 } 563 else 564 { 565 pScanMngr->stats.DiscoveryAByStatus[ SCAN_CRS_SCAN_STOPPED ]++; 566 } 567 break; 568 569 default: 570 break; 571 } 572 #endif 573 /* mark that continuous scan is stopping */ 574 pScanMngr->contScanState = SCAN_CSS_STOPPING; 575 } 576 577 /* clear current neighbor APs */ 578 pScanMngr->neighborAPsDiscoveryList[ RADIO_BAND_2_4_GHZ ].numOfEntries = 0; 579 pScanMngr->neighborAPsDiscoveryList[ RADIO_BAND_5_0_GHZ ].numOfEntries = 0; 580 581 /* clear current BSS field .This is for the case that scanMngr_setNeighborAPs() is called before scanMngr_startcontScan() */ 582 for ( i = 0; i < MAC_ADDR_LEN; i++ ) 583 { 584 pScanMngr->currentBSS.addr[ i ] = 0xff; 585 } 586 587 } 588 589 /** 590 * \author Ronen Kalish\n 591 * \date 01-Mar-2005\n 592 * \brief returns the currently available BSS list. Verifies channels with the reg. domain.\n 593 * 594 * Function Scope \e Public.\n 595 * \param hScanMngr - handle to the scan manager object.\n 596 * \return BSS list structure pointer.\n 597 */ 598 bssList_t* scanMngr_getBSSList( TI_HANDLE hScanMngr ) 599 { 600 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 601 UINT8 BSSIndex; 602 paramInfo_t param; 603 604 605 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 606 ("scanMngr_getBSSList called, hScanMngr=0x%x.\n", hScanMngr) ); 607 608 /* loop on all BSS'es */ 609 for ( BSSIndex = 0; BSSIndex < pScanMngr->BSSList.numOfEntries; ) 610 { 611 /* verify channel validity with the reg domain - for active scan! 612 (because connection will be attempted on the channel... */ 613 param.paramType = REGULATORY_DOMAIN_GET_SCAN_CAPABILITIES; 614 param.content.channelCapabilityReq.band = pScanMngr->BSSList.BSSList[ BSSIndex ].band; 615 param.content.channelCapabilityReq.scanOption = ACTIVE_SCANNING; 616 param.content.channelCapabilityReq.channelNum = pScanMngr->BSSList.BSSList[ BSSIndex ].channel; 617 regulatoryDomain_getParam( pScanMngr->hRegulatoryDomain, ¶m ); 618 619 /* if channel is not valid */ 620 if ( !param.content.channelCapabilityRet.channelValidity ) 621 { 622 /* will replace this entry with one further down the array, if any. Therefore, index is not increased 623 (because a new entry will be placed in the same index). If this is the last entry - the number of 624 BSSes will be decreased, and thus the loop will exit */ 625 scanMngrRemoveBSSListEntry( hScanMngr, BSSIndex ); 626 } 627 else 628 { 629 BSSIndex++; 630 } 631 } 632 633 /* return the BSS list */ 634 return (bssList_t*)&(pScanMngr->BSSList); 635 } 636 637 /** 638 * \author Ronen Kalish\n 639 * \date 01-Mar-2005\n 640 * \brief Sets the neighbor APs.\n 641 * 642 * Function Scope \e Public.\n 643 * \param hScanMngr - handle to the scan manager object.\n 644 * \param neighborAPList - the neighbor AP list.\n 645 */ 646 void scanMngr_setNeighborAPs( TI_HANDLE hScanMngr, neighborAPList_t* neighborAPList ) 647 { 648 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 649 int neighborAPIndex, currentBSSNeighborIndex; 650 651 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 652 ("scanMngr_setNeighborAPs called, hScanMngr=0x%x.\n", hScanMngr) ); 653 scanMngrTracePrintNeighborAPsList( hScanMngr, neighborAPList ); 654 655 /* if continuous scan is running, indicate that it shouldn't proceed to next scan (if any) */ 656 if ( pScanMngr->contScanState != SCAN_CSS_IDLE ) 657 { 658 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 659 ("scanMngr_setNeighborAPs called, switched to STOPPING state \n")); 660 661 pScanMngr->contScanState = SCAN_CSS_STOPPING; 662 } 663 664 /* clear current neighbor APs */ 665 pScanMngr->neighborAPsDiscoveryList[ RADIO_BAND_2_4_GHZ ].numOfEntries = 0; 666 pScanMngr->neighborAPsDiscoveryList[ RADIO_BAND_5_0_GHZ ].numOfEntries = 0; 667 668 /* copy new neighbor APs, according to band */ 669 for ( neighborAPIndex = 0; neighborAPIndex < neighborAPList->numOfEntries; neighborAPIndex++ ) 670 { 671 /* insert to appropriate list */ 672 os_memoryCopy( pScanMngr->hOS, 673 &(pScanMngr->neighborAPsDiscoveryList[ neighborAPList->APListPtr[ neighborAPIndex ].band ].APListPtr[ pScanMngr->neighborAPsDiscoveryList[ neighborAPList->APListPtr[ neighborAPIndex ].band ].numOfEntries ]), 674 &(neighborAPList->APListPtr[ neighborAPIndex ]), 675 sizeof(neighborAP_t) ); 676 677 /* if AP is in track list, mark as discovered. This is done only if continuous scan 678 has already started, to ensure the roaming canidate list holds valid information */ 679 if ( TRUE == pScanMngr->bContinuousScanStarted ) 680 { 681 pScanMngr->neighborAPsDiscoveryList[ neighborAPList->APListPtr[ neighborAPIndex ].band ].trackStatusList[ pScanMngr->neighborAPsDiscoveryList[ neighborAPList->APListPtr[ neighborAPIndex ].band ].numOfEntries ] = 682 ( -1 == scanMngrGetTrackIndexByBssid( hScanMngr, &(neighborAPList->APListPtr[ neighborAPIndex ].BSSID) ) ? 683 SCAN_NDS_NOT_DISCOVERED : 684 SCAN_NDS_DISCOVERED ); 685 } 686 else 687 { 688 /* if continuous scan has not yet started, all AP's are yet to be discovered... */ 689 pScanMngr->neighborAPsDiscoveryList[ neighborAPList->APListPtr[ neighborAPIndex ].band ].trackStatusList[ pScanMngr->neighborAPsDiscoveryList[ neighborAPList->APListPtr[ neighborAPIndex ].band ].numOfEntries ] = 690 SCAN_NDS_NOT_DISCOVERED; 691 } 692 693 /* increase neighbor AP count */ 694 pScanMngr->neighborAPsDiscoveryList[ neighborAPList->APListPtr[ neighborAPIndex ].band ].numOfEntries++; 695 } 696 697 /* remove all tracked APs that are designated as neighbor APs, but are not anymore. Policy has not 698 changed, so there's no need to check APs that are not neighbor APs and were inserted to the BSS 699 list because they are on a policy defined channel. */ 700 scanMngrUpdateBSSList( hScanMngr, TRUE, FALSE ); 701 702 /* if current BSS is a neighbor AP, mark it */ 703 currentBSSNeighborIndex = scanMngrGetNeighborAPIndex( hScanMngr, 704 pScanMngr->currentBSSBand, 705 &(pScanMngr->currentBSS) ); 706 if ( -1 != currentBSSNeighborIndex ) 707 { 708 pScanMngr->neighborAPsDiscoveryList[ pScanMngr->currentBSSBand ].trackStatusList[ currentBSSNeighborIndex ] = 709 SCAN_NDS_CURRENT_AP; 710 } 711 712 /* reset discovery counters */ 713 pScanMngr->neighborAPsDiscoveryIndex[ RADIO_BAND_2_4_GHZ ] = 0; 714 pScanMngr->neighborAPsDiscoveryIndex[ RADIO_BAND_5_0_GHZ ] = 0; 715 pScanMngr->channelDiscoveryIndex[ RADIO_BAND_2_4_GHZ ] = 0; 716 pScanMngr->channelDiscoveryIndex[ RADIO_BAND_5_0_GHZ ] = 0; 717 /* set current discovery part to first part (G neighbor APs) */ 718 pScanMngr->currentDiscoveryPart = SCAN_SDP_NEIGHBOR_G; 719 /* now advance discovery part */ 720 scanMngrSetNextDiscoveryPart( hScanMngr ); 721 } 722 723 /** 724 * \author Ronen Kalish\n 725 * \date 01-Mar-2005\n 726 * \brief change quality level (normal / deteriorating).\n 727 * 728 * Function Scope \e Public.\n 729 * \param hScanMngr - handle to the scan manager object.\n 730 * \param bLowQuality - TRUE if quality is deteriorating, FALSE if quality is normal.\n 731 */ 732 void scanMngr_qualityChangeTrigger( TI_HANDLE hScanMngr, BOOLEAN bLowQuality ) 733 { 734 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 735 736 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 737 ("scanMngr_qualityChangeTrigger called, hScanMngr=0x%x, bLowQuality=%s.\n", 738 hScanMngr, (TRUE == bLowQuality ? "TRUE" : "FALSE")) ); 739 740 /* remember the low quality trigger (in case policy changes, to know which timer interval to use) */ 741 pScanMngr->bLowQuality = bLowQuality; 742 743 /* This function shouldn't be called when continuous scan is not running */ 744 if ( FALSE == pScanMngr->bContinuousScanStarted ) 745 { 746 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 747 ("Quality change trigger when continuous scan is not running.\n") ); 748 } 749 750 /* stop the timer */ 751 if ( TRUE == pScanMngr->bTimerRunning ) 752 { 753 os_timerStop( pScanMngr->hOS, pScanMngr->hContinuousScanTimer ); 754 /* start the timer with the new interval */ 755 os_timerStart( pScanMngr->hOS, pScanMngr->hContinuousScanTimer, 756 (TRUE == bLowQuality ? 757 pScanMngr->scanPolicy.deterioratingScanInterval : 758 pScanMngr->scanPolicy.normalScanInterval), 759 TRUE ); 760 } 761 } 762 763 764 /** 765 * \author Ronen Kalish\n 766 * \date 13-Mar-2005\n 767 * \brief Notifies the scan manager of a roaming event. Should be called BEFORE the SCR group 768 * \brief is changed back to connected.\n 769 * 770 * Function Scope \e Public.\n 771 * \param hScanMngr - handle to the scan manager object.\n 772 * \param macAddress - mac address of the new AP.\n 773 * \param band - the band of the new AP.\n 774 */ 775 void scanMngr_handoverDone( TI_HANDLE hScanMngr, macAddress_t* macAddress, radioBand_e band ) 776 { 777 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 778 int i, currentBSSNeighborIndex; 779 780 /* mark that TSF values are not synchronized */ 781 pScanMngr->bSynchronized = FALSE; 782 783 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 784 ("scanMngr_handoverDone called\n")); 785 786 /* if previous AP is in neighbor AP list, mark it as not discoverd */ 787 currentBSSNeighborIndex = scanMngrGetNeighborAPIndex( hScanMngr, 788 pScanMngr->currentBSSBand, 789 &(pScanMngr->currentBSS) ); 790 if ( -1 != currentBSSNeighborIndex ) 791 { 792 pScanMngr->neighborAPsDiscoveryList[ pScanMngr->currentBSSBand ].trackStatusList[ currentBSSNeighborIndex ] = 793 SCAN_NDS_NOT_DISCOVERED; 794 } 795 796 /* copy new current AP info */ 797 pScanMngr->currentBSSBand = band; 798 os_memoryCopy( pScanMngr->hOS, &(pScanMngr->currentBSS), macAddress, MAC_ADDR_LEN ); 799 800 /* if new current AP is a neighbor AP, mark it */ 801 currentBSSNeighborIndex = scanMngrGetNeighborAPIndex( hScanMngr, band, macAddress ); 802 if ( -1 != currentBSSNeighborIndex ) 803 { 804 pScanMngr->neighborAPsDiscoveryList[ band ].trackStatusList[ currentBSSNeighborIndex ] = 805 SCAN_NDS_CURRENT_AP; 806 /* note - no need to update discovery index - when adding neighbor APs the check (whether discovery should 807 be attempted) is done for every channel! */ 808 } 809 810 /* if a continuous scan is running, mark that it should stop */ 811 if ( SCAN_CSS_IDLE != pScanMngr->contScanState ) 812 { 813 814 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 815 ("scanMngr_handoverDone called, switched to STOPPING state \n")); 816 817 pScanMngr->contScanState = SCAN_CSS_STOPPING; 818 scanConcentrator_stopScan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_CONT ); 819 } 820 821 /* if the new AP is in the track list */ 822 i = scanMngrGetTrackIndexByBssid( hScanMngr, macAddress ); 823 if ( i != -1 ) 824 { 825 /* remove it */ 826 scanMngrRemoveBSSListEntry( hScanMngr, i ); 827 } 828 } 829 830 /** 831 * \author Ronen Kalish\n 832 * \date 01-Mar-2005\n 833 * \brief Callback used by the scan concentrator for immediate scan result.\n 834 * 835 * Function Scope \e Public.\n 836 * \param hScanMngr - handle to the scan manager object.\n 837 * \param resultStatus - reason for calling this function (frame received / scan complete).\n 838 * \param frameInfo - frame related information (in case of a frame reception).\n 839 * \param SPSStatus - bitmap indicating which channels were scan, in case of an SPS scan.\n 840 */ 841 void scanMngr_immedScanCB( TI_HANDLE hScanMngr, scan_cncnResultStatus_e resultStatus, 842 scan_frameInfo_t* frameInfo, UINT16 SPSStatus ) 843 { 844 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 845 scan_bandPolicy_t* aPolicy; 846 scan_cncnResultStatus_e nextResultStatus; 847 848 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 849 ("scanMngr_immedScanCB called, hScanMngr=0x%x, resultStatus=%d", 850 hScanMngr, resultStatus) ); 851 852 switch (resultStatus) 853 { 854 /* if this function is called because a frame was received, update the BSS list accordingly */ 855 case SCAN_CRS_RECEIVED_FRAME: 856 scanMngrUpdateReceivedFrame( hScanMngr, frameInfo ); 857 break; 858 859 /* scan was completed successfuly */ 860 case SCAN_CRS_SCAN_COMPLETE_OK: 861 /* act according to immediate scan state */ 862 switch (pScanMngr->immedScanState) 863 { 864 /* immediate scan on G finished */ 865 case SCAN_ISS_G_BAND: 866 #ifdef TI_DBG 867 pScanMngr->stats.ImmediateGByStatus[ resultStatus ]++; 868 #endif 869 /* check if another scan is needed (this time on A) */ 870 aPolicy = scanMngrGetPolicyByBand( hScanMngr, RADIO_BAND_5_0_GHZ ); 871 if ( (NULL != aPolicy) && 872 (SCAN_TYPE_NO_SCAN != aPolicy->immediateScanMethod.scanType) ) 873 { 874 /* build scan command */ 875 scanMngrBuildImmediateScanCommand( hScanMngr, aPolicy, pScanMngr->bImmedNeighborAPsOnly ); 876 877 /* if no channels are available, report error */ 878 if ( 0 < pScanMngr->scanParams.numOfChannels ) 879 { 880 /* mark that immediate scan is running on band A */ 881 pScanMngr->immedScanState = SCAN_ISS_A_BAND; 882 883 /* send scan command to scan concentrator */ 884 nextResultStatus = 885 scanConcentrator_scan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_IMMED, &(pScanMngr->scanParams) ); 886 if ( SCAN_CRS_SCAN_RUNNING != nextResultStatus ) 887 { 888 pScanMngr->immedScanState = SCAN_ISS_IDLE; 889 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 890 ("Failed to start immediate scan on band A, return code %d.\n", resultStatus) ); 891 #ifdef TI_DBG 892 pScanMngr->stats.ImmediateAByStatus[ nextResultStatus ]++; 893 #endif 894 roamingMngr_immediateScanComplete( pScanMngr->hRoamingMngr, SCAN_MRS_SCAN_COMPLETE_OK ); 895 } 896 } 897 else 898 { 899 /* mark that immediate scan is not running */ 900 pScanMngr->immedScanState = SCAN_ISS_IDLE; 901 902 /* no channels are actually available for scan - notify the roaming manager of the scan complete */ 903 roamingMngr_immediateScanComplete( pScanMngr->hRoamingMngr, SCAN_MRS_SCAN_COMPLETE_OK ); 904 } 905 } 906 else 907 { 908 /* mark that immediate scan is not running */ 909 pScanMngr->immedScanState = SCAN_ISS_IDLE; 910 911 /* otherwise, notify the roaming manager of the scan complete */ 912 roamingMngr_immediateScanComplete( pScanMngr->hRoamingMngr, SCAN_MRS_SCAN_COMPLETE_OK ); 913 } 914 break; 915 916 /* stop immediate scan was requested */ 917 case SCAN_ISS_STOPPING: 918 /* mark that immediate scan is not running */ 919 pScanMngr->immedScanState = SCAN_ISS_IDLE; 920 921 /* notify the roaming manager of the scan complete */ 922 roamingMngr_immediateScanComplete( pScanMngr->hRoamingMngr, SCAN_MRS_SCAN_STOPPED ); 923 break; 924 925 /* Scan completed on A band */ 926 case SCAN_ISS_A_BAND: 927 /* mark that immediate scan is not running */ 928 pScanMngr->immedScanState = SCAN_ISS_IDLE; 929 #ifdef TI_DBG 930 pScanMngr->stats.ImmediateAByStatus[ resultStatus ]++; 931 #endif 932 /* otherwise, notify the roaming manager of the scan complete */ 933 roamingMngr_immediateScanComplete( pScanMngr->hRoamingMngr, SCAN_MRS_SCAN_COMPLETE_OK ); 934 break; 935 936 default: 937 /* should not be at any other stage when CB is invoked */ 938 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 939 ("Immediate scan CB called with scan complete OK reason in state:%d", pScanMngr->immedScanState) ); 940 941 /* reset continuous scan to idle */ 942 pScanMngr->immedScanState = SCAN_ISS_IDLE; 943 break; 944 } 945 break; 946 947 /* scan was completed due to an error! */ 948 default: 949 #ifdef TI_DBG 950 switch (pScanMngr->immedScanState) 951 { 952 case SCAN_ISS_G_BAND: 953 pScanMngr->stats.ImmediateGByStatus[ resultStatus ]++; 954 break; 955 956 case SCAN_ISS_A_BAND: 957 pScanMngr->stats.ImmediateAByStatus[ resultStatus ]++; 958 break; 959 960 default: 961 break; 962 } 963 #endif 964 /* mark that immediate scan is not running */ 965 pScanMngr->immedScanState = SCAN_ISS_IDLE; 966 967 roamingMngr_immediateScanComplete( pScanMngr->hRoamingMngr, scanMngrConvertResultStatus(resultStatus) ); 968 break; 969 } 970 } 971 972 /** 973 * \author Ronen Kalish\n 974 * \date 01-Mar-2005\n 975 * \brief Callback used by the scan concentrator for continuous scan result.\n 976 * 977 * Function Scope \e Public.\n 978 * \param hScanMngr - handle to the scan manager object.\n 979 * \param resultStatus - reason for calling this function (frame received / scan complete).\n 980 * \param frameInfo - frame related info (in case of a frame reception).\n 981 * \param SPSStatus - bitmap indicating which channels were scan, in case of an SPS scan.\n 982 */ 983 void scanMngr_contScanCB( TI_HANDLE hScanMngr, scan_cncnResultStatus_e resultStatus, 984 scan_frameInfo_t* frameInfo, UINT16 SPSStatus ) 985 { 986 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 987 scan_bandPolicy_t *aPolicy; 988 scan_cncnResultStatus_e nextResultStatus; 989 990 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 991 ("scanMngr_contScanCB called, hScanMngr=0x%x, resultStatus=%d, SPSStatus=%d\n", 992 hScanMngr, resultStatus, SPSStatus) ); 993 switch (resultStatus) 994 { 995 /* frame received - update BSS list accordingly */ 996 case SCAN_CRS_RECEIVED_FRAME: 997 scanMngrUpdateReceivedFrame( hScanMngr, frameInfo ); 998 break; 999 1000 /* scan was completed successfully - either continue to next stage or simply finish this cycle */ 1001 case SCAN_CRS_SCAN_COMPLETE_OK: 1002 #ifdef SCAN_MNGR_DBG 1003 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1004 ("Continuous scan completes successfuly.\n") ); 1005 scanMngrDebugPrintBSSList( hScanMngr ); 1006 #endif 1007 #ifdef TI_DBG 1008 if ( SCAN_TYPE_SPS == pScanMngr->scanParams.scanType ) 1009 { 1010 int i; 1011 1012 /*update SPS channels attendant statistics */ 1013 for ( i = 0; i < pScanMngr->scanParams.numOfChannels; i++ ) 1014 { 1015 if ( FALSE == WAS_SPS_CHANNEL_ATTENDED( SPSStatus, i ) ) 1016 { 1017 pScanMngr->stats.SPSChannelsNotAttended[ i ]++; 1018 } 1019 } 1020 } 1021 #endif 1022 1023 /* first, remove APs that were not tracked. Note that this function does NOT 1024 increase the retry counter, and therefore there's no harm in calling it even if only 1025 some of the APs were searched in the previous tracking command, or previous command was 1026 discovery */ 1027 scanMngrPerformAging( hScanMngr ); 1028 1029 /* if new BSS's were found (or enough scan iterations passed w/o finding any), notify the roaming manager */ 1030 if ( ((TRUE == pScanMngr->bNewBSSFound) || 1031 (SCAN_MNGR_CONSEC_SCAN_ITER_FOR_PRE_AUTH < pScanMngr->consecNotFound)) && 1032 (pScanMngr->BSSList.numOfEntries > 0) ) /* in case no AP was found for specified iterations number, 1033 but no AP is present, and so is pre-auth */ 1034 { 1035 pScanMngr->bNewBSSFound = FALSE; 1036 pScanMngr->consecNotFound = 0; 1037 roamingMngr_updateNewBssList( pScanMngr->hRoamingMngr, (bssList_t*)&(pScanMngr->BSSList) ); 1038 } 1039 1040 /* act according to continuous scan state */ 1041 switch (pScanMngr->contScanState) 1042 { 1043 case SCAN_CSS_TRACKING_G_BAND: 1044 #ifdef TI_DBG 1045 pScanMngr->stats.TrackingGByStatus[ resultStatus ]++; 1046 #endif 1047 WLAN_REPORT_INFORMATION(pScanMngr->hReport , SCAN_MNGR_MODULE_LOG , ("\n Starting SCAN_CSS_TRACKING_G_BAND \n")); 1048 /* if necessary, attempt tracking on A */ 1049 aPolicy = scanMngrGetPolicyByBand( hScanMngr, RADIO_BAND_5_0_GHZ ); 1050 /* if a policy is defined for A band tracking, attempt to perform it */ 1051 if ( (NULL != aPolicy) && 1052 (SCAN_TYPE_NO_SCAN != aPolicy->trackingMethod.scanType) ) 1053 { 1054 /* recalculate current TSF, to adjust the TSF read at the beginning of 1055 the continuous scan process with the tracking on G duration */ 1056 pScanMngr->currentTSF += 1057 ((os_timeStampMs( pScanMngr->hOS ) - pScanMngr->currentHostTimeStamp) * 1000); 1058 1059 /* build scan command */ 1060 scanMngrBuildTrackScanCommand( hScanMngr, aPolicy, RADIO_BAND_5_0_GHZ ); 1061 1062 /* if channels are available for tracking on A */ 1063 if ( 0 < pScanMngr->scanParams.numOfChannels ) 1064 { 1065 /* mark that continuous scan is now tracking on A */ 1066 pScanMngr->contScanState = SCAN_CSS_TRACKING_A_BAND; 1067 1068 /* send scan command */ 1069 nextResultStatus = 1070 scanConcentrator_scan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_CONT, &(pScanMngr->scanParams) ); 1071 if ( SCAN_CRS_SCAN_RUNNING != nextResultStatus ) 1072 { 1073 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1074 ("Failed to start tracking continuous scan on band A, return code %d.\n", resultStatus) ); 1075 #ifdef TI_DBG 1076 pScanMngr->stats.TrackingAByStatus[ nextResultStatus ]++; 1077 #endif 1078 pScanMngr->contScanState = SCAN_CSS_IDLE; 1079 } 1080 #ifdef SCAN_MNGR_DBG 1081 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1082 ("Tracking on A started.\n") ); 1083 #endif 1084 return; 1085 } 1086 } 1087 /* in case a TSF error was received on last continuous scan cycle, mark (now, that tracking 1088 on both bands was attempted), that TSF values are synchronized */ 1089 pScanMngr->bSynchronized = TRUE; 1090 1091 /* the break is missing on purpose: if tracking on A was not successful (or not needed), continue to discovery */ 1092 1093 case SCAN_CSS_TRACKING_A_BAND: 1094 #ifdef TI_DBG 1095 /* update stats - since there's no break above, we must check that the state is indeed tracking on A */ 1096 if ( SCAN_CSS_TRACKING_A_BAND == pScanMngr->contScanState ) 1097 { 1098 pScanMngr->stats.TrackingAByStatus[ resultStatus ]++; 1099 } 1100 #endif 1101 WLAN_REPORT_INFORMATION(pScanMngr->hReport , SCAN_MNGR_MODULE_LOG , ("\n SCAN_CSS_TRACKING_A_BAND \n" )) ; 1102 /* if necessary and possible, attempt discovery */ 1103 if ( (SCAN_SDP_NO_DISCOVERY != pScanMngr->currentDiscoveryPart) && 1104 (pScanMngr->BSSList.numOfEntries <= pScanMngr->scanPolicy.BSSNumberToStartDiscovery) ) 1105 { 1106 /* build scan command */ 1107 scanMngrBuildDiscoveryScanCommand( hScanMngr ); 1108 1109 /* if channels are available for discovery */ 1110 if ( 0 < pScanMngr->scanParams.numOfChannels ) 1111 { 1112 /* mark that continuous scan is now in discovery state */ 1113 pScanMngr->contScanState = SCAN_CSS_DISCOVERING; 1114 1115 /* mark that no new APs were discovered in this discovery operation */ 1116 pScanMngr->bNewBSSFound = FALSE; 1117 1118 /* send scan command */ 1119 nextResultStatus = 1120 scanConcentrator_scan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_CONT, &(pScanMngr->scanParams) ); 1121 if ( SCAN_CRS_SCAN_RUNNING != nextResultStatus ) 1122 { 1123 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1124 ("Failed to start discovery continuous scan, nextResultStatus %d.\n", nextResultStatus) ); 1125 pScanMngr->contScanState = SCAN_CSS_IDLE; 1126 } 1127 #ifdef SCAN_MNGR_DBG 1128 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1129 ("Disocvery started.\n") ); 1130 #endif 1131 return; 1132 } 1133 } 1134 1135 /* the break is missing on purpose: if discovery was not successful (or not needed), finish scan cycle */ 1136 1137 case SCAN_CSS_DISCOVERING: 1138 #ifdef TI_DBG 1139 /* update stats - since there's no break above, we must check that the state is indeed discocery */ 1140 if ( SCAN_CSS_DISCOVERING == pScanMngr->contScanState ) 1141 { 1142 if ( RADIO_BAND_2_4_GHZ == pScanMngr->statsLastDiscoveryBand ) 1143 { 1144 pScanMngr->stats.DiscoveryGByStatus[ resultStatus ]++; 1145 } 1146 else 1147 { 1148 pScanMngr->stats.DiscoveryAByStatus[ resultStatus ]++; 1149 } 1150 } 1151 #endif 1152 /* continuous scan cycle is complete */ 1153 pScanMngr->contScanState = SCAN_CSS_IDLE; 1154 1155 break; 1156 1157 case SCAN_CSS_STOPPING: 1158 /* continuous scan cycle is complete */ 1159 pScanMngr->contScanState = SCAN_CSS_IDLE; 1160 break; 1161 1162 default: 1163 /* should not be at any other stage when CB is invoked */ 1164 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1165 ("Continuous scan CB called with scan complete OK reason in state:%d\n", pScanMngr->contScanState) ); 1166 1167 /* reset continuous scan to idle */ 1168 pScanMngr->contScanState = SCAN_CSS_IDLE; 1169 pScanMngr->bNewBSSFound = FALSE; 1170 break; 1171 } 1172 break; 1173 1174 /* SPS scan was completed with TSF error */ 1175 case SCAN_CRS_TSF_ERROR: 1176 /* report the recovery event */ 1177 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1178 ("Continuous scan callback called with TSF error indication\n") ); 1179 /* mark that the TSF values are no longer valid */ 1180 pScanMngr->bSynchronized = FALSE; 1181 #ifdef TI_DBG 1182 switch ( pScanMngr->contScanState ) 1183 { 1184 case SCAN_CSS_TRACKING_G_BAND: 1185 pScanMngr->stats.TrackingGByStatus[ resultStatus ]++; 1186 break; 1187 1188 case SCAN_CSS_TRACKING_A_BAND: 1189 pScanMngr->stats.TrackingAByStatus[ resultStatus ]++; 1190 break; 1191 1192 default: 1193 break; 1194 } 1195 #endif 1196 /* stop continuous scan cycle for this time (to avoid tracking using discovery only on A, thus 1197 having mixed results - some are synchronized, some are not */ 1198 pScanMngr->contScanState = SCAN_CSS_IDLE; 1199 break; 1200 1201 default: 1202 /* report the status received */ 1203 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1204 ("Continuous scan CB called with status %d\n", resultStatus) ); 1205 1206 /* also perform aging (since it does not increase counter, no harm done if this was not tracking */ 1207 scanMngrPerformAging( hScanMngr ); 1208 #ifdef TI_DBG 1209 switch ( pScanMngr->contScanState ) 1210 { 1211 case SCAN_CSS_TRACKING_G_BAND: 1212 pScanMngr->stats.TrackingGByStatus[ resultStatus ]++; 1213 break; 1214 1215 case SCAN_CSS_TRACKING_A_BAND: 1216 pScanMngr->stats.TrackingAByStatus[ resultStatus ]++; 1217 break; 1218 1219 case SCAN_CSS_DISCOVERING: 1220 if ( RADIO_BAND_2_4_GHZ == pScanMngr->statsLastDiscoveryBand ) 1221 { 1222 pScanMngr->stats.DiscoveryGByStatus[ resultStatus ]++; 1223 } 1224 else 1225 { 1226 pScanMngr->stats.DiscoveryGByStatus[ resultStatus ]++; 1227 } 1228 default: 1229 break; 1230 } 1231 #endif 1232 /* finish scan for this iteration */ 1233 pScanMngr->contScanState = SCAN_CSS_IDLE; 1234 break; 1235 } 1236 } 1237 1238 /** 1239 * \author Ronen Kalish\n 1240 * \date 08-Mar-2005\n 1241 * \brief Parses and executes a get param command.\n 1242 * 1243 * Function Scope \e Public.\n 1244 * \param hScanMngr - handle to the scan manager object.\n 1245 * \param pParam - the param to get.\n 1246 * \return OK if the parameter was get successfully, NOK otherwise.\n 1247 */ 1248 TI_STATUS scanMngr_getParam( TI_HANDLE hScanMngr, paramInfo_t *pParam ) 1249 { 1250 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1251 1252 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1253 ("scanMngr_getParam called, hScanMngr=0x%x, pParam=0x%x\n", 1254 hScanMngr, pParam) ); 1255 1256 /* act according to parameter type */ 1257 switch ( pParam->paramType ) 1258 { 1259 case SCAN_MNGR_BSS_LIST_GET: 1260 pParam->content.pScanBssList = scanMngr_getBSSList( hScanMngr ); 1261 break; 1262 1263 default: 1264 WLAN_REPORT_ERROR( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1265 ("Scan manager getParam called with param type %d.\n", pParam->paramType) ); 1266 return PARAM_NOT_SUPPORTED; 1267 /* break; - unreachable */ 1268 } 1269 1270 return OK; 1271 } 1272 1273 /** 1274 * \author Ronen Kalish\n 1275 * \date 01-Mar-2005\n 1276 * \brief Parses and executes a set param command.\n 1277 * 1278 * Function Scope \e Public.\n 1279 * \param hScanMngr - handle to the scan manager object.\n 1280 * \param pParam - the param to set.\n 1281 * \return OK if the parameter was set successfully, NOK otherwise.\n 1282 */ 1283 TI_STATUS scanMngr_setParam( TI_HANDLE hScanMngr, paramInfo_t *pParam ) 1284 { 1285 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1286 1287 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1288 ("scanMngr_setParam called, hScanMngr=0x%x, pParam=0x%x, pParam->paramType=%d, " 1289 "pParam->content.applicationConfigBuffer.buffer=0x%x, " 1290 "pParam->content.applicationConfigBuffer.bufferSize=%d.\n", 1291 hScanMngr, pParam, pParam->paramType, pParam->content.applicationConfigBuffer.buffer, 1292 pParam->content.applicationConfigBuffer.bufferSize) ); 1293 1294 /* act according to parameter type */ 1295 switch ( pParam->paramType ) 1296 { 1297 case SCAN_MNGR_SET_CONFIGURATION: 1298 if ( sizeof(scan_Policy_t) != pParam->content.applicationConfigBuffer.bufferSize ) 1299 { 1300 WLAN_REPORT_ERROR( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1301 ("Scan manager set configuration received with wrong buffer size %d.\n", 1302 pParam->content.applicationConfigBuffer.bufferSize) ); 1303 return NOK; 1304 } 1305 scanMngr_setScanPolicy( hScanMngr, (scan_Policy_t*)(pParam->content.applicationConfigBuffer.buffer) ); 1306 break; 1307 1308 default: 1309 WLAN_REPORT_ERROR( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1310 ("Set param, Params is not supported:%d\n", pParam->paramType) ); 1311 return PARAM_NOT_SUPPORTED; 1312 } 1313 1314 return OK; 1315 } 1316 1317 /** 1318 * \author Ronen Kalish\n 1319 * \date 01-Mar-2005\n 1320 * \brief Sets the scan policy.\n 1321 * 1322 * Function Scope \e Public.\n 1323 * \param hScanMngr - handle to the scan manager object.\n 1324 * \param scanPolicy - a pointer to the policy data.\n 1325 */ 1326 void scanMngr_setScanPolicy( TI_HANDLE hScanMngr, scan_Policy_t* scanPolicy ) 1327 { 1328 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1329 1330 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1331 ("scanMngr_setScanPolicy called, hScanMngr=0x%x.\n", hScanMngr) ); 1332 #ifdef SCAN_MNGR_DBG 1333 scanMngrTracePrintScanPolicy( scanPolicy ); 1334 #endif 1335 1336 /* if continuous or immediate scan are running, indicate that they shouldn't proceed to next scan (if any), 1337 and stop the scan operation (in case a triggered scan was in progress and the voice was stopped, the scan 1338 must be stopped or a recovery will occur */ 1339 if ( pScanMngr->contScanState != SCAN_CSS_IDLE ) 1340 { 1341 pScanMngr->contScanState = SCAN_CSS_STOPPING; 1342 scanConcentrator_stopScan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_CONT ); 1343 } 1344 if ( pScanMngr->immedScanState != SCAN_ISS_IDLE ) 1345 { 1346 pScanMngr->immedScanState = SCAN_ISS_STOPPING; 1347 scanConcentrator_stopScan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_IMMED ); 1348 } 1349 1350 /* set new scan policy */ 1351 os_memoryCopy( pScanMngr->hOS, &(pScanMngr->scanPolicy), scanPolicy, sizeof(scan_Policy_t) ); 1352 1353 /* remove all tracked APs that are not on a policy defined channel (neighbor APs haven't changed, 1354 so there's no need to check them */ 1355 scanMngrUpdateBSSList( hScanMngr, FALSE, TRUE ); 1356 1357 /* if continuous scan timer is running, stop it */ 1358 if ( TRUE == pScanMngr->bTimerRunning ) 1359 { 1360 os_timerStop( pScanMngr->hOS, pScanMngr->hContinuousScanTimer ); 1361 pScanMngr->bTimerRunning = FALSE; 1362 } 1363 1364 /* if continuous scan was started, start the timer using the new intervals */ 1365 if ( TRUE == pScanMngr->bContinuousScanStarted ) 1366 { 1367 pScanMngr->bTimerRunning = TRUE; 1368 os_timerStart( pScanMngr->hOS, pScanMngr->hContinuousScanTimer, 1369 (FALSE == pScanMngr->bLowQuality ? 1370 pScanMngr->scanPolicy.normalScanInterval : 1371 pScanMngr->scanPolicy.deterioratingScanInterval), 1372 TRUE ); 1373 } 1374 1375 /* reset discovery counters */ 1376 pScanMngr->neighborAPsDiscoveryIndex[ RADIO_BAND_2_4_GHZ ] = 0; 1377 pScanMngr->neighborAPsDiscoveryIndex[ RADIO_BAND_5_0_GHZ ] = 0; 1378 pScanMngr->channelDiscoveryIndex[ RADIO_BAND_2_4_GHZ ] = 0; 1379 pScanMngr->channelDiscoveryIndex[ RADIO_BAND_5_0_GHZ ] = 0; 1380 /* set current discovery part to first part */ 1381 pScanMngr->currentDiscoveryPart = SCAN_SDP_NEIGHBOR_G; 1382 /* now advance discovery part to first valid part */ 1383 scanMngrSetNextDiscoveryPart( hScanMngr ); 1384 } 1385 1386 /** 1387 * \author Terence Zaoui\n 1388 * \date 06-Feb-2006\n 1389 * \brief CB function for current TSF and last beacon TSF and DTIM read.\n 1390 * 1391 * Function Scope \e Public.\n 1392 * \param hScanMngr - handle to the scan manager object.\n 1393 * \param status - read status (OK / NOK).\n 1394 * \param CB_buf - a pointer to the data read.\n 1395 */ 1396 void scanMngrGetCurrentTsfDtimMibCB(TI_HANDLE hScanMngr, TI_STATUS status, UINT8* CB_buf) 1397 { 1398 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1399 1400 os_memoryCopy(pScanMngr->hOS, (UINT8*)&(pScanMngr->currTsfDtimMib) , CB_buf , sizeof(tsf_dtim_mib_t) ) ; 1401 1402 /* set the current TSF and last beacon TSF and DTIM count */ 1403 INT64_HIGHER( pScanMngr->currentTSF ) = pScanMngr->currTsfDtimMib.CurrentTSFHigh; 1404 INT64_LOWER( pScanMngr->currentTSF ) = pScanMngr->currTsfDtimMib.CurrentTSFLow; 1405 1406 INT64_HIGHER( pScanMngr->lastLocalBcnTSF ) = pScanMngr->currTsfDtimMib.lastTBTTHigh; 1407 INT64_LOWER( pScanMngr->lastLocalBcnTSF ) = pScanMngr->currTsfDtimMib.lastTBTTLow; 1408 1409 pScanMngr->lastLocalBcnDTIMCount = pScanMngr->currTsfDtimMib.LastDTIMCount; 1410 1411 WLAN_REPORT_INFORMATION( pScanMngr->hReport , SCAN_MNGR_MODULE_LOG , 1412 ("\n currentTSF = %u-%u lastLocalBcnTSF = %u-%u lastDTIMCount = %d \n", 1413 INT64_HIGHER( pScanMngr->currentTSF ), INT64_LOWER( pScanMngr->currentTSF ), 1414 INT64_HIGHER( pScanMngr->lastLocalBcnTSF ), INT64_LOWER( pScanMngr->lastLocalBcnTSF ), 1415 pScanMngr->lastLocalBcnDTIMCount ) ); 1416 1417 /* get the current host time stamp */ 1418 pScanMngr->currentHostTimeStamp = os_timeStampMs( pScanMngr->hOS ); 1419 1420 /* now that the current TSF and last beacon TSF had been retrieved from the FW, 1421 continuous scan may proceed */ 1422 scanMngrPerformContinuousScan(hScanMngr); 1423 } 1424 1425 /** 1426 * \author Terence Zaoui\n 1427 * \date 06-Feb-2006\n 1428 * \brief requests current TSF and last beacon TSF and DTIM from the FW.\n 1429 * 1430 * Function Scope \e Public.\n 1431 * \param hScanMngr - handle to the scan manager object.\n 1432 */ 1433 void scanMngr_GetUpdatedTsfDtimMibForScan( TI_HANDLE hScanMngr ) 1434 { 1435 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1436 whalParamInfo_t whalParam; 1437 TI_STATUS reqStatus = OK; 1438 1439 WLAN_REPORT_INFORMATION( pScanMngr->hReport , SCAN_MNGR_MODULE_LOG , 1440 ("\nscanMngr_GetUpdatedTsfDtimMibForScan called\n") ); 1441 1442 /* Getting the current TSF and DTIM values */ 1443 whalParam.paramType = HAL_CTRL_TSF_DTIM_MIB; 1444 whalParam.content.interogateCmdCBParams.CB_Func = (void *)scanMngrGetCurrentTsfDtimMibCB; 1445 whalParam.content.interogateCmdCBParams.CB_handle = hScanMngr; 1446 whalParam.content.interogateCmdCBParams.CB_buf = (UINT8*)(&(pScanMngr->currTsfDtimMib)); 1447 reqStatus = whalCtrl_GetParam( pScanMngr->hHalCtrl, &whalParam ); 1448 if ( OK != reqStatus ) 1449 { 1450 WLAN_REPORT_ERROR( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1451 ("%s: getParam from HAL CTRL failed wih status: %d\n", 1452 __FUNCTION__, reqStatus) ); 1453 } 1454 } 1455 1456 /** 1457 * \author Ronen Kalish\n 1458 * \date 01-Mar-2005\n 1459 * \brief Starts a continuous scan operation.\n 1460 * 1461 * Function Scope \e Private.\n 1462 * \param hScanMngr - handle to the scan manager object.\n 1463 */ 1464 void scanMngrPerformContinuousScan( TI_HANDLE hScanMngr ) 1465 { 1466 1467 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1468 scan_bandPolicy_t *gPolicy, *aPolicy; 1469 scan_cncnResultStatus_e resultStatus; 1470 paramInfo_t param; 1471 1472 #ifdef SCAN_MNGR_DBG 1473 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1474 ("scanMngrPerformContinuousScan called, hScanMngr=0x%x.\n", hScanMngr) ); 1475 scanMngrDebugPrintBSSList( hScanMngr ); 1476 #endif 1477 1478 /* this function is called due to continuous scan timer expiry, to start a new continuous scan cycle. 1479 If the continuous scan is anything but idle, a new cycle is not started. */ 1480 if ( SCAN_CSS_IDLE != pScanMngr->contScanState ) 1481 { 1482 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1483 ("Continuous scan timer expired and continuous scan state is:%d\n", pScanMngr->contScanState) ); 1484 return; 1485 } 1486 1487 /* retrieve the current BSS DTIM period and beacon interval, for SPS DTIM avoidance 1488 calculations later. This is done before the continuous scan process is started, 1489 to check that they are not zero (in case the STA disconnected and somehow the 1490 scan manager was not notified of the event). If the STA disconnected, the continuous 1491 scan process is aborted */ 1492 param.paramType = SITE_MGR_BEACON_INTERVAL_PARAM; 1493 siteMgr_getParam( pScanMngr->hSiteMngr, ¶m ); 1494 pScanMngr->currentBSSBeaconInterval = param.content.beaconInterval; 1495 1496 param.paramType = SITE_MGR_DTIM_PERIOD_PARAM; 1497 siteMgr_getParam( pScanMngr->hSiteMngr, ¶m ); 1498 pScanMngr->currentBSSDtimPeriod = param.content.siteMgrDtimPeriod; 1499 1500 /* now check that none of the above is zero */ 1501 if ( (0 == pScanMngr->currentBSSBeaconInterval) || (0 == pScanMngr->currentBSSDtimPeriod) ) 1502 { 1503 WLAN_REPORT_ERROR( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1504 ("Trying to start continuous scan cycle but DTIM period=%d and beacon interval=%d\n", 1505 pScanMngr->currentBSSDtimPeriod, pScanMngr->currentBSSBeaconInterval) ); 1506 return; 1507 } 1508 1509 /* increase the consecutive not found counter */ 1510 pScanMngr->consecNotFound++; 1511 1512 /* first try tracking on G */ 1513 gPolicy = scanMngrGetPolicyByBand( hScanMngr, RADIO_BAND_2_4_GHZ ); 1514 /* if a policy is defined for G band tracking, attempt to perform it */ 1515 if ( (NULL != gPolicy) && 1516 (SCAN_TYPE_NO_SCAN != gPolicy->trackingMethod.scanType) ) 1517 { 1518 /* build scan command */ 1519 scanMngrBuildTrackScanCommand( hScanMngr, gPolicy, RADIO_BAND_2_4_GHZ ); 1520 1521 /* if channels are available for tracking on G */ 1522 if ( 0 < pScanMngr->scanParams.numOfChannels ) 1523 { 1524 /* mark that continuous scan is now tracking on G */ 1525 pScanMngr->contScanState = SCAN_CSS_TRACKING_G_BAND; 1526 1527 /* send scan command */ 1528 resultStatus = scanConcentrator_scan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_CONT, &(pScanMngr->scanParams) ); 1529 if ( SCAN_CRS_SCAN_RUNNING != resultStatus ) 1530 { 1531 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1532 ("Failed to start tracking continuous scan on G, return code %d.\n", resultStatus) ); 1533 #ifdef TI_DBG 1534 pScanMngr->stats.TrackingGByStatus[ resultStatus ]++; 1535 #endif 1536 pScanMngr->contScanState = SCAN_CSS_IDLE; 1537 } 1538 #ifdef SCAN_MNGR_DBG 1539 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1540 ("Tracking on G started.\n") ); 1541 #endif 1542 return; 1543 } 1544 } 1545 1546 /* if not, try tracking on A */ 1547 aPolicy = scanMngrGetPolicyByBand( hScanMngr, RADIO_BAND_5_0_GHZ ); 1548 /* if a policy is defined for A band tracking, attempt to perform it */ 1549 if ( (NULL != aPolicy) && 1550 (SCAN_TYPE_NO_SCAN != aPolicy->trackingMethod.scanType) ) 1551 { 1552 /* build scan command */ 1553 scanMngrBuildTrackScanCommand( hScanMngr, aPolicy, RADIO_BAND_5_0_GHZ ); 1554 1555 /* if channels are available for tracking on A */ 1556 if ( 0 < pScanMngr->scanParams.numOfChannels ) 1557 { 1558 /* mark that continuous scan is now tracking on A */ 1559 pScanMngr->contScanState = SCAN_CSS_TRACKING_A_BAND; 1560 1561 /* send scan command */ 1562 resultStatus = scanConcentrator_scan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_CONT, &(pScanMngr->scanParams) ); 1563 if ( SCAN_CRS_SCAN_RUNNING != resultStatus ) 1564 { 1565 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1566 ("Failed to start tracking continuous scan on A, return code %d.\n", resultStatus) ); 1567 #ifdef TI_DBG 1568 pScanMngr->stats.TrackingAByStatus[ resultStatus ]++; 1569 #endif 1570 pScanMngr->contScanState = SCAN_CSS_IDLE; 1571 } 1572 #ifdef SCAN_MNGR_DBG 1573 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1574 ("Tracking on A started.\n") ); 1575 #endif 1576 return; 1577 } 1578 } 1579 /* in case a TSF error was received on last continuous scan cycle, mark (now, that tracking 1580 on both bands was attempted), that TSF values are synchronized */ 1581 pScanMngr->bSynchronized = TRUE; 1582 1583 /* if this does not work as well, try discovery */ 1584 /* discovery can be performed if discovery part is valid (this is maintained whenever a new policy or neighbor AP list 1585 is set, a discovery scan command is built, and a new neighbor AP is discovered) */ 1586 if ( (SCAN_SDP_NO_DISCOVERY != pScanMngr->currentDiscoveryPart) && 1587 (pScanMngr->BSSList.numOfEntries <= pScanMngr->scanPolicy.BSSNumberToStartDiscovery) ) 1588 { 1589 /* build scan command */ 1590 scanMngrBuildDiscoveryScanCommand( hScanMngr ); 1591 1592 /* if channels are available for discovery */ 1593 if ( 0 < pScanMngr->scanParams.numOfChannels ) 1594 { 1595 /* mark that continuous scan is now in discovery state */ 1596 pScanMngr->contScanState = SCAN_CSS_DISCOVERING; 1597 1598 /* mark that no new BSS's were found (yet) */ 1599 pScanMngr->bNewBSSFound = FALSE; 1600 1601 /* send scan command */ 1602 resultStatus = scanConcentrator_scan( pScanMngr->hScanCncn, SCAN_SCC_ROAMING_CONT, &(pScanMngr->scanParams) ); 1603 if ( SCAN_CRS_SCAN_RUNNING != resultStatus ) 1604 { 1605 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1606 ("Failed to start discovery continuous scan, resultStatus %d.\n", resultStatus) ); 1607 #ifdef TI_DBG 1608 if ( RADIO_BAND_2_4_GHZ == pScanMngr->statsLastDiscoveryBand ) 1609 { 1610 pScanMngr->stats.DiscoveryGByStatus[ resultStatus ]++; 1611 } 1612 else 1613 { 1614 pScanMngr->stats.DiscoveryAByStatus[ resultStatus ]++; 1615 } 1616 #endif 1617 pScanMngr->contScanState = SCAN_CSS_IDLE; 1618 } 1619 #ifdef SCAN_MNGR_DBG 1620 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1621 ("Discovery started.\n") ); 1622 #endif 1623 return; 1624 } 1625 } 1626 1627 /* if we got here, no scan had executed successfully - print a warning */ 1628 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1629 ("Unable to perform continuous scan.\n") ); 1630 } 1631 1632 /** 1633 * \author Ronen Kalish\n 1634 * \date 01-Mar-2005\n 1635 * \brief Perform aging on the BSS list.\n 1636 * 1637 * Function Scope \e Private.\n 1638 * \param hScanMngr - handle to the scan manager object.\n 1639 */ 1640 void scanMngrPerformAging( TI_HANDLE hScanMngr ) 1641 { 1642 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1643 UINT8 BSSEntryIndex; 1644 1645 #ifdef SCAN_MNGR_DBG 1646 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1647 ("Performing Aging.\n") ); 1648 #endif 1649 /* loop on all entries in the BSS list */ 1650 for ( BSSEntryIndex = 0; BSSEntryIndex < pScanMngr->BSSList.numOfEntries; ) 1651 { 1652 /* if an entry failed enough consecutive track attempts - remove it */ 1653 if ( pScanMngr->BSSList.scanBSSList[ BSSEntryIndex ].trackFailCount > 1654 pScanMngr->scanPolicy.maxTrackFailures ) 1655 { 1656 /* will replace this entry with one further down the array, if any. Therefore, index is not increased 1657 (because a new entry will be placed in the same index). If this is the last entry - the number of 1658 BSSes will be decreased, and thus the loop will exit */ 1659 #ifdef SCAN_MNGR_DBG 1660 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1661 ("Aging: removing BSSID %2x:%2x:%2x:%2x:%2x:%2x from index: %d.\n", 1662 pScanMngr->BSSList.BSSList[ BSSEntryIndex ].BSSID.addr[ 0 ], 1663 pScanMngr->BSSList.BSSList[ BSSEntryIndex ].BSSID.addr[ 1 ], 1664 pScanMngr->BSSList.BSSList[ BSSEntryIndex ].BSSID.addr[ 2 ], 1665 pScanMngr->BSSList.BSSList[ BSSEntryIndex ].BSSID.addr[ 3 ], 1666 pScanMngr->BSSList.BSSList[ BSSEntryIndex ].BSSID.addr[ 4 ], 1667 pScanMngr->BSSList.BSSList[ BSSEntryIndex ].BSSID.addr[ 5 ], 1668 pScanMngr->BSSList.numOfEntries) ); 1669 #endif 1670 scanMngrRemoveBSSListEntry( hScanMngr, BSSEntryIndex ); 1671 } 1672 else 1673 { 1674 BSSEntryIndex++; 1675 } 1676 } 1677 } 1678 1679 /** 1680 * \author Ronen Kalish\n 1681 * \date 01-Mar-2005\n 1682 * \brief Updates object data according to a received frame.\n 1683 * 1684 * Function Scope \e Private.\n 1685 * \param hScanMngr - handle to the scan manager object.\n 1686 * \param frameInfo - pointer to frame related information.\n 1687 */ 1688 void scanMngrUpdateReceivedFrame( TI_HANDLE hScanMngr, scan_frameInfo_t* frameInfo ) 1689 { 1690 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1691 int BSSListIndex, neighborAPIndex; 1692 scan_bandPolicy_t* pBandPolicy; 1693 1694 #ifdef SCAN_MNGR_DBG 1695 scanMngrDebugPrintReceivedFrame( hScanMngr, frameInfo ); 1696 #endif 1697 #ifdef TI_DBG 1698 pScanMngr->stats.receivedFrames++; 1699 #endif 1700 /* first check if the frame pass RSSI threshold. If not discard it and continue */ 1701 pBandPolicy = scanMngrGetPolicyByBand( hScanMngr, frameInfo->band ); 1702 if ( NULL == pBandPolicy ) /* sanity checking */ 1703 { 1704 WLAN_REPORT_ERROR( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1705 ("Recieved framed on band %d, for which policy is not defined!\n", frameInfo->band) ); 1706 #ifdef TI_DBG 1707 pScanMngr->stats.discardedFramesOther++; 1708 #endif 1709 return; 1710 } 1711 1712 if ( frameInfo->rssi < pBandPolicy->rxRSSIThreshold ) 1713 { 1714 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1715 ("Discarding frame beacuse RSSI %d is lower than threshold %d\n", 1716 frameInfo->rssi, pBandPolicy->rxRSSIThreshold) ); 1717 #ifdef TI_DBG 1718 pScanMngr->stats.discardedFramesLowRSSI++; 1719 #endif 1720 return; 1721 } 1722 1723 /* search for this AP in the tracking list */ 1724 BSSListIndex = scanMngrGetTrackIndexByBssid( hScanMngr, frameInfo->bssId ); 1725 1726 /* if the frame received from an AP in the track list */ 1727 if ( -1 != BSSListIndex ) 1728 { 1729 scanMngrUpdateBSSInfo( hScanMngr, BSSListIndex, frameInfo ); 1730 } 1731 /* otherwise, if the list is not full and AP is either a neighbor AP or on a policy defined channel: */ 1732 else 1733 { 1734 neighborAPIndex = scanMngrGetNeighborAPIndex( hScanMngr, frameInfo->band, frameInfo->bssId ); 1735 1736 if ( (pScanMngr->BSSList.numOfEntries < pScanMngr->scanPolicy.BSSListSize) && 1737 ((TRUE == scanMngrIsPolicyChannel( hScanMngr, frameInfo->band, frameInfo->channel )) || 1738 (-1 != neighborAPIndex)) ) 1739 { 1740 /* insert the AP to the list */ 1741 scanMngrInsertNewBSSToTrackingList( hScanMngr, frameInfo ); 1742 1743 /* if this is a neighbor AP */ 1744 if ( -1 != neighborAPIndex ) 1745 { 1746 /* mark in the neighbor AP list that it's being tracked */ 1747 pScanMngr->neighborAPsDiscoveryList[ frameInfo->band ].trackStatusList[ neighborAPIndex ] = SCAN_NDS_DISCOVERED; 1748 1749 /* if the discovery index for this neighbor AP band points to this AP, 1750 advance it and advance discovery part if needed */ 1751 if ( pScanMngr->neighborAPsDiscoveryIndex[ frameInfo->band ] == neighborAPIndex ) 1752 { 1753 do { 1754 pScanMngr->neighborAPsDiscoveryIndex[ frameInfo->band ]++; /* advance discovery index */ 1755 /* while discovery list is not exhausted and no AP for discovery is found */ 1756 } while ( (pScanMngr->neighborAPsDiscoveryIndex[ frameInfo->band ] < pScanMngr->neighborAPsDiscoveryList[ frameInfo->band ].numOfEntries) && 1757 (SCAN_NDS_NOT_DISCOVERED != pScanMngr->neighborAPsDiscoveryList[ frameInfo->band ].trackStatusList[ pScanMngr->neighborAPsDiscoveryIndex[ frameInfo->band ] ]) ); 1758 /* if discovery list isexhausted */ 1759 if ( pScanMngr->neighborAPsDiscoveryIndex[ frameInfo->band ] == pScanMngr->neighborAPsDiscoveryList[ frameInfo->band ].numOfEntries ) 1760 { 1761 /* restart discovery cycle for this band's neighbor APs */ 1762 pScanMngr->neighborAPsDiscoveryIndex[ frameInfo->band ] = 0; 1763 /* set new discovery part (if needed) */ 1764 scanMngrSetNextDiscoveryPart( hScanMngr ); 1765 } 1766 } 1767 } 1768 } 1769 #ifdef TI_DBG 1770 else 1771 { 1772 pScanMngr->stats.discardedFramesOther++; 1773 } 1774 #endif 1775 } 1776 } 1777 1778 /** 1779 * \author Ronen Kalish\n 1780 * \date 17-Mar-2005\n 1781 * \brief Cerate a new tracking entry and store the newly discovered AP info in it.\n 1782 * 1783 * Function Scope \e Private.\n 1784 * \param hScanMngr - handle to the scan manager object.\n 1785 * \param frameInfo - a pointer to the information received from this AP.\n 1786 */ 1787 void scanMngrInsertNewBSSToTrackingList( TI_HANDLE hScanMngr, scan_frameInfo_t* frameInfo ) 1788 { 1789 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1790 #ifdef SCAN_SPS_USE_DRIFT_COMPENSATION 1791 int i; 1792 #endif 1793 1794 /* mark that a new AP was discovered (for discovery stage) */ 1795 pScanMngr->bNewBSSFound = TRUE; 1796 1797 /* insert fields that are not update regulary */ 1798 pScanMngr->BSSList.BSSList[ pScanMngr->BSSList.numOfEntries ].bNeighborAP = 1799 ( -1 == scanMngrGetNeighborAPIndex( hScanMngr, frameInfo->band, frameInfo->bssId ) ? 1800 FALSE : 1801 TRUE ); 1802 os_memoryCopy( pScanMngr->hOS, 1803 (void *)&(pScanMngr->BSSList.BSSList[ pScanMngr->BSSList.numOfEntries ].BSSID.addr[ 0 ]), 1804 (void *)frameInfo->bssId, 1805 MAC_ADDR_LEN ); 1806 1807 /* initialize average RSSI value */ 1808 pScanMngr->BSSList.BSSList[ pScanMngr->BSSList.numOfEntries ].RSSI = frameInfo->rssi; 1809 pScanMngr->BSSList.BSSList[ pScanMngr->BSSList.numOfEntries ].lastRSSI = frameInfo->rssi; 1810 1811 #ifdef SCAN_SPS_USE_DRIFT_COMPENSATION 1812 /* initialize previous delta change array (used for SPS drift compensation) */ 1813 pScanMngr->BSSList.scanBSSList[ pScanMngr->BSSList.numOfEntries ].prevTSFDelta = 0; 1814 pScanMngr->BSSList.scanBSSList[ pScanMngr->BSSList.numOfEntries ].deltaChangeArrayIndex = 0; 1815 for ( i = 0; i < SCAN_SPS_NUM_OF_TSF_DELTA_ENTRIES; i++ ) 1816 { 1817 pScanMngr->BSSList.scanBSSList[ pScanMngr->BSSList.numOfEntries ].deltaChangeArray[ i ] = 0; 1818 } 1819 #endif 1820 1821 /* update regular fields */ 1822 pScanMngr->BSSList.scanBSSList[ pScanMngr->BSSList.numOfEntries ].trackFailCount = 0; /* for correct statistics update */ 1823 scanMngrUpdateBSSInfo( hScanMngr, pScanMngr->BSSList.numOfEntries, frameInfo ); 1824 1825 /* increase the number of tracked APs */ 1826 pScanMngr->BSSList.numOfEntries++; 1827 } 1828 1829 /** 1830 * \author Ronen Kalish\n 1831 * \date 17-Mar-2005\n 1832 * \brief Updates tracked AP information.\n 1833 * 1834 * Function Scope \e Private.\n 1835 * \param hScanMngr - handle to the scan manager object.\n 1836 * \param BSSListIndex - index to the BSS list where the AP information is stored.\n 1837 * \param frameInfo - a pointer to the information received from this AP.\n 1838 */ 1839 void scanMngrUpdateBSSInfo( TI_HANDLE hScanMngr, UINT8 BSSListIndex, scan_frameInfo_t* frameInfo ) 1840 { 1841 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1842 1843 /* update AP data */ 1844 pScanMngr->BSSList.BSSList[ BSSListIndex ].lastRxHostTimestamp = os_timeStampMs( pScanMngr->hOS ); 1845 pScanMngr->BSSList.BSSList[ BSSListIndex ].resultType = (frameInfo->parsedIEs->subType == BEACON) ? SCAN_RFT_BEACON : SCAN_RFT_PROBE_RESPONSE; 1846 pScanMngr->BSSList.BSSList[ BSSListIndex ].band = frameInfo->band; 1847 pScanMngr->BSSList.BSSList[ BSSListIndex ].channel = frameInfo->channel; 1848 /* if the received TSF (which is the lower 32 bits) is smaller than the lower 32 bits of the last beacon 1849 TSF, it means the higher 32 bits should be increased by 1 (TSF overflow to higher 32 bits occurred between 1850 last beacon of current AP and this frame). */ 1851 if ( INT64_LOWER( (pScanMngr->currentTSF) ) > frameInfo->staTSF ) 1852 { 1853 INT64_HIGHER( (pScanMngr->BSSList.scanBSSList[ BSSListIndex ].localTSF) ) = 1854 INT64_HIGHER( (pScanMngr->currentTSF) ) + 1; 1855 } 1856 else 1857 { 1858 INT64_HIGHER( (pScanMngr->BSSList.scanBSSList[ BSSListIndex ].localTSF) ) = 1859 INT64_HIGHER( (pScanMngr->currentTSF) ); 1860 } 1861 INT64_LOWER( (pScanMngr->BSSList.scanBSSList[ BSSListIndex ].localTSF) ) = frameInfo->staTSF; 1862 1863 if ( BEACON == frameInfo->parsedIEs->subType ) 1864 { 1865 os_memoryCopy( pScanMngr->hOS, &(pScanMngr->BSSList.BSSList[ BSSListIndex ].lastRxTSF), 1866 (void *)frameInfo->parsedIEs->content.iePacket.timestamp, TIME_STAMP_LEN ); 1867 pScanMngr->BSSList.BSSList[ BSSListIndex ].beaconInterval = 1868 frameInfo->parsedIEs->content.iePacket.beaconInerval; 1869 pScanMngr->BSSList.BSSList[ BSSListIndex ].capabilities = 1870 frameInfo->parsedIEs->content.iePacket.capabilities; 1871 } 1872 else 1873 { 1874 os_memoryCopy( pScanMngr->hOS, &(pScanMngr->BSSList.BSSList[ BSSListIndex ].lastRxTSF), 1875 (void *)frameInfo->parsedIEs->content.iePacket.timestamp, TIME_STAMP_LEN ); 1876 pScanMngr->BSSList.BSSList[ BSSListIndex ].beaconInterval = 1877 frameInfo->parsedIEs->content.iePacket.beaconInerval; 1878 pScanMngr->BSSList.BSSList[ BSSListIndex ].capabilities = 1879 frameInfo->parsedIEs->content.iePacket.capabilities; 1880 } 1881 #ifdef TI_DBG 1882 /* 1883 update track fail histogram: 1884 1. only done when tracking (to avoid updating due to "accidental re-discovery" 1885 2. only done for APs which have their track fail count larger than 0. The reason for that is because 1886 when tracking is started, the track fail count is increased, and thus if it is 0 tracking was not 1887 attempted for this AP, or more than one frame was received as a result of tracking operation for the AP. 1888 */ 1889 if ( ((SCAN_CSS_TRACKING_A_BAND == pScanMngr->contScanState) || 1890 (SCAN_CSS_TRACKING_G_BAND == pScanMngr->contScanState)) && 1891 (0 < pScanMngr->BSSList.scanBSSList[ BSSListIndex ].trackFailCount) ) 1892 { 1893 if ( SCAN_MNGR_STAT_MAX_TRACK_FAILURE <= 1894 pScanMngr->BSSList.scanBSSList[ BSSListIndex ].trackFailCount ) 1895 { 1896 pScanMngr->stats.ConsecutiveTrackFailCountHistogram[ SCAN_MNGR_STAT_MAX_TRACK_FAILURE - 1 ]++; 1897 } 1898 else 1899 { 1900 pScanMngr->stats.ConsecutiveTrackFailCountHistogram[ pScanMngr->BSSList.scanBSSList[ BSSListIndex ].trackFailCount - 1 ]++; 1901 } 1902 } 1903 #endif 1904 pScanMngr->BSSList.scanBSSList[ BSSListIndex ].trackFailCount = 0; 1905 1906 /* update RSSI value */ 1907 { 1908 INT8 rssiPrevVal = pScanMngr->BSSList.BSSList[ BSSListIndex ].RSSI; 1909 INT8 tmpRssiAvg = ((RSSI_PREVIOUS_COEFFICIENT * rssiPrevVal) + 1910 ((10-RSSI_PREVIOUS_COEFFICIENT) * frameInfo->rssi)) / 10; 1911 1912 pScanMngr->BSSList.BSSList[ BSSListIndex ].lastRSSI = frameInfo->rssi; 1913 1914 if (rssiPrevVal!=0) 1915 { 1916 /* for faster convergence on RSSI changes use rounding error calculation with latest sample and not 1917 on latest average */ 1918 if (frameInfo->rssi > tmpRssiAvg) 1919 tmpRssiAvg++; 1920 else 1921 if (frameInfo->rssi < tmpRssiAvg) 1922 tmpRssiAvg--; 1923 1924 pScanMngr->BSSList.BSSList[ BSSListIndex ].RSSI = tmpRssiAvg; 1925 } 1926 else 1927 { 1928 pScanMngr->BSSList.BSSList[ BSSListIndex ].RSSI = frameInfo->rssi; 1929 } 1930 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 1931 ("given RSSI=%d, AVRG RSSI=%d\n", 1932 frameInfo->rssi, 1933 pScanMngr->BSSList.BSSList[ BSSListIndex ].RSSI)); 1934 1935 } 1936 1937 pScanMngr->BSSList.BSSList[ BSSListIndex ].rxRate = frameInfo->rate; 1938 os_memoryCopy( pScanMngr->hOS, pScanMngr->BSSList.BSSList[ BSSListIndex ].pBuffer, 1939 frameInfo->buffer, frameInfo->bufferLength ); 1940 pScanMngr->BSSList.BSSList[ BSSListIndex ].bufferLength = frameInfo->bufferLength; 1941 } 1942 1943 /** 1944 * \author Ronen Kalish\n 1945 * \date 16-Mar-2005\n 1946 * \brief Search tracking list for an entry matching given BSSID.\n 1947 * 1948 * Function Scope \e Private.\n 1949 * \param hScanMngr - handle to the scan manager object.\n 1950 * \param bssId - the BSSID to search for.\n 1951 * \return entry index if found, -1 if no entry matching the BSSID was found.\n 1952 */ 1953 INT8 scanMngrGetTrackIndexByBssid( TI_HANDLE hScanMngr, macAddress_t* bssId ) 1954 { 1955 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1956 int i; 1957 1958 for ( i = 0; i < pScanMngr->BSSList.numOfEntries; i++ ) 1959 { 1960 if ( 0 == os_memoryCompare( pScanMngr->hOS, (UINT8*)bssId, 1961 (UINT8*)&(pScanMngr->BSSList.BSSList[ i ].BSSID) , MAC_ADDR_LEN ) ) 1962 { 1963 return i; 1964 } 1965 } 1966 return -1; 1967 } 1968 1969 /** 1970 * \author Ronen Kalish\n 1971 * \date 02-Mar-2005\n 1972 * \brief Search current policy for band policy 1973 * 1974 * Function Scope \e Private.\n 1975 * \param hScanMngr - handle to the scan manager object.\n 1976 * \param band - the band to find policy for.\n 1977 * \return the policy structure if found, NULL if no policy configured for this band.\n 1978 */ 1979 scan_bandPolicy_t* scanMngrGetPolicyByBand( TI_HANDLE hScanMngr, radioBand_e band ) 1980 { 1981 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 1982 int i; 1983 1984 /* loop on all configured policies, and look for the requested band */ 1985 for ( i = 0; i < pScanMngr->scanPolicy.numOfBands; i++ ) 1986 { 1987 if ( band == pScanMngr->scanPolicy.bandScanPolicy[ i ].band ) 1988 { 1989 return &(pScanMngr->scanPolicy.bandScanPolicy[ i ]); 1990 } 1991 } 1992 1993 /* if no policy was found, there's no policy configured for the requested band */ 1994 return NULL; 1995 } 1996 1997 /** 1998 * \author Ronen Kalish\n 1999 * \date 06-Mar-2005\n 2000 * \brief Sets the next discovery part according to current discovery part, policies and neighbor APs availability .\n 2001 * 2002 * Function Scope \e Private.\n 2003 * \param hScanMngr - handle to the scan manager object.\n 2004 */ 2005 void scanMngrSetNextDiscoveryPart( TI_HANDLE hScanMngr ) 2006 { 2007 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 2008 scan_discoveryPart_e nextDiscoveryPart, originalDiscoveryPart; 2009 2010 /* sanity check - if discovery part is not valid, restart from first discovery part */ 2011 if ( SCAN_SDP_NO_DISCOVERY <= pScanMngr->currentDiscoveryPart ) 2012 { 2013 pScanMngr->currentDiscoveryPart = SCAN_SDP_NEIGHBOR_G; 2014 } 2015 2016 /* if current discovery part is valid, do nothing */ 2017 if ( TRUE == scanMngrIsDiscoveryValid( hScanMngr, pScanMngr->currentDiscoveryPart ) ) 2018 { 2019 return; 2020 } 2021 2022 /* next discovery part is found according to current part, in the following order: 2023 Neighbor APs on G, Neighbor APs on A, Channel list on G, Channel list on A */ 2024 /* get next discovery part */ 2025 nextDiscoveryPart = pScanMngr->currentDiscoveryPart; 2026 originalDiscoveryPart = pScanMngr->currentDiscoveryPart; 2027 2028 do 2029 { 2030 nextDiscoveryPart++; 2031 /* loop back to first discovery part if discovery list end had been reached */ 2032 if ( SCAN_SDP_NO_DISCOVERY == nextDiscoveryPart ) 2033 { 2034 nextDiscoveryPart = SCAN_SDP_NEIGHBOR_G; 2035 } 2036 /* try next discovery part until first one is reached again or a valid part is found */ 2037 } while( (nextDiscoveryPart != originalDiscoveryPart) && 2038 (FALSE == scanMngrIsDiscoveryValid( hScanMngr, nextDiscoveryPart )) ); 2039 2040 /* if a discovery part for which discovery is valid was found, use it */ 2041 if ( TRUE == scanMngrIsDiscoveryValid( hScanMngr, nextDiscoveryPart ) ) 2042 { 2043 pScanMngr->currentDiscoveryPart = nextDiscoveryPart; 2044 } 2045 /* otherwise don't do discovery */ 2046 else 2047 { 2048 pScanMngr->currentDiscoveryPart = SCAN_SDP_NO_DISCOVERY; 2049 } 2050 } 2051 2052 /** 2053 * \author Ronen Kalish\n 2054 * \date 06-Mar-2005\n 2055 * \brief Checks whether discovery should be performed on the specified discovery part.\n 2056 * 2057 * Function Scope \e Private.\n 2058 * \param hScanMngr - handle to the scan manager object.\n 2059 * \param discoveryPart - the discovery part to check.\n 2060 */ 2061 BOOLEAN scanMngrIsDiscoveryValid( TI_HANDLE hScanMngr, scan_discoveryPart_e discoveryPart ) 2062 { 2063 scanMngr_t* pScanMngr = (TI_HANDLE)hScanMngr; 2064 scan_bandPolicy_t *gPolicy, *aPolicy; 2065 2066 gPolicy = scanMngrGetPolicyByBand( hScanMngr, RADIO_BAND_2_4_GHZ ); 2067 aPolicy = scanMngrGetPolicyByBand( hScanMngr, RADIO_BAND_5_0_GHZ ); 2068 2069 switch (discoveryPart) 2070 { 2071 case SCAN_SDP_NEIGHBOR_G: 2072 /* for discovery on G neighbor APs, a policy must be defined for G, discovery scan type should be present, 2073 number of neighbor APs on G should be greater than zero, and at least one AP should be yet undiscovered */ 2074 if ( (NULL != gPolicy) && 2075 (SCAN_TYPE_NO_SCAN != gPolicy->discoveryMethod.scanType) && 2076 (0 < pScanMngr->neighborAPsDiscoveryList[ RADIO_BAND_2_4_GHZ ].numOfEntries) && 2077 (TRUE == scanMngrNeighborAPsAvailableForDiscovery( hScanMngr, RADIO_BAND_2_4_GHZ )) ) 2078 { 2079 return TRUE; 2080 } 2081 else 2082 { 2083 return FALSE; 2084 } 2085 /* break; - unreachable */ 2086 2087 case SCAN_SDP_NEIGHBOR_A: 2088 /* for discovery on A neighbor APs, a policy must be defined for A, discovery scan type should be present, 2089 number of neighbor APs on A should be greater than zero, and at least one AP should be yet undiscovered */ 2090 if ( (NULL != aPolicy) && 2091 (SCAN_TYPE_NO_SCAN != aPolicy->discoveryMethod.scanType) && 2092 (0 < pScanMngr->neighborAPsDiscoveryList[ RADIO_BAND_5_0_GHZ ].numOfEntries) && 2093 (TRUE == scanMngrNeighborAPsAvailableForDiscovery( hScanMngr, RADIO_BAND_5_0_GHZ )) ) 2094 { 2095 return TRUE; 2096 } 2097 else 2098 { 2099 return FALSE; 2100 } 2101 /* break; - unreachable */ 2102 2103 case SCAN_SDP_CHANNEL_LIST_G: 2104 /* for discovery on G channel list, a policy must be defined for G, discovery scan type should be present, 2105 and number of channels in G channel list should be greater than zero */ 2106 if ( (NULL != gPolicy) && 2107 (SCAN_TYPE_NO_SCAN != gPolicy->discoveryMethod.scanType) && 2108 (0 < gPolicy->numOfChannles) ) 2109 { 2110 return TRUE; 2111 } 2112 else 2113 { 2114 return FALSE; 2115 } 2116 /* break; - unreachable */ 2117 2118 case SCAN_SDP_CHANNEL_LIST_A: 2119 /* for discovery on A channel list, a policy must be defined for A, discovery scan type should be present, 2120 and number of channels in A channel list should be greater than zero */ 2121 if ( (NULL != aPolicy) && 2122 (SCAN_TYPE_NO_SCAN != aPolicy->discoveryMethod.scanType) && 2123 (0 < aPolicy->numOfChannles) ) 2124 { 2125 return TRUE; 2126 } 2127 else 2128 { 2129 return FALSE; 2130 } 2131 /* break; - unreachable */ 2132 2133 default: 2134 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 2135 ("Checking whather discovery is valid for discovery part %d", discoveryPart) ); 2136 return FALSE; 2137 /* break; - unreachable */ 2138 } 2139 } 2140 2141 /** 2142 * \author Ronen Kalish\n 2143 * \date 07-Mar-2005\n 2144 * \brief Check whether there are neighbor APs to track on the given band.\n 2145 * 2146 * Function Scope \e Private.\n 2147 * \param hScanMngr - handle to the scan manager object.\n 2148 * \param bandPolicy - The scan policy for the requested band.\n 2149 * \param bNeighborAPsOnly - whether to scan for neighbor APs only or for all policy defined channels.\n 2150 */ 2151 BOOLEAN scanMngrNeighborAPsAvailableForDiscovery( TI_HANDLE hScanMngr, radioBand_e band ) 2152 { 2153 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 2154 int i; 2155 2156 2157 /* loop on all neighbor APs of the given band */ 2158 for ( i = 0; i < pScanMngr->neighborAPsDiscoveryList[ band ].numOfEntries; i++ ) 2159 { 2160 /* if a neighbor AP is not being tracked, meaning it yet has to be discovered, return TRUE */ 2161 if ( SCAN_NDS_NOT_DISCOVERED == pScanMngr->neighborAPsDiscoveryList[ band ].trackStatusList[ i ] ) 2162 { 2163 return TRUE; 2164 } 2165 } 2166 /* if all neighbor APs are being tracked (or no neighbor APs available) return FALSE */ 2167 return FALSE; 2168 } 2169 2170 /** 2171 * \author Ronen Kalish\n 2172 * \date 02-Mar-2005\n 2173 * \brief Builds a scan command on the object workspace for immediate scan.\n 2174 * 2175 * Function Scope \e Private.\n 2176 * \param hScanMngr - handle to the scan manager object.\n 2177 * \param bandPolicy - The scan policy for the requested band.\n 2178 * \param bNeighborAPsOnly - whether to scan for neighbor APs only or for all policy defined channels.\n 2179 */ 2180 void scanMngrBuildImmediateScanCommand( TI_HANDLE hScanMngr, scan_bandPolicy_t* bandPolicy, BOOLEAN bNeighborAPsOnly ) 2181 { 2182 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 2183 int channelIndex; 2184 paramInfo_t param; 2185 macAddress_t broadcastAddress; 2186 int i; 2187 2188 /* first, build the command header */ 2189 scanMngrBuildScanCommandHeader( hScanMngr, &(bandPolicy->immediateScanMethod), bandPolicy->band ); 2190 2191 /* if requested to scan on neighbor APs only */ 2192 if ( TRUE == bNeighborAPsOnly ) 2193 { 2194 /* loop on all neighbor APs */ 2195 channelIndex = 0; 2196 while ( (channelIndex < pScanMngr->neighborAPsDiscoveryList[ bandPolicy->band ].numOfEntries) && 2197 (pScanMngr->scanParams.numOfChannels < SCAN_MAX_NUM_OF_NORMAL_CHANNELS_PER_COMMAND) ) 2198 { 2199 /* verify channel with reg domain */ 2200 param.paramType = REGULATORY_DOMAIN_GET_SCAN_CAPABILITIES; 2201 param.content.channelCapabilityReq.band = bandPolicy->band; 2202 if ( (bandPolicy->immediateScanMethod.scanType == SCAN_TYPE_NORMAL_PASSIVE) || 2203 (bandPolicy->immediateScanMethod.scanType == SCAN_TYPE_TRIGGERED_PASSIVE) || 2204 (bandPolicy->immediateScanMethod.scanType == SCAN_TYPE_SPS) ) 2205 { 2206 param.content.channelCapabilityReq.scanOption = PASSIVE_SCANNING; 2207 } 2208 else 2209 { 2210 param.content.channelCapabilityReq.scanOption = ACTIVE_SCANNING; 2211 } 2212 param.content.channelCapabilityReq.channelNum = 2213 pScanMngr->neighborAPsDiscoveryList[ bandPolicy->band ].APListPtr[ channelIndex ].channel; 2214 regulatoryDomain_getParam( pScanMngr->hRegulatoryDomain, ¶m ); 2215 2216 /* if the channel is allowed, insert it to the scan command */ 2217 if (param.content.channelCapabilityRet.channelValidity) 2218 { 2219 scanMngrAddNormalChannel( hScanMngr, &(bandPolicy->immediateScanMethod), 2220 pScanMngr->neighborAPsDiscoveryList[ bandPolicy->band ].APListPtr[ channelIndex ].channel, 2221 &(pScanMngr->neighborAPsDiscoveryList[ bandPolicy->band ].APListPtr[ channelIndex ].BSSID), 2222 param.content.channelCapabilityRet.maxTxPowerDbm ); 2223 } 2224 channelIndex++; 2225 } 2226 } 2227 else 2228 /* scan on all policy defined channels */ 2229 { 2230 /* set the broadcast address */ 2231 for ( i = 0; i < MAC_ADDR_LEN; i++ ) 2232 { 2233 broadcastAddress.addr[ i ] = 0xff; 2234 } 2235 2236 /* loop on all channels in the policy */ 2237 channelIndex = 0; 2238 while ( (channelIndex < bandPolicy->numOfChannles) && 2239 (pScanMngr->scanParams.numOfChannels < SCAN_MAX_NUM_OF_NORMAL_CHANNELS_PER_COMMAND) ) 2240 { 2241 /* verify channel with reg domain */ 2242 param.paramType = REGULATORY_DOMAIN_GET_SCAN_CAPABILITIES; 2243 param.content.channelCapabilityReq.band = bandPolicy->band; 2244 if ( (bandPolicy->immediateScanMethod.scanType == SCAN_TYPE_NORMAL_PASSIVE) || 2245 (bandPolicy->immediateScanMethod.scanType == SCAN_TYPE_TRIGGERED_PASSIVE) || 2246 (bandPolicy->immediateScanMethod.scanType == SCAN_TYPE_SPS) ) 2247 { 2248 param.content.channelCapabilityReq.scanOption = PASSIVE_SCANNING; 2249 } 2250 else 2251 { 2252 param.content.channelCapabilityReq.scanOption = ACTIVE_SCANNING; 2253 } 2254 param.content.channelCapabilityReq.channelNum = bandPolicy->channelList[ channelIndex ]; 2255 regulatoryDomain_getParam( pScanMngr->hRegulatoryDomain, ¶m ); 2256 2257 /* if the channel is allowed, insert it to the scan command */ 2258 if (param.content.channelCapabilityRet.channelValidity) 2259 { 2260 scanMngrAddNormalChannel( hScanMngr, &(bandPolicy->immediateScanMethod), 2261 bandPolicy->channelList[ channelIndex ], 2262 &broadcastAddress, 2263 param.content.channelCapabilityRet.maxTxPowerDbm ); 2264 } 2265 channelIndex++; 2266 } 2267 } 2268 } 2269 2270 /** 2271 * \author Ronen Kalish\n 2272 * \date 03-Mar-2005\n 2273 * \brief Builds a scan command on the object workspace for tracking.\n 2274 * 2275 * Function Scope \e Private.\n 2276 * \param hScanMngr - handle to the scan manager object.\n 2277 * \param bandPolicy - The scan policy for the band to track on.\n 2278 * \param band - the band to scan.\n 2279 */ 2280 void scanMngrBuildTrackScanCommand( TI_HANDLE hScanMngr, scan_bandPolicy_t* bandPolicy, radioBand_e band ) 2281 { 2282 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 2283 int BSSListIndex; 2284 paramInfo_t param; 2285 scan_Method_t* scanMethod; 2286 2287 WLAN_REPORT_INFORMATION(pScanMngr->hReport , SCAN_MNGR_MODULE_LOG , ("\n scanMngrBuildTrackScanCommand \n" )) ; 2288 2289 2290 /* SPS is performed differently from all other scan types, and only if TSF error has not occured */ 2291 if ( (SCAN_TYPE_SPS == bandPolicy->trackingMethod.scanType) && (TRUE == pScanMngr->bSynchronized) ) 2292 { 2293 /* build the command header */ 2294 WLAN_REPORT_INFORMATION(pScanMngr->hReport , SCAN_MNGR_MODULE_LOG ,("\nSPS invoked\n") ); 2295 scanMngrBuildScanCommandHeader( hScanMngr, &(bandPolicy->trackingMethod), band ); 2296 2297 /* build the channel list */ 2298 scanMngrAddSPSChannels( hScanMngr, &(bandPolicy->trackingMethod), band ); 2299 return; 2300 } 2301 2302 /* the scan method to use is the method defined for tracking, unless this is SPS and TSF error occurred, 2303 in which case we use the discovery method this time. */ 2304 if ( (SCAN_TYPE_SPS == bandPolicy->trackingMethod.scanType) && (FALSE == pScanMngr->bSynchronized) ) 2305 { 2306 /* use discovery scan method */ 2307 scanMethod = &(bandPolicy->discoveryMethod); 2308 } 2309 else 2310 { 2311 /* use tracking method */ 2312 scanMethod = &(bandPolicy->trackingMethod); 2313 } 2314 2315 /* build the command header */ 2316 scanMngrBuildScanCommandHeader( hScanMngr, scanMethod, band ); 2317 2318 /* insert channels from tracking list according to requested band */ 2319 BSSListIndex = 0; 2320 while ( (BSSListIndex < pScanMngr->BSSList.numOfEntries) && 2321 (pScanMngr->scanParams.numOfChannels < SCAN_MAX_NUM_OF_NORMAL_CHANNELS_PER_COMMAND) ) 2322 { 2323 /* if BSS is on the right band */ 2324 if ( band == pScanMngr->BSSList.BSSList[ BSSListIndex ].band ) 2325 { 2326 /* verify the channel with the reg domain */ 2327 param.paramType = REGULATORY_DOMAIN_GET_SCAN_CAPABILITIES; 2328 param.content.channelCapabilityReq.band = band; 2329 if ( (scanMethod->scanType == SCAN_TYPE_NORMAL_PASSIVE) || 2330 (scanMethod->scanType == SCAN_TYPE_TRIGGERED_PASSIVE) ) 2331 { 2332 param.content.channelCapabilityReq.scanOption = PASSIVE_SCANNING; 2333 } 2334 else 2335 { 2336 param.content.channelCapabilityReq.scanOption = ACTIVE_SCANNING; 2337 } 2338 param.content.channelCapabilityReq.channelNum = pScanMngr->BSSList.BSSList[ BSSListIndex ].channel; 2339 regulatoryDomain_getParam( pScanMngr->hRegulatoryDomain, ¶m ); 2340 2341 /* if channel is verified for requested scan type */ 2342 if ( param.content.channelCapabilityRet.channelValidity ) 2343 { 2344 scanMngrAddNormalChannel( hScanMngr, scanMethod, 2345 pScanMngr->BSSList.BSSList[ BSSListIndex ].channel, 2346 &(pScanMngr->BSSList.BSSList[ BSSListIndex ].BSSID), 2347 param.content.channelCapabilityRet.maxTxPowerDbm ); 2348 2349 /* increase AP track attempts counter */ 2350 if ( (SCAN_TYPE_SPS == bandPolicy->trackingMethod.scanType) && (FALSE == pScanMngr->bSynchronized) ) 2351 { 2352 pScanMngr->BSSList.scanBSSList[ BSSListIndex ].trackFailCount = 2353 pScanMngr->scanPolicy.maxTrackFailures + 1; 2354 } 2355 else 2356 { 2357 pScanMngr->BSSList.scanBSSList[ BSSListIndex ].trackFailCount++; 2358 } 2359 } 2360 /* if channel is not verified, there are two options: 2361 1. we are using the tracking method, and thus the AP should be removed (because we are unable 2362 to track it) 2363 2. we are using the discovery method (because a TSF error occurred and tracking method is SPS). 2364 In this case, it seems we do not have to remove the AP (because the channel may not be valid 2365 for active scan but it is valid for passive scan), but since we had a TSF error the AP would 2366 be removed anyhow if not re-discovered now, so no harm done in removing it as well. */ 2367 else 2368 { 2369 /* removing an AP is done by increasing its track failure counter to maximum. Since it is 2370 not tracked, it would not be found, and thus would be removed by aging process performed 2371 at scan completion */ 2372 pScanMngr->BSSList.scanBSSList[ BSSListIndex ].trackFailCount = 2373 pScanMngr->scanPolicy.maxTrackFailures + 1; 2374 #ifdef TI_DBG 2375 /* update statistics */ 2376 pScanMngr->stats.APsRemovedInvalidChannel++; 2377 #endif 2378 } 2379 } 2380 BSSListIndex++; 2381 } 2382 } 2383 2384 /** 2385 * \author Ronen Kalish\n 2386 * \date 03-Mar-2005\n 2387 * \brief Builds a scan command on the object workspace for discovery.\n 2388 * 2389 * Function Scope \e Private.\n 2390 * \param hScanMngr - handle to the scan manager object.\n 2391 */ 2392 void scanMngrBuildDiscoveryScanCommand( TI_HANDLE hScanMngr ) 2393 { 2394 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 2395 radioBand_e band; 2396 scan_bandPolicy_t* bandPolicy; 2397 2398 /* find on which band to discover at current cycle */ 2399 if ( (SCAN_SDP_NEIGHBOR_G == pScanMngr->currentDiscoveryPart) || 2400 (SCAN_SDP_CHANNEL_LIST_G == pScanMngr->currentDiscoveryPart) ) 2401 { 2402 band = RADIO_BAND_2_4_GHZ; 2403 bandPolicy = scanMngrGetPolicyByBand( hScanMngr, band ); 2404 } 2405 else 2406 { 2407 band = RADIO_BAND_5_0_GHZ; 2408 bandPolicy = scanMngrGetPolicyByBand( hScanMngr, band ); 2409 } 2410 2411 /* first, build the command header */ 2412 scanMngrBuildScanCommandHeader( hScanMngr, &(bandPolicy->discoveryMethod), band ); 2413 2414 /* channels are added according to current discovery part */ 2415 switch ( pScanMngr->currentDiscoveryPart ) 2416 { 2417 case SCAN_SDP_NEIGHBOR_G: 2418 /* add channels from neighbor AP discovery list */ 2419 scanMngrAddNeighborAPsForDiscovery( hScanMngr, bandPolicy ); 2420 2421 /* if neighbor AP list is exhausted, proceed to next discovery part */ 2422 if ( 0 == pScanMngr->neighborAPsDiscoveryIndex[ band ] ) 2423 { 2424 pScanMngr->currentDiscoveryPart++; 2425 scanMngrSetNextDiscoveryPart( hScanMngr ); 2426 } 2427 2428 /* if need to discover more APs, (not enough neighbor APs), proceed to G channel list */ 2429 if ( pScanMngr->scanParams.numOfChannels < bandPolicy->numOfChannlesForDiscovery ) 2430 { 2431 scanMngrAddChannelListForDiscovery( hScanMngr, bandPolicy ); 2432 } 2433 2434 #ifdef TI_DBG 2435 pScanMngr->statsLastDiscoveryBand = RADIO_BAND_2_4_GHZ; 2436 #endif 2437 break; 2438 2439 case SCAN_SDP_NEIGHBOR_A: 2440 /* add channels from neighbor AP discovery list */ 2441 scanMngrAddNeighborAPsForDiscovery( hScanMngr, bandPolicy ); 2442 2443 /* if neighbor AP list is exhausted, proceed to next discovery part */ 2444 if ( 0 == pScanMngr->neighborAPsDiscoveryIndex[ band ] ) 2445 { 2446 pScanMngr->currentDiscoveryPart++; 2447 scanMngrSetNextDiscoveryPart( hScanMngr ); 2448 } 2449 2450 /* if need to discover more APs, (not enough neighbor APs), proceed to A channel list */ 2451 if ( pScanMngr->scanParams.numOfChannels < bandPolicy->numOfChannlesForDiscovery ) 2452 { 2453 scanMngrAddChannelListForDiscovery( hScanMngr, bandPolicy ); 2454 } 2455 2456 #ifdef TI_DBG 2457 pScanMngr->statsLastDiscoveryBand = RADIO_BAND_5_0_GHZ; 2458 #endif 2459 break; 2460 2461 case SCAN_SDP_CHANNEL_LIST_G: 2462 /* add channels from policy channel list */ 2463 scanMngrAddChannelListForDiscovery( hScanMngr, bandPolicy ); 2464 2465 /* if channel list is exhausted, proceed to next discovery part */ 2466 if ( 0 == pScanMngr->channelDiscoveryIndex[ band ] ) 2467 { 2468 pScanMngr->currentDiscoveryPart++; 2469 scanMngrSetNextDiscoveryPart( hScanMngr ); 2470 } 2471 2472 /* if need to discover more APs (not enough channels on channel list), proceed to G neighbor APs */ 2473 if ( pScanMngr->scanParams.numOfChannels < bandPolicy->numOfChannlesForDiscovery ) 2474 { 2475 scanMngrAddNeighborAPsForDiscovery( hScanMngr, bandPolicy ); 2476 } 2477 2478 #ifdef TI_DBG 2479 pScanMngr->statsLastDiscoveryBand = RADIO_BAND_2_4_GHZ; 2480 #endif 2481 break; 2482 2483 case SCAN_SDP_CHANNEL_LIST_A: 2484 /* add channels from policy channel list */ 2485 scanMngrAddChannelListForDiscovery( hScanMngr, bandPolicy ); 2486 2487 /* if channel list is exhausted, proceed to next discovery part */ 2488 if ( 0 == pScanMngr->channelDiscoveryIndex[ band ] ) 2489 { 2490 pScanMngr->currentDiscoveryPart++; 2491 scanMngrSetNextDiscoveryPart( hScanMngr ); 2492 } 2493 2494 /* if need to discover more APs (not enough channels on channel list), proceed to A neighbor APs */ 2495 if ( pScanMngr->scanParams.numOfChannels < bandPolicy->numOfChannlesForDiscovery ) 2496 { 2497 scanMngrAddNeighborAPsForDiscovery( hScanMngr, bandPolicy ); 2498 } 2499 #ifdef TI_DBG 2500 pScanMngr->statsLastDiscoveryBand = RADIO_BAND_5_0_GHZ; 2501 #endif 2502 break; 2503 2504 case SCAN_SDP_NO_DISCOVERY: 2505 default: 2506 WLAN_REPORT_ERROR( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 2507 ("scanMngrBuildDiscoveryScanCommand called and current discovery part is %d", 2508 pScanMngr->currentDiscoveryPart) ); 2509 break; 2510 } 2511 } 2512 2513 /** 2514 * \author Ronen Kalish\n 2515 * \date 02-Mar-2005\n 2516 * \brief Builds the scan command header on the object workspace.\n 2517 * 2518 * Function Scope \e Private.\n 2519 * \param hScanMngr - handle to the scan manager object.\n 2520 * \param scanMethod - The scan method (and parameters) to use.\n 2521 * \param band - the band to scan.\n 2522 */ 2523 void scanMngrBuildScanCommandHeader( TI_HANDLE hScanMngr, scan_Method_t* scanMethod, radioBand_e band ) 2524 { 2525 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 2526 2527 2528 /* set general scan parameters */ 2529 /* SSID is not set - scan concentrator will set it for the scan manager to current SSID */ 2530 pScanMngr->scanParams.scanType = scanMethod->scanType; 2531 pScanMngr->scanParams.band = band; 2532 2533 switch (scanMethod->scanType) 2534 { 2535 case SCAN_TYPE_NORMAL_ACTIVE: 2536 /* In active scan, the desired SSID is set by the scan concentrator to the current SSID. 2537 Stting anything not zero triggers this in the scan concentrator */ 2538 pScanMngr->scanParams.desiredSsid.len = 1; 2539 pScanMngr->scanParams.probeReqNumber = scanMethod->method.basicMethodParams.probReqParams.numOfProbeReqs; 2540 pScanMngr->scanParams.probeRequestRate = scanMethod->method.basicMethodParams.probReqParams.bitrate; 2541 break; 2542 2543 case SCAN_TYPE_TRIGGERED_ACTIVE: 2544 /* In active scan, the desired SSID is set by the scan concentrator to the current SSID. 2545 Stting anything not zero triggers this in the scan concentrator */ 2546 pScanMngr->scanParams.desiredSsid.len = 1; 2547 pScanMngr->scanParams.probeReqNumber = scanMethod->method.TidTriggerdMethodParams.basicMethodParams.probReqParams.numOfProbeReqs; 2548 pScanMngr->scanParams.probeRequestRate = scanMethod->method.TidTriggerdMethodParams.basicMethodParams.probReqParams.bitrate; 2549 pScanMngr->scanParams.Tid = scanMethod->method.TidTriggerdMethodParams.triggeringTid; 2550 break; 2551 2552 case SCAN_TYPE_TRIGGERED_PASSIVE: 2553 pScanMngr->scanParams.Tid = scanMethod->method.TidTriggerdMethodParams.triggeringTid; 2554 /* In Passive scan, Desired SSID length is set to 0 so that the Scan concentrator won't replace 2555 it with the current SSID (to be able to receive beacons from AP's with multiple or hidden 2556 SSID) */ 2557 pScanMngr->scanParams.desiredSsid.len = 0; 2558 break; 2559 2560 case SCAN_TYPE_NORMAL_PASSIVE: 2561 /* In Passive scan, Desired SSID length is set to 0 so that the Scan concentrator won't replace 2562 it with the current SSID (to be able to receive beacons from AP's with multiple or hidden 2563 SSID) */ 2564 pScanMngr->scanParams.desiredSsid.len = 0; 2565 break; 2566 2567 case SCAN_TYPE_SPS: 2568 /* SPS doesn't have SSID filter, it only uses BSSID filter */ 2569 break; 2570 2571 default: 2572 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 2573 ("Unrecognized scan type %d when building scan command", scanMethod->scanType) ); 2574 break; 2575 } 2576 2577 /* set 0 channels - actual channel will be added by caller */ 2578 pScanMngr->scanParams.numOfChannels = 0; 2579 } 2580 2581 /** 2582 * \author Ronen Kalish\n 2583 * \date 06-Mar-2005\n 2584 * \brief Add neighbor APs to scan command on the object workspace for discovery scan.\n 2585 * 2586 * Function Scope \e Private.\n 2587 * \param hScanMngr - handle to the scan manager object.\n 2588 * \param bandPolicy - the scan policy for the band to use.\n 2589 */ 2590 void scanMngrAddNeighborAPsForDiscovery( TI_HANDLE hScanMngr, scan_bandPolicy_t* bandPolicy ) 2591 { 2592 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 2593 int neighborAPIndex = pScanMngr->neighborAPsDiscoveryIndex[ bandPolicy->band ]; 2594 paramInfo_t param; 2595 2596 /* loop while neighbor AP list has not been exhausted, command is not full and not enough APs for discovery had been found */ 2597 while ( (pScanMngr->scanParams.numOfChannels < bandPolicy->numOfChannlesForDiscovery) && 2598 (pScanMngr->scanParams.numOfChannels < SCAN_MAX_NUM_OF_NORMAL_CHANNELS_PER_COMMAND) && 2599 (neighborAPIndex < pScanMngr->neighborAPsDiscoveryList[ bandPolicy->band ].numOfEntries) ) 2600 { 2601 /* if the AP is not being tracked */ 2602 if ( SCAN_NDS_NOT_DISCOVERED == 2603 pScanMngr->neighborAPsDiscoveryList[ bandPolicy->band ].trackStatusList[ neighborAPIndex ] ) 2604 { 2605 /* verify channel with reg domain */ 2606 param.paramType = REGULATORY_DOMAIN_GET_SCAN_CAPABILITIES; 2607 param.content.channelCapabilityReq.band = bandPolicy->band; 2608 if ( (bandPolicy->discoveryMethod.scanType == SCAN_TYPE_NORMAL_PASSIVE) || 2609 (bandPolicy->discoveryMethod.scanType == SCAN_TYPE_TRIGGERED_PASSIVE) || 2610 (bandPolicy->discoveryMethod.scanType == SCAN_TYPE_SPS) ) 2611 { 2612 param.content.channelCapabilityReq.scanOption = PASSIVE_SCANNING; 2613 } 2614 else 2615 { 2616 param.content.channelCapabilityReq.scanOption = ACTIVE_SCANNING; 2617 } 2618 param.content.channelCapabilityReq.channelNum = 2619 pScanMngr->neighborAPsDiscoveryList[ bandPolicy->band ].APListPtr[ neighborAPIndex ].channel; 2620 regulatoryDomain_getParam( pScanMngr->hRegulatoryDomain, ¶m ); 2621 2622 /* if the channel is allowed, insert it to the scan command */ 2623 if (param.content.channelCapabilityRet.channelValidity) 2624 { 2625 scanMngrAddNormalChannel( hScanMngr, &(bandPolicy->discoveryMethod), 2626 pScanMngr->neighborAPsDiscoveryList[ bandPolicy->band ].APListPtr[ neighborAPIndex ].channel, 2627 &(pScanMngr->neighborAPsDiscoveryList[ bandPolicy->band ].APListPtr[ neighborAPIndex ].BSSID), 2628 param.content.channelCapabilityRet.maxTxPowerDbm ); 2629 } 2630 } 2631 neighborAPIndex++; 2632 } 2633 2634 /* if neighbor AP list has been exhuasted */ 2635 if ( neighborAPIndex == pScanMngr->neighborAPsDiscoveryList[ bandPolicy->band ].numOfEntries ) 2636 { 2637 /* reset discovery index */ 2638 pScanMngr->neighborAPsDiscoveryIndex[ bandPolicy->band ] = 0; 2639 } 2640 else 2641 { 2642 /* just update neighbor APs discovery index */ 2643 pScanMngr->neighborAPsDiscoveryIndex[ bandPolicy->band ] = neighborAPIndex; 2644 } 2645 } 2646 2647 /** 2648 * \author Ronen Kalish\n 2649 * \date 06-Mar-2005\n 2650 * \brief Add channel from policy channels list to scan command on the object workspace for discovery scan.\n 2651 * 2652 * Function Scope \e Private.\n 2653 * \param hScanMngr - handle to the scan manager object.\n 2654 * \param bandPolicy - the scan policy for the band to use.\n 2655 */ 2656 void scanMngrAddChannelListForDiscovery( TI_HANDLE hScanMngr, scan_bandPolicy_t* bandPolicy ) 2657 { 2658 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 2659 paramInfo_t param; 2660 macAddress_t broadcastAddress; 2661 int i, channelListIndex = pScanMngr->channelDiscoveryIndex[ bandPolicy->band ]; 2662 2663 2664 /* set broadcast MAC address */ 2665 for ( i = 0; i < MAC_ADDR_LEN; i++ ) 2666 { 2667 broadcastAddress.addr[ i ] = 0xff; 2668 } 2669 2670 /* loop while channel list has not been exhausted, command is not full, and not enough APs for discovery had been found */ 2671 while ( (pScanMngr->scanParams.numOfChannels < bandPolicy->numOfChannlesForDiscovery) && 2672 (pScanMngr->scanParams.numOfChannels < SCAN_MAX_NUM_OF_NORMAL_CHANNELS_PER_COMMAND) && 2673 (channelListIndex < bandPolicy->numOfChannles) ) 2674 { 2675 /* verify channel with reg domain */ 2676 param.paramType = REGULATORY_DOMAIN_GET_SCAN_CAPABILITIES; 2677 param.content.channelCapabilityReq.band = bandPolicy->band; 2678 if ( (bandPolicy->discoveryMethod.scanType == SCAN_TYPE_NORMAL_PASSIVE) || 2679 (bandPolicy->discoveryMethod.scanType == SCAN_TYPE_TRIGGERED_PASSIVE) || 2680 (bandPolicy->discoveryMethod.scanType == SCAN_TYPE_SPS) ) 2681 { 2682 param.content.channelCapabilityReq.scanOption = PASSIVE_SCANNING; 2683 } 2684 else 2685 { 2686 param.content.channelCapabilityReq.scanOption = ACTIVE_SCANNING; 2687 } 2688 param.content.channelCapabilityReq.channelNum = 2689 bandPolicy->channelList[ channelListIndex ]; 2690 regulatoryDomain_getParam( pScanMngr->hRegulatoryDomain, ¶m ); 2691 2692 /* if the channel is allowed, insert it to the scan command */ 2693 if (param.content.channelCapabilityRet.channelValidity) 2694 { 2695 scanMngrAddNormalChannel( hScanMngr, &(bandPolicy->discoveryMethod), 2696 bandPolicy->channelList[ channelListIndex ], 2697 &broadcastAddress, 2698 param.content.channelCapabilityRet.maxTxPowerDbm ); 2699 } 2700 channelListIndex++; 2701 } 2702 2703 /* if channel discovery list has been exhuasted */ 2704 if ( channelListIndex == bandPolicy->numOfChannles ) 2705 { 2706 /* reset discovery index */ 2707 pScanMngr->channelDiscoveryIndex[ bandPolicy->band ] = 0; 2708 } 2709 else 2710 { 2711 /* just update channel list discovery index */ 2712 pScanMngr->channelDiscoveryIndex[ bandPolicy->band ] = channelListIndex; 2713 } 2714 } 2715 2716 /** 2717 * \author Ronen Kalish\n 2718 * \date 02-Mar-2005\n 2719 * \brief Add SPS channels to scan command on the object workspace.\n 2720 * 2721 * Function Scope \e Private.\n 2722 * \param hScanMngr - handle to the scan manager object.\n 2723 * \param scanMethod - The scan method (and parameters) to use.\n 2724 * \param band - the band to scan.\n 2725 */ 2726 void scanMngrAddSPSChannels( TI_HANDLE hScanMngr, scan_Method_t* scanMethod, radioBand_e band ) 2727 { 2728 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 2729 UINT64 EarliestTSFToInsert; 2730 UINT32 timeToStartInAdvance = scanMethod->method.spsMethodParams.scanDuration / 2731 SCAN_SPS_DURATION_PART_IN_ADVANCE; 2732 scan_SPSHelper_t nextEventArray[ MAX_SIZE_OF_BSS_TRACK_LIST ]; 2733 int BSSListIndex, i, j, nextEventArrayHead, nextEventArraySize; 2734 paramInfo_t param; 2735 #ifdef SCAN_MNGR_SPS_DBG 2736 UINT32 highValue, lowValue, maxNextEventArraySize; 2737 #endif 2738 2739 WLAN_REPORT_INFORMATION(pScanMngr->hReport , SCAN_MNGR_MODULE_LOG ,("\nscanMngrAddSPSChannels invoked for band %d\n",band) ); 2740 /* initialize latest TSF value */ 2741 pScanMngr->scanParams.latestTSFValue = 0; 2742 2743 /* initialize the next event arry */ 2744 nextEventArrayHead = -1; 2745 nextEventArraySize = 0; 2746 2747 #ifdef SCAN_MNGR_SPS_DBG 2748 highValue = INT64_HIGHER( pScanMngr->currentTSF ); 2749 lowValue = INT64_LOWER( pScanMngr->currentTSF ); 2750 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 2751 ("current TSF: %u-%u\n", highValue, lowValue) ); 2752 #endif 2753 2754 /* insert channels from tracking list to next event array according to requested band */ 2755 for ( BSSListIndex = 0; BSSListIndex < pScanMngr->BSSList.numOfEntries; BSSListIndex++ ) 2756 { 2757 /* if BSS is on the right band */ 2758 if ( band == pScanMngr->BSSList.BSSList[ BSSListIndex ].band ) 2759 { 2760 /* verify the channel with the reg domain */ 2761 param.paramType = REGULATORY_DOMAIN_GET_SCAN_CAPABILITIES; 2762 param.content.channelCapabilityReq.band = band; 2763 param.content.channelCapabilityReq.scanOption = PASSIVE_SCANNING; 2764 param.content.channelCapabilityReq.channelNum = pScanMngr->BSSList.BSSList[ BSSListIndex ].channel; 2765 regulatoryDomain_getParam( pScanMngr->hRegulatoryDomain, ¶m ); 2766 2767 /* if channel is verified for requested scan type */ 2768 if ( param.content.channelCapabilityRet.channelValidity ) 2769 { 2770 /* if this AP local TSF value is greater that latest TSF value, change it */ 2771 if ( pScanMngr->BSSList.scanBSSList[ BSSListIndex ].localTSF > pScanMngr->scanParams.latestTSFValue ) 2772 { 2773 /* the latest TSF value is used by the FW to detect TSF error (an AP recovery). When a TSF 2774 error occurs, the latest TSF value should be in the future (because the AP TSF was 2775 reset). */ 2776 pScanMngr->scanParams.latestTSFValue = pScanMngr->BSSList.scanBSSList[ BSSListIndex ].localTSF; 2777 } 2778 2779 /* calculate the TSF of the next event for tracked AP. Scan should start 2780 SCAN_SPS_DURATION_PART_IN_ADVANCE before the calculated event */ 2781 nextEventArray[ nextEventArraySize ].nextEventTSF = 2782 scanMngrCalculateNextEventTSF( hScanMngr, &(pScanMngr->BSSList), BSSListIndex, 2783 pScanMngr->currentTSF + SCAN_SPS_GUARD_FROM_CURRENT_TSF + 2784 timeToStartInAdvance ) - timeToStartInAdvance; 2785 #ifdef SCAN_MNGR_SPS_DBG 2786 highValue = INT64_HIGHER( nextEventArray[ nextEventArraySize ].nextEventTSF ); 2787 lowValue = INT64_LOWER( nextEventArray[ nextEventArraySize ].nextEventTSF ); 2788 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 2789 ("BSSID:%02x:%02x:%02x:%02x:%02x:%02x will send frame at TSF:%x-%x\n", 2790 pScanMngr->BSSList.BSSList[ BSSListIndex ].BSSID.addr[ 0 ], 2791 pScanMngr->BSSList.BSSList[ BSSListIndex ].BSSID.addr[ 1 ], 2792 pScanMngr->BSSList.BSSList[ BSSListIndex ].BSSID.addr[ 2 ], 2793 pScanMngr->BSSList.BSSList[ BSSListIndex ].BSSID.addr[ 3 ], 2794 pScanMngr->BSSList.BSSList[ BSSListIndex ].BSSID.addr[ 4 ], 2795 pScanMngr->BSSList.BSSList[ BSSListIndex ].BSSID.addr[ 5 ], 2796 highValue, lowValue) ); 2797 #endif 2798 nextEventArray[ nextEventArraySize ].trackListIndex = BSSListIndex; 2799 2800 /* insert it, sorted, to the next event array */ 2801 /* if need to insert as head (either because list is empty or because it has earliest TSF) */ 2802 if ( (-1 == nextEventArrayHead) || 2803 (nextEventArray[ nextEventArraySize ].nextEventTSF < nextEventArray[ nextEventArrayHead ].nextEventTSF) ) 2804 { 2805 /* link the newly inserted AP to the current head */ 2806 nextEventArray[ nextEventArraySize ].nextAPIndex = nextEventArrayHead; 2807 /* make current head point to newly inserted AP */ 2808 nextEventArrayHead = nextEventArraySize; 2809 nextEventArraySize++; 2810 } 2811 /* insert into the list */ 2812 else 2813 { 2814 /* start with list head */ 2815 i = nextEventArrayHead; 2816 /* while the new AP TSF is larger and list end had not been reached */ 2817 while ( (nextEventArray[ i ].nextAPIndex != -1) && /* list end had not been reached */ 2818 (nextEventArray[ nextEventArray[ i ].nextAPIndex ].nextEventTSF < nextEventArray[ nextEventArraySize ].nextEventTSF) ) /* next event TSF of the next AP in the list is smaller than that of the AP being inserted */ 2819 { 2820 /* proceed to the next AP */ 2821 i = nextEventArray[ i ].nextAPIndex; 2822 } 2823 /* insert this AP to the list, right after the next event entry found */ 2824 nextEventArray[ nextEventArraySize ].nextAPIndex = nextEventArray[ i ].nextAPIndex; 2825 nextEventArray[ i ].nextAPIndex = nextEventArraySize; 2826 nextEventArraySize++; 2827 } 2828 } 2829 /* if for some reason a channel on which an AP was found is not valid for passive scan, 2830 the AP should be removed. */ 2831 else 2832 { 2833 /* removing the AP is done by increasing its track count to maximum - and since it is 2834 not tracked it will not be discovered, and thus will be deleted when the scan is complete */ 2835 pScanMngr->BSSList.scanBSSList[ BSSListIndex ].trackFailCount = 2836 pScanMngr->scanPolicy.maxTrackFailures + 1; 2837 #ifdef TI_DBG 2838 /*update statistics */ 2839 pScanMngr->stats.APsRemovedInvalidChannel++; 2840 #endif 2841 } 2842 } 2843 } 2844 2845 #ifdef SCAN_MNGR_SPS_DBG 2846 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 2847 ("SPS list after first stage:\n") ); 2848 scanMngrDebugPrintSPSHelperList( hScanMngr, nextEventArray, nextEventArrayHead, nextEventArraySize ); 2849 maxNextEventArraySize = nextEventArraySize; 2850 #endif 2851 2852 /* insert channels from next event array to scan command */ 2853 EarliestTSFToInsert = pScanMngr->currentTSF + SCAN_SPS_GUARD_FROM_CURRENT_TSF; 2854 /* insert all APs to scan command (as long as command is not full) */ 2855 while ( (nextEventArraySize > 0) && 2856 (pScanMngr->scanParams.numOfChannels < SCAN_MAX_NUM_OF_SPS_CHANNELS_PER_COMMAND) ) 2857 { 2858 /* if first list entry fits, and it doesn't collide with current AP DTIM */ 2859 if ( EarliestTSFToInsert < nextEventArray[ nextEventArrayHead ].nextEventTSF ) 2860 { 2861 if ( FALSE == scanMngrDTIMInRange( hScanMngr, nextEventArray[ nextEventArrayHead ].nextEventTSF, 2862 nextEventArray[ nextEventArrayHead ].nextEventTSF + scanMethod->method.spsMethodParams.scanDuration ) ) 2863 { 2864 /* insert it to scan command */ 2865 pScanMngr->scanParams.channelEntry[ pScanMngr->scanParams.numOfChannels ].SPSChannelEntry.scanStartTime = 2866 INT64_LOWER( (nextEventArray[ nextEventArrayHead ].nextEventTSF) ); 2867 pScanMngr->scanParams.channelEntry[ pScanMngr->scanParams.numOfChannels ].SPSChannelEntry.scanDuration = 2868 scanMethod->method.spsMethodParams.scanDuration; 2869 pScanMngr->scanParams.channelEntry[ pScanMngr->scanParams.numOfChannels ].SPSChannelEntry.ETMaxNumOfAPframes = 2870 scanMethod->method.spsMethodParams.ETMaxNumberOfApFrames; 2871 pScanMngr->scanParams.channelEntry[ pScanMngr->scanParams.numOfChannels ].SPSChannelEntry.earlyTerminationEvent = 2872 scanMethod->method.spsMethodParams.earlyTerminationEvent; 2873 pScanMngr->scanParams.channelEntry[ pScanMngr->scanParams.numOfChannels ].SPSChannelEntry.channel = 2874 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].channel; 2875 os_memoryCopy( pScanMngr->hOS, 2876 &(pScanMngr->scanParams.channelEntry[ pScanMngr->scanParams.numOfChannels ].SPSChannelEntry.bssId), 2877 &(pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID), 2878 MAC_ADDR_LEN ); 2879 /* increase the AP track attempts counter */ 2880 pScanMngr->BSSList.scanBSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].trackFailCount++; 2881 /* increase number of channels in scan command */ 2882 pScanMngr->scanParams.numOfChannels++; 2883 /* set earliest TSF that would fit in scan command */ 2884 EarliestTSFToInsert = nextEventArray[ nextEventArrayHead ].nextEventTSF + 2885 scanMethod->method.spsMethodParams.scanDuration + 2886 SCAN_SPS_GUARD_FROM_LAST_BSS; 2887 /* remove it from next event array */ 2888 nextEventArrayHead = nextEventArray[ nextEventArrayHead ].nextAPIndex; 2889 nextEventArraySize--; 2890 } 2891 else 2892 { 2893 UINT32 beaconIntervalUsec = 2894 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].beaconInterval * 1024; 2895 2896 /* if the next beacon also collide with DTIM */ 2897 if ( TRUE == scanMngrDTIMInRange( hScanMngr, nextEventArray[ nextEventArrayHead ].nextEventTSF + beaconIntervalUsec, 2898 nextEventArray[ nextEventArrayHead ].nextEventTSF + scanMethod->method.spsMethodParams.scanDuration + beaconIntervalUsec ) ) 2899 { 2900 /* An AP whose two consecutive beacons collide with current AP DTIM is not trackable by SPS!!! 2901 Shouldn't happen at a normal setup, but checked to avoid endless loop. 2902 First, remove it from the tracking list (by increasing it's track count above the maximum) */ 2903 pScanMngr->BSSList.scanBSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].trackFailCount = 2904 pScanMngr->scanPolicy.maxTrackFailures + 1; 2905 2906 /* and also remove it from the SPS list */ 2907 nextEventArrayHead = nextEventArray[ nextEventArrayHead ].nextAPIndex; 2908 nextEventArraySize--; 2909 2910 #ifdef TI_DBG 2911 /* update statistics */ 2912 pScanMngr->stats.APsRemovedDTIMOverlap++; 2913 #endif 2914 } 2915 else 2916 { 2917 /* calculate next event TSF - will get the next beacon, since timeToStartInAdvance is added to current beacon TSF */ 2918 nextEventArray[ nextEventArrayHead ].nextEventTSF = 2919 scanMngrCalculateNextEventTSF( hScanMngr, &(pScanMngr->BSSList), 2920 nextEventArray[ nextEventArrayHead ].trackListIndex, 2921 nextEventArray[ nextEventArrayHead ].nextEventTSF + timeToStartInAdvance + 1) 2922 - timeToStartInAdvance; 2923 2924 #ifdef SCAN_MNGR_SPS_DBG 2925 highValue = INT64_HIGHER( nextEventArray[ nextEventArrayHead ].nextEventTSF ); 2926 lowValue = INT64_LOWER( nextEventArray[ nextEventArrayHead ].nextEventTSF ); 2927 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 2928 ("reacalculating next frame for BSSID:%02x:%02x:%02x:%02x:%02x:%02x at TSF:%x-%x, bacause of DTIM collision\n", 2929 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 0 ], 2930 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 1 ], 2931 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 2 ], 2932 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 3 ], 2933 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 4 ], 2934 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 5 ], 2935 highValue, lowValue) ); 2936 #endif 2937 2938 /* reinsert to the next event array, sorted */ 2939 /* if still needs to be head, do nothing (because it's still head). otherwise: */ 2940 if ( (1 < nextEventArraySize) && /* list has more than one entry */ 2941 (nextEventArray[ nextEventArrayHead ].nextEventTSF > nextEventArray[ nextEventArray[ nextEventArrayHead ].nextAPIndex ].nextEventTSF) ) /* first event in list is earlier */ 2942 { 2943 /* first remove the head from the list */ 2944 j = nextEventArrayHead; 2945 nextEventArrayHead = nextEventArray[ nextEventArrayHead ].nextAPIndex; 2946 2947 /* start with list head */ 2948 i = nextEventArrayHead; 2949 /* while the new AP TSF is larger and list end had not been reached */ 2950 while ( (nextEventArray[ i ].nextAPIndex != -1) && /* list end had not been reached */ 2951 (nextEventArray[ nextEventArray[ i ].nextAPIndex ].nextEventTSF < nextEventArray[ j ].nextEventTSF) ) /* next event TSF of the next AP in the list is smaller than that of the AP being inserted */ 2952 { 2953 /* proceed to the next AP */ 2954 i = nextEventArray[ i ].nextAPIndex; 2955 } 2956 /* insert this AP to the list, right after the next event entry found */ 2957 nextEventArray[ j ].nextAPIndex = nextEventArray[ i ].nextAPIndex; 2958 nextEventArray[ i ].nextAPIndex = j; 2959 } 2960 2961 #ifdef SCAN_MNGR_SPS_DBG 2962 scanMngrDebugPrintSPSHelperList( hScanMngr, nextEventArray, nextEventArrayHead, maxNextEventArraySize ); 2963 #endif 2964 #ifdef TI_DBG 2965 /* update statistics */ 2966 pScanMngr->stats.SPSSavedByDTIMCheck++; 2967 #endif 2968 } 2969 } 2970 } 2971 else 2972 { 2973 /* calculate next event TSF */ 2974 nextEventArray[ nextEventArrayHead ].nextEventTSF = 2975 scanMngrCalculateNextEventTSF( hScanMngr, &(pScanMngr->BSSList), 2976 nextEventArray[ nextEventArrayHead ].trackListIndex, 2977 EarliestTSFToInsert + timeToStartInAdvance ) - timeToStartInAdvance; 2978 2979 #ifdef SCAN_MNGR_SPS_DBG 2980 highValue = INT64_HIGHER( nextEventArray[ nextEventArrayHead ].nextEventTSF ); 2981 lowValue = INT64_LOWER( nextEventArray[ nextEventArrayHead ].nextEventTSF ); 2982 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 2983 ("reacalculating next frame for BSSID:%02x:%02x:%02x:%02x:%02x:%02x at TSF:%x-%x\n", 2984 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 0 ], 2985 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 1 ], 2986 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 2 ], 2987 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 3 ], 2988 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 4 ], 2989 pScanMngr->BSSList.BSSList[ nextEventArray[ nextEventArrayHead ].trackListIndex ].BSSID.addr[ 5 ], 2990 highValue, lowValue) ); 2991 #endif 2992 2993 /* reinsert to the next event array, sorted */ 2994 /* if still needs to be head, do nothing (because it's still head). otherwise: */ 2995 if ( (1 < nextEventArraySize) && /* list has more than one entry */ 2996 (nextEventArray[ nextEventArrayHead ].nextEventTSF > nextEventArray[ nextEventArray[ nextEventArrayHead ].nextAPIndex ].nextEventTSF) ) /* first event in list is earlier */ 2997 { 2998 /* first remove the head from the list */ 2999 j = nextEventArrayHead; 3000 nextEventArrayHead = nextEventArray[ nextEventArrayHead ].nextAPIndex; 3001 3002 /* start with list head */ 3003 i = nextEventArrayHead; 3004 /* while the new AP TSF is larger and list end had not been reached */ 3005 while ( (nextEventArray[ i ].nextAPIndex != -1) && /* list end had not been reached */ 3006 (nextEventArray[ nextEventArray[ i ].nextAPIndex ].nextEventTSF < nextEventArray[ j ].nextEventTSF) ) /* next event TSF of the next AP in the list is smaller than that of the AP being inserted */ 3007 { 3008 /* proceed to the next AP */ 3009 i = nextEventArray[ i ].nextAPIndex; 3010 } 3011 /* insert this AP to the list, right after the next event entry found */ 3012 nextEventArray[ j ].nextAPIndex = nextEventArray[ i ].nextAPIndex; 3013 nextEventArray[ i ].nextAPIndex = j; 3014 } 3015 3016 #ifdef SCAN_MNGR_SPS_DBG 3017 scanMngrDebugPrintSPSHelperList( hScanMngr, nextEventArray, nextEventArrayHead, maxNextEventArraySize ); 3018 #endif 3019 } 3020 } 3021 /* For SPS scan, the scan duration is added to the command, since later on current TSF cannot be 3022 reevaluated. The scan duration is TSF at end of scan minus current TSF, divided by 1000 (convert 3023 to milliseconds) plus 1 (for the division reminder). */ 3024 pScanMngr->scanParams.SPSScanDuration = 3025 (((UINT32)(EarliestTSFToInsert - SCAN_SPS_GUARD_FROM_LAST_BSS - pScanMngr->currentTSF)) / 1000) + 1; 3026 } 3027 3028 /** 3029 * \author Ronen Kalish\n 3030 * \date 07-Mar-2005\n 3031 * \brief Calculates local TSF of the next event (beacon or GPR) of the given tracked AP.\n 3032 * 3033 * Function Scope \e Private.\n 3034 * \param hScanMngr - handle to the scan manager object.\n 3035 * \param BSSList - a pointer to the track list.\n 3036 * \param entryIndex - the index of the AP for which calculation is requires in the tracking list.\n 3037 * \param initialTSFValue - local TSF value AFTER which the next event is to found.\n 3038 * \return The approximate current TSF 3039 */ 3040 UINT64 scanMngrCalculateNextEventTSF( TI_HANDLE hScanMngr, scan_BSSList_t* BSSList, UINT8 entryIndex, UINT64 initialTSFValue ) 3041 { 3042 UINT64 remoteBeaconTSF, localBeaconTSF; 3043 INT64 localRemoteTSFDelta; 3044 UINT32 reminder; 3045 INT32 averageDeltaChange = 0; 3046 int i; 3047 #ifdef SCAN_MNGR_SPS_DBG 3048 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 3049 #endif /* SCAN_MNGR_SPS_DBG */ 3050 3051 /* graphical representation: 3052 E E E E E E E E E 3053 Remote TSF Line: | | | | | | | | | 3054 0 remoteTSF | | | | | | | | | Returned value 3055 +-----------------------+------+------+------+------+------+------+------+------+------+------+----------------... 3056 3057 Local TSF Line: 3058 0 localTSF initialTSFValue 3059 +-------------------+---------------------------------------------------------------+-----+---------------... 3060 3061 note that: 3062 1. both lines Don't start at the same time! 3063 2. remoteTSF and localTSF were measured when last frame was received from the tracked AP. the difference between their 3064 values is the constant difference between the two lines. 3065 3. initialTSFValue is the local TSF the first event after which is requested. 3066 4. returned value is the TSF (in local scale!) of the next event of the tracked AP. 3067 5. an E represents an occurring event, which is a scheduled frame transmission (beacon or GPR) of the tracked AP. 3068 */ 3069 3070 /* 3071 * The next event TSF is calculated as follows: 3072 * first, the difference between the local TSF (that of the AP the STA is currently connected to) and the 3073 * remote TSF (that of the AP being tracked) is calculated using the TSF values measured when last scan was 3074 * performed. Than, the initial TSF value is converted to remote TSF value, using the delta just calculated. 3075 * The next remote TSF is found (in remote TSF value) by subtracting the reminder of dividing the current 3076 * remote TSF value by the remote beacon interval (time passed from last beacon) from the current remote TSF 3077 * (hence amounting to the last beacon remote TSF), and than adding beacon interval. This is finally converted 3078 * back to local TSF, which is the requested value. 3079 * 3080 * After all this is done, clock drift between current AP and remote AP is compensated. This is done in thr 3081 * following way: the delte between local TSF and remote TSF is compared to this value at the last scan 3082 * (if they are equal, the clocks tick at the same rate). This difference is store in an array holding a 3083 * configured number of such previous differences (currenlty 4). The average value of these previous values 3084 * is then calculated, and added the the TSF value calculated before. This way, the average drift between 3085 * the local AP and the candidate AP is measured, and the next drift value can be estimated and thus 3086 * taken into account. 3087 */ 3088 3089 #ifdef SCAN_MNGR_SPS_DBG 3090 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3091 ("initial TSF value:%x-%x\n", 3092 INT64_HIGHER( initialTSFValue ), INT64_LOWER( initialTSFValue )) ); 3093 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3094 ("local time stamp:%x-%x\n", 3095 INT64_HIGHER( BSSList->scanBSSList[ entryIndex ].localTSF ), 3096 INT64_LOWER( BSSList->scanBSSList[ entryIndex ].localTSF )) ); 3097 #endif 3098 /* calculate the delta between local and remote TSF */ 3099 localRemoteTSFDelta = BSSList->scanBSSList[ entryIndex ].localTSF - 3100 BSSList->BSSList[ entryIndex ].lastRxTSF; 3101 /* convert initial TSF to remote timeline */ 3102 remoteBeaconTSF = initialTSFValue - localRemoteTSFDelta; 3103 #ifdef SCAN_MNGR_SPS_DBG 3104 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3105 ("Local TSF:%u-%u, Remote TSF: %u-%u\n", 3106 INT64_HIGHER(BSSList->scanBSSList[ entryIndex ].localTSF), 3107 INT64_LOWER(BSSList->scanBSSList[ entryIndex ].localTSF), 3108 INT64_HIGHER(BSSList->BSSList[ entryIndex ].lastRxTSF), 3109 INT64_LOWER(BSSList->BSSList[ entryIndex ].lastRxTSF) ) ); 3110 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3111 ("TSF delta:%u-%u, current remote TSF:%u-%u\n", 3112 INT64_HIGHER(localRemoteTSFDelta), 3113 INT64_LOWER(localRemoteTSFDelta), 3114 INT64_HIGHER(remoteBeaconTSF ), 3115 INT64_LOWER(remoteBeaconTSF )) ); 3116 #endif 3117 /* find last remote beacon transmission by subtracting the reminder of current remote TSF divided 3118 by the beacon interval (indicating how much time passed since last beacon) from current remote 3119 TSF */ 3120 reminder = reminder64( remoteBeaconTSF, BSSList->BSSList[ entryIndex ].beaconInterval * 1024 ); 3121 remoteBeaconTSF -= reminder; 3122 3123 #ifdef SCAN_MNGR_SPS_DBG 3124 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3125 ("reminder=%d\n",reminder) ); 3126 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3127 ("Last remote beacon TSF:%x-%x\n", 3128 INT64_HIGHER(remoteBeaconTSF), 3129 INT64_LOWER(remoteBeaconTSF)) ); 3130 #endif 3131 /* advance from last beacon to next beacon */ 3132 remoteBeaconTSF += BSSList->BSSList[ entryIndex ].beaconInterval * 1024; 3133 #ifdef SCAN_MNGR_SPS_DBG 3134 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3135 ("Next remote beacon TSF:%x-%x\n", 3136 INT64_HIGHER(remoteBeaconTSF), 3137 INT64_LOWER(remoteBeaconTSF)) ); 3138 #endif 3139 3140 #ifdef SCAN_SPS_USE_DRIFT_COMPENSATION 3141 /* update delta change array with the change between current and last delta (if last delta is valid) */ 3142 if ( 0 != BSSList->scanBSSList[ entryIndex ].prevTSFDelta ) 3143 { 3144 BSSList->scanBSSList[ entryIndex ].deltaChangeArray[ BSSList->scanBSSList[ entryIndex ].deltaChangeArrayIndex ] = 3145 (INT32)(localRemoteTSFDelta - BSSList->scanBSSList[ entryIndex ].prevTSFDelta); 3146 #ifdef SCAN_MNGR_SPS_DBG 3147 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3148 ("current delta^2:%d\n", localRemoteTSFDelta - BSSList->scanBSSList[ entryIndex ].prevTSFDelta) ); 3149 #endif 3150 if ( SCAN_SPS_NUM_OF_TSF_DELTA_ENTRIES == ++BSSList->scanBSSList[ entryIndex ].deltaChangeArrayIndex ) 3151 { 3152 BSSList->scanBSSList[ entryIndex ].deltaChangeArrayIndex = 0; 3153 } 3154 } 3155 BSSList->scanBSSList[ entryIndex ].prevTSFDelta = localRemoteTSFDelta; 3156 3157 /* calculate average delta change, and add (or subtract) it from beacon timing */ 3158 for ( i = 0; i < SCAN_SPS_NUM_OF_TSF_DELTA_ENTRIES; i++ ) 3159 { 3160 averageDeltaChange += BSSList->scanBSSList[ entryIndex ].deltaChangeArray[ i ]; 3161 } 3162 averageDeltaChange /= SCAN_SPS_NUM_OF_TSF_DELTA_ENTRIES; 3163 #ifdef SCAN_MNGR_SPS_DBG 3164 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3165 ("average delta change: %d\n", averageDeltaChange) ); 3166 #endif /* SCAN_MNGR_SPS_DBG */ 3167 remoteBeaconTSF += averageDeltaChange; 3168 #endif 3169 3170 /* convert to local TSF */ 3171 localBeaconTSF = remoteBeaconTSF + localRemoteTSFDelta; 3172 3173 #ifdef SCAN_SPS_USE_DRIFT_COMPENSATION 3174 /* if beacon (in local TSF) is before initial TSF value (possible due to drift compensation), 3175 proceed to next beacon */ 3176 if ( localBeaconTSF < initialTSFValue ) 3177 { 3178 localBeaconTSF += (BSSList->BSSList[ entryIndex ].beaconInterval * 1024); 3179 } 3180 #endif 3181 3182 return localBeaconTSF; 3183 } 3184 3185 /** 3186 * \author Ronen Kalish\n 3187 * \date 20-September-2005\n 3188 * \brief Check whether a time range collides with current AP DTIM 3189 * 3190 * Function Scope \e Private.\n 3191 * \param hScanMngr - handle to the scan manager object.\n 3192 * \param rangeStart - the time range start TSF.\n 3193 * \param rangeEnd - the time range end TSF.\n 3194 * \return Whether the event collides with a DTIM (TRUF if it does, FALSE if it doesn't).\n 3195 */ 3196 BOOLEAN scanMngrDTIMInRange( TI_HANDLE hScanMngr, UINT64 rangeStart, UINT64 rangeEnd ) 3197 { 3198 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 3199 UINT64 DTIMEventStart, DTIMEventEnd; 3200 UINT32 DTIMPeriodInUsec; /* DTIM period in micro seconds */ 3201 3202 #ifdef SCAN_MNGR_DTIM_DBG 3203 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3204 ("DTIM check: SPS raneg start:%x-%x, end:%x-%x\n", 3205 INT64_HIGHER(rangeStart), INT64_LOWER(rangeStart), 3206 INT64_HIGHER(rangeEnd), INT64_LOWER(rangeEnd)) ); 3207 #endif 3208 3209 /* calculate DTIM period */ 3210 DTIMPeriodInUsec = pScanMngr->currentBSSBeaconInterval * 1024 * pScanMngr->currentBSSDtimPeriod; 3211 3212 #ifdef SCAN_MNGR_DTIM_DBG 3213 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3214 ("DTIM period in usec: %d\n", DTIMPeriodInUsec) ); 3215 #endif 3216 3217 /* calculate (from DTIM count) the first DTIM after the last seen beacon. The last seen beacon will always 3218 occur before the SPS - because it already happened, and the SPS is a future event. However, the next DTIM 3219 is not necessarily prior to the SPS - it is also a future event (if the last beacon was not a DTIM) */ 3220 if ( 0 == pScanMngr->lastLocalBcnDTIMCount ) 3221 { /* The last beacon was a DTIM */ 3222 DTIMEventStart = pScanMngr->lastLocalBcnTSF; 3223 } 3224 else 3225 { /* The last beacon was not a DTIM - calculate the next beacon that will be a DTIM */ 3226 DTIMEventStart = pScanMngr->lastLocalBcnTSF + 3227 ((pScanMngr->currentBSSDtimPeriod - pScanMngr->lastLocalBcnDTIMCount) * pScanMngr->currentBSSBeaconInterval); 3228 WLAN_REPORT_INFORMATION(pScanMngr->hReport, SCAN_MNGR_MODULE_LOG,("\n Next DTIM TSF:%u-%u , last beacon TSF:%u-%u, last DTIM count: %d, beacon interval: %d\n", 3229 INT64_HIGHER(DTIMEventStart), INT64_LOWER(DTIMEventStart), 3230 INT64_HIGHER(pScanMngr->lastLocalBcnTSF), INT64_LOWER(pScanMngr->lastLocalBcnTSF), 3231 pScanMngr->lastLocalBcnDTIMCount, pScanMngr->currentBSSBeaconInterval)) ; 3232 } 3233 #ifdef SCAN_MNGR_DTIM_DBG 3234 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3235 ("Next DTIM TSF:%u-%u, last beacon TSF:%u-%u, last DTIM count: %d, beacon interval: %d\n", 3236 INT64_HIGHER(DTIMEventStart), INT64_LOWER(DTIMEventStart), 3237 INT64_HIGHER(pScanMngr->lastLocalBcnTSF), INT64_LOWER(pScanMngr->lastLocalBcnTSF), 3238 pScanMngr->lastLocalBcnDTIMCount, pScanMngr->currentBSSBeaconInterval) ); 3239 #endif 3240 3241 /* calculate the DTIM event end (add the DTIM length). Note that broadcast frames after the DTIM are not 3242 taken into consideration because their availability and length varies. Even if at some point SPS will be 3243 missed due to broadcast RX frames, it does not mean this AP cannot be tracked. */ 3244 DTIMEventEnd = DTIMEventStart + SCAN_SPS_FW_DTIM_LENGTH; 3245 3246 /* if this DTIM is after the SPS end - than no collision will occur! */ 3247 if ( DTIMEventStart > rangeEnd ) 3248 { 3249 #ifdef SCAN_MNGR_DTIM_DBG 3250 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3251 ("no collision because DTIM is after SPS\n") ); 3252 #endif 3253 return FALSE; 3254 } 3255 /* if this DTIM end is not before the SPS range start - it means the DTIM is colliding with the SPS, because 3256 it neither ends before the SPS nor starts after it */ 3257 else if ( DTIMEventEnd >= rangeStart ) 3258 { 3259 #ifdef SCAN_MNGR_DTIM_DBG 3260 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3261 ("Collision beacuse DTIM is not before SPS\n") ); 3262 #endif 3263 return TRUE; 3264 } 3265 /* the DTIM is before the SPS range - find the first DTIM after the SPS start (and check if it's colliding 3266 with the SPS range */ 3267 else 3268 { 3269 /* get the usec difference from the SPS range start to the last DTIM */ 3270 UINT64 usecDiffFromRangeStartToLastDTIM = rangeStart - DTIMEventStart; 3271 /* get the reminder from the usec difference divided by the DTIM period - the time (in usec) from last DTIM 3272 to SPS start */ 3273 UINT32 reminder = reminder64( usecDiffFromRangeStartToLastDTIM, DTIMPeriodInUsec ); 3274 /* get the next DTIM start time by adding DTIM period to the last DTIM before the SPS range start */ 3275 DTIMEventStart = rangeStart - reminder + DTIMPeriodInUsec; 3276 /* get DTIM end time */ 3277 DTIMEventEnd = DTIMEventStart + SCAN_SPS_FW_DTIM_LENGTH; 3278 #ifdef SCAN_MNGR_DTIM_DBG 3279 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3280 ("Diff from range start to last DTIM: %x-%x, reminder:%d, DTIM start:%x-%x, DTIM end: %x-%x\n", 3281 INT64_HIGHER(usecDiffFromRangeStartToLastDTIM), INT64_LOWER(usecDiffFromRangeStartToLastDTIM), 3282 reminder, INT64_HIGHER(DTIMEventStart), INT64_LOWER(DTIMEventStart), 3283 INT64_HIGHER(DTIMEventEnd), INT64_LOWER(DTIMEventEnd)) ); 3284 #endif 3285 3286 /* if the SPS starts after the DTIM ends or before the DTIM starts - no collision occurs */ 3287 if ( (rangeStart > DTIMEventEnd) || (rangeEnd < DTIMEventStart) ) 3288 { 3289 #ifdef SCAN_MNGR_DTIM_DBG 3290 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3291 ("No collision will occur because DTIM is before or after SPS\n") ); 3292 #endif 3293 return FALSE; 3294 } 3295 /* otherwise - a collision will occur! */ 3296 { 3297 #ifdef SCAN_MNGR_DTIM_DBG 3298 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3299 ("Collision will occur!\n") ); 3300 #endif 3301 return TRUE; 3302 } 3303 } 3304 } 3305 3306 /** 3307 * \author Ronen Kalish\n 3308 * \date 03-Mar-2005\n 3309 * \brief Add a normal channel entry to the object workspace scan command.\n 3310 * 3311 * Function Scope \e Private.\n 3312 * \param hScanMngr - handle to the scan manager object.\n 3313 * \param scanMethod - The scan method (and parameters) to use.\n 3314 * \param channel - the channel index.\n 3315 * \param BSSID - pointer to the BSSID to use (may be broadcast.\n 3316 * \param txPowerDbm - tx power to transmit probe requests.\n 3317 */ 3318 void scanMngrAddNormalChannel( TI_HANDLE hScanMngr, scan_Method_t* scanMethod, UINT8 channel, 3319 macAddress_t* BSSID, UINT8 txPowerDbm ) 3320 { 3321 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 3322 int commandChannelIndex; 3323 scan_basicMethodParams_t* basicMethodParams; 3324 3325 /* get next channel in the object workspace */ 3326 commandChannelIndex = pScanMngr->scanParams.numOfChannels; 3327 pScanMngr->scanParams.numOfChannels++; 3328 3329 /* get basic method params pointer according to scan type */ 3330 switch ( scanMethod->scanType ) 3331 { 3332 case SCAN_TYPE_NORMAL_PASSIVE: 3333 case SCAN_TYPE_NORMAL_ACTIVE: 3334 basicMethodParams = &(scanMethod->method.basicMethodParams); 3335 break; 3336 3337 case SCAN_TYPE_TRIGGERED_PASSIVE: 3338 case SCAN_TYPE_TRIGGERED_ACTIVE: 3339 basicMethodParams = &(scanMethod->method.TidTriggerdMethodParams.basicMethodParams); 3340 break; 3341 3342 default: 3343 WLAN_REPORT_WARNING( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3344 ("Unercognized scan type %d when adding normal channel to scan list.\n", scanMethod->scanType ) ); 3345 basicMethodParams = NULL; 3346 } 3347 3348 /* set params */ 3349 pScanMngr->scanParams.channelEntry[ commandChannelIndex ].normalChannelEntry.channel = channel; 3350 pScanMngr->scanParams.channelEntry[ commandChannelIndex ].normalChannelEntry.txPowerDbm = 3351 MIN( txPowerDbm, basicMethodParams->probReqParams.txPowerDbm ); 3352 pScanMngr->scanParams.channelEntry[ commandChannelIndex ].normalChannelEntry.maxChannelDwellTime = 3353 basicMethodParams->maxChannelDwellTime; 3354 pScanMngr->scanParams.channelEntry[ commandChannelIndex ].normalChannelEntry.minChannelDwellTime = 3355 basicMethodParams->minChannelDwellTime; 3356 pScanMngr->scanParams.channelEntry[ commandChannelIndex ].normalChannelEntry.earlyTerminationEvent = 3357 basicMethodParams->earlyTerminationEvent; 3358 pScanMngr->scanParams.channelEntry[ commandChannelIndex ].normalChannelEntry.ETMaxNumOfAPframes = 3359 basicMethodParams->ETMaxNumberOfApFrames; 3360 os_memoryCopy( pScanMngr->hOS, 3361 &(pScanMngr->scanParams.channelEntry[ commandChannelIndex ].normalChannelEntry.bssId), 3362 BSSID, 3363 MAC_ADDR_LEN ); 3364 } 3365 3366 /* Clear all candidate BSSList for Roaming */ 3367 void scanMngrClearBSSListEntry( TI_HANDLE hScanMngr ) 3368 { 3369 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 3370 3371 while(pScanMngr->BSSList.numOfEntries) 3372 scanMngrRemoveBSSListEntry(hScanMngr, pScanMngr->BSSList.numOfEntries-1); 3373 } 3374 3375 /** 3376 * \author Ronen Kalish\n 3377 * \date 02-Mar-2005\n 3378 * \brief Removes an entry from the BSS list (by replacing it with another entry, if any). 3379 * 3380 * Function Scope \e Private.\n 3381 * \param hScanMngr - handle to the scan manager object.\n 3382 * \param BSSEntryIndex - index of the entry to remove.\n 3383 */ 3384 void scanMngrRemoveBSSListEntry( TI_HANDLE hScanMngr, UINT8 BSSEntryIndex ) 3385 { 3386 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 3387 UINT8* tempResultBuffer; 3388 3389 #ifdef TI_DBG 3390 /*update statistics */ 3391 if ( SCAN_MNGR_STAT_MAX_TRACK_FAILURE <= pScanMngr->BSSList.scanBSSList[ BSSEntryIndex ].trackFailCount ) 3392 { 3393 pScanMngr->stats.ConsecutiveTrackFailCountHistogram[ SCAN_MNGR_STAT_MAX_TRACK_FAILURE - 1 ]++; 3394 } 3395 else 3396 { 3397 pScanMngr->stats.ConsecutiveTrackFailCountHistogram[ pScanMngr->BSSList.scanBSSList[ BSSEntryIndex ].trackFailCount ]++; 3398 } 3399 #endif 3400 /* if no more entries are available, simply reduce the number of entries. 3401 As this is the last entry, it won't be accessed any more. */ 3402 if ( (pScanMngr->BSSList.numOfEntries-1) == BSSEntryIndex ) 3403 { 3404 3405 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3406 ("Removing last entry %d in BSS list\n", pScanMngr->BSSList.numOfEntries) ); 3407 3408 pScanMngr->BSSList.numOfEntries--; 3409 } 3410 else 3411 { 3412 #ifdef SCAN_MNGR_DBG 3413 WLAN_REPORT_INFORMATION( pScanMngr->hReport, SCAN_MNGR_MODULE_LOG, 3414 ("Removing entry %d of %d\n", BSSEntryIndex, pScanMngr->BSSList.numOfEntries) ); 3415 #endif 3416 /* keep the scan result buffer pointer */ 3417 tempResultBuffer = pScanMngr->BSSList.BSSList[ BSSEntryIndex ].pBuffer; 3418 /* copy the last entry over this one */ 3419 os_memoryCopy( pScanMngr->hOS, &(pScanMngr->BSSList.BSSList[ BSSEntryIndex ]), 3420 &(pScanMngr->BSSList.BSSList[ pScanMngr->BSSList.numOfEntries-1 ]), 3421 sizeof(bssEntry_t) ); 3422 os_memoryCopy( pScanMngr->hOS, &(pScanMngr->BSSList.scanBSSList[ BSSEntryIndex ]), 3423 &(pScanMngr->BSSList.scanBSSList[ pScanMngr->BSSList.numOfEntries-1 ]), 3424 sizeof(scan_BSSEntry_t) ); 3425 /* replace the scan result buffer of the last entry */ 3426 pScanMngr->BSSList.BSSList[ pScanMngr->BSSList.numOfEntries-1 ].pBuffer = tempResultBuffer; 3427 /* decrease the number of BSS entries */ 3428 pScanMngr->BSSList.numOfEntries--; 3429 } 3430 } 3431 3432 /** 3433 * \author Ronen Kalish\n 3434 * \date 02-Mar-2005\n 3435 * \brief Removes all BSS list entries that are neither neighbor APs not on a policy defined channel.\n 3436 * 3437 * Function Scope \e Private.\n 3438 * \param hScanMngr - handle to the scan manager object.\n 3439 * \param bCheckNeighborAPs - whether to verify that APs marked as neighbor APs are really neighbor APs.\n 3440 * \param bCheckChannels - whether to verify that APs not marked as neighbor APs are on policy defined channel.\n 3441 */ 3442 void scanMngrUpdateBSSList( TI_HANDLE hScanMngr, BOOLEAN bCheckNeighborAPs, BOOLEAN bCheckChannels ) 3443 { 3444 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 3445 int BSSEntryIndex; 3446 3447 /* loop on all BSS list entry */ 3448 for ( BSSEntryIndex = 0; BSSEntryIndex < pScanMngr->BSSList.numOfEntries; BSSEntryIndex++ ) 3449 { 3450 /* an AP can be in the BSS list either because it's a neighbor AP or, if not, because it's on a 3451 policy defined channel. When Neighbor AP list is changed, it is only necessary to check APs that 3452 are in the list because they are neighbor APs. When the policy is changed, it is only necessary 3453 to check APs that are in the list because they are on a policy defined channel. */ 3454 3455 /* if a check for neighbor APs is requested, check only APs that are designated as neighbor APs, 3456 and only check if they still are neighbor APs */ 3457 if ( (TRUE == bCheckNeighborAPs) && 3458 (TRUE == pScanMngr->BSSList.BSSList[ BSSEntryIndex ].bNeighborAP) && 3459 (-1 == scanMngrGetNeighborAPIndex( hScanMngr, 3460 pScanMngr->BSSList.BSSList[ BSSEntryIndex ].band, 3461 &(pScanMngr->BSSList.BSSList[ BSSEntryIndex ].BSSID) )) ) 3462 { 3463 /* remove it */ 3464 scanMngrRemoveBSSListEntry( hScanMngr, BSSEntryIndex ); 3465 } 3466 3467 /* if a check for policy defined channels is requested, check only APs that are not designated as 3468 neighbor APs */ 3469 if ( (TRUE == bCheckChannels) && 3470 (FALSE == pScanMngr->BSSList.BSSList[ BSSEntryIndex ].bNeighborAP) && 3471 (FALSE == scanMngrIsPolicyChannel( hScanMngr, 3472 pScanMngr->BSSList.BSSList[ BSSEntryIndex ].band, 3473 pScanMngr->BSSList.BSSList[ BSSEntryIndex ].channel )) ) 3474 { 3475 /* remove it */ 3476 scanMngrRemoveBSSListEntry( hScanMngr, BSSEntryIndex ); 3477 } 3478 } 3479 } 3480 3481 /** 3482 * \author Ronen Kalish\n 3483 * \date 02-Mar-2005\n 3484 * \brief returns the index of a neighbor AP.\n 3485 * 3486 * Function Scope \e Private.\n 3487 * \param hScanMngr - handle to the scan manager object.\n 3488 * \param band - the band on which the AP resides.\n 3489 * \param bssId - the AP's BSSID.\n 3490 * \return the index into the neighbor AP list for the given address, -1 if AP is not in list.\n 3491 */ 3492 INT8 scanMngrGetNeighborAPIndex( TI_HANDLE hScanMngr, radioBand_e band, macAddress_t* bssId ) 3493 { 3494 scanMngr_t* pScanMngr = (scanMngr_t*)hScanMngr; 3495 int i; 3496 3497 /* loop on all neighbor APS for this AP's band, and compare BSSID's */ 3498 for ( i = 0; i < pScanMngr->neighborAPsDiscoveryList[ band ].numOfEntries; i++ ) 3499 { 3500 if ( 0 == os_memoryCompare( pScanMngr->hOS, 3501 (PUINT8)&(bssId->addr[ 0 ]), 3502 (PUINT8)&(pScanMngr->neighborAPsDiscoveryList[ band ].APListPtr[ i ].BSSID.addr[ 0 ]), 3503 MAC_ADDR_LEN ) ) 3504 { 3505 return i; 3506 } 3507 } 3508 3509 /* if the AP wasn't found in the list, it's not a neighbor AP... */ 3510 return -1; 3511 } 3512 3513 /** 3514 * \author Ronen Kalish\n 3515 * \date 02-Mar-2005\n 3516 * \brief Checks whether a channel is defined on a policy.\n 3517 * 3518 * Function Scope \e Private.\n 3519 * \param hScanMngr - handle to the scan manager object.\n 3520 * \param band - the band on which the channel is.\n 3521 * \param channel - the channel number.\n 3522 * \return TRUE if channel is defined on policy, FALSE otherwise.\n 3523 */ 3524 BOOLEAN scanMngrIsPolicyChannel( TI_HANDLE hScanMngr, radioBand_e band, UINT8 channel ) 3525 { 3526 int i; 3527 scan_bandPolicy_t* bandPolicy = scanMngrGetPolicyByBand( hScanMngr, band ); 3528 3529 3530 /* check if the AP's band is defined in the policy */ 3531 if ( NULL == bandPolicy ) 3532 { 3533 return FALSE; 3534 } 3535 3536 /* loop on all channels for the AP's band */ 3537 for ( i = 0; i < bandPolicy->numOfChannles; i++ ) 3538 { 3539 if ( bandPolicy->channelList[ i ] == channel ) 3540 { 3541 return TRUE; 3542 } 3543 } 3544 3545 /* if no channel was found, the AP is NOT on a policy configured channel */ 3546 return FALSE; 3547 } 3548 3549 /** 3550 * \author Ronen Kalish\n 3551 * \date 18-Apr-2005\n 3552 * \brief Converts scan concentrator result status to scan manager result status, to be returned to roaming manager.\n 3553 * 3554 * Function Scope \e Private.\n 3555 * \param result status - scan concentrator result status.\n 3556 * \return appropriate scan manager status.\n 3557 */ 3558 scan_mngrResultStatus_e scanMngrConvertResultStatus( scan_cncnResultStatus_e resultStatus ) 3559 { 3560 switch (resultStatus)