summaryrefslogtreecommitdiff
path: root/wl1271/utils/timer.c
blob: 7be2426a76767ad6ef1c341205e34ebcffa4cf98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
/*
 * timer.c
 *
 * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved.      
 * All rights reserved.                                                  
 *                                                                       
 * Redistribution and use in source and binary forms, with or without    
 * modification, are permitted provided that the following conditions    
 * are met:                                                              
 *                                                                       
 *  * Redistributions of source code must retain the above copyright     
 *    notice, this list of conditions and the following disclaimer.      
 *  * Redistributions in binary form must reproduce the above copyright  
 *    notice, this list of conditions and the following disclaimer in    
 *    the documentation and/or other materials provided with the         
 *    distribution.                                                      
 *  * Neither the name Texas Instruments nor the names of its            
 *    contributors may be used to endorse or promote products derived    
 *    from this software without specific prior written permission.      
 *                                                                       
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


/** \file   timer.c 
 *  \brief  The timers services OS-Independent layer over the OS-API timer services which are OS-Dependent.
 *  
 *  \see    timer.h, osapi.c
 */

#define __FILE_ID__  FILE_ID_0
#include "osApi.h"
#include "report.h"
#include "queue.h"
#include "context.h"
#include "timer.h"


#define EXPIRY_QUE_SIZE  QUE_UNLIMITED_SIZE

/* The timer module structure (common to all timers) */
typedef struct 
{
    TI_HANDLE   hOs;
    TI_HANDLE   hReport;
    TI_HANDLE   hContext;
    TI_UINT32   uContextId;     /* The ID allocated to this module on registration to context module */
    TI_HANDLE   hInitQueue;     /* Handle of the Init-Queue */
    TI_HANDLE   hOperQueue;     /* Handle of the Operational-Queue */
    TI_BOOL     bOperState;     /* TRUE when the driver is in operational state (not init or recovery) */
    TI_UINT32   uTwdInitCount;  /* Increments on each TWD init (i.e. recovery) */
    TI_UINT32   uTimersCount;   /* Number of created timers */
} TTimerModule;	

/* Per timer structure */
typedef struct 
{
    TI_HANDLE    hTimerModule;             /* The timer module handle (see TTimerModule, needed on expiry) */
    TI_HANDLE    hOsTimerObj;              /* The OS-API timer object handle */
    TQueNodeHdr  tQueNodeHdr;              /* The header used for queueing the timer */
    TTimerCbFunc fExpiryCbFunc;            /* The CB-function provided by the timer user for expiration */
    TI_HANDLE    hExpiryCbHndl;            /* The CB-function handle */
    TI_UINT32    uIntervalMsec;            /* The timer duration in Msec */
    TI_BOOL      bPeriodic;                /* If TRUE, restarted after each expiry */
    TI_BOOL      bOperStateWhenStarted;    /* The bOperState value when the timer was started */
    TI_UINT32    uTwdInitCountWhenStarted; /* The uTwdInitCount value when the timer was started */
} TTimerInfo;	




/** 
 * \fn     tmr_Create 
 * \brief  Create the timer module
 * 
 * Allocate and clear the timer module object.
 * 
 * \note   This is NOT a specific timer creation! (see tmr_CreateTimer)
 * \param  hOs - Handle to Os Abstraction Layer
 * \return Handle of the allocated object 
 * \sa     tmr_Destroy
 */ 
TI_HANDLE tmr_Create (TI_HANDLE hOs)
{
    TI_HANDLE hTimerModule;

    /* allocate module object */
    hTimerModule = os_memoryAlloc (hOs, sizeof(TTimerModule));
	
    if (!hTimerModule)
    {
        WLAN_OS_REPORT (("tmr_Create():  Allocation failed!!\n"));
        return NULL;
    }
	
    os_memoryZero (hOs, hTimerModule, (sizeof(TTimerModule)));

    return (hTimerModule);
}


/** 
 * \fn     tmr_Destroy
 * \brief  Destroy the module. 
 * 
 * Free the module's queues and object.
 * 
 * \note   This is NOT a specific timer destruction! (see tmr_DestroyTimer)
 * \param  hTimerModule - The module object
 * \return TI_OK on success or TI_NOK on failure 
 * \sa     tmr_Create
 */ 
