Home | History | Annotate | Download | only in tml
      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