1 /* 2 * ScanCncn.c 3 * 4 * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name Texas Instruments nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /** \file ScanCncn.c 35 * \brief Scan concentartor implementation 36 * 37 * \see ScanCncnSm.c, ScanCncnSmSpecific.c 38 */ 39 40 41 #define __FILE_ID__ FILE_ID_76 42 #include "ScanCncn.h" 43 #include "report.h" 44 #include "scrApi.h" 45 #include "regulatoryDomainApi.h" 46 #include "siteMgrApi.h" 47 #include "healthMonitor.h" 48 #include "TWDriver.h" 49 #include "DrvMainModules.h" 50 #include "GenSM.h" 51 #include "ScanCncnPrivate.h" 52 #include "ScanCncnOsSm.h" 53 #include "scanResultTable.h" 54 #include "smeApi.h" 55 #include "apConnApi.h" 56 #include "EvHandler.h" 57 58 /* static functions */ 59 void scanCncn_SGupdateScanParams (TI_HANDLE hScanCncn, UScanParams *puScanParams, TI_BOOL bPeriodicScan) ; 60 static void scanCncn_VerifyChannelsWithRegDomain (TI_HANDLE hScanCncn, UScanParams *puScanParams, TI_BOOL bPeriodicScan); 61 static void scanCncn_Mix1ShotScanChannels (TScanChannelEntry *pChannelArray, TI_UINT32 uValidChannelsCount); 62 static void scanCncn_MixPeriodicScanChannels (TPeriodicChannelEntry *pChannelArray, TI_UINT32 uValidChannelsCount); 63 64 #define SCAN_CLIENT_FROM_TAG( tag ) tag2Client[ tag ]; 65 static EScanCncnClient tag2Client[ SCAN_RESULT_TAG_MAX_NUMBER ] = 66 { SCAN_SCC_NO_CLIENT, SCAN_SCC_APP_ONE_SHOT, SCAN_SCC_DRIVER, SCAN_SCC_APP_PERIODIC, SCAN_SCC_NO_CLIENT, 67 SCAN_SCC_ROAMING_IMMED, SCAN_SCC_ROAMING_CONT }; 68 69 /** 70 * \fn scanCncn_Create 71 * \brief Create the scan concentrator object 72 * 73 * Create the scan concentrator object. Allocates system resources and creates the client modules. 74 * 75 * \param hOS - handle to the OS object 76 * \return hanlde to the new scan concentrator object 77 * \sa scanCncn_Destroy, scanCncn_Init, scanCncn_SetDefaults 78 */ 79 TI_HANDLE scanCncn_Create (TI_HANDLE hOS) 80 { 81 TScanCncn *pScanCncn; 82 TI_UINT32 uIndex; 83 84 /* Allocate scan concentartor object memory */ 85 pScanCncn = (TScanCncn*)os_memoryAlloc (hOS, sizeof (TScanCncn)); 86 if (NULL == pScanCncn) 87 { 88 WLAN_OS_REPORT (("scanCncn_Create: Unable to allocate memory for scan concentrator object\n")); 89 return NULL; 90 } 91 92 /* nullify the new object */ 93 os_memorySet (hOS, (void*)pScanCncn, 0, sizeof (TScanCncn)); 94 95 /* Store OS handle */ 96 pScanCncn->hOS = hOS; 97 98 /* Create different clients */ 99 for (uIndex = 0; uIndex < SCAN_SCC_NUM_OF_CLIENTS; uIndex++) 100 { 101 pScanCncn->pScanClients[ uIndex ] = scanCncnSm_Create (hOS); 102 if (NULL == pScanCncn->pScanClients[ uIndex ]) 103 { 104 WLAN_OS_REPORT (("scanCncn_Create: Unable to create client %d object\n", uIndex)); 105 /* free all resources allocated so far */ 106 scanCncn_Destroy ((TI_HANDLE)pScanCncn); 107 return NULL; 108 } 109 } 110 111 /* create the OS scan SM */ 112 pScanCncn->hOSScanSm = scanCncnOsSm_Create ((TI_HANDLE)pScanCncn); 113 if (NULL == pScanCncn->hOSScanSm) 114 { 115 WLAN_OS_REPORT (("scanCncn_Create: Unable to create OS scan SM\n")); 116 /* free all resources allocated so far */ 117 scanCncn_Destroy ((TI_HANDLE)pScanCncn); 118 return NULL; 119 } 120 121 /* create the app scan result table */ 122 pScanCncn->hScanResultTable = scanResultTable_Create (hOS, SCAN_CNCN_APP_SCAN_TABLE_ENTRIES); 123 if (NULL == pScanCncn->hScanResultTable) 124 { 125 WLAN_OS_REPORT (("scanCncn_Create: Unable to create application scan result table\n")); 126 /* free all resources allocated so far */ 127 scanCncn_Destroy ((TI_HANDLE)pScanCncn); 128 return NULL; 129 } 130 131 /* return handle to the new object */ 132 return (TI_HANDLE)pScanCncn; 133 } 134 135 /** 136 * \fn scanCncn_Destroy 137 * \brief Destroys the scan concentrator object 138 * 139 * Destroys the scan concentrator object. Destroys the cleint modules and frees system resources. 140 * 141 * \param hScanCncn - handle to the scan concentrator object 142 * \return None 143 * \sa scanCncn_Create 144 */ 145 void scanCncn_Destroy (TI_HANDLE hScanCncn) 146 { 147 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 148 TI_UINT32 uIndex; 149 150 /* destory the app scan result table */ 151 scanResultTable_Destroy (pScanCncn->hScanResultTable); 152 153 /* destroy the OS scan SM */ 154 scanCncnOsSm_Destroy (hScanCncn); 155 156 /* destroy the client objects */ 157 for (uIndex = 0; uIndex < SCAN_SCC_NUM_OF_CLIENTS; uIndex++) 158 { 159 scanCncnSm_Destroy (pScanCncn->pScanClients[ uIndex ]); 160 } 161 162 /* release the scan concentrator object */ 163 os_memoryFree (pScanCncn->hOS, hScanCncn, sizeof (TScanCncn)); 164 } 165 166 /** 167 * \fn scanCncn_Init 168 * \brief Initializes the scan concentartor module 169 * 170 * Copy handles, register callbacks and initialize client modules 171 * 172 * \param pStadHandles - modules handles structure 173 * \return None 174 * \sa scanCncn_Create, scanCncn_SetDefaults 175 */ 176 void scanCncn_Init (TStadHandlesList *pStadHandles) 177 { 178 TScanCncn *pScanCncn = (TScanCncn*)pStadHandles->hScanCncn; 179 180 /* store handles */ 181 pScanCncn->hTWD = pStadHandles->hTWD; 182 pScanCncn->hReport = pStadHandles->hReport; 183 pScanCncn->hRegulatoryDomain = pStadHandles->hRegulatoryDomain; 184 pScanCncn->hSiteManager = pStadHandles->hSiteMgr; 185 pScanCncn->hSCR = pStadHandles->hSCR; 186 pScanCncn->hAPConn = pStadHandles->hAPConnection; 187 pScanCncn->hEvHandler = pStadHandles->hEvHandler; 188 pScanCncn->hMlme = pStadHandles->hMlmeSm; 189 pScanCncn->hHealthMonitor = pStadHandles->hHealthMonitor; 190 pScanCncn->hSme = pStadHandles->hSme; 191 192 /* nullify other parameters */ 193 pScanCncn->eConnectionStatus = STA_NOT_CONNECTED; 194 pScanCncn->bUseSGParams = TI_FALSE; /* bUseSGParams is TI_TRUE only when SG module is enabled */ 195 pScanCncn->eCurrentRunningAppScanClient = SCAN_SCC_NO_CLIENT; 196 pScanCncn->uOSScanLastTimeStamp = 0; 197 pScanCncn->bOSScanRunning = TI_FALSE; 198 199 /* initialize client objects */ 200 scanCncnSm_Init (pScanCncn->pScanClients[ SCAN_SCC_ROAMING_IMMED ], pScanCncn->hReport, pScanCncn->hTWD, 201 pScanCncn->hSCR, pScanCncn->hAPConn, pScanCncn->hMlme, (TI_HANDLE)pScanCncn, 202 scanCncnSmImmed1Shot_ScrRequest, scanCncnSmImmed1Shot_ScrRelease, scanCncnSmImmed1Shot_StartScan, 203 scanCncnSmImmed1Shot_StopScan, scanCncnSmImmed1Shot_Recovery, "Immediate scan SM"); 204 scanCncnSm_Init (pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ], pScanCncn->hReport, pScanCncn->hTWD, 205 pScanCncn->hSCR, pScanCncn->hAPConn, pScanCncn->hMlme, (TI_HANDLE)pScanCncn, 206 scanCncnSmCont1Shot_ScrRequest, scanCncnSmCont1Shot_ScrRelease, scanCncnSmCont1Shot_StartScan, 207 scanCncnSmCont1Shot_StopScan, scanCncnSmCont1Shot_Recovery, "Continuous scan SM"); 208 scanCncnSm_Init (pScanCncn->pScanClients[ SCAN_SCC_DRIVER ], pScanCncn->hReport, pScanCncn->hTWD, 209 pScanCncn->hSCR, pScanCncn->hAPConn, pScanCncn->hMlme, (TI_HANDLE)pScanCncn, 210 scanCncnSmDrvP_ScrRequest, scanCncnSmDrvP_ScrRelease, scanCncnSmDrvP_StartScan, 211 scanCncnSmDrvP_StopScan, scanCncnSmDrvP_Recovery, "Driver scan SM"); 212 scanCncnSm_Init (pScanCncn->pScanClients[ SCAN_SCC_APP_PERIODIC ], pScanCncn->hReport, pScanCncn->hTWD, 213 pScanCncn->hSCR, pScanCncn->hAPConn, pScanCncn->hMlme, (TI_HANDLE)pScanCncn, 214 scanCncnSmAppP_ScrRequest, scanCncnSmAppP_ScrRelease, scanCncnSmAppP_StartScan, 215 scanCncnSmAppP_StopScan, scanCncnSmAppP_Recovery, "Periodic application scan SM"); 216 scanCncnSm_Init (pScanCncn->pScanClients[ SCAN_SCC_APP_ONE_SHOT ], pScanCncn->hReport, pScanCncn->hTWD, 217 pScanCncn->hSCR, pScanCncn->hAPConn, pScanCncn->hMlme, (TI_HANDLE)pScanCncn, 218 scanCncnSmApp1Shot_ScrRequest, scanCncnSmApp1Shot_ScrRelease, scanCncnSmApp1Shot_StartScan, 219 scanCncnSmApp1Shot_StopScan, scanCncnSmApp1Shot_Recovery, "One-shot application scan SM"); 220 221 /* Initialize the OS scan SM */ 222 scanCncnOsSm_Init ((TI_HANDLE)pScanCncn); 223 224 /* initlaize the application scan result table */ 225 scanResultTable_Init (pScanCncn->hScanResultTable, pStadHandles, SCAN_RESULT_TABLE_DONT_CLEAR); 226 } 227 228 /** 229 * \fn scanCncn_SetDefaults 230 * \brief Set registry values to scan concentrator 231 * 232 * Set registry values to scan concentrator 233 * 234 * \param hScanCncn - handle to the scan concentrator object 235 * \param pScanConcentratorInitParams - pointer to the registry parameters struct 236 * \return None 237 * \sa scanCncn_Create, scanCncn_Init 238 */ 239 void scanCncn_SetDefaults (TI_HANDLE hScanCncn, TScanCncnInitParams *pScanCncnInitParams) 240 { 241 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 242 243 /* copy registry values */ 244 os_memoryCopy (pScanCncn->hOS, 245 &pScanCncn->tInitParams, 246 pScanCncnInitParams, 247 sizeof (TScanCncnInitParams)); 248 249 /* register SCR callbacks */ 250 scr_registerClientCB (pScanCncn->hSCR, SCR_CID_APP_SCAN, scanCncn_ScrAppCB, (TI_HANDLE)pScanCncn); 251 scr_registerClientCB (pScanCncn->hSCR, SCR_CID_DRIVER_FG_SCAN, scanCncn_ScrDriverCB, (TI_HANDLE)pScanCncn); 252 scr_registerClientCB (pScanCncn->hSCR, SCR_CID_CONT_SCAN, scanCncn_ScrRoamingContCB, (TI_HANDLE)pScanCncn); 253 scr_registerClientCB (pScanCncn->hSCR, SCR_CID_IMMED_SCAN, scanCncn_ScrRoamingImmedCB, (TI_HANDLE)pScanCncn); 254 255 /* register TWD scan complete CB */ 256 TWD_RegisterScanCompleteCb (pScanCncn->hTWD, scanCncn_ScanCompleteNotificationCB, 257 (TI_HANDLE)pScanCncn); 258 /* register and enable periodic scan complete event with TWD */ 259 TWD_RegisterEvent (pScanCncn->hTWD, TWD_OWN_EVENT_PERIODIC_SCAN_COMPLETE, 260 (void *)scanCncn_PeriodicScanCompleteCB, (TI_HANDLE)pScanCncn); 261 TWD_EnableEvent (pScanCncn->hTWD, TWD_OWN_EVENT_PERIODIC_SCAN_COMPLETE); 262 263 /* and periodic scan report */ 264 TWD_RegisterEvent (pScanCncn->hTWD, TWD_OWN_EVENT_PERIODIC_SCAN_REPORT, 265 (void *)scanCncn_PeriodicScanReportCB, (TI_HANDLE)pScanCncn); 266 TWD_EnableEvent (pScanCncn->hTWD, TWD_OWN_EVENT_PERIODIC_SCAN_REPORT); 267 268 /* "register" the application scan result callback */ 269 scanCncn_RegisterScanResultCB ((TI_HANDLE)pScanCncn, SCAN_SCC_APP_ONE_SHOT, scanCncn_AppScanResultCB, (TI_HANDLE)pScanCncn); 270 scanCncn_RegisterScanResultCB ((TI_HANDLE)pScanCncn, SCAN_SCC_APP_PERIODIC, scanCncn_AppScanResultCB, (TI_HANDLE)pScanCncn); 271 272 /* set the Scan Result Aging threshold for the scan concentrator's Scan Result Table */ 273 scanResultTable_SetSraThreshold(pScanCncn->hScanResultTable, pScanCncnInitParams->uSraThreshold); 274 275 /* set to the sme the handler of the scan concentrator Scan Result Table */ 276 sme_SetScanResultTable(pScanCncn->hSme, pScanCncn->hScanResultTable); 277 } 278 279 /** 280 * \fn scanCncn_SwitchToConnected 281 * \brief Notifies the scan concentratoe the STA has connected to an infrastructure BSS 282 * 283 * Notifies the scan concentratoe the STA has connected to an infrastructure BSS 284 * 285 * \param hScanCncn - handle to the scan concentrator object 286 * \return None 287 * \sa scanCncn_SwitchToNotConnected, scanCncn_SwitchToIBSS 288 */ 289 void scanCncn_SwitchToConnected (TI_HANDLE hScanCncn) 290 { 291 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 292 293 TRACE0(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_SwitchToConnected: Switching to connected state.\n"); 294 295 /* change connection status to connected */ 296 pScanCncn->eConnectionStatus = STA_CONNECTED; 297 298 /* Any running scans in other modes will be aborted (if needed) by the SCR (or have already been) */ 299 } 300 301 /** 302 * \fn scanCncn_SwitchToNotConnected 303 * \brief Notifies the scan concentratoe the STA has disconnected from a BSS 304 * 305 * Notifies the scan concentratoe the STA has disconnected from a BSS 306 * 307 * \param hScanCncn - handle to the scan concentrator object 308 * \return None 309 * \sa scanCncn_SwitchToConnected, scanCncn_SwitchToIBSS 310 */ 311 void scanCncn_SwitchToNotConnected (TI_HANDLE hScanCncn) 312 { 313 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 314 315 TRACE0(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_SwitchToNotConnected: Switching to not connected state.\n"); 316 317 /* change connection status to connected */ 318 pScanCncn->eConnectionStatus = STA_NOT_CONNECTED; 319 320 /* Any running scans in other modes will be aborted (if needed) by the SCR (or have already been) */ 321 } 322 323 /** 324 * \fn scanCncn_SwitchToIBSS 325 * \brief Notifies the scan concentratoe the STA has connected to an independent BSS 326 * 327 * Notifies the scan concentratoe the STA has connected to an independent BSS 328 * 329 * \param hScanCncn - handle to the scan concentrator object 330 * \return None 331 * \sa scanCncn_SwitchToConnected, scanCncn_SwitchToNotConnected 332 */ 333 void scanCncn_SwitchToIBSS (TI_HANDLE hScanCncn) 334 { 335 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 336 337 TRACE0(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_SwitchToIBSS: Switching to IBSS state.\n"); 338 339 /* change connection status to connected */ 340 pScanCncn->eConnectionStatus = STA_IBSS; 341 342 /* Any running scans in other modes will be aborted (if needed) by the SCR (or have already been) */ 343 } 344 345 EScanCncnResultStatus scanCncn_Start1ShotScan (TI_HANDLE hScanCncn, 346 EScanCncnClient eClient, 347 TScanParams* pScanParams) 348 { 349 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 350 paramInfo_t *pParam; 351 352 TRACE1(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_Start1ShotScan: Received scan request from client %d\n", eClient); 353 354 pParam = (paramInfo_t *)os_memoryAlloc(pScanCncn->hOS, sizeof(paramInfo_t)); 355 if (!pParam) { 356 return SCAN_CRS_SCAN_FAILED; 357 } 358 359 /* copy scan parameters to local buffer */ 360 os_memoryCopy (pScanCncn->hOS, &(pScanCncn->pScanClients[ eClient ]->uScanParams.tOneShotScanParams), 361 pScanParams, sizeof(TScanParams)); 362 363 /* 364 * roaming scans (continuous and immediate) require to set the current SSID, to keep the scan manager 365 * unaware of it, unless the SSID is broadcast (to allow customers to request broadcast scan) 366 */ 367 if ((SCAN_SCC_ROAMING_CONT == eClient) || (SCAN_SCC_ROAMING_IMMED == eClient)) 368 { 369 if (0 != pScanParams->desiredSsid.len) 370 { 371 /* set the SSID of the current AP */ 372 pParam->paramType = SME_DESIRED_SSID_ACT_PARAM; 373 sme_GetParam (pScanCncn->hSme, pParam); 374 os_memoryCopy (pScanCncn->hOS, 375 &(pScanCncn->pScanClients[ eClient ]->uScanParams.tOneShotScanParams.desiredSsid), 376 &(pParam->content.smeDesiredSSID), 377 sizeof(TSsid)); 378 } 379 } 380 os_memoryFree(pScanCncn->hOS, pParam, sizeof(paramInfo_t)); 381 382 /* ask the reg domain which channels are allowed for the requested scan type */ 383 scanCncn_VerifyChannelsWithRegDomain (hScanCncn, &(pScanCncn->pScanClients[ eClient ]->uScanParams), TI_FALSE); 384 385 /* if no channels are available for scan, return negative result */ 386 if (0 == pScanCncn->pScanClients[ eClient ]->uScanParams.tOneShotScanParams.numOfChannels) 387 { 388 TRACE0(pScanCncn->hReport, REPORT_SEVERITY_ERROR , "scanCncn_Start1ShotScan: no cahnnels to scan after reg. domain verification, can't scan\n"); 389 return SCAN_CRS_SCAN_FAILED; 390 } 391 392 /* Mix the channel order in the 1 Shot Scan channel array */ 393 scanCncn_Mix1ShotScanChannels (pScanCncn->pScanClients[ eClient ]->uScanParams.tOneShotScanParams.channelEntry, 394 pScanCncn->pScanClients[ eClient ]->uScanParams.tOneShotScanParams.numOfChannels); 395 396 if (TI_TRUE == pScanCncn->bUseSGParams) 397 { 398 scanCncn_SGupdateScanParams (hScanCncn, &(pScanCncn->pScanClients[ eClient ]->uScanParams), TI_FALSE); 399 } 400 401 /* mark that a scan request is in progress (to avoid client re-entrance if the scan fail) */ 402 pScanCncn->pScanClients[ eClient ]->bInRequest = TI_TRUE; 403 404 /* mark the scan result as TI_OK (until other status will replace it) */ 405 pScanCncn->pScanClients[ eClient ]->eScanResult = SCAN_CRS_SCAN_COMPLETE_OK; 406 407 /* send a start scan event to the SM */ 408 genSM_Event (pScanCncn->pScanClients[ eClient ]->hGenSM, SCAN_CNCN_SM_EVENT_START, 409 (TI_HANDLE)pScanCncn->pScanClients[ eClient ]); 410 411 /* mark that the scan request is no longer in progress */ 412 pScanCncn->pScanClients[ eClient ]->bInRequest = TI_FALSE; 413 414 /* 415 * return scan result - if an error occured return the error, otherwise return running 416 * (complete_ok is set to be returned when scan is complete) 417 */ 418 if (SCAN_CRS_SCAN_COMPLETE_OK != pScanCncn->pScanClients[ eClient ]->eScanResult) 419 { 420 return pScanCncn->pScanClients[ eClient ]->eScanResult; 421 } 422 return SCAN_CRS_SCAN_RUNNING; 423 } 424 425 void scanCncn_StopScan (TI_HANDLE hScanCncn, EScanCncnClient eClient) 426 { 427 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 428 429 TRACE1( pScanCncn->hReport, REPORT_SEVERITY_INFORMATION, "scanCncn_StopScan: Received stop scan request from client %d\n", eClient); 430 431 /* 432 * mark that null data should be sent (different from abort, where null dats is not sent 433 * to reduce abort time) 434 */ 435 pScanCncn->pScanClients[ eClient ]->bSendNullDataOnStop = TI_TRUE; 436 437 /* if no previous error has occurred, change the state to stopped */ 438 if (SCAN_CRS_SCAN_COMPLETE_OK == pScanCncn->pScanClients[ eClient ]->eScanResult) 439 { 440 pScanCncn->pScanClients[ eClient ]->eScanResult = SCAN_CRS_SCAN_STOPPED; 441 } 442 443 /* send a stop scan event to the SM */ 444 genSM_Event (pScanCncn->pScanClients[ eClient ]->hGenSM, SCAN_CNCN_SM_EVENT_STOP, 445 (TI_HANDLE)pScanCncn->pScanClients[ eClient ]); 446 } 447 448 /** 449 * \fn scanCncn_StartPeriodicScan 450 * \brief Starts a periodic scan operation 451 * 452 * Starts a periodic scan operation: 453 * - copies scan params to scan concentrator object 454 * - verifies the requested channels with the reg doamin 455 * - if needed, adjust to SG compensation values 456 * - send an event to the client SM 457 * 458 * \param hScanCncn - handle to the scan concentrator object 459 * \param eClient - the client requesting the scan operation 460 * \param pScanParams - scan parameters 461 * \return Scan opeartion status 462 * \retval SCAN_CRS_SCAN_RUNNING - scan started successfully and is now running 463 * \retval SCAN_CRS_SCAN_FAILED - scan failed to start due to an unexpected error 464 * \sa scanCncn_StopPeriodicScan 465 */ 466 EScanCncnResultStatus scanCncn_StartPeriodicScan (TI_HANDLE hScanCncn, 467 EScanCncnClient eClient, 468 TPeriodicScanParams *pScanParams) 469 { 470 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 471 472 TRACE1(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_startPeriodicScan: Received scan request from client %d\n", eClient); 473 474 /* copy scan parameters to local buffer */ 475 os_memoryCopy (pScanCncn->hOS, &(pScanCncn->pScanClients[ eClient ]->uScanParams.tPeriodicScanParams), 476 pScanParams, sizeof(TPeriodicScanParams)); 477 478 /* ask the reg domain which channels are allowed for the requested scan type */ 479 scanCncn_VerifyChannelsWithRegDomain (hScanCncn, &(pScanCncn->pScanClients[ eClient ]->uScanParams), TI_TRUE); 480 481 /* if no channels are available for scan, return negative result */ 482 if (0 == pScanCncn->pScanClients[ eClient ]->uScanParams.tPeriodicScanParams.uChannelNum) 483 { 484 TRACE0(pScanCncn->hReport, REPORT_SEVERITY_ERROR , "scanCncn_StartPeriodicScan: no cahnnels to scan after reg. domain verification, can't scan\n"); 485 return SCAN_CRS_SCAN_FAILED; 486 } 487 488 /* Mix the channel order in the Periodic Scan channel array */ 489 scanCncn_MixPeriodicScanChannels (pScanCncn->pScanClients[ eClient ]->uScanParams.tPeriodicScanParams.tChannels, 490 pScanCncn->pScanClients[ eClient ]->uScanParams.tPeriodicScanParams.uChannelNum); 491 492 if (TI_TRUE == pScanCncn->bUseSGParams) 493 { 494 scanCncn_SGupdateScanParams (hScanCncn, &(pScanCncn->pScanClients[ eClient ]->uScanParams), TI_TRUE); 495 } 496 497 /* mark that a scan request is in progress (to avoid client re-entrance if the scan fail) */ 498 pScanCncn->pScanClients[ eClient ]->bInRequest = TI_TRUE; 499 500 /* mark the scan result as TI_OK (until other status will replace it) */ 501 pScanCncn->pScanClients[ eClient ]->eScanResult = SCAN_CRS_SCAN_COMPLETE_OK; 502 503 /* send a start scan event to the SM */ 504 genSM_Event (pScanCncn->pScanClients[ eClient ]->hGenSM, SCAN_CNCN_SM_EVENT_START, 505 (TI_HANDLE)pScanCncn->pScanClients[ eClient ]); 506 507 /* mark that the scan request is no longer in progress */ 508 pScanCncn->pScanClients[ eClient ]->bInRequest = TI_FALSE; 509 510 /* 511 * return scan result - if an error occured return the error, otherwise return running 512 * (complete_ok is set to be returned when scan is complete) 513 */ 514 if (SCAN_CRS_SCAN_COMPLETE_OK != pScanCncn->pScanClients[ eClient ]->eScanResult) 515 { 516 return pScanCncn->pScanClients[ eClient ]->eScanResult; 517 } 518 return SCAN_CRS_SCAN_RUNNING; 519 } 520 521 /** 522 * \fn scanCncn_StopPeriodicScan 523 * \brief Stop an on-going periodic scan operation 524 * 525 * Set necessary flags and send a stop scan event to the client SM 526 * 527 * \param hScanCncn - handle to the scan concentrator object 528 * \param eClient - the client requesting to stop the scan operation 529 * \return None 530 * \sa scanCncn_StartPeriodicScan 531 */ 532 void scanCncn_StopPeriodicScan (TI_HANDLE hScanCncn, EScanCncnClient eClient) 533 { 534 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 535 536 TRACE1( pScanCncn->hReport, REPORT_SEVERITY_INFORMATION, "scanCncn_StopPeriodicScan: Received stop scan request from client %d\n", eClient); 537 538 /* if no previous error has occurred, change the state to stopped */ 539 if (SCAN_CRS_SCAN_COMPLETE_OK == pScanCncn->pScanClients[ eClient ]->eScanResult) 540 { 541 pScanCncn->pScanClients[ eClient ]->eScanResult = SCAN_CRS_SCAN_STOPPED; 542 } 543 544 /* send a stop scan event to the SM */ 545 genSM_Event (pScanCncn->pScanClients[ eClient ]->hGenSM, SCAN_CNCN_SM_EVENT_STOP, 546 (TI_HANDLE)pScanCncn->pScanClients[ eClient ]); 547 } 548 549 void scanCncn_RegisterScanResultCB (TI_HANDLE hScanCncn, EScanCncnClient eClient, 550 TScanResultCB scanResultCBFunc, TI_HANDLE scanResultCBObj) 551 { 552 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 553 554 /* save the function and object pointers */ 555 pScanCncn->pScanClients[ eClient ]->tScanResultCB = scanResultCBFunc; 556 pScanCncn->pScanClients[ eClient ]->hScanResultCBObj = scanResultCBObj; 557 } 558 559 /** 560 * \fn scanCncn_ScanCompleteNotificationCB 561 * \brief Called when a scan is complete 562 * 563 * Update scan status and send a complete event to the SM 564 * 565 * \note Must wait for all results to be received before the scan is actually completed 566 * \param hScanCncn - handle to the scan concentrator object 567 * \param eTag - the scan type tag 568 * \param uResoultCount - number of results received during this scan 569 * \param SPSStatus - which channels were attempted (if this is an SPS scan) 570 * \param bTSFError - whether a TSF error occurred (if this is an SPS scan) 571 * \param scanStatus - scan SRV status (OK / NOK) 572 * \return None 573 */ 574 void scanCncn_ScanCompleteNotificationCB (TI_HANDLE hScanCncn, EScanResultTag eTag, 575 TI_UINT32 uResultCount, TI_UINT16 SPSStatus, 576 TI_BOOL bTSFError, TI_STATUS scanStatus, 577 TI_STATUS PSMode) 578 { 579 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 580 EScanCncnClient eClient; 581 582 TRACE6(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_ScanCompleteNotificationCB: tag: %d, result count: %d, SPS status: %d, TSF Error: %d, scan status: %d, PS mode: %d\n", eTag, uResultCount, SPSStatus, bTSFError, scanStatus, PSMode); 583 584 /* get the scan client value from the scan tag */ 585 eClient = SCAN_CLIENT_FROM_TAG (eTag); 586 587 /* update scan result if scan SRV reported error (and no error occured so far) */ 588 if ((TI_OK != scanStatus) && (SCAN_CRS_SCAN_COMPLETE_OK == pScanCncn->pScanClients[ eClient ]->eScanResult)) 589 { 590 pScanCncn->pScanClients[ eClient ]->eScanResult = SCAN_CRS_SCAN_FAILED; 591 } 592 593 /* for SPS: copy SPS result and update scan status according to TSF error */ 594 if (SCAN_TYPE_SPS == pScanCncn->pScanClients[ eClient ]->uScanParams.tOneShotScanParams.scanType) 595 { 596 pScanCncn->pScanClients[ eClient ]->uSPSScanResult = SPSStatus; 597 if (TI_TRUE == bTSFError) 598 { 599 pScanCncn->pScanClients[ eClient ]->eScanResult = SCAN_CRS_TSF_ERROR; 600 } 601 } 602 603 /* update number of frames expected */ 604 pScanCncn->pScanClients[ eClient ]->uResultExpectedNumber += uResultCount; 605 606 /* check if all frames had been received */ 607 if (pScanCncn->pScanClients[ eClient ]->uResultCounter >= pScanCncn->pScanClients[ eClient ]->uResultExpectedNumber) 608 { 609 TRACE2(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_ScanCompleteNotificationCB: client %d received %d results, matching scan complete FW indication, sending scan complete event\n", eClient, pScanCncn->pScanClients[ eClient ]->uResultCounter); 610 611 /* all frames had been received, send a scan complete event to the client SM */ 612 genSM_Event (pScanCncn->pScanClients[ eClient ]->hGenSM, SCAN_CNCN_SM_EVENT_SCAN_COMPLETE, 613 (TI_HANDLE)pScanCncn->pScanClients[ eClient ]); 614 } 615 else 616 { 617 TRACE3(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_ScanCompleteNotificationCB: client %d received %d results, FW indicated %d results, waiting for more\n", eClient, pScanCncn->pScanClients[ eClient ]->uResultCounter, pScanCncn->pScanClients[ eClient ]->uResultExpectedNumber); 618 619 /* still waiting for some frames, turn on the scan complete pending flag */ 620 pScanCncn->pScanClients[ eClient ]->bScanCompletePending = TI_TRUE; 621 } 622 } 623 624 /** 625 * \fn scanCncn_PeriodicScanReportCB 626 * \brief Called when results are available but periodic scan is not yet complete 627 * 628 * Called when results are available but periodic scan is not yet complete 629 * 630 * \param hScanCncn - handle to the scan concentrator object 631 * \param str - event data 632 * \param strLen - data length 633 * \return None 634 * \sa scanCncn_PeriodicScanCompleteCB 635 */ 636 void scanCncn_PeriodicScanReportCB (TI_HANDLE hScanCncn, char* str, TI_UINT32 strLen) 637 { 638 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 639 EScanCncnClient eClient; 640 EScanResultTag eTag = (EScanResultTag)str[ 1 ]; 641 TI_UINT32 uResultCount = str[ 0 ]; 642 643 TRACE2(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_PeriodicScanReportCB: tag: %d, result count: %d\n", eTag, uResultCount); 644 645 /* get the scan client value from the scan tag */ 646 eClient = SCAN_CLIENT_FROM_TAG (eTag); 647 648 /* update number of frames expected */ 649 pScanCncn->pScanClients[ eClient ]->uResultExpectedNumber += uResultCount; 650 } 651 /** 652 * \fn scanCncn_PeriodicScanReportCB 653 * \brief Called when results are available but the scan is bot yet complete 654 * 655 * Called when results are available but the scan is bot yet complete 656 * 657 * \param hScanCncn - handle to the scan concentrator object 658 * \param str - event data 659 * \param strLen - data length 660 * \return None 661 * \sa scanCncn_PeriodicScanReportCB 662 */ 663 void scanCncn_PeriodicScanCompleteCB (TI_HANDLE hScanCncn, char* str, TI_UINT32 strLen) 664 { 665 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 666 EScanCncnClient eClient; 667 EScanResultTag eTag = (EScanResultTag)str[1]; 668 TI_UINT32 uResultCount = (TI_UINT8)(str[0]); 669 670 TRACE2(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_PeriodicScanCompleteCB: tag: %d, result count: %d\n", eTag, uResultCount); 671 672 /* get the scan client value from the scan tag */ 673 eClient = SCAN_CLIENT_FROM_TAG (eTag); 674 675 /* update number of frames expected */ 676 pScanCncn->pScanClients[ eClient ]->uResultExpectedNumber += uResultCount; 677 678 /* check if all frames had been received */ 679 if (pScanCncn->pScanClients[ eClient ]->uResultCounter >= pScanCncn->pScanClients[ eClient ]->uResultExpectedNumber) 680 { 681 TRACE2(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_PeriodicScanCompleteCB: client %d received %d results, matching scan complete FW indication, sending scan complete event\n", eClient, pScanCncn->pScanClients[ eClient ]->uResultCounter); 682 /* all frames had been received, send a scan complete event to the client SM */ 683 genSM_Event (pScanCncn->pScanClients[ eClient ]->hGenSM, SCAN_CNCN_SM_EVENT_SCAN_COMPLETE, 684 (TI_HANDLE)pScanCncn->pScanClients[ eClient ]); 685 } 686 else 687 { 688 TRACE3(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_PeriodicScanCompleteCB: client %d received %d results, FW indicated %d results, waiting for more\n", eClient, pScanCncn->pScanClients[ eClient ]->uResultCounter, pScanCncn->pScanClients[ eClient ]->uResultExpectedNumber); 689 /* still waiting for some frames, turn on the scan complete pending flag */ 690 pScanCncn->pScanClients[ eClient ]->bScanCompletePending = TI_TRUE; 691 } 692 } 693 694 /** 695 * \fn scanCncn_MlmeResultCB 696 * \brief Handles an MLME result (received frame) 697 * 698 * Filters the frame for roaming scans and passes it to the appropriate client 699 * 700 * \param hScanCncn - handle to the scan concentrator object 701 * \param bssid - a pointer to the address of the AP sending this frame 702 * \param frameInfo - the IE in the frame 703 * \param pRxAttr - a pointer to TNET RX attributes struct 704 * \param buffer - a pointer to the frame body 705 * \param bufferLength - the frame body length 706 * \return None 707 */ 708 void scanCncn_MlmeResultCB (TI_HANDLE hScanCncn, TMacAddr* bssid, mlmeFrameInfo_t* frameInfo, 709 TRxAttr* pRxAttr, TI_UINT8* buffer, TI_UINT16 bufferLength) 710 { 711 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 712 EScanCncnClient eClient; 713 TScanFrameInfo tScanFrameInfo; 714 TI_BOOL bValidResult = TI_TRUE; 715 716 /* get the scan client value from the scan tag */ 717 eClient = SCAN_CLIENT_FROM_TAG (pRxAttr->eScanTag); 718 719 /* increase scan result counter */ 720 pScanCncn->pScanClients[ eClient ]->uResultCounter++; 721 722 /* 723 * erroneous results are signaled by NULL pointers and are notified to the scan concentrator to 724 * update the counter only! 725 */ 726 if (NULL == bssid) 727 { 728 TRACE0(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_MlmeResultCB: received an empty frame notification from MLME\n"); 729 730 /* invalid resuilt */ 731 bValidResult = TI_FALSE; 732 } 733 /* are results valid so far (TI_TRUE == bValidResult) */ 734 else 735 { 736 TRACE6(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_MlmeResultCB: received frame from BBSID: %02x:%02x:%02x:%02x:%02x:%02x\n", (*bssid)[ 0 ], (*bssid)[ 1 ], (*bssid)[ 2 ], (*bssid)[ 3 ], (*bssid)[ 4 ], (*bssid)[ 5 ]); 737 738 /* If SSID IE is missing, discard the frame */ 739 if (frameInfo->content.iePacket.pSsid == NULL) 740 { 741 TRACE6(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_MlmeResultCB: discarding frame from BSSID: %02x:%02x:%02x:%02x:%02x:%02x, because SSID IE is missing!!\n", (*bssid)[ 0 ], (*bssid)[ 1 ], (*bssid)[ 2 ], (*bssid)[ 3 ], (*bssid)[ 4 ], (*bssid)[ 5 ]); 742 bValidResult = TI_FALSE; 743 } 744 745 /* If SSID length is 0 (hidden SSID) */ 746 else if (frameInfo->content.iePacket.pSsid->hdr[1] == 0) 747 { 748 /* Discard the frame unless it is application scan for any SSID - In this case we want to see also the hidden SSIDs*/ 749 if (!(((SCAN_SCC_APP_ONE_SHOT == eClient) || (SCAN_SCC_APP_PERIODIC == eClient)) && 750 pScanCncn->pScanClients[ eClient ]->uScanParams.tOneShotScanParams.desiredSsid.len == 0)) 751 { 752 TRACE6(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_MlmeResultCB: discarding frame from BSSID: %02x:%02x:%02x:%02x:%02x:%02x, because SSID is hidden (len=0)\n", (*bssid)[ 0 ], (*bssid)[ 1 ], (*bssid)[ 2 ], (*bssid)[ 3 ], (*bssid)[ 4 ], (*bssid)[ 5 ]); 753 bValidResult = TI_FALSE; 754 } 755 } 756 757 /* 758 * for roaming continuous and immediate, discard frames from current AP, 759 * or frames with SSID different than desired when the scan is NOT SPS 760 */ 761 else if ((SCAN_SCC_ROAMING_CONT == eClient) || (SCAN_SCC_ROAMING_IMMED == eClient)) 762 { 763 bssEntry_t *pCurrentAP; 764 765 pCurrentAP = apConn_getBSSParams(pScanCncn->hAPConn); 766 if(MAC_EQUAL(*bssid, pCurrentAP->BSSID) || 767 ((os_memoryCompare (pScanCncn->hOS, 768 (TI_UINT8*)frameInfo->content.iePacket.pSsid->serviceSetId, 769 (TI_UINT8*)pScanCncn->pScanClients[ eClient ]->uScanParams.tOneShotScanParams.desiredSsid.str, 770 pScanCncn->pScanClients[ eClient ]->uScanParams.tOneShotScanParams.desiredSsid.len)) && 771 pScanCncn->pScanClients[ eClient ]->uScanParams.tOneShotScanParams.scanType != SCAN_TYPE_SPS)) 772 { 773 TRACE6(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_MlmeResultCB: discarding frame from SSID: , BSSID: %02x:%02x:%02x:%02x:%02x:%02x, because SSID different from desired or from current AP!\n", (*bssid)[ 0 ], (*bssid)[ 1 ], (*bssid)[ 2 ], (*bssid)[ 3 ], (*bssid)[ 4 ], (*bssid)[ 5 ]); 774 bValidResult = TI_FALSE; 775 } 776 777 } 778 779 /* if rssi is lower than the Rssi threshold, discard frame */ 780 if ( pRxAttr->Rssi < pScanCncn->tInitParams.nRssiThreshold ) 781 { 782 TRACE7(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_MlmeResultCB: discarding frame from BSSID: %02x:%02x:%02x:%02x:%02x:%02x, because RSSI = %d\n", (*bssid)[ 0 ], (*bssid)[ 1 ], (*bssid)[ 2 ], (*bssid)[ 3 ], (*bssid)[ 4 ], (*bssid)[ 5 ], pRxAttr->Rssi); 783 bValidResult = TI_FALSE; 784 } 785 786 if(TI_TRUE == bValidResult) 787 { 788 /* build the scan frame info object */ 789 tScanFrameInfo.bssId = bssid; 790 tScanFrameInfo.band = (ERadioBand)pRxAttr->band; 791 tScanFrameInfo.channel = pRxAttr->channel; 792 tScanFrameInfo.parsedIEs = frameInfo; 793 tScanFrameInfo.rate = pRxAttr->Rate; 794 tScanFrameInfo.rssi = pRxAttr->Rssi; 795 tScanFrameInfo.snr = pRxAttr->SNR; 796 tScanFrameInfo.staTSF = pRxAttr->TimeStamp; 797 tScanFrameInfo.buffer = buffer; 798 tScanFrameInfo.bufferLength = bufferLength; 799 800 if (TI_TRUE == pScanCncn->tInitParams.bPushMode) 801 { 802 /* 803 * The scan found result, send a scan report event to the use with the frame parameters without save the result in the scan table 804 */ 805 EvHandlerSendEvent (pScanCncn->hEvHandler, IPC_EVENT_SCAN_REPORT, (TI_UINT8*)&tScanFrameInfo, sizeof(TScanFrameInfo)); 806 } 807 else 808 { 809 /* call the client result CB */ 810 pScanCncn->pScanClients[ eClient ]->tScanResultCB (pScanCncn->pScanClients[ eClient ]->hScanResultCBObj, 811 SCAN_CRS_RECEIVED_FRAME, &tScanFrameInfo, 0xffff ); /* SPS status is only valid on SPS scan complete */ 812 } 813 } 814 } 815 816 /* check if scan complete is pending for this frame for all results */ 817 if((TI_TRUE == pScanCncn->pScanClients[ eClient ]->bScanCompletePending) && 818 (pScanCncn->pScanClients[ eClient ]->uResultCounter == pScanCncn->pScanClients[ eClient ]->uResultExpectedNumber)) 819 { 820 TRACE1(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_MlmeResultCB: received frame number %d, scan complete pending, sending scan complet event\n", pScanCncn->pScanClients[ eClient ]->uResultCounter); 821 822 /* send a scan complete event to the client SM */ 823 genSM_Event (pScanCncn->pScanClients[ eClient ]->hGenSM, SCAN_CNCN_SM_EVENT_SCAN_COMPLETE, 824 (TI_HANDLE)pScanCncn->pScanClients[ eClient ]); 825 } 826 } 827 828 /** 829 * \fn scanCncn_ScrRoamingImmedCB 830 * \brief Called by SCR for immediate roaming client status change notification 831 * 832 * Handles status change by sending the appropriate SM event 833 * 834 * \param hScanCncn - handle to the scan concentrator object 835 * \param eRrequestStatus - the immediate scan for roaming client status 836 * \param eResource - the resource for which the CB is issued 837 * \param ePendreason - The reason for pend status, if the status is pend 838 * \return None 839 */ 840 void scanCncn_ScrRoamingImmedCB (TI_HANDLE hScanCncn, EScrClientRequestStatus eRequestStatus, 841 EScrResourceId eResource, EScePendReason ePendReason) 842 { 843 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 844 845 TRACE3(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_ScrRoamingImmedCB: status: %d, resource: %d pend reason: %d\n", eRequestStatus, eResource, ePendReason); 846 847 /* act according to the request staus */ 848 switch (eRequestStatus) 849 { 850 case SCR_CRS_RUN: 851 /* send an SCR run event to the SM */ 852 genSM_Event (pScanCncn->pScanClients[ SCAN_SCC_ROAMING_IMMED ]->hGenSM, SCAN_CNCN_SM_EVENT_RUN, 853 (TI_HANDLE)pScanCncn->pScanClients[ SCAN_SCC_ROAMING_IMMED ]); 854 break; 855 856 case SCR_CRS_PEND: 857 /* if pending reason has changed to different group - send a reject event 858 (should only happen when pending) */ 859 if ( SCR_PR_DIFFERENT_GROUP_RUNNING == ePendReason ) 860 { 861 /* send an SCR reject event to the SM - would not scan when not performing roaming */ 862 pScanCncn->pScanClients[ SCAN_SCC_ROAMING_IMMED ]->eScanResult = SCAN_CRS_SCAN_FAILED; 863 genSM_Event (pScanCncn->pScanClients[ SCAN_SCC_ROAMING_IMMED ]->hGenSM, SCAN_CNCN_SM_EVENT_REJECT, 864 (TI_HANDLE)pScanCncn->pScanClients[ SCAN_SCC_ROAMING_IMMED ]); 865 } 866 break; 867 868 case SCR_CRS_FW_RESET: 869 /* if no previous error has occurred, change the state to FW reset */ 870 if (SCAN_CRS_SCAN_COMPLETE_OK == pScanCncn->pScanClients[ SCAN_SCC_ROAMING_IMMED ]->eScanResult) 871 { 872 pScanCncn->pScanClients[ SCAN_SCC_ROAMING_IMMED ]->eScanResult = SCAN_CRS_SCAN_ABORTED_FW_RESET; 873 } 874 875 /* send a recovery event to the SM */ 876 genSM_Event (pScanCncn->pScanClients[ SCAN_SCC_ROAMING_IMMED ]->hGenSM, SCAN_CNCN_SM_EVENT_RECOVERY, 877 (TI_HANDLE)pScanCncn->pScanClients[ SCAN_SCC_ROAMING_IMMED ]); 878 break; 879 880 case SCR_CRS_ABORT: 881 /* This should never happen, report error */ 882 default: 883 TRACE1(pScanCncn->hReport, REPORT_SEVERITY_ERROR , "scanCncn_ScrRoamingImmedCB: Illegal SCR request status: %d.\n", eRequestStatus); 884 break; 885 } 886 } 887 888 /** 889 * \fn scanCncn_ScrRoamingContCB 890 * \brief Called by SCR for continuous roaming client status change notification 891 * 892 * Handles status change by sending the appropriate SM event 893 * 894 * \param hScanCncn - handle to the scan concentrator object 895 * \param eRrequestStatus - the continuous scan for roaming client status 896 * \param eResource - the resource for which the CB is issued 897 * \param ePendreason - The reason for pend status, if the status is pend 898 * \return None 899 */ 900 void scanCncn_ScrRoamingContCB (TI_HANDLE hScanCncn, EScrClientRequestStatus eRequestStatus, 901 EScrResourceId eResource, EScePendReason ePendReason) 902 { 903 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 904 905 TRACE3(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_ScrRoamingContCB: status: %d, resource: %d pend reason: %d\n", eRequestStatus, eResource, ePendReason); 906 907 /* act according to the request staus */ 908 switch (eRequestStatus) 909 { 910 case SCR_CRS_RUN: 911 /* send an SCR run event to the SM */ 912 genSM_Event (pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]->hGenSM, SCAN_CNCN_SM_EVENT_RUN, 913 (TI_HANDLE)pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]); 914 break; 915 916 case SCR_CRS_PEND: 917 /* if pending reason has changed to different group - send a reject event (should only happen when pending) */ 918 if ( SCR_PR_DIFFERENT_GROUP_RUNNING == ePendReason ) 919 { 920 pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]->eScanResult = SCAN_CRS_SCAN_FAILED; 921 genSM_Event (pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]->hGenSM, SCAN_CNCN_SM_EVENT_REJECT, 922 (TI_HANDLE)pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]); 923 } 924 break; 925 926 case SCR_CRS_FW_RESET: 927 /* if no previous error has occurred, change the state to FW reset */ 928 if (SCAN_CRS_SCAN_COMPLETE_OK == pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]->eScanResult) 929 { 930 pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]->eScanResult = SCAN_CRS_SCAN_ABORTED_FW_RESET; 931 } 932 933 /* send a recovery event to the SM */ 934 genSM_Event (pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]->hGenSM, SCAN_CNCN_SM_EVENT_RECOVERY, 935 (TI_HANDLE)pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]); 936 break; 937 938 939 case SCR_CRS_ABORT: 940 /* mark not to send NULL data when scan is stopped */ 941 pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]->bSendNullDataOnStop = TI_FALSE; 942 943 /* if no previous error has occurred, change the result to abort */ 944 if (SCAN_CRS_SCAN_COMPLETE_OK == pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]->eScanResult) 945 { 946 pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]->eScanResult = SCAN_CRS_SCAN_ABORTED_HIGHER_PRIORITY; 947 } 948 949 /* send an abort scan event to the SM */ 950 genSM_Event (pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]->hGenSM, SCAN_CNCN_SM_EVENT_ABORT, 951 (TI_HANDLE)pScanCncn->pScanClients[ SCAN_SCC_ROAMING_CONT ]); 952 break; 953 954 default: 955 TRACE1(pScanCncn->hReport, REPORT_SEVERITY_ERROR , "scanCncn_ScrRoamingContCB: Illegal SCR request status: %d.\n", eRequestStatus); 956 break; 957 } 958 } 959 960 /** 961 * \fn scanCncn_ScrAppCB 962 * \brief Called by SCR for application scan client status change notification 963 * 964 * Handles status change by sending the appropriate SM event 965 * 966 * \note this function is used by the SCR for both one-shot and periodic application scan 967 * \param hScanCncn - handle to the scan concentrator object 968 * \param eRrequestStatus - the application scan client status 969 * \param eResource - the resource for which the CB is issued 970 * \param ePendreason - The reason for pend status, if the status is pend 971 * \return None 972 */ 973 void scanCncn_ScrAppCB (TI_HANDLE hScanCncn, EScrClientRequestStatus eRequestStatus, 974 EScrResourceId eResource, EScePendReason ePendReason ) 975 { 976 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 977 EScanCncnClient eClient; 978 979 TRACE3(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_ScrAppCB: status: %d, resource: %d pend reason: %d\n", eRequestStatus, eResource, ePendReason); 980 981 /* set client according to SCr resource */ 982 if (SCR_RESOURCE_PERIODIC_SCAN == eResource) 983 { 984 eClient = SCAN_SCC_APP_PERIODIC; 985 } 986 else 987 { 988 eClient = SCAN_SCC_APP_ONE_SHOT; 989 } 990 991 /* act according to the request staus */ 992 switch (eRequestStatus) 993 { 994 /* 995 * Note: pend is not handled because application scan cancel its scan request when it receives pend 996 * as the SCR request result, and thus it is assumed that the application scan request will never be 997 * pending 998 */ 999 case SCR_CRS_RUN: 1000 /* send an SCR run event to the SM */ 1001 genSM_Event (pScanCncn->pScanClients[ eClient ]->hGenSM, SCAN_CNCN_SM_EVENT_RUN, 1002 (TI_HANDLE)pScanCncn->pScanClients[ eClient ]); 1003 break; 1004 1005 case SCR_CRS_FW_RESET: 1006 /* if no previous error has occurred, change the state to FW reset */ 1007 if (SCAN_CRS_SCAN_COMPLETE_OK == pScanCncn->pScanClients[ eClient ]->eScanResult) 1008 { 1009 pScanCncn->pScanClients[ eClient ]->eScanResult = SCAN_CRS_SCAN_ABORTED_FW_RESET; 1010 } 1011 1012 /* send a recovery event to the SM */ 1013 genSM_Event (pScanCncn->pScanClients[ eClient ]->hGenSM, SCAN_CNCN_SM_EVENT_RECOVERY, 1014 (TI_HANDLE)pScanCncn->pScanClients[ eClient ]); 1015 break; 1016 1017 case SCR_CRS_ABORT: 1018 /* mark not to send NULL data when scan is stopped */ 1019 pScanCncn->pScanClients[ eClient ]->bSendNullDataOnStop = TI_FALSE; 1020 1021 /* if no previous error has occurred, change the result to abort */ 1022 if (SCAN_CRS_SCAN_COMPLETE_OK == pScanCncn->pScanClients[ eClient ]->eScanResult) 1023 { 1024 pScanCncn->pScanClients[ eClient ]->eScanResult = SCAN_CRS_SCAN_ABORTED_HIGHER_PRIORITY; 1025 } 1026 1027 /* send an abort scan event to the SM */ 1028 genSM_Event (pScanCncn->pScanClients[ eClient ]->hGenSM, SCAN_CNCN_SM_EVENT_ABORT, 1029 (TI_HANDLE)pScanCncn->pScanClients[ eClient ]); 1030 break; 1031 1032 default: 1033 TRACE1(pScanCncn->hReport, REPORT_SEVERITY_ERROR , "scanCncn_ScrAppCB: Illegal SCR request status: %d.\n", eRequestStatus); 1034 break; 1035 } 1036 } 1037 1038 /** 1039 * \fn scanCncn_ScrDriverCB 1040 * \brief Called by SCR for driver scan client status change notification 1041 * 1042 * Handles status change by sending the appropriate SM event 1043 * 1044 * \param hScanCncn - handle to the scan concentrator object 1045 * \param eRrequestStatus - the driver scan client status 1046 * \param eResource - the resource for which the CB is issued 1047 * \param ePendreason - The reason for pend status, if the status is pend 1048 * \return None 1049 */ 1050 void scanCncn_ScrDriverCB (TI_HANDLE hScanCncn, EScrClientRequestStatus eRequestStatus, 1051 EScrResourceId eResource, EScePendReason ePendReason) 1052 { 1053 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 1054 1055 TRACE3(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_ScrDriverCB: status: %d, resource: %d pend reason: %d\n", eRequestStatus, eResource, ePendReason); 1056 1057 /* act according to the request staus */ 1058 switch (eRequestStatus) 1059 { 1060 case SCR_CRS_RUN: 1061 /* send the next event to the SM */ 1062 genSM_Event (pScanCncn->pScanClients[ SCAN_SCC_DRIVER ]->hGenSM, SCAN_CNCN_SM_EVENT_RUN, 1063 (TI_HANDLE)pScanCncn->pScanClients[ SCAN_SCC_DRIVER ]); 1064 break; 1065 1066 case SCR_CRS_PEND: 1067 /* if pending reason has changed to different group - send a reject event (should only happen when pending) */ 1068 if ( SCR_PR_DIFFERENT_GROUP_RUNNING == ePendReason ) 1069 { 1070 pScanCncn->pScanClients[ SCAN_SCC_DRIVER ]->eScanResult = SCAN_CRS_SCAN_FAILED; 1071 genSM_Event (pScanCncn->pScanClients[ SCAN_SCC_DRIVER ]->hGenSM, SCAN_CNCN_SM_EVENT_REJECT, 1072 (TI_HANDLE)pScanCncn->pScanClients[ SCAN_SCC_DRIVER ]); 1073 } 1074 break; 1075 1076 case SCR_CRS_FW_RESET: 1077 /* if no previous error has occurred, change the state to FW reset */ 1078 if (SCAN_CRS_SCAN_COMPLETE_OK == pScanCncn->pScanClients[ SCAN_SCC_DRIVER ]->eScanResult) 1079 { 1080 pScanCncn->pScanClients[ SCAN_SCC_DRIVER ]->eScanResult = SCAN_CRS_SCAN_ABORTED_FW_RESET; 1081 } 1082 1083 /* send a recovery event to the SM */ 1084 genSM_Event (pScanCncn->pScanClients[ SCAN_SCC_DRIVER ]->hGenSM, SCAN_CNCN_SM_EVENT_RECOVERY, 1085 (TI_HANDLE)pScanCncn->pScanClients[ SCAN_SCC_DRIVER ]); 1086 break; 1087 1088 case SCR_CRS_ABORT: 1089 /* This should never happen, report error */ 1090 default: 1091 TRACE1(pScanCncn->hReport, REPORT_SEVERITY_ERROR , "scanCncn_ScrDriverCB: Illegal SCR request status: %d.\n", eRequestStatus); 1092 break; 1093 } 1094 } 1095 1096 /** 1097 * \fn scanCncn_VerifyChannelsWithRegDomain 1098 * \brief Verifies channel validity and TX power with the reg. domain 1099 * 1100 * Verifies channel validity and TX power with the reg. domain. Removes invalid channels. 1101 * 1102 * \param hScanCncn - handle to the scan concentrator object 1103 * \param puScanParams - a pointer to the scan parmeters union 1104 * \param bPeriodicScan - TRUE if the parameters are for periodic scan, FALSE if for one-shot scan 1105 * \return None 1106 */ 1107 void scanCncn_VerifyChannelsWithRegDomain (TI_HANDLE hScanCncn, UScanParams *puScanParams, TI_BOOL bPeriodicScan) 1108 { 1109 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 1110 paramInfo_t *pParam; 1111 paramInfo_t tDfsParam; 1112 TI_UINT8 i, uChannelNum; 1113 1114 pParam = (paramInfo_t *)os_memoryAlloc(pScanCncn->hOS, sizeof(paramInfo_t)); 1115 if (!pParam) { 1116 return; 1117 } 1118 1119 /* get channel number according to scan type */ 1120 if (TI_TRUE == bPeriodicScan) 1121 { 1122 uChannelNum = puScanParams->tPeriodicScanParams.uChannelNum; 1123 } 1124 else 1125 { 1126 uChannelNum = puScanParams->tOneShotScanParams.numOfChannels; 1127 } 1128 1129 /* check channels */ 1130 for (i = 0; i < uChannelNum; ) 1131 { /* Note that i is only increased when channel is valid - if channel is invalid, another 1132 channel is copied in its place, and thus the same index should be checked again. However, 1133 since the number of channels is decreased, the loop end condition is getting nearer! */ 1134 pParam->paramType = REGULATORY_DOMAIN_GET_SCAN_CAPABILITIES; 1135 if (TI_TRUE == bPeriodicScan) 1136 { 1137 /* set band and scan type for periodic scan */ 1138 pParam->content.channelCapabilityReq.band = puScanParams->tPeriodicScanParams.tChannels[ i ].eBand; 1139 if (puScanParams->tPeriodicScanParams.tChannels[ i ].eScanType == SCAN_TYPE_NORMAL_PASSIVE) 1140 { 1141 pParam->content.channelCapabilityReq.scanOption = PASSIVE_SCANNING; 1142 } 1143 else 1144 { 1145 /* query the reg. domain whether this is a DFS channel */ 1146 tDfsParam.paramType = REGULATORY_DOMAIN_IS_DFS_CHANNEL; 1147 tDfsParam.content.tDfsChannel.eBand = puScanParams->tPeriodicScanParams.tChannels[ i ].eBand; 1148 tDfsParam.content.tDfsChannel.uChannel = puScanParams->tPeriodicScanParams.tChannels[ i ].uChannel; 1149 regulatoryDomain_getParam (pScanCncn->hRegulatoryDomain, &tDfsParam); 1150 1151 /* if this is a DFS channel */ 1152 if (TI_TRUE == tDfsParam.content.tDfsChannel.bDfsChannel) 1153 { 1154 /* 1155 * DFS channels are first scanned passive and than active, so reg. domain can only validate 1156 * these channels for pasiive scanning at the moment 1157 */ 1158 pParam->content.channelCapabilityReq.scanOption = PASSIVE_SCANNING; 1159 1160 /* set the channel scan type to DFS */ 1161 puScanParams->tPeriodicScanParams.tChannels[ i ].eScanType = SCAN_TYPE_PACTSIVE; 1162 /* passive scan time is passed for all channels to the TWD, and copied there to the FW */ 1163 } 1164 else 1165 { 1166 pParam->content.channelCapabilityReq.scanOption = ACTIVE_SCANNING; 1167 } 1168 } 1169 1170 /* set channel for periodic scan */ 1171 pParam->content.channelCapabilityReq.channelNum = 1172 puScanParams->tPeriodicScanParams.tChannels[ i ].uChannel; 1173 regulatoryDomain_getParam (pScanCncn->hRegulatoryDomain, pParam); 1174 if (TI_FALSE == pParam->content.channelCapabilityRet.channelValidity) 1175 { /* channel not allowed - copy the rest of the channel in its place */ 1176 os_memoryCopy (pScanCncn->hOS, &(puScanParams->tPeriodicScanParams.tChannels[ i ]), 1177 &(puScanParams->tPeriodicScanParams.tChannels[ i + 1 ]), 1178 sizeof(TPeriodicChannelEntry) * (puScanParams->tPeriodicScanParams.uChannelNum - i - 1)); 1179 puScanParams->tPeriodicScanParams.uChannelNum--; 1180 uChannelNum--; 1181 } 1182 else 1183 { 1184 /* also set the power level to the minimumm between requested power and allowed power */ 1185 puScanParams->tPeriodicScanParams.tChannels[ i ].uTxPowerLevelDbm = 1186 TI_MIN( pParam->content.channelCapabilityRet.maxTxPowerDbm, 1187 puScanParams->tPeriodicScanParams.tChannels[ i ].uTxPowerLevelDbm ); 1188 1189 i += 1; 1190 } 1191 } 1192 else 1193 { 1194 /* set band and scan type for one-shot scan */ 1195 pParam->content.channelCapabilityReq.band = puScanParams->tOneShotScanParams.band; 1196 if ((puScanParams->tOneShotScanParams.scanType == SCAN_TYPE_NORMAL_PASSIVE) || 1197 (puScanParams->tOneShotScanParams.scanType == SCAN_TYPE_TRIGGERED_PASSIVE) || 1198 (puScanParams->tOneShotScanParams.scanType == SCAN_TYPE_SPS)) 1199 { 1200 pParam->content.channelCapabilityReq.scanOption = PASSIVE_SCANNING; 1201 } 1202 else 1203 { 1204 pParam->content.channelCapabilityReq.scanOption = ACTIVE_SCANNING; 1205 } 1206 1207 /* set channel for one-shot scan - SPS */ 1208 if (SCAN_TYPE_SPS == puScanParams->tOneShotScanParams.scanType) 1209 { 1210 pParam->content.channelCapabilityReq.channelNum = 1211 puScanParams->tOneShotScanParams.channelEntry[ i ].SPSChannelEntry.channel; 1212 regulatoryDomain_getParam (pScanCncn->hRegulatoryDomain, pParam); 1213 if (TI_FALSE == pParam->content.channelCapabilityRet.channelValidity) 1214 { /* channel not allowed - copy the rest of the channel in its place */ 1215 os_memoryCopy (pScanCncn->hOS, &(puScanParams->tOneShotScanParams.channelEntry[ i ]), 1216 &(puScanParams->tOneShotScanParams.channelEntry[ i + 1 ]), 1217 sizeof(TScanSpsChannelEntry) * (puScanParams->tOneShotScanParams.numOfChannels - i - 1)); 1218 puScanParams->tOneShotScanParams.numOfChannels--; 1219 uChannelNum--; 1220 } 1221 else 1222 { 1223 i += 1; 1224 } 1225 1226 } 1227 /* set channel for one-shot scan - all other scan types */ 1228 else 1229 { 1230 pParam->content.channelCapabilityReq.channelNum = 1231 puScanParams->tOneShotScanParams.channelEntry[ i ].normalChannelEntry.channel; 1232 regulatoryDomain_getParam (pScanCncn->hRegulatoryDomain, pParam); 1233 if (TI_FALSE == pParam->content.channelCapabilityRet.channelValidity) 1234 { /* channel not allowed - copy the rest of the channel in its place */ 1235 os_memoryCopy (pScanCncn->hOS, &(puScanParams->tOneShotScanParams.channelEntry[ i ]), 1236 &(puScanParams->tOneShotScanParams.channelEntry[ i + 1 ]), 1237 sizeof(TScanNormalChannelEntry) * (puScanParams->tOneShotScanParams.numOfChannels - i - 1)); 1238 puScanParams->tOneShotScanParams.numOfChannels--; 1239 uChannelNum--; 1240 } 1241 else 1242 { 1243 puScanParams->tOneShotScanParams.channelEntry[i].normalChannelEntry.txPowerDbm = 1244 TI_MIN (pParam->content.channelCapabilityRet.maxTxPowerDbm, 1245 puScanParams->tOneShotScanParams.channelEntry[i].normalChannelEntry.txPowerDbm); 1246 i += 1; 1247 } 1248 } 1249 } 1250 } 1251 os_memoryFree(pScanCncn->hOS, pParam, sizeof(paramInfo_t)); 1252 } 1253 1254 /** 1255 * \fn scanCncn_SGconfigureScanParams 1256 * \brief Configures Bluetooth coexistence compensation paramters 1257 * 1258 * Configures Bluetooth coexistence compensation paramters. 1259 * This function is called when SG is enabled or disabled from the SoftGemini module. 1260 * The compensation is needed since BT Activity holds the antenna and over-ride Scan activity 1261 * 1262 * \param hScanCncn - handle to the scan concentrator object.\n 1263 * \param bUseSGParams - whether to use the new parameters (TI_TRUE when SG is enabled) 1264 * \param probeReqPercent - increasing num probe requests in that percentage 1265 * \param SGcompensationMaxTime - max value from which we won't increase dwelling time 1266 * \param SGcompensationPercent - increasing dwell time in that percentage 1267 * \return None 1268 * \sa scanCncn_SGupdateScanParams 1269 */ 1270 void scanCncn_SGconfigureScanParams (TI_HANDLE hScanCncn, TI_BOOL bUseSGParams, 1271 TI_UINT8 probeReqPercent, TI_UINT32 SGcompensationMaxTime, 1272 TI_UINT32 SGcompensationPercent) 1273 { 1274 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 1275 1276 pScanCncn->bUseSGParams = bUseSGParams; 1277 pScanCncn->uSGprobeRequestPercent = probeReqPercent; 1278 pScanCncn->uSGcompensationMaxTime = SGcompensationMaxTime; 1279 pScanCncn->uSGcompensationPercent = SGcompensationPercent; 1280 1281 TRACE4(pScanCncn->hReport, REPORT_SEVERITY_INFORMATION , "scanCncn_SGconfigureScanParams: bUseSGParams=%d, numOfProbeRequest=%d, compensationMaxTime=%d, SGcompensationPercent=%d\n", pScanCncn->bUseSGParams, pScanCncn->uSGprobeRequestPercent, pScanCncn->uSGcompensationMaxTime, pScanCncn->uSGcompensationPercent); 1282 } 1283 1284 /** 1285 * \fn scanCncn_SGupdateScanParams 1286 * \brief Updates dwell times and probe request number to compensate for bluetooth transmissions 1287 * 1288 * Updates dwell times and probe request number to compensate for bluetooth transmissions 1289 * 1290 * \param hScanCncn - handle to the scan concentrator object 1291 * \param puScanParams - a pointer to the scan parmeters union 1292 * \param bPeriodicScan - TRUE if the parameters are for periodic scan, FALSE if for one-shot scan 1293 * \return None 1294 * \sa scanCncn_SGconfigureScanParams 1295 */ 1296 void scanCncn_SGupdateScanParams (TI_HANDLE hScanCncn, UScanParams *puScanParams, TI_BOOL bPeriodicScan) 1297 { 1298 TScanCncn *pScanCncn = (TScanCncn*)hScanCncn; 1299 TI_UINT32 i, uTempTime; 1300 1301 /* one shot scan */ 1302 if (TI_FALSE == bPeriodicScan) 1303 { 1304 /* get a pointer to the one-shot scan params */ 1305 TScanParams *pScanParams = &(puScanParams->tOneShotScanParams); 1306 1307 /* for each channel increase the min and max dwell time */ 1308 for (i = 0; i < pScanParams->numOfChannels; i++) 1309 { 1310 /* SPS scan */ 1311 if (SCAN_TYPE_SPS == pScanParams->scanType) 1312 { 1313 if (pScanCncn->uSGcompensationMaxTime > 1314 pScanParams->channelEntry[i].SPSChannelEntry.scanDuration) 1315 { 1316 uTempTime = ((pScanParams->channelEntry[i].SPSChannelEntry.scanDuration) * 1317 (100 + pScanCncn->uSGcompensationPercent)) / 100 ; 1318 1319 if (uTempTime > pScanCncn->uSGcompensationMaxTime) 1320 { 1321 uTempTime = pScanCncn->uSGcompensationMaxTime; 1322 } 1323 pScanParams->channelEntry[i].SPSChannelEntry.scanDuration = uTempTime; 1324 } 1325 } 1326 /* all other scan types */ 1327 else 1328 { 1329 if (pScanCncn->uSGcompensationMaxTime > 1330 pScanParams->channelEntry[i].normalChannelEntry.minChannelDwellTime) 1331 { 1332 uTempTime = ((pScanParams->channelEntry[i].normalChannelEntry.minChannelDwellTime) * 1333 (100 + pScanCncn->uSGcompensationPercent)) / 100 ; 1334 1335 if (uTempTime > pScanCncn->uSGcompensationMaxTime) 1336 { 1337 uTempTime = pScanCncn->uSGcompensationMaxTime; 1338 } 1339 pScanParams->channelEntry[i].normalChannelEntry.minChannelDwellTime = uTempTime; 1340 } 1341 1342 if (pScanCncn->uSGcompensationMaxTime > 1343 pScanParams->channelEntry[i].normalChannelEntry.maxChannelDwellTime) 1344 { 1345 uTempTime = ((pScanParams->channelEntry[i].normalChannelEntry.maxChannelDwellTime) * 1346 (100 + pScanCncn->uSGcompensationPercent)) / 100 ; 1347 1348 if (uTempTime > pScanCncn->uSGcompensationMaxTime) 1349 { 1350 uTempTime = pScanCncn->uSGcompensationMaxTime; 1351 } 1352 pScanParams->channelEntry[i].normalChannelEntry.maxChannelDwellTime = uTempTime; 1353 } 1354 } 1355 } 1356 1357 /* update ProbeReqNumber by SG percantage */ 1358 if (pScanParams->probeReqNumber > 0) 1359 { 1360 pScanParams->probeReqNumber = ((pScanParams->probeReqNumber) * 1361 (100 + pScanCncn->uSGprobeRequestPercent)) / 100 ; 1362 } 1363 } 1364 /* periodic scan */ 1365 else 1366 { 1367 TPeriodicScanParams *pPeriodicScanParams = &(puScanParams->tPeriodicScanParams); 1368 1369 /* for each channel increase the min and max dwell time */ 1370 for (i = 0; i < pPeriodicScanParams->uChannelNum; i++) 1371 { 1372 if (pScanCncn->uSGcompensationMaxTime > 1373 pPeriodicScanParams->tChannels[ i ].uMinDwellTimeMs) 1374 { 1375 uTempTime = ((pPeriodicScanParams->tChannels[ i ].uMinDwellTimeMs) * 1376 (100 + pScanCncn->uSGcompensationPercent)) / 100 ; 1377 1378 if (uTempTime > pScanCncn->uSGcompensationMaxTime) 1379 { 1380 uTempTime = pScanCncn->uSGcompensationMaxTime; 1381 } 1382 pPeriodicScanParams->tChannels[ i ].uMinDwellTimeMs = uTempTime; 1383 } 1384 1385 if (pScanCncn->uSGcompensationMaxTime > 1386 pPeriodicScanParams->tChannels[ i ].uMaxDwellTimeMs) 1387 { 1388 uTempTime = ((pPeriodicScanParams->tChannels[ i ].uMaxDwellTimeMs) * 1389 (100 + pScanCncn->uSGcompensationPercent)) / 100 ; 1390 1391 if (uTempTime > pScanCncn->uSGcompensationMaxTime) 1392 { 1393 uTempTime = pScanCncn->uSGcompensationMaxTime; 1394 } 1395 pPeriodicScanParams->tChannels[ i ].uMaxDwellTimeMs = uTempTime; 1396 } 1397 } 1398 1399 /* update ProbeReqNumber by SG percantage */ 1400 if (pPeriodicScanParams->uProbeRequestNum > 0) 1401 { 1402 pPeriodicScanParams->uProbeRequestNum = ((pPeriodicScanParams->uProbeRequestNum) * 1403 (100 + pScanCncn->uSGprobeRequestPercent)) / 100 ; 1404 } 1405 } 1406 } 1407 1408 /** 1409 * \fn scanCncn_Mix1ShotScanChannels 1410 * \brief Mix the channel order in a 1 Shot Scan channel array. 1411 * 1412 * Mix the channel order in a 1 Shot Scan channel array. 1413 * 1414 * \param pChannelArray - where to store allowed channels information 1415 * \param uValidChannelsCount - Number of allowed channels (that were placed in the given channels array) 1416 * \return None 1417 */ 1418 static void scanCncn_Mix1ShotScanChannels (TScanChannelEntry *pChannelArray, TI_UINT32 uValidChannelsCount) 1419 { 1420 TI_UINT32 i; 1421 TScanChannelEntry tTempArray[MAX_CHANNEL_IN_BAND_2_4]; 1422 1423 if (uValidChannelsCount <= MIN_CHANNEL_IN_BAND_2_4) 1424 { 1425 return; 1426 } 1427 1428 if (uValidChannelsCount > MAX_CHANNEL_IN_BAND_2_4) 1429 { 1430 uValidChannelsCount = MAX_CHANNEL_IN_BAND_2_4; 1431 } 1432 1433 /* 1434 * Create new Channels Array that will mix the channels 1435 * something like: 1,8,2,9,3,10,4,11,5,12,6,13,7,14 1436 * For odd number of channels, the last channel will be adjacent, but never mind... 1437 */ 1438 for (i = 0 ; i < uValidChannelsCount - 1 ; i+=2) 1439 { 1440 tTempArray[i] = pChannelArray[i/2]; 1441 tTempArray[i+1] = pChannelArray[(uValidChannelsCount+i)/2]; 1442 } 1443 1444 /* if this is the last odd channel */ 1445 if ((i + 1) == uValidChannelsCount) 1446 { 1447 tTempArray[i] = tTempArray[i - 1]; 1448 tTempArray[i - 1] = pChannelArray[uValidChannelsCount - 1]; 1449 } 1450 1451 /* Now copy to the real array */ 1452 for (i = 0 ; i < uValidChannelsCount; i++) 1453 { 1454 pChannelArray[i] = tTempArray[i]; 1455 } 1456 } 1457 1458 1459 /** 1460 * \fn scanCncn_MixPeriodicScanChannels 1461 * \brief Mix the channel order in a Periodic Scan channel 1462 * array. 1463 * 1464 * Mix the channel order in a Periodic Scan channel array. 1465 * 1466 * \param pChannelArray - where to store allowed channels information 1467 * \param uValidChannelsCount - Number of allowed channels (that were placed in the given channels array) 1468 * \return None 1469 */ 1470 static void scanCncn_MixPeriodicScanChannels (TPeriodicChannelEntry *pChannelArray, TI_UINT32 uValidChannelsCount) 1471 { 1472 TI_UINT32 i; 1473 TPeriodicChannelEntry tTempArray[MAX_CHANNEL_IN_BAND_2_4]; 1474 1475 if (uValidChannelsCount <= MIN_CHANNEL_IN_BAND_2_4) 1476 { 1477 return; 1478 } 1479 1480 if (uValidChannelsCount > MAX_CHANNEL_IN_BAND_2_4) 1481 { 1482 uValidChannelsCount = MAX_CHANNEL_IN_BAND_2_4; 1483 } 1484 1485 /* 1486 * Create new Channels Array that will mix the channels 1487 * something like: 1,8,2,9,3,10,4,11,5,12,6,13,7,14 1488 * For odd number of channels, the last channel will be adjacent, but never mind... 1489 */ 1490 for (i = 0 ; i < uValidChannelsCount - 1 ; i+=2) 1491 { 1492 tTempArray[i] = pChannelArray[i/2]; 1493 tTempArray[i+1] = pChannelArray[(uValidChannelsCount+i)/2]; 1494 } 1495 1496 /* if this is the last odd channel */ 1497 if ((i + 1) == uValidChannelsCount) 1498 { 1499 tTempArray[i] = tTempArray[i - 1]; 1500 tTempArray[i - 1] = pChannelArray[uValidChannelsCount - 1]; 1501 } 1502 1503 /* Now copy to the real array */ 1504 for (i = 0 ; i < uValidChannelsCount; i++) 1505 { 1506 pChannelArray[i] = tTempArray[i]; 1507 } 1508 } 1509