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