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

Generated on Thu Aug 28 20:14:58 2008 for pcsc-lite by  doxygen 1.5.6