Home | History | Annotate | Download | only in utils
      1 /*
      2  * timer.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 
     35 /** \file   timer.c
     36  *  \brief  The timers services OS-Independent layer over the OS-API timer services which are OS-Dependent.
     37  *
     38  *  \see    timer.h, osapi.c
     39  */
     40 
     41 #include <linux/kernel.h>
     42 #define __FILE_ID__  FILE_ID_0
     43 #include "osApi.h"
     44 #include "report.h"
     45 #include "queue.h"
     46 #include "context.h"
     47 #include "timer.h"
     48 
     49 
     50 #define EXPIRY_QUE_SIZE  64  /* support case where all timers expire during recovery or error */
     51 
     52 /* The timer module structure (common to all timers) */
     53 typedef struct
     54 {
     55     TI_HANDLE   hOs;
     56     TI_HANDLE   hReport;
     57     TI_HANDLE   hContext;
     58     TI_UINT32   uContextId;     /* The ID allocated to this module on registration to context module */
     59     TI_HANDLE   hInitQueue;     /* Handle of the Init-Queue */
     60     TI_HANDLE   hOperQueue;     /* Handle of the Operational-Queue */
     61     TI_BOOL     bOperState;     /* TRUE when the driver is in operational state (not init or recovery) */
     62     TI_UINT32   uTwdInitCount;  /* Increments on each TWD init (i.e. recovery) */
     63     TI_UINT32   uTimersCount;   /* Number of created timers */
     64 } TTimerModule;
     65 
     66 /* Per timer structure */
     67 typedef struct
     68 {
     69     TI_HANDLE    hTimerModule;             /* The timer module handle (see TTimerModule, needed on expiry) */
     70     TI_HANDLE    hOsTimerObj;              /* The OS-API timer object handle */
     71     TQueNodeHdr  tQueNodeHdr;              /* The header used for queueing the timer */
     72     TTimerCbFunc fExpiryCbFunc;            /* The CB-function provided by the timer user for expiration */
     73     TI_HANDLE    hExpiryCbHndl;            /* The CB-function handle */
     74     TI_UINT32    uIntervalMsec;            /* The timer duration in Msec */
     75     TI_BOOL      bPeriodic;                /* If TRUE, restarted after each expiry */
     76     TI_BOOL      bOperStateWhenStarted;    /* The bOperState value when the timer was started */
     77     TI_UINT32    uTwdInitCountWhenStarted; /* The uTwdInitCount value when the timer was started */
     78 } TTimerInfo;
     79 
     80 
     81 
     82 
     83 /**
     84  * \fn     tmr_Create
     85  * \brief  Create the timer module
     86  *
     87  * Allocate and clear the timer module object.
     88  *
     89  * \note   This is NOT a specific timer creation! (see tmr_CreateTimer)
     90  * \param  hOs - Handle to Os Abstraction Layer
     91  * \return Handle of the allocated object
     92  * \sa     tmr_Destroy
     93  */
     94 TI_HANDLE tmr_Create (TI_HANDLE hOs)
     95 {
     96     TI_HANDLE hTimerModule;
     97 
     98     /* allocate module object */
     99     hTimerModule = os_memoryAlloc (hOs, sizeof(TTimerModule));
    100 
    101     if (!hTimerModule)
    102     {
    103         WLAN_OS_REPORT (("tmr_Create():  Allocation failed!!\n"));
    104         return NULL;
    105     }
    106 
    107     os_memoryZero (hOs, hTimerModule, (sizeof(TTimerModule)));
    108 
    109     return (hTimerModule);
    110 }
    111 
    112 
    113 /**
    114  * \fn     tmr_Destroy
    115  * \brief  Destroy the module.
    116  *
    117  * Free the module's queues and object.
    118  *
    119  * \note   This is NOT a specific timer destruction! (see tmr_DestroyTimer)
    120  * \param  hTimerModule - The module object
    121  * \return TI_OK on success or TI_NOK on failure
    122  * \sa     tmr_Create
    123  */
    124 TI_STATUS tmr_Destroy (TI_HANDLE hTimerModule)
    125 {
    126     TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;
    127 
    128     if (!pTimerModule)
    129     {
    130         WLAN_OS_REPORT (("tmr_Destroy(): ERROR - NULL timer!\n"));
    131         return TI_NOK;
    132     }
    133 
    134     /* Alert if there are still timers that were not destroyed */
    135     if (pTimerModule->uTimersCount)
    136     {
    137         WLAN_OS_REPORT (("tmr_Destroy():  ERROR - Destroying Timer module but not all timers were destroyed!!\n"));
    138     }
    139 #if 0
    140     /* Clear queues (critical section is used inside these functions) */
    141     tmr_ClearInitQueue (hTimerModule);
    142     tmr_ClearOperQueue (hTimerModule);
    143 #endif
    144     /* Destroy the module's queues (protect in critical section)) */
    145     context_EnterCriticalSection (pTimerModule->hContext);
    146     que_Destroy (pTimerModule->hInitQueue);
    147     que_Destroy (pTimerModule->hOperQueue);
    148     context_LeaveCriticalSection (pTimerModule->hContext);
    149 
    150     /* free module object */
    151     os_memoryFree (pTimerModule->hOs, pTimerModule, sizeof(TTimerModule));
    152 
    153     return TI_OK;
    154 }
    155 /**
    156  * \fn     tmr_Free
    157  * \brief  Free the memory.
    158  *
    159  * Free the module's queues and object.
    160  *
    161  * \param  hTimerModule - The module object
    162  * \return TI_OK on success or TI_NOK on failure
    163  * \sa     tmr_Create
    164  */
    165 TI_STATUS tmr_Free(TI_HANDLE hTimerModule)
    166 {
    167     TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;
    168 
    169     if (!pTimerModule)
    170     {
    171         WLAN_OS_REPORT (("tmr_Free(): ERROR - NULL timer!\n"));
    172         return TI_NOK;
    173     }
    174 
    175     /* free module object */
    176     os_memoryFree (pTimerModule->hOs, pTimerModule, sizeof(TTimerModule));
    177 
    178     return TI_OK;
    179 }
    180 
    181 
    182 /**
    183  * \fn     tmr_ClearInitQueue & tmr_ClearOperQueue
    184  * \brief  Clear Init/Operationsl queue
    185  *
    186  * Dequeue all queued timers.
    187  *
    188  * \note
    189  * \param  hTimerModule - The object
    190  * \return void
    191  * \sa
    192  */
    193 void tmr_ClearInitQueue (TI_HANDLE hTimerModule)
    194 {
    195     TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;
    196     TTimerInfo   *pTimerInfo;      /* The timer handle */
    197 
    198     do {
    199         context_EnterCriticalSection (pTimerModule->hContext);
    200         pTimerInfo = que_Dequeue (pTimerModule->hInitQueue);
    201         context_LeaveCriticalSection (pTimerModule->hContext);
    202     } while (pTimerInfo != NULL);
    203 }
    204 
    205 void tmr_ClearOperQueue (TI_HANDLE hTimerModule)
    206 {
    207     TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;
    208     TTimerInfo   *pTimerInfo;      /* The timer handle */
    209 
    210     do {
    211         context_EnterCriticalSection (pTimerModule->hContext);
    212         pTimerInfo = que_Dequeue (pTimerModule->hOperQueue);
    213         context_LeaveCriticalSection (pTimerModule->hContext);
    214     } while (pTimerInfo != NULL);
    215 }
    216 
    217 
    218 /**
    219  * \fn     tmr_Init
    220  * \brief  Init required handles
    221  *
    222  * Init required handles and module variables, create the init-queue and
    223  *     operational-queue, and register as the context-engine client.
    224  *
    225  * \note
    226  * \param  hTimerModule  - The queue object
    227  * \param  hOs       - Handle to Os Abstraction Layer
    228  * \param  hReport   - Handle to report module
    229  * \param  hContext  - Handle to context module
    230  * \return void
    231  * \sa
    232  */
    233 void tmr_Init (TI_HANDLE hTimerModule, TI_HANDLE hOs, TI_HANDLE hReport, TI_HANDLE hContext)
    234 {
    235     TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;
    236     TI_UINT32     uNodeHeaderOffset;
    237 
    238     if (!pTimerModule)
    239     {
    240         WLAN_OS_REPORT (("tmr_Init(): ERROR - NULL timer!\n"));
    241         return;
    242     }
    243 
    244     pTimerModule->hOs           = hOs;
    245     pTimerModule->hReport       = hReport;
    246     pTimerModule->hContext      = hContext;
    247 
    248     pTimerModule->bOperState    = TI_FALSE;
    249     pTimerModule->uTimersCount  = 0;
    250     pTimerModule->uTwdInitCount = 0;
    251 
    252     /* The offset of the queue-node-header from timer structure entry is needed by the queue */
    253     uNodeHeaderOffset = TI_FIELD_OFFSET(TTimerInfo, tQueNodeHdr);
    254 
    255     /* Create and initialize the Init and Operational queues (for timers expiry events) */
    256     pTimerModule->hInitQueue = que_Create (pTimerModule->hOs,
    257                                            pTimerModule->hReport,
    258                                            EXPIRY_QUE_SIZE,
    259                                            uNodeHeaderOffset);
    260     pTimerModule->hOperQueue = que_Create (pTimerModule->hOs,
    261                                            pTimerModule->hReport,
    262                                            EXPIRY_QUE_SIZE,
    263                                            uNodeHeaderOffset);
    264 
    265     /* Register to the context engine and get the client ID */
    266     pTimerModule->uContextId = context_RegisterClient (pTimerModule->hContext,
    267                                                        tmr_HandleExpiry,
    268                                                        hTimerModule,
    269                                                        TI_TRUE,
    270                                                        "TIMER",
    271                                                        sizeof("TIMER"));
    272 }
    273 
    274 
    275 /**
    276  * \fn     tmr_UpdateDriverState
    277  * \brief  Update driver state
    278  *
    279  * Under critical section, update driver state (operational or not),
    280  *   and if opertional, clear init queue.
    281  * Leave critical section and if operational state, request schedule for handling
    282  *   timer events in driver context (if any).
    283  *
    284  * \note
    285  * \param  hTimerModule - The timer module object
    286  * \param  bOperState   - TRUE if driver state is now operational, FALSE if not.
    287  * \return void
    288  * \sa
    289  */
    290 void tmr_UpdateDriverState (TI_HANDLE hTimerModule, TI_BOOL bOperState)
    291 {
    292     TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;
    293     TTimerInfo   *pTimerInfo;      /* The timer handle */
    294 
    295     if (!pTimerModule)
    296     {
    297         WLAN_OS_REPORT (("tmr_UpdateDriverState(): ERROR - NULL timer!\n"));
    298         return;
    299     }
    300 
    301     /* Enter critical section */
    302     context_EnterCriticalSection (pTimerModule->hContext);
    303 
    304     if (bOperState == pTimerModule->bOperState)
    305     {
    306         context_LeaveCriticalSection (pTimerModule->hContext);
    307         TRACE1(pTimerModule->hReport, REPORT_SEVERITY_ERROR, "tmr_UpdateDriverState(): New bOperState (%d) is as current!\n", bOperState);
    308         return;
    309     }
    310 
    311     /* Save new state (TRUE means operational). */
    312     pTimerModule->bOperState = bOperState;
    313 
    314     /* If new state is operational */
    315     if (bOperState)
    316     {
    317         /* Increment the TWD initializations counter (for detecting recovery events). */
    318         pTimerModule->uTwdInitCount++;
    319     }
    320 
    321     /* Leave critical section */
    322     context_LeaveCriticalSection (pTimerModule->hContext);
    323 
    324     /* If new state is operational */
    325     if (bOperState)
    326     {
    327         /* Empty the init queue (obsolete). */
    328         do {
    329             context_EnterCriticalSection (pTimerModule->hContext);
    330             pTimerInfo = que_Dequeue (pTimerModule->hInitQueue);
    331             context_LeaveCriticalSection (pTimerModule->hContext);
    332         } while (pTimerInfo != NULL);
    333     }
    334 
    335     /* If new state is operational, request switch to driver context for handling timer events */
    336     if (bOperState)
    337     {
    338         context_RequestSchedule (pTimerModule->hContext, pTimerModule->uContextId);
    339     }
    340 }
    341 
    342 
    343 
    344 /**
    345  * \fn     tmr_CreateTimer
    346  * \brief  Create a new timer
    347  *
    348  * Create a new timer object, icluding creating a timer in the OS-API.
    349  *
    350  * \note   This timer creation may be used only after tmr_Create() and tmr_Init() were executed!!
    351  * \param  hTimerModule - The module handle
    352  * \return TI_HANDLE    - The created timer handle
    353  * \sa     tmr_DestroyTimer
    354  */
    355 TI_HANDLE tmr_CreateTimer (TI_HANDLE hTimerModule)
    356 {
    357     TTimerModule *pTimerModule = (TTimerModule *)hTimerModule; /* The timer module handle */
    358     TTimerInfo   *pTimerInfo;  /* The created timer handle */
    359 
    360     if (!pTimerModule)
    361     {
    362         WLAN_OS_REPORT (("tmr_CreateTimer(): ERROR - NULL timer!\n"));
    363         return NULL;
    364     }
    365 
    366     /* Allocate timer object */
    367     pTimerInfo = os_memoryAlloc (pTimerModule->hOs, sizeof(TTimerInfo));
    368     if (!pTimerInfo)
    369     {
    370         WLAN_OS_REPORT (("tmr_CreateTimer():  Timer allocation failed!!\n"));
    371         return NULL;
    372     }
    373     os_memoryZero (pTimerModule->hOs, pTimerInfo, (sizeof(TTimerInfo)));
    374 
    375     /* Allocate OS-API timer, providing the common expiry callback with the current timer handle */
    376     pTimerInfo->hOsTimerObj = os_timerCreate(pTimerModule->hOs, tmr_GetExpiry, (TI_HANDLE)pTimerInfo);
    377     if (!pTimerInfo->hOsTimerObj)
    378     {
    379         TRACE0(pTimerModule->hReport, REPORT_SEVERITY_CONSOLE ,"tmr_CreateTimer():  OS-API Timer allocation failed!!\n");
    380         os_memoryFree (pTimerModule->hOs, pTimerInfo, sizeof(TTimerInfo));
    381         WLAN_OS_REPORT (("tmr_CreateTimer():  OS-API Timer allocation failed!!\n"));
    382         return NULL;
    383     }
    384 
    385     /* Save the timer module handle in the created timer object (needed for the expiry callback) */
    386     pTimerInfo->hTimerModule = hTimerModule;
    387     pTimerModule->uTimersCount++;  /* count created timers */
    388 
    389     /* Return the created timer handle */
    390     return (TI_HANDLE)pTimerInfo;
    391 }
    392 
    393 
    394 /**
    395  * \fn     tmr_DestroyTimer
    396  * \brief  Destroy the specified timer
    397  *
    398  * Destroy the specified timer object, icluding the timer in the OS-API.
    399  *
    400  * \note   This timer destruction function should be used before tmr_Destroy() is executed!!
    401  * \param  hTimerInfo - The timer handle
    402  * \return TI_OK on success or TI_NOK on failure
    403  * \sa     tmr_CreateTimer
    404  */
    405 TI_STATUS tmr_DestroyTimer (TI_HANDLE hTimerInfo)
    406 {
    407     TTimerInfo *pTimerInfo = (TTimerInfo *)hTimerInfo;  /* The timer handle */
    408     TTimerModule *pTimerModule;                  /* The timer module handle */
    409 
    410     if (!pTimerInfo)
    411     {
    412         return TI_NOK;
    413     }
    414     pTimerModule = (TTimerModule *)pTimerInfo->hTimerModule;
    415     if (!pTimerModule)
    416     {
    417         WLAN_OS_REPORT (("tmr_DestroyTimer(): ERROR - NULL timer!\n"));
    418         return TI_NOK;
    419     }
    420 
    421     /* Free the OS-API timer */
    422     if (pTimerInfo->hOsTimerObj) {
    423         os_timerDestroy (pTimerModule->hOs, pTimerInfo->hOsTimerObj);
    424         pTimerModule->uTimersCount--;  /* update created timers number */
    425     }
    426     /* Free the timer object */
    427     os_memoryFree (pTimerModule->hOs, hTimerInfo, sizeof(TTimerInfo));
    428     return TI_OK;
    429 }
    430 
    431 
    432 /**
    433  * \fn     tmr_StartTimer
    434  * \brief  Start a timer
    435  *
    436  * Start the specified timer running.
    437  *
    438  * \note   Periodic-Timer may be used by applications that serve the timer expiry
    439  *           in a single context.
    440  *         If an application can't finish serving the timer expiry in a single context,
    441  *           e.g. periodic scan, then it isn't recommended to use the periodic timer service.
    442  *         If such an application uses the periodic timer then it should protect itself from cases
    443  *            where the timer expires again before the previous timer expiry processing is finished!!
    444  * \param  hTimerInfo    - The specific timer handle
    445  * \param  fExpiryCbFunc - The timer's expiry callback function.
    446  * \param  hExpiryCbHndl - The client's expiry callback function handle.
    447  * \param  uIntervalMsec - The timer's duration in Msec.
    448  * \param  bPeriodic     - If TRUE, the timer is restarted after expiry.
    449  * \return void
    450  * \sa     tmr_StopTimer, tmr_GetExpiry
    451  */
    452 void tmr_StartTimer (TI_HANDLE     hTimerInfo,
    453                      TTimerCbFunc  fExpiryCbFunc,
    454                      TI_HANDLE     hExpiryCbHndl,
    455                      TI_UINT32     uIntervalMsec,
    456                      TI_BOOL       bPeriodic)
    457 {
    458     TTimerInfo   *pTimerInfo   = (TTimerInfo *)hTimerInfo;                 /* The timer handle */
    459     TTimerModule *pTimerModule = (TTimerModule *)pTimerInfo->hTimerModule; /* The timer module handle */
    460 
    461     if (!pTimerModule)
    462     {
    463         WLAN_OS_REPORT (("tmr_StartTimer(): ERROR - NULL timer!\n"));
    464         return;
    465     }
    466 
    467     /* Save the timer parameters. */
    468     pTimerInfo->fExpiryCbFunc            = fExpiryCbFunc;
    469     pTimerInfo->hExpiryCbHndl            = hExpiryCbHndl;
    470     pTimerInfo->uIntervalMsec            = uIntervalMsec;
    471     pTimerInfo->bPeriodic                = bPeriodic;
    472     pTimerInfo->bOperStateWhenStarted    = pTimerModule->bOperState;
    473     pTimerInfo->uTwdInitCountWhenStarted = pTimerModule->uTwdInitCount;
    474 
    475     /* Start OS-API timer running */
    476     os_timerStart(pTimerModule->hOs, pTimerInfo->hOsTimerObj, uIntervalMsec);
    477 }
    478 
    479 
    480 /**
    481  * \fn     tmr_StopTimer
    482  * \brief  Stop a running timer
    483  *
    484  * Stop the specified timer.
    485  *
    486  * \note   When using this function, it must be considered that timer expiry may happen
    487  *           right before the timer is stopped, so it can't be assumed that this completely
    488  *           prevents the timer expiry event!
    489  * \param  hTimerInfo - The specific timer handle
    490  * \return void
    491  * \sa     tmr_StartTimer
    492  */
    493 void tmr_StopTimer (TI_HANDLE hTimerInfo)
    494 {
    495     TTimerInfo   *pTimerInfo   = (TTimerInfo *)hTimerInfo;                 /* The timer handle */
    496     TTimerModule *pTimerModule = (TTimerModule *)pTimerInfo->hTimerModule; /* The timer module handle */
    497 
    498     if (!pTimerModule)
    499     {
    500         WLAN_OS_REPORT (("tmr_StopTimer(): ERROR - NULL timer!\n"));
    501         return;
    502     }
    503 
    504     /* Stop OS-API timer running */
    505     os_timerStop(pTimerModule->hOs, pTimerInfo->hOsTimerObj);
    506 
    507     /* Clear periodic flag to prevent timer restart if we are in tmr_HandleExpiry context. */
    508     pTimerInfo->bPeriodic = TI_FALSE;
    509 }
    510 
    511 
    512 /**
    513  * \fn     tmr_GetExpiry
    514  * \brief  Called by OS-API upon any timer expiry
    515  *
    516  * This is the common callback function called upon expiartion of any timer.
    517  * It is called by the OS-API in timer expiry context and handles the transition
    518  *   to the driver's context for handling the expiry event.
    519  *
    520  * \note
    521  * \param  hTimerInfo - The specific timer handle
    522  * \return void
    523  * \sa     tmr_HandleExpiry
    524  */
    525 void tmr_GetExpiry (TI_HANDLE hTimerInfo)
    526 {
    527     TTimerInfo   *pTimerInfo   = (TTimerInfo *)hTimerInfo;                 /* The timer handle */
    528     TTimerModule *pTimerModule = (TTimerModule *)pTimerInfo->hTimerModule; /* The timer module handle */
    529 
    530     if (!pTimerModule)
    531     {
    532         WLAN_OS_REPORT (("tmr_GetExpiry(): ERROR - NULL timer!\n"));
    533         return;
    534     }
    535 
    536     /* Enter critical section */
    537     context_EnterCriticalSection (pTimerModule->hContext);
    538 
    539     /*
    540      * If the expired timer was started when the driver's state was Operational,
    541      *   insert it to the Operational-queue
    542      */
    543     if (pTimerInfo->bOperStateWhenStarted)
    544     {
    545         que_Enqueue (pTimerModule->hOperQueue, hTimerInfo);
    546     }
    547 
    548     /*
    549      * Else (started when driver's state was NOT-Operational), if now the state is still
    550      *   NOT Operational insert it to the Init-queue.
    551      *   (If state changed from non-operational to operational the event is ignored)
    552      */
    553     else if (!pTimerModule->bOperState)
    554     {
    555         que_Enqueue (pTimerModule->hInitQueue, hTimerInfo);
    556     }
    557 
    558     /* Leave critical section */
    559     context_LeaveCriticalSection (pTimerModule->hContext);
    560 
    561     /* Request switch to driver context for handling timer events */
    562     context_RequestSchedule (pTimerModule->hContext, pTimerModule->uContextId);
    563 }
    564 
    565 
    566 /**
    567  * \fn     tmr_HandleExpiry
    568  * \brief  Handles queued expiry events in driver context
    569  *
    570  * This is the Timer module's callback that is registered to the ContextEngine module to be invoked
    571  *   from the driver task (after requested by tmr_GetExpiry through context_RequestSchedule ()).
    572  * It dequeues all expiry events from the queue that correlates to the current driver state,
    573  *   and calls their users callbacks.
    574  *
    575  * \note
    576  * \param  hTimerModule - The module object
    577  * \return void
    578  * \sa     tmr_GetExpiry
    579  */
    580 void tmr_HandleExpiry (TI_HANDLE hTimerModule)
    581 {
    582     TTimerModule *pTimerModule = (TTimerModule *)hTimerModule; /* The timer module handle */
    583     TTimerInfo   *pTimerInfo;      /* The timer handle */
    584     TI_BOOL       bTwdInitOccured; /* Indicates if TWD init occured since timer start */
    585 
    586     if (!pTimerModule)
    587     {
    588         WLAN_OS_REPORT (("tmr_HandleExpiry(): ERROR - NULL timer!\n"));
    589         return;
    590     }
    591 
    592     while (1)
    593     {
    594         /* Enter critical section */
    595         context_EnterCriticalSection (pTimerModule->hContext);
    596 
    597         /* If current driver state is Operational, dequeue timer object from Operational-queue */
    598         if (pTimerModule->bOperState)
    599         {
    600             pTimerInfo = (TTimerInfo *) que_Dequeue (pTimerModule->hOperQueue);
    601         }
    602 
    603         /* Else (driver state is NOT-Operational), dequeue timer object from Init-queue */
    604         else
    605         {
    606             pTimerInfo = (TTimerInfo *) que_Dequeue (pTimerModule->hInitQueue);
    607         }
    608 
    609         /* Leave critical section */
    610         context_LeaveCriticalSection (pTimerModule->hContext);
    611 
    612         /* If no more objects in queue, exit */
    613         if (!pTimerInfo)
    614         {
    615             return;  /** EXIT Point **/
    616         }
    617 
    618         /* If current TWD-Init-Count is different than when the timer was started, Init occured. */
    619         bTwdInitOccured = (pTimerModule->uTwdInitCount != pTimerInfo->uTwdInitCountWhenStarted);
    620 
    621         /* Call specific timer callback function */
    622         pTimerInfo->fExpiryCbFunc (pTimerInfo->hExpiryCbHndl, bTwdInitOccured);
    623 
    624         /* If the expired timer is periodic, start it again. */
    625         if (pTimerInfo->bPeriodic)
    626         {
    627             tmr_StartTimer ((TI_HANDLE)pTimerInfo,
    628                             pTimerInfo->fExpiryCbFunc,
    629                             pTimerInfo->hExpiryCbHndl,
    630                             pTimerInfo->uIntervalMsec,
    631                             pTimerInfo->bPeriodic);
    632         }
    633     }
    634 }
    635 
    636 
    637 /**
    638  * \fn     tmr_PrintModule / tmr_PrintTimer
    639  * \brief  Print module / timer information
    640  *
    641  * Print the module's information / a specific timer information.
    642  *
    643  * \note
    644  * \param  The module / timer handle
    645  * \return void
    646  * \sa
    647  */
    648 
    649 #ifdef TI_DBG
    650 
    651 void tmr_PrintModule (TI_HANDLE hTimerModule)
    652 {
    653     TTimerModule *pTimerModule = (TTimerModule *)hTimerModule;
    654 
    655     if (!pTimerModule)
    656     {
    657         WLAN_OS_REPORT (("tmr_PrintModule(): ERROR - NULL timer!\n"));
    658         return;
    659     }
    660 
    661     /* Print module parameters */
    662     WLAN_OS_REPORT(("tmr_PrintModule(): uContextId=%d, bOperState=%d, uTwdInitCount=%d, uTimersCount=%d\n",
    663     pTimerModule->uContextId, pTimerModule->bOperState,
    664     pTimerModule->uTwdInitCount, pTimerModule->uTimersCount));
    665 
    666     /* Print Init Queue Info */
    667     WLAN_OS_REPORT(("tmr_PrintModule(): Init-Queue:\n"));
    668     que_Print(pTimerModule->hInitQueue);
    669 
    670     /* Print Operational Queue Info */
    671     WLAN_OS_REPORT(("tmr_PrintModule(): Operational-Queue:\n"));
    672     que_Print(pTimerModule->hOperQueue);
    673 }
    674 
    675 void tmr_PrintTimer (TI_HANDLE hTimerInfo)
    676 {
    677 #ifdef REPORT_LOG
    678     TTimerInfo   *pTimerInfo   = (TTimerInfo *)hTimerInfo;                 /* The timer handle */
    679 
    680     WLAN_OS_REPORT(("tmr_PrintTimer(): uIntervalMs=%d, bPeriodic=%d, bOperStateWhenStarted=%d, uTwdInitCountWhenStarted=%d, hOsTimerObj=0x%x, fExpiryCbFunc=0x%x\n",
    681     pTimerInfo->uIntervalMsec, pTimerInfo->bPeriodic, pTimerInfo->bOperStateWhenStarted,
    682     pTimerInfo->uTwdInitCountWhenStarted, pTimerInfo->hOsTimerObj, pTimerInfo->fExpiryCbFunc));
    683 #endif
    684 }
    685 
    686 #endif /* TI_DBG */
    687