2 * Copyright (C) 2010 NXP Semiconductors
3 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 * \file phOsalNfc_Timer.c
20 * \brief OSAL Timer Implementation for linux
22 * Project: Trusted NFC Linux Light
25 * $Author: Jérémie Corbier
34 #include <phOsalNfc.h>
35 #include <phOsalNfc_Timer.h>
38 #include <phDal4Nfc_messageQueueLib.h>
39 #include <phDal4Nfc_message_glib.h>
42 #define MAX_NO_TIMERS 16
45 * \struct phOsalNfc_Timer
46 * Internal OSAL timer structure
48 struct phOsalNfc_Timer
50 timer_t handle; /*!< System timer handle. */
51 ppCallBck_t callback; /*!< Callback to be called when timer expires. */
52 void* pContext; /*!< Callback context. */
59 static struct phOsalNfc_Timer timers[MAX_NO_TIMERS] =
70 extern int nDeferedCallMessageQueueId;
72 void phOsalNfc_Timer_DeferredCall(void *params)
74 phOsalNfc_Timer_Msg_t *timer_msg;
79 timer_msg = (phOsalNfc_Timer_Msg_t *)params;
81 if((timer_msg != NULL) && (timer_msg->pCallBck != NULL))
82 timer_msg->pCallBck(timer_msg->TimerId, timer_msg->pContext);
84 if ((timer_msg->TimerId >= MAX_NO_TIMERS) /*|| (timer_msg->TimerId < 0)*/ /*prevent fix */)
86 //printf("Bad TimerId=%d, should be <= to %d\n", timer_msg->TimerId, MAX_NO_TIMERS);
90 if(timers[timer_msg->TimerId].ptr != NULL)
92 phOsalNfc_FreeMemory(timers[timer_msg->TimerId].ptr);
93 timers[timer_msg->TimerId].ptr = NULL;
96 phOsalNfc_FreeMemory(timer_msg);
101 * \brief System timer callback.
102 * This callback is called by Linux whenever one the timers expires. It
103 * calls the corresponding registered callback.
105 * \param sv structure storing the expired timer ID.
107 static void phOsalNfc_Timer_Expired(union sigval sv)
109 uint32_t timerid = (uint32_t)(sv.sival_int);
111 if((timerid < MAX_NO_TIMERS)&&(timers[timerid].nIsStopped == 1))
113 //printf("phOsalNfc_Timer_Expired : Expired but already stopped TimerId=%d\n", timerid);
117 if(timerid < MAX_NO_TIMERS)
120 phOsalNfc_Timer_Stop(timerid);
125 phOsalNfc_Timer_Msg_t *timer_msg;
126 phOsalNfc_DeferedCalldInfo_t *osal_defer_msg;
127 phDal4Nfc_Message_Wrapper_t wrapper;
129 timer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_Timer_Msg_t));
130 if(timer_msg == NULL)
132 phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0);
136 osal_defer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_DeferedCalldInfo_t));
137 if(osal_defer_msg == NULL)
139 phOsalNfc_FreeMemory(timer_msg);
140 phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0);
144 timer_msg->TimerId = timerid;
145 timer_msg->pCallBck = timers[timerid].callback;
146 timer_msg->pContext = timers[timerid].pContext;
148 osal_defer_msg->pCallback = phOsalNfc_Timer_DeferredCall;
149 osal_defer_msg->pParameter = timer_msg;
152 wrapper.msg.eMsgType = PH_OSALNFC_TIMER_MSG;
153 wrapper.msg.pMsgData = osal_defer_msg;
154 wrapper.msg.Size = sizeof(phOsalNfc_DeferedCalldInfo_t);
156 timers[timerid].ptr = osal_defer_msg;
157 #ifndef G_IDLE_ADD_MSGQ
158 phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (void *)&wrapper, sizeof(phOsalNfc_Message_t), 0);
160 PostMessage((void *)&wrapper, sizeof(phOsalNfc_Message_t), 0);
162 //(timers[timerid].callback)(timerid, timers[timerid].pContext);
167 static void phOsalNfc_Timer_Dummy_Cb(uint32_t timerid, void *pContext) {}
170 * \brief Creates a new timer.
171 * This function checks whether there is an available timer slot. If
172 * this is the case, then it reserves it for future usage and returns its
175 * \return a valid timer ID or PH_OSALNFC_INVALID_TIMER_ID if an error occured.
177 uint32_t phOsalNfc_Timer_Create(void)
182 se.sigev_notify = SIGEV_THREAD;
183 se.sigev_notify_function = phOsalNfc_Timer_Expired;
184 se.sigev_notify_attributes = NULL;
186 /* Look for available timer slot */
187 for(timerid = 0; timerid < MAX_NO_TIMERS; timerid++)
188 if(timers[timerid].callback == NULL)
190 if(timerid == MAX_NO_TIMERS)
191 return PH_OSALNFC_INVALID_TIMER_ID;
193 se.sigev_value.sival_int = (int)timerid;
195 /* Create POSIX timer */
196 if(timer_create(CLOCK_REALTIME, &se, &(timers[timerid].handle)) == -1)
197 return PH_OSALNFC_INVALID_TIMER_ID;
198 timers[timerid].callback = phOsalNfc_Timer_Dummy_Cb;
200 timers[timerid].ptr = NULL;
207 * \brief Starts a timer.
208 * This function starts the timer \a TimerId with an expiration time of
209 * \a RegTimeCnt milliseconds. Each time it expires, \a
210 * Application_callback is called.
212 * \param TimerId a valid timer ID.
213 * \param RegTimeCnt expiration time in milliseconds.
214 * \param Application_callback callback to be called when timer expires.
216 void phOsalNfc_Timer_Start(uint32_t TimerId,
218 ppCallBck_t Application_callback,
221 struct itimerspec its;
223 if(TimerId >= MAX_NO_TIMERS)
225 if(Application_callback == NULL)
227 if(timers[TimerId].callback == NULL)
230 its.it_interval.tv_sec = 0;
231 its.it_interval.tv_nsec = 0;
232 its.it_value.tv_sec = RegTimeCnt / 1000;
233 its.it_value.tv_nsec = 1000000 * (RegTimeCnt % 1000);
234 if(its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0)
236 // this would inadvertently stop the timer
237 its.it_value.tv_nsec = 1;
240 timers[TimerId].callback = Application_callback;
241 timers[TimerId].pContext = pContext;
242 timers[TimerId].nIsStopped = 0;
244 timer_settime(timers[TimerId].handle, 0, &its, NULL);
248 * \brief Stops a timer.
249 * This function stops an already started timer.
251 * \param TimerId a valid timer ID.
253 void phOsalNfc_Timer_Stop(uint32_t TimerId)
255 struct itimerspec its = {{0, 0}, {0, 0}};
257 if(TimerId >= MAX_NO_TIMERS)
259 if(timers[TimerId].callback == NULL)
261 if(timers[TimerId].nIsStopped == 1)
264 timers[TimerId].nIsStopped = 1;
265 timer_settime(timers[TimerId].handle, 0, &its, NULL);
269 * \brief Deletes a timer.
270 * This function deletes a timer.
272 * \param TimerId a valid timer ID.
274 void phOsalNfc_Timer_Delete(uint32_t TimerId)
276 if(TimerId >= MAX_NO_TIMERS)
278 if(timers[TimerId].callback == NULL)
281 timer_delete(timers[TimerId].handle);
283 timers[TimerId].callback = NULL;
284 timers[TimerId].pContext = NULL;