TI_STATUS tmr_Destroy (TI_HANDLE hTimerModule)
{
    TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;

    if (!pTimerModule)
    {
        WLAN_OS_REPORT (("tmr_Destroy(): ERROR - NULL timer!\n"));
        return TI_NOK;
    }

    /* Alert if there are still timers that were not destroyed */
    if (pTimerModule->uTimersCount)
    {
        WLAN_OS_REPORT (("tmr_Destroy():  ERROR - Destroying Timer module but not all timers were destroyed!!\n"));
    }

    /* Destroy the module's queues (protect in critical section)) */
    context_EnterCriticalSection (pTimerModule->hContext);
    que_Destroy (pTimerModule->hInitQueue);
    que_Destroy (pTimerModule->hOperQueue);
    context_LeaveCriticalSection (pTimerModule->hContext);

    /* free module object */
    os_memoryFree (pTimerModule->hOs, pTimerModule, sizeof(TTimerModule));
	
    return TI_OK;
}
/** 
 * \fn     tmr_Free
 * \brief  Free the memory. 
 * 
 * Free the module's queues and object.
 * 
 * \param  hTimerModule - The module object
 * \return TI_OK on success or TI_NOK on failure 
 * \sa     tmr_Create
 */ 
TI_STATUS tmr_Free(TI_HANDLE hTimerModule)
{
    TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;

    if (!pTimerModule)
    {
        WLAN_OS_REPORT (("tmr_Free(): ERROR - NULL timer!\n"));
        return TI_NOK;
    }

    /* free module object */
    os_memoryFree (pTimerModule->hOs, pTimerModule, sizeof(TTimerModule));
	
    return TI_OK;
}


/** 
 * \fn     tmr_ClearInitQueue & tmr_ClearOperQueue
 * \brief  Clear Init/Operationsl queue
 * 
 * Dequeue all queued timers.
 * 
 * \note   
 * \param  hTimerModule - The object                                          
 * \return void 
 * \sa     
 */ 
void tmr_ClearInitQueue (TI_HANDLE hTimerModule)
{
    TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;

    context_EnterCriticalSection (pTimerModule->hContext);
    while (que_Dequeue (pTimerModule->hInitQueue) != NULL) {}
    context_LeaveCriticalSection (pTimerModule->hContext);
}

void tmr_ClearOperQueue (TI_HANDLE hTimerModule)
{
    TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;

    context_EnterCriticalSection (pTimerModule->hContext);
    while (que_Dequeue (pTimerModule->hOperQueue) != NULL) {}
    context_LeaveCriticalSection (pTimerModule->hContext);
}


/** 
 * \fn     tmr_Init 
 * \brief  Init required handles 
 * 
 * Init required handles and module variables, create the init-queue and 
 *     operational-queue, and register as the context-engine client.
 * 
 * \note    
 * \param  hTimerModule  - The queue object
 * \param  hOs       - Handle to Os Abstraction Layer
 * \param  hReport   - Handle to report module
 * \param  hContext  - Handle to context module
 * \return void        
 * \sa     
 */ 
void tmr_Init (TI_HANDLE hTimerModule, TI_HANDLE hOs, TI_HANDLE hReport, TI_HANDLE hContext)
{
    TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;
    TI_UINT32     uNodeHeaderOffset;

    if (!pTimerModule)
    {
        WLAN_OS_REPORT (("tmr_Init(): ERROR - NULL timer!\n"));
        return;
    }

    pTimerModule->hOs           = hOs;
    pTimerModule->hReport       = hReport;
    pTimerModule->hContext      = hContext;
	
    pTimerModule->bOperState    = TI_FALSE;
    pTimerModule->uTimersCount  = 0;
    pTimerModule->uTwdInitCount = 0;

    /* The offset of the queue-node-header from timer structure entry is needed by the queue */
    uNodeHeaderOffset = TI_FIELD_OFFSET(TTimerInfo, tQueNodeHdr); 

    /* Create and initialize the Init and Operational queues (for timers expiry events) */
    pTimerModule->hInitQueue = que_Create (pTimerModule->hOs, 
                                           pTimerModule->hReport, 
                                           EXPIRY_QUE_SIZE, 
                                           uNodeHeaderOffset);
    pTimerModule->hOperQueue = que_Create (pTimerModule->hOs, 
                                           pTimerModule->hReport, 
                                           EXPIRY_QUE_SIZE, 
                                           uNodeHeaderOffset);

    /* Register to the context engine and get the client ID */
    pTimerModule->uContextId = context_RegisterClient (pTimerModule->hContext,
                                                       tmr_HandleExpiry,
                                                       hTimerModule,
                                                       TI_TRUE,
                                                       "TIMER",
                                                       sizeof("TIMER"));
}


