readerfactory.c

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