1 /*
2 * Copyright (C) 2010-2014 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 * OSAL Implementation for Timers.
19 */
20
21 #include <phNfcCommon.h>
22 #include <phNfcTypes.h>
23 #include <phNxpLog.h>
24 #include <phNxpNciHal.h>
25 #include <phOsalNfc_Timer.h>
26 #include <signal.h>
27
28 #define PH_NFC_MAX_TIMER (5U)
29 static phOsalNfc_TimerHandle_t apTimerInfo[PH_NFC_MAX_TIMER];
30
31 extern phNxpNciHal_Control_t nxpncihal_ctrl;
32
33 /*
34 * Defines the base address for generating timerid.
35 */
36 #define PH_NFC_TIMER_BASE_ADDRESS (100U)
37
38 /*
39 * Defines the value for invalid timerid returned during timeSetEvent
40 */
41 #define PH_NFC_TIMER_ID_ZERO (0x00)
42
43 /*
44 * Invalid timer ID type. This ID used indicate timer creation is failed */
45 #define PH_NFC_TIMER_ID_INVALID (0xFFFF)
46
47 /* Forward declarations */
48 static void phOsalNfc_PostTimerMsg(phLibNfc_Message_t* pMsg);
49 static void phOsalNfc_DeferredCall(void* pParams);
50 static void phOsalNfc_Timer_Expired(union sigval sv);
51
52 /*
53 *************************** Function Definitions ******************************
54 */
55
56 /*******************************************************************************
57 **
58 ** Function phOsalNfc_Timer_Create
59 **
60 ** Description Creates a timer which shall call back the specified function
61 ** when the timer expires. Fails if OSAL module is not
62 ** initialized or timers are already occupied
63 **
64 ** Parameters None
65 **
66 ** Returns TimerId
67 ** TimerId value of PH_OSALNFC_TIMER_ID_INVALID indicates that
68 ** timer is not created
69 **
70 *******************************************************************************/
phOsalNfc_Timer_Create(void)71 uint32_t phOsalNfc_Timer_Create(void) {
72 /* dwTimerId is also used as an index at which timer object can be stored */
73 uint32_t dwTimerId = PH_OSALNFC_TIMER_ID_INVALID;
74 static struct sigevent se;
75 phOsalNfc_TimerHandle_t* pTimerHandle;
76 /* Timer needs to be initialized for timer usage */
77
78 se.sigev_notify = SIGEV_THREAD;
79 se.sigev_notify_function = phOsalNfc_Timer_Expired;
80 se.sigev_notify_attributes = NULL;
81 dwTimerId = phUtilNfc_CheckForAvailableTimer();
82
83 /* Check whether timers are available, if yes create a timer handle structure
84 */
85 if ((PH_NFC_TIMER_ID_ZERO != dwTimerId) && (dwTimerId <= PH_NFC_MAX_TIMER)) {
86 pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwTimerId - 1];
87 /* Build the Timer Id to be returned to Caller Function */
88 dwTimerId += PH_NFC_TIMER_BASE_ADDRESS;
89 se.sigev_value.sival_int = (int)dwTimerId;
90 /* Create POSIX timer */
91 if (timer_create(CLOCK_REALTIME, &se, &(pTimerHandle->hTimerHandle)) ==
92 -1) {
93 dwTimerId = PH_NFC_TIMER_ID_INVALID;
94 } else {
95 /* Set the state to indicate timer is ready */
96 pTimerHandle->eState = eTimerIdle;
97 /* Store the Timer Id which shall act as flag during check for timer
98 * availability */
99 pTimerHandle->TimerId = dwTimerId;
100 }
101 } else {
102 dwTimerId = PH_NFC_TIMER_ID_INVALID;
103 }
104
105 /* Timer ID invalid can be due to Uninitialized state,Non availability of
106 * Timer */
107 return dwTimerId;
108 }
109
110 /*******************************************************************************
111 **
112 ** Function phOsalNfc_Timer_Start
113 **
114 ** Description Starts the requested, already created, timer.
115 ** If the timer is already running, timer stops and restarts
116 ** with the new timeout value and new callback function in case
117 ** any ??????
118 ** Creates a timer which shall call back the specified function
119 ** when the timer expires
120 **
121 ** Parameters dwTimerId - valid timer ID obtained during timer creation
122 ** dwRegTimeCnt - requested timeout in milliseconds
123 ** pApplication_callback - application callback interface to be
124 ** called when timer expires
125 ** pContext - caller context, to be passed to the application
126 ** callback function
127 **
128 ** Returns NFC status:
129 ** NFCSTATUS_SUCCESS - the operation was successful
130 ** NFCSTATUS_NOT_INITIALISED - OSAL Module is not initialized
131 ** NFCSTATUS_INVALID_PARAMETER - invalid parameter passed to
132 ** the function
133 ** PH_OSALNFC_TIMER_START_ERROR - timer could not be created
134 ** due to system error
135 **
136 *******************************************************************************/
phOsalNfc_Timer_Start(uint32_t dwTimerId,uint32_t dwRegTimeCnt,pphOsalNfc_TimerCallbck_t pApplication_callback,void * pContext)137 NFCSTATUS phOsalNfc_Timer_Start(uint32_t dwTimerId, uint32_t dwRegTimeCnt,
138 pphOsalNfc_TimerCallbck_t pApplication_callback,
139 void* pContext) {
140 NFCSTATUS wStartStatus = NFCSTATUS_SUCCESS;
141
142 struct itimerspec its;
143 uint32_t dwIndex;
144 phOsalNfc_TimerHandle_t* pTimerHandle;
145 /* Retrieve the index at which the timer handle structure is stored */
146 dwIndex = dwTimerId - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
147 pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
148 /* OSAL Module needs to be initialized for timer usage */
149 /* Check whether the handle provided by user is valid */
150 if ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 != pTimerHandle->TimerId) &&
151 (NULL != pApplication_callback)) {
152 its.it_interval.tv_sec = 0;
153 its.it_interval.tv_nsec = 0;
154 its.it_value.tv_sec = dwRegTimeCnt / 1000;
155 its.it_value.tv_nsec = 1000000 * (dwRegTimeCnt % 1000);
156 if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) {
157 /* This would inadvertently stop the timer*/
158 its.it_value.tv_nsec = 1;
159 }
160 pTimerHandle->Application_callback = pApplication_callback;
161 pTimerHandle->pContext = pContext;
162 pTimerHandle->eState = eTimerRunning;
163 /* Arm the timer */
164 if ((timer_settime(pTimerHandle->hTimerHandle, 0, &its, NULL)) == -1) {
165 wStartStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_START_ERROR);
166 }
167 } else {
168 wStartStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
169 }
170
171 return wStartStatus;
172 }
173
174 /*******************************************************************************
175 **
176 ** Function phOsalNfc_Timer_Stop
177 **
178 ** Description Stops already started timer
179 ** Allows to stop running timer. In case timer is stopped,
180 ** timer callback will not be notified any more
181 **
182 ** Parameters dwTimerId - valid timer ID obtained during timer creation
183 **
184 ** Returns NFC status:
185 ** NFCSTATUS_SUCCESS - the operation was successful
186 ** NFCSTATUS_NOT_INITIALISED - OSAL Module is not initialized
187 ** NFCSTATUS_INVALID_PARAMETER - invalid parameter passed to
188 ** the function
189 ** PH_OSALNFC_TIMER_STOP_ERROR - timer could not be stopped due
190 ** to system error
191 **
192 *******************************************************************************/
phOsalNfc_Timer_Stop(uint32_t dwTimerId)193 NFCSTATUS phOsalNfc_Timer_Stop(uint32_t dwTimerId) {
194 NFCSTATUS wStopStatus = NFCSTATUS_SUCCESS;
195 static struct itimerspec its = {{0, 0}, {0, 0}};
196
197 uint32_t dwIndex;
198 phOsalNfc_TimerHandle_t* pTimerHandle;
199 dwIndex = dwTimerId - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
200 pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
201 /* OSAL Module and Timer needs to be initialized for timer usage */
202 /* Check whether the TimerId provided by user is valid */
203 if ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 != pTimerHandle->TimerId) &&
204 (pTimerHandle->eState != eTimerIdle)) {
205 /* Stop the timer only if the callback has not been invoked */
206 if (pTimerHandle->eState == eTimerRunning) {
207 if ((timer_settime(pTimerHandle->hTimerHandle, 0, &its, NULL)) == -1) {
208 wStopStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_STOP_ERROR);
209 } else {
210 /* Change the state of timer to Stopped */
211 pTimerHandle->eState = eTimerStopped;
212 }
213 }
214 } else {
215 wStopStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
216 }
217
218 return wStopStatus;
219 }
220
221 /*******************************************************************************
222 **
223 ** Function phOsalNfc_Timer_Delete
224 **
225 ** Description Deletes previously created timer
226 ** Allows to delete previously created timer. In case timer is
227 ** running, it is first stopped and then deleted
228 **
229 ** Parameters dwTimerId - valid timer ID obtained during timer creation
230 **
231 ** Returns NFC status:
232 ** NFCSTATUS_SUCCESS - the operation was successful
233 ** NFCSTATUS_NOT_INITIALISED - OSAL Module is not initialized
234 ** NFCSTATUS_INVALID_PARAMETER - invalid parameter passed to
235 ** the function
236 ** PH_OSALNFC_TIMER_DELETE_ERROR - timer could not be stopped
237 ** due to system error
238 **
239 *******************************************************************************/
phOsalNfc_Timer_Delete(uint32_t dwTimerId)240 NFCSTATUS phOsalNfc_Timer_Delete(uint32_t dwTimerId) {
241 NFCSTATUS wDeleteStatus = NFCSTATUS_SUCCESS;
242
243 uint32_t dwIndex;
244 phOsalNfc_TimerHandle_t* pTimerHandle;
245 dwIndex = dwTimerId - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
246 pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
247 /* OSAL Module and Timer needs to be initialized for timer usage */
248
249 /* Check whether the TimerId passed by user is valid and Deregistering of
250 * timer is successful */
251 if ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 != pTimerHandle->TimerId) &&
252 (NFCSTATUS_SUCCESS == phOsalNfc_CheckTimerPresence(pTimerHandle))) {
253 /* Cancel the timer before deleting */
254 if (timer_delete(pTimerHandle->hTimerHandle) == -1) {
255 wDeleteStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_DELETE_ERROR);
256 }
257 /* Clear Timer structure used to store timer related data */
258 memset(pTimerHandle, (uint8_t)0x00, sizeof(phOsalNfc_TimerHandle_t));
259 } else {
260 wDeleteStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
261 }
262 return wDeleteStatus;
263 }
264
265 /*******************************************************************************
266 **
267 ** Function phOsalNfc_Timer_Cleanup
268 **
269 ** Description Deletes all previously created timers
270 ** Allows to delete previously created timers. In case timer is
271 ** running, it is first stopped and then deleted
272 **
273 ** Parameters None
274 **
275 ** Returns None
276 **
277 *******************************************************************************/
phOsalNfc_Timer_Cleanup(void)278 void phOsalNfc_Timer_Cleanup(void) {
279 /* Delete all timers */
280 uint32_t dwIndex;
281 phOsalNfc_TimerHandle_t* pTimerHandle;
282 for (dwIndex = 0; dwIndex < PH_NFC_MAX_TIMER; dwIndex++) {
283 pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
284 /* OSAL Module and Timer needs to be initialized for timer usage */
285
286 /* Check whether the TimerId passed by user is valid and Deregistering of
287 * timer is successful */
288 if ((0x00 != pTimerHandle->TimerId) &&
289 (NFCSTATUS_SUCCESS == phOsalNfc_CheckTimerPresence(pTimerHandle))) {
290 /* Cancel the timer before deleting */
291 if (timer_delete(pTimerHandle->hTimerHandle) == -1) {
292 NXPLOG_TML_E("timer %d delete error!", dwIndex);
293 }
294 /* Clear Timer structure used to store timer related data */
295 memset(pTimerHandle, (uint8_t)0x00, sizeof(phOsalNfc_TimerHandle_t));
296 }
297 }
298
299 return;
300 }
301
302 /*******************************************************************************
303 **
304 ** Function phOsalNfc_DeferredCall
305 **
306 ** Description Invokes the timer callback function after timer expiration.
307 ** Shall invoke the callback function registered by the timer
308 ** caller function
309 **
310 ** Parameters pParams - parameters indicating the ID of the timer
311 **
312 ** Returns None -
313 **
314 *******************************************************************************/
phOsalNfc_DeferredCall(void * pParams)315 static void phOsalNfc_DeferredCall(void* pParams) {
316 /* Retrieve the timer id from the parameter */
317 uint32_t dwIndex;
318 phOsalNfc_TimerHandle_t* pTimerHandle;
319 if (NULL != pParams) {
320 /* Retrieve the index at which the timer handle structure is stored */
321 dwIndex = (uintptr_t)pParams - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
322 pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
323 if (pTimerHandle->Application_callback != NULL) {
324 /* Invoke the callback function with osal Timer ID */
325 pTimerHandle->Application_callback((uintptr_t)pParams,
326 pTimerHandle->pContext);
327 }
328 }
329
330 return;
331 }
332
333 /*******************************************************************************
334 **
335 ** Function phOsalNfc_PostTimerMsg
336 **
337 ** Description Posts message on the user thread
338 ** Shall be invoked upon expiration of a timer
339 ** Shall post message on user thread through which timer
340 ** callback function shall be invoked
341 **
342 ** Parameters pMsg - pointer to the message structure posted on user
343 ** thread
344 **
345 ** Returns None
346 **
347 *******************************************************************************/
phOsalNfc_PostTimerMsg(phLibNfc_Message_t * pMsg)348 static void phOsalNfc_PostTimerMsg(phLibNfc_Message_t* pMsg) {
349 (void)phDal4Nfc_msgsnd(
350 nxpncihal_ctrl.gDrvCfg
351 .nClientId /*gpphOsalNfc_Context->dwCallbackThreadID*/,
352 pMsg, 0);
353
354 return;
355 }
356
357 /*******************************************************************************
358 **
359 ** Function phOsalNfc_Timer_Expired
360 **
361 ** Description posts message upon expiration of timer
362 ** Shall be invoked when any one timer is expired
363 ** Shall post message on user thread to invoke respective
364 ** callback function provided by the caller of Timer function
365 **
366 ** Returns None
367 **
368 *******************************************************************************/
phOsalNfc_Timer_Expired(union sigval sv)369 static void phOsalNfc_Timer_Expired(union sigval sv) {
370 uint32_t dwIndex;
371 phOsalNfc_TimerHandle_t* pTimerHandle;
372
373 dwIndex = ((uint32_t)(sv.sival_int)) - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
374 pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
375 /* Timer is stopped when callback function is invoked */
376 pTimerHandle->eState = eTimerStopped;
377
378 pTimerHandle->tDeferedCallInfo.pDeferedCall = &phOsalNfc_DeferredCall;
379 pTimerHandle->tDeferedCallInfo.pParam = (void*)((intptr_t)(sv.sival_int));
380
381 pTimerHandle->tOsalMessage.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
382 pTimerHandle->tOsalMessage.pMsgData = (void*)&pTimerHandle->tDeferedCallInfo;
383
384 /* Post a message on the queue to invoke the function */
385 phOsalNfc_PostTimerMsg((phLibNfc_Message_t*)&pTimerHandle->tOsalMessage);
386
387 return;
388 }
389
390 /*******************************************************************************
391 **
392 ** Function phUtilNfc_CheckForAvailableTimer
393 **
394 ** Description Find an available timer id
395 **
396 ** Parameters void
397 **
398 ** Returns Available timer id
399 **
400 *******************************************************************************/
phUtilNfc_CheckForAvailableTimer(void)401 uint32_t phUtilNfc_CheckForAvailableTimer(void) {
402 /* Variable used to store the index at which the object structure details
403 can be stored. Initialize it as not available. */
404 uint32_t dwIndex = 0x00;
405 uint32_t dwRetval = 0x00;
406
407 /* Check whether Timer object can be created */
408 for (dwIndex = 0x00; ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 == dwRetval));
409 dwIndex++) {
410 if (!(apTimerInfo[dwIndex].TimerId)) {
411 dwRetval = (dwIndex + 0x01);
412 }
413 }
414
415 return (dwRetval);
416 }
417
418 /*******************************************************************************
419 **
420 ** Function phOsalNfc_CheckTimerPresence
421 **
422 ** Description Checks the requested timer is present or not
423 **
424 ** Parameters pObjectHandle - timer context
425 **
426 ** Returns NFCSTATUS_SUCCESS if found
427 ** Other value if not found
428 **
429 *******************************************************************************/
phOsalNfc_CheckTimerPresence(void * pObjectHandle)430 NFCSTATUS phOsalNfc_CheckTimerPresence(void* pObjectHandle) {
431 uint32_t dwIndex;
432 NFCSTATUS wRegisterStatus = NFCSTATUS_INVALID_PARAMETER;
433
434 for (dwIndex = 0x00;
435 ((dwIndex < PH_NFC_MAX_TIMER) && (wRegisterStatus != NFCSTATUS_SUCCESS));
436 dwIndex++) {
437 /* For Timer, check whether the requested handle is present or not */
438 if (((&apTimerInfo[dwIndex]) == (phOsalNfc_TimerHandle_t*)pObjectHandle) &&
439 (apTimerInfo[dwIndex].TimerId)) {
440 wRegisterStatus = NFCSTATUS_SUCCESS;
441 }
442 }
443 return wRegisterStatus;
444 }
445