65#include "configfile.h"
68#define INITIAL_MAX_READERS_CONTEXTS 2
70int pcsclite_max_reader_context = -1;
71READER_CONTEXT ** sReadersContexts;
72static int maxReaderHandles = PCSC_MAX_READER_HANDLES;
74static char *ConfigFile = NULL;
75static int ConfigFileCRC = 0;
77static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER;
78int16_t ReaderEvents = 1;
80static LONG removeReader(READER_CONTEXT * sReader);
82static int RDR_CLIHANDLES_seeker(
const void *el,
const void *key)
84 const RDR_CLIHANDLES *rdrCliHandles = el;
86 if ((el == NULL) || (key == NULL))
88 Log3(PCSC_LOG_CRITICAL,
89 "RDR_CLIHANDLES_seeker called with NULL pointer: el=%p, key=%p",
101LONG _RefReader(READER_CONTEXT * sReader)
111LONG _UnrefReader(READER_CONTEXT * sReader)
119 removeReader(sReader);
124LONG RFAllocateReaderSpace(
unsigned int customMaxReaderHandles)
128 if (customMaxReaderHandles != 0)
129 maxReaderHandles = customMaxReaderHandles;
131 pcsclite_max_reader_context = INITIAL_MAX_READERS_CONTEXTS;
132 sReadersContexts = calloc(pcsclite_max_reader_context,
sizeof(sReadersContexts[0]));
133 if (NULL == sReadersContexts)
137 for (i = 0; i < pcsclite_max_reader_context; i++)
139 sReadersContexts[i] = malloc(
sizeof(READER_CONTEXT));
140 sReadersContexts[i]->vHandle = NULL;
141 atomic_init(&sReadersContexts[i]->hLockId, 0);
142 atomic_init(&sReadersContexts[i]->contexts, 0);
143 atomic_init(&sReadersContexts[i]->reference, 0);
146 memset(sReadersContexts[i]->readerState.readerName, 0, MAX_READERNAME);
147 memset(sReadersContexts[i]->readerState.cardAtr, 0,
MAX_ATR_SIZE);
148 sReadersContexts[i]->readerState.eventCounter = 0;
149 sReadersContexts[i]->readerState.readerState = 0;
150 sReadersContexts[i]->readerState.readerSharing = 0;
156 return EHInitializeEventStructures();
159static LONG RFReAllocateReaderSpace(
void)
161 int new_size = pcsclite_max_reader_context + INITIAL_MAX_READERS_CONTEXTS;
163 Log3(PCSC_LOG_INFO,
"from %d to %d", pcsclite_max_reader_context, new_size);
165 sReadersContexts = realloc(sReadersContexts, new_size *
sizeof(sReadersContexts[0]));
168 for (
int i = pcsclite_max_reader_context; i < new_size; i++)
170 sReadersContexts[i] = malloc(
sizeof(READER_CONTEXT));
171 sReadersContexts[i]->vHandle = NULL;
172 atomic_init(&sReadersContexts[i]->hLockId, 0);
173 atomic_init(&sReadersContexts[i]->contexts, 0);
174 atomic_init(&sReadersContexts[i]->reference, 0);
177 memset(sReadersContexts[i]->readerState.readerName, 0, MAX_READERNAME);
178 memset(sReadersContexts[i]->readerState.cardAtr, 0,
MAX_ATR_SIZE);
179 sReadersContexts[i]->readerState.eventCounter = 0;
180 sReadersContexts[i]->readerState.readerState = 0;
181 sReadersContexts[i]->readerState.readerSharing = 0;
186 pcsclite_max_reader_context = new_size;
191LONG RFAddReader(
const char *readerNameLong,
int port,
const char *library,
194 DWORD dwContext = 0, dwGetSize;
195 UCHAR ucGetData[1], ucThread[1];
199 char *readerName = NULL;
201 if ((readerNameLong == NULL) || (library == NULL) || (device == NULL))
205 const char *ro_filter =
SYS_GetEnv(
"PCSCLITE_FILTER_IGNORE_READER_NAMES");
211 filter = alloca(strlen(ro_filter)+1);
212 strcpy(filter, ro_filter);
217 next = strchr(filter,
':');
225 if (*filter && strstr(readerNameLong, filter))
228 "Reader name \"%s\" contains \"%s\": ignored",
229 readerNameLong, filter);
244 readerName = alloca(strlen(readerNameLong)+1);
245 strcpy(readerName, readerNameLong);
248 if (strlen(readerName) > MAX_READERNAME -
sizeof(
" 00 00"))
251 "Reader name too long: %zd chars instead of max %zd. Truncating!",
252 strlen(readerName), MAX_READERNAME -
sizeof(
" 00 00"));
253 readerName[MAX_READERNAME -
sizeof(
" 00 00")] =
'\0';
257 for (i = 0; i < pcsclite_max_reader_context; i++)
259 if (sReadersContexts[i]->vHandle != 0)
261 char lpcStripReader[MAX_READERNAME];
265 strncpy(lpcStripReader,
266 sReadersContexts[i]->readerState.readerName,
267 sizeof(lpcStripReader));
268 tmplen = strlen(lpcStripReader);
269 lpcStripReader[tmplen - 6] = 0;
271 if ((strcmp(readerName, lpcStripReader) == 0)
272 && (port == sReadersContexts[i]->port)
273 && (strcmp(device, sReadersContexts[i]->device) == 0))
275 Log1(PCSC_LOG_ERROR,
"Duplicate reader found.");
282 for (i = 0; i < pcsclite_max_reader_context; i++)
284 if (sReadersContexts[i]->vHandle == 0)
291 if (i == pcsclite_max_reader_context)
294 RFReAllocateReaderSpace();
299 parentNode = RFSetReaderName(sReadersContexts[dwContext], readerName,
304 sReadersContexts[dwContext]->library = strdup(library);
305 sReadersContexts[dwContext]->device = strdup(device);
306 sReadersContexts[dwContext]->version = 0;
307 sReadersContexts[dwContext]->port = port;
308 sReadersContexts[dwContext]->mMutex = NULL;
309 sReadersContexts[dwContext]->contexts = 0;
310 sReadersContexts[dwContext]->pthThread = 0;
311 sReadersContexts[dwContext]->hLockId = 0;
312 sReadersContexts[dwContext]->LockCount = 0;
313 sReadersContexts[dwContext]->vHandle = NULL;
314 sReadersContexts[dwContext]->pFeeds = NULL;
315 sReadersContexts[dwContext]->pMutex = NULL;
316 sReadersContexts[dwContext]->pthCardEvent = NULL;
318 lrv = list_init(&sReadersContexts[dwContext]->handlesList);
321 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
325 lrv = list_attributes_seeker(&sReadersContexts[dwContext]->handlesList,
326 RDR_CLIHANDLES_seeker);
329 Log2(PCSC_LOG_CRITICAL,
330 "list_attributes_seeker failed with return value: %d", lrv);
334 (void)pthread_mutex_init(&sReadersContexts[dwContext]->handlesList_lock,
337 (void)pthread_mutex_init(&sReadersContexts[dwContext]->powerState_lock,
339 sReadersContexts[dwContext]->powerState = POWER_STATE_UNPOWERED;
342 sReadersContexts[dwContext]->reference = 1;
345 if (parentNode >= 0 && parentNode < pcsclite_max_reader_context)
347 sReadersContexts[dwContext]->pFeeds =
348 sReadersContexts[parentNode]->pFeeds;
349 *(sReadersContexts[dwContext])->pFeeds += 1;
350 sReadersContexts[dwContext]->vHandle =
351 sReadersContexts[parentNode]->vHandle;
352 sReadersContexts[dwContext]->mMutex =
353 sReadersContexts[parentNode]->mMutex;
354 sReadersContexts[dwContext]->pMutex =
355 sReadersContexts[parentNode]->pMutex;
358 dwGetSize =
sizeof(ucThread);
362 if (rv ==
IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
364 Log1(PCSC_LOG_INFO,
"Driver is thread safe");
365 sReadersContexts[dwContext]->mMutex = NULL;
366 sReadersContexts[dwContext]->pMutex = NULL;
369 *(sReadersContexts[dwContext])->pMutex += 1;
372 if (sReadersContexts[dwContext]->pFeeds == NULL)
374 sReadersContexts[dwContext]->pFeeds = malloc(
sizeof(
int));
380 *(sReadersContexts[dwContext])->pFeeds = 1;
383 if (sReadersContexts[dwContext]->mMutex == 0)
385 sReadersContexts[dwContext]->mMutex =
386 malloc(
sizeof(pthread_mutex_t));
387 (void)pthread_mutex_init(sReadersContexts[dwContext]->mMutex, NULL);
390 if (sReadersContexts[dwContext]->pMutex == NULL)
392 sReadersContexts[dwContext]->pMutex = malloc(
sizeof(
int));
393 *(sReadersContexts[dwContext])->pMutex = 1;
396 rv = RFInitializeReader(sReadersContexts[dwContext]);
399 int log_level = PCSC_LOG_ERROR;
401 log_level = PCSC_LOG_INFO;
404 Log2(log_level,
"%s init failed.", readerName);
405 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
411 RESPONSECODE (*fct)(DWORD, int) = NULL;
413 dwGetSize =
sizeof(fct);
419 Log1(PCSC_LOG_INFO,
"Using the pcscd polling thread");
423 sReadersContexts[dwContext]->pthCardEvent = fct;
424 Log1(PCSC_LOG_INFO,
"Using the reader polling thread");
427 rv = EHSpawnEventHandler(sReadersContexts[dwContext]);
430 Log2(PCSC_LOG_ERROR,
"%s init failed.", readerName);
431 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
439 if (ReaderEvents < 0)
443 dwGetSize =
sizeof(ucGetData);
447 int nbSlots = ucGetData[0];
448 if (rv !=
IFD_SUCCESS || dwGetSize != 1 || nbSlots == 0)
463 for (j = 1; j < nbSlots; j++)
465 char *tmpReader = NULL;
466 DWORD dwContextB = 0;
467 RESPONSECODE (*fct)(DWORD, int) = NULL;
470 for (i = 0; i < pcsclite_max_reader_context; i++)
472 if (sReadersContexts[i]->vHandle == 0)
479 if (i == pcsclite_max_reader_context)
482 RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
487 tmpReader = sReadersContexts[dwContextB]->readerState.readerName;
489 sReadersContexts[dwContext]->readerState.readerName,
490 sizeof(sReadersContexts[dwContextB]->readerState.readerName));
491 snprintf(tmpReader + strlen(tmpReader) - 2, 3,
"%02X", j);
493 sReadersContexts[dwContextB]->library =
494 sReadersContexts[dwContext]->library;
495 sReadersContexts[dwContextB]->device =
496 sReadersContexts[dwContext]->device;
497 sReadersContexts[dwContextB]->version =
498 sReadersContexts[dwContext]->version;
499 sReadersContexts[dwContextB]->port =
500 sReadersContexts[dwContext]->port;
501 sReadersContexts[dwContextB]->vHandle =
502 sReadersContexts[dwContext]->vHandle;
503 sReadersContexts[dwContextB]->mMutex =
504 sReadersContexts[dwContext]->mMutex;
505 sReadersContexts[dwContextB]->pMutex =
506 sReadersContexts[dwContext]->pMutex;
507 sReadersContexts[dwContextB]->slot =
508 sReadersContexts[dwContext]->slot + j;
509 sReadersContexts[dwContextB]->pthCardEvent = NULL;
515 sReadersContexts[dwContextB]->pFeeds =
516 sReadersContexts[dwContext]->pFeeds;
519 *(sReadersContexts[dwContextB])->pFeeds += 1;
521 sReadersContexts[dwContextB]->contexts = 0;
522 sReadersContexts[dwContextB]->hLockId = 0;
523 sReadersContexts[dwContextB]->LockCount = 0;
525 lrv = list_init(&sReadersContexts[dwContextB]->handlesList);
528 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
532 lrv = list_attributes_seeker(&sReadersContexts[dwContextB]->handlesList,
533 RDR_CLIHANDLES_seeker);
536 Log2(PCSC_LOG_CRITICAL,
537 "list_attributes_seeker failed with return value: %d", lrv);
541 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->handlesList_lock, NULL);
542 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->powerState_lock,
544 sReadersContexts[dwContextB]->powerState = POWER_STATE_UNPOWERED;
547 sReadersContexts[dwContextB]->reference = 1;
550 dwGetSize =
sizeof(ucThread);
554 if (rv ==
IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
556 Log1(PCSC_LOG_INFO,
"Driver is slot thread safe");
558 sReadersContexts[dwContextB]->library =
559 strdup(sReadersContexts[dwContext]->library);
560 sReadersContexts[dwContextB]->device =
561 strdup(sReadersContexts[dwContext]->device);
562 sReadersContexts[dwContextB]->mMutex =
563 malloc(
sizeof(pthread_mutex_t));
564 (void)pthread_mutex_init(sReadersContexts[dwContextB]->mMutex,
567 sReadersContexts[dwContextB]->pMutex = malloc(
sizeof(
int));
568 *(sReadersContexts[dwContextB])->pMutex = 1;
571 *(sReadersContexts[dwContextB])->pMutex += 1;
573 rv = RFInitializeReader(sReadersContexts[dwContextB]);
577 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
582 dwGetSize =
sizeof(fct);
588 Log1(PCSC_LOG_INFO,
"Using the pcscd polling thread");
592 sReadersContexts[dwContextB]->pthCardEvent = fct;
593 Log1(PCSC_LOG_INFO,
"Using the reader polling thread");
596 rv = EHSpawnEventHandler(sReadersContexts[dwContextB]);
599 Log2(PCSC_LOG_ERROR,
"%s init failed.", readerName);
600 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
608LONG RFRemoveReader(
const char *readerName,
int port,
int flags)
610 char lpcStripReader[MAX_READERNAME];
617 if (readerName == NULL)
621 extend =
SYS_GetEnv(
"PCSCLITE_FILTER_EXTEND_READER_NAMES");
623 extend_size = strlen(extend);
626 for (i = 0; i < pcsclite_max_reader_context; i++)
628 if (sReadersContexts[i] && (sReadersContexts[i]->vHandle != 0))
630 strncpy(lpcStripReader,
631 sReadersContexts[i]->readerState.readerName,
632 sizeof(lpcStripReader));
633 lpcStripReader[strlen(lpcStripReader) - 6 - extend_size] = 0;
636 if ((strncmp(readerName, lpcStripReader, MAX_READERNAME -
sizeof(
" 00 00")) == 0)
637 && (port == sReadersContexts[i]->port))
639 if (flags & REMOVE_READER_FLAG_REMOVED)
646 valueLength =
sizeof(tagValue);
658 UNREF_READER(sReadersContexts[i])
666 if (ReaderEvents < 0)
672LONG removeReader(READER_CONTEXT * sContext)
675 if (sContext -> pthThread)
676 EHDestroyEventHandler(sContext);
678 if ((NULL == sContext->
pMutex) || (NULL == sContext->
pFeeds))
681 "Trying to remove an already removed driver");
685 RFUnInitializeReader(sContext);
690 if (0 == *sContext->
pMutex)
692 (void)pthread_mutex_destroy(sContext->
mMutex);
704 if (*sContext->
pFeeds == 0)
720 while (list_size(&sContext->handlesList) != 0)
723 RDR_CLIHANDLES *currentHandle;
725 currentHandle = list_get_at(&sContext->handlesList, 0);
726 lrv = list_delete_at(&sContext->handlesList, 0);
728 Log2(PCSC_LOG_CRITICAL,
729 "list_delete_at failed with return value: %d", lrv);
735 list_destroy(&sContext->handlesList);
743LONG RFSetReaderName(READER_CONTEXT * rContext,
const char *readerName,
744 const char *libraryName,
int port)
748 int currentDigit = -1;
749 int supportedChannels = 0;
750 bool usedDigits[pcsclite_max_reader_context];
752 const char *extend = NULL;
755 for (i = 0; i < pcsclite_max_reader_context; i++)
756 usedDigits[i] =
false;
758 for (i = 0; i < pcsclite_max_reader_context; i++)
760 if (sReadersContexts[i]->vHandle != 0)
762 if (strcmp(sReadersContexts[i]->library, libraryName) == 0)
768 valueLength =
sizeof(tagValue);
771 &valueLength, tagValue);
776 supportedChannels = tagValue[0];
778 "Support %d simultaneous readers", tagValue[0]);
781 supportedChannels = 1;
784 if ((((sReadersContexts[i]->port & 0xFFFF0000) ==
785 PCSCLITE_HP_BASE_PORT)
786 && (sReadersContexts[i]->port != port))
787 || (supportedChannels > 1))
789 const char *reader = sReadersContexts[i]->readerState.readerName;
803 currentDigit = strtol(reader + strlen(reader) - 5, NULL, 16);
806 usedDigits[currentDigit] =
true;
816 if (currentDigit != -1)
818 for (i = 0; i < pcsclite_max_reader_context; i++)
821 if (usedDigits[i] ==
false)
825 if (i == pcsclite_max_reader_context)
827 Log2(PCSC_LOG_ERROR,
"Max number of readers reached: %d", pcsclite_max_reader_context);
831 if (i >= supportedChannels)
833 Log3(PCSC_LOG_ERROR,
"Driver %s does not support more than "
834 "%d reader(s). Maybe the driver should support "
835 "TAG_IFD_SIMULTANEOUS_ACCESS", libraryName, supportedChannels);
841 extend =
SYS_GetEnv(
"PCSCLITE_FILTER_EXTEND_READER_NAMES");
850 readerName, extend, i);
853 rContext->
slot = i << 16;
858LONG RFReaderInfo(
const char *readerName, READER_CONTEXT ** sReader)
862 if (readerName == NULL)
865 for (i = 0; i < pcsclite_max_reader_context; i++)
867 if (sReadersContexts[i]->vHandle != 0)
869 if (strcmp(readerName,
870 sReadersContexts[i]->readerState.readerName) == 0)
873 REF_READER(sReadersContexts[i])
875 *sReader = sReadersContexts[i];
884LONG RFReaderInfoById(
SCARDHANDLE hCard, READER_CONTEXT * * sReader)
888 for (i = 0; i < pcsclite_max_reader_context; i++)
890 if (sReadersContexts[i]->vHandle != 0)
892 RDR_CLIHANDLES * currentHandle;
893 (void)pthread_mutex_lock(&sReadersContexts[i]->handlesList_lock);
894 currentHandle = list_seek(&sReadersContexts[i]->handlesList,
896 (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock);
897 if (currentHandle != NULL)
900 REF_READER(sReadersContexts[i])
902 *sReader = sReadersContexts[i];
911LONG RFLoadReader(READER_CONTEXT * rContext)
916 Log2(PCSC_LOG_INFO,
"Reusing already loaded driver for %s",
928LONG RFBindFunctions(READER_CONTEXT * rContext)
933 rv = DYN_GetAddress(rContext->
vHandle, &f,
"IFDHCreateChannelByName",
true);
937 rContext->
version = IFD_HVERSION_3_0;
941 rv = DYN_GetAddress(rContext->
vHandle, &f,
"IFDHCreateChannel",
false);
945 rContext->
version = IFD_HVERSION_2_0;
950 Log1(PCSC_LOG_CRITICAL,
"IFDHandler functions missing");
955 if (rContext->
version == IFD_HVERSION_2_0)
958#define GET_ADDRESS_OPTIONALv2(s, code) \
961 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s, false); \
962 if (SCARD_S_SUCCESS != rvl) \
966 rContext->psFunctions.psFunctions_v2.pvf ## s = f1; \
969#define GET_ADDRESSv2(s) \
970 GET_ADDRESS_OPTIONALv2(s, \
971 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
974 Log1(PCSC_LOG_INFO,
"Loading IFD Handler 2.0");
976 GET_ADDRESSv2(CreateChannel)
977 GET_ADDRESSv2(CloseChannel)
978 GET_ADDRESSv2(GetCapabilities)
979 GET_ADDRESSv2(SetCapabilities)
980 GET_ADDRESSv2(PowerICC)
981 GET_ADDRESSv2(TransmitToICC)
982 GET_ADDRESSv2(ICCPresence)
983 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
985 GET_ADDRESSv2(Control)
987 else if (rContext->version == IFD_HVERSION_3_0)
990#define GET_ADDRESS_OPTIONALv3(s, code) \
993 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s, false); \
994 if (SCARD_S_SUCCESS != rvl) \
998 rContext->psFunctions.psFunctions_v3.pvf ## s = f1; \
1001#define GET_ADDRESSv3(s) \
1002 GET_ADDRESS_OPTIONALv3(s, \
1003 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
1006 Log1(PCSC_LOG_INFO,
"Loading IFD Handler 3.0");
1008 GET_ADDRESSv2(CreateChannel)
1009 GET_ADDRESSv2(CloseChannel)
1010 GET_ADDRESSv2(GetCapabilities)
1011 GET_ADDRESSv2(SetCapabilities)
1012 GET_ADDRESSv2(PowerICC)
1013 GET_ADDRESSv2(TransmitToICC)
1014 GET_ADDRESSv2(ICCPresence)
1015 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
1017 GET_ADDRESSv3(CreateChannelByName)
1018 GET_ADDRESSv3(Control)
1023 Log1(PCSC_LOG_CRITICAL,
"IFD Handler not 1.0/2.0 or 3.0");
1030LONG RFUnBindFunctions(READER_CONTEXT * rContext)
1038LONG RFUnloadReader(READER_CONTEXT * rContext)
1041 if (*rContext->
pFeeds == 1)
1043 Log1(PCSC_LOG_INFO,
"Unloading reader driver.");
1044 (void)DYN_CloseLibrary(rContext->
vHandle);
1053LONG RFCheckSharing(
SCARDHANDLE hCard, READER_CONTEXT * rContext)
1061LONG RFLockSharing(
SCARDHANDLE hCard, READER_CONTEXT * rContext)
1065 (void)pthread_mutex_lock(&LockMutex);
1066 rv = RFCheckSharing(hCard, rContext);
1072 (void)pthread_mutex_unlock(&LockMutex);
1077LONG RFUnlockSharing(
SCARDHANDLE hCard, READER_CONTEXT * rContext)
1081 (void)pthread_mutex_lock(&LockMutex);
1082 rv = RFCheckSharing(hCard, rContext);
1105 (void)pthread_mutex_unlock(&LockMutex);
1110LONG RFUnlockAllSharing(
SCARDHANDLE hCard, READER_CONTEXT * rContext)
1114 (void)pthread_mutex_lock(&LockMutex);
1115 rv = RFCheckSharing(hCard, rContext);
1121 (void)pthread_mutex_unlock(&LockMutex);
1126LONG RFInitializeReader(READER_CONTEXT * rContext)
1132 Log4(PCSC_LOG_INFO,
"Attempting startup of %s using %s on port 0x%X",
1135#ifndef PCSCLITE_STATIC_DRIVER
1137 rv = RFLoadReader(rContext);
1140 Log2(PCSC_LOG_ERROR,
"RFLoadReader failed: 0x%lX", rv);
1145 rv = RFBindFunctions(rContext);
1149 Log2(PCSC_LOG_ERROR,
"RFBindFunctions failed: 0x%lX", rv);
1150 (void)RFUnloadReader(rContext);
1155 rContext->
vHandle = RFInitializeReader;
1163 int log_level = PCSC_LOG_CRITICAL;
1169 log_level = PCSC_LOG_INFO;
1173 Log3(log_level,
"Open Port 0x%X Failed (%s)",
1178 rContext->
slot = -1;
1184void RFUnInitializeReader(READER_CONTEXT * rContext)
1186 Log2(PCSC_LOG_INFO,
"Attempting shutdown of %s.",
1190 if (rContext->
slot != -1)
1193 (void)RFUnBindFunctions(rContext);
1194 (void)RFUnloadReader(rContext);
1213SCARDHANDLE RFCreateReaderHandle(READER_CONTEXT * rContext)
1222 READER_CONTEXT *dummy_reader;
1232 ret = RFReaderInfoById(randHandle, &dummy_reader);
1234 UNREF_READER(dummy_reader)
1243LONG RFAddReaderHandle(READER_CONTEXT * rContext,
SCARDHANDLE hCard)
1245 int listLength, lrv;
1246 RDR_CLIHANDLES *newHandle;
1250 listLength = list_size(&rContext->handlesList);
1253 if (listLength >= maxReaderHandles)
1255 Log2(PCSC_LOG_CRITICAL,
1256 "Too many handles opened, exceeding configured max (%d)",
1262 newHandle = malloc(
sizeof(RDR_CLIHANDLES));
1263 if (NULL == newHandle)
1265 Log1(PCSC_LOG_CRITICAL,
"malloc failed");
1270 newHandle->
hCard = hCard;
1273 lrv = list_append(&rContext->handlesList, newHandle);
1277 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
1286LONG RFRemoveReaderHandle(READER_CONTEXT * rContext,
SCARDHANDLE hCard)
1288 RDR_CLIHANDLES *currentHandle;
1293 currentHandle = list_seek(&rContext->handlesList, &hCard);
1294 if (NULL == currentHandle)
1296 Log2(PCSC_LOG_CRITICAL,
"list_seek failed to locate hCard=%lX", hCard);
1301 lrv = list_delete(&rContext->handlesList, currentHandle);
1303 Log2(PCSC_LOG_CRITICAL,
1304 "list_delete failed with return value: %d", lrv);
1306 free(currentHandle);
1315void RFSetReaderEventState(READER_CONTEXT * rContext, DWORD dwEvent)
1318 int list_index, listSize;
1319 RDR_CLIHANDLES *currentHandle;
1322 listSize = list_size(&rContext->handlesList);
1324 for (list_index = 0; list_index < listSize; list_index++)
1326 currentHandle = list_get_at(&rContext->handlesList, list_index);
1327 if (NULL == currentHandle)
1329 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed at index %d",
1338 if (SCARD_REMOVED == dwEvent)
1348LONG RFCheckReaderEventState(READER_CONTEXT * rContext,
SCARDHANDLE hCard)
1351 RDR_CLIHANDLES *currentHandle;
1352 DWORD dwEventStatus;
1355 currentHandle = list_seek(&rContext->handlesList, &hCard);
1357 if (NULL == currentHandle)
1360 Log2(PCSC_LOG_CRITICAL,
"list_seek failed for hCard 0x%lX", hCard);
1365 switch(dwEventStatus)
1386LONG RFClearReaderEventState(READER_CONTEXT * rContext,
SCARDHANDLE hCard)
1388 RDR_CLIHANDLES *currentHandle;
1391 currentHandle = list_seek(&rContext->handlesList, &hCard);
1393 if (NULL == currentHandle)
1405LONG RFCheckReaderStatus(READER_CONTEXT * rContext)
1413void RFCleanupReaders(
void)
1417 Log1(PCSC_LOG_INFO,
"entering cleaning function");
1418 for (i = 0; i < pcsclite_max_reader_context; i++)
1420 if (sReadersContexts[i]->vHandle != 0)
1423 char lpcStripReader[MAX_READERNAME];
1425 Log2(PCSC_LOG_INFO,
"Stopping reader: %s",
1426 sReadersContexts[i]->readerState.readerName);
1428 strncpy(lpcStripReader,
1429 sReadersContexts[i]->readerState.readerName,
1430 sizeof(lpcStripReader));
1432 lpcStripReader[strlen(lpcStripReader) - 6] =
'\0';
1434 rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->port,
1435 REMOVE_READER_NO_FLAG);
1438 Log2(PCSC_LOG_ERROR,
"RFRemoveReader error: %s", rv2text(rv));
1441 free(sReadersContexts[i]);
1442 sReadersContexts[i] = NULL;
1459void RFWaitForReaderInit(
void)
1465 need_to_wait =
false;
1466 for (
int i = 0; i < pcsclite_max_reader_context; i++)
1469 if (sReadersContexts[i] && sReadersContexts[i]->vHandle != NULL)
1473 == sReadersContexts[i]->readerState.cardAtrLength)
1475 Log2(PCSC_LOG_DEBUG,
"Waiting init for reader: %s",
1476 sReadersContexts[i]->readerState.readerName);
1477 need_to_wait =
true;
1484 }
while (need_to_wait);
1489int RFStartSerialReaders(
const char *readerconf)
1495 ConfigFile = strdup(readerconf);
1497 rv = DBGetReaderListDir(readerconf, &reader_list);
1500 if (NULL == reader_list)
1507 (void)RFAddReader(reader_list[i].pcFriendlyname,
1508 reader_list[i].channelId,
1509 reader_list[i].pcLibpath, reader_list[i].pcDevicename);
1513 ConfigFileCRC += reader_list[i].pcFriendlyname[j];
1514 for (j=0; j<reader_list[i].
pcLibpath[j]; j++)
1515 ConfigFileCRC += reader_list[i].pcLibpath[j];
1517 ConfigFileCRC += reader_list[i].pcDevicename[j];
1520 free(reader_list[i].pcFriendlyname);
1521 free(reader_list[i].pcLibpath);
1522 free(reader_list[i].pcDevicename);
1529void RFReCheckReaderConf(
void)
1534 (void)DBGetReaderListDir(ConfigFile, &reader_list);
1537 if (NULL == reader_list)
1547 crc += reader_list[i].pcFriendlyname[j];
1548 for (j=0; j<reader_list[i].
pcLibpath[j]; j++)
1549 crc += reader_list[i].pcLibpath[j];
1551 crc += reader_list[i].pcDevicename[j];
1555 if (crc != ConfigFileCRC)
1557 Log2(PCSC_LOG_CRITICAL,
1558 "configuration file: %s has been modified. Recheck canceled",
1566 char present =
false;
1568 Log2(PCSC_LOG_DEBUG,
"refresh reader: %s",
1569 reader_list[i].pcFriendlyname);
1572 for (r = 0; r < pcsclite_max_reader_context; r++)
1574 if (sReadersContexts[r]->vHandle != 0)
1576 char lpcStripReader[MAX_READERNAME];
1580 strncpy(lpcStripReader,
1581 sReadersContexts[r]->readerState.readerName,
1582 sizeof(lpcStripReader));
1583 tmplen = strlen(lpcStripReader);
1584 lpcStripReader[tmplen - 6] = 0;
1586 if ((strcmp(reader_list[i].pcFriendlyname, lpcStripReader) == 0)
1587 && (reader_list[i].channelId == sReadersContexts[r]->port))
1598 Log2(PCSC_LOG_INFO,
"Reader %s disappeared",
1599 reader_list[i].pcFriendlyname);
1600 (void)RFRemoveReader(reader_list[i].pcFriendlyname,
1601 reader_list[i].channelId, REMOVE_READER_NO_FLAG);
1610 (void)RFAddReader(reader_list[i].pcFriendlyname,
1611 reader_list[i].channelId, reader_list[i].pcLibpath,
1612 reader_list[i].pcDevicename);
1615 free(reader_list[i].pcFriendlyname);
1616 free(reader_list[i].pcLibpath);
1617 free(reader_list[i].pcDevicename);
1631void RFSetPowerState(READER_CONTEXT * rContext,
int value)
This abstracts dynamic library loading functions.
void EHSignalEventToClients(void)
Sends an asynchronous event to any waiting client.
This handles card insertion/removal events, updates ATR, protocol, and status information.
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
#define READER_NOT_INITIALIZED
Special value to indicate that power up has not yet happen This is used to auto start mode to wait un...
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
#define SCARD_W_RESET_CARD
The smart card has been reset, so any shared state information is invalid.
#define SCARD_F_UNKNOWN_ERROR
An internal error has been detected, but the source is unknown.
#define SCARD_E_INVALID_TARGET
Registry startup information is missing or invalid.
#define SCARD_S_SUCCESS
No error was encountered.
#define SCARD_E_NO_MEMORY
Not enough memory available to complete this command.
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
#define SCARD_E_DUPLICATE_READER
The reader driver did not produce a unique reader name.
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
#define SCARD_W_REMOVED_CARD
The smart card has been removed, so further communication is not possible.
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
#define SCARD_E_NOT_TRANSACTED
An attempt was made to end a non-existent transaction.
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
This provides a search API for hot pluggble devices.
#define IFD_NO_SUCH_DEVICE
The IFD_NO_SUCH_DEVICE error must be returned by the driver when it detects the reader is no more pre...
#define TAG_IFD_SIMULTANEOUS_ACCESS
number of reader the driver can manage
#define TAG_IFD_THREAD_SAFE
driver is thread safe
#define TAG_IFD_SLOTS_NUMBER
number of slots of the reader
#define TAG_IFD_POLLING_THREAD_WITH_TIMEOUT
driver uses a polling thread with a timeout parameter
#define TAG_IFD_SLOT_THREAD_SAFE
support access to different slots of the reader
#define IFD_SUCCESS
no error
#define TAG_IFD_DEVICE_REMOVED
signals the reader has been removed
RESPONSECODE IFDCloseIFD(READER_CONTEXT *rContext)
Close a communication channel to the IFD.
RESPONSECODE IFDOpenIFD(READER_CONTEXT *rContext)
Open a communication channel to the IFD.
RESPONSECODE IFDGetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, PDWORD pdwLength, PUCHAR pucValue)
Gets capabilities in the reader.
LONG IFDStatusICC(READER_CONTEXT *rContext, PDWORD pdwStatus)
Provide statistical information about the IFD and ICC including insertions, atr, powering status/etc.
RESPONSECODE IFDSetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, DWORD dwLength, PUCHAR pucValue)
Set capabilities in the reader.
This wraps the dynamic ifdhandler functions.
#define SCARD_PROTOCOL_UNDEFINED
protocol not set
#define MAX_ATR_SIZE
Maximum ATR size.
#define SCARD_UNKNOWN
Unknown state.
LONG SCARDHANDLE
hCard returned by SCardConnect()
int RFGetPowerState(READER_CONTEXT *rContext)
Wait until all connected readers have a chance to power up a possibly inserted card.
This keeps track of a list of currently available reader structures.
define structures to represent a reader
SCARDHANDLE hCard
hCard for this connection
_Atomic DWORD dwEventStatus
Recent event that must be sent.
READER_STATE readerState
reader state
pthread_mutex_t * mMutex
Mutex for this connection.
pthread_mutex_t powerState_lock
powerState mutex
_Atomic int32_t contexts
Number of open contexts.
int slot
Current Reader Slot.
int * pFeeds
Number of shared client to lib.
_Atomic SCARDHANDLE hLockId
Lock Id.
int * pMutex
Number of client to mutex.
int version
IFD Handler version number.
union ReaderContext::@114326376151332066361210111067242353223333322260 psFunctions
driver functions
pthread_mutex_t handlesList_lock
lock for the above list
_Atomic int LockCount
number of recursive locks
char * library
Library Path.
_Atomic int reference
number of users of the structure
int powerState
auto power off state
char * device
Device Name.
_Atomic LPVOID vHandle
Dlopen handle.
char * pcFriendlyname
FRIENDLYNAME.
char * pcDevicename
DEVICENAME.
_Atomic int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
char readerName[MAX_READERNAME]
reader name
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
uint32_t eventCounter
number of card events
_Atomic uint32_t cardAtrLength
ATR length.
uint32_t readerState
SCARD_* bit field.
This handles abstract system level calls.
const char * SYS_GetEnv(const char *name)
(More) secure version of getenv(3)
int SYS_RandomInt(void)
Generate a pseudo random number.
int SYS_USleep(int)
Makes the current process sleep for some microseconds.