Home | History | Annotate | Download | only in Linux_x86
      1 /*
      2  * Copyright (C) 2010 NXP Semiconductors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /**
     18  * \file phOsalNfc_Timer.c
     19  * \brief OSAL Timer Implementation for linux
     20  *
     21  * Project: Trusted NFC Linux Light
     22  *
     23  * $Date: 03 aug 2009
     24  * $Author: Jrmie Corbier
     25  * $Revision: 1.0
     26  *
     27  */
     28 
     29 #include <stdlib.h>
     30 #include <signal.h>
     31 #include <time.h>
     32 
     33 #include <phOsalNfc.h>
     34 #include <phOsalNfc_Timer.h>
     35 #include <stdio.h>
     36 
     37 #include <phDal4Nfc_messageQueueLib.h>
     38 
     39 #define NSECS 1000000
     40 #define MAX_NO_TIMERS 16
     41 
     42 /*!
     43  * \struct phOsalNfc_Timer
     44  * Internal OSAL timer structure
     45  */
     46 struct phOsalNfc_Timer
     47 {
     48    timer_t handle;         /*!< System timer handle. */
     49    ppCallBck_t callback;   /*!< Callback to be called when timer expires. */
     50    void* pContext;         /*!< Callback context. */
     51 #ifdef NXP_MESSAGING
     52    void *ptr;
     53 #endif
     54    int nIsStopped;
     55 };
     56 
     57 static struct phOsalNfc_Timer timers[MAX_NO_TIMERS] =
     58 {
     59    {0, NULL, NULL
     60 #ifdef NXP_MESSAGING
     61      , NULL
     62 #endif
     63      , 0
     64    },
     65 };
     66 
     67 #ifdef NXP_MESSAGING
     68 extern int nDeferedCallMessageQueueId;
     69 
     70 void phOsalNfc_Timer_DeferredCall(void *params)
     71 {
     72    phOsalNfc_Timer_Msg_t *timer_msg;
     73 
     74    if(params == NULL)
     75       return;
     76 
     77    timer_msg = (phOsalNfc_Timer_Msg_t *)params;
     78 
     79    if((timer_msg != NULL) && (timer_msg->pCallBck != NULL))
     80       timer_msg->pCallBck(timer_msg->TimerId, timer_msg->pContext);
     81 
     82    if ((timer_msg->TimerId >= MAX_NO_TIMERS) || (timer_msg->TimerId < 0))
     83    {
     84       printf("Bad TimerId=%d, should be <= to %d\n", timer_msg->TimerId, MAX_NO_TIMERS);
     85    }
     86    else
     87    {
     88       if(timers[timer_msg->TimerId].ptr != NULL)
     89       {
     90          phOsalNfc_FreeMemory(timers[timer_msg->TimerId].ptr);
     91          timers[timer_msg->TimerId].ptr = NULL;
     92       }
     93    }
     94    phOsalNfc_FreeMemory(timer_msg);
     95 }
     96 #endif
     97 
     98 /*!
     99  * \brief System timer callback.
    100  *        This callback is called by Linux whenever one the timers expires.  It
    101  *        calls the corresponding registered callback.
    102  *
    103  * \param sv structure storing the expired timer ID.
    104  */
    105 static void phOsalNfc_Timer_Expired(union sigval sv)
    106 {
    107    uint32_t timerid = (uint32_t)(sv.sival_int);
    108 
    109    if((timerid < MAX_NO_TIMERS)&&(timers[timerid].nIsStopped == 1))
    110    {
    111       //printf("phOsalNfc_Timer_Expired : Expired but already stopped TimerId=%d\n", timerid);
    112       return;
    113    }
    114 
    115    if(timerid < MAX_NO_TIMERS)
    116    {
    117 #ifndef CYCLIC_TIMER
    118       phOsalNfc_Timer_Stop(timerid);
    119 #else
    120 
    121 #endif
    122 #ifdef NXP_MESSAGING
    123       phOsalNfc_Timer_Msg_t *timer_msg;
    124       phOsalNfc_DeferedCalldInfo_t *osal_defer_msg;
    125       phDal4Nfc_Message_Wrapper_t wrapper;
    126 
    127       timer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_Timer_Msg_t));
    128       if(timer_msg == NULL)
    129          phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0);
    130 
    131       osal_defer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_DeferedCalldInfo_t));
    132       if(osal_defer_msg == NULL)
    133       {
    134          phOsalNfc_FreeMemory(timer_msg);
    135          phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0);
    136       }
    137 
    138       timer_msg->TimerId = timerid;
    139       timer_msg->pCallBck = timers[timerid].callback;
    140       timer_msg->pContext = timers[timerid].pContext;
    141 
    142       osal_defer_msg->pCallback = phOsalNfc_Timer_DeferredCall;
    143       osal_defer_msg->pParameter = timer_msg;
    144 
    145       wrapper.mtype = 1;
    146       wrapper.msg.eMsgType = PH_OSALNFC_TIMER_MSG;
    147       wrapper.msg.pMsgData = osal_defer_msg;
    148       wrapper.msg.Size = sizeof(phOsalNfc_DeferedCalldInfo_t);
    149 
    150       timers[timerid].ptr = osal_defer_msg;
    151 
    152       phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (void *)&wrapper,
    153          sizeof(phOsalNfc_Message_t), 0);
    154 #else
    155       (timers[timerid].callback)(timerid, timers[timerid].pContext);
    156 #endif
    157    }
    158 }
    159 
    160 static void phOsalNfc_Timer_Dummy_Cb(uint32_t timerid, void *pContext) {}
    161 
    162 /*!
    163  * \brief Creates a new timer.
    164  *        This function checks whether there is an available timer slot.  If
    165  *        this is the case, then it reserves it for future usage and returns its
    166  *        ID.
    167  *
    168  * \return a valid timer ID or PH_OSALNFC_INVALID_TIMER_ID if an error occured.
    169  */
    170 uint32_t phOsalNfc_Timer_Create(void)
    171 {
    172    uint32_t timerid;
    173    struct sigevent se;
    174 
    175    se.sigev_notify = SIGEV_THREAD;
    176    se.sigev_notify_function = phOsalNfc_Timer_Expired;
    177    se.sigev_notify_attributes = NULL;
    178 
    179    /* Look for available timer slot */
    180    for(timerid = 0; timerid < MAX_NO_TIMERS; timerid++)
    181       if(timers[timerid].callback == NULL)
    182          break;
    183    if(timerid == MAX_NO_TIMERS)
    184       return PH_OSALNFC_INVALID_TIMER_ID;
    185 
    186    se.sigev_value.sival_int = (int)timerid;
    187 
    188    /* Create POSIX timer */
    189    if(timer_create(CLOCK_REALTIME, &se, &(timers[timerid].handle)) == -1)
    190       return PH_OSALNFC_INVALID_TIMER_ID;
    191    timers[timerid].callback = phOsalNfc_Timer_Dummy_Cb;
    192 #ifdef NXP_MESSAGING
    193    timers[timerid].ptr = NULL;
    194 #endif
    195 
    196    return timerid;
    197 }
    198 
    199 /*!
    200  * \brief Starts a timer.
    201  *        This function starts the timer \a TimerId with an expiration time of
    202  *        \a RegTimeCnt milliseconds.  Each time it expires, \a
    203  *        Application_callback is called.
    204  *
    205  * \param TimerId a valid timer ID.
    206  * \param RegTimeCnt expiration time in milliseconds.
    207  * \param Application_callback callback to be called when timer expires.
    208  */
    209 void phOsalNfc_Timer_Start(uint32_t TimerId,
    210                            uint32_t RegTimeCnt,
    211                            ppCallBck_t  Application_callback,
    212                            void *pContext)
    213 {
    214    struct itimerspec its;
    215 
    216    if(TimerId >= MAX_NO_TIMERS)
    217       return;
    218    if(Application_callback == NULL)
    219       return;
    220    if(timers[TimerId].callback == NULL)
    221       return;
    222 
    223    its.it_interval.tv_sec  = 0;
    224    its.it_interval.tv_nsec = 0;
    225    its.it_value.tv_sec     = RegTimeCnt / 1000;
    226    its.it_value.tv_nsec    = 1000000 * (RegTimeCnt % 1000);
    227    if(its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0)
    228    {
    229      // this would inadvertently stop the timer
    230      its.it_value.tv_nsec = 1;
    231    }
    232 
    233    timers[TimerId].callback = Application_callback;
    234    timers[TimerId].pContext = pContext;
    235    timers[TimerId].nIsStopped = 0;
    236 
    237    timer_settime(timers[TimerId].handle, 0, &its, NULL);
    238 }
    239 
    240 /*!
    241  * \brief Stops a timer.
    242  *        This function stops an already started timer.
    243  *
    244  * \param TimerId a valid timer ID.
    245  */
    246 void phOsalNfc_Timer_Stop(uint32_t TimerId)
    247 {
    248    struct itimerspec its = {{0, 0}, {0, 0}};
    249 
    250    if(TimerId >= MAX_NO_TIMERS)
    251       return;
    252    if(timers[TimerId].callback == NULL)
    253       return;
    254    if(timers[TimerId].nIsStopped == 1)
    255       return;
    256 
    257    timers[TimerId].nIsStopped = 1;
    258    timer_settime(timers[TimerId].handle, 0, &its, NULL);
    259 }
    260 
    261 /*!
    262  * \brief Deletes a timer.
    263  *        This function deletes a timer.
    264  *
    265  * \param TimerId a valid timer ID.
    266  */
    267 void phOsalNfc_Timer_Delete(uint32_t TimerId)
    268 {
    269    if(TimerId >= MAX_NO_TIMERS)
    270       return;
    271    if(timers[TimerId].callback == NULL)
    272       return;
    273 
    274    timer_delete(timers[TimerId].handle);
    275 
    276    timers[TimerId].callback = NULL;
    277    timers[TimerId].pContext = NULL;
    278 }
    279