Home | History | Annotate | Download | only in Sta_Management
      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