278 lines
7.2 KiB
C
278 lines
7.2 KiB
C
/*
|
|
* Copyright (C) 2010 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.
|
|
*/
|
|
|
|
/**
|
|
* \file phOsalNfc_Timer.c
|
|
* \brief OSAL Timer Implementation for linux
|
|
*
|
|
* Project: Trusted NFC Linux Light
|
|
*
|
|
* $Date: 03 aug 2009
|
|
* $Author: Jérémie Corbier
|
|
* $Revision: 1.0
|
|
*
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
|
|
#include <phOsalNfc.h>
|
|
#include <phOsalNfc_Timer.h>
|
|
#include <stdio.h>
|
|
|
|
#include <phDal4Nfc_messageQueueLib.h>
|
|
|
|
#define NSECS 1000000
|
|
#define MAX_NO_TIMERS 16
|
|
|
|
/*!
|
|
* \struct phOsalNfc_Timer
|
|
* Internal OSAL timer structure
|
|
*/
|
|
struct phOsalNfc_Timer
|
|
{
|
|
timer_t handle; /*!< System timer handle. */
|
|
ppCallBck_t callback; /*!< Callback to be called when timer expires. */
|
|
void* pContext; /*!< Callback context. */
|
|
#ifdef NXP_MESSAGING
|
|
void *ptr;
|
|
#endif
|
|
int nIsStopped;
|
|
};
|
|
|
|
static struct phOsalNfc_Timer timers[MAX_NO_TIMERS] =
|
|
{
|
|
{0, NULL, NULL
|
|
#ifdef NXP_MESSAGING
|
|
, NULL
|
|
#endif
|
|
, 0
|
|
},
|
|
};
|
|
|
|
#ifdef NXP_MESSAGING
|
|
extern int nDeferedCallMessageQueueId;
|
|
|
|
void phOsalNfc_Timer_DeferredCall(void *params)
|
|
{
|
|
phOsalNfc_Timer_Msg_t *timer_msg;
|
|
|
|
if(params == NULL)
|
|
return;
|
|
|
|
timer_msg = (phOsalNfc_Timer_Msg_t *)params;
|
|
|
|
if((timer_msg != NULL) && (timer_msg->pCallBck != NULL))
|
|
timer_msg->pCallBck(timer_msg->TimerId, timer_msg->pContext);
|
|
|
|
if ((timer_msg->TimerId >= MAX_NO_TIMERS) || (timer_msg->TimerId < 0))
|
|
{
|
|
printf("Bad TimerId=%d, should be <= to %d\n", timer_msg->TimerId, MAX_NO_TIMERS);
|
|
}
|
|
else
|
|
{
|
|
if(timers[timer_msg->TimerId].ptr != NULL)
|
|
{
|
|
phOsalNfc_FreeMemory(timers[timer_msg->TimerId].ptr);
|
|
timers[timer_msg->TimerId].ptr = NULL;
|
|
}
|
|
}
|
|
phOsalNfc_FreeMemory(timer_msg);
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
* \brief System timer callback.
|
|
* This callback is called by Linux whenever one the timers expires. It
|
|
* calls the corresponding registered callback.
|
|
*
|
|
* \param sv structure storing the expired timer ID.
|
|
*/
|
|
static void phOsalNfc_Timer_Expired(union sigval sv)
|
|
{
|
|
uint32_t timerid = (uint32_t)(sv.sival_int);
|
|
|
|
if((timerid < MAX_NO_TIMERS)&&(timers[timerid].nIsStopped == 1))
|
|
{
|
|
//printf("phOsalNfc_Timer_Expired : Expired but already stopped TimerId=%d\n", timerid);
|
|
return;
|
|
}
|
|
|
|
if(timerid < MAX_NO_TIMERS)
|
|
{
|
|
#ifndef CYCLIC_TIMER
|
|
phOsalNfc_Timer_Stop(timerid);
|
|
#else
|
|
|
|
#endif
|
|
#ifdef NXP_MESSAGING
|
|
phOsalNfc_Timer_Msg_t *timer_msg;
|
|
phOsalNfc_DeferedCalldInfo_t *osal_defer_msg;
|
|
phDal4Nfc_Message_Wrapper_t wrapper;
|
|
|
|
timer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_Timer_Msg_t));
|
|
if(timer_msg == NULL)
|
|
phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0);
|
|
|
|
osal_defer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_DeferedCalldInfo_t));
|
|
if(osal_defer_msg == NULL)
|
|
{
|
|
phOsalNfc_FreeMemory(timer_msg);
|
|
phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0);
|
|
}
|
|
|
|
timer_msg->TimerId = timerid;
|
|
timer_msg->pCallBck = timers[timerid].callback;
|
|
timer_msg->pContext = timers[timerid].pContext;
|
|
|
|
osal_defer_msg->pCallback = phOsalNfc_Timer_DeferredCall;
|
|
osal_defer_msg->pParameter = timer_msg;
|
|
|
|
wrapper.mtype = 1;
|
|
wrapper.msg.eMsgType = PH_OSALNFC_TIMER_MSG;
|
|
wrapper.msg.pMsgData = osal_defer_msg;
|
|
wrapper.msg.Size = sizeof(phOsalNfc_DeferedCalldInfo_t);
|
|
|
|
timers[timerid].ptr = osal_defer_msg;
|
|
|
|
phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (void *)&wrapper,
|
|
sizeof(phOsalNfc_Message_t), 0);
|
|
#else
|
|
(timers[timerid].callback)(timerid, timers[timerid].pContext);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void phOsalNfc_Timer_Dummy_Cb(uint32_t timerid, void *pContext) {}
|
|
|
|
/*!
|
|
* \brief Creates a new timer.
|
|
* This function checks whether there is an available timer slot. If
|
|
* this is the case, then it reserves it for future usage and returns its
|
|
* ID.
|
|
*
|
|
* \return a valid timer ID or PH_OSALNFC_INVALID_TIMER_ID if an error occured.
|
|
*/
|
|
uint32_t phOsalNfc_Timer_Create(void)
|
|
{
|
|
uint32_t timerid;
|
|
struct sigevent se;
|
|
|
|
se.sigev_notify = SIGEV_THREAD;
|
|
se.sigev_notify_function = phOsalNfc_Timer_Expired;
|
|
se.sigev_notify_attributes = NULL;
|
|
|
|
/* Look for available timer slot */
|
|
for(timerid = 0; timerid < MAX_NO_TIMERS; timerid++)
|
|
if(timers[timerid].callback == NULL)
|
|
break;
|
|
if(timerid == MAX_NO_TIMERS)
|
|
return PH_OSALNFC_INVALID_TIMER_ID;
|
|
|
|
se.sigev_value.sival_int = (int)timerid;
|
|
|
|
/* Create POSIX timer */
|
|
if(timer_create(CLOCK_REALTIME, &se, &(timers[timerid].handle)) == -1)
|
|
return PH_OSALNFC_INVALID_TIMER_ID;
|
|
timers[timerid].callback = phOsalNfc_Timer_Dummy_Cb;
|
|
#ifdef NXP_MESSAGING
|
|
timers[timerid].ptr = NULL;
|
|
#endif
|
|
|
|
return timerid;
|
|
}
|
|
|
|
/*!
|
|
* \brief Starts a timer.
|
|
* This function starts the timer \a TimerId with an expiration time of
|
|
* \a RegTimeCnt milliseconds. Each time it expires, \a
|
|
* Application_callback is called.
|
|
*
|
|
* \param TimerId a valid timer ID.
|
|
* \param RegTimeCnt expiration time in milliseconds.
|
|
* \param Application_callback callback to be called when timer expires.
|
|
*/
|
|
void phOsalNfc_Timer_Start(uint32_t TimerId,
|
|
uint32_t RegTimeCnt,
|
|
ppCallBck_t Application_callback,
|
|
void *pContext)
|
|
{
|
|
struct itimerspec its;
|
|
|
|
if(TimerId >= MAX_NO_TIMERS)
|
|
return;
|
|
if(Application_callback == NULL)
|
|
return;
|
|
if(timers[TimerId].callback == NULL)
|
|
return;
|
|
|
|
its.it_interval.tv_sec = 0;
|
|
its.it_interval.tv_nsec = 0;
|
|
its.it_value.tv_sec = RegTimeCnt / 1000;
|
|
its.it_value.tv_nsec = 1000000 * (RegTimeCnt % 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;
|
|
}
|
|
|
|
timers[TimerId].callback = Application_callback;
|
|
timers[TimerId].pContext = pContext;
|
|
timers[TimerId].nIsStopped = 0;
|
|
|
|
timer_settime(timers[TimerId].handle, 0, &its, NULL);
|
|
}
|
|
|
|
/*!
|
|
* \brief Stops a timer.
|
|
* This function stops an already started timer.
|
|
*
|
|
* \param TimerId a valid timer ID.
|
|
*/
|
|
void phOsalNfc_Timer_Stop(uint32_t TimerId)
|
|
{
|
|
struct itimerspec its = {{0, 0}, {0, 0}};
|
|
|
|
if(TimerId >= MAX_NO_TIMERS)
|
|
return;
|
|
if(timers[TimerId].callback == NULL)
|
|
return;
|
|
if(timers[TimerId].nIsStopped == 1)
|
|
return;
|
|
|
|
timers[TimerId].nIsStopped = 1;
|
|
timer_settime(timers[TimerId].handle, 0, &its, NULL);
|
|
}
|
|
|
|
/*!
|
|
* \brief Deletes a timer.
|
|
* This function deletes a timer.
|
|
*
|
|
* \param TimerId a valid timer ID.
|
|
*/
|
|
void phOsalNfc_Timer_Delete(uint32_t TimerId)
|
|
{
|
|
if(TimerId >= MAX_NO_TIMERS)
|
|
return;
|
|
if(timers[TimerId].callback == NULL)
|
|
return;
|
|
|
|
timer_delete(timers[TimerId].handle);
|
|
|
|
timers[TimerId].callback = NULL;
|
|
timers[TimerId].pContext = NULL;
|
|
}
|