1 /* 2 * Copyright (C) 2010 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 * \file phOsalNfc_Timer.c 19 * \brief OSAL Timer Implementation for linux 20 * 21 * Project: Trusted NFC Linux Light 22 * 23 * $Date: 03 aug 2009 24 * $Author: Jrmie Corbier 25 * $Revision: 1.0 26 * 27 */ 28 29 #include <stdlib.h> 30 #include <signal.h> 31 #include <time.h> 32 33 #include <phOsalNfc.h> 34 #include <phOsalNfc_Timer.h> 35 #include <stdio.h> 36 37 #include <phDal4Nfc_messageQueueLib.h> 38 39 #define NSECS 1000000 40 #define MAX_NO_TIMERS 16 41 42 /*! 43 * \struct phOsalNfc_Timer 44 * Internal OSAL timer structure 45 */ 46 struct phOsalNfc_Timer 47 { 48 timer_t handle; /*!< System timer handle. */ 49 ppCallBck_t callback; /*!< Callback to be called when timer expires. */ 50 void* pContext; /*!< Callback context. */ 51 #ifdef NXP_MESSAGING 52 void *ptr; 53 #endif 54 int nIsStopped; 55 }; 56 57 static struct phOsalNfc_Timer timers[MAX_NO_TIMERS] = 58 { 59 {0, NULL, NULL 60 #ifdef NXP_MESSAGING 61 , NULL 62 #endif 63 , 0 64 }, 65 }; 66 67 #ifdef NXP_MESSAGING 68 extern int nDeferedCallMessageQueueId; 69 70 void phOsalNfc_Timer_DeferredCall(void *params) 71 { 72 phOsalNfc_Timer_Msg_t *timer_msg; 73 74 if(params == NULL) 75 return; 76 77 timer_msg = (phOsalNfc_Timer_Msg_t *)params; 78 79 if((timer_msg != NULL) && (timer_msg->pCallBck != NULL)) 80 timer_msg->pCallBck(timer_msg->TimerId, timer_msg->pContext); 81 82 if ((timer_msg->TimerId >= MAX_NO_TIMERS) || (timer_msg->TimerId < 0)) 83 { 84 printf("Bad TimerId=%d, should be <= to %d\n", timer_msg->TimerId, MAX_NO_TIMERS); 85 } 86 else 87 { 88 if(timers[timer_msg->TimerId].ptr != NULL) 89 { 90 phOsalNfc_FreeMemory(timers[timer_msg->TimerId].ptr); 91 timers[timer_msg->TimerId].ptr = NULL; 92 } 93 } 94 phOsalNfc_FreeMemory(timer_msg); 95 } 96 #endif 97 98 /*! 99 * \brief System timer callback. 100 * This callback is called by Linux whenever one the timers expires. It 101 * calls the corresponding registered callback. 102 * 103 * \param sv structure storing the expired timer ID. 104 */ 105 static void phOsalNfc_Timer_Expired(union sigval sv) 106 { 107 uint32_t timerid = (uint32_t)(sv.sival_int); 108 109 if((timerid < MAX_NO_TIMERS)&&(timers[timerid].nIsStopped == 1)) 110 { 111 //printf("phOsalNfc_Timer_Expired : Expired but already stopped TimerId=%d\n", timerid); 112 return; 113 } 114 115 if(timerid < MAX_NO_TIMERS) 116 { 117 #ifndef CYCLIC_TIMER 118 phOsalNfc_Timer_Stop(timerid); 119 #else 120 121 #endif 122 #ifdef NXP_MESSAGING 123 phOsalNfc_Timer_Msg_t *timer_msg; 124 phOsalNfc_DeferedCalldInfo_t *osal_defer_msg; 125 phDal4Nfc_Message_Wrapper_t wrapper; 126 127 timer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_Timer_Msg_t)); 128 if(timer_msg == NULL) 129 phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0); 130 131 osal_defer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_DeferedCalldInfo_t)); 132 if(osal_defer_msg == NULL) 133 { 134 phOsalNfc_FreeMemory(timer_msg); 135 phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0); 136 } 137 138 timer_msg->TimerId = timerid; 139 timer_msg->pCallBck = timers[timerid].callback; 140 timer_msg->pContext = timers[timerid].pContext; 141 142 osal_defer_msg->pCallback = phOsalNfc_Timer_DeferredCall; 143 osal_defer_msg->pParameter = timer_msg; 144 145 wrapper.mtype = 1; 146 wrapper.msg.eMsgType = PH_OSALNFC_TIMER_MSG; 147 wrapper.msg.pMsgData = osal_defer_msg; 148 wrapper.msg.Size = sizeof(phOsalNfc_DeferedCalldInfo_t); 149 150 timers[timerid].ptr = osal_defer_msg; 151 152 phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (void *)&wrapper, 153 sizeof(phOsalNfc_Message_t), 0); 154 #else 155 (timers[timerid].callback)(timerid, timers[timerid].pContext); 156 #endif 157 } 158 } 159 160 static void phOsalNfc_Timer_Dummy_Cb(uint32_t timerid, void *pContext) {} 161 162 /*! 163 * \brief Creates a new timer. 164 * This function checks whether there is an available timer slot. If 165 * this is the case, then it reserves it for future usage and returns its 166 * ID. 167 * 168 * \return a valid timer ID or PH_OSALNFC_INVALID_TIMER_ID if an error occured. 169 */ 170 uint32_t phOsalNfc_Timer_Create(void) 171 { 172 uint32_t timerid; 173 struct sigevent se; 174 175 se.sigev_notify = SIGEV_THREAD; 176 se.sigev_notify_function = phOsalNfc_Timer_Expired; 177 se.sigev_notify_attributes = NULL; 178 179 /* Look for available timer slot */ 180 for(timerid = 0; timerid < MAX_NO_TIMERS; timerid++) 181 if(timers[timerid].callback == NULL) 182 break; 183 if(timerid == MAX_NO_TIMERS) 184 return PH_OSALNFC_INVALID_TIMER_ID; 185 186 se.sigev_value.sival_int = (int)timerid; 187 188 /* Create POSIX timer */ 189 if(timer_create(CLOCK_REALTIME, &se, &(timers[timerid].handle)) == -1) 190 return PH_OSALNFC_INVALID_TIMER_ID; 191 timers[timerid].callback = phOsalNfc_Timer_Dummy_Cb; 192 #ifdef NXP_MESSAGING 193 timers[timerid].ptr = NULL; 194 #endif 195 196 return timerid; 197 } 198 199 /*! 200 * \brief Starts a timer. 201 * This function starts the timer \a TimerId with an expiration time of 202 * \a RegTimeCnt milliseconds. Each time it expires, \a 203 * Application_callback is called. 204 * 205 * \param TimerId a valid timer ID. 206 * \param RegTimeCnt expiration time in milliseconds. 207 * \param Application_callback callback to be called when timer expires. 208 */ 209 void phOsalNfc_Timer_Start(uint32_t TimerId, 210 uint32_t RegTimeCnt, 211 ppCallBck_t Application_callback, 212 void *pContext) 213 { 214 struct itimerspec its; 215 216 if(TimerId >= MAX_NO_TIMERS) 217 return; 218 if(Application_callback == NULL) 219 return; 220 if(timers[TimerId].callback == NULL) 221 return; 222 223 its.it_interval.tv_sec = 0; 224 its.it_interval.tv_nsec = 0; 225 its.it_value.tv_sec = RegTimeCnt / 1000; 226 its.it_value.tv_nsec = 1000000 * (RegTimeCnt % 1000); 227 if(its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) 228 { 229 // this would inadvertently stop the timer 230 its.it_value.tv_nsec = 1; 231 } 232 233 timers[TimerId].callback = Application_callback; 234 timers[TimerId].pContext = pContext; 235 timers[TimerId].nIsStopped = 0; 236 237 timer_settime(timers[TimerId].handle, 0, &its, NULL); 238 } 239 240 /*! 241 * \brief Stops a timer. 242 * This function stops an already started timer. 243 * 244 * \param TimerId a valid timer ID. 245 */ 246 void phOsalNfc_Timer_Stop(uint32_t TimerId) 247 { 248 struct itimerspec its = {{0, 0}, {0, 0}}; 249 250 if(TimerId >= MAX_NO_TIMERS) 251 return; 252 if(timers[TimerId].callback == NULL) 253 return; 254 if(timers[TimerId].nIsStopped == 1) 255 return; 256 257 timers[TimerId].nIsStopped = 1; 258 timer_settime(timers[TimerId].handle, 0, &its, NULL); 259 } 260 261 /*! 262 * \brief Deletes a timer. 263 * This function deletes a timer. 264 * 265 * \param TimerId a valid timer ID. 266 */ 267 void phOsalNfc_Timer_Delete(uint32_t TimerId) 268 { 269 if(TimerId >= MAX_NO_TIMERS) 270 return; 271 if(timers[TimerId].callback == NULL) 272 return; 273 274 timer_delete(timers[TimerId].handle); 275 276 timers[TimerId].callback = NULL; 277 timers[TimerId].pContext = NULL; 278 } 279