pcsc-lite 1.6.4
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-2010
00009  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00010  * Copyright (C) 2009
00011  *  Jean-Luc Giraud <jlgiraud@googlemail.com>
00012  *
00013  * $Id: readerfactory.c 5070 2010-07-26 13:27:51Z 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, READER_CONTEXT * rContext)
00896 {
00897     if (rContext->hLockId == 0 || rContext->hLockId == hCard)
00898         return SCARD_S_SUCCESS;
00899     else
00900         return SCARD_E_SHARING_VIOLATION;
00901 }
00902 
00903 LONG RFLockSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
00904 {
00905     LONG rv;
00906 
00907     (void)pthread_mutex_lock(&LockMutex);
00908     rv = RFCheckSharing(hCard, rContext);
00909     if (SCARD_S_SUCCESS == rv)
00910     {
00911         rContext->LockCount += 1;
00912         rContext->hLockId = hCard;
00913     }
00914     (void)pthread_mutex_unlock(&LockMutex);
00915 
00916     return rv;
00917 }
00918 
00919 LONG RFUnlockSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
00920 {
00921     LONG rv;
00922 
00923     (void)pthread_mutex_lock(&LockMutex);
00924     rv = RFCheckSharing(hCard, rContext);
00925     if (SCARD_S_SUCCESS == rv)
00926     {
00927         if (rContext->LockCount > 0)
00928             rContext->LockCount -= 1;
00929         if (0 == rContext->LockCount)
00930             rContext->hLockId = 0;
00931     }
00932     (void)pthread_mutex_unlock(&LockMutex);
00933 
00934     return rv;
00935 }
00936 
00937 LONG RFUnlockAllSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
00938 {
00939     LONG rv;
00940 
00941     (void)pthread_mutex_lock(&LockMutex);
00942     rv = RFCheckSharing(hCard, rContext);
00943     if (SCARD_S_SUCCESS == rv)
00944     {
00945         rContext->LockCount = 0;
00946         rContext->hLockId = 0;
00947     }
00948     (void)pthread_mutex_unlock(&LockMutex);
00949 
00950     return rv;
00951 }
00952 
00953 LONG RFInitializeReader(READER_CONTEXT * rContext)
00954 {
00955     LONG rv;
00956 
00957     /* Spawn the event handler thread */
00958     Log3(PCSC_LOG_INFO, "Attempting startup of %s using %s",
00959         rContext->lpcReader, rContext->lpcLibrary);
00960 
00961 #ifndef PCSCLITE_STATIC_DRIVER
00962     /* loads the library */
00963     rv = RFLoadReader(rContext);
00964     if (rv != SCARD_S_SUCCESS)
00965     {
00966         Log2(PCSC_LOG_ERROR, "RFLoadReader failed: %X", rv);
00967         return rv;
00968     }
00969 
00970     /* binds the functions */
00971     rv = RFBindFunctions(rContext);
00972 
00973     if (rv != SCARD_S_SUCCESS)
00974     {
00975         Log2(PCSC_LOG_ERROR, "RFBindFunctions failed: %X", rv);
00976         (void)RFUnloadReader(rContext);
00977         return rv;
00978     }
00979 #else
00980     /* define a fake vHandle. Can be any value except NULL */
00981     rContext->vHandle = RFInitializeReader;
00982 #endif
00983 
00984     /* tries to open the port */
00985     rv = IFDOpenIFD(rContext);
00986 
00987     if (rv != IFD_SUCCESS)
00988     {
00989         Log3(PCSC_LOG_CRITICAL, "Open Port %X Failed (%s)",
00990             rContext->port, rContext->lpcDevice);
00991         (void)RFUnBindFunctions(rContext);
00992         (void)RFUnloadReader(rContext);
00993         if (IFD_NO_SUCH_DEVICE == rv)
00994             return SCARD_E_UNKNOWN_READER;
00995         else
00996             return SCARD_E_INVALID_TARGET;
00997     }
00998 
00999     return SCARD_S_SUCCESS;
01000 }
01001 
01002 LONG RFUnInitializeReader(READER_CONTEXT * rContext)
01003 {
01004     Log2(PCSC_LOG_INFO, "Attempting shutdown of %s.",
01005         rContext->lpcReader);
01006 
01007     /* Close the port, unbind the functions, and unload the library */
01008 
01009     /*
01010      * If the reader is getting uninitialized then it is being unplugged
01011      * so I can't send a IFDPowerICC call to it
01012      *
01013      * IFDPowerICC( rContext, IFD_POWER_DOWN, Atr, &AtrLen );
01014      */
01015     (void)IFDCloseIFD(rContext);
01016     (void)RFUnBindFunctions(rContext);
01017     (void)RFUnloadReader(rContext);
01018 
01019     return SCARD_S_SUCCESS;
01020 }
01021 
01022 SCARDHANDLE RFCreateReaderHandle(READER_CONTEXT * rContext)
01023 {
01024     USHORT randHandle;
01025 
01026     /* Create a random handle with 16 bits check to see if it already is
01027      * used. */
01028     /* FIXME: THIS IS NOT STRONG ENOUGH: A 128-bit token should be
01029      * generated.  The client and server would associate token and hCard
01030      * for authentication. */
01031     randHandle = SYS_RandomInt(10, 65000);
01032 
01033     int i;
01034 again:
01035     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01036     {
01037         if ((sReadersContexts[i])->vHandle != 0)
01038         {
01039             RDR_CLIHANDLES *currentHandle;
01040             list_t * l = &((sReadersContexts[i])->handlesList);
01041 
01042             (void)pthread_mutex_lock(&(sReadersContexts[i])->handlesList_lock);
01043             list_iterator_start(l);
01044             while (list_iterator_hasnext(l))
01045             {
01046                 currentHandle = list_iterator_next(l);
01047                 if ((rContext->dwIdentity + randHandle) ==
01048                     (currentHandle->hCard))
01049                 {
01050                     /* Get a new handle and loop again */
01051                     randHandle = SYS_RandomInt(10, 65000);
01052                     list_iterator_stop(l);
01053                     (void)pthread_mutex_unlock(&(sReadersContexts[i])->handlesList_lock);
01054                     goto again;
01055                 }
01056             }
01057             list_iterator_stop(l);
01058             (void)pthread_mutex_unlock(&(sReadersContexts[i])->handlesList_lock);
01059         }
01060     }
01061 
01062     /* Once the for loop is completed w/o restart a good handle was
01063      * found and the loop can be exited. */
01064     return rContext->dwIdentity + randHandle;
01065 }
01066 
01067 LONG RFFindReaderHandle(SCARDHANDLE hCard)
01068 {
01069     int i;
01070 
01071     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01072     {
01073         if ((sReadersContexts[i])->vHandle != 0)
01074         {
01075             RDR_CLIHANDLES * currentHandle;
01076             (void)pthread_mutex_lock(&(sReadersContexts[i])->handlesList_lock);
01077             currentHandle = list_seek(&((sReadersContexts[i])->handlesList),
01078                 &hCard);
01079             (void)pthread_mutex_unlock(&(sReadersContexts[i])->handlesList_lock);
01080             if (currentHandle != NULL)
01081                 return SCARD_S_SUCCESS;
01082         }
01083     }
01084 
01085     return SCARD_E_INVALID_HANDLE;
01086 }
01087 
01088 LONG RFDestroyReaderHandle(/*@unused@*/ SCARDHANDLE hCard)
01089 {
01090     (void)hCard;
01091     return SCARD_S_SUCCESS;
01092 }
01093 
01094 LONG RFAddReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard)
01095 {
01096     int listLength, lrv;
01097     RDR_CLIHANDLES *newHandle;
01098     LONG rv = SCARD_S_SUCCESS;
01099 
01100     (void)pthread_mutex_lock(&rContext->handlesList_lock);
01101     listLength = list_size(&(rContext->handlesList));
01102 
01103     /* Throttle the number of possible handles */
01104     if (listLength >= maxReaderHandles)
01105     {
01106         Log2(PCSC_LOG_CRITICAL,
01107             "Too many handles opened, exceeding configured max (%d)",
01108             maxReaderHandles);
01109         rv = SCARD_E_NO_MEMORY;
01110         goto end;
01111     }
01112 
01113     newHandle = malloc(sizeof(RDR_CLIHANDLES));
01114     if (NULL == newHandle)
01115     {
01116         Log1(PCSC_LOG_CRITICAL, "malloc failed");
01117         rv = SCARD_E_NO_MEMORY;
01118         goto end;
01119     }
01120 
01121     newHandle->hCard = hCard;
01122     newHandle->dwEventStatus = 0;
01123 
01124     lrv = list_append(&(rContext->handlesList), newHandle);
01125     if (lrv < 0)
01126     {
01127         free(newHandle);
01128         Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %X",
01129             lrv);
01130         rv = SCARD_E_NO_MEMORY;
01131     }
01132 end:
01133     (void)pthread_mutex_unlock(&rContext->handlesList_lock);
01134     return SCARD_S_SUCCESS;
01135 }
01136 
01137 LONG RFRemoveReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard)
01138 {
01139     RDR_CLIHANDLES *currentHandle;
01140     int lrv;
01141     LONG rv = SCARD_S_SUCCESS;
01142 
01143     (void)pthread_mutex_lock(&rContext->handlesList_lock);
01144     currentHandle = list_seek(&(rContext->handlesList), &hCard);
01145     if (NULL == currentHandle)
01146     {
01147         Log2(PCSC_LOG_CRITICAL, "list_seek failed to locate hCard=%X", hCard);
01148         rv = SCARD_E_INVALID_HANDLE;
01149         goto end;
01150     }
01151 
01152     lrv = list_delete(&(rContext->handlesList), currentHandle);
01153     if (lrv < 0)
01154         Log2(PCSC_LOG_CRITICAL,
01155             "list_delete failed with return value: %X", lrv);
01156 
01157     free(currentHandle);
01158 
01159 end:
01160     (void)pthread_mutex_unlock(&rContext->handlesList_lock);
01161 
01162     /* Not Found */
01163     return rv;
01164 }
01165 
01166 LONG RFSetReaderEventState(READER_CONTEXT * rContext, DWORD dwEvent)
01167 {
01168     /* Set all the handles for that reader to the event */
01169     int list_index, listSize;
01170     RDR_CLIHANDLES *currentHandle;
01171 
01172     (void)pthread_mutex_lock(&rContext->handlesList_lock);
01173     listSize = list_size(&(rContext->handlesList));
01174 
01175     for (list_index = 0; list_index < listSize; list_index++)
01176     {
01177         currentHandle = list_get_at(&(rContext->handlesList), list_index);
01178         if (NULL == currentHandle)
01179         {
01180             Log2(PCSC_LOG_CRITICAL, "list_get_at failed at index %s",
01181                 list_index);
01182             continue;
01183         }
01184 
01185         currentHandle->dwEventStatus = dwEvent;
01186     }
01187     (void)pthread_mutex_unlock(&rContext->handlesList_lock);
01188 
01189     if (SCARD_REMOVED == dwEvent)
01190     {
01191         /* unlock the card */
01192         rContext->hLockId = 0;
01193         rContext->LockCount = 0;
01194     }
01195 
01196     return SCARD_S_SUCCESS;
01197 }
01198 
01199 LONG RFCheckReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard)
01200 {
01201     LONG rv;
01202     RDR_CLIHANDLES *currentHandle;
01203 
01204     (void)pthread_mutex_lock(&rContext->handlesList_lock);
01205     currentHandle = list_seek(&(rContext->handlesList), &hCard);
01206     (void)pthread_mutex_unlock(&rContext->handlesList_lock);
01207     if (NULL == currentHandle)
01208     {
01209         /* Not Found */
01210         Log2(PCSC_LOG_CRITICAL, "list_seek failed for hCard %X", hCard);
01211         return SCARD_E_INVALID_HANDLE;
01212     }
01213 
01214     switch(currentHandle->dwEventStatus)
01215     {
01216         case 0:
01217             rv = SCARD_S_SUCCESS;
01218             break;
01219 
01220         case SCARD_REMOVED:
01221             rv = SCARD_W_REMOVED_CARD;
01222             break;
01223 
01224         case SCARD_RESET:
01225             rv = SCARD_W_RESET_CARD;
01226             break;
01227 
01228         default:
01229             rv = SCARD_E_INVALID_VALUE;
01230     }
01231 
01232     return rv;
01233 }
01234 
01235 LONG RFClearReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard)
01236 {
01237     RDR_CLIHANDLES *currentHandle;
01238 
01239     (void)pthread_mutex_lock(&rContext->handlesList_lock);
01240     currentHandle = list_seek(&(rContext->handlesList), &hCard);
01241     (void)pthread_mutex_unlock(&rContext->handlesList_lock);
01242     if (NULL == currentHandle)
01243         /* Not Found */
01244         return SCARD_E_INVALID_HANDLE;
01245 
01246     currentHandle->dwEventStatus = 0;
01247 
01248     /* hCards should be unique so we
01249      * should be able to return
01250      * as soon as we have a hit */
01251     return SCARD_S_SUCCESS;
01252 }
01253 
01254 LONG RFCheckReaderStatus(READER_CONTEXT * rContext)
01255 {
01256     if ((rContext->readerState == NULL)
01257         || (rContext->readerState->readerState & SCARD_UNKNOWN))
01258         return SCARD_E_READER_UNAVAILABLE;
01259     else
01260         return SCARD_S_SUCCESS;
01261 }
01262 
01263 void RFCleanupReaders(void)
01264 {
01265     int i;
01266 
01267     Log1(PCSC_LOG_INFO, "entering cleaning function");
01268     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01269     {
01270         if (sReadersContexts[i]->vHandle != 0)
01271         {
01272             LONG rv;
01273             char lpcStripReader[MAX_READERNAME];
01274 
01275             Log2(PCSC_LOG_INFO, "Stopping reader: %s",
01276                 sReadersContexts[i]->lpcReader);
01277 
01278             strncpy(lpcStripReader, (sReadersContexts[i])->lpcReader,
01279                 sizeof(lpcStripReader));
01280             /* strip the 6 last char ' 00 00' */
01281             lpcStripReader[strlen(lpcStripReader) - 6] = '\0';
01282 
01283             rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->port);
01284 
01285             if (rv != SCARD_S_SUCCESS)
01286                 Log2(PCSC_LOG_ERROR, "RFRemoveReader error: 0x%08X", rv);
01287         }
01288     }
01289 }
01290 
01291 #ifdef USE_SERIAL
01292 int RFStartSerialReaders(const char *readerconf)
01293 {
01294     SerialReader *reader_list = NULL;
01295     int i, rv;
01296 
01297     /* remember the configuration filename for RFReCheckReaderConf() */
01298     ConfigFile = strdup(readerconf);
01299 
01300     rv = DBGetReaderListDir(readerconf, &reader_list);
01301 
01302     /* the list is empty */
01303     if (NULL == reader_list)
01304         return rv;
01305 
01306     for (i=0; reader_list[i].pcFriendlyname; i++)
01307     {
01308         int j;
01309 
01310         (void)RFAddReader(reader_list[i].pcFriendlyname,
01311             reader_list[i].channelId,
01312             reader_list[i].pcLibpath, reader_list[i].pcDevicename);
01313 
01314         /* update the ConfigFileCRC (this false "CRC" is very weak) */
01315         for (j=0; j<reader_list[i].pcFriendlyname[j]; j++)
01316             ConfigFileCRC += reader_list[i].pcFriendlyname[j];
01317         for (j=0; j<reader_list[i].pcLibpath[j]; j++)
01318             ConfigFileCRC += reader_list[i].pcLibpath[j];
01319         for (j=0; j<reader_list[i].pcDevicename[j]; j++)
01320             ConfigFileCRC += reader_list[i].pcDevicename[j];
01321 
01322         /* free strings allocated by DBGetReaderListDir() */
01323         free(reader_list[i].pcFriendlyname);
01324         free(reader_list[i].pcLibpath);
01325         free(reader_list[i].pcDevicename);
01326     }
01327     free(reader_list);
01328 
01329     return rv;
01330 }
01331 
01332 void RFReCheckReaderConf(void)
01333 {
01334     SerialReader *reader_list = NULL;
01335     int i, crc;
01336 
01337     (void)DBGetReaderListDir(ConfigFile, &reader_list);
01338 
01339     /* the list is empty */
01340     if (NULL == reader_list)
01341         return;
01342 
01343     crc = 0;
01344     for (i=0; reader_list[i].pcFriendlyname; i++)
01345     {
01346         int j;
01347 
01348         /* calculate a local crc */
01349         for (j=0; j<reader_list[i].pcFriendlyname[j]; j++)
01350             crc += reader_list[i].pcFriendlyname[j];
01351         for (j=0; j<reader_list[i].pcLibpath[j]; j++)
01352             crc += reader_list[i].pcLibpath[j];
01353         for (j=0; j<reader_list[i].pcDevicename[j]; j++)
01354             crc += reader_list[i].pcDevicename[j];
01355     }
01356 
01357     /* cancel if the configuration file has been modified */
01358     if (crc != ConfigFileCRC)
01359     {
01360         Log2(PCSC_LOG_CRITICAL,
01361             "configuration file: %s has been modified. Recheck canceled",
01362             ConfigFile);
01363         return;
01364     }
01365 
01366     for (i=0; reader_list[i].pcFriendlyname; i++)
01367     {
01368         int r;
01369         char present = FALSE;
01370 
01371         Log2(PCSC_LOG_DEBUG, "refresh reader: %s",
01372             reader_list[i].pcFriendlyname);
01373 
01374         /* is the reader already present? */
01375         for (r = 0; r < PCSCLITE_MAX_READERS_CONTEXTS; r++)
01376         {
01377             if (sReadersContexts[r]->vHandle != 0)
01378             {
01379                 char lpcStripReader[MAX_READERNAME];
01380                 int tmplen;
01381 
01382                 /* get the reader name without the reader and slot numbers */
01383                 strncpy(lpcStripReader, sReadersContexts[i]->lpcReader,
01384                     sizeof(lpcStripReader));
01385                 tmplen = strlen(lpcStripReader);
01386                 lpcStripReader[tmplen - 6] = 0;
01387 
01388                 if ((strcmp(reader_list[i].pcFriendlyname, lpcStripReader) == 0)
01389                     && (reader_list[r].channelId == sReadersContexts[i]->port))
01390                 {
01391                     DWORD dwStatus = 0, dwAtrLen = 0;
01392                     UCHAR ucAtr[MAX_ATR_SIZE];
01393 
01394                     /* the reader was already started */
01395                     present = TRUE;
01396 
01397                     /* verify the reader is still connected */
01398                     if (IFDStatusICC(sReadersContexts[r], &dwStatus, ucAtr,
01399                         &dwAtrLen) != SCARD_S_SUCCESS)
01400                     {
01401                         Log2(PCSC_LOG_INFO, "Reader %s disappeared",
01402                             reader_list[i].pcFriendlyname);
01403                         (void)RFRemoveReader(reader_list[i].pcFriendlyname,
01404                             reader_list[r].channelId);
01405                     }
01406                 }
01407             }
01408         }
01409 
01410         /* the reader was not present */
01411         if (!present)
01412             /* we try to add it */
01413             (void)RFAddReader(reader_list[i].pcFriendlyname,
01414                 reader_list[i].channelId, reader_list[i].pcLibpath,
01415                 reader_list[i].pcDevicename);
01416 
01417         /* free strings allocated by DBGetReaderListDir() */
01418         free(reader_list[i].pcFriendlyname);
01419         free(reader_list[i].pcLibpath);
01420         free(reader_list[i].pcDevicename);
01421     }
01422     free(reader_list);
01423 }
01424 #endif
01425 
01426 #if 0
01427 void RFSuspendAllReaders(void)
01428 {
01429     int i;
01430 
01431     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01432     {
01433         if ((sReadersContexts[i])->vHandle != 0)
01434         {
01435             (void)EHDestroyEventHandler(sReadersContexts[i]);
01436             (void)IFDCloseIFD(sReadersContexts[i]);
01437         }
01438     }
01439 }
01440 
01441 void RFAwakeAllReaders(void)
01442 {
01443     LONG rv = IFD_SUCCESS;
01444     int i;
01445     int initFlag;
01446 
01447     initFlag = 0;
01448 
01449     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01450     {
01451         /* If the library is loaded and the event handler is not running */
01452         if ( ((sReadersContexts[i])->vHandle != 0) &&
01453             ((sReadersContexts[i])->pthThread == 0) )
01454         {
01455             int j;
01456 
01457             for (j=0; j < i; j++)
01458             {
01459                 if (((sReadersContexts[j])->vHandle == (sReadersContexts[i])->vHandle)&&
01460                     ((sReadersContexts[j])->port == (sReadersContexts[i])->port))
01461                 {
01462                     initFlag = 1;
01463                 }
01464             }
01465 
01466             if (initFlag == 0)
01467                 rv = IFDOpenIFD(sReadersContexts[i]);
01468             else
01469                 initFlag = 0;
01470 
01471             if (rv != IFD_SUCCESS)
01472             {
01473                 Log3(PCSC_LOG_ERROR, "Open Port %X Failed (%s)",
01474                     (sReadersContexts[i])->port, (sReadersContexts[i])->lpcDevice);
01475             }
01476 
01477             (void)EHSpawnEventHandler(sReadersContexts[i], NULL);
01478             (void)RFSetReaderEventState(sReadersContexts[i], SCARD_RESET);
01479         }
01480     }
01481 }
01482 #endif
01483