pcsc-lite
1.8.2
|
00001 /* 00002 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 00003 * 00004 * Copyright (C) 1999-2004 00005 * David Corcoran <corcoran@linuxnet.com> 00006 * Copyright (C) 2003-2004 00007 * Damien Sauveron <damien.sauveron@labri.fr> 00008 * Copyright (C) 2002-2011 00009 * Ludovic Rousseau <ludovic.rousseau@free.fr> 00010 * Copyright (C) 2009 00011 * Jean-Luc Giraud <jlgiraud@googlemail.com> 00012 * 00013 * $Id: readerfactory.c 6129 2011-12-05 13:57:11Z rousseau $ 00014 */ 00015 00021 #include "config.h" 00022 #include <stdio.h> 00023 #include <stdlib.h> 00024 #include <string.h> 00025 #include <unistd.h> 00026 #include <sys/types.h> 00027 #include <sys/stat.h> 00028 #include <errno.h> 00029 #include <fcntl.h> 00030 #include <pthread.h> 00031 00032 #include "misc.h" 00033 #include "pcscd.h" 00034 #include "debuglog.h" 00035 #include "readerfactory.h" 00036 #include "dyn_generic.h" 00037 #include "sys_generic.h" 00038 #include "eventhandler.h" 00039 #include "ifdwrapper.h" 00040 #include "hotplug.h" 00041 #include "strlcpycat.h" 00042 #include "configfile.h" 00043 #include "utils.h" 00044 00045 #ifndef TRUE 00046 #define TRUE 1 00047 #define FALSE 0 00048 #endif 00049 00050 static READER_CONTEXT * sReadersContexts[PCSCLITE_MAX_READERS_CONTEXTS]; 00051 READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]; 00052 static int maxReaderHandles = PCSC_MAX_READER_HANDLES; 00053 static DWORD dwNumReadersContexts = 0; 00054 #ifdef USE_SERIAL 00055 static char *ConfigFile = NULL; 00056 static int ConfigFileCRC = 0; 00057 #endif 00058 static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER; 00059 00060 #define IDENTITY_SHIFT 16 00061 00062 static int RDR_CLIHANDLES_seeker(const void *el, const void *key) 00063 { 00064 const RDR_CLIHANDLES *rdrCliHandles = el; 00065 00066 if ((el == NULL) || (key == NULL)) 00067 { 00068 Log3(PCSC_LOG_CRITICAL, 00069 "RDR_CLIHANDLES_seeker called with NULL pointer: el=%p, key=%p", 00070 el, key); 00071 return 0; 00072 } 00073 00074 if (rdrCliHandles->hCard == *(SCARDHANDLE *)key) 00075 return 1; 00076 00077 return 0; 00078 } 00079 00080 00081 LONG RFAllocateReaderSpace(unsigned int customMaxReaderHandles) 00082 { 00083 int i; /* Counter */ 00084 00085 if (customMaxReaderHandles != 0) 00086 maxReaderHandles = customMaxReaderHandles; 00087 00088 /* Allocate each reader structure */ 00089 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00090 { 00091 sReadersContexts[i] = malloc(sizeof(READER_CONTEXT)); 00092 sReadersContexts[i]->vHandle = NULL; 00093 00094 /* Zero out each value in the struct */ 00095 memset(readerStates[i].readerName, 0, MAX_READERNAME); 00096 memset(readerStates[i].cardAtr, 0, MAX_ATR_SIZE); 00097 readerStates[i].readerState = 0; 00098 readerStates[i].readerSharing = 0; 00099 readerStates[i].cardAtrLength = READER_NOT_INITIALIZED; 00100 readerStates[i].cardProtocol = SCARD_PROTOCOL_UNDEFINED; 00101 00102 sReadersContexts[i]->readerState = &readerStates[i]; 00103 } 00104 00105 /* Create public event structures */ 00106 return EHInitializeEventStructures(); 00107 } 00108 00109 LONG RFAddReader(const char *readerName, int port, const char *library, 00110 const char *device) 00111 { 00112 DWORD dwContext = 0, dwGetSize; 00113 UCHAR ucGetData[1], ucThread[1]; 00114 LONG rv, parentNode; 00115 int i, j; 00116 int lrv = 0; 00117 00118 if ((readerName == NULL) || (library == NULL) || (device == NULL)) 00119 return SCARD_E_INVALID_VALUE; 00120 00121 /* Reader name too long? also count " 00 00"*/ 00122 if (strlen(readerName) > MAX_READERNAME - sizeof(" 00 00")) 00123 { 00124 Log3(PCSC_LOG_ERROR, 00125 "Reader name too long: %zd chars instead of max %zd", 00126 strlen(readerName), MAX_READERNAME - sizeof(" 00 00")); 00127 return SCARD_E_INVALID_VALUE; 00128 } 00129 00130 /* Same name, same port - duplicate reader cannot be used */ 00131 if (dwNumReadersContexts != 0) 00132 { 00133 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00134 { 00135 if (sReadersContexts[i]->vHandle != 0) 00136 { 00137 char lpcStripReader[MAX_READERNAME]; 00138 int tmplen; 00139 00140 /* get the reader name without the reader and slot numbers */ 00141 strncpy(lpcStripReader, 00142 sReadersContexts[i]->readerState->readerName, 00143 sizeof(lpcStripReader)); 00144 tmplen = strlen(lpcStripReader); 00145 lpcStripReader[tmplen - 6] = 0; 00146 00147 if ((strcmp(readerName, lpcStripReader) == 0) && 00148 (port == sReadersContexts[i]->port)) 00149 { 00150 Log1(PCSC_LOG_ERROR, "Duplicate reader found."); 00151 return SCARD_E_DUPLICATE_READER; 00152 } 00153 } 00154 } 00155 } 00156 00157 /* We must find an empty slot to put the reader structure */ 00158 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00159 { 00160 if (sReadersContexts[i]->vHandle == 0) 00161 { 00162 dwContext = i; 00163 break; 00164 } 00165 } 00166 00167 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 00168 { 00169 /* No more spots left return */ 00170 return SCARD_E_NO_MEMORY; 00171 } 00172 00173 /* Check and set the readername to see if it must be enumerated */ 00174 parentNode = RFSetReaderName(sReadersContexts[dwContext], readerName, 00175 library, port); 00176 if (parentNode < -1) 00177 return SCARD_E_NO_MEMORY; 00178 00179 sReadersContexts[dwContext]->library = strdup(library); 00180 sReadersContexts[dwContext]->device = strdup(device); 00181 sReadersContexts[dwContext]->version = 0; 00182 sReadersContexts[dwContext]->port = port; 00183 sReadersContexts[dwContext]->mMutex = NULL; 00184 sReadersContexts[dwContext]->contexts = 0; 00185 sReadersContexts[dwContext]->pthThread = 0; 00186 sReadersContexts[dwContext]->hLockId = 0; 00187 sReadersContexts[dwContext]->LockCount = 0; 00188 sReadersContexts[dwContext]->vHandle = NULL; 00189 sReadersContexts[dwContext]->pFeeds = NULL; 00190 sReadersContexts[dwContext]->pMutex = NULL; 00191 sReadersContexts[dwContext]->pthCardEvent = NULL; 00192 sReadersContexts[dwContext]->dwIdentity = 00193 (dwContext + 1) << IDENTITY_SHIFT; 00194 00195 lrv = list_init(&sReadersContexts[dwContext]->handlesList); 00196 if (lrv < 0) 00197 { 00198 Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv); 00199 return SCARD_E_NO_MEMORY; 00200 } 00201 00202 lrv = list_attributes_seeker(&sReadersContexts[dwContext]->handlesList, 00203 RDR_CLIHANDLES_seeker); 00204 if (lrv < 0) 00205 { 00206 Log2(PCSC_LOG_CRITICAL, 00207 "list_attributes_seeker failed with return value: %d", lrv); 00208 return SCARD_E_NO_MEMORY; 00209 } 00210 00211 (void)pthread_mutex_init(&sReadersContexts[dwContext]->handlesList_lock, 00212 NULL); 00213 00214 (void)pthread_mutex_init(&sReadersContexts[dwContext]->powerState_lock, 00215 NULL); 00216 sReadersContexts[dwContext]->powerState = POWER_STATE_UNPOWERED; 00217 00218 /* If a clone to this reader exists take some values from that clone */ 00219 if (parentNode >= 0 && parentNode < PCSCLITE_MAX_READERS_CONTEXTS) 00220 { 00221 sReadersContexts[dwContext]->pFeeds = 00222 sReadersContexts[parentNode]->pFeeds; 00223 *(sReadersContexts[dwContext])->pFeeds += 1; 00224 sReadersContexts[dwContext]->vHandle = 00225 sReadersContexts[parentNode]->vHandle; 00226 sReadersContexts[dwContext]->mMutex = 00227 sReadersContexts[parentNode]->mMutex; 00228 sReadersContexts[dwContext]->pMutex = 00229 sReadersContexts[parentNode]->pMutex; 00230 00231 /* Call on the parent driver to see if it is thread safe */ 00232 dwGetSize = sizeof(ucThread); 00233 rv = IFDGetCapabilities(sReadersContexts[parentNode], 00234 TAG_IFD_THREAD_SAFE, &dwGetSize, ucThread); 00235 00236 if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1) 00237 { 00238 Log1(PCSC_LOG_INFO, "Driver is thread safe"); 00239 sReadersContexts[dwContext]->mMutex = NULL; 00240 sReadersContexts[dwContext]->pMutex = NULL; 00241 } 00242 else 00243 *(sReadersContexts[dwContext])->pMutex += 1; 00244 } 00245 00246 if (sReadersContexts[dwContext]->pFeeds == NULL) 00247 { 00248 sReadersContexts[dwContext]->pFeeds = malloc(sizeof(int)); 00249 00250 /* Initialize pFeeds to 1, otherwise multiple 00251 cloned readers will cause pcscd to crash when 00252 RFUnloadReader unloads the driver library 00253 and there are still devices attached using it --mikeg*/ 00254 *(sReadersContexts[dwContext])->pFeeds = 1; 00255 } 00256 00257 if (sReadersContexts[dwContext]->mMutex == 0) 00258 { 00259 sReadersContexts[dwContext]->mMutex = 00260 malloc(sizeof(pthread_mutex_t)); 00261 (void)pthread_mutex_init(sReadersContexts[dwContext]->mMutex, NULL); 00262 } 00263 00264 if (sReadersContexts[dwContext]->pMutex == NULL) 00265 { 00266 sReadersContexts[dwContext]->pMutex = malloc(sizeof(int)); 00267 *(sReadersContexts[dwContext])->pMutex = 1; 00268 } 00269 00270 dwNumReadersContexts += 1; 00271 00272 rv = RFInitializeReader(sReadersContexts[dwContext]); 00273 if (rv != SCARD_S_SUCCESS) 00274 { 00275 /* Cannot connect to reader. Exit gracefully */ 00276 Log2(PCSC_LOG_ERROR, "%s init failed.", readerName); 00277 (void)RFRemoveReader(readerName, port); 00278 return rv; 00279 } 00280 00281 /* asynchronous card movement? */ 00282 { 00283 RESPONSECODE (*fct)(DWORD, int) = NULL; 00284 00285 dwGetSize = sizeof(fct); 00286 00287 rv = IFDGetCapabilities(sReadersContexts[dwContext], 00288 TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct); 00289 if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct))) 00290 { 00291 Log1(PCSC_LOG_INFO, "Using the pcscd polling thread"); 00292 } 00293 else 00294 { 00295 sReadersContexts[dwContext]->pthCardEvent = fct; 00296 Log1(PCSC_LOG_INFO, "Using the reader polling thread"); 00297 } 00298 00299 rv = EHSpawnEventHandler(sReadersContexts[dwContext]); 00300 if (rv != SCARD_S_SUCCESS) 00301 { 00302 Log2(PCSC_LOG_ERROR, "%s init failed.", readerName); 00303 (void)RFRemoveReader(readerName, port); 00304 return rv; 00305 } 00306 } 00307 00308 /* Call on the driver to see if there are multiple slots */ 00309 dwGetSize = sizeof(ucGetData); 00310 rv = IFDGetCapabilities((sReadersContexts[dwContext]), 00311 TAG_IFD_SLOTS_NUMBER, &dwGetSize, ucGetData); 00312 00313 if (rv != IFD_SUCCESS || dwGetSize != 1 || ucGetData[0] == 0) 00314 /* Reader does not have this defined. Must be a single slot 00315 * reader so we can just return SCARD_S_SUCCESS. */ 00316 return SCARD_S_SUCCESS; 00317 00318 if (rv == IFD_SUCCESS && dwGetSize == 1 && ucGetData[0] == 1) 00319 /* Reader has this defined and it only has one slot */ 00320 return SCARD_S_SUCCESS; 00321 00322 /* 00323 * Check the number of slots and create a different 00324 * structure for each one accordingly 00325 */ 00326 00327 /* Initialize the rest of the slots */ 00328 for (j = 1; j < ucGetData[0]; j++) 00329 { 00330 char *tmpReader = NULL; 00331 DWORD dwContextB = 0; 00332 RESPONSECODE (*fct)(DWORD, int) = NULL; 00333 00334 /* We must find an empty spot to put the reader structure */ 00335 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00336 { 00337 if (sReadersContexts[i]->vHandle == 0) 00338 { 00339 dwContextB = i; 00340 break; 00341 } 00342 } 00343 00344 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 00345 { 00346 /* No more slot left return */ 00347 RFRemoveReader(readerName, port); 00348 return SCARD_E_NO_MEMORY; 00349 } 00350 00351 /* Copy the previous reader name and increment the slot number */ 00352 tmpReader = sReadersContexts[dwContextB]->readerState->readerName; 00353 (void)strlcpy(tmpReader, 00354 sReadersContexts[dwContext]->readerState->readerName, 00355 sizeof(sReadersContexts[dwContextB]->readerState->readerName)); 00356 snprintf(tmpReader + strlen(tmpReader) - 2, 3, "%02X", j); 00357 00358 sReadersContexts[dwContextB]->library = 00359 sReadersContexts[dwContext]->library; 00360 sReadersContexts[dwContextB]->device = 00361 sReadersContexts[dwContext]->device; 00362 sReadersContexts[dwContextB]->version = 00363 sReadersContexts[dwContext]->version; 00364 sReadersContexts[dwContextB]->port = 00365 sReadersContexts[dwContext]->port; 00366 sReadersContexts[dwContextB]->vHandle = 00367 sReadersContexts[dwContext]->vHandle; 00368 sReadersContexts[dwContextB]->mMutex = 00369 sReadersContexts[dwContext]->mMutex; 00370 sReadersContexts[dwContextB]->pMutex = 00371 sReadersContexts[dwContext]->pMutex; 00372 sReadersContexts[dwContextB]->slot = 00373 sReadersContexts[dwContext]->slot + j; 00374 sReadersContexts[dwContextB]->pthCardEvent = NULL; 00375 00376 /* 00377 * Added by Dave - slots did not have a pFeeds 00378 * parameter so it was by luck they were working 00379 */ 00380 sReadersContexts[dwContextB]->pFeeds = 00381 sReadersContexts[dwContext]->pFeeds; 00382 00383 /* Added by Dave for multiple slots */ 00384 *(sReadersContexts[dwContextB])->pFeeds += 1; 00385 00386 sReadersContexts[dwContextB]->contexts = 0; 00387 sReadersContexts[dwContextB]->hLockId = 0; 00388 sReadersContexts[dwContextB]->LockCount = 0; 00389 sReadersContexts[dwContextB]->dwIdentity = 00390 (dwContextB + 1) << IDENTITY_SHIFT; 00391 00392 lrv = list_init(&sReadersContexts[dwContextB]->handlesList); 00393 if (lrv < 0) 00394 { 00395 Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv); 00396 return SCARD_E_NO_MEMORY; 00397 } 00398 00399 lrv = list_attributes_seeker(&sReadersContexts[dwContextB]->handlesList, 00400 RDR_CLIHANDLES_seeker); 00401 if (lrv < 0) 00402 { 00403 Log2(PCSC_LOG_CRITICAL, 00404 "list_attributes_seeker failed with return value: %d", lrv); 00405 return SCARD_E_NO_MEMORY; 00406 } 00407 00408 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->handlesList_lock, NULL); 00409 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->powerState_lock, 00410 NULL); 00411 sReadersContexts[dwContextB]->powerState = POWER_STATE_UNPOWERED; 00412 00413 /* Call on the parent driver to see if the slots are thread safe */ 00414 dwGetSize = sizeof(ucThread); 00415 rv = IFDGetCapabilities((sReadersContexts[dwContext]), 00416 TAG_IFD_SLOT_THREAD_SAFE, &dwGetSize, ucThread); 00417 00418 if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1) 00419 { 00420 sReadersContexts[dwContextB]->mMutex = 00421 malloc(sizeof(pthread_mutex_t)); 00422 (void)pthread_mutex_init(sReadersContexts[dwContextB]->mMutex, 00423 NULL); 00424 00425 sReadersContexts[dwContextB]->pMutex = malloc(sizeof(int)); 00426 *(sReadersContexts[dwContextB])->pMutex = 1; 00427 } 00428 else 00429 *(sReadersContexts[dwContextB])->pMutex += 1; 00430 00431 dwNumReadersContexts += 1; 00432 00433 rv = RFInitializeReader(sReadersContexts[dwContextB]); 00434 if (rv != SCARD_S_SUCCESS) 00435 { 00436 /* Cannot connect to slot. Exit gracefully */ 00437 (void)RFRemoveReader(readerName, port); 00438 return rv; 00439 } 00440 00441 /* asynchronous card movement? */ 00442 dwGetSize = sizeof(fct); 00443 00444 rv = IFDGetCapabilities((sReadersContexts[dwContextB]), 00445 TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct); 00446 if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct))) 00447 { 00448 Log1(PCSC_LOG_INFO, "Using the pcscd polling thread"); 00449 } 00450 else 00451 { 00452 sReadersContexts[dwContextB]->pthCardEvent = fct; 00453 Log1(PCSC_LOG_INFO, "Using the reader polling thread"); 00454 } 00455 00456 rv = EHSpawnEventHandler(sReadersContexts[dwContextB]); 00457 if (rv != SCARD_S_SUCCESS) 00458 { 00459 Log2(PCSC_LOG_ERROR, "%s init failed.", readerName); 00460 (void)RFRemoveReader(readerName, port); 00461 return rv; 00462 } 00463 } 00464 00465 return SCARD_S_SUCCESS; 00466 } 00467 00468 LONG RFRemoveReader(const char *readerName, int port) 00469 { 00470 LONG rv; 00471 READER_CONTEXT * sContext; 00472 00473 if (readerName == NULL) 00474 return SCARD_E_INVALID_VALUE; 00475 00476 while (SCARD_S_SUCCESS == 00477 RFReaderInfoNamePort(port, readerName, &sContext)) 00478 { 00479 /* Try to destroy the thread */ 00480 if (sContext -> pthThread) 00481 (void)EHDestroyEventHandler(sContext); 00482 00483 if ((NULL == sContext->pMutex) || (NULL == sContext->pFeeds)) 00484 { 00485 Log1(PCSC_LOG_ERROR, 00486 "Trying to remove an already removed driver"); 00487 return SCARD_E_INVALID_VALUE; 00488 } 00489 00490 rv = RFUnInitializeReader(sContext); 00491 if (rv != SCARD_S_SUCCESS) 00492 return rv; 00493 00494 *sContext->pMutex -= 1; 00495 00496 /* free shared resources when the last slot is closed */ 00497 if (0 == *sContext->pMutex) 00498 { 00499 (void)pthread_mutex_destroy(sContext->mMutex); 00500 free(sContext->mMutex); 00501 sContext->mMutex = NULL; 00502 free(sContext->library); 00503 free(sContext->device); 00504 free(sContext->pMutex); 00505 sContext->pMutex = NULL; 00506 } 00507 00508 *sContext->pFeeds -= 1; 00509 00510 /* Added by Dave to free the pFeeds variable */ 00511 if (*sContext->pFeeds == 0) 00512 { 00513 free(sContext->pFeeds); 00514 sContext->pFeeds = NULL; 00515 } 00516 00517 (void)pthread_mutex_destroy(&sContext->powerState_lock); 00518 sContext->version = 0; 00519 sContext->port = 0; 00520 sContext->contexts = 0; 00521 sContext->slot = 0; 00522 sContext->hLockId = 0; 00523 sContext->LockCount = 0; 00524 sContext->vHandle = NULL; 00525 sContext->dwIdentity = 0; 00526 00527 (void)pthread_mutex_lock(&sContext->handlesList_lock); 00528 while (list_size(&(sContext->handlesList)) != 0) 00529 { 00530 int lrv; 00531 RDR_CLIHANDLES *currentHandle; 00532 00533 currentHandle = list_get_at(&(sContext->handlesList), 0); 00534 lrv = list_delete_at(&(sContext->handlesList), 0); 00535 if (lrv < 0) 00536 Log2(PCSC_LOG_CRITICAL, 00537 "list_delete_at failed with return value: %d", lrv); 00538 00539 free(currentHandle); 00540 } 00541 (void)pthread_mutex_unlock(&sContext->handlesList_lock); 00542 (void)pthread_mutex_destroy(&sContext->handlesList_lock); 00543 list_destroy(&(sContext->handlesList)); 00544 dwNumReadersContexts -= 1; 00545 00546 /* signal an event to clients */ 00547 (void)EHSignalEventToClients(); 00548 } 00549 00550 return SCARD_S_SUCCESS; 00551 } 00552 00553 LONG RFSetReaderName(READER_CONTEXT * rContext, const char *readerName, 00554 const char *libraryName, int port) 00555 { 00556 LONG parent = -1; /* reader number of the parent of the clone */ 00557 DWORD valueLength; 00558 int currentDigit = -1; 00559 int supportedChannels = 0; 00560 int usedDigits[PCSCLITE_MAX_READERS_CONTEXTS]; 00561 int i; 00562 00563 /* Clear the list */ 00564 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00565 usedDigits[i] = FALSE; 00566 00567 if (dwNumReadersContexts != 0) 00568 { 00569 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00570 { 00571 if (sReadersContexts[i]->vHandle != 0) 00572 { 00573 if (strcmp(sReadersContexts[i]->library, libraryName) == 0) 00574 { 00575 UCHAR tagValue[1]; 00576 LONG ret; 00577 00578 /* Ask the driver if it supports multiple channels */ 00579 valueLength = sizeof(tagValue); 00580 ret = IFDGetCapabilities(sReadersContexts[i], 00581 TAG_IFD_SIMULTANEOUS_ACCESS, 00582 &valueLength, tagValue); 00583 00584 if ((ret == IFD_SUCCESS) && (valueLength == 1) && 00585 (tagValue[0] > 1)) 00586 { 00587 supportedChannels = tagValue[0]; 00588 Log2(PCSC_LOG_INFO, 00589 "Support %d simultaneous readers", tagValue[0]); 00590 } 00591 else 00592 supportedChannels = 1; 00593 00594 /* Check to see if it is a hotplug reader and different */ 00595 if ((((sReadersContexts[i]->port & 0xFFFF0000) == 00596 PCSCLITE_HP_BASE_PORT) 00597 && (sReadersContexts[i]->port != port)) 00598 || (supportedChannels > 1)) 00599 { 00600 const char *reader = sReadersContexts[i]->readerState->readerName; 00601 00602 /* 00603 * tells the caller who the parent of this 00604 * clone is so it can use it's shared 00605 * resources like mutex/etc. 00606 */ 00607 parent = i; 00608 00609 /* 00610 * If the same reader already exists and it is 00611 * hotplug then we must look for others and 00612 * enumerate the readername 00613 */ 00614 currentDigit = strtol(reader + strlen(reader) - 5, NULL, 16); 00615 00616 /* This spot is taken */ 00617 usedDigits[currentDigit] = TRUE; 00618 } 00619 } 00620 } 00621 } 00622 } 00623 00624 /* default value */ 00625 i = 0; 00626 00627 /* Other identical readers exist on the same bus */ 00628 if (currentDigit != -1) 00629 { 00630 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00631 { 00632 /* get the first free digit */ 00633 if (usedDigits[i] == FALSE) 00634 break; 00635 } 00636 00637 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 00638 { 00639 Log2(PCSC_LOG_ERROR, "Max number of readers reached: %d", PCSCLITE_MAX_READERS_CONTEXTS); 00640 return -2; 00641 } 00642 00643 if (i >= supportedChannels) 00644 { 00645 Log3(PCSC_LOG_ERROR, "Driver %s does not support more than " 00646 "%d reader(s). Maybe the driver should support " 00647 "TAG_IFD_SIMULTANEOUS_ACCESS", libraryName, supportedChannels); 00648 return -2; 00649 } 00650 } 00651 00652 snprintf(rContext->readerState->readerName, 00653 sizeof(rContext->readerState->readerName), "%s %02X 00", 00654 readerName, i); 00655 00656 /* Set the slot in 0xDDDDCCCC */ 00657 rContext->slot = i << 16; 00658 00659 return parent; 00660 } 00661 00662 LONG RFReaderInfo(const char *readerName, READER_CONTEXT ** sReader) 00663 { 00664 int i; 00665 00666 if (readerName == NULL) 00667 return SCARD_E_UNKNOWN_READER; 00668 00669 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00670 { 00671 if (sReadersContexts[i]->vHandle != 0) 00672 { 00673 if (strcmp(readerName, 00674 sReadersContexts[i]->readerState->readerName) == 0) 00675 { 00676 *sReader = sReadersContexts[i]; 00677 return SCARD_S_SUCCESS; 00678 } 00679 } 00680 } 00681 00682 return SCARD_E_UNKNOWN_READER; 00683 } 00684 00685 LONG RFReaderInfoNamePort(int port, const char *readerName, 00686 READER_CONTEXT * * sReader) 00687 { 00688 char lpcStripReader[MAX_READERNAME]; 00689 int i; 00690 00691 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00692 { 00693 if (sReadersContexts[i]->vHandle != 0) 00694 { 00695 int tmplen; 00696 00697 strncpy(lpcStripReader, 00698 sReadersContexts[i]->readerState->readerName, 00699 sizeof(lpcStripReader)); 00700 tmplen = strlen(lpcStripReader); 00701 lpcStripReader[tmplen - 6] = 0; 00702 00703 if ((strcmp(readerName, lpcStripReader) == 0) && 00704 (port == sReadersContexts[i]->port)) 00705 { 00706 *sReader = sReadersContexts[i]; 00707 return SCARD_S_SUCCESS; 00708 } 00709 } 00710 } 00711 00712 return SCARD_E_INVALID_VALUE; 00713 } 00714 00715 LONG RFReaderInfoById(DWORD dwIdentity, READER_CONTEXT * * sReader) 00716 { 00717 int i; 00718 00719 /* Strip off the lower nibble and get the identity */ 00720 dwIdentity = dwIdentity >> IDENTITY_SHIFT; 00721 dwIdentity = dwIdentity << IDENTITY_SHIFT; 00722 00723 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00724 { 00725 if (dwIdentity == sReadersContexts[i]->dwIdentity) 00726 { 00727 *sReader = sReadersContexts[i]; 00728 return SCARD_S_SUCCESS; 00729 } 00730 } 00731 00732 return SCARD_E_INVALID_VALUE; 00733 } 00734 00735 LONG RFLoadReader(READER_CONTEXT * rContext) 00736 { 00737 if (rContext->vHandle != 0) 00738 { 00739 Log2(PCSC_LOG_INFO, "Reusing already loaded driver for %s", 00740 rContext->library); 00741 /* Another reader exists with this library loaded */ 00742 return SCARD_S_SUCCESS; 00743 } 00744 00745 return DYN_LoadLibrary(&rContext->vHandle, rContext->library); 00746 } 00747 00748 LONG RFBindFunctions(READER_CONTEXT * rContext) 00749 { 00750 int rv; 00751 void *f; 00752 00753 rv = DYN_GetAddress(rContext->vHandle, &f, "IFDHCreateChannelByName"); 00754 if (SCARD_S_SUCCESS == rv) 00755 { 00756 /* Ifd Handler 3.0 found */ 00757 rContext->version = IFD_HVERSION_3_0; 00758 } 00759 else 00760 { 00761 rv = DYN_GetAddress(rContext->vHandle, &f, "IFDHCreateChannel"); 00762 if (SCARD_S_SUCCESS == rv) 00763 { 00764 /* Ifd Handler 2.0 found */ 00765 rContext->version = IFD_HVERSION_2_0; 00766 } 00767 else 00768 { 00769 /* Neither version of the IFD Handler was found - exit */ 00770 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing"); 00771 return SCARD_F_UNKNOWN_ERROR; 00772 } 00773 } 00774 00775 if (rContext->version == IFD_HVERSION_2_0) 00776 { 00777 /* The following binds version 2.0 of the IFD Handler specs */ 00778 #define GET_ADDRESS_OPTIONALv2(s, code) \ 00779 { \ 00780 void *f1 = NULL; \ 00781 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s); \ 00782 if (SCARD_S_SUCCESS != rvl) \ 00783 { \ 00784 code \ 00785 } \ 00786 rContext->psFunctions.psFunctions_v2.pvf ## s = f1; \ 00787 } 00788 00789 #define GET_ADDRESSv2(s) \ 00790 GET_ADDRESS_OPTIONALv2(s, \ 00791 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \ 00792 return(rv); ) 00793 00794 Log1(PCSC_LOG_INFO, "Loading IFD Handler 2.0"); 00795 00796 GET_ADDRESSv2(CreateChannel) 00797 GET_ADDRESSv2(CloseChannel) 00798 GET_ADDRESSv2(GetCapabilities) 00799 GET_ADDRESSv2(SetCapabilities) 00800 GET_ADDRESSv2(PowerICC) 00801 GET_ADDRESSv2(TransmitToICC) 00802 GET_ADDRESSv2(ICCPresence) 00803 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, ) 00804 00805 GET_ADDRESSv2(Control) 00806 } 00807 else if (rContext->version == IFD_HVERSION_3_0) 00808 { 00809 /* The following binds version 3.0 of the IFD Handler specs */ 00810 #define GET_ADDRESS_OPTIONALv3(s, code) \ 00811 { \ 00812 void *f1 = NULL; \ 00813 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s); \ 00814 if (SCARD_S_SUCCESS != rvl) \ 00815 { \ 00816 code \ 00817 } \ 00818 rContext->psFunctions.psFunctions_v3.pvf ## s = f1; \ 00819 } 00820 00821 #define GET_ADDRESSv3(s) \ 00822 GET_ADDRESS_OPTIONALv3(s, \ 00823 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \ 00824 return(rv); ) 00825 00826 Log1(PCSC_LOG_INFO, "Loading IFD Handler 3.0"); 00827 00828 GET_ADDRESSv2(CreateChannel) 00829 GET_ADDRESSv2(CloseChannel) 00830 GET_ADDRESSv2(GetCapabilities) 00831 GET_ADDRESSv2(SetCapabilities) 00832 GET_ADDRESSv2(PowerICC) 00833 GET_ADDRESSv2(TransmitToICC) 00834 GET_ADDRESSv2(ICCPresence) 00835 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, ) 00836 00837 GET_ADDRESSv3(CreateChannelByName) 00838 GET_ADDRESSv3(Control) 00839 } 00840 else 00841 { 00842 /* Who knows what could have happenned for it to get here. */ 00843 Log1(PCSC_LOG_CRITICAL, "IFD Handler not 1.0/2.0 or 3.0"); 00844 return SCARD_F_UNKNOWN_ERROR; 00845 } 00846 00847 return SCARD_S_SUCCESS; 00848 } 00849 00850 LONG RFUnBindFunctions(READER_CONTEXT * rContext) 00851 { 00852 /* Zero out everything */ 00853 memset(&rContext->psFunctions, 0, sizeof(rContext->psFunctions)); 00854 00855 return SCARD_S_SUCCESS; 00856 } 00857 00858 LONG RFUnloadReader(READER_CONTEXT * rContext) 00859 { 00860 /* Make sure no one else is using this library */ 00861 if (*rContext->pFeeds == 1) 00862 { 00863 Log1(PCSC_LOG_INFO, "Unloading reader driver."); 00864 (void)DYN_CloseLibrary(&rContext->vHandle); 00865 } 00866 00867 rContext->vHandle = NULL; 00868 00869 return SCARD_S_SUCCESS; 00870 } 00871 00872 LONG RFCheckSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext) 00873 { 00874 if (rContext->hLockId == 0 || rContext->hLockId == hCard) 00875 return SCARD_S_SUCCESS; 00876 else 00877 return SCARD_E_SHARING_VIOLATION; 00878 } 00879 00880 LONG RFLockSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext) 00881 { 00882 LONG rv; 00883 00884 (void)pthread_mutex_lock(&LockMutex); 00885 rv = RFCheckSharing(hCard, rContext); 00886 if (SCARD_S_SUCCESS == rv) 00887 { 00888 rContext->LockCount += 1; 00889 rContext->hLockId = hCard; 00890 } 00891 (void)pthread_mutex_unlock(&LockMutex); 00892 00893 return rv; 00894 } 00895 00896 LONG RFUnlockSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext) 00897 { 00898 LONG rv; 00899 00900 (void)pthread_mutex_lock(&LockMutex); 00901 rv = RFCheckSharing(hCard, rContext); 00902 if (SCARD_S_SUCCESS == rv) 00903 { 00904 if (rContext->LockCount > 0) 00905 rContext->LockCount -= 1; 00906 if (0 == rContext->LockCount) 00907 rContext->hLockId = 0; 00908 } 00909 (void)pthread_mutex_unlock(&LockMutex); 00910 00911 return rv; 00912 } 00913 00914 LONG RFUnlockAllSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext) 00915 { 00916 LONG rv; 00917 00918 (void)pthread_mutex_lock(&LockMutex); 00919 rv = RFCheckSharing(hCard, rContext); 00920 if (SCARD_S_SUCCESS == rv) 00921 { 00922 rContext->LockCount = 0; 00923 rContext->hLockId = 0; 00924 } 00925 (void)pthread_mutex_unlock(&LockMutex); 00926 00927 return rv; 00928 } 00929 00930 LONG RFInitializeReader(READER_CONTEXT * rContext) 00931 { 00932 LONG rv; 00933 00934 /* Spawn the event handler thread */ 00935 Log3(PCSC_LOG_INFO, "Attempting startup of %s using %s", 00936 rContext->readerState->readerName, rContext->library); 00937 00938 #ifndef PCSCLITE_STATIC_DRIVER 00939 /* loads the library */ 00940 rv = RFLoadReader(rContext); 00941 if (rv != SCARD_S_SUCCESS) 00942 { 00943 Log2(PCSC_LOG_ERROR, "RFLoadReader failed: 0x%lX", rv); 00944 return rv; 00945 } 00946 00947 /* binds the functions */ 00948 rv = RFBindFunctions(rContext); 00949 00950 if (rv != SCARD_S_SUCCESS) 00951 { 00952 Log2(PCSC_LOG_ERROR, "RFBindFunctions failed: 0x%lX", rv); 00953 (void)RFUnloadReader(rContext); 00954 return rv; 00955 } 00956 #else 00957 /* define a fake vHandle. Can be any value except NULL */ 00958 rContext->vHandle = RFInitializeReader; 00959 #endif 00960 00961 /* tries to open the port */ 00962 rv = IFDOpenIFD(rContext); 00963 00964 if (rv != IFD_SUCCESS) 00965 { 00966 Log3(PCSC_LOG_CRITICAL, "Open Port 0x%X Failed (%s)", 00967 rContext->port, rContext->device); 00968 00969 /* the reader was not started correctly */ 00970 rContext->slot = -1; 00971 00972 /* IFDOpenIFD() failed */ 00973 rContext->slot = -1; 00974 00975 if (IFD_NO_SUCH_DEVICE == rv) 00976 return SCARD_E_UNKNOWN_READER; 00977 else 00978 return SCARD_E_INVALID_TARGET; 00979 } 00980 00981 return SCARD_S_SUCCESS; 00982 } 00983 00984 LONG RFUnInitializeReader(READER_CONTEXT * rContext) 00985 { 00986 Log2(PCSC_LOG_INFO, "Attempting shutdown of %s.", 00987 rContext->readerState->readerName); 00988 00989 /* Do not close a reader if IFDOpenIFD() failed in RFInitializeReader() */ 00990 if (rContext->slot != -1) 00991 (void)IFDCloseIFD(rContext); 00992 00993 (void)RFUnBindFunctions(rContext); 00994 (void)RFUnloadReader(rContext); 00995 00996 /* 00997 * Zero out the public status struct to allow it to be recycled and 00998 * used again 00999 */ 01000 memset(rContext->readerState->readerName, 0, 01001 sizeof(rContext->readerState->readerName)); 01002 memset(rContext->readerState->cardAtr, 0, 01003 sizeof(rContext->readerState->cardAtr)); 01004 rContext->readerState->readerState = 0; 01005 rContext->readerState->readerSharing = 0; 01006 rContext->readerState->cardAtrLength = READER_NOT_INITIALIZED; 01007 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; 01008 01009 return SCARD_S_SUCCESS; 01010 } 01011 01012 SCARDHANDLE RFCreateReaderHandle(READER_CONTEXT * rContext) 01013 { 01014 USHORT randHandle; 01015 01016 /* Create a random handle with 16 bits check to see if it already is 01017 * used. */ 01018 /* FIXME: THIS IS NOT STRONG ENOUGH: A 128-bit token should be 01019 * generated. The client and server would associate token and hCard 01020 * for authentication. */ 01021 randHandle = SYS_RandomInt(10, 65000); 01022 01023 int i; 01024 again: 01025 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 01026 { 01027 if (sReadersContexts[i]->vHandle != 0) 01028 { 01029 RDR_CLIHANDLES *currentHandle; 01030 list_t * l = &sReadersContexts[i]->handlesList; 01031 01032 (void)pthread_mutex_lock(&sReadersContexts[i]->handlesList_lock); 01033 list_iterator_start(l); 01034 while (list_iterator_hasnext(l)) 01035 { 01036 currentHandle = list_iterator_next(l); 01037 if (((LONG)rContext->dwIdentity + randHandle) == 01038 (currentHandle->hCard)) 01039 { 01040 /* Get a new handle and loop again */ 01041 randHandle = SYS_RandomInt(10, 65000); 01042 list_iterator_stop(l); 01043 (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock); 01044 goto again; 01045 } 01046 } 01047 list_iterator_stop(l); 01048 (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock); 01049 } 01050 } 01051 01052 /* Once the for loop is completed w/o restart a good handle was 01053 * found and the loop can be exited. */ 01054 return rContext->dwIdentity + randHandle; 01055 } 01056 01057 LONG RFFindReaderHandle(SCARDHANDLE hCard) 01058 { 01059 int i; 01060 01061 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 01062 { 01063 if (sReadersContexts[i]->vHandle != 0) 01064 { 01065 RDR_CLIHANDLES * currentHandle; 01066 (void)pthread_mutex_lock(&sReadersContexts[i]->handlesList_lock); 01067 currentHandle = list_seek(&sReadersContexts[i]->handlesList, 01068 &hCard); 01069 (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock); 01070 if (currentHandle != NULL) 01071 return SCARD_S_SUCCESS; 01072 } 01073 } 01074 01075 return SCARD_E_INVALID_HANDLE; 01076 } 01077 01078 LONG RFDestroyReaderHandle(/*@unused@*/ SCARDHANDLE hCard) 01079 { 01080 (void)hCard; 01081 return SCARD_S_SUCCESS; 01082 } 01083 01084 LONG RFAddReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard) 01085 { 01086 int listLength, lrv; 01087 RDR_CLIHANDLES *newHandle; 01088 LONG rv = SCARD_S_SUCCESS; 01089 01090 (void)pthread_mutex_lock(&rContext->handlesList_lock); 01091 listLength = list_size(&(rContext->handlesList)); 01092 01093 /* Throttle the number of possible handles */ 01094 if (listLength >= maxReaderHandles) 01095 { 01096 Log2(PCSC_LOG_CRITICAL, 01097 "Too many handles opened, exceeding configured max (%d)", 01098 maxReaderHandles); 01099 rv = SCARD_E_NO_MEMORY; 01100 goto end; 01101 } 01102 01103 newHandle = malloc(sizeof(RDR_CLIHANDLES)); 01104 if (NULL == newHandle) 01105 { 01106 Log1(PCSC_LOG_CRITICAL, "malloc failed"); 01107 rv = SCARD_E_NO_MEMORY; 01108 goto end; 01109 } 01110 01111 newHandle->hCard = hCard; 01112 newHandle->dwEventStatus = 0; 01113 01114 lrv = list_append(&(rContext->handlesList), newHandle); 01115 if (lrv < 0) 01116 { 01117 free(newHandle); 01118 Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %d", 01119 lrv); 01120 rv = SCARD_E_NO_MEMORY; 01121 } 01122 end: 01123 (void)pthread_mutex_unlock(&rContext->handlesList_lock); 01124 return rv; 01125 } 01126 01127 LONG RFRemoveReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard) 01128 { 01129 RDR_CLIHANDLES *currentHandle; 01130 int lrv; 01131 LONG rv = SCARD_S_SUCCESS; 01132 01133 (void)pthread_mutex_lock(&rContext->handlesList_lock); 01134 currentHandle = list_seek(&(rContext->handlesList), &hCard); 01135 if (NULL == currentHandle) 01136 { 01137 Log2(PCSC_LOG_CRITICAL, "list_seek failed to locate hCard=%lX", hCard); 01138 rv = SCARD_E_INVALID_HANDLE; 01139 goto end; 01140 } 01141 01142 lrv = list_delete(&(rContext->handlesList), currentHandle); 01143 if (lrv < 0) 01144 Log2(PCSC_LOG_CRITICAL, 01145 "list_delete failed with return value: %d", lrv); 01146 01147 free(currentHandle); 01148 01149 end: 01150 (void)pthread_mutex_unlock(&rContext->handlesList_lock); 01151 01152 /* Not Found */ 01153 return rv; 01154 } 01155 01156 LONG RFSetReaderEventState(READER_CONTEXT * rContext, DWORD dwEvent) 01157 { 01158 /* Set all the handles for that reader to the event */ 01159 int list_index, listSize; 01160 RDR_CLIHANDLES *currentHandle; 01161 01162 (void)pthread_mutex_lock(&rContext->handlesList_lock); 01163 listSize = list_size(&(rContext->handlesList)); 01164 01165 for (list_index = 0; list_index < listSize; list_index++) 01166 { 01167 currentHandle = list_get_at(&(rContext->handlesList), list_index); 01168 if (NULL == currentHandle) 01169 { 01170 Log2(PCSC_LOG_CRITICAL, "list_get_at failed at index %d", 01171 list_index); 01172 continue; 01173 } 01174 01175 currentHandle->dwEventStatus = dwEvent; 01176 } 01177 (void)pthread_mutex_unlock(&rContext->handlesList_lock); 01178 01179 if (SCARD_REMOVED == dwEvent) 01180 { 01181 /* unlock the card */ 01182 rContext->hLockId = 0; 01183 rContext->LockCount = 0; 01184 } 01185 01186 return SCARD_S_SUCCESS; 01187 } 01188 01189 LONG RFCheckReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard) 01190 { 01191 LONG rv; 01192 RDR_CLIHANDLES *currentHandle; 01193 01194 (void)pthread_mutex_lock(&rContext->handlesList_lock); 01195 currentHandle = list_seek(&(rContext->handlesList), &hCard); 01196 (void)pthread_mutex_unlock(&rContext->handlesList_lock); 01197 if (NULL == currentHandle) 01198 { 01199 /* Not Found */ 01200 Log2(PCSC_LOG_CRITICAL, "list_seek failed for hCard 0x%lX", hCard); 01201 return SCARD_E_INVALID_HANDLE; 01202 } 01203 01204 switch(currentHandle->dwEventStatus) 01205 { 01206 case 0: 01207 rv = SCARD_S_SUCCESS; 01208 break; 01209 01210 case SCARD_REMOVED: 01211 rv = SCARD_W_REMOVED_CARD; 01212 break; 01213 01214 case SCARD_RESET: 01215 rv = SCARD_W_RESET_CARD; 01216 break; 01217 01218 default: 01219 rv = SCARD_E_INVALID_VALUE; 01220 } 01221 01222 return rv; 01223 } 01224 01225 LONG RFClearReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard) 01226 { 01227 RDR_CLIHANDLES *currentHandle; 01228 01229 (void)pthread_mutex_lock(&rContext->handlesList_lock); 01230 currentHandle = list_seek(&(rContext->handlesList), &hCard); 01231 (void)pthread_mutex_unlock(&rContext->handlesList_lock); 01232 if (NULL == currentHandle) 01233 /* Not Found */ 01234 return SCARD_E_INVALID_HANDLE; 01235 01236 currentHandle->dwEventStatus = 0; 01237 01238 /* hCards should be unique so we 01239 * should be able to return 01240 * as soon as we have a hit */ 01241 return SCARD_S_SUCCESS; 01242 } 01243 01244 LONG RFCheckReaderStatus(READER_CONTEXT * rContext) 01245 { 01246 if (rContext->readerState->readerState & SCARD_UNKNOWN) 01247 return SCARD_E_READER_UNAVAILABLE; 01248 else 01249 return SCARD_S_SUCCESS; 01250 } 01251 01252 void RFCleanupReaders(void) 01253 { 01254 int i; 01255 01256 Log1(PCSC_LOG_INFO, "entering cleaning function"); 01257 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 01258 { 01259 if (sReadersContexts[i]->vHandle != 0) 01260 { 01261 LONG rv; 01262 char lpcStripReader[MAX_READERNAME]; 01263 01264 Log2(PCSC_LOG_INFO, "Stopping reader: %s", 01265 sReadersContexts[i]->readerState->readerName); 01266 01267 strncpy(lpcStripReader, 01268 sReadersContexts[i]->readerState->readerName, 01269 sizeof(lpcStripReader)); 01270 /* strip the 6 last char ' 00 00' */ 01271 lpcStripReader[strlen(lpcStripReader) - 6] = '\0'; 01272 01273 rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->port); 01274 01275 if (rv != SCARD_S_SUCCESS) 01276 Log2(PCSC_LOG_ERROR, "RFRemoveReader error: 0x%08lX", rv); 01277 } 01278 } 01279 } 01280 01285 #ifdef USE_USB 01286 void RFWaitForReaderInit(void) 01287 { 01288 int i, need_to_wait; 01289 01290 do 01291 { 01292 need_to_wait = FALSE; 01293 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 01294 { 01295 /* reader is present */ 01296 if (sReadersContexts[i]->vHandle != NULL) 01297 { 01298 /* but card state is not yet available */ 01299 if (READER_NOT_INITIALIZED 01300 == sReadersContexts[i]->readerState->cardAtrLength) 01301 { 01302 Log2(PCSC_LOG_DEBUG, "Waiting init for reader: %s", 01303 sReadersContexts[i]->readerState->readerName); 01304 need_to_wait = TRUE; 01305 } 01306 } 01307 } 01308 01309 if (need_to_wait) 01310 SYS_USleep(10*1000); /* 10 ms */ 01311 } while (need_to_wait); 01312 } 01313 #endif 01314 01315 #ifdef USE_SERIAL 01316 int RFStartSerialReaders(const char *readerconf) 01317 { 01318 SerialReader *reader_list = NULL; 01319 int i, rv; 01320 01321 /* remember the configuration filename for RFReCheckReaderConf() */ 01322 ConfigFile = strdup(readerconf); 01323 01324 rv = DBGetReaderListDir(readerconf, &reader_list); 01325 01326 /* the list is empty */ 01327 if (NULL == reader_list) 01328 return rv; 01329 01330 for (i=0; reader_list[i].pcFriendlyname; i++) 01331 { 01332 int j; 01333 01334 (void)RFAddReader(reader_list[i].pcFriendlyname, 01335 reader_list[i].channelId, 01336 reader_list[i].pcLibpath, reader_list[i].pcDevicename); 01337 01338 /* update the ConfigFileCRC (this false "CRC" is very weak) */ 01339 for (j=0; j<reader_list[i].pcFriendlyname[j]; j++) 01340 ConfigFileCRC += reader_list[i].pcFriendlyname[j]; 01341 for (j=0; j<reader_list[i].pcLibpath[j]; j++) 01342 ConfigFileCRC += reader_list[i].pcLibpath[j]; 01343 for (j=0; j<reader_list[i].pcDevicename[j]; j++) 01344 ConfigFileCRC += reader_list[i].pcDevicename[j]; 01345 01346 /* free strings allocated by DBGetReaderListDir() */ 01347 free(reader_list[i].pcFriendlyname); 01348 free(reader_list[i].pcLibpath); 01349 free(reader_list[i].pcDevicename); 01350 } 01351 free(reader_list); 01352 01353 return rv; 01354 } 01355 01356 void RFReCheckReaderConf(void) 01357 { 01358 SerialReader *reader_list = NULL; 01359 int i, crc; 01360 01361 (void)DBGetReaderListDir(ConfigFile, &reader_list); 01362 01363 /* the list is empty */ 01364 if (NULL == reader_list) 01365 return; 01366 01367 crc = 0; 01368 for (i=0; reader_list[i].pcFriendlyname; i++) 01369 { 01370 int j; 01371 01372 /* calculate a local crc */ 01373 for (j=0; j<reader_list[i].pcFriendlyname[j]; j++) 01374 crc += reader_list[i].pcFriendlyname[j]; 01375 for (j=0; j<reader_list[i].pcLibpath[j]; j++) 01376 crc += reader_list[i].pcLibpath[j]; 01377 for (j=0; j<reader_list[i].pcDevicename[j]; j++) 01378 crc += reader_list[i].pcDevicename[j]; 01379 } 01380 01381 /* cancel if the configuration file has been modified */ 01382 if (crc != ConfigFileCRC) 01383 { 01384 Log2(PCSC_LOG_CRITICAL, 01385 "configuration file: %s has been modified. Recheck canceled", 01386 ConfigFile); 01387 return; 01388 } 01389 01390 for (i=0; reader_list[i].pcFriendlyname; i++) 01391 { 01392 int r; 01393 char present = FALSE; 01394 01395 Log2(PCSC_LOG_DEBUG, "refresh reader: %s", 01396 reader_list[i].pcFriendlyname); 01397 01398 /* is the reader already present? */ 01399 for (r = 0; r < PCSCLITE_MAX_READERS_CONTEXTS; r++) 01400 { 01401 if (sReadersContexts[r]->vHandle != 0) 01402 { 01403 char lpcStripReader[MAX_READERNAME]; 01404 int tmplen; 01405 01406 /* get the reader name without the reader and slot numbers */ 01407 strncpy(lpcStripReader, 01408 sReadersContexts[i]->readerState->readerName, 01409 sizeof(lpcStripReader)); 01410 tmplen = strlen(lpcStripReader); 01411 lpcStripReader[tmplen - 6] = 0; 01412 01413 if ((strcmp(reader_list[i].pcFriendlyname, lpcStripReader) == 0) 01414 && (reader_list[r].channelId == sReadersContexts[i]->port)) 01415 { 01416 DWORD dwStatus = 0; 01417 01418 /* the reader was already started */ 01419 present = TRUE; 01420 01421 /* verify the reader is still connected */ 01422 if (IFDStatusICC(sReadersContexts[r], &dwStatus) 01423 != SCARD_S_SUCCESS) 01424 { 01425 Log2(PCSC_LOG_INFO, "Reader %s disappeared", 01426 reader_list[i].pcFriendlyname); 01427 (void)RFRemoveReader(reader_list[i].pcFriendlyname, 01428 reader_list[r].channelId); 01429 } 01430 } 01431 } 01432 } 01433 01434 /* the reader was not present */ 01435 if (!present) 01436 /* we try to add it */ 01437 (void)RFAddReader(reader_list[i].pcFriendlyname, 01438 reader_list[i].channelId, reader_list[i].pcLibpath, 01439 reader_list[i].pcDevicename); 01440 01441 /* free strings allocated by DBGetReaderListDir() */ 01442 free(reader_list[i].pcFriendlyname); 01443 free(reader_list[i].pcLibpath); 01444 free(reader_list[i].pcDevicename); 01445 } 01446 free(reader_list); 01447 } 01448 #endif 01449