1 /*
2  * Copyright 2010-2014, 2020,2023 NXP
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   if (dwIndex >= PH_NFC_MAX_TIMER) {
148     return PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
149   }
150   pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
151   /* OSAL Module needs to be initialized for timer usage */
152   /* Check whether the handle provided by user is valid */
153   if ((0x00 != pTimerHandle->TimerId) && (NULL != pApplication_callback)) {
154     its.it_interval.tv_sec = 0;
155     its.it_interval.tv_nsec = 0;
156     its.it_value.tv_sec = dwRegTimeCnt / 1000;
157     its.it_value.tv_nsec = 1000000 * (dwRegTimeCnt % 1000);
158     if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) {
159       /* This would inadvertently stop the timer*/
160       its.it_value.tv_nsec = 1;
161     }
162     pTimerHandle->Application_callback = pApplication_callback;
163     pTimerHandle->pContext = pContext;
164     pTimerHandle->eState = eTimerRunning;
165     /* Arm the timer */
166     if ((timer_settime(pTimerHandle->hTimerHandle, 0, &its, NULL)) == -1) {
167       wStartStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_START_ERROR);
168     }
169   } else {
170     wStartStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
171   }
172 
173   return wStartStatus;
174 }
175 
176 /*******************************************************************************
177 **
178 ** Function         phOsalNfc_Timer_Stop
179 **
180 ** Description      Stops already started timer
181 **                  Allows to stop running timer. In case timer is stopped,
182 **                  timer callback will not be notified any more
183 **
184 ** Parameters       dwTimerId - valid timer ID obtained during timer creation
185 **
186 ** Returns          NFC status:
187 **                  NFCSTATUS_SUCCESS - the operation was successful
188 **                  NFCSTATUS_NOT_INITIALISED - OSAL Module is not initialized
189 **                  NFCSTATUS_INVALID_PARAMETER - invalid parameter passed to
190 **                                                the function
191 **                  PH_OSALNFC_TIMER_STOP_ERROR - timer could not be stopped due
192 **                                                to system error
193 **
194 *******************************************************************************/
phOsalNfc_Timer_Stop(uint32_t dwTimerId)195 NFCSTATUS phOsalNfc_Timer_Stop(uint32_t dwTimerId) {
196   NFCSTATUS wStopStatus = NFCSTATUS_SUCCESS;
197   static struct itimerspec its = {{0, 0}, {0, 0}};
198 
199   uint32_t dwIndex;
200   phOsalNfc_TimerHandle_t* pTimerHandle;
201   dwIndex = dwTimerId - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
202   if (dwIndex >= PH_NFC_MAX_TIMER) {
203     return PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
204   }
205   pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
206   /* OSAL Module and Timer needs to be initialized for timer usage */
207   /* Check whether the TimerId provided by user is valid */
208   if ((0x00 != pTimerHandle->TimerId) && (pTimerHandle->eState != eTimerIdle)) {
209     /* Stop the timer only if the callback has not been invoked */
210     if (pTimerHandle->eState == eTimerRunning) {
211       if ((timer_settime(pTimerHandle->hTimerHandle, 0, &its, NULL)) == -1) {
212         wStopStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_STOP_ERROR);
213       } else {
214         /* Change the state of timer to Stopped */
215         pTimerHandle->eState = eTimerStopped;
216       }
217     }
218   } else {
219     wStopStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
220   }
221 
222   return wStopStatus;
223 }
224 
225 /*******************************************************************************
226 **
227 ** Function         phOsalNfc_Timer_Delete
228 **
229 ** Description      Deletes previously created timer
230 **                  Allows to delete previously created timer. In case timer is
231 **                  running, it is first stopped and then deleted
232 **
233 ** Parameters       dwTimerId - valid timer ID obtained during timer creation
234 **
235 ** Returns          NFC status:
236 **                  NFCSTATUS_SUCCESS - the operation was successful
237 **                  NFCSTATUS_NOT_INITIALISED - OSAL Module is not initialized
238 **                  NFCSTATUS_INVALID_PARAMETER - invalid parameter passed to
239 **                                                the function
240 **                  PH_OSALNFC_TIMER_DELETE_ERROR - timer could not be stopped
241 **                                                  due to system error
242 **
243 *******************************************************************************/
phOsalNfc_Timer_Delete(uint32_t dwTimerId)244 NFCSTATUS phOsalNfc_Timer_Delete(uint32_t dwTimerId) {
245   NFCSTATUS wDeleteStatus = NFCSTATUS_SUCCESS;
246 
247   uint32_t dwIndex;
248   phOsalNfc_TimerHandle_t* pTimerHandle;
249   dwIndex = dwTimerId - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
250   if (dwIndex >= PH_NFC_MAX_TIMER) {
251     return PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
252   }
253   pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
254   /* OSAL Module and Timer needs to be initialized for timer usage */
255 
256   /* Check whether the TimerId passed by user is valid and Deregistering of
257    * timer is successful */
258   if ((0x00 != pTimerHandle->TimerId) &&
259       (NFCSTATUS_SUCCESS == phOsalNfc_CheckTimerPresence(pTimerHandle))) {
260     /* Cancel the timer before deleting */
261     if (timer_delete(pTimerHandle->hTimerHandle) == -1) {
262       wDeleteStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_DELETE_ERROR);
263     }
264     /* Clear Timer structure used to store timer related data */
265     memset(pTimerHandle, (uint8_t)0x00, sizeof(phOsalNfc_TimerHandle_t));
266   } else {
267     wDeleteStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER);
268   }
269   return wDeleteStatus;
270 }
271 
272 /*******************************************************************************
273 **
274 ** Function         phOsalNfc_Timer_Cleanup
275 **
276 ** Description      Deletes all previously created timers
277 **                  Allows to delete previously created timers. In case timer is
278 **                  running, it is first stopped and then deleted
279 **
280 ** Parameters       None
281 **
282 ** Returns          None
283 **
284 *******************************************************************************/
phOsalNfc_Timer_Cleanup(void)285 void phOsalNfc_Timer_Cleanup(void) {
286   /* Delete all timers */
287   uint32_t dwIndex;
288   phOsalNfc_TimerHandle_t* pTimerHandle;
289   for (dwIndex = 0; dwIndex < PH_NFC_MAX_TIMER; dwIndex++) {
290     pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
291     /* OSAL Module and Timer needs to be initialized for timer usage */
292 
293     /* Check whether the TimerId passed by user is valid and Deregistering of
294      * timer is successful */
295     if ((0x00 != pTimerHandle->TimerId) &&
296         (NFCSTATUS_SUCCESS == phOsalNfc_CheckTimerPresence(pTimerHandle))) {
297       /* Cancel the timer before deleting */
298       if (timer_delete(pTimerHandle->hTimerHandle) == -1) {
299         NXPLOG_TML_E("timer %d delete error!", dwIndex);
300       }
301       /* Clear Timer structure used to store timer related data */
302       memset(pTimerHandle, (uint8_t)0x00, sizeof(phOsalNfc_TimerHandle_t));
303     }
304   }
305 
306   return;
307 }
308 
309 /*******************************************************************************
310 **
311 ** Function         phOsalNfc_DeferredCall
312 **
313 ** Description      Invokes the timer callback function after timer expiration.
314 **                  Shall invoke the callback function registered by the timer
315 **                  caller function
316 **
317 ** Parameters       pParams - parameters indicating the ID of the timer
318 **
319 ** Returns          None                -
320 **
321 *******************************************************************************/
phOsalNfc_DeferredCall(void * pParams)322 static void phOsalNfc_DeferredCall(void* pParams) {
323   /* Retrieve the timer id from the parameter */
324   unsigned long dwIndex;
325   phOsalNfc_TimerHandle_t* pTimerHandle;
326   if (NULL != pParams) {
327     /* Retrieve the index at which the timer handle structure is stored */
328     dwIndex = (uintptr_t)pParams - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
329     pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
330     if (pTimerHandle->Application_callback != NULL) {
331       /* Invoke the callback function with osal Timer ID */
332       pTimerHandle->Application_callback((uintptr_t)pParams,
333                                          pTimerHandle->pContext);
334     }
335   }
336 
337   return;
338 }
339 
340 /*******************************************************************************
341 **
342 ** Function         phOsalNfc_PostTimerMsg
343 **
344 ** Description      Posts message on the user thread
345 **                  Shall be invoked upon expiration of a timer
346 **                  Shall post message on user thread through which timer
347 **                  callback function shall be invoked
348 **
349 ** Parameters       pMsg - pointer to the message structure posted on user
350 **                         thread
351 **
352 ** Returns          None
353 **
354 *******************************************************************************/
phOsalNfc_PostTimerMsg(phLibNfc_Message_t * pMsg)355 static void phOsalNfc_PostTimerMsg(phLibNfc_Message_t* pMsg) {
356   (void)phDal4Nfc_msgsnd(
357       nxpncihal_ctrl.gDrvCfg
358           .nClientId /*gpphOsalNfc_Context->dwCallbackThreadID*/,
359       pMsg, 0);
360 
361   return;
362 }
363 
364 /*******************************************************************************
365 **
366 ** Function         phOsalNfc_Timer_Expired
367 **
368 ** Description      posts message upon expiration of timer
369 **                  Shall be invoked when any one timer is expired
370 **                  Shall post message on user thread to invoke respective
371 **                  callback function provided by the caller of Timer function
372 **
373 ** Returns          None
374 **
375 *******************************************************************************/
phOsalNfc_Timer_Expired(union sigval sv)376 static void phOsalNfc_Timer_Expired(union sigval sv) {
377   uint32_t dwIndex;
378   phOsalNfc_TimerHandle_t* pTimerHandle;
379 
380   dwIndex = ((uint32_t)(sv.sival_int)) - PH_NFC_TIMER_BASE_ADDRESS - 0x01;
381   pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex];
382   /* Timer is stopped when callback function is invoked */
383   pTimerHandle->eState = eTimerStopped;
384 
385   pTimerHandle->tDeferedCallInfo.pDeferedCall = &phOsalNfc_DeferredCall;
386   pTimerHandle->tDeferedCallInfo.pParam = (void*)((intptr_t)(sv.sival_int));
387 
388   pTimerHandle->tOsalMessage.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
389   pTimerHandle->tOsalMessage.pMsgData = (void*)&pTimerHandle->tDeferedCallInfo;
390 
391   /* Post a message on the queue to invoke the function */
392   phOsalNfc_PostTimerMsg((phLibNfc_Message_t*)&pTimerHandle->tOsalMessage);
393 
394   return;
395 }
396 
397 /*******************************************************************************
398 **
399 ** Function         phUtilNfc_CheckForAvailableTimer
400 **
401 ** Description      Find an available timer id
402 **
403 ** Parameters       void
404 **
405 ** Returns          Available timer id
406 **
407 *******************************************************************************/
phUtilNfc_CheckForAvailableTimer(void)408 uint32_t phUtilNfc_CheckForAvailableTimer(void) {
409   /* Variable used to store the index at which the object structure details
410      can be stored. Initialize it as not available. */
411   uint32_t dwIndex = 0x00;
412   uint32_t dwRetval = 0x00;
413 
414   /* Check whether Timer object can be created */
415   for (dwIndex = 0x00; ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 == dwRetval));
416        dwIndex++) {
417     if (!(apTimerInfo[dwIndex].TimerId)) {
418       dwRetval = (dwIndex + 0x01);
419     }
420   }
421 
422   return (dwRetval);
423 }
424 
425 /*******************************************************************************
426 **
427 ** Function         phOsalNfc_CheckTimerPresence
428 **
429 ** Description      Checks the requested timer is present or not
430 **
431 ** Parameters       pObjectHandle - timer context
432 **
433 ** Returns          NFCSTATUS_SUCCESS if found
434 **                  Other value if not found
435 **
436 *******************************************************************************/
phOsalNfc_CheckTimerPresence(void * pObjectHandle)437 NFCSTATUS phOsalNfc_CheckTimerPresence(void* pObjectHandle) {
438   uint32_t dwIndex;
439   NFCSTATUS wRegisterStatus = NFCSTATUS_INVALID_PARAMETER;
440 
441   for (dwIndex = 0x00;
442        ((dwIndex < PH_NFC_MAX_TIMER) && (wRegisterStatus != NFCSTATUS_SUCCESS));
443        dwIndex++) {
444     /* For Timer, check whether the requested handle is present or not */
445     if (((&apTimerInfo[dwIndex]) == (phOsalNfc_TimerHandle_t*)pObjectHandle) &&
446         (apTimerInfo[dwIndex].TimerId)) {
447       wRegisterStatus = NFCSTATUS_SUCCESS;
448     }
449   }
450   return wRegisterStatus;
451 }
452