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