• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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: Jérémie 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 
phOsalNfc_Timer_DeferredCall(void * params)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  */
phOsalNfc_Timer_Expired(union sigval sv)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 
phOsalNfc_Timer_Dummy_Cb(uint32_t timerid,void * pContext)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  */
phOsalNfc_Timer_Create(void)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  */
phOsalNfc_Timer_Start(uint32_t TimerId,uint32_t RegTimeCnt,ppCallBck_t Application_callback,void * pContext)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  */
phOsalNfc_Timer_Stop(uint32_t TimerId)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  */
phOsalNfc_Timer_Delete(uint32_t TimerId)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