pcsc-lite
1.8.3
|
00001 /* 00002 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 00003 * 00004 * Copyright (C) 2000-2002 00005 * David Corcoran <corcoran@linuxnet.com> 00006 * Copyright (C) 2002-2011 00007 * Ludovic Rousseau <ludovic.rousseau@free.fr> 00008 * 00009 * $Id: eventhandler.c 5859 2011-07-09 11:28:20Z rousseau $ 00010 */ 00011 00018 #include "config.h" 00019 #include <sys/types.h> 00020 #include <sys/stat.h> 00021 #include <errno.h> 00022 #include <fcntl.h> 00023 #include <string.h> 00024 #include <stdlib.h> 00025 #include <pthread.h> 00026 00027 #include "misc.h" 00028 #include "pcscd.h" 00029 #include "debuglog.h" 00030 #include "readerfactory.h" 00031 #include "eventhandler.h" 00032 #include "dyn_generic.h" 00033 #include "sys_generic.h" 00034 #include "ifdwrapper.h" 00035 #include "prothandler.h" 00036 #include "strlcpycat.h" 00037 #include "utils.h" 00038 #include "winscard_svc.h" 00039 #include "simclist.h" 00040 00041 static list_t ClientsWaitingForEvent; 00042 pthread_mutex_t ClientsWaitingForEvent_lock; 00044 static void EHStatusHandlerThread(READER_CONTEXT *); 00045 00046 LONG EHRegisterClientForEvent(int32_t filedes) 00047 { 00048 (void)pthread_mutex_lock(&ClientsWaitingForEvent_lock); 00049 00050 (void)list_append(&ClientsWaitingForEvent, &filedes); 00051 00052 (void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock); 00053 00054 return SCARD_S_SUCCESS; 00055 } /* EHRegisterClientForEvent */ 00056 00061 LONG EHTryToUnregisterClientForEvent(int32_t filedes) 00062 { 00063 LONG rv = SCARD_S_SUCCESS; 00064 int ret; 00065 00066 (void)pthread_mutex_lock(&ClientsWaitingForEvent_lock); 00067 00068 ret = list_delete(&ClientsWaitingForEvent, &filedes); 00069 00070 (void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock); 00071 00072 if (ret < 0) 00073 rv = SCARD_F_INTERNAL_ERROR; 00074 00075 return rv; 00076 } /* EHTryToUnregisterClientForEvent */ 00077 00081 LONG EHUnregisterClientForEvent(int32_t filedes) 00082 { 00083 LONG rv = EHTryToUnregisterClientForEvent(filedes); 00084 00085 if (rv < 0) 00086 Log2(PCSC_LOG_ERROR, "Can't remove client: %d", filedes); 00087 00088 return rv; 00089 } /* EHUnregisterClientForEvent */ 00090 00094 LONG EHSignalEventToClients(void) 00095 { 00096 LONG rv = SCARD_S_SUCCESS; 00097 int32_t filedes; 00098 00099 (void)pthread_mutex_lock(&ClientsWaitingForEvent_lock); 00100 00101 (void)list_iterator_start(&ClientsWaitingForEvent); 00102 while (list_iterator_hasnext(&ClientsWaitingForEvent)) 00103 { 00104 filedes = *(int32_t *)list_iterator_next(&ClientsWaitingForEvent); 00105 rv = MSGSignalClient(filedes, SCARD_S_SUCCESS); 00106 } 00107 (void)list_iterator_stop(&ClientsWaitingForEvent); 00108 00109 (void)list_clear(&ClientsWaitingForEvent); 00110 00111 (void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock); 00112 00113 return rv; 00114 } /* EHSignalEventToClients */ 00115 00116 LONG EHInitializeEventStructures(void) 00117 { 00118 (void)list_init(&ClientsWaitingForEvent); 00119 00120 /* request to store copies, and provide the metric function */ 00121 (void)list_attributes_copy(&ClientsWaitingForEvent, list_meter_int32_t, 1); 00122 00123 /* setting the comparator, so the list can sort, find the min, max etc */ 00124 (void)list_attributes_comparator(&ClientsWaitingForEvent, list_comparator_int32_t); 00125 00126 (void)pthread_mutex_init(&ClientsWaitingForEvent_lock, NULL); 00127 00128 return SCARD_S_SUCCESS; 00129 } 00130 00131 LONG EHDestroyEventHandler(READER_CONTEXT * rContext) 00132 { 00133 int rv; 00134 DWORD dwGetSize; 00135 UCHAR ucGetData[1]; 00136 00137 if ('\0' == rContext->readerState->readerName[0]) 00138 { 00139 Log1(PCSC_LOG_INFO, "Thread already stomped."); 00140 return SCARD_S_SUCCESS; 00141 } 00142 00143 /* 00144 * Set the thread to 0 to exit thread 00145 */ 00146 rContext->hLockId = 0xFFFF; 00147 00148 Log1(PCSC_LOG_INFO, "Stomping thread."); 00149 00150 /* kill the "polling" thread */ 00151 dwGetSize = sizeof(ucGetData); 00152 rv = IFDGetCapabilities(rContext, TAG_IFD_POLLING_THREAD_KILLABLE, 00153 &dwGetSize, ucGetData); 00154 00155 #ifdef HAVE_PTHREAD_CANCEL 00156 if ((IFD_SUCCESS == rv) && (1 == dwGetSize) && ucGetData[0]) 00157 { 00158 Log1(PCSC_LOG_INFO, "Killing polling thread"); 00159 (void)pthread_cancel(rContext->pthThread); 00160 } 00161 else 00162 #endif 00163 { 00164 /* ask to stop the "polling" thread */ 00165 RESPONSECODE (*fct)(DWORD) = NULL; 00166 00167 dwGetSize = sizeof(fct); 00168 rv = IFDGetCapabilities(rContext, TAG_IFD_STOP_POLLING_THREAD, 00169 &dwGetSize, (PUCHAR)&fct); 00170 00171 if ((IFD_SUCCESS == rv) && (dwGetSize == sizeof(fct))) 00172 { 00173 Log1(PCSC_LOG_INFO, "Request stoping of polling thread"); 00174 fct(rContext->slot); 00175 } 00176 else 00177 Log1(PCSC_LOG_INFO, "Waiting polling thread"); 00178 } 00179 00180 /* wait for the thread to finish */ 00181 rv = pthread_join(rContext->pthThread, NULL); 00182 if (rv) 00183 Log2(PCSC_LOG_ERROR, "pthread_join failed: %s", strerror(rv)); 00184 00185 /* Zero the thread */ 00186 rContext->pthThread = 0; 00187 00188 Log1(PCSC_LOG_INFO, "Thread stomped."); 00189 00190 return SCARD_S_SUCCESS; 00191 } 00192 00193 LONG EHSpawnEventHandler(READER_CONTEXT * rContext) 00194 { 00195 LONG rv; 00196 DWORD dwStatus = 0; 00197 00198 rv = IFDStatusICC(rContext, &dwStatus); 00199 if (rv != SCARD_S_SUCCESS) 00200 { 00201 Log2(PCSC_LOG_ERROR, "Initial Check Failed on %s", 00202 rContext->readerState->readerName); 00203 return SCARD_F_UNKNOWN_ERROR; 00204 } 00205 00206 rv = ThreadCreate(&rContext->pthThread, 0, 00207 (PCSCLITE_THREAD_FUNCTION( ))EHStatusHandlerThread, (LPVOID) rContext); 00208 if (rv) 00209 { 00210 Log2(PCSC_LOG_ERROR, "ThreadCreate failed: %s", strerror(rv)); 00211 return SCARD_E_NO_MEMORY; 00212 } 00213 else 00214 return SCARD_S_SUCCESS; 00215 } 00216 00217 static void EHStatusHandlerThread(READER_CONTEXT * rContext) 00218 { 00219 LONG rv; 00220 const char *readerName; 00221 DWORD dwStatus; 00222 uint32_t readerState; 00223 int32_t readerSharing; 00224 DWORD dwCurrentState; 00225 DWORD dwAtrLen; 00226 00227 /* 00228 * Zero out everything 00229 */ 00230 dwStatus = 0; 00231 00232 readerName = rContext->readerState->readerName; 00233 00234 rv = IFDStatusICC(rContext, &dwStatus); 00235 00236 if ((SCARD_S_SUCCESS == rv) && (dwStatus & SCARD_PRESENT)) 00237 { 00238 #ifdef DISABLE_AUTO_POWER_ON 00239 rContext->readerState->cardAtrLength = 0; 00240 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00241 readerState = SCARD_PRESENT; 00242 Log1(PCSC_LOG_INFO, "Skip card power on"); 00243 #else 00244 dwAtrLen = sizeof(rContext->readerState->cardAtr); 00245 rv = IFDPowerICC(rContext, IFD_POWER_UP, 00246 rContext->readerState->cardAtr, &dwAtrLen); 00247 rContext->readerState->cardAtrLength = dwAtrLen; 00248 00249 /* the protocol is unset after a power on */ 00250 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00251 00252 if (rv == IFD_SUCCESS) 00253 { 00254 readerState = SCARD_PRESENT | SCARD_POWERED | SCARD_NEGOTIABLE; 00255 rContext->powerState = POWER_STATE_POWERED; 00256 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_POWERED"); 00257 00258 if (rContext->readerState->cardAtrLength > 0) 00259 { 00260 LogXxd(PCSC_LOG_INFO, "Card ATR: ", 00261 rContext->readerState->cardAtr, 00262 rContext->readerState->cardAtrLength); 00263 } 00264 else 00265 Log1(PCSC_LOG_INFO, "Card ATR: (NULL)"); 00266 } 00267 else 00268 { 00269 readerState = SCARD_PRESENT | SCARD_SWALLOWED; 00270 rContext->powerState = POWER_STATE_UNPOWERED; 00271 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED"); 00272 Log3(PCSC_LOG_ERROR, "Error powering up card: %ld 0x%04lX", rv, rv); 00273 } 00274 #endif 00275 00276 dwCurrentState = SCARD_PRESENT; 00277 } 00278 else 00279 { 00280 readerState = SCARD_ABSENT; 00281 rContext->readerState->cardAtrLength = 0; 00282 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00283 00284 dwCurrentState = SCARD_ABSENT; 00285 } 00286 00287 /* 00288 * Set all the public attributes to this reader 00289 */ 00290 rContext->readerState->readerState = readerState; 00291 rContext->readerState->readerSharing = readerSharing = rContext->contexts; 00292 00293 (void)EHSignalEventToClients(); 00294 00295 while (1) 00296 { 00297 dwStatus = 0; 00298 00299 rv = IFDStatusICC(rContext, &dwStatus); 00300 00301 if (rv != SCARD_S_SUCCESS) 00302 { 00303 Log2(PCSC_LOG_ERROR, "Error communicating to: %s", readerName); 00304 00305 /* 00306 * Set error status on this reader while errors occur 00307 */ 00308 rContext->readerState->readerState = SCARD_UNKNOWN; 00309 rContext->readerState->cardAtrLength = 0; 00310 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00311 00312 dwCurrentState = SCARD_UNKNOWN; 00313 00314 (void)EHSignalEventToClients(); 00315 } 00316 00317 if (dwStatus & SCARD_ABSENT) 00318 { 00319 if (dwCurrentState == SCARD_PRESENT || 00320 dwCurrentState == SCARD_UNKNOWN) 00321 { 00322 /* 00323 * Change the status structure 00324 */ 00325 Log2(PCSC_LOG_INFO, "Card Removed From %s", readerName); 00326 /* 00327 * Notify the card has been removed 00328 */ 00329 (void)RFSetReaderEventState(rContext, SCARD_REMOVED); 00330 00331 rContext->readerState->cardAtrLength = 0; 00332 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00333 rContext->readerState->readerState = SCARD_ABSENT; 00334 dwCurrentState = SCARD_ABSENT; 00335 00336 rContext->readerState->eventCounter++; 00337 00338 (void)EHSignalEventToClients(); 00339 } 00340 00341 } 00342 else if (dwStatus & SCARD_PRESENT) 00343 { 00344 if (dwCurrentState == SCARD_ABSENT || 00345 dwCurrentState == SCARD_UNKNOWN) 00346 { 00347 #ifdef DISABLE_AUTO_POWER_ON 00348 rContext->readerState->cardAtrLength = 0; 00349 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00350 rContext->readerState->readerState = SCARD_PRESENT; 00351 rContext->powerState = POWER_STATE_UNPOWERED; 00352 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED"); 00353 readerState = SCARD_PRESENT; 00354 rv = IFD_SUCCESS; 00355 Log1(PCSC_LOG_INFO, "Skip card power on"); 00356 #else 00357 /* 00358 * Power and reset the card 00359 */ 00360 dwAtrLen = sizeof(rContext->readerState->cardAtr); 00361 rv = IFDPowerICC(rContext, IFD_POWER_UP, 00362 rContext->readerState->cardAtr, &dwAtrLen); 00363 rContext->readerState->cardAtrLength = dwAtrLen; 00364 00365 /* the protocol is unset after a power on */ 00366 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00367 00368 if (rv == IFD_SUCCESS) 00369 { 00370 rContext->readerState->readerState = SCARD_PRESENT | SCARD_POWERED | SCARD_NEGOTIABLE; 00371 rContext->powerState = POWER_STATE_POWERED; 00372 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_POWERED"); 00373 } 00374 else 00375 { 00376 rContext->readerState->readerState = SCARD_PRESENT | SCARD_SWALLOWED; 00377 rContext->powerState = POWER_STATE_UNPOWERED; 00378 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED"); 00379 rContext->readerState->cardAtrLength = 0; 00380 } 00381 #endif 00382 00383 dwCurrentState = SCARD_PRESENT; 00384 00385 rContext->readerState->eventCounter++; 00386 00387 Log2(PCSC_LOG_INFO, "Card inserted into %s", readerName); 00388 00389 (void)EHSignalEventToClients(); 00390 00391 if (rv == IFD_SUCCESS) 00392 { 00393 if (rContext->readerState->cardAtrLength > 0) 00394 { 00395 LogXxd(PCSC_LOG_INFO, "Card ATR: ", 00396 rContext->readerState->cardAtr, 00397 rContext->readerState->cardAtrLength); 00398 } 00399 else 00400 Log1(PCSC_LOG_INFO, "Card ATR: (NULL)"); 00401 } 00402 else 00403 Log1(PCSC_LOG_ERROR,"Error powering up card."); 00404 } 00405 } 00406 00407 /* 00408 * Sharing may change w/o an event pass it on 00409 */ 00410 if (readerSharing != rContext->contexts) 00411 { 00412 readerSharing = rContext->contexts; 00413 rContext->readerState->readerSharing = readerSharing; 00414 (void)EHSignalEventToClients(); 00415 } 00416 00417 if (rContext->pthCardEvent) 00418 { 00419 int ret; 00420 int timeout; 00421 00422 #ifndef DISABLE_ON_DEMAND_POWER_ON 00423 if (POWER_STATE_POWERED == rContext->powerState) 00424 /* The card is powered but not yet used */ 00425 timeout = PCSCLITE_POWER_OFF_GRACE_PERIOD; 00426 else 00427 /* The card is already in use or not used at all */ 00428 #endif 00429 timeout = PCSCLITE_STATUS_EVENT_TIMEOUT; 00430 00431 ret = rContext->pthCardEvent(rContext->slot, timeout); 00432 if (IFD_SUCCESS != ret) 00433 (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE); 00434 } 00435 else 00436 (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE); 00437 00438 #ifndef DISABLE_ON_DEMAND_POWER_ON 00439 /* the card is powered but not used */ 00440 (void)pthread_mutex_lock(&rContext->powerState_lock); 00441 if (POWER_STATE_POWERED == rContext->powerState) 00442 { 00443 /* power down */ 00444 IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL); 00445 rContext->powerState = POWER_STATE_UNPOWERED; 00446 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED"); 00447 00448 /* the protocol is unset after a power down */ 00449 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00450 } 00451 00452 /* the card was in use */ 00453 if (POWER_STATE_GRACE_PERIOD == rContext->powerState) 00454 { 00455 /* the next state should be UNPOWERED unless the 00456 * card is used again */ 00457 rContext->powerState = POWER_STATE_POWERED; 00458 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_POWERED"); 00459 } 00460 (void)pthread_mutex_unlock(&rContext->powerState_lock); 00461 #endif 00462 00463 if (rContext->hLockId == 0xFFFF) 00464 { 00465 /* 00466 * Exit and notify the caller 00467 */ 00468 (void)EHSignalEventToClients(); 00469 Log1(PCSC_LOG_INFO, "Die"); 00470 rContext->hLockId = 0; 00471 (void)pthread_exit(NULL); 00472 } 00473 } 00474 } 00475