/** 
 * \fn     tmr_UpdateDriverState 
 * \brief  Update driver state 
 * 
 * Under critical section, update driver state (operational or not),
 *   and if opertional, clear init queue.
 * Leave critical section and if operational state, request schedule for handling 
 *   timer events in driver context (if any).
 * 
 * \note    
 * \param  hTimerModule - The timer module object
 * \param  bOperState   - TRUE if driver state is now operational, FALSE if not.
 * \return void  
 * \sa     
 */ 
void tmr_UpdateDriverState (TI_HANDLE hTimerModule, TI_BOOL bOperState)
{
    TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;

    if (!pTimerModule)
    {
        WLAN_OS_REPORT (("tmr_UpdateDriverState(): ERROR - NULL timer!\n"));
        return;
    }

    /* Enter critical section */
    context_EnterCriticalSection (pTimerModule->hContext);

    if (bOperState == pTimerModule->bOperState) 
    {
        context_LeaveCriticalSection (pTimerModule->hContext);
        TRACE1(pTimerModule->hReport, REPORT_SEVERITY_ERROR, "tmr_UpdateDriverState(): New bOperState (%d) is as current!\n", bOperState);
        return;
    }

    /* Save new state (TRUE means operational). */
    pTimerModule->bOperState = bOperState;

    /* If new state is operational */
    if (bOperState) 
    {
        /* Increment the TWD initializations counter (for detecting recovery events). */
        pTimerModule->uTwdInitCount++;

        /* Empty the init queue (obsolete). */
        while (que_Dequeue (pTimerModule->hInitQueue) != NULL) {}
    }

    /* Leave critical section */
    context_LeaveCriticalSection (pTimerModule->hContext);

    /* If new state is operational, request switch to driver context for handling timer events */
    if (bOperState) 
    {
        context_RequestSchedule (pTimerModule->hContext, pTimerModule->uContextId);
    }
}



/** 
 * \fn     tmr_CreateTimer
 * \brief  Create a new timer
 * 
 * Create a new timer object, icluding creating a timer in the OS-API.  
 * 
 * \note   This timer creation may be used only after tmr_Create() and tmr_Init() were executed!!
 * \param  hTimerModule - The module handle
 * \return TI_HANDLE    - The created timer handle
 * \sa     tmr_DestroyTimer
 */ 
TI_HANDLE tmr_CreateTimer (TI_HANDLE hTimerModule)
{
    TTimerModule *pTimerModule = (TTimerModule *)hTimerModule; /* The timer module handle */
    TTimerInfo   *pTimerInfo;  /* The created timer handle */

    if (!pTimerModule)
    {
        WLAN_OS_REPORT (("tmr_CreateTimer(): ERROR - NULL timer!\n"));
        return NULL;
    }

    /* Allocate timer object */
    pTimerInfo = os_memoryAlloc (pTimerModule->hOs, sizeof(TTimerInfo));
    if (!pTimerInfo)
    {
        WLAN_OS_REPORT (("tmr_CreateTimer():  Timer allocation failed!!\n"));
        return NULL;
    }
    os_memoryZero (pTimerModule->hOs, pTimerInfo, (sizeof(TTimerInfo)));

    /* Allocate OS-API timer, providing the common expiry callback with the current timer handle */
    pTimerInfo->hOsTimerObj = os_timerCreate(pTimerModule->hOs, tmr_GetExpiry, (TI_HANDLE)pTimerInfo);
    if (!pTimerInfo->hOsTimerObj)
    {
        TRACE0(pTimerModule->hReport, REPORT_SEVERITY_CONSOLE ,"tmr_CreateTimer():  OS-API Timer allocation failed!!\n");
        os_memoryFree (pTimerModule->hOs, pTimerInfo, sizeof(TTimerInfo));
        WLAN_OS_REPORT (("tmr_CreateTimer():  OS-API Timer allocation failed!!\n"));
        return NULL;
    }

    /* Save the timer module handle in the created timer object (needed for the expiry callback) */
    pTimerInfo->hTimerModule = hTimerModule;
    pTimerModule->uTimersCount++;  /* count created timers */

    /* Return the created timer handle */
    return (TI_HANDLE)pTimerInfo;
}


