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