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