/** 
 * \fn     tmr_DestroyTimer
 * \brief  Destroy the specified timer
 * 
 * Destroy the specified timer object, icluding the timer in the OS-API.  
 * 
 * \note   This timer destruction function should be used before tmr_Destroy() is executed!!
 * \param  hTimerInfo - The timer handle
 * \return TI_OK on success or TI_NOK on failure 
 * \sa     tmr_CreateTimer
 */ 
TI_STATUS tmr_DestroyTimer (TI_HANDLE hTimerInfo)
{
    TTimerInfo *pTimerInfo = (TTimerInfo *)hTimerInfo;  /* The timer handle */     
    TTimerModule *pTimerModule;                  /* The timer module handle */

    if (!pTimerInfo)
    {
        return TI_NOK;
    }
    pTimerModule = (TTimerModule *)pTimerInfo->hTimerModule;
    if (!pTimerModule)
    {
        WLAN_OS_REPORT (("tmr_DestroyTimer(): ERROR - NULL timer!\n"));
        return TI_NOK;
    }

    /* Free the OS-API timer */
    if (pTimerInfo->hOsTimerObj) {
        os_timerDestroy (pTimerModule->hOs, pTimerInfo->hOsTimerObj);
        pTimerModule->uTimersCount--;  /* update created timers number */
    }
    /* Free the timer object */
    os_memoryFree (pTimerModule->hOs, hTimerInfo, sizeof(TTimerInfo));
    return TI_OK;
}


/** 
 * \fn     tmr_StartTimer
 * \brief  Start a timer
 * 
 * Start the specified timer running.
 * 
 * \note   Periodic-Timer may be used by applications that serve the timer expiry 
 *           in a single context.
 *         If an application can't finish serving the timer expiry in a single context, 
 *           e.g. periodic scan, then it isn't recommended to use the periodic timer service.
 *         If such an application uses the periodic timer then it should protect itself from cases
 *            where the timer expires again before the previous timer expiry processing is finished!!
 * \param  hTimerInfo    - The specific timer handle
 * \param  fExpiryCbFunc - The timer's expiry callback function.
 * \param  hExpiryCbHndl - The client's expiry callback function handle.
 * \param  uIntervalMsec - The timer's duration in Msec.
 * \param  bPeriodic     - If TRUE, the timer is restarted after expiry.
 * \return void
 * \sa     tmr_StopTimer, tmr_GetExpiry
 */ 
void tmr_StartTimer (TI_HANDLE     hTimerInfo,
                     TTimerCbFunc  fExpiryCbFunc,
                     TI_HANDLE     hExpiryCbHndl,
                     TI_UINT32     uIntervalMsec,
                     TI_BOOL       bPeriodic)
{
    TTimerInfo   *pTimerInfo   = (TTimerInfo *)hTimerInfo;                 /* The timer handle */     
    TTimerModule *pTimerModule = (TTimerModule *)pTimerInfo->hTimerModule; /* The timer module handle */

    if (!pTimerModule)
    {
        WLAN_OS_REPORT (("tmr_StartTimer(): ERROR - NULL timer!\n"));
        return;
    }

    /* Save the timer parameters. */
    pTimerInfo->fExpiryCbFunc            = fExpiryCbFunc;
    pTimerInfo->hExpiryCbHndl            = hExpiryCbHndl;
    pTimerInfo->uIntervalMsec            = uIntervalMsec;
    pTimerInfo->bPeriodic                = bPeriodic;
    pTimerInfo->bOperStateWhenStarted    = pTimerModule->bOperState;
    pTimerInfo->uTwdInitCountWhenStarted = pTimerModule->uTwdInitCount;

    /* Start OS-API timer running */
    os_timerStart(pTimerModule->hOs, pTimerInfo->hOsTimerObj, uIntervalMsec);
}


