pcsc-lite 1.5.5

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