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