/** 
 * \fn     tmr_StopTimer
 * \brief  Stop a running timer
 * 
 * Stop the specified timer.
 * 
 * \note   When using this function, it must be considered that timer expiry may happen
 *           right before the timer is stopped, so it can't be assumed that this completely 
 *           prevents the timer expiry event!
 * \param  hTimerInfo - The specific timer handle
 * \return void
 * \sa     tmr_StartTimer
 */ 
void tmr_StopTimer (TI_HANDLE hTimerInfo)
{
    TTimerInfo   *pTimerInfo   = (TTimerInfo *)hTimerInfo;                 /* The timer handle */     
    TTimerModule *pTimerModule = (TTimerModule *)pTimerInfo->hTimerModule; /* The timer module handle */

    if (!pTimerModule)
    {
        WLAN_OS_REPORT (("tmr_StopTimer(): ERROR - NULL timer!\n"));
        return;
    }

    /* Stop OS-API timer running */
    os_timerStop(pTimerModule->hOs, pTimerInfo->hOsTimerObj);

    /* Clear periodic flag to prevent timer restart if we are in tmr_HandleExpiry context. */
    pTimerInfo->bPeriodic = TI_FALSE;
}


/** 
 * \fn     tmr_GetExpiry
 * \brief  Called by OS-API upon any timer expiry
 * 
 * This is the common callback function called upon expiartion of any timer.
 * It is called by the OS-API in timer expiry context and handles the transition
 *   to the driver's context for handling the expiry event.
 * 
 * \note   
 * \param  hTimerInfo - The specific timer handle
 * \return void
 * \sa     tmr_HandleExpiry
 */ 
void tmr_GetExpiry (TI_HANDLE hTimerInfo)
{
    TTimerInfo   *pTimerInfo   = (TTimerInfo *)hTimerInfo;                 /* The timer handle */     
    TTimerModule *pTimerModule = (TTimerModule *)pTimerInfo->hTimerModule; /* The timer module handle */

    if (!pTimerModule)
    {
        WLAN_OS_REPORT (("tmr_GetExpiry(): ERROR - NULL timer!\n"));
        return;
    }

    /* Enter critical section */
    context_EnterCriticalSection (pTimerModule->hContext);

    /* 
     * If the expired timer was started when the driver's state was Operational,
     *   insert it to the Operational-queue 
     */
    if (pTimerInfo->bOperStateWhenStarted)
    {
        que_Enqueue (pTimerModule->hOperQueue, hTimerInfo);
    }

    /* 
     * Else (started when driver's state was NOT-Operational), if now the state is still
     *   NOT Operational insert it to the Init-queue.
     *   (If state changed from non-operational to operational the event is ignored)
     */
    else if (!pTimerModule->bOperState)
    {
        que_Enqueue (pTimerModule->hInitQueue, hTimerInfo);
    }

    /* Leave critical section */
    context_LeaveCriticalSection (pTimerModule->hContext);

    /* Request switch to driver context for handling timer events */
    context_RequestSchedule (pTimerModule->hContext, pTimerModule->uContextId);
}


/** 
 * \fn     tmr_HandleExpiry
 * \brief  Handles queued expiry events in driver context
 * 
 * This is the Timer module's callback that is registered to the ContextEngine module to be invoked
 *   from the driver task (after requested by tmr_GetExpiry through context_RequestSchedule ()).
 * It dequeues all expiry events from the queue that correlates to the current driver state,
 *   and calls their users callbacks.
 * 
 * \note   
 * \param  hTimerModule - The module object
 * \return void
 * \sa     tmr_GetExpiry
 */ 
