• 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_DeferredCall(void* pParams);
45 static void phOsalUwb_Timer_Expired(union sigval sv);
46 
47 /*
48  *************************** Function Definitions ******************************
49  */
50 
51 /*******************************************************************************
52 **
53 ** Function         phOsalUwb_Timer_Create
54 **
55 ** Description      Creates a timer which shall call back the specified function
56 **                  when the timer expires. Fails if OSAL module is not
57 **                  initialized or timers are already occupied
58 **
59 ** Parameters       None
60 **
61 ** Returns          TimerId
62 **                  TimerId value of PH_OSALUWB_TIMER_ID_INVALID indicates that
63 **                  timer is not created
64 **
65 *******************************************************************************/
phOsalUwb_Timer_Create(void)66 uint32_t phOsalUwb_Timer_Create(void) {
67   /* dwTimerId is also used as an index at which timer object can be stored */
68   uint32_t dwTimerId;
69   static struct sigevent se;
70   phOsalUwb_TimerHandle_t* pTimerHandle;
71   /* Timer needs to be initialized for timer usage */
72 
73   se.sigev_notify = SIGEV_THREAD;
74   se.sigev_notify_function = phOsalUwb_Timer_Expired;
75   se.sigev_notify_attributes = NULL;
76   dwTimerId = phUtilUwb_CheckForAvailableTimer();
77 
78   /* Check whether timers are available, if yes create a timer handle structure
79    */
80   if ((PH_UWB_TIMER_ID_ZERO != dwTimerId) && (dwTimerId <= PH_UWB_MAX_TIMER)) {
81     pTimerHandle = (phOsalUwb_TimerHandle_t*)&apTimerInfo[dwTimerId - 1];
82     /* Build the Timer Id to be returned to Caller Function */
83     dwTimerId += PH_UWB_TIMER_BASE_ADDRESS;
84     se.sigev_value.sival_int = (int)dwTimerId;
85     /* Create POSIX timer */
86     if (timer_create(CLOCK_REALTIME, &se, &(pTimerHandle->hTimerHandle)) ==
87         -1) {
88       dwTimerId = PH_UWB_TIMER_ID_INVALID;
89     } else {
90       /* Set the state to indicate timer is ready */
91       pTimerHandle->eState = eTimerIdle;
92       /* Store the Timer Id which shall act as flag during check for timer
93        * availability */
94       pTimerHandle->TimerId = dwTimerId;
95     }
96   } else {
97     dwTimerId = PH_UWB_TIMER_ID_INVALID;
98   }
99 
100   /* Timer ID invalid can be due to Uninitialized state,Non availability of
101    * Timer */
102   return dwTimerId;
103 }
104 
105 /*******************************************************************************
106 **
107 ** Function         phOsalUwb_Timer_Start
108 **
109 ** Description      Starts the requested, already created, timer.
110 **                  If the timer is already running, timer stops and restarts
111 **                  with the new timeout value and new callback function in case
112 **                  any ??????
113 **                  Creates a timer which shall call back the specified function
114 **                  when the timer expires
115 **
116 ** Parameters       dwTimerId - valid timer ID obtained during timer creation
117 **                  dwRegTimeCnt - requested timeout in milliseconds
118 **                  pApplication_callback - application callback interface to be
119 **                                          called when timer expires
120 **                  pContext - caller context, to be passed to the application
121 **                             callback function
122 **
123 ** Returns          UWB status:
124 **                  UWBSTATUS_SUCCESS - the operation was successful
125 **                  UWBSTATUS_NOT_INITIALISED - OSAL Module is not initialized
126 **                  UWBSTATUS_INVALID_PARAMETER - invalid parameter passed to
127 **                                                the function
128 **                  PH_OSALUWB_TIMER_START_ERROR - timer could not be created
129 **                                                 due to system error
130 **
131 *******************************************************************************/
phOsalUwb_Timer_Start(uint32_t dwTimerId,uint32_t dwRegTimeCnt,pphOsalUwb_TimerCallbck_t pApplication_callback,void * pContext)132 tHAL_UWB_STATUS phOsalUwb_Timer_Start(uint32_t dwTimerId, uint32_t dwRegTimeCnt,
133                                 pphOsalUwb_TimerCallbck_t pApplication_callback,
134                                 void* pContext) {
135   tHAL_UWB_STATUS wStartStatus = UWBSTATUS_SUCCESS;
136 
137   struct itimerspec its;
138   uint32_t dwIndex;
139   phOsalUwb_TimerHandle_t* pTimerHandle;
140   /* Retrieve the index at which the timer handle structure is stored */
141   dwIndex = (uint32_t)(dwTimerId - PH_UWB_TIMER_BASE_ADDRESS - 0x01);
142 
143   if (dwIndex >= PH_UWB_MAX_TIMER) {
144     wStartStatus = PHUWBSTVAL(CID_UWB_OSAL, UWBSTATUS_INVALID_PARAMETER);
145     return wStartStatus;
146   }
147   pTimerHandle = (phOsalUwb_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 ((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 = PHUWBSTVAL(CID_UWB_OSAL, PH_OSALUWB_TIMER_START_ERROR);
166     }
167   } else {
168     wStartStatus = PHUWBSTVAL(CID_UWB_OSAL, UWBSTATUS_INVALID_PARAMETER);
169   }
170 
171   return wStartStatus;
172 }
173 
174 /*******************************************************************************
175 **
176 ** Function         phOsalUwb_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          UWB status:
185 **                  UWBSTATUS_SUCCESS - the operation was successful
186 **                  UWBSTATUS_NOT_INITIALISED - OSAL Module is not initialized
187 **                  UWBSTATUS_INVALID_PARAMETER - invalid parameter passed to
188 **                                                the function
189 **                  PH_OSALUWB_TIMER_STOP_ERROR - timer could not be stopped due
190 **                                                to system error
191 **
192 *******************************************************************************/
phOsalUwb_Timer_Stop(uint32_t dwTimerId)193 tHAL_UWB_STATUS phOsalUwb_Timer_Stop(uint32_t dwTimerId) {
194   tHAL_UWB_STATUS wStopStatus = UWBSTATUS_SUCCESS;
195   static struct itimerspec its = {{0, 0}, {0, 0}};
196 
197   uint32_t dwIndex;
198   phOsalUwb_TimerHandle_t* pTimerHandle;
199   dwIndex = (uint32_t)(dwTimerId - PH_UWB_TIMER_BASE_ADDRESS - 0x01);
200   if (dwIndex >= PH_UWB_MAX_TIMER) {
201     wStopStatus = PHUWBSTVAL(CID_UWB_OSAL, UWBSTATUS_INVALID_PARAMETER);
202     return wStopStatus;
203   }
204   pTimerHandle = (phOsalUwb_TimerHandle_t*)&apTimerInfo[dwIndex];
205   /* OSAL Module and Timer needs to be initialized for timer usage */
206   /* Check whether the TimerId provided by user is valid */
207   if ((0x00 != pTimerHandle->TimerId) &&
208       (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 = PHUWBSTVAL(CID_UWB_OSAL, PH_OSALUWB_TIMER_STOP_ERROR);
213       } else {
214         /* Change the state of timer to Stopped */
215         pTimerHandle->eState = eTimerStopped;
216       }
217     }
218   } else {
219     wStopStatus = PHUWBSTVAL(CID_UWB_OSAL, UWBSTATUS_INVALID_PARAMETER);
220   }
221 
222   return wStopStatus;
223 }
224 
225 /*******************************************************************************
226 **
227 ** Function         phOsalUwb_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          UWB status:
236 **                  UWBSTATUS_SUCCESS - the operation was successful
237 **                  UWBSTATUS_NOT_INITIALISED - OSAL Module is not initialized
238 **                  UWBSTATUS_INVALID_PARAMETER - invalid parameter passed to
239 **                                                the function
240 **                  PH_OSALUWB_TIMER_DELETE_ERROR - timer could not be stopped
241 **                                                  due to system error
242 **
243 *******************************************************************************/
phOsalUwb_Timer_Delete(uint32_t dwTimerId)244 tHAL_UWB_STATUS phOsalUwb_Timer_Delete(uint32_t dwTimerId) {
245   tHAL_UWB_STATUS wDeleteStatus = UWBSTATUS_SUCCESS;
246 
247   uint32_t dwIndex;
248   phOsalUwb_TimerHandle_t* pTimerHandle;
249   dwIndex = (uint32_t)(dwTimerId - PH_UWB_TIMER_BASE_ADDRESS - 0x01);
250   if (dwIndex >= PH_UWB_MAX_TIMER) {
251     wDeleteStatus = PHUWBSTVAL(CID_UWB_OSAL, UWBSTATUS_INVALID_PARAMETER);
252     return wDeleteStatus;
253   }
254   pTimerHandle = (phOsalUwb_TimerHandle_t*)&apTimerInfo[dwIndex];
255   /* OSAL Module and Timer needs to be initialized for timer usage */
256 
257   /* Check whether the TimerId passed by user is valid and Deregistering of
258    * timer is successful */
259   if ((0x00 != pTimerHandle->TimerId) &&
260       (UWBSTATUS_SUCCESS == phOsalUwb_CheckTimerPresence(pTimerHandle))) {
261     /* Cancel the timer before deleting */
262     if (timer_delete(pTimerHandle->hTimerHandle) == -1) {
263       wDeleteStatus = PHUWBSTVAL(CID_UWB_OSAL, PH_OSALUWB_TIMER_DELETE_ERROR);
264     }
265     /* Clear Timer structure used to store timer related data */
266     memset(pTimerHandle, (uint8_t)0x00, sizeof(phOsalUwb_TimerHandle_t));
267   } else {
268     wDeleteStatus = PHUWBSTVAL(CID_UWB_OSAL, UWBSTATUS_INVALID_PARAMETER);
269   }
270   return wDeleteStatus;
271 }
272 
273 /*******************************************************************************
274 **
275 ** Function         phOsalUwb_Timer_Cleanup
276 **
277 ** Description      Deletes all previously created timers
278 **                  Allows to delete previously created timers. In case timer is
279 **                  running, it is first stopped and then deleted
280 **
281 ** Parameters       None
282 **
283 ** Returns          None
284 **
285 *******************************************************************************/
phOsalUwb_Timer_Cleanup(void)286 void phOsalUwb_Timer_Cleanup(void) {
287   /* Delete all timers */
288   uint32_t dwIndex;
289   phOsalUwb_TimerHandle_t* pTimerHandle;
290   for (dwIndex = 0; dwIndex < PH_UWB_MAX_TIMER; dwIndex++) {
291     pTimerHandle = (phOsalUwb_TimerHandle_t*)&apTimerInfo[dwIndex];
292     /* OSAL Module and Timer needs to be initialized for timer usage */
293 
294     /* Check whether the TimerId passed by user is valid and Deregistering of
295      * timer is successful */
296     if ((0x00 != pTimerHandle->TimerId) &&
297         (UWBSTATUS_SUCCESS == phOsalUwb_CheckTimerPresence(pTimerHandle))) {
298       /* Cancel the timer before deleting */
299       if (timer_delete(pTimerHandle->hTimerHandle) == -1) {
300         NXPLOG_TML_E("timer %d delete error!", dwIndex);
301       }
302       /* Clear Timer structure used to store timer related data */
303       memset(pTimerHandle, (uint8_t)0x00, sizeof(phOsalUwb_TimerHandle_t));
304     }
305   }
306 
307   return;
308 }
309 
310 /*******************************************************************************
311 **
312 ** Function         phOsalUwb_DeferredCall
313 **
314 ** Description      Invokes the timer callback function after timer expiration.
315 **                  Shall invoke the callback function registered by the timer
316 **                  caller function
317 **
318 ** Parameters       pParams - parameters indicating the ID of the timer
319 **
320 ** Returns          None                -
321 **
322 *******************************************************************************/
phOsalUwb_DeferredCall(void * pParams)323 static void phOsalUwb_DeferredCall(void* pParams) {
324   /* Retrieve the timer id from the parameter */
325   uint32_t dwIndex;
326   phOsalUwb_TimerHandle_t* pTimerHandle;
327   if (NULL != pParams) {
328     /* Retrieve the index at which the timer handle structure is stored */
329     dwIndex = (uint32_t)((uintptr_t)pParams - PH_UWB_TIMER_BASE_ADDRESS - 0x01);
330     pTimerHandle = (phOsalUwb_TimerHandle_t*)&apTimerInfo[dwIndex];
331     if (pTimerHandle->Application_callback != NULL) {
332       /* Invoke the callback function with osal Timer ID */
333       pTimerHandle->Application_callback((uintptr_t)pParams,
334                                          pTimerHandle->pContext);
335     }
336   }
337 
338   return;
339 }
340 
341 /*******************************************************************************
342 **
343 ** Function         phOsalUwb_Timer_Expired
344 **
345 ** Description      posts message upon expiration of timer
346 **                  Shall be invoked when any one timer is expired
347 **                  Shall post message on user thread to invoke respective
348 **                  callback function provided by the caller of Timer function
349 **
350 ** Returns          None
351 **
352 *******************************************************************************/
phOsalUwb_Timer_Expired(union sigval sv)353 static void phOsalUwb_Timer_Expired(union sigval sv) {
354   uint32_t dwIndex;
355   phOsalUwb_TimerHandle_t* pTimerHandle;
356 
357   dwIndex = (uint32_t)(((uint32_t)(sv.sival_int)) - PH_UWB_TIMER_BASE_ADDRESS - 0x01);
358   pTimerHandle = (phOsalUwb_TimerHandle_t*)&apTimerInfo[dwIndex];
359   /* Timer is stopped when callback function is invoked */
360   pTimerHandle->eState = eTimerStopped;
361 
362   pTimerHandle->tDeferredCallInfo.pDeferredCall = &phOsalUwb_DeferredCall;
363   pTimerHandle->tDeferredCallInfo.pParam = (void*)((intptr_t)(sv.sival_int));
364 
365   /* Post a message on the queue to invoke the function */
366   auto msg = std::make_shared<phLibUwb_Message>(PH_LIBUWB_DEFERREDCALL_MSG, &pTimerHandle->tDeferredCallInfo);
367   nxpucihal_ctrl.gDrvCfg.pClientMq->send(msg);
368 }
369 
370 /*******************************************************************************
371 **
372 ** Function         phUtilUwb_CheckForAvailableTimer
373 **
374 ** Description      Find an available timer id
375 **
376 ** Parameters       void
377 **
378 ** Returns          Available timer id
379 **
380 *******************************************************************************/
phUtilUwb_CheckForAvailableTimer(void)381 uint32_t phUtilUwb_CheckForAvailableTimer(void) {
382   /* Variable used to store the index at which the object structure details
383      can be stored. Initialize it as not available. */
384   uint32_t dwIndex = 0x00;
385   uint32_t dwRetval = 0x00;
386 
387   /* Check whether Timer object can be created */
388   for (dwIndex = 0x00; ((dwIndex < PH_UWB_MAX_TIMER) && (0x00 == dwRetval));
389        dwIndex++) {
390     if (!(apTimerInfo[dwIndex].TimerId)) {
391       dwRetval = (dwIndex + 0x01);
392     }
393   }
394 
395   return (dwRetval);
396 }
397 
398 /*******************************************************************************
399 **
400 ** Function         phOsalUwb_CheckTimerPresence
401 **
402 ** Description      Checks the requested timer is present or not
403 **
404 ** Parameters       pObjectHandle - timer context
405 **
406 ** Returns          UWBSTATUS_SUCCESS if found
407 **                  Other value if not found
408 **
409 *******************************************************************************/
phOsalUwb_CheckTimerPresence(void * pObjectHandle)410 tHAL_UWB_STATUS phOsalUwb_CheckTimerPresence(void* pObjectHandle) {
411   uint32_t dwIndex;
412   tHAL_UWB_STATUS wRegisterStatus = UWBSTATUS_INVALID_PARAMETER;
413 
414   for (dwIndex = 0x00;
415        ((dwIndex < PH_UWB_MAX_TIMER) && (wRegisterStatus != UWBSTATUS_SUCCESS));
416        dwIndex++) {
417     /* For Timer, check whether the requested handle is present or not */
418     if (((&apTimerInfo[dwIndex]) == (phOsalUwb_TimerHandle_t*)pObjectHandle) &&
419         (apTimerInfo[dwIndex].TimerId)) {
420       wRegisterStatus = UWBSTATUS_SUCCESS;
421     }
422   }
423   return wRegisterStatus;
424 }
425