1/*
2 * ScanSrv.c
3 *
4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 *  * Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *  * Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in
15 *    the documentation and/or other materials provided with the
16 *    distribution.
17 *  * Neither the name Texas Instruments nor the names of its
18 *    contributors may be used to endorse or promote products derived
19 *    from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/** \file ScanSrv.c
35 *  \brief This file include the scan SRV module implementation
36 *
37 *  \see   ScanSrv.h, ScanSrvSm.h, ScanSrvSm.c
38 */
39
40
41#define __FILE_ID__  FILE_ID_115
42#include "report.h"
43#include "timer.h"
44#include "ScanSrv.h"
45#include "ScanSrvSM.h"
46#include "MacServices.h"
47#include "MacServices_api.h"
48#include "eventMbox_api.h"
49#include "CmdBld.h"
50
51/**
52 * \\n
53 * \date 16-Oct-2004\n
54 * \brief Creates the scan SRV object
55 *
56 * Function Scope \e Public.\n
57 * \param hOS - handle to the OS object.\n
58 * \return a handle to the scan SRV object, NULL if an error occurred.\n
59 */
60TI_HANDLE MacServices_scanSRV_create( TI_HANDLE hOS )
61{
62    /* allocate the scan SRV object */
63    scanSRV_t *pScanSRV = os_memoryAlloc( hOS, sizeof(scanSRV_t));
64    if ( NULL == pScanSRV )
65    {
66        WLAN_OS_REPORT( ("ERROR: Failed to create scan SRV module"));
67        return NULL;
68    }
69
70    os_memoryZero( pScanSRV->hOS, pScanSRV, sizeof(scanSRV_t));
71
72    /* allocate the state machine */
73    if ( TI_OK != fsm_Create( hOS, &(pScanSRV->SM), SCAN_SRV_NUM_OF_STATES, SCAN_SRV_NUM_OF_EVENTS ))
74    {
75        WLAN_OS_REPORT( ("ERROR: Failed to allocate scan SRV state machine"));
76        os_memoryFree( hOS, pScanSRV, sizeof(scanSRV_t));
77        return NULL;
78    }
79
80    /* store the OS handle */
81    pScanSRV->hOS = hOS;
82
83    return pScanSRV;
84}
85
86/**
87 * \\n
88 * \date 29-Dec-2004\n
89 * \brief Finalizes the scan SRV module (releasing memory and timer)
90 *
91 * Function Scope \e Public.\n
92 * \param hScanSRV - handle to the scan SRV object.\n
93 */
94void MacServices_scanSRV_destroy( TI_HANDLE hScanSRV )
95{
96    scanSRV_t *pScanSRV = (scanSRV_t*)hScanSRV;
97
98    /* free timer */
99	if (pScanSRV->hScanSrvTimer)
100	{
101		tmr_DestroyTimer (pScanSRV->hScanSrvTimer);
102	}
103
104    /* free memory */
105    fsm_Unload( pScanSRV->hOS, pScanSRV->SM );
106    os_memoryFree( pScanSRV->hOS, (TI_HANDLE)pScanSRV , sizeof(scanSRV_t));
107}
108
109/**
110 * \\n
111 * \date 29-Dec-2004\n
112 * \brief Initializes the scan SRV module, registers SCAN_COMPLETE to HAL.
113 *
114 * Function Scope \e Public.\n
115 * \param hScanSRV - handle to the scan SRV object.\n
116 * \param Handles of other modules.\n
117  */
118TI_STATUS MacServices_scanSRV_init (TI_HANDLE hMacServices,
119                                    TI_HANDLE hReport,
120                                    TI_HANDLE hTWD,
121                                    TI_HANDLE hTimer,
122                                    TI_HANDLE hEventMbox,
123                                    TI_HANDLE hCmdBld)
124{
125    MacServices_t* pMacServices =  (MacServices_t*)hMacServices;
126    scanSRV_t *pScanSRV =  pMacServices->hScanSRV;
127
128    /* store handles */
129    pScanSRV->hTWD = hTWD;
130    pScanSRV->hTimer = hTimer;
131    pScanSRV->hReport = hReport;
132    pScanSRV->hEventMbox = hEventMbox;
133    pScanSRV->hPowerSrv = pMacServices->hPowerSrv;
134    pScanSRV->hCmdBld = hCmdBld;
135    pScanSRV->commandResponseFunc = NULL;
136    pScanSRV->commandResponseObj = NULL;
137
138    /* create the timer */
139    pScanSRV->hScanSrvTimer = tmr_CreateTimer (pScanSRV->hTimer);
140	if (pScanSRV->hScanSrvTimer == NULL)
141	{
142        TRACE0(pScanSRV->hReport, REPORT_SEVERITY_ERROR, "MacServices_scanSRV_init(): Failed to create hScanSrvTimer!\n");
143		return TI_NOK;
144	}
145
146    /* init state machine */
147    scanSRVSM_init ((TI_HANDLE)pScanSRV);
148
149    /* Register our scan complete handler to the HAL events mailbox */
150    eventMbox_RegisterEvent (pScanSRV->hEventMbox,
151                              TWD_OWN_EVENT_SCAN_CMPLT,
152                              (void *)MacServices_scanSRV_scanCompleteCB,
153                              (TI_HANDLE)pScanSRV);
154    eventMbox_RegisterEvent (pScanSRV->hEventMbox,
155                              TWD_OWN_EVENT_SPS_SCAN_CMPLT,
156                              (void *)MacServices_scanSRV_scanCompleteCB,
157                              (TI_HANDLE)pScanSRV);
158
159    /* init other stuff */
160    pScanSRV->currentNumberOfConsecutiveNoScanCompleteEvents = 0;
161
162    TRACE0( hReport, REPORT_SEVERITY_INIT, ".....Scan SRV configured successfully.\n");
163
164    return TI_OK;
165}
166
167/**
168 * \brief Restart the scan SRV module upon recovery.
169 *
170 * Function Scope \e Public.\n
171 * \param hScanSRV - handle to the scan SRV object.\n
172 */
173void scanSRV_restart (TI_HANDLE hScanSRV)
174{
175	scanSRV_t *pScanSRV =  (scanSRV_t *)hScanSRV;
176    /* init state machine */
177	/* initialize current state */
178	pScanSRV->SMState = SCAN_SRV_STATE_IDLE;
179
180    if (pScanSRV->bTimerRunning)
181    {
182        tmr_StopTimer (pScanSRV->hScanSrvTimer);
183        pScanSRV->bTimerRunning = TI_FALSE;
184    }
185}
186
187/**
188 * \\n
189 * \date 26-July-2006\n
190 * \brief Configures the scan SRV module with initialization values
191 *
192 * Function Scope \e Public.\n
193 * \param hScanSRV - handle to the scan SRV object.\n
194 * \param hReport - handle to the report object.\n
195 * \param hTWD - handle to the HAL ctrl object.\n
196  */
197void MacServices_scanSrv_config( TI_HANDLE hMacServices, TScanSrvInitParams* pInitParams )
198{
199    MacServices_t* pMacServices =  (MacServices_t*)hMacServices;
200    scanSRV_t *pScanSRV =  pMacServices->hScanSRV;
201
202    pScanSRV->numberOfNoScanCompleteToRecovery = pInitParams->numberOfNoScanCompleteToRecovery;
203
204    /* Set Triggered scan time out per channel */
205    pScanSRV->uTriggeredScanTimeOut = pInitParams->uTriggeredScanTimeOut;
206	TWD_CmdSetSplitScanTimeOut (pScanSRV->hTWD, pScanSRV->uTriggeredScanTimeOut);
207}
208
209/**
210 * \\n
211 * \date 29-Dec-2004\n
212 * \brief Registers a complete callback for scan complete notifications.
213 *
214 * Function Scope \e Public.\n
215 * \param hMacServices - handle to the MacServices object.\n
216 * \param scanCompleteCB - the complete callback function.\n
217 * \param hScanCompleteObj - handle to the object passed to the scan complete callback function.\n
218 */
219void MacServices_scanSRV_registerScanCompleteCB( TI_HANDLE hMacServices,
220                                     TScanSrvCompleteCb scanCompleteCB, TI_HANDLE hScanCompleteObj )
221{
222    scanSRV_t *pScanSRV = (scanSRV_t*)((MacServices_t*)hMacServices)->hScanSRV;
223
224    pScanSRV->scanCompleteNotificationFunc = scanCompleteCB;
225    pScanSRV->scanCompleteNotificationObj = hScanCompleteObj;
226}
227
228/**
229 * \brief Registers a failure event callback for scan error notifications.
230 *
231 * Function Scope \e member.\n
232 * \param hScanSRV - handle to the Scan SRV object.\n
233 * \param failureEventCB - the failure event callback function.\n
234 * \param hFailureEventObj - handle to the object passed to the failure event callback function.\n
235 */
236void scanSRV_registerFailureEventCB( TI_HANDLE hScanSRV,
237                                     void * failureEventCB, TI_HANDLE hFailureEventObj )
238{
239    scanSRV_t *pScanSRV = (scanSRV_t*)(hScanSRV);
240
241    pScanSRV->failureEventFunc  = (TFailureEventCb)failureEventCB;
242    pScanSRV->failureEventObj   = hFailureEventObj;
243}
244
245/**
246 * \\n
247 * \date 27-Sep-2005\n
248 * \brief This function is the CB which is called as response to 'StartScan' or 'StopScan' \n.
249 *        here we check if there is a GWSI command response , and call it if necessary .\n
250 * Function Scope \e Private.\n
251 * \param hScanSrv - handle to the scan SRV object.\n
252 * \param MboxStatus - mailbox status. \n
253 */
254void MacServices_scanSRVCommandMailBoxCB(TI_HANDLE hScanSrv,TI_UINT16 MboxStatus)
255{
256    scanSRV_t* pScanSRV = (scanSRV_t*)hScanSrv;
257    TI_UINT16 responseStatus;
258    TCmdResponseCb CB_Func;
259    TI_HANDLE  CB_Handle;
260
261    TRACE1( pScanSRV->hReport, REPORT_SEVERITY_INFORMATION, " status %u\n",MboxStatus);
262
263    /* set response to TI_OK or TI_NOK */
264    responseStatus = ((MboxStatus > 0) ? TI_NOK : TI_OK);
265
266    /* if we have a Response Function (only in GWSI) we set it back to NULL and then
267        we call it */
268    if (pScanSRV->commandResponseFunc != NULL)
269    {
270        CB_Func = pScanSRV->commandResponseFunc;
271        CB_Handle = pScanSRV->commandResponseObj;
272
273        pScanSRV->commandResponseFunc = NULL;
274        pScanSRV->commandResponseObj = NULL;
275
276        CB_Func(CB_Handle, responseStatus);
277    }
278     /* if scan request failed */
279    if ( TI_OK != responseStatus )
280    {
281        TRACE0( pScanSRV->hReport, REPORT_SEVERITY_ERROR, "Mail box returned error , quitting scan.\n");
282
283        /* send a scan complete event. This will do all necessary clean-up (timer, power manager, notifying scan complete) */
284        scanSRVSM_SMEvent( hScanSrv, (scan_SRVSMStates_e*)&pScanSRV->SMState, SCAN_SRV_EVENT_SCAN_COMPLETE );
285    }
286}
287
288/**
289 * \\n
290 * \date 29-Dec-2004\n
291 * \brief Performs a scan
292 *
293 * Function Scope \e Public.\n
294 * \param hMacServices - handle to the MacServices object.\n
295 * \param scanParams - the scan specific parameters.\n
296 * \param eScanresultTag - tag used for result and scan complete tracking
297 * \param bHighPriority - whether to perform a high priority (overlaps DTIM) scan.\n
298 * \param bDriverMode - whether to try to enter driver mode (with PS on) before issuing the scan command.\n
299 * \param bScanOnDriverModeError - whether to proceed with the scan if requested to enter driver mode and failed.\n
300 * \param psRequest - Parameter sent to PowerSaveServer on PS request to indicate PS on or "keep current"
301 * \param bSendNullData - whether to send Null data when exiting driver mode on scan complete.\n
302 * \param commandResponseFunc - CB function which called after downloading the command. \n
303 * \param commandResponseObj -  The CB function Obj (Notice : last 2 params are NULL in Legacy run). \n
304 * \param psRequest - Parameter sent to PowerSaveServer on PS request to indicate PS on or "keep current"
305 * \return TI_OK if successful (various, TBD codes if not).\n
306 */
307TI_STATUS MacServices_scanSRV_scan( TI_HANDLE hMacServices, TScanParams *scanParams, EScanResultTag eScanTag,
308                                    TI_BOOL bHighPriority, TI_BOOL bDriverMode, TI_BOOL bScanOnDriverModeError,
309                        E80211PsMode psRequest, TI_BOOL bSendNullData,
310                        TCmdResponseCb commandResponseFunc, TI_HANDLE commandResponseObj)
311{
312   scanSRV_t *pScanSRV = (scanSRV_t*)((MacServices_t*)hMacServices)->hScanSRV;
313
314
315    TRACE0( pScanSRV->hReport, REPORT_SEVERITY_INFORMATION, "Scan request received.\n");
316
317    /* sanity check - scan can only start if the scan SRV is idle */
318    if ( SCAN_SRV_STATE_IDLE != pScanSRV->SMState )
319    {
320        TRACE0( pScanSRV->hReport, REPORT_SEVERITY_WARNING, "Scan request while scan is running!\n");
321        return TI_NOK;
322    }
323
324    /* Response function for GWSI only. In Legacy run we get NULL and never use it. */
325    pScanSRV->commandResponseFunc = commandResponseFunc;
326    pScanSRV->commandResponseObj  = commandResponseObj;
327
328    pScanSRV->bInRequest = TI_TRUE;
329    pScanSRV->returnStatus = TI_OK;
330
331    /* copy scan paramaters */
332    pScanSRV->scanParams = scanParams;
333    pScanSRV->eScanTag = eScanTag;
334    pScanSRV->uResultCount = 0;
335    pScanSRV->bHighPriority = bHighPriority;
336    pScanSRV->bScanOnDriverModeFailure = bScanOnDriverModeError;
337    pScanSRV->bSendNullData = bSendNullData;
338    pScanSRV->psRequest = psRequest;
339
340    if ( SCAN_TYPE_SPS == scanParams->scanType )
341    {
342        pScanSRV->bSPSScan = TI_TRUE;
343
344    }
345    else
346    {
347        pScanSRV->bSPSScan = TI_FALSE;
348    }
349
350
351    /* check whether the scan will overlap DTIM frame */
352    if ( (TI_FALSE == bHighPriority) && (TI_TRUE == bDriverMode))
353    {
354        pScanSRV->bDtimOverlapping = TI_FALSE;
355    }
356    else
357    {
358        pScanSRV->bDtimOverlapping = TI_TRUE;
359    }
360
361    /* mark the no scan complete flag. The purpose of this flag is to be able to identify
362       whether the scan complete is a normal process, or was it generated because a no scan ocmplete
363       was identified, a stop scan command was snet to the FW, and thus a scan complete was received.
364       In the former case we nullify the consecutive no scan complete counter, whereas in the latter
365       we do not. */
366    pScanSRV->bNoScanCompleteFlag = TI_FALSE;
367
368    /* if required to enter driver mode */
369    if ( TI_TRUE == bDriverMode )
370    {
371        pScanSRV->bExitFromDriverMode = TI_TRUE;
372        /* send a PS_REQUEST event */
373        scanSRVSM_SMEvent( (TI_HANDLE)pScanSRV, (scan_SRVSMStates_e*)&(pScanSRV->SMState), SCAN_SRV_EVENT_REQUEST_PS );
374    }
375    /* no driver mode required */
376    else
377    {
378        pScanSRV->bExitFromDriverMode = TI_FALSE;
379        /* send a PS_SUCCESS event - will start the scan */
380        scanSRVSM_SMEvent( (TI_HANDLE)pScanSRV, (scan_SRVSMStates_e*)&pScanSRV->SMState, SCAN_SRV_EVENT_PS_SUCCESS );
381    }
382
383    pScanSRV->bInRequest = TI_FALSE;
384
385    return pScanSRV->returnStatus;
386}
387
388/**
389 * \\n
390 * \date 29-Dec-2004\n
391 * \brief Sends a Stop Scan command to FW, no matter if we are in scan progress or not
392 *
393 * Function Scope \e Public.\n
394 * \param hMacServices - handle to the MacServices object.\n
395 * \param eScanTag - scan tag, used for scan complete and result tracking
396 * \param bSendNullData - indicates whether to send Null data when exiting driver mode.\n
397 * \param commandResponseFunc - CB function which called after downloading the command. \n
398 * \param commandResponseObj -  The CB function Obj (Notice : last 2 params are NULL in Legacy run). \n
399 * \return TI_OK if successful (various, TBD codes if not).\n
400 */
401TI_STATUS MacServices_scanSRV_stopScan( TI_HANDLE hMacServices, EScanResultTag eScanTag, TI_BOOL bSendNullData,
402                                        TCmdResponseCb ScanCommandResponseCB, TI_HANDLE CB_handle )
403{
404    scanSRV_t *pScanSRV = (scanSRV_t*)((MacServices_t*)hMacServices)->hScanSRV;
405    TI_INT32 stopScanStatus;
406
407    TRACE0( pScanSRV->hReport, REPORT_SEVERITY_INFORMATION, "Stop scan request received.\n");
408
409    /* update the driver mode exit flag */
410    pScanSRV->bSendNullData = bSendNullData;
411
412    if ( TI_TRUE == pScanSRV->bSPSScan )
413    {
414        stopScanStatus = cmdBld_CmdStopSPSScan (pScanSRV->hCmdBld, eScanTag, (void *)ScanCommandResponseCB, CB_handle);
415    }
416    else
417    {
418        stopScanStatus = cmdBld_CmdStopScan (pScanSRV->hCmdBld, eScanTag, (void *)ScanCommandResponseCB, CB_handle);
419    }
420
421    if (TI_OK != stopScanStatus)
422    {
423        return TI_NOK;
424    }
425
426    /* send a stop scan event */
427    scanSRVSM_SMEvent( (TI_HANDLE)pScanSRV, (scan_SRVSMStates_e*)&pScanSRV->SMState, SCAN_SRV_EVENT_STOP_SCAN );
428
429    return pScanSRV->returnStatus;
430}
431
432/**
433 * \\n
434 * \date 17-Jan-2005\n
435 * \brief Notifies the scan SRV of a FW reset (that had originally been reported by a different module).\n
436 *
437 * Function Scope \e Public.\n
438 * \param hMacServices - handle to the MacServices object.\n
439 * \return TI_OK if successful (various, TBD codes if not).\n
440 */
441TI_STATUS MacServices_scanSRV_stopOnFWReset( TI_HANDLE hMacServices )
442{
443   scanSRV_t *pScanSRV = (scanSRV_t*)((MacServices_t*)hMacServices)->hScanSRV;
444
445    TRACE0( pScanSRV->hReport, REPORT_SEVERITY_INFORMATION, "FW reset notification received.\n");
446
447    /* mark the return status */
448    pScanSRV->returnStatus = TI_NOK;
449
450    /* send a FW reset event */
451    return scanSRVSM_SMEvent( (TI_HANDLE)pScanSRV, (scan_SRVSMStates_e*)&pScanSRV->SMState, SCAN_SRV_EVENT_FW_RESET );
452}
453
454/**
455 * \\n
456 * \date 29-Dec-2004\n
457 * \brief callback function used by the power server to notify driver mode result
458 *          this CB is used in requesting PS and exiting PS.
459 * Function Scope \e Public.\n
460 * \param hScanSRV - handle to the scan SRV object.\n
461 * \param psStatus - the power save request status.\n
462 */
463void MacServices_scanSRV_powerSaveCB( TI_HANDLE hScanSRV, TI_UINT8 PSMode,TI_UINT8 psStatus )
464{
465    scanSRV_t *pScanSRV = (scanSRV_t*)hScanSRV;
466
467    TRACE1( pScanSRV->hReport, REPORT_SEVERITY_INFORMATION, "PS Call Back status %d .\n",psStatus);
468
469    /* if driver mode enter/exit succeedded */
470    if ( (ENTER_POWER_SAVE_SUCCESS == psStatus) || (EXIT_POWER_SAVE_SUCCESS == psStatus))
471    {
472        TRACE0( pScanSRV->hReport, REPORT_SEVERITY_INFORMATION, "PS successful.\n");
473
474        /* send a PS_SUCCESS event */
475        scanSRVSM_SMEvent( (TI_HANDLE)pScanSRV, (scan_SRVSMStates_e*)&pScanSRV->SMState, SCAN_SRV_EVENT_PS_SUCCESS );
476    }
477    /* driver mode entry failed, and scan is requested even on PS failure but we are entering PS and not Exiting */
478    else if ( (TI_TRUE == pScanSRV->bScanOnDriverModeFailure) && ( ENTER_POWER_SAVE_FAIL == psStatus))
479    {
480        TRACE0( pScanSRV->hReport, REPORT_SEVERITY_INFORMATION, "PS enter failed, continune scan .\n");
481
482        /* send a PS_SUCCESS event */
483        scanSRVSM_SMEvent( (TI_HANDLE)pScanSRV, (scan_SRVSMStates_e*)&pScanSRV->SMState, SCAN_SRV_EVENT_PS_SUCCESS );
484    }
485    /* driver mode enter or exit failed */
486    else
487    {
488        /* if we are trying to enter PS and fail to do so - return error on scan complete */
489        if ( ENTER_POWER_SAVE_FAIL == psStatus)
490        {
491            TRACE0( pScanSRV->hReport, REPORT_SEVERITY_WARNING, "PS enter failed . quiting scan .\n");
492            /* Set the return status  */
493            pScanSRV->returnStatus = TI_NOK;
494        }
495
496        /* send a PS FAIL event */
497        scanSRVSM_SMEvent( (TI_HANDLE)pScanSRV, (scan_SRVSMStates_e*)&pScanSRV->SMState, SCAN_SRV_EVENT_PS_FAIL );
498    }
499}
500
501
502/**
503 * \\n
504 * \date 29-Dec-2004\n
505 * \brief Callback function used by the HAL ctrl to notify scan complete
506 *
507 * Function Scope \e Public.\n
508 * \param hScanSRV - handle to the scan SRV object.\n
509 * \param str - pointer to scan result buffer (holding SPS status for SPS scan only!).\n
510 * \param strLen - scan result buffer length (should ALWAYS be 2, even for non SPS scans).\n
511 */
512void MacServices_scanSRV_scanCompleteCB( TI_HANDLE hScanSRV, char* str, TI_UINT32 strLen )
513{
514    scanSRV_t *pScanSRV = (scanSRV_t*)hScanSRV;
515    scanCompleteResults_t   *pResult = (scanCompleteResults_t*)str;
516
517    TRACE0( pScanSRV->hReport, REPORT_SEVERITY_INFORMATION, "Scan complete notification from TNET.\n");
518
519	/* nullify the consecutive no scan complete events counter  - only if this is a scan complete that
520       does not happen afetr a stop scan (due to a timer expiry) */
521	if ( TI_FALSE == pScanSRV->bNoScanCompleteFlag )
522    {
523        pScanSRV->currentNumberOfConsecutiveNoScanCompleteEvents = 0;
524    }
525
526    /* copy result counter and scan tag */
527    pScanSRV->uResultCount = pResult->numberOfScanResults;
528    pScanSRV->eScanTag = (EScanResultTag)pResult->scanTag;
529
530    /* copy scan SPS addmitted channels and SPS result */
531    if (TI_FALSE == pScanSRV->bSPSScan)
532    {
533        /* normal scan - no result is available */
534        pScanSRV->bTSFError = TI_FALSE;
535        TRACE0( pScanSRV->hReport, REPORT_SEVERITY_INFORMATION, "Normal scan completed.\n");
536    }
537    else
538    {
539        /* SPS scan - first byte indicates whether a TSF error (AP recovery) occured */
540        if ( 0 != (pResult->scheduledScanStatus >> 24))
541        {
542            pScanSRV->bTSFError = TI_TRUE;
543        }
544        else
545        {
546            pScanSRV->bTSFError = TI_FALSE;
547        }
548
549        /* next two bytes indicates on which channels scan was attempted */
550        pScanSRV->SPSScanResult = (TI_UINT16)(pResult->scheduledScanStatus >> 16) | 0xff;
551        pScanSRV->SPSScanResult = ENDIAN_HANDLE_WORD( pScanSRV->SPSScanResult );
552        TRACE1( pScanSRV->hReport, REPORT_SEVERITY_INFORMATION, "SPS scan completed. TSF error: , SPS result: %x\n", pScanSRV->SPSScanResult);
553    }
554
555    /* send a SCAN_COMPLETE event  */
556    scanSRVSM_SMEvent( (TI_HANDLE)pScanSRV, (scan_SRVSMStates_e*)&pScanSRV->SMState, SCAN_SRV_EVENT_SCAN_COMPLETE );
557}
558
559/**
560 * \\n
561 * \date 29-Dec-2004\n
562 * \brief called when a scan timer expires. Completes the scan and starts a recovery process.
563 *
564 * Function Scope \e Public.\n
565 * \param hScanSRV - handle to the scan SRV object.\n
566 * \param bTwdInitOccured - Indicates if TWDriver recovery occured since timer started.\n
567 */
568void MacServices_scanSRV_scanTimerExpired (TI_HANDLE hScanSRV, TI_BOOL bTwdInitOccured)
569{
570    scanSRV_t *pScanSRV = (scanSRV_t*)hScanSRV;
571
572    /* mark that no scan complete occured (see sanSRV_scan for more detailed explanation) */
573    pScanSRV->bNoScanCompleteFlag = TI_TRUE;
574
575    /* send a TIMER_EXPIRED event */
576    scanSRVSM_SMEvent( (TI_HANDLE)pScanSRV, (scan_SRVSMStates_e*)&pScanSRV->SMState, SCAN_SRV_EVENT_TIMER_EXPIRED );
577}
578
579/**
580 * \\n
581 * \date 29-Dec-2004\n
582 * \brief Calculates the maximal time required for a scan operation
583 *
584 * Function Scope \e Public.\n
585 * \param hScanSRV - handle to the scan SRV object.\n
586 * \param scanParams - the scan parameters
587 * \param bConsiderDTIM - whether this scan overlaps DTIM
588 * \return the time (in milliseconds)
589 */
590TI_UINT32 MacServices_scanSRVcalculateScanTimeout( TI_HANDLE hScanSRV, TScanParams* scanParams, TI_BOOL bConsiderDTIM )
591{
592    TI_UINT32 i, uDtimPeriodMs, uBeaconIntervalMs, timeout = 0;
593    scanSRV_t *pScanSRV = (scanSRV_t*)hScanSRV;
594
595    /********************************************************************************
596        timeout calculation is performed according to scan type:
597        1. for normal scan, multiply the channel time by the number of channels.
598           if this scan is not overlapping DTIM, add the DTIM period (in case
599           starting the scan right now will cause the very last milliseconds of the
600           scan to overlap the next DTIM). Add the guard time.
601        2. for triggered scan, multiply the channel time plus the trigger time
602           constant (the maximum time between two frames from the Tid
603           according to which the scan is triggered) by the number of channels.
604           DTIM period is added only as precaution - since the scan is divided to
605           channels, only very few of them will be delayed due to DTIM (in the worst
606           case), and this delay would be only the length of one channel scan.
607           Eventually, Add the guard time.
608        3. for SPS scan: Measure the time from current TSF to the TSF at which the
609           scan is scheduled to finish (done by the scan manager, and passed as
610           a parameter in the scan structure). Add guard time. DTIM overlapping is not
611           considered because if the scan overlaps DTIM the channels which are
612           scheduled during the DTIM (if any) won't be scanned.
613     ********************************************************************************/
614
615    /* get DTIM time, if scanning in connected mode and need to consider DTIM */
616    if ( bConsiderDTIM )
617    {
618        /* new dtimPeriod calculation */
619        uBeaconIntervalMs = MacServices_scanSRVConvertTUToMsec (pScanSRV->uBeaconInterval);
620        uDtimPeriodMs     = uBeaconIntervalMs * pScanSRV->uDtimPeriod;
621    }
622    else
623    {
624        uDtimPeriodMs = 0;
625    }
626
627    switch (scanParams->scanType)
628    {
629    case SCAN_TYPE_NORMAL_ACTIVE:
630    case SCAN_TYPE_NORMAL_PASSIVE:
631        /* the timeout is the scan duration on all channels */
632        for ( i = 0; i < scanParams->numOfChannels; i++ )
633        {
634            timeout += scanParams->channelEntry[ i ].normalChannelEntry.maxChannelDwellTime;
635        }
636        timeout = (timeout / 1000) + uDtimPeriodMs + SCAN_SRV_FW_GUARD_TIME_MS;
637        break;
638
639    case SCAN_TYPE_TRIGGERED_ACTIVE:
640    case SCAN_TYPE_TRIGGERED_PASSIVE:
641        /* the timeout is the scan duration on all channels, plus the maximum time that can pass
642           between two different frames from the same Tid */
643        for ( i = 0; i < scanParams->numOfChannels; i++ )
644        {
645            timeout += scanParams->channelEntry[ i ].normalChannelEntry.maxChannelDwellTime;
646        }
647        timeout = (timeout / 1000) + uDtimPeriodMs +
648                  ((pScanSRV->uTriggeredScanTimeOut / 1000 + 1) * scanParams->numOfChannels) +
649                  SCAN_SRV_FW_GUARD_TIME_MS;
650        break;
651
652    case SCAN_TYPE_SPS:
653        timeout = scanParams->SPSScanDuration + SCAN_SRV_FW_GUARD_TIME_MS;
654        break;
655
656    default:
657        TRACE1( pScanSRV->hReport, REPORT_SEVERITY_ERROR, "Trying to calculate timeout for undefined scan type %d\n", scanParams->scanType);
658        break;
659    }
660    TRACE1( pScanSRV->hReport, REPORT_SEVERITY_INFORMATION, "scanSRVcalculateScanTimeout, timeout = %d\n", timeout);
661
662    return timeout;
663}
664
665/**
666 * \\n
667 * \date 16-Jan-2005\n
668 * \brief Convert time units (1024 usecs) to millisecs
669 *
670 * Function Scope \e Private.\n
671 * \param tu - the time in time units
672 * \return the time in milliseconds
673 */
674TI_UINT32 MacServices_scanSRVConvertTUToMsec( TI_UINT32 tu )
675{
676    return (tu * 1024) / 1000;
677}
678
679
680/**
681 * \\n
682 * \brief Save DTIM and Beacon periods for scan timeout calculations
683 *
684 * Function Scope \e Public.\n
685 * \param hMacServices    - module object
686 * \param uDtimPeriod     - DTIM period in number of beacons
687 * \param uBeaconInterval - Beacon perios in TUs (1024 msec)
688 * \return void
689 */
690void MacServices_scanSrv_UpdateDtimTbtt (TI_HANDLE hMacServices,
691                                         TI_UINT8  uDtimPeriod,
692                                         TI_UINT16 uBeaconInterval)
693{
694    scanSRV_t *pScanSRV = (scanSRV_t*)((MacServices_t*)hMacServices)->hScanSRV;
695
696    pScanSRV->uDtimPeriod     = uDtimPeriod;
697    pScanSRV->uBeaconInterval = uBeaconInterval;
698}
699
700
701#ifdef TI_DBG
702/**
703 * \\n
704 * \date God knows when...\n
705 * \brief Prints Scan Server SM status.\n
706 *
707 * Function Scope \e Public.\n
708 * \param hMacServices - handle to the Mac Services object.\n
709 * \return always TI_OK.\n
710 */
711void MacServices_scanSrv_printDebugStatus(TI_HANDLE hMacServices)
712{
713   scanSRV_t *pScanSRV = (scanSRV_t*)((MacServices_t*)hMacServices)->hScanSRV;
714
715    WLAN_OS_REPORT(("scanSrv State="));
716    switch (pScanSRV->SMState)
717    {
718    case SCAN_SRV_STATE_IDLE:
719        WLAN_OS_REPORT((" IDLE\n"));
720        break;
721    case SCAN_SRV_STATE_PS_WAIT:
722        WLAN_OS_REPORT((" PS_WAIT\n"));
723        break;
724    case SCAN_SRV_STATE_PS_EXIT:
725        WLAN_OS_REPORT((" PS_EXIT\n"));
726        break;
727    case SCAN_SRV_STATE_SCANNING:
728        WLAN_OS_REPORT((" SCANNING\n"));
729        break;
730    case SCAN_SRV_STATE_STOPPING:
731        WLAN_OS_REPORT((" STOPPING\n"));
732        break;
733    default:
734        WLAN_OS_REPORT((" Invalid State=%d\n",pScanSRV->SMState));
735        break;
736
737    }
738
739    if (NULL != pScanSRV->scanParams)
740    {
741        WLAN_OS_REPORT(("scanSrv bExitFromDriverMode=%d, bHighPriority=%d, bInRequest=%d,\n \
742                        bScanOnDriverModeFailure=%d, bSendNullData=%d, bSPSScan=%d, bTimerRunning=%d, \n \
743                        psRequest=%d, scanType=%d\n",
744                        pScanSRV->bExitFromDriverMode,
745                        pScanSRV->bHighPriority,
746                        pScanSRV->bInRequest,
747                        pScanSRV->bScanOnDriverModeFailure,
748                        pScanSRV->bSendNullData,
749                        pScanSRV->bSPSScan,
750                        pScanSRV->bTimerRunning,
751                        pScanSRV->psRequest,
752                        pScanSRV->scanParams->scanType));
753    }
754}
755#endif
756
757