void tmr_HandleExpiry (TI_HANDLE hTimerModule)
{
    TTimerModule *pTimerModule = (TTimerModule *)hTimerModule; /* The timer module handle */
    TTimerInfo   *pTimerInfo;      /* The timer handle */     
    TI_BOOL       bTwdInitOccured; /* Indicates if TWD init occured since timer start */

    if (!pTimerModule)
    {
        WLAN_OS_REPORT (("tmr_HandleExpiry(): ERROR - NULL timer!\n"));
        return;
    }

    while (1)
    {
        /* Enter critical section */
        context_EnterCriticalSection (pTimerModule->hContext);
    
        /* If current driver state is Operational, dequeue timer object from Operational-queue */
        if (pTimerModule->bOperState)
        {
            pTimerInfo = (TTimerInfo *) que_Dequeue (pTimerModule->hOperQueue);
        }
    
        /* Else (driver state is NOT-Operational), dequeue timer object from Init-queue */
        else
        {
            pTimerInfo = (TTimerInfo *) que_Dequeue (pTimerModule->hInitQueue);
        }
    
        /* Leave critical section */
        context_LeaveCriticalSection (pTimerModule->hContext);

        /* If no more objects in queue, exit */
        if (!pTimerInfo) 
        {
            return;  /** EXIT Point **/
        }

        /* If current TWD-Init-Count is different than when the timer was started, Init occured. */
        bTwdInitOccured = (pTimerModule->uTwdInitCount != pTimerInfo->uTwdInitCountWhenStarted);

        /* Call specific timer callback function */
        pTimerInfo->fExpiryCbFunc (pTimerInfo->hExpiryCbHndl, bTwdInitOccured);

        /* If the expired timer is periodic, start it again. */
        if (pTimerInfo->bPeriodic) 
        {
            tmr_StartTimer ((TI_HANDLE)pTimerInfo,
                            pTimerInfo->fExpiryCbFunc,
                            pTimerInfo->hExpiryCbHndl,
                            pTimerInfo->uIntervalMsec,
                            pTimerInfo->bPeriodic);
        }
    }
}


/** 
 * \fn     tmr_PrintModule / tmr_PrintTimer
 * \brief  Print module / timer information
 * 
 * Print the module's information / a specific timer information.
 * 
 * \note   
 * \param  The module / timer handle
 * \return void
 * \sa     
 */ 

#ifdef TI_DBG

void tmr_PrintModule (TI_HANDLE hTimerModule)
{
    TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;

    if (!pTimerModule)
    {
        WLAN_OS_REPORT (("tmr_PrintModule(): ERROR - NULL timer!\n"));
        return;
    }

    /* Print module parameters */
    WLAN_OS_REPORT(("tmr_PrintModule(): uContextId=%d, bOperState=%d, uTwdInitCount=%d, uTimersCount=%d\n", 
    pTimerModule->uContextId, pTimerModule->bOperState, 
    pTimerModule->uTwdInitCount, pTimerModule->uTimersCount));

    /* Print Init Queue Info */
    WLAN_OS_REPORT(("tmr_PrintModule(): Init-Queue:\n")); 
    que_Print(pTimerModule->hInitQueue);

    /* Print Operational Queue Info */
    WLAN_OS_REPORT(("tmr_PrintModule(): Operational-Queue:\n")); 
    que_Print(pTimerModule->hOperQueue);
}

void tmr_PrintTimer (TI_HANDLE hTimerInfo)
{
#ifdef REPORT_LOG
    TTimerInfo   *pTimerInfo   = (TTimerInfo *)hTimerInfo;                 /* The timer handle */     

    WLAN_OS_REPORT(("tmr_PrintTimer(): uIntervalMs=%d, bPeriodic=%d, bOperStateWhenStarted=%d, uTwdInitCountWhenStarted=%d, hOsTimerObj=0x%x, fExpiryCbFunc=0x%x\n", 
    pTimerInfo->uIntervalMsec, pTimerInfo->bPeriodic, pTimerInfo->bOperStateWhenStarted, 
    pTimerInfo->uTwdInitCountWhenStarted, pTimerInfo->hOsTimerObj, pTimerInfo->fExpiryCbFunc));
#endif
}

#endif /* TI_DBG */