2
* MUSCLE SmartCard Development ( http://www.linuxnet.com )
4
* Copyright (C) 1999-2004
5
* David Corcoran <corcoran@linuxnet.com>
6
* Damien Sauveron <damien.sauveron@labri.fr>
7
* Ludovic Rousseau <ludovic.rousseau@free.fr>
9
* $Id: readerfactory.c 1722 2005-11-21 13:05:20Z rousseau $
14
* @brief This keeps track of a list of currently available reader structures.
22
#include <sys/types.h>
28
#include "ifdhandler.h"
30
#include "thread_generic.h"
31
#include "readerfactory.h"
32
#include "dyn_generic.h"
33
#include "sys_generic.h"
34
#include "eventhandler.h"
35
#include "ifdwrapper.h"
37
#include "strlcpycat.h"
38
#include "configfile.h"
45
static PREADER_CONTEXT sReadersContexts[PCSCLITE_MAX_READERS_CONTEXTS];
46
static DWORD dwNumReadersContexts = 0;
47
static char *ConfigFile = NULL;
48
static int ConfigFileCRC = 0;
50
LONG RFAllocateReaderSpace(void)
55
* Allocate each reader structure
57
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
59
sReadersContexts[i] = (PREADER_CONTEXT) malloc(sizeof(READER_CONTEXT));
60
(sReadersContexts[i])->vHandle = NULL;
61
(sReadersContexts[i])->readerState = NULL;
65
* Create public event structures
67
return EHInitializeEventStructures();
70
LONG RFAddReader(LPTSTR lpcReader, DWORD dwPort, LPTSTR lpcLibrary, LPTSTR lpcDevice)
72
DWORD dwContext = 0, dwGetSize;
73
UCHAR ucGetData[1], ucThread[1];
77
if ((lpcReader == NULL) || (lpcLibrary == NULL) || (lpcDevice == NULL))
78
return SCARD_E_INVALID_VALUE;
80
/* Reader name too long? */
81
if (strlen(lpcReader) >= MAX_READERNAME)
83
Log3(PCSC_LOG_ERROR, "Reader name too long: %d chars instead of max %d",
84
strlen(lpcReader), MAX_READERNAME);
85
return SCARD_E_INVALID_VALUE;
88
/* Library name too long? */
89
if (strlen(lpcLibrary) >= MAX_LIBNAME)
91
Log3(PCSC_LOG_ERROR, "Library name too long: %d chars instead of max %d",
92
strlen(lpcLibrary), MAX_LIBNAME);
93
return SCARD_E_INVALID_VALUE;
96
/* Device name too long? */
97
if (strlen(lpcDevice) >= MAX_DEVICENAME)
99
Log3(PCSC_LOG_ERROR, "Device name too long: %d chars instead of max %d",
100
strlen(lpcDevice), MAX_DEVICENAME);
101
return SCARD_E_INVALID_VALUE;
105
* Same name, same port - duplicate reader cannot be used
107
if (dwNumReadersContexts != 0)
109
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
111
if ((sReadersContexts[i])->vHandle != 0)
113
char lpcStripReader[MAX_READERNAME];
116
/* get the reader name without the reader and slot numbers */
117
strncpy(lpcStripReader, (sReadersContexts[i])->lpcReader,
118
sizeof(lpcStripReader));
119
tmplen = strlen(lpcStripReader);
120
lpcStripReader[tmplen - 6] = 0;
122
if ((strcmp(lpcReader, lpcStripReader) == 0) &&
123
(dwPort == (sReadersContexts[i])->dwPort))
125
Log1(PCSC_LOG_ERROR, "Duplicate reader found.");
126
return SCARD_E_DUPLICATE_READER;
133
* We must find an empty slot to put the reader structure
135
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
137
if ((sReadersContexts[i])->vHandle == 0)
144
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
147
* No more spots left return
149
return SCARD_E_NO_MEMORY;
153
* Check and set the readername to see if it must be enumerated
155
parentNode = RFSetReaderName(sReadersContexts[dwContext], lpcReader,
156
lpcLibrary, dwPort, 0);
158
strlcpy((sReadersContexts[dwContext])->lpcLibrary, lpcLibrary,
159
sizeof((sReadersContexts[dwContext])->lpcLibrary));
160
strlcpy((sReadersContexts[dwContext])->lpcDevice, lpcDevice,
161
sizeof((sReadersContexts[dwContext])->lpcDevice));
162
(sReadersContexts[dwContext])->dwVersion = 0;
163
(sReadersContexts[dwContext])->dwPort = dwPort;
164
(sReadersContexts[dwContext])->mMutex = 0;
165
(sReadersContexts[dwContext])->dwBlockStatus = 0;
166
(sReadersContexts[dwContext])->dwContexts = 0;
167
(sReadersContexts[dwContext])->pthThread = 0;
168
(sReadersContexts[dwContext])->dwLockId = 0;
169
(sReadersContexts[dwContext])->vHandle = 0;
170
(sReadersContexts[dwContext])->pdwFeeds = NULL;
171
(sReadersContexts[dwContext])->pdwMutex = NULL;
172
(sReadersContexts[dwContext])->dwIdentity =
173
(dwContext + 1) << (sizeof(DWORD) / 2) * 8;
174
(sReadersContexts[dwContext])->readerState = NULL;
176
for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
177
(sReadersContexts[dwContext])->psHandles[i].hCard = 0;
180
* If a clone to this reader exists take some values from that clone
182
if (parentNode >= 0 && parentNode < PCSCLITE_MAX_READERS_CONTEXTS)
184
(sReadersContexts[dwContext])->pdwFeeds =
185
(sReadersContexts[parentNode])->pdwFeeds;
186
*(sReadersContexts[dwContext])->pdwFeeds += 1;
187
(sReadersContexts[dwContext])->vHandle =
188
(sReadersContexts[parentNode])->vHandle;
189
(sReadersContexts[dwContext])->mMutex =
190
(sReadersContexts[parentNode])->mMutex;
191
(sReadersContexts[dwContext])->pdwMutex =
192
(sReadersContexts[parentNode])->pdwMutex;
195
* Call on the driver to see if it is thread safe
197
dwGetSize = sizeof(ucThread);
198
rv = IFDGetCapabilities((sReadersContexts[parentNode]),
199
TAG_IFD_THREAD_SAFE, &dwGetSize, ucThread);
201
if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
203
Log1(PCSC_LOG_INFO, "Driver is thread safe");
204
(sReadersContexts[dwContext])->mMutex = 0;
205
(sReadersContexts[dwContext])->pdwMutex = NULL;
208
*(sReadersContexts[dwContext])->pdwMutex += 1;
211
if ((sReadersContexts[dwContext])->pdwFeeds == NULL)
213
(sReadersContexts[dwContext])->pdwFeeds =
214
(DWORD *)malloc(sizeof(DWORD));
216
/* Initialize pdwFeeds to 1, otherwise multiple
217
cloned readers will cause pcscd to crash when
218
RFUnloadReader unloads the driver library
219
and there are still devices attached using it --mikeg*/
221
*(sReadersContexts[dwContext])->pdwFeeds = 1;
224
if ((sReadersContexts[dwContext])->mMutex == 0)
226
(sReadersContexts[dwContext])->mMutex =
227
(PCSCLITE_MUTEX_T) malloc(sizeof(PCSCLITE_MUTEX));
228
SYS_MutexInit((sReadersContexts[dwContext])->mMutex);
231
if ((sReadersContexts[dwContext])->pdwMutex == NULL)
233
(sReadersContexts[dwContext])->pdwMutex =
234
(DWORD *)malloc(sizeof(DWORD));
236
*(sReadersContexts[dwContext])->pdwMutex = 1;
239
dwNumReadersContexts += 1;
241
rv = RFInitializeReader(sReadersContexts[dwContext]);
242
if (rv != SCARD_S_SUCCESS)
245
* Cannot connect to reader exit gracefully
248
* Clean up so it is not using needed space
250
Log2(PCSC_LOG_ERROR, "%s init failed.", lpcReader);
252
(sReadersContexts[dwContext])->dwVersion = 0;
253
(sReadersContexts[dwContext])->dwPort = 0;
254
(sReadersContexts[dwContext])->vHandle = 0;
255
(sReadersContexts[dwContext])->readerState = NULL;
256
(sReadersContexts[dwContext])->dwIdentity = 0;
259
* Destroy and free the mutex
261
if (*(sReadersContexts[dwContext])->pdwMutex == 1)
263
SYS_MutexDestroy((sReadersContexts[dwContext])->mMutex);
264
free((sReadersContexts[dwContext])->mMutex);
267
*(sReadersContexts[dwContext])->pdwMutex -= 1;
269
if (*(sReadersContexts[dwContext])->pdwMutex == 0)
271
free((sReadersContexts[dwContext])->pdwMutex);
272
(sReadersContexts[dwContext])->pdwMutex = NULL;
275
*(sReadersContexts[dwContext])->pdwFeeds -= 1;
277
if (*(sReadersContexts[dwContext])->pdwFeeds == 0)
279
free((sReadersContexts[dwContext])->pdwFeeds);
280
(sReadersContexts[dwContext])->pdwFeeds = NULL;
283
dwNumReadersContexts -= 1;
288
rv = EHSpawnEventHandler(sReadersContexts[dwContext]);
289
if (rv != SCARD_S_SUCCESS)
293
* Call on the driver to see if there are multiple slots
296
dwGetSize = sizeof(ucGetData);
297
rv = IFDGetCapabilities((sReadersContexts[dwContext]),
298
TAG_IFD_SLOTS_NUMBER, &dwGetSize, ucGetData);
300
if (rv != IFD_SUCCESS || dwGetSize != 1 || ucGetData[0] == 0)
302
* Reader does not have this defined. Must be a single slot
303
* reader so we can just return SCARD_S_SUCCESS.
305
return SCARD_S_SUCCESS;
307
if (rv == IFD_SUCCESS && dwGetSize == 1 && ucGetData[0] == 1)
309
* Reader has this defined and it only has one slot
311
return SCARD_S_SUCCESS;
314
* Check the number of slots and create a different
315
* structure for each one accordingly
319
* Initialize the rest of the slots
322
for (j = 1; j < ucGetData[0]; j++)
324
char *tmpReader = NULL;
325
DWORD dwContextB = 0;
328
* We must find an empty spot to put the
331
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
333
if ((sReadersContexts[i])->vHandle == 0)
340
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
343
* No more spots left return
345
rv = RFRemoveReader(lpcReader, dwPort);
346
return SCARD_E_NO_MEMORY;
350
* Copy the previous reader name and increment the slot number
352
tmpReader = sReadersContexts[dwContextB]->lpcReader;
353
strlcpy(tmpReader, sReadersContexts[dwContext]->lpcReader,
354
sizeof(sReadersContexts[dwContextB]->lpcReader));
355
sprintf(tmpReader + strlen(tmpReader) - 2, "%02X", j);
357
strlcpy((sReadersContexts[dwContextB])->lpcLibrary, lpcLibrary,
358
sizeof((sReadersContexts[dwContextB])->lpcLibrary));
359
strlcpy((sReadersContexts[dwContextB])->lpcDevice, lpcDevice,
360
sizeof((sReadersContexts[dwContextB])->lpcDevice));
361
(sReadersContexts[dwContextB])->dwVersion =
362
(sReadersContexts[dwContext])->dwVersion;
363
(sReadersContexts[dwContextB])->dwPort =
364
(sReadersContexts[dwContext])->dwPort;
365
(sReadersContexts[dwContextB])->vHandle =
366
(sReadersContexts[dwContext])->vHandle;
367
(sReadersContexts[dwContextB])->mMutex =
368
(sReadersContexts[dwContext])->mMutex;
369
(sReadersContexts[dwContextB])->pdwMutex =
370
(sReadersContexts[dwContext])->pdwMutex;
371
sReadersContexts[dwContextB]->dwSlot =
372
sReadersContexts[dwContext]->dwSlot + j;
375
* Added by Dave - slots did not have a pdwFeeds
376
* parameter so it was by luck they were working
379
(sReadersContexts[dwContextB])->pdwFeeds =
380
(sReadersContexts[dwContext])->pdwFeeds;
382
/* Added by Dave for multiple slots */
383
*(sReadersContexts[dwContextB])->pdwFeeds += 1;
385
(sReadersContexts[dwContextB])->dwBlockStatus = 0;
386
(sReadersContexts[dwContextB])->dwContexts = 0;
387
(sReadersContexts[dwContextB])->dwLockId = 0;
388
(sReadersContexts[dwContextB])->readerState = NULL;
389
(sReadersContexts[dwContextB])->dwIdentity =
390
(dwContextB + 1) << (sizeof(DWORD) / 2) * 8;
392
for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
393
(sReadersContexts[dwContextB])->psHandles[i].hCard = 0;
396
* Call on the driver to see if the slots are thread safe
399
dwGetSize = sizeof(ucThread);
400
rv = IFDGetCapabilities((sReadersContexts[dwContext]),
401
TAG_IFD_SLOT_THREAD_SAFE, &dwGetSize, ucThread);
403
if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
405
(sReadersContexts[dwContextB])->mMutex =
406
(PCSCLITE_MUTEX_T) malloc(sizeof(PCSCLITE_MUTEX));
407
SYS_MutexInit((sReadersContexts[dwContextB])->mMutex);
409
(sReadersContexts[dwContextB])->pdwMutex =
410
(DWORD *)malloc(sizeof(DWORD));
411
*(sReadersContexts[dwContextB])->pdwMutex = 1;
414
*(sReadersContexts[dwContextB])->pdwMutex += 1;
416
dwNumReadersContexts += 1;
418
rv = RFInitializeReader(sReadersContexts[dwContextB]);
419
if (rv != SCARD_S_SUCCESS)
422
* Cannot connect to slot exit gracefully
425
* Clean up so it is not using needed space
427
Log2(PCSC_LOG_ERROR, "%s init failed.", lpcReader);
429
(sReadersContexts[dwContextB])->dwVersion = 0;
430
(sReadersContexts[dwContextB])->dwPort = 0;
431
(sReadersContexts[dwContextB])->vHandle = 0;
432
(sReadersContexts[dwContextB])->readerState = NULL;
433
(sReadersContexts[dwContextB])->dwIdentity = 0;
436
* Destroy and free the mutex
438
if (*(sReadersContexts[dwContextB])->pdwMutex == 1)
440
SYS_MutexDestroy((sReadersContexts[dwContextB])->mMutex);
441
free((sReadersContexts[dwContextB])->mMutex);
444
*(sReadersContexts[dwContextB])->pdwMutex -= 1;
446
if (*(sReadersContexts[dwContextB])->pdwMutex == 0)
448
free((sReadersContexts[dwContextB])->pdwMutex);
449
(sReadersContexts[dwContextB])->pdwMutex = NULL;
452
*(sReadersContexts[dwContextB])->pdwFeeds -= 1;
454
if (*(sReadersContexts[dwContextB])->pdwFeeds == 0)
456
free((sReadersContexts[dwContextB])->pdwFeeds);
457
(sReadersContexts[dwContextB])->pdwFeeds = NULL;
460
dwNumReadersContexts -= 1;
465
EHSpawnEventHandler(sReadersContexts[dwContextB]);
468
return SCARD_S_SUCCESS;
471
LONG RFRemoveReader(LPTSTR lpcReader, DWORD dwPort)
474
PREADER_CONTEXT sContext;
477
return SCARD_E_INVALID_VALUE;
479
while ((rv = RFReaderInfoNamePort(dwPort, lpcReader, &sContext))
485
* Try to destroy the thread
487
rv = EHDestroyEventHandler(sContext);
489
rv = RFUnInitializeReader(sContext);
490
if (rv != SCARD_S_SUCCESS)
494
* Destroy and free the mutex
496
if ((NULL == sContext->pdwMutex) || (NULL == sContext->pdwFeeds))
499
"Trying to remove an already removed driver");
500
return SCARD_E_INVALID_VALUE;
503
if (*sContext->pdwMutex == 1)
505
SYS_MutexDestroy(sContext->mMutex);
506
free(sContext->mMutex);
509
*sContext->pdwMutex -= 1;
511
if (*sContext->pdwMutex == 0)
513
free(sContext->pdwMutex);
514
sContext->pdwMutex = NULL;
517
*sContext->pdwFeeds -= 1;
519
/* Added by Dave to free the pdwFeeds variable */
521
if (*sContext->pdwFeeds == 0)
523
free(sContext->pdwFeeds);
524
sContext->pdwFeeds = NULL;
527
sContext->lpcDevice[0] = 0;
528
sContext->dwVersion = 0;
529
sContext->dwPort = 0;
530
sContext->mMutex = 0;
531
sContext->dwBlockStatus = 0;
532
sContext->dwContexts = 0;
533
sContext->dwSlot = 0;
534
sContext->dwLockId = 0;
535
sContext->vHandle = 0;
536
sContext->dwIdentity = 0;
537
sContext->readerState = NULL;
539
for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
540
sContext->psHandles[i].hCard = 0;
542
dwNumReadersContexts -= 1;
545
return SCARD_S_SUCCESS;
548
LONG RFSetReaderName(PREADER_CONTEXT rContext, LPTSTR readerName,
549
LPTSTR libraryName, DWORD dwPort, DWORD dwSlot)
551
LONG parent = -1; /* reader number of the parent of the clone */
553
int currentDigit = -1;
554
int supportedChannels = 0;
555
int usedDigits[PCSCLITE_MAX_READERS_CONTEXTS];
561
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
562
usedDigits[i] = FALSE;
564
if ((0 == dwSlot) && (dwNumReadersContexts != 0))
566
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
568
if ((sReadersContexts[i])->vHandle != 0)
570
if (strcmp((sReadersContexts[i])->lpcLibrary, libraryName) == 0)
576
* Ask the driver if it supports multiple channels
578
valueLength = sizeof(tagValue);
579
ret = IFDGetCapabilities((sReadersContexts[i]),
580
TAG_IFD_SIMULTANEOUS_ACCESS,
581
&valueLength, tagValue);
583
if ((ret == IFD_SUCCESS) && (valueLength == 1) &&
586
supportedChannels = tagValue[0];
588
"Support %d simultaneous readers", tagValue[0]);
591
supportedChannels = -1;
594
* Check to see if it is a hotplug reader and
597
if (((((sReadersContexts[i])->dwPort & 0xFFFF0000) ==
598
PCSCLITE_HP_BASE_PORT)
599
&& ((sReadersContexts[i])->dwPort != dwPort))
600
|| (supportedChannels > 1))
602
char *lpcReader = sReadersContexts[i]->lpcReader;
605
* tells the caller who the parent of this
606
* clone is so it can use it's shared
607
* resources like mutex/etc.
612
* If the same reader already exists and it is
613
* hotplug then we must look for others and
614
* enumerate the readername
616
currentDigit = strtol(lpcReader + strlen(lpcReader) - 5, NULL, 16);
621
usedDigits[currentDigit] = TRUE;
632
/* Other identical readers exist on the same bus */
633
if (currentDigit != -1)
635
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
637
/* get the first free digit */
638
if (usedDigits[i] == FALSE)
642
if ((i == PCSCLITE_MAX_READERS_CONTEXTS) || (i > supportedChannels))
646
sprintf(rContext->lpcReader, "%s %02X %02lX", readerName, i, dwSlot);
649
* Set the slot in 0xDDDDCCCC
651
rContext->dwSlot = (i << 16) + dwSlot;
657
LONG RFListReaders(LPTSTR lpcReaders, LPDWORD pdwReaderNum)
663
if (dwNumReadersContexts == 0)
664
return SCARD_E_READER_UNAVAILABLE;
667
* Ignore the groups for now, return all readers
672
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
674
if ((sReadersContexts[i])->vHandle != 0)
676
dwCSize += strlen((sReadersContexts[i])->lpcReader) + 1;
681
if (p > dwNumReadersContexts)
683
* We are severely hosed here
686
* Hopefully this will never be true
688
return SCARD_F_UNKNOWN_ERROR;
691
* Added for extra NULL byte on MultiString
696
* If lpcReaders is not allocated then just
699
* return the amount needed to allocate
703
*pdwReaderNum = dwCSize;
704
return SCARD_S_SUCCESS;
707
if (*pdwReaderNum < dwCSize)
708
return SCARD_E_INSUFFICIENT_BUFFER;
710
*pdwReaderNum = dwCSize;
711
lpcTReaders = lpcReaders;
715
* Creating MultiString
717
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
719
if ((sReadersContexts[i])->vHandle != 0)
721
strcpy(&lpcTReaders[p], (sReadersContexts[i])->lpcReader);
722
p += strlen((sReadersContexts[i])->lpcReader); /* Copy */
723
lpcTReaders[p] = 0; /* Add NULL */
724
p += 1; /* Move on */
728
lpcTReaders[p] = 0; /* Add NULL */
730
return SCARD_S_SUCCESS;
734
LONG RFReaderInfo(LPTSTR lpcReader, PREADER_CONTEXT * sReader)
739
return SCARD_E_UNKNOWN_READER;
741
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
743
if ((sReadersContexts[i])->vHandle != 0)
745
if (strcmp(lpcReader, (sReadersContexts[i])->lpcReader) == 0)
747
*sReader = sReadersContexts[i];
748
return SCARD_S_SUCCESS;
753
return SCARD_E_UNKNOWN_READER;
756
LONG RFReaderInfoNamePort(DWORD dwPort, LPTSTR lpcReader,
757
PREADER_CONTEXT * sReader)
759
char lpcStripReader[MAX_READERNAME];
762
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
764
if ((sReadersContexts[i])->vHandle != 0)
768
strncpy(lpcStripReader, (sReadersContexts[i])->lpcReader,
769
sizeof(lpcStripReader));
770
tmplen = strlen(lpcStripReader);
771
lpcStripReader[tmplen - 6] = 0;
773
if ((strcmp(lpcReader, lpcStripReader) == 0) &&
774
(dwPort == (sReadersContexts[i])->dwPort))
776
*sReader = sReadersContexts[i];
777
return SCARD_S_SUCCESS;
782
return SCARD_E_INVALID_VALUE;
785
LONG RFReaderInfoById(DWORD dwIdentity, PREADER_CONTEXT * sReader)
790
* Strip off the lower nibble and get the identity
792
dwIdentity = dwIdentity >> (sizeof(DWORD) / 2) * 8;
793
dwIdentity = dwIdentity << (sizeof(DWORD) / 2) * 8;
795
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
797
if (dwIdentity == (sReadersContexts[i])->dwIdentity)
799
*sReader = sReadersContexts[i];
800
return SCARD_S_SUCCESS;
804
return SCARD_E_INVALID_VALUE;
807
LONG RFLoadReader(PREADER_CONTEXT rContext)
809
if (rContext->vHandle != 0)
811
Log1(PCSC_LOG_ERROR, "Warning library pointer not NULL");
813
* Another reader exists with this library loaded
815
return SCARD_S_SUCCESS;
818
return DYN_LoadLibrary(&rContext->vHandle, rContext->lpcLibrary);
821
LONG RFBindFunctions(PREADER_CONTEXT rContext)
826
* Use this function as a dummy to determine the IFD Handler version
827
* type 1.0/2.0/3.0. Suppress error messaging since it can't be 1.0,
831
DebugLogSuppress(DEBUGLOG_IGNORE_ENTRIES);
833
rv1 = DYN_GetAddress(rContext->vHandle,
834
(void **)&rContext->psFunctions.psFunctions_v1.pvfCreateChannel,
835
"IO_Create_Channel");
837
rv2 = DYN_GetAddress(rContext->vHandle,
838
(void **)&rContext->psFunctions.psFunctions_v2.pvfCreateChannel,
839
"IFDHCreateChannel");
841
rv3 = DYN_GetAddress(rContext->vHandle,
842
(void **)&rContext->psFunctions.psFunctions_v3.pvfCreateChannelByName,
843
"IFDHCreateChannelByName");
845
DebugLogSuppress(DEBUGLOG_LOG_ENTRIES);
847
if (rv1 != SCARD_S_SUCCESS && rv2 != SCARD_S_SUCCESS && rv3 != SCARD_S_SUCCESS)
850
* Neither version of the IFD Handler was found - exit
852
Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing");
855
} else if (rv1 == SCARD_S_SUCCESS)
858
* Ifd Handler 1.0 found
860
rContext->dwVersion = IFD_HVERSION_1_0;
861
} else if (rv3 == SCARD_S_SUCCESS)
864
* Ifd Handler 3.0 found
866
rContext->dwVersion = IFD_HVERSION_3_0;
871
* Ifd Handler 2.0 found
873
rContext->dwVersion = IFD_HVERSION_2_0;
877
* The following binds version 1.0 of the IFD Handler specs
880
if (rContext->dwVersion == IFD_HVERSION_1_0)
882
Log1(PCSC_LOG_INFO, "Loading IFD Handler 1.0");
884
#define GET_ADDRESS_OPTIONALv1(field, function, code) \
886
if (SCARD_S_SUCCESS != DYN_GetAddress(rContext->vHandle, (void **)&rContext->psFunctions.psFunctions_v1.pvf ## field, "IFD_" #function)) \
888
rContext->psFunctions.psFunctions_v1.pvf ## field = NULL; \
893
#define GET_ADDRESSv1(field, function) \
894
GET_ADDRESS_OPTIONALv1(field, function, \
895
Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #function ); \
898
DYN_GetAddress(rContext->vHandle,
899
(void **)&rContext->psFunctions.psFunctions_v1.pvfCreateChannel,
900
"IO_Create_Channel");
902
if (SCARD_S_SUCCESS != DYN_GetAddress(rContext->vHandle,
903
(void **)&rContext->psFunctions.psFunctions_v1.pvfCloseChannel,
906
rContext->psFunctions.psFunctions_v1.pvfCloseChannel = NULL;
907
Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing");
911
GET_ADDRESSv1(GetCapabilities, Get_Capabilities)
912
GET_ADDRESSv1(SetCapabilities, Set_Capabilities)
913
GET_ADDRESSv1(PowerICC, Power_ICC)
914
GET_ADDRESSv1(TransmitToICC, Transmit_to_ICC)
915
GET_ADDRESSv1(ICCPresence, Is_ICC_Present)
917
GET_ADDRESS_OPTIONALv1(SetProtocolParameters, Set_Protocol_Parameters, )
919
else if (rContext->dwVersion == IFD_HVERSION_2_0)
922
* The following binds version 2.0 of the IFD Handler specs
925
#define GET_ADDRESS_OPTIONALv2(s, code) \
927
if (SCARD_S_SUCCESS != DYN_GetAddress(rContext->vHandle, (void **)&rContext->psFunctions.psFunctions_v2.pvf ## s, "IFDH" #s)) \
929
rContext->psFunctions.psFunctions_v2.pvf ## s = NULL; \
934
#define GET_ADDRESSv2(s) \
935
GET_ADDRESS_OPTIONALv2(s, \
936
Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
939
Log1(PCSC_LOG_INFO, "Loading IFD Handler 2.0");
941
GET_ADDRESSv2(CloseChannel)
942
GET_ADDRESSv2(GetCapabilities)
943
GET_ADDRESSv2(SetCapabilities)
944
GET_ADDRESSv2(PowerICC)
945
GET_ADDRESSv2(TransmitToICC)
946
GET_ADDRESSv2(ICCPresence)
947
GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
949
GET_ADDRESSv2(Control)
951
else if (rContext->dwVersion == IFD_HVERSION_3_0)
954
* The following binds version 3.0 of the IFD Handler specs
957
#define GET_ADDRESS_OPTIONALv3(s, code) \
959
if (SCARD_S_SUCCESS != DYN_GetAddress(rContext->vHandle, (void **)&rContext->psFunctions.psFunctions_v3.pvf ## s, "IFDH" #s)) \
961
rContext->psFunctions.psFunctions_v3.pvf ## s = NULL; \
966
#define GET_ADDRESSv3(s) \
967
GET_ADDRESS_OPTIONALv3(s, \
968
Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
971
Log1(PCSC_LOG_INFO, "Loading IFD Handler 3.0");
973
GET_ADDRESSv2(CloseChannel)
974
GET_ADDRESSv2(GetCapabilities)
975
GET_ADDRESSv2(SetCapabilities)
976
GET_ADDRESSv2(PowerICC)
977
GET_ADDRESSv2(TransmitToICC)
978
GET_ADDRESSv2(ICCPresence)
979
GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
981
GET_ADDRESSv3(Control)
986
* Who knows what could have happenned for it to get here.
988
Log1(PCSC_LOG_CRITICAL, "IFD Handler not 1.0/2.0 or 3.0");
992
return SCARD_S_SUCCESS;
995
LONG RFUnBindFunctions(PREADER_CONTEXT rContext)
998
* Zero out everything
1001
memset(&rContext->psFunctions, 0, sizeof(rContext->psFunctions));
1003
return SCARD_S_SUCCESS;
1006
LONG RFUnloadReader(PREADER_CONTEXT rContext)
1009
* Make sure no one else is using this library
1012
if (*rContext->pdwFeeds == 1)
1014
Log1(PCSC_LOG_INFO, "Unloading reader driver.");
1015
DYN_CloseLibrary(&rContext->vHandle);
1018
rContext->vHandle = 0;
1020
return SCARD_S_SUCCESS;
1023
LONG RFCheckSharing(DWORD hCard)
1026
PREADER_CONTEXT rContext = NULL;
1028
rv = RFReaderInfoById(hCard, &rContext);
1030
if (rv != SCARD_S_SUCCESS)
1033
if (rContext->dwLockId == 0 || rContext->dwLockId == hCard)
1034
return SCARD_S_SUCCESS;
1036
return SCARD_E_SHARING_VIOLATION;
1040
LONG RFLockSharing(DWORD hCard)
1042
PREADER_CONTEXT rContext = NULL;
1044
RFReaderInfoById(hCard, &rContext);
1046
if (RFCheckSharing(hCard) == SCARD_S_SUCCESS)
1048
EHSetSharingEvent(rContext, 1);
1049
rContext->dwLockId = hCard;
1052
return SCARD_E_SHARING_VIOLATION;
1054
return SCARD_S_SUCCESS;
1057
LONG RFUnlockSharing(DWORD hCard)
1059
PREADER_CONTEXT rContext = NULL;
1061
RFReaderInfoById(hCard, &rContext);
1063
if (RFCheckSharing(hCard) == SCARD_S_SUCCESS)
1065
EHSetSharingEvent(rContext, 0);
1066
rContext->dwLockId = 0;
1069
return SCARD_E_SHARING_VIOLATION;
1071
return SCARD_S_SUCCESS;
1074
LONG RFUnblockContext(SCARDCONTEXT hContext)
1078
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1079
(sReadersContexts[i])->dwBlockStatus = hContext;
1081
return SCARD_S_SUCCESS;
1084
LONG RFUnblockReader(PREADER_CONTEXT rContext)
1086
rContext->dwBlockStatus = BLOCK_STATUS_RESUME;
1087
return SCARD_S_SUCCESS;
1090
LONG RFInitializeReader(PREADER_CONTEXT rContext)
1095
* Spawn the event handler thread
1097
Log2(PCSC_LOG_INFO, "Attempting startup of %s.", rContext->lpcReader);
1099
/******************************************/
1101
* This section loads the library
1103
/******************************************/
1104
rv = RFLoadReader(rContext);
1105
if (rv != SCARD_S_SUCCESS)
1108
/*******************************************/
1110
* This section binds the functions
1112
/*******************************************/
1113
rv = RFBindFunctions(rContext);
1115
if (rv != SCARD_S_SUCCESS)
1117
RFUnloadReader(rContext);
1121
/*******************************************/
1123
* This section tries to open the port
1125
/*******************************************/
1127
rv = IFDOpenIFD(rContext);
1129
if (rv != IFD_SUCCESS)
1131
Log3(PCSC_LOG_CRITICAL, "Open Port %X Failed (%s)",
1132
rContext->dwPort, rContext->lpcDevice);
1133
RFUnBindFunctions(rContext);
1134
RFUnloadReader(rContext);
1135
return SCARD_E_INVALID_TARGET;
1138
return SCARD_S_SUCCESS;
1141
LONG RFUnInitializeReader(PREADER_CONTEXT rContext)
1143
Log2(PCSC_LOG_INFO, "Attempting shutdown of %s.",
1144
rContext->lpcReader);
1147
* Close the port, unbind the functions, and unload the library
1151
* If the reader is getting uninitialized then it is being unplugged
1152
* so I can't send a IFDPowerICC call to it
1154
* IFDPowerICC( rContext, IFD_POWER_DOWN, Atr, &AtrLen );
1156
IFDCloseIFD(rContext);
1157
RFUnBindFunctions(rContext);
1158
RFUnloadReader(rContext);
1160
return SCARD_S_SUCCESS;
1163
SCARDHANDLE RFCreateReaderHandle(PREADER_CONTEXT rContext)
1168
* Create a random handle with 16 bits check to see if it already is
1171
randHandle = SYS_RandomInt(10, 65000);
1177
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1179
if ((sReadersContexts[i])->vHandle != 0)
1183
for (j = 0; j < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; j++)
1185
if ((rContext->dwIdentity + randHandle) ==
1186
(sReadersContexts[i])->psHandles[j].hCard)
1189
* Get a new handle and loop again
1191
randHandle = SYS_RandomInt(10, 65000);
1199
* Once the for loop is completed w/o restart a good handle was
1200
* found and the loop can be exited.
1203
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1207
return rContext->dwIdentity + randHandle;
1210
LONG RFFindReaderHandle(SCARDHANDLE hCard)
1214
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1216
if ((sReadersContexts[i])->vHandle != 0)
1220
for (j = 0; j < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; j++)
1222
if (hCard == (sReadersContexts[i])->psHandles[j].hCard)
1223
return SCARD_S_SUCCESS;
1228
return SCARD_E_INVALID_HANDLE;
1231
LONG RFDestroyReaderHandle(SCARDHANDLE hCard)
1233
return SCARD_S_SUCCESS;
1236
LONG RFAddReaderHandle(PREADER_CONTEXT rContext, SCARDHANDLE hCard)
1240
for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
1242
if (rContext->psHandles[i].hCard == 0)
1244
rContext->psHandles[i].hCard = hCard;
1245
rContext->psHandles[i].dwEventStatus = 0;
1250
if (i == PCSCLITE_MAX_READER_CONTEXT_CHANNELS)
1252
return SCARD_E_INSUFFICIENT_BUFFER;
1254
return SCARD_S_SUCCESS;
1257
LONG RFRemoveReaderHandle(PREADER_CONTEXT rContext, SCARDHANDLE hCard)
1261
for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
1263
if (rContext->psHandles[i].hCard == hCard)
1265
rContext->psHandles[i].hCard = 0;
1266
rContext->psHandles[i].dwEventStatus = 0;
1271
if (i == PCSCLITE_MAX_READER_CONTEXT_CHANNELS)
1273
return SCARD_E_INVALID_HANDLE;
1275
return SCARD_S_SUCCESS;
1278
LONG RFSetReaderEventState(PREADER_CONTEXT rContext, DWORD dwEvent)
1283
* Set all the handles for that reader to the event
1285
for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
1287
if (rContext->psHandles[i].hCard != 0)
1288
rContext->psHandles[i].dwEventStatus = dwEvent;
1291
return SCARD_S_SUCCESS;
1294
LONG RFCheckReaderEventState(PREADER_CONTEXT rContext, SCARDHANDLE hCard)
1298
for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
1300
if (rContext->psHandles[i].hCard == hCard)
1302
if (rContext->psHandles[i].dwEventStatus == SCARD_REMOVED)
1303
return SCARD_W_REMOVED_CARD;
1306
if (rContext->psHandles[i].dwEventStatus == SCARD_RESET)
1307
return SCARD_W_RESET_CARD;
1310
if (rContext->psHandles[i].dwEventStatus == 0)
1311
return SCARD_S_SUCCESS;
1313
return SCARD_E_INVALID_VALUE;
1319
return SCARD_E_INVALID_HANDLE;
1322
LONG RFClearReaderEventState(PREADER_CONTEXT rContext, SCARDHANDLE hCard)
1326
for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
1328
if (rContext->psHandles[i].hCard == hCard)
1329
rContext->psHandles[i].dwEventStatus = 0;
1332
if (i == PCSCLITE_MAX_READER_CONTEXT_CHANNELS)
1334
return SCARD_E_INVALID_HANDLE;
1336
return SCARD_S_SUCCESS;
1339
LONG RFCheckReaderStatus(PREADER_CONTEXT rContext)
1341
if ((rContext->readerState == NULL)
1342
|| (rContext->readerState->readerState & SCARD_UNKNOWN))
1343
return SCARD_E_READER_UNAVAILABLE;
1345
return SCARD_S_SUCCESS;
1348
void RFCleanupReaders(int shouldExit)
1352
Log1(PCSC_LOG_INFO, "entering cleaning function");
1353
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1355
if (sReadersContexts[i]->vHandle != 0)
1358
char lpcStripReader[MAX_READERNAME];
1360
Log2(PCSC_LOG_INFO, "Stopping reader: %s",
1361
sReadersContexts[i]->lpcReader);
1363
strncpy(lpcStripReader, (sReadersContexts[i])->lpcReader,
1364
sizeof(lpcStripReader));
1366
* strip the 6 last char ' 00 00'
1368
lpcStripReader[strlen(lpcStripReader) - 6] = '\0';
1370
rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->dwPort);
1372
if (rv != SCARD_S_SUCCESS)
1373
Log2(PCSC_LOG_ERROR, "RFRemoveReader error: %s",
1374
pcsc_stringify_error(rv));
1379
* exit() will call at_exit()
1386
int RFStartSerialReaders(char *readerconf)
1388
SerialReader *reader_list;
1391
/* remember the ocnfiguration filename for RFReCheckReaderConf() */
1392
ConfigFile = strdup(readerconf);
1394
rv = DBGetReaderList(readerconf, &reader_list);
1396
/* the list is empty */
1397
if (NULL == reader_list)
1400
for (i=0; reader_list[i].pcFriendlyname; i++)
1404
RFAddReader(reader_list[i].pcFriendlyname, reader_list[i].dwChannelId,
1405
reader_list[i].pcLibpath, reader_list[i].pcDevicename);
1407
/* update the ConfigFileCRC (this false "CRC" is very weak) */
1408
for (j=0; j<reader_list[i].pcFriendlyname[j]; j++)
1409
ConfigFileCRC += reader_list[i].pcFriendlyname[j];
1410
for (j=0; j<reader_list[i].pcLibpath[j]; j++)
1411
ConfigFileCRC += reader_list[i].pcLibpath[j];
1412
for (j=0; j<reader_list[i].pcDevicename[j]; j++)
1413
ConfigFileCRC += reader_list[i].pcDevicename[j];
1415
/* free strings allocated by DBGetReaderList() */
1416
free(reader_list[i].pcFriendlyname);
1417
free(reader_list[i].pcLibpath);
1418
free(reader_list[i].pcDevicename);
1425
void RFReCheckReaderConf(void)
1427
SerialReader *reader_list;
1430
DBGetReaderList(ConfigFile, &reader_list);
1432
/* the list is empty */
1433
if (NULL == reader_list)
1437
for (i=0; reader_list[i].pcFriendlyname; i++)
1441
/* calculate a local crc */
1442
for (j=0; j<reader_list[i].pcFriendlyname[j]; j++)
1443
crc += reader_list[i].pcFriendlyname[j];
1444
for (j=0; j<reader_list[i].pcLibpath[j]; j++)
1445
crc += reader_list[i].pcLibpath[j];
1446
for (j=0; j<reader_list[i].pcDevicename[j]; j++)
1447
crc += reader_list[i].pcDevicename[j];
1450
/* cancel if the configuration file has been modified */
1451
if (crc != ConfigFileCRC)
1453
Log2(PCSC_LOG_CRITICAL,
1454
"configuration file: %s has been modified. Recheck canceled",
1459
for (i=0; reader_list[i].pcFriendlyname; i++)
1462
char present = FALSE;
1464
Log2(PCSC_LOG_DEBUG, "refresh reader: %s",
1465
reader_list[i].pcFriendlyname);
1467
/* is the reader already present? */
1468
for (r = 0; r < PCSCLITE_MAX_READERS_CONTEXTS; r++)
1470
if (sReadersContexts[r]->vHandle != 0)
1472
char lpcStripReader[MAX_READERNAME];
1475
/* get the reader name without the reader and slot numbers */
1476
strncpy(lpcStripReader, sReadersContexts[i]->lpcReader,
1477
sizeof(lpcStripReader));
1478
tmplen = strlen(lpcStripReader);
1479
lpcStripReader[tmplen - 6] = 0;
1481
if ((strcmp(reader_list[i].pcFriendlyname, lpcStripReader) == 0)
1482
&& (reader_list[r].dwChannelId == sReadersContexts[i]->dwPort))
1484
DWORD dwStatus = 0, dwAtrLen = 0;
1485
UCHAR ucAtr[MAX_ATR_SIZE];
1487
/* the reader was already started */
1490
/* verify the reader is still connected */
1491
if (IFDStatusICC(sReadersContexts[r], &dwStatus, ucAtr,
1492
&dwAtrLen) != SCARD_S_SUCCESS)
1494
Log2(PCSC_LOG_INFO, "Reader %s disappeared",
1495
reader_list[i].pcFriendlyname);
1496
RFRemoveReader(reader_list[i].pcFriendlyname,
1497
reader_list[r].dwChannelId);
1503
/* the reader was not present */
1505
/* we try to add it */
1506
RFAddReader(reader_list[i].pcFriendlyname,
1507
reader_list[i].dwChannelId, reader_list[i].pcLibpath,
1508
reader_list[i].pcDevicename);
1510
/* free strings allocated by DBGetReaderList() */
1511
free(reader_list[i].pcFriendlyname);
1512
free(reader_list[i].pcLibpath);
1513
free(reader_list[i].pcDevicename);
1518
void RFSuspendAllReaders(void)
1522
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1524
if ((sReadersContexts[i])->vHandle != 0)
1526
EHDestroyEventHandler(sReadersContexts[i]);
1527
IFDCloseIFD(sReadersContexts[i]);
1533
void RFAwakeAllReaders(void)
1535
LONG rv = IFD_SUCCESS;
1541
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1543
/* If the library is loaded and the event handler is not running */
1544
if ( ((sReadersContexts[i])->vHandle != 0) &&
1545
((sReadersContexts[i])->pthThread == 0) )
1549
for (j=0; j < i; j++)
1551
if (((sReadersContexts[j])->vHandle == (sReadersContexts[i])->vHandle)&&
1552
((sReadersContexts[j])->dwPort == (sReadersContexts[i])->dwPort))
1559
rv = IFDOpenIFD(sReadersContexts[i]);
1563
if (rv != IFD_SUCCESS)
1565
Log3(PCSC_LOG_ERROR, "Open Port %X Failed (%s)",
1566
(sReadersContexts[i])->dwPort, (sReadersContexts[i])->lpcDevice);
1570
EHSpawnEventHandler(sReadersContexts[i]);
1571
RFSetReaderEventState(sReadersContexts[i], SCARD_RESET);