/* * Copyright (C) 2010-2014 NXP Semiconductors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * OSAL Implementation for Timers. */ #include <phNfcCommon.h> #include <phNfcTypes.h> #include <phNxpLog.h> #include <phNxpNciHal.h> #include <phOsalNfc_Timer.h> #include <signal.h> #define PH_NFC_MAX_TIMER (5U) static phOsalNfc_TimerHandle_t apTimerInfo[PH_NFC_MAX_TIMER]; extern phNxpNciHal_Control_t nxpncihal_ctrl; /* * Defines the base address for generating timerid. */ #define PH_NFC_TIMER_BASE_ADDRESS (100U) /* * Defines the value for invalid timerid returned during timeSetEvent */ #define PH_NFC_TIMER_ID_ZERO (0x00) /* * Invalid timer ID type. This ID used indicate timer creation is failed */ #define PH_NFC_TIMER_ID_INVALID (0xFFFF) /* Forward declarations */ static void phOsalNfc_PostTimerMsg(phLibNfc_Message_t* pMsg); static void phOsalNfc_DeferredCall(void* pParams); static void phOsalNfc_Timer_Expired(union sigval sv); /* *************************** Function Definitions ****************************** */ /******************************************************************************* ** ** Function phOsalNfc_Timer_Create ** ** Description Creates a timer which shall call back the specified function ** when the timer expires. Fails if OSAL module is not ** initialized or timers are already occupied ** ** Parameters None ** ** Returns TimerId ** TimerId value of PH_OSALNFC_TIMER_ID_INVALID indicates that ** timer is not created ** *******************************************************************************/ uint32_t phOsalNfc_Timer_Create(void) { /* dwTimerId is also used as an index at which timer object can be stored */ uint32_t dwTimerId = PH_OSALNFC_TIMER_ID_INVALID; static struct sigevent se; phOsalNfc_TimerHandle_t* pTimerHandle; /* Timer needs to be initialized for timer usage */ se.sigev_notify = SIGEV_THREAD; se.sigev_notify_function = phOsalNfc_Timer_Expired; se.sigev_notify_attributes = NULL; dwTimerId = phUtilNfc_CheckForAvailableTimer(); /* Check whether timers are available, if yes create a timer handle structure */ if ((PH_NFC_TIMER_ID_ZERO != dwTimerId) && (dwTimerId <= PH_NFC_MAX_TIMER)) { pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwTimerId - 1]; /* Build the Timer Id to be returned to Caller Function */ dwTimerId += PH_NFC_TIMER_BASE_ADDRESS; se.sigev_value.sival_int = (int)dwTimerId; /* Create POSIX timer */ if (timer_create(CLOCK_REALTIME, &se, &(pTimerHandle->hTimerHandle)) == -1) { dwTimerId = PH_NFC_TIMER_ID_INVALID; } else { /* Set the state to indicate timer is ready */ pTimerHandle->eState = eTimerIdle; /* Store the Timer Id which shall act as flag during check for timer * availability */ pTimerHandle->TimerId = dwTimerId; } } else { dwTimerId = PH_NFC_TIMER_ID_INVALID; } /* Timer ID invalid can be due to Uninitialized state,Non availability of * Timer */ return dwTimerId; } /******************************************************************************* ** ** Function phOsalNfc_Timer_Start ** ** Description Starts the requested, already created, timer. ** If the timer is already running, timer stops and restarts ** with the new timeout value and new callback function in case ** any ?????? ** Creates a timer which shall call back the specified function ** when the timer expires ** ** Parameters dwTimerId - valid timer ID obtained during timer creation ** dwRegTimeCnt - requested timeout in milliseconds ** pApplication_callback - application callback interface to be ** called when timer expires ** pContext - caller context, to be passed to the application ** callback function ** ** Returns NFC status: ** NFCSTATUS_SUCCESS - the operation was successful ** NFCSTATUS_NOT_INITIALISED - OSAL Module is not initialized ** NFCSTATUS_INVALID_PARAMETER - invalid parameter passed to ** the function ** PH_OSALNFC_TIMER_START_ERROR - timer could not be created ** due to system error ** *******************************************************************************/ NFCSTATUS phOsalNfc_Timer_Start(uint32_t dwTimerId, uint32_t dwRegTimeCnt, pphOsalNfc_TimerCallbck_t pApplication_callback, void* pContext) { NFCSTATUS wStartStatus = NFCSTATUS_SUCCESS; struct itimerspec its; uint32_t dwIndex; phOsalNfc_TimerHandle_t* pTimerHandle; /* Retrieve the index at which the timer handle structure is stored */ dwIndex = dwTimerId - PH_NFC_TIMER_BASE_ADDRESS - 0x01; pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex]; /* OSAL Module needs to be initialized for timer usage */ /* Check whether the handle provided by user is valid */ if ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 != pTimerHandle->TimerId) && (NULL != pApplication_callback)) { its.it_interval.tv_sec = 0; its.it_interval.tv_nsec = 0; its.it_value.tv_sec = dwRegTimeCnt / 1000; its.it_value.tv_nsec = 1000000 * (dwRegTimeCnt % 1000); if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) { /* This would inadvertently stop the timer*/ its.it_value.tv_nsec = 1; } pTimerHandle->Application_callback = pApplication_callback; pTimerHandle->pContext = pContext; pTimerHandle->eState = eTimerRunning; /* Arm the timer */ if ((timer_settime(pTimerHandle->hTimerHandle, 0, &its, NULL)) == -1) { wStartStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_START_ERROR); } } else { wStartStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER); } return wStartStatus; } /******************************************************************************* ** ** Function phOsalNfc_Timer_Stop ** ** Description Stops already started timer ** Allows to stop running timer. In case timer is stopped, ** timer callback will not be notified any more ** ** Parameters dwTimerId - valid timer ID obtained during timer creation ** ** Returns NFC status: ** NFCSTATUS_SUCCESS - the operation was successful ** NFCSTATUS_NOT_INITIALISED - OSAL Module is not initialized ** NFCSTATUS_INVALID_PARAMETER - invalid parameter passed to ** the function ** PH_OSALNFC_TIMER_STOP_ERROR - timer could not be stopped due ** to system error ** *******************************************************************************/ NFCSTATUS phOsalNfc_Timer_Stop(uint32_t dwTimerId) { NFCSTATUS wStopStatus = NFCSTATUS_SUCCESS; static struct itimerspec its = {{0, 0}, {0, 0}}; uint32_t dwIndex; phOsalNfc_TimerHandle_t* pTimerHandle; dwIndex = dwTimerId - PH_NFC_TIMER_BASE_ADDRESS - 0x01; pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex]; /* OSAL Module and Timer needs to be initialized for timer usage */ /* Check whether the TimerId provided by user is valid */ if ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 != pTimerHandle->TimerId) && (pTimerHandle->eState != eTimerIdle)) { /* Stop the timer only if the callback has not been invoked */ if (pTimerHandle->eState == eTimerRunning) { if ((timer_settime(pTimerHandle->hTimerHandle, 0, &its, NULL)) == -1) { wStopStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_STOP_ERROR); } else { /* Change the state of timer to Stopped */ pTimerHandle->eState = eTimerStopped; } } } else { wStopStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER); } return wStopStatus; } /******************************************************************************* ** ** Function phOsalNfc_Timer_Delete ** ** Description Deletes previously created timer ** Allows to delete previously created timer. In case timer is ** running, it is first stopped and then deleted ** ** Parameters dwTimerId - valid timer ID obtained during timer creation ** ** Returns NFC status: ** NFCSTATUS_SUCCESS - the operation was successful ** NFCSTATUS_NOT_INITIALISED - OSAL Module is not initialized ** NFCSTATUS_INVALID_PARAMETER - invalid parameter passed to ** the function ** PH_OSALNFC_TIMER_DELETE_ERROR - timer could not be stopped ** due to system error ** *******************************************************************************/ NFCSTATUS phOsalNfc_Timer_Delete(uint32_t dwTimerId) { NFCSTATUS wDeleteStatus = NFCSTATUS_SUCCESS; uint32_t dwIndex; phOsalNfc_TimerHandle_t* pTimerHandle; dwIndex = dwTimerId - PH_NFC_TIMER_BASE_ADDRESS - 0x01; pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex]; /* OSAL Module and Timer needs to be initialized for timer usage */ /* Check whether the TimerId passed by user is valid and Deregistering of * timer is successful */ if ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 != pTimerHandle->TimerId) && (NFCSTATUS_SUCCESS == phOsalNfc_CheckTimerPresence(pTimerHandle))) { /* Cancel the timer before deleting */ if (timer_delete(pTimerHandle->hTimerHandle) == -1) { wDeleteStatus = PHNFCSTVAL(CID_NFC_OSAL, PH_OSALNFC_TIMER_DELETE_ERROR); } /* Clear Timer structure used to store timer related data */ memset(pTimerHandle, (uint8_t)0x00, sizeof(phOsalNfc_TimerHandle_t)); } else { wDeleteStatus = PHNFCSTVAL(CID_NFC_OSAL, NFCSTATUS_INVALID_PARAMETER); } return wDeleteStatus; } /******************************************************************************* ** ** Function phOsalNfc_Timer_Cleanup ** ** Description Deletes all previously created timers ** Allows to delete previously created timers. In case timer is ** running, it is first stopped and then deleted ** ** Parameters None ** ** Returns None ** *******************************************************************************/ void phOsalNfc_Timer_Cleanup(void) { /* Delete all timers */ uint32_t dwIndex; phOsalNfc_TimerHandle_t* pTimerHandle; for (dwIndex = 0; dwIndex < PH_NFC_MAX_TIMER; dwIndex++) { pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex]; /* OSAL Module and Timer needs to be initialized for timer usage */ /* Check whether the TimerId passed by user is valid and Deregistering of * timer is successful */ if ((0x00 != pTimerHandle->TimerId) && (NFCSTATUS_SUCCESS == phOsalNfc_CheckTimerPresence(pTimerHandle))) { /* Cancel the timer before deleting */ if (timer_delete(pTimerHandle->hTimerHandle) == -1) { NXPLOG_TML_E("timer %d delete error!", dwIndex); } /* Clear Timer structure used to store timer related data */ memset(pTimerHandle, (uint8_t)0x00, sizeof(phOsalNfc_TimerHandle_t)); } } return; } /******************************************************************************* ** ** Function phOsalNfc_DeferredCall ** ** Description Invokes the timer callback function after timer expiration. ** Shall invoke the callback function registered by the timer ** caller function ** ** Parameters pParams - parameters indicating the ID of the timer ** ** Returns None - ** *******************************************************************************/ static void phOsalNfc_DeferredCall(void* pParams) { /* Retrieve the timer id from the parameter */ uint32_t dwIndex; phOsalNfc_TimerHandle_t* pTimerHandle; if (NULL != pParams) { /* Retrieve the index at which the timer handle structure is stored */ dwIndex = (uintptr_t)pParams - PH_NFC_TIMER_BASE_ADDRESS - 0x01; pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex]; if (pTimerHandle->Application_callback != NULL) { /* Invoke the callback function with osal Timer ID */ pTimerHandle->Application_callback((uintptr_t)pParams, pTimerHandle->pContext); } } return; } /******************************************************************************* ** ** Function phOsalNfc_PostTimerMsg ** ** Description Posts message on the user thread ** Shall be invoked upon expiration of a timer ** Shall post message on user thread through which timer ** callback function shall be invoked ** ** Parameters pMsg - pointer to the message structure posted on user ** thread ** ** Returns None ** *******************************************************************************/ static void phOsalNfc_PostTimerMsg(phLibNfc_Message_t* pMsg) { (void)phDal4Nfc_msgsnd( nxpncihal_ctrl.gDrvCfg .nClientId /*gpphOsalNfc_Context->dwCallbackThreadID*/, pMsg, 0); return; } /******************************************************************************* ** ** Function phOsalNfc_Timer_Expired ** ** Description posts message upon expiration of timer ** Shall be invoked when any one timer is expired ** Shall post message on user thread to invoke respective ** callback function provided by the caller of Timer function ** ** Returns None ** *******************************************************************************/ static void phOsalNfc_Timer_Expired(union sigval sv) { uint32_t dwIndex; phOsalNfc_TimerHandle_t* pTimerHandle; dwIndex = ((uint32_t)(sv.sival_int)) - PH_NFC_TIMER_BASE_ADDRESS - 0x01; pTimerHandle = (phOsalNfc_TimerHandle_t*)&apTimerInfo[dwIndex]; /* Timer is stopped when callback function is invoked */ pTimerHandle->eState = eTimerStopped; pTimerHandle->tDeferedCallInfo.pDeferedCall = &phOsalNfc_DeferredCall; pTimerHandle->tDeferedCallInfo.pParam = (void*)((intptr_t)(sv.sival_int)); pTimerHandle->tOsalMessage.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG; pTimerHandle->tOsalMessage.pMsgData = (void*)&pTimerHandle->tDeferedCallInfo; /* Post a message on the queue to invoke the function */ phOsalNfc_PostTimerMsg((phLibNfc_Message_t*)&pTimerHandle->tOsalMessage); return; } /******************************************************************************* ** ** Function phUtilNfc_CheckForAvailableTimer ** ** Description Find an available timer id ** ** Parameters void ** ** Returns Available timer id ** *******************************************************************************/ uint32_t phUtilNfc_CheckForAvailableTimer(void) { /* Variable used to store the index at which the object structure details can be stored. Initialize it as not available. */ uint32_t dwIndex = 0x00; uint32_t dwRetval = 0x00; /* Check whether Timer object can be created */ for (dwIndex = 0x00; ((dwIndex < PH_NFC_MAX_TIMER) && (0x00 == dwRetval)); dwIndex++) { if (!(apTimerInfo[dwIndex].TimerId)) { dwRetval = (dwIndex + 0x01); } } return (dwRetval); } /******************************************************************************* ** ** Function phOsalNfc_CheckTimerPresence ** ** Description Checks the requested timer is present or not ** ** Parameters pObjectHandle - timer context ** ** Returns NFCSTATUS_SUCCESS if found ** Other value if not found ** *******************************************************************************/ NFCSTATUS phOsalNfc_CheckTimerPresence(void* pObjectHandle) { uint32_t dwIndex; NFCSTATUS wRegisterStatus = NFCSTATUS_INVALID_PARAMETER; for (dwIndex = 0x00; ((dwIndex < PH_NFC_MAX_TIMER) && (wRegisterStatus != NFCSTATUS_SUCCESS)); dwIndex++) { /* For Timer, check whether the requested handle is present or not */ if (((&apTimerInfo[dwIndex]) == (phOsalNfc_TimerHandle_t*)pObjectHandle) && (apTimerInfo[dwIndex].TimerId)) { wRegisterStatus = NFCSTATUS_SUCCESS; } } return wRegisterStatus; }