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