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