Initialize Tizen 2.3
[adaptation/devices/nfc-plugin-nxp.git] / Linux_x86 / phOsalNfc_Timer.c
1 /*
2  * Copyright (C) 2010 NXP Semiconductors
3  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
4  *
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 /**
19  * \file phOsalNfc_Timer.c
20  * \brief OSAL Timer Implementation for linux
21  *
22  * Project: Trusted NFC Linux Light
23  *
24  * $Date: 03 aug 2009
25  * $Author: Jérémie Corbier
26  * $Revision: 1.0
27  *
28  */
29
30 #include <stdlib.h>
31 #include <signal.h>
32 #include <time.h>
33
34 #include <phOsalNfc.h>
35 #include <phOsalNfc_Timer.h>
36 #include <stdio.h>
37
38 #include <phDal4Nfc_messageQueueLib.h>
39 #include <phDal4Nfc_message_glib.h>
40
41 #define NSECS 1000000
42 #define MAX_NO_TIMERS 16
43
44 /*!
45  * \struct phOsalNfc_Timer
46  * Internal OSAL timer structure
47  */
48 struct phOsalNfc_Timer
49 {
50    timer_t handle;         /*!< System timer handle. */
51    ppCallBck_t callback;   /*!< Callback to be called when timer expires. */
52    void* pContext;         /*!< Callback context. */
53 #ifdef NXP_MESSAGING
54    void *ptr;
55 #endif
56    int nIsStopped;
57 };
58
59 static struct phOsalNfc_Timer timers[MAX_NO_TIMERS] =
60 {
61    {0, NULL, NULL
62 #ifdef NXP_MESSAGING
63      , NULL
64 #endif
65      , 0
66    },
67 };
68
69 #ifdef NXP_MESSAGING
70 extern int nDeferedCallMessageQueueId;
71
72 void phOsalNfc_Timer_DeferredCall(void *params)
73 {
74    phOsalNfc_Timer_Msg_t *timer_msg;
75
76    if(params == NULL)
77       return;
78
79    timer_msg = (phOsalNfc_Timer_Msg_t *)params;
80
81    if((timer_msg != NULL) && (timer_msg->pCallBck != NULL))
82       timer_msg->pCallBck(timer_msg->TimerId, timer_msg->pContext);
83
84    if ((timer_msg->TimerId >= MAX_NO_TIMERS) /*|| (timer_msg->TimerId < 0)*/ /*prevent fix */)
85    {
86       //printf("Bad TimerId=%d, should be <= to %d\n", timer_msg->TimerId, MAX_NO_TIMERS);
87    }
88    else
89    {
90       if(timers[timer_msg->TimerId].ptr != NULL)
91       {
92          phOsalNfc_FreeMemory(timers[timer_msg->TimerId].ptr);
93          timers[timer_msg->TimerId].ptr = NULL;
94       }
95    }
96    phOsalNfc_FreeMemory(timer_msg);
97 }
98 #endif
99
100 /*!
101  * \brief System timer callback.
102  *        This callback is called by Linux whenever one the timers expires.  It
103  *        calls the corresponding registered callback.
104  *
105  * \param sv structure storing the expired timer ID.
106  */
107 static void phOsalNfc_Timer_Expired(union sigval sv)
108 {
109    uint32_t timerid = (uint32_t)(sv.sival_int);
110
111    if((timerid < MAX_NO_TIMERS)&&(timers[timerid].nIsStopped == 1))
112    {
113       //printf("phOsalNfc_Timer_Expired : Expired but already stopped TimerId=%d\n", timerid);
114       return;
115    }
116
117    if(timerid < MAX_NO_TIMERS)
118    {
119 #ifndef CYCLIC_TIMER
120       phOsalNfc_Timer_Stop(timerid);
121 #else
122
123 #endif
124 #ifdef NXP_MESSAGING
125       phOsalNfc_Timer_Msg_t *timer_msg;
126       phOsalNfc_DeferedCalldInfo_t *osal_defer_msg;
127       phDal4Nfc_Message_Wrapper_t wrapper;
128
129       timer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_Timer_Msg_t));
130       if(timer_msg == NULL)
131       {
132          phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0);
133           return;
134       }
135
136       osal_defer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_DeferedCalldInfo_t));
137       if(osal_defer_msg == NULL)
138       {
139          phOsalNfc_FreeMemory(timer_msg);
140          phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0);
141           return;
142       }
143
144       timer_msg->TimerId = timerid;
145       timer_msg->pCallBck = timers[timerid].callback;
146       timer_msg->pContext = timers[timerid].pContext;
147
148       osal_defer_msg->pCallback = phOsalNfc_Timer_DeferredCall;
149       osal_defer_msg->pParameter = timer_msg;
150
151       wrapper.mtype = 1;
152       wrapper.msg.eMsgType = PH_OSALNFC_TIMER_MSG;
153       wrapper.msg.pMsgData = osal_defer_msg;
154       wrapper.msg.Size = sizeof(phOsalNfc_DeferedCalldInfo_t);
155
156       timers[timerid].ptr = osal_defer_msg;
157 #ifndef G_IDLE_ADD_MSGQ
158       phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (void *)&wrapper, sizeof(phOsalNfc_Message_t), 0);
159 #else
160       PostMessage((void *)&wrapper, sizeof(phOsalNfc_Message_t), 0);
161 #endif
162       //(timers[timerid].callback)(timerid, timers[timerid].pContext);
163 #endif
164    }
165 }
166
167 static void phOsalNfc_Timer_Dummy_Cb(uint32_t timerid, void *pContext) {}
168
169 /*!
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
173  *        ID.
174  *
175  * \return a valid timer ID or PH_OSALNFC_INVALID_TIMER_ID if an error occured.
176  */
177 uint32_t phOsalNfc_Timer_Create(void)
178 {
179    uint32_t timerid;
180    struct sigevent se;
181
182    se.sigev_notify = SIGEV_THREAD;
183    se.sigev_notify_function = phOsalNfc_Timer_Expired;
184    se.sigev_notify_attributes = NULL;
185
186    /* Look for available timer slot */
187    for(timerid = 0; timerid < MAX_NO_TIMERS; timerid++)
188       if(timers[timerid].callback == NULL)
189          break;
190    if(timerid == MAX_NO_TIMERS)
191       return PH_OSALNFC_INVALID_TIMER_ID;
192
193    se.sigev_value.sival_int = (int)timerid;
194
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;
199 #ifdef NXP_MESSAGING
200    timers[timerid].ptr = NULL;
201 #endif
202
203    return timerid;
204 }
205
206 /*!
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.
211  *
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.
215  */
216 void phOsalNfc_Timer_Start(uint32_t TimerId,
217                            uint32_t RegTimeCnt,
218                            ppCallBck_t  Application_callback,
219                            void *pContext)
220 {
221    struct itimerspec its;
222
223    if(TimerId >= MAX_NO_TIMERS)
224       return;
225    if(Application_callback == NULL)
226       return;
227    if(timers[TimerId].callback == NULL)
228       return;
229
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)
235    {
236      // this would inadvertently stop the timer
237      its.it_value.tv_nsec = 1;
238    }
239
240    timers[TimerId].callback = Application_callback;
241    timers[TimerId].pContext = pContext;
242    timers[TimerId].nIsStopped = 0;
243
244    timer_settime(timers[TimerId].handle, 0, &its, NULL);
245 }
246
247 /*!
248  * \brief Stops a timer.
249  *        This function stops an already started timer.
250  *
251  * \param TimerId a valid timer ID.
252  */
253 void phOsalNfc_Timer_Stop(uint32_t TimerId)
254 {
255    struct itimerspec its = {{0, 0}, {0, 0}};
256
257    if(TimerId >= MAX_NO_TIMERS)
258       return;
259    if(timers[TimerId].callback == NULL)
260       return;
261    if(timers[TimerId].nIsStopped == 1)
262       return;
263
264    timers[TimerId].nIsStopped = 1;
265    timer_settime(timers[TimerId].handle, 0, &its, NULL);
266 }
267
268 /*!
269  * \brief Deletes a timer.
270  *        This function deletes a timer.
271  *
272  * \param TimerId a valid timer ID.
273  */
274 void phOsalNfc_Timer_Delete(uint32_t TimerId)
275 {
276    if(TimerId >= MAX_NO_TIMERS)
277       return;
278    if(timers[TimerId].callback == NULL)
279       return;
280
281    timer_delete(timers[TimerId].handle);
282
283    timers[TimerId].callback = NULL;
284    timers[TimerId].pContext = NULL;
285 }