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