• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
scanCncn_Create(TI_HANDLE hOS)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  */
scanCncn_Destroy(TI_HANDLE hScanCncn)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  */
scanCncn_Init(TStadHandlesList * pStadHandles)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  */
scanCncn_SetDefaults(TI_HANDLE hScanCncn,TScanCncnInitParams * pScanCncnInitParams)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  */
scanCncn_SwitchToConnected(TI_HANDLE hScanCncn)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  */
scanCncn_SwitchToNotConnected(TI_HANDLE hScanCncn)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  */
scanCncn_SwitchToIBSS(TI_HANDLE hScanCncn)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 
scanCncn_Start1ShotScan(TI_HANDLE hScanCncn,EScanCncnClient eClient,TScanParams * pScanParams)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 
scanCncn_StopScan(TI_HANDLE hScanCncn,EScanCncnClient eClient)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  */
scanCncn_StartPeriodicScan(TI_HANDLE hScanCncn,EScanCncnClient eClient,TPeriodicScanParams * pScanParams)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  */
scanCncn_StopPeriodicScan(TI_HANDLE hScanCncn,EScanCncnClient eClient)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 
scanCncn_RegisterScanResultCB(TI_HANDLE hScanCncn,EScanCncnClient eClient,TScanResultCB scanResultCBFunc,TI_HANDLE scanResultCBObj)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  */
scanCncn_ScanCompleteNotificationCB(TI_HANDLE hScanCncn,EScanResultTag eTag,TI_UINT32 uResultCount,TI_UINT16 SPSStatus,TI_BOOL bTSFError,TI_STATUS scanStatus,TI_STATUS PSMode)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  */
scanCncn_PeriodicScanReportCB(TI_HANDLE hScanCncn,char * str,TI_UINT32 strLen)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  */
scanCncn_PeriodicScanCompleteCB(TI_HANDLE hScanCncn,char * str,TI_UINT32 strLen)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  */
scanCncn_MlmeResultCB(TI_HANDLE hScanCncn,TMacAddr * bssid,mlmeFrameInfo_t * frameInfo,TRxAttr * pRxAttr,TI_UINT8 * buffer,TI_UINT16 bufferLength)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  */
scanCncn_ScrRoamingImmedCB(TI_HANDLE hScanCncn,EScrClientRequestStatus eRequestStatus,EScrResourceId eResource,EScePendReason ePendReason)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  */
scanCncn_ScrRoamingContCB(TI_HANDLE hScanCncn,EScrClientRequestStatus eRequestStatus,EScrResourceId eResource,EScePendReason ePendReason)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  */
scanCncn_ScrAppCB(TI_HANDLE hScanCncn,EScrClientRequestStatus eRequestStatus,EScrResourceId eResource,EScePendReason ePendReason)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  */
scanCncn_ScrDriverCB(TI_HANDLE hScanCncn,EScrClientRequestStatus eRequestStatus,EScrResourceId eResource,EScePendReason ePendReason)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  */
scanCncn_VerifyChannelsWithRegDomain(TI_HANDLE hScanCncn,UScanParams * puScanParams,TI_BOOL bPeriodicScan)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  */
scanCncn_SGconfigureScanParams(TI_HANDLE hScanCncn,TI_BOOL bUseSGParams,TI_UINT8 probeReqPercent,TI_UINT32 SGcompensationMaxTime,TI_UINT32 SGcompensationPercent)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  */
scanCncn_SGupdateScanParams(TI_HANDLE hScanCncn,UScanParams * puScanParams,TI_BOOL bPeriodicScan)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  */
scanCncn_Mix1ShotScanChannels(TScanChannelEntry * pChannelArray,TI_UINT32 uValidChannelsCount)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  */
scanCncn_MixPeriodicScanChannels(TPeriodicChannelEntry * pChannelArray,TI_UINT32 uValidChannelsCount)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