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