pcsc-lite 1.6.4
|
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-2010 00007 * Ludovic Rousseau <ludovic.rousseau@free.fr> 00008 * 00009 * $Id: eventhandler.c 5123 2010-08-13 10:09:10Z 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 "ifdhandler.h" 00030 #include "debuglog.h" 00031 #include "readerfactory.h" 00032 #include "eventhandler.h" 00033 #include "dyn_generic.h" 00034 #include "sys_generic.h" 00035 #include "ifdwrapper.h" 00036 #include "prothandler.h" 00037 #include "strlcpycat.h" 00038 #include "utils.h" 00039 #include "winscard_svc.h" 00040 #include "simclist.h" 00041 00042 READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]; 00043 static list_t ClientsWaitingForEvent; 00044 pthread_mutex_t ClientsWaitingForEvent_lock; 00046 static void EHStatusHandlerThread(READER_CONTEXT *); 00047 00048 LONG EHRegisterClientForEvent(int32_t filedes) 00049 { 00050 (void)pthread_mutex_lock(&ClientsWaitingForEvent_lock); 00051 00052 (void)list_append(&ClientsWaitingForEvent, &filedes); 00053 00054 (void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock); 00055 00056 return SCARD_S_SUCCESS; 00057 } /* EHRegisterClientForEvent */ 00058 00063 LONG EHTryToUnregisterClientForEvent(int32_t filedes) 00064 { 00065 LONG rv = SCARD_S_SUCCESS; 00066 int ret; 00067 00068 (void)pthread_mutex_lock(&ClientsWaitingForEvent_lock); 00069 00070 ret = list_delete(&ClientsWaitingForEvent, &filedes); 00071 00072 (void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock); 00073 00074 if (ret < 0) 00075 rv = SCARD_F_INTERNAL_ERROR; 00076 00077 return rv; 00078 } /* EHTryToUnregisterClientForEvent */ 00079 00083 LONG EHUnregisterClientForEvent(int32_t filedes) 00084 { 00085 LONG rv = EHTryToUnregisterClientForEvent(filedes); 00086 00087 if (rv < 0) 00088 Log2(PCSC_LOG_ERROR, "Can't remove client: %d", filedes); 00089 00090 return rv; 00091 } /* EHUnregisterClientForEvent */ 00092 00096 LONG EHSignalEventToClients(void) 00097 { 00098 LONG rv = SCARD_S_SUCCESS; 00099 int32_t filedes; 00100 00101 (void)pthread_mutex_lock(&ClientsWaitingForEvent_lock); 00102 00103 (void)list_iterator_start(&ClientsWaitingForEvent); 00104 while (list_iterator_hasnext(&ClientsWaitingForEvent)) 00105 { 00106 filedes = *(int32_t *)list_iterator_next(&ClientsWaitingForEvent); 00107 rv = MSGSignalClient(filedes, SCARD_S_SUCCESS); 00108 } 00109 (void)list_iterator_stop(&ClientsWaitingForEvent); 00110 00111 (void)list_clear(&ClientsWaitingForEvent); 00112 00113 (void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock); 00114 00115 return rv; 00116 } /* EHSignalEventToClients */ 00117 00118 LONG EHInitializeEventStructures(void) 00119 { 00120 int i; 00121 00122 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00123 { 00124 /* Zero out each value in the struct */ 00125 memset(readerStates[i].readerName, 0, MAX_READERNAME); 00126 memset(readerStates[i].cardAtr, 0, MAX_ATR_SIZE); 00127 readerStates[i].readerID = 0; 00128 readerStates[i].readerState = 0; 00129 readerStates[i].readerSharing = 0; 00130 readerStates[i].cardAtrLength = 0; 00131 readerStates[i].cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00132 } 00133 00134 (void)list_init(&ClientsWaitingForEvent); 00135 00136 /* request to store copies, and provide the metric function */ 00137 (void)list_attributes_copy(&ClientsWaitingForEvent, list_meter_int32_t, 1); 00138 00139 /* setting the comparator, so the list can sort, find the min, max etc */ 00140 (void)list_attributes_comparator(&ClientsWaitingForEvent, list_comparator_int32_t); 00141 00142 (void)pthread_mutex_init(&ClientsWaitingForEvent_lock, NULL); 00143 00144 return SCARD_S_SUCCESS; 00145 } 00146 00147 LONG EHDestroyEventHandler(READER_CONTEXT * rContext) 00148 { 00149 int rv; 00150 DWORD dwGetSize; 00151 UCHAR ucGetData[1]; 00152 00153 if (NULL == rContext->readerState) 00154 { 00155 Log1(PCSC_LOG_ERROR, "Thread never started (reader init failed?)"); 00156 return SCARD_S_SUCCESS; 00157 } 00158 00159 if ('\0' == rContext->readerState->readerName[0]) 00160 { 00161 Log1(PCSC_LOG_INFO, "Thread already stomped."); 00162 return SCARD_S_SUCCESS; 00163 } 00164 00165 /* 00166 * Set the thread to 0 to exit thread 00167 */ 00168 rContext->hLockId = 0xFFFF; 00169 00170 Log1(PCSC_LOG_INFO, "Stomping thread."); 00171 00172 /* kill the "polling" thread */ 00173 dwGetSize = sizeof(ucGetData); 00174 rv = IFDGetCapabilities(rContext, TAG_IFD_POLLING_THREAD_KILLABLE, 00175 &dwGetSize, ucGetData); 00176 00177 #ifdef HAVE_PTHREAD_CANCEL 00178 if ((IFD_SUCCESS == rv) && (1 == dwGetSize) && ucGetData[0]) 00179 { 00180 Log1(PCSC_LOG_INFO, "Killing polling thread"); 00181 (void)pthread_cancel(rContext->pthThread); 00182 } 00183 else 00184 #endif 00185 { 00186 /* ask to stop the "polling" thread */ 00187 RESPONSECODE (*fct)(DWORD) = NULL; 00188 00189 dwGetSize = sizeof(fct); 00190 rv = IFDGetCapabilities(rContext, TAG_IFD_STOP_POLLING_THREAD, 00191 &dwGetSize, (PUCHAR)&fct); 00192 00193 if ((IFD_SUCCESS == rv) && (dwGetSize == sizeof(fct))) 00194 { 00195 Log1(PCSC_LOG_INFO, "Request stoping of polling thread"); 00196 fct(rContext->slot); 00197 } 00198 else 00199 Log1(PCSC_LOG_INFO, "Waiting polling thread"); 00200 } 00201 00202 /* wait for the thread to finish */ 00203 rv = pthread_join(rContext->pthThread, NULL); 00204 if (rv) 00205 Log2(PCSC_LOG_ERROR, "pthread_join failed: %s", strerror(rv)); 00206 00207 /* 00208 * Zero out the public status struct to allow it to be recycled and 00209 * used again 00210 */ 00211 memset(rContext->readerState->readerName, 0, 00212 sizeof(rContext->readerState->readerName)); 00213 memset(rContext->readerState->cardAtr, 0, 00214 sizeof(rContext->readerState->cardAtr)); 00215 rContext->readerState->readerID = 0; 00216 rContext->readerState->readerState = 0; 00217 rContext->readerState->readerSharing = 0; 00218 rContext->readerState->cardAtrLength = 0; 00219 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00220 00221 /* Zero the thread */ 00222 rContext->pthThread = 0; 00223 00224 Log1(PCSC_LOG_INFO, "Thread stomped."); 00225 00226 return SCARD_S_SUCCESS; 00227 } 00228 00229 LONG EHSpawnEventHandler(READER_CONTEXT * rContext, 00230 RESPONSECODE (*card_event)(DWORD)) 00231 { 00232 LONG rv; 00233 DWORD dwStatus = 0; 00234 int i; 00235 UCHAR ucAtr[MAX_ATR_SIZE]; 00236 DWORD dwAtrLen = 0; 00237 00238 rv = IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen); 00239 if (rv != SCARD_S_SUCCESS) 00240 { 00241 Log2(PCSC_LOG_ERROR, "Initial Check Failed on %s", rContext->lpcReader); 00242 return SCARD_F_UNKNOWN_ERROR; 00243 } 00244 00245 /* 00246 * Find an empty reader slot and insert the new reader 00247 */ 00248 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00249 { 00250 if (readerStates[i].readerID == 0) 00251 break; 00252 } 00253 00254 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 00255 return SCARD_F_INTERNAL_ERROR; 00256 00257 /* 00258 * Set all the attributes to this reader 00259 */ 00260 rContext->readerState = &readerStates[i]; 00261 (void)strlcpy(rContext->readerState->readerName, rContext->lpcReader, 00262 sizeof(rContext->readerState->readerName)); 00263 memcpy(rContext->readerState->cardAtr, ucAtr, dwAtrLen); 00264 rContext->readerState->readerID = i + 100; 00265 rContext->readerState->readerState = dwStatus; 00266 rContext->readerState->readerSharing = rContext->contexts; 00267 rContext->readerState->cardAtrLength = dwAtrLen; 00268 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00269 00270 rContext->pthCardEvent = card_event; 00271 rv = ThreadCreate(&rContext->pthThread, 0, 00272 (PCSCLITE_THREAD_FUNCTION( ))EHStatusHandlerThread, (LPVOID) rContext); 00273 if (rv) 00274 { 00275 Log2(PCSC_LOG_ERROR, "ThreadCreate failed: %s", strerror(rv)); 00276 return SCARD_E_NO_MEMORY; 00277 } 00278 else 00279 return SCARD_S_SUCCESS; 00280 } 00281 00282 static void incrementEventCounter(struct pubReaderStatesList *readerState) 00283 { 00284 int counter; 00285 00286 counter = (readerState -> readerState >> 16) & 0xFFFF; 00287 counter++; 00288 readerState -> readerState = (readerState -> readerState & 0xFFFF) 00289 + (counter << 16); 00290 } 00291 00292 static void EHStatusHandlerThread(READER_CONTEXT * rContext) 00293 { 00294 LONG rv; 00295 LPCSTR lpcReader; 00296 DWORD dwStatus; 00297 int32_t readerSharing; 00298 DWORD dwCurrentState; 00299 DWORD dwAtrLen; 00300 00301 /* 00302 * Zero out everything 00303 */ 00304 dwStatus = 0; 00305 readerSharing = 0; 00306 dwCurrentState = 0; 00307 00308 lpcReader = rContext->lpcReader; 00309 00310 dwAtrLen = rContext->readerState->cardAtrLength; 00311 rv = IFDStatusICC(rContext, &dwStatus, rContext->readerState->cardAtr, 00312 &dwAtrLen); 00313 rContext->readerState->cardAtrLength = dwAtrLen; 00314 00315 if (dwStatus & SCARD_PRESENT) 00316 { 00317 dwAtrLen = MAX_ATR_SIZE; 00318 rv = IFDPowerICC(rContext, IFD_POWER_UP, 00319 rContext->readerState->cardAtr, 00320 &dwAtrLen); 00321 rContext->readerState->cardAtrLength = dwAtrLen; 00322 00323 /* the protocol is unset after a power on */ 00324 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00325 00326 if (rv == IFD_SUCCESS) 00327 { 00328 dwStatus |= SCARD_PRESENT; 00329 dwStatus &= ~SCARD_ABSENT; 00330 dwStatus |= SCARD_POWERED; 00331 dwStatus |= SCARD_NEGOTIABLE; 00332 dwStatus &= ~SCARD_SPECIFIC; 00333 dwStatus &= ~SCARD_SWALLOWED; 00334 dwStatus &= ~SCARD_UNKNOWN; 00335 00336 if (rContext->readerState->cardAtrLength > 0) 00337 { 00338 LogXxd(PCSC_LOG_INFO, "Card ATR: ", 00339 rContext->readerState->cardAtr, 00340 rContext->readerState->cardAtrLength); 00341 } 00342 else 00343 Log1(PCSC_LOG_INFO, "Card ATR: (NULL)"); 00344 } 00345 else 00346 { 00347 dwStatus |= SCARD_PRESENT; 00348 dwStatus &= ~SCARD_ABSENT; 00349 dwStatus |= SCARD_SWALLOWED; 00350 dwStatus &= ~SCARD_POWERED; 00351 dwStatus &= ~SCARD_NEGOTIABLE; 00352 dwStatus &= ~SCARD_SPECIFIC; 00353 dwStatus &= ~SCARD_UNKNOWN; 00354 Log3(PCSC_LOG_ERROR, "Error powering up card: %d 0x%04X", rv, rv); 00355 } 00356 00357 dwCurrentState = SCARD_PRESENT; 00358 } 00359 else 00360 { 00361 dwStatus |= SCARD_ABSENT; 00362 dwStatus &= ~SCARD_PRESENT; 00363 dwStatus &= ~SCARD_POWERED; 00364 dwStatus &= ~SCARD_NEGOTIABLE; 00365 dwStatus &= ~SCARD_SPECIFIC; 00366 dwStatus &= ~SCARD_SWALLOWED; 00367 dwStatus &= ~SCARD_UNKNOWN; 00368 rContext->readerState->cardAtrLength = 0; 00369 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00370 00371 dwCurrentState = SCARD_ABSENT; 00372 } 00373 00374 /* 00375 * Set all the public attributes to this reader 00376 */ 00377 rContext->readerState->readerState = dwStatus; 00378 rContext->readerState->readerSharing = readerSharing = 00379 rContext->contexts; 00380 00381 (void)EHSignalEventToClients(); 00382 00383 while (1) 00384 { 00385 dwStatus = 0; 00386 00387 dwAtrLen = rContext->readerState->cardAtrLength; 00388 rv = IFDStatusICC(rContext, &dwStatus, 00389 rContext->readerState->cardAtr, 00390 &dwAtrLen); 00391 rContext->readerState->cardAtrLength = dwAtrLen; 00392 00393 if (rv != SCARD_S_SUCCESS) 00394 { 00395 Log2(PCSC_LOG_ERROR, "Error communicating to: %s", lpcReader); 00396 00397 /* 00398 * Set error status on this reader while errors occur 00399 */ 00400 rContext->readerState->readerState &= ~SCARD_ABSENT; 00401 rContext->readerState->readerState &= ~SCARD_PRESENT; 00402 rContext->readerState->readerState &= ~SCARD_POWERED; 00403 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE; 00404 rContext->readerState->readerState &= ~SCARD_SPECIFIC; 00405 rContext->readerState->readerState &= ~SCARD_SWALLOWED; 00406 rContext->readerState->readerState |= SCARD_UNKNOWN; 00407 rContext->readerState->cardAtrLength = 0; 00408 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00409 00410 dwCurrentState = SCARD_UNKNOWN; 00411 00412 (void)EHSignalEventToClients(); 00413 } 00414 00415 if (dwStatus & SCARD_ABSENT) 00416 { 00417 if (dwCurrentState == SCARD_PRESENT || 00418 dwCurrentState == SCARD_UNKNOWN) 00419 { 00420 /* 00421 * Change the status structure 00422 */ 00423 Log2(PCSC_LOG_INFO, "Card Removed From %s", lpcReader); 00424 /* 00425 * Notify the card has been removed 00426 */ 00427 (void)RFSetReaderEventState(rContext, SCARD_REMOVED); 00428 00429 rContext->readerState->cardAtrLength = 0; 00430 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00431 rContext->readerState->readerState |= SCARD_ABSENT; 00432 rContext->readerState->readerState &= ~SCARD_UNKNOWN; 00433 rContext->readerState->readerState &= ~SCARD_PRESENT; 00434 rContext->readerState->readerState &= ~SCARD_POWERED; 00435 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE; 00436 rContext->readerState->readerState &= ~SCARD_SWALLOWED; 00437 rContext->readerState->readerState &= ~SCARD_SPECIFIC; 00438 dwCurrentState = SCARD_ABSENT; 00439 00440 incrementEventCounter(rContext->readerState); 00441 00442 (void)EHSignalEventToClients(); 00443 } 00444 00445 } 00446 else if (dwStatus & SCARD_PRESENT) 00447 { 00448 if (dwCurrentState == SCARD_ABSENT || 00449 dwCurrentState == SCARD_UNKNOWN) 00450 { 00451 /* 00452 * Power and reset the card 00453 */ 00454 dwAtrLen = MAX_ATR_SIZE; 00455 rv = IFDPowerICC(rContext, IFD_POWER_UP, 00456 rContext->readerState->cardAtr, 00457 &dwAtrLen); 00458 rContext->readerState->cardAtrLength = dwAtrLen; 00459 00460 /* the protocol is unset after a power on */ 00461 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00462 00463 if (rv == IFD_SUCCESS) 00464 { 00465 rContext->readerState->readerState |= SCARD_PRESENT; 00466 rContext->readerState->readerState &= ~SCARD_ABSENT; 00467 rContext->readerState->readerState |= SCARD_POWERED; 00468 rContext->readerState->readerState |= SCARD_NEGOTIABLE; 00469 rContext->readerState->readerState &= ~SCARD_SPECIFIC; 00470 rContext->readerState->readerState &= ~SCARD_UNKNOWN; 00471 rContext->readerState->readerState &= ~SCARD_SWALLOWED; 00472 } 00473 else 00474 { 00475 rContext->readerState->readerState |= SCARD_PRESENT; 00476 rContext->readerState->readerState &= ~SCARD_ABSENT; 00477 rContext->readerState->readerState |= SCARD_SWALLOWED; 00478 rContext->readerState->readerState &= ~SCARD_POWERED; 00479 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE; 00480 rContext->readerState->readerState &= ~SCARD_SPECIFIC; 00481 rContext->readerState->readerState &= ~SCARD_UNKNOWN; 00482 rContext->readerState->cardAtrLength = 0; 00483 } 00484 00485 dwCurrentState = SCARD_PRESENT; 00486 00487 incrementEventCounter(rContext->readerState); 00488 00489 Log2(PCSC_LOG_INFO, "Card inserted into %s", lpcReader); 00490 00491 (void)EHSignalEventToClients(); 00492 00493 if (rv == IFD_SUCCESS) 00494 { 00495 if (rContext->readerState->cardAtrLength > 0) 00496 { 00497 LogXxd(PCSC_LOG_INFO, "Card ATR: ", 00498 rContext->readerState->cardAtr, 00499 rContext->readerState->cardAtrLength); 00500 } 00501 else 00502 Log1(PCSC_LOG_INFO, "Card ATR: (NULL)"); 00503 } 00504 else 00505 Log1(PCSC_LOG_ERROR,"Error powering up card."); 00506 } 00507 } 00508 00509 /* 00510 * Sharing may change w/o an event pass it on 00511 */ 00512 if (readerSharing != rContext->contexts) 00513 { 00514 readerSharing = rContext->contexts; 00515 rContext->readerState->readerSharing = readerSharing; 00516 (void)EHSignalEventToClients(); 00517 } 00518 00519 if (rContext->pthCardEvent) 00520 { 00521 int ret; 00522 00523 ret = rContext->pthCardEvent(rContext->slot); 00524 if (IFD_NO_SUCH_DEVICE == ret) 00525 (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE); 00526 } 00527 else 00528 (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE); 00529 00530 if (rContext->hLockId == 0xFFFF) 00531 { 00532 /* 00533 * Exit and notify the caller 00534 */ 00535 (void)EHSignalEventToClients(); 00536 Log1(PCSC_LOG_INFO, "Die"); 00537 rContext->hLockId = 0; 00538 (void)pthread_exit(NULL); 00539 } 00540 } 00541 } 00542