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