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