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] = calloc(1,
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);
151 return EHInitializeEventStructures();
154static LONG RFReAllocateReaderSpace(
void)
156 int new_size = pcsclite_max_reader_context + INITIAL_MAX_READERS_CONTEXTS;
158 Log3(PCSC_LOG_INFO,
"from %d to %d", pcsclite_max_reader_context, new_size);
160 sReadersContexts = realloc(sReadersContexts, new_size *
sizeof(sReadersContexts[0]));
163 for (
int i = pcsclite_max_reader_context; i < new_size; i++)
165 sReadersContexts[i] = malloc(
sizeof(READER_CONTEXT));
166 sReadersContexts[i]->vHandle = NULL;
167 atomic_init(&sReadersContexts[i]->hLockId, 0);
168 atomic_init(&sReadersContexts[i]->contexts, 0);
169 atomic_init(&sReadersContexts[i]->reference, 0);
172 memset(sReadersContexts[i]->readerState.readerName, 0, MAX_READERNAME);
173 memset(sReadersContexts[i]->readerState.cardAtr, 0,
MAX_ATR_SIZE);
174 sReadersContexts[i]->readerState.eventCounter = 0;
175 sReadersContexts[i]->readerState.readerState = 0;
176 sReadersContexts[i]->readerState.readerSharing = 0;
181 pcsclite_max_reader_context = new_size;
186LONG RFAddReader(
const char *readerNameLong,
int port,
const char *library,
189 DWORD dwContext = 0, dwGetSize;
190 UCHAR ucGetData[1], ucThread[1];
194 char *readerName = NULL;
196 if ((readerNameLong == NULL) || (library == NULL) || (device == NULL))
200 const char *ro_filter =
SYS_GetEnv(
"PCSCLITE_FILTER_IGNORE_READER_NAMES");
206 filter = alloca(strlen(ro_filter)+1);
207 strcpy(filter, ro_filter);
212 next = strchr(filter,
':');
220 if (*filter && strstr(readerNameLong, filter))
223 "Reader name \"%s\" contains \"%s\": ignored",
224 readerNameLong, filter);
239 readerName = alloca(strlen(readerNameLong)+1);
240 strcpy(readerName, readerNameLong);
243 if (strlen(readerName) > MAX_READERNAME -
sizeof(
" 00 00"))
246 "Reader name too long: %zd chars instead of max %zd. Truncating!",
247 strlen(readerName), MAX_READERNAME -
sizeof(
" 00 00"));
248 readerName[MAX_READERNAME -
sizeof(
" 00 00")] =
'\0';
252 for (i = 0; i < pcsclite_max_reader_context; i++)
254 if (sReadersContexts[i]->vHandle != 0)
256 char lpcStripReader[MAX_READERNAME];
260 strncpy(lpcStripReader,
261 sReadersContexts[i]->readerState.readerName,
262 sizeof(lpcStripReader));
263 tmplen = strlen(lpcStripReader);
264 lpcStripReader[tmplen - 6] = 0;
266 if ((strcmp(readerName, lpcStripReader) == 0)
267 && (port == sReadersContexts[i]->port)
268 && (strcmp(device, sReadersContexts[i]->device) == 0))
270 Log1(PCSC_LOG_ERROR,
"Duplicate reader found.");
277 for (i = 0; i < pcsclite_max_reader_context; i++)
279 if (sReadersContexts[i]->vHandle == 0)
286 if (i == pcsclite_max_reader_context)
289 RFReAllocateReaderSpace();
294 parentNode = RFSetReaderName(sReadersContexts[dwContext], readerName,
299 sReadersContexts[dwContext]->library = strdup(library);
300 sReadersContexts[dwContext]->device = strdup(device);
301 sReadersContexts[dwContext]->version = 0;
302 sReadersContexts[dwContext]->port = port;
303 sReadersContexts[dwContext]->mMutex = NULL;
304 sReadersContexts[dwContext]->contexts = 0;
305 sReadersContexts[dwContext]->pthThread = 0;
306 sReadersContexts[dwContext]->hLockId = 0;
307 sReadersContexts[dwContext]->LockCount = 0;
308 sReadersContexts[dwContext]->vHandle = NULL;
309 sReadersContexts[dwContext]->pFeeds = NULL;
310 sReadersContexts[dwContext]->pMutex = NULL;
311 sReadersContexts[dwContext]->pthCardEvent = NULL;
313 lrv = list_init(&sReadersContexts[dwContext]->handlesList);
316 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
320 lrv = list_attributes_seeker(&sReadersContexts[dwContext]->handlesList,
321 RDR_CLIHANDLES_seeker);
324 Log2(PCSC_LOG_CRITICAL,
325 "list_attributes_seeker failed with return value: %d", lrv);
329 (void)pthread_mutex_init(&sReadersContexts[dwContext]->handlesList_lock,
332 (void)pthread_mutex_init(&sReadersContexts[dwContext]->powerState_lock,
334 sReadersContexts[dwContext]->powerState = POWER_STATE_UNPOWERED;
337 sReadersContexts[dwContext]->reference = 1;
340 if (parentNode >= 0 && parentNode < pcsclite_max_reader_context)
342 sReadersContexts[dwContext]->pFeeds =
343 sReadersContexts[parentNode]->pFeeds;
344 *(sReadersContexts[dwContext])->pFeeds += 1;
345 sReadersContexts[dwContext]->vHandle =
346 sReadersContexts[parentNode]->vHandle;
347 sReadersContexts[dwContext]->mMutex =
348 sReadersContexts[parentNode]->mMutex;
349 sReadersContexts[dwContext]->pMutex =
350 sReadersContexts[parentNode]->pMutex;
353 dwGetSize =
sizeof(ucThread);
357 if (rv ==
IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
359 Log1(PCSC_LOG_INFO,
"Driver is thread safe");
360 sReadersContexts[dwContext]->mMutex = NULL;
361 sReadersContexts[dwContext]->pMutex = NULL;
364 *(sReadersContexts[dwContext])->pMutex += 1;
367 if (sReadersContexts[dwContext]->pFeeds == NULL)
369 sReadersContexts[dwContext]->pFeeds = malloc(
sizeof(
int));
375 *(sReadersContexts[dwContext])->pFeeds = 1;
378 if (sReadersContexts[dwContext]->mMutex == 0)
380 sReadersContexts[dwContext]->mMutex =
381 malloc(
sizeof(pthread_mutex_t));
382 (void)pthread_mutex_init(sReadersContexts[dwContext]->mMutex, NULL);
385 if (sReadersContexts[dwContext]->pMutex == NULL)
387 sReadersContexts[dwContext]->pMutex = malloc(
sizeof(
int));
388 *(sReadersContexts[dwContext])->pMutex = 1;
391 rv = RFInitializeReader(sReadersContexts[dwContext]);
394 int log_level = PCSC_LOG_ERROR;
396 log_level = PCSC_LOG_INFO;
399 Log2(log_level,
"%s init failed.", readerName);
400 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
406 RESPONSECODE (*fct)(DWORD, int) = NULL;
408 dwGetSize =
sizeof(fct);
414 Log1(PCSC_LOG_INFO,
"Using the pcscd polling thread");
418 sReadersContexts[dwContext]->pthCardEvent = fct;
419 Log1(PCSC_LOG_INFO,
"Using the reader polling thread");
422 rv = EHSpawnEventHandler(sReadersContexts[dwContext]);
425 Log2(PCSC_LOG_ERROR,
"%s init failed.", readerName);
426 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
434 if (ReaderEvents < 0)
438 dwGetSize =
sizeof(ucGetData);
442 int nbSlots = ucGetData[0];
443 if (rv !=
IFD_SUCCESS || dwGetSize != 1 || nbSlots == 0)
458 for (j = 1; j < nbSlots; j++)
460 char *tmpReader = NULL;
461 DWORD dwContextB = 0;
462 RESPONSECODE (*fct)(DWORD, int) = NULL;
465 for (i = 0; i < pcsclite_max_reader_context; i++)
467 if (sReadersContexts[i]->vHandle == 0)
474 if (i == pcsclite_max_reader_context)
477 RFReAllocateReaderSpace();
482 tmpReader = sReadersContexts[dwContextB]->readerState.readerName;
484 sReadersContexts[dwContext]->readerState.readerName,
485 sizeof(sReadersContexts[dwContextB]->readerState.readerName));
486 snprintf(tmpReader + strlen(tmpReader) - 2, 3,
"%02X", j);
488 sReadersContexts[dwContextB]->library =
489 sReadersContexts[dwContext]->library;
490 sReadersContexts[dwContextB]->device =
491 sReadersContexts[dwContext]->device;
492 sReadersContexts[dwContextB]->version =
493 sReadersContexts[dwContext]->version;
494 sReadersContexts[dwContextB]->port =
495 sReadersContexts[dwContext]->port;
496 sReadersContexts[dwContextB]->vHandle =
497 sReadersContexts[dwContext]->vHandle;
498 sReadersContexts[dwContextB]->mMutex =
499 sReadersContexts[dwContext]->mMutex;
500 sReadersContexts[dwContextB]->pMutex =
501 sReadersContexts[dwContext]->pMutex;
502 sReadersContexts[dwContextB]->slot =
503 sReadersContexts[dwContext]->slot + j;
504 sReadersContexts[dwContextB]->pthCardEvent = NULL;
510 sReadersContexts[dwContextB]->pFeeds =
511 sReadersContexts[dwContext]->pFeeds;
514 *(sReadersContexts[dwContextB])->pFeeds += 1;
516 sReadersContexts[dwContextB]->contexts = 0;
517 sReadersContexts[dwContextB]->hLockId = 0;
518 sReadersContexts[dwContextB]->LockCount = 0;
520 lrv = list_init(&sReadersContexts[dwContextB]->handlesList);
523 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
527 lrv = list_attributes_seeker(&sReadersContexts[dwContextB]->handlesList,
528 RDR_CLIHANDLES_seeker);
531 Log2(PCSC_LOG_CRITICAL,
532 "list_attributes_seeker failed with return value: %d", lrv);
536 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->handlesList_lock, NULL);
537 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->powerState_lock,
539 sReadersContexts[dwContextB]->powerState = POWER_STATE_UNPOWERED;
542 sReadersContexts[dwContextB]->reference = 1;
545 dwGetSize =
sizeof(ucThread);
549 if (rv ==
IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
551 Log1(PCSC_LOG_INFO,
"Driver is slot thread safe");
553 sReadersContexts[dwContextB]->library =
554 strdup(sReadersContexts[dwContext]->library);
555 sReadersContexts[dwContextB]->device =
556 strdup(sReadersContexts[dwContext]->device);
557 sReadersContexts[dwContextB]->mMutex =
558 malloc(
sizeof(pthread_mutex_t));
559 (void)pthread_mutex_init(sReadersContexts[dwContextB]->mMutex,
562 sReadersContexts[dwContextB]->pMutex = malloc(
sizeof(
int));
563 *(sReadersContexts[dwContextB])->pMutex = 1;
566 *(sReadersContexts[dwContextB])->pMutex += 1;
568 rv = RFInitializeReader(sReadersContexts[dwContextB]);
572 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
577 dwGetSize =
sizeof(fct);
583 Log1(PCSC_LOG_INFO,
"Using the pcscd polling thread");
587 sReadersContexts[dwContextB]->pthCardEvent = fct;
588 Log1(PCSC_LOG_INFO,
"Using the reader polling thread");
591 rv = EHSpawnEventHandler(sReadersContexts[dwContextB]);
594 Log2(PCSC_LOG_ERROR,
"%s init failed.", readerName);
595 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
603LONG RFRemoveReader(
const char *readerName,
int port,
int flags)
605 char lpcStripReader[MAX_READERNAME];
612 if (readerName == NULL)
616 extend =
SYS_GetEnv(
"PCSCLITE_FILTER_EXTEND_READER_NAMES");
618 extend_size = strlen(extend);
621 for (i = 0; i < pcsclite_max_reader_context; i++)
623 if (sReadersContexts[i] && (sReadersContexts[i]->vHandle != 0))
625 strncpy(lpcStripReader,
626 sReadersContexts[i]->readerState.readerName,
627 sizeof(lpcStripReader));
628 lpcStripReader[strlen(lpcStripReader) - 6 - extend_size] = 0;
631 if ((strncmp(readerName, lpcStripReader, MAX_READERNAME -
sizeof(
" 00 00")) == 0)
632 && (port == sReadersContexts[i]->port))
634 if (flags & REMOVE_READER_FLAG_REMOVED)
641 valueLength =
sizeof(tagValue);
653 UNREF_READER(sReadersContexts[i])
661 if (ReaderEvents < 0)
667LONG removeReader(READER_CONTEXT * sContext)
670 if (sContext -> pthThread)
671 EHDestroyEventHandler(sContext);
673 if ((NULL == sContext->
pMutex) || (NULL == sContext->
pFeeds))
676 "Trying to remove an already removed driver");
680 RFUnInitializeReader(sContext);
685 if (0 == *sContext->
pMutex)
687 (void)pthread_mutex_destroy(sContext->
mMutex);
699 if (*sContext->
pFeeds == 0)
715 while (list_size(&sContext->handlesList) != 0)
718 RDR_CLIHANDLES *currentHandle;
720 currentHandle = list_get_at(&sContext->handlesList, 0);
721 lrv = list_delete_at(&sContext->handlesList, 0);
723 Log2(PCSC_LOG_CRITICAL,
724 "list_delete_at failed with return value: %d", lrv);
730 list_destroy(&sContext->handlesList);
738LONG RFSetReaderName(READER_CONTEXT * rContext,
const char *readerName,
739 const char *libraryName,
int port)
743 int currentDigit = -1;
744 int supportedChannels = 0;
745 bool usedDigits[pcsclite_max_reader_context];
747 const char *extend = NULL;
750 for (i = 0; i < pcsclite_max_reader_context; i++)
751 usedDigits[i] =
false;
753 for (i = 0; i < pcsclite_max_reader_context; i++)
755 if (sReadersContexts[i]->vHandle != 0)
757 if (strcmp(sReadersContexts[i]->library, libraryName) == 0)
763 valueLength =
sizeof(tagValue);
766 &valueLength, tagValue);
771 supportedChannels = tagValue[0];
773 "Support %d simultaneous readers", tagValue[0]);
776 supportedChannels = 1;
779 if ((((sReadersContexts[i]->port & 0xFFFF0000) ==
780 PCSCLITE_HP_BASE_PORT)
781 && (sReadersContexts[i]->port != port))
782 || (supportedChannels > 1))
784 const char *reader = sReadersContexts[i]->readerState.readerName;
798 currentDigit = strtol(reader + strlen(reader) - 5, NULL, 16);
801 usedDigits[currentDigit] =
true;
811 if (currentDigit != -1)
813 for (i = 0; i < pcsclite_max_reader_context; i++)
816 if (usedDigits[i] ==
false)
820 if (i == pcsclite_max_reader_context)
822 Log2(PCSC_LOG_ERROR,
"Max number of readers reached: %d", pcsclite_max_reader_context);
826 if (i >= supportedChannels)
828 Log3(PCSC_LOG_ERROR,
"Driver %s does not support more than "
829 "%d reader(s). Maybe the driver should support "
830 "TAG_IFD_SIMULTANEOUS_ACCESS", libraryName, supportedChannels);
836 extend =
SYS_GetEnv(
"PCSCLITE_FILTER_EXTEND_READER_NAMES");
845 readerName, extend, i);
848 rContext->
slot = i << 16;
853LONG RFReaderInfo(
const char *readerName, READER_CONTEXT ** sReader)
857 if (readerName == NULL)
860 for (i = 0; i < pcsclite_max_reader_context; i++)
862 if (sReadersContexts[i]->vHandle != 0)
864 if (strcmp(readerName,
865 sReadersContexts[i]->readerState.readerName) == 0)
868 REF_READER(sReadersContexts[i])
870 *sReader = sReadersContexts[i];
879LONG RFReaderInfoById(
SCARDHANDLE hCard, READER_CONTEXT * * sReader)
883 for (i = 0; i < pcsclite_max_reader_context; i++)
885 if (sReadersContexts[i]->vHandle != 0)
887 RDR_CLIHANDLES * currentHandle;
888 (void)pthread_mutex_lock(&sReadersContexts[i]->handlesList_lock);
889 currentHandle = list_seek(&sReadersContexts[i]->handlesList,
891 (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock);
892 if (currentHandle != NULL)
895 REF_READER(sReadersContexts[i])
897 *sReader = sReadersContexts[i];
906LONG RFLoadReader(READER_CONTEXT * rContext)
911 Log2(PCSC_LOG_INFO,
"Reusing already loaded driver for %s",
923LONG RFBindFunctions(READER_CONTEXT * rContext)
928 rv = DYN_GetAddress(rContext->
vHandle, &f,
"IFDHCreateChannelByName",
true);
932 rContext->
version = IFD_HVERSION_3_0;
936 rv = DYN_GetAddress(rContext->
vHandle, &f,
"IFDHCreateChannel",
false);
940 rContext->
version = IFD_HVERSION_2_0;
945 Log1(PCSC_LOG_CRITICAL,
"IFDHandler functions missing");
950 if (rContext->
version == IFD_HVERSION_2_0)
953#define GET_ADDRESS_OPTIONALv2(s, code) \
956 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s, false); \
957 if (SCARD_S_SUCCESS != rvl) \
961 rContext->psFunctions.psFunctions_v2.pvf ## s = f1; \
964#define GET_ADDRESSv2(s) \
965 GET_ADDRESS_OPTIONALv2(s, \
966 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
969 Log1(PCSC_LOG_INFO,
"Loading IFD Handler 2.0");
971 GET_ADDRESSv2(CreateChannel)
972 GET_ADDRESSv2(CloseChannel)
973 GET_ADDRESSv2(GetCapabilities)
974 GET_ADDRESSv2(SetCapabilities)
975 GET_ADDRESSv2(PowerICC)
976 GET_ADDRESSv2(TransmitToICC)
977 GET_ADDRESSv2(ICCPresence)
978 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
980 GET_ADDRESSv2(Control)
982 else if (rContext->version == IFD_HVERSION_3_0)
985#define GET_ADDRESS_OPTIONALv3(s, code) \
988 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s, false); \
989 if (SCARD_S_SUCCESS != rvl) \
993 rContext->psFunctions.psFunctions_v3.pvf ## s = f1; \
996#define GET_ADDRESSv3(s) \
997 GET_ADDRESS_OPTIONALv3(s, \
998 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
1001 Log1(PCSC_LOG_INFO,
"Loading IFD Handler 3.0");
1003 GET_ADDRESSv2(CreateChannel)
1004 GET_ADDRESSv2(CloseChannel)
1005 GET_ADDRESSv2(GetCapabilities)
1006 GET_ADDRESSv2(SetCapabilities)
1007 GET_ADDRESSv2(PowerICC)
1008 GET_ADDRESSv2(TransmitToICC)
1009 GET_ADDRESSv2(ICCPresence)
1010 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
1012 GET_ADDRESSv3(CreateChannelByName)
1013 GET_ADDRESSv3(Control)
1018 Log1(PCSC_LOG_CRITICAL,
"IFD Handler not 1.0/2.0 or 3.0");
1025LONG RFUnBindFunctions(READER_CONTEXT * rContext)
1033LONG RFUnloadReader(READER_CONTEXT * rContext)
1036 if (*rContext->
pFeeds == 1)
1038 Log1(PCSC_LOG_INFO,
"Unloading reader driver.");
1039 (void)DYN_CloseLibrary(rContext->
vHandle);
1048LONG RFCheckSharing(
SCARDHANDLE hCard, READER_CONTEXT * rContext)
1056LONG RFLockSharing(
SCARDHANDLE hCard, READER_CONTEXT * rContext)
1060 (void)pthread_mutex_lock(&LockMutex);
1061 rv = RFCheckSharing(hCard, rContext);
1067 (void)pthread_mutex_unlock(&LockMutex);
1072LONG RFUnlockSharing(
SCARDHANDLE hCard, READER_CONTEXT * rContext)
1076 (void)pthread_mutex_lock(&LockMutex);
1077 rv = RFCheckSharing(hCard, rContext);
1100 (void)pthread_mutex_unlock(&LockMutex);
1105LONG RFUnlockAllSharing(
SCARDHANDLE hCard, READER_CONTEXT * rContext)
1109 (void)pthread_mutex_lock(&LockMutex);
1110 rv = RFCheckSharing(hCard, rContext);
1116 (void)pthread_mutex_unlock(&LockMutex);
1121LONG RFInitializeReader(READER_CONTEXT * rContext)
1127 Log4(PCSC_LOG_INFO,
"Attempting startup of %s using %s on port 0x%X",
1130#ifndef PCSCLITE_STATIC_DRIVER
1132 rv = RFLoadReader(rContext);
1135 Log2(PCSC_LOG_ERROR,
"RFLoadReader failed: 0x%lX", rv);
1140 rv = RFBindFunctions(rContext);
1144 Log2(PCSC_LOG_ERROR,
"RFBindFunctions failed: 0x%lX", rv);
1145 (void)RFUnloadReader(rContext);
1150 rContext->
vHandle = RFInitializeReader;
1158 int log_level = PCSC_LOG_CRITICAL;
1164 log_level = PCSC_LOG_INFO;
1168 Log3(log_level,
"Open Port 0x%X Failed (%s)",
1173 rContext->
slot = -1;
1179void RFUnInitializeReader(READER_CONTEXT * rContext)
1181 Log2(PCSC_LOG_INFO,
"Attempting shutdown of %s.",
1185 if (rContext->
slot != -1)
1188 (void)RFUnBindFunctions(rContext);
1189 (void)RFUnloadReader(rContext);
1208SCARDHANDLE RFCreateReaderHandle(READER_CONTEXT * rContext)
1217 READER_CONTEXT *dummy_reader;
1227 ret = RFReaderInfoById(randHandle, &dummy_reader);
1229 UNREF_READER(dummy_reader)
1238LONG RFAddReaderHandle(READER_CONTEXT * rContext,
SCARDHANDLE hCard)
1240 int listLength, lrv;
1241 RDR_CLIHANDLES *newHandle;
1245 listLength = list_size(&rContext->handlesList);
1248 if (listLength >= maxReaderHandles)
1250 Log2(PCSC_LOG_CRITICAL,
1251 "Too many handles opened, exceeding configured max (%d)",
1257 newHandle = malloc(
sizeof(RDR_CLIHANDLES));
1258 if (NULL == newHandle)
1260 Log1(PCSC_LOG_CRITICAL,
"malloc failed");
1265 newHandle->
hCard = hCard;
1268 lrv = list_append(&rContext->handlesList, newHandle);
1272 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
1281LONG RFRemoveReaderHandle(READER_CONTEXT * rContext,
SCARDHANDLE hCard)
1283 RDR_CLIHANDLES *currentHandle;
1288 currentHandle = list_seek(&rContext->handlesList, &hCard);
1289 if (NULL == currentHandle)
1291 Log2(PCSC_LOG_CRITICAL,
"list_seek failed to locate hCard=%lX", hCard);
1296 lrv = list_delete(&rContext->handlesList, currentHandle);
1298 Log2(PCSC_LOG_CRITICAL,
1299 "list_delete failed with return value: %d", lrv);
1301 free(currentHandle);
1310void RFSetReaderEventState(READER_CONTEXT * rContext, DWORD dwEvent)
1313 int list_index, listSize;
1314 RDR_CLIHANDLES *currentHandle;
1317 listSize = list_size(&rContext->handlesList);
1319 for (list_index = 0; list_index < listSize; list_index++)
1321 currentHandle = list_get_at(&rContext->handlesList, list_index);
1322 if (NULL == currentHandle)
1324 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed at index %d",
1333 if (SCARD_REMOVED == dwEvent)
1343LONG RFCheckReaderEventState(READER_CONTEXT * rContext,
SCARDHANDLE hCard)
1346 RDR_CLIHANDLES *currentHandle;
1347 DWORD dwEventStatus;
1350 currentHandle = list_seek(&rContext->handlesList, &hCard);
1352 if (NULL == currentHandle)
1355 Log2(PCSC_LOG_CRITICAL,
"list_seek failed for hCard 0x%lX", hCard);
1360 switch(dwEventStatus)
1381LONG RFClearReaderEventState(READER_CONTEXT * rContext,
SCARDHANDLE hCard)
1383 RDR_CLIHANDLES *currentHandle;
1386 currentHandle = list_seek(&rContext->handlesList, &hCard);
1388 if (NULL == currentHandle)
1400LONG RFCheckReaderStatus(READER_CONTEXT * rContext)
1408void RFCleanupReaders(
void)
1412 Log1(PCSC_LOG_INFO,
"entering cleaning function");
1413 for (i = 0; i < pcsclite_max_reader_context; i++)
1415 if (sReadersContexts[i]->vHandle != 0)
1418 char lpcStripReader[MAX_READERNAME];
1420 Log2(PCSC_LOG_INFO,
"Stopping reader: %s",
1421 sReadersContexts[i]->readerState.readerName);
1423 strncpy(lpcStripReader,
1424 sReadersContexts[i]->readerState.readerName,
1425 sizeof(lpcStripReader));
1427 lpcStripReader[strlen(lpcStripReader) - 6] =
'\0';
1429 rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->port,
1430 REMOVE_READER_NO_FLAG);
1433 Log2(PCSC_LOG_ERROR,
"RFRemoveReader error: %s", rv2text(rv));
1436 free(sReadersContexts[i]);
1437 sReadersContexts[i] = NULL;
1454void RFWaitForReaderInit(
void)
1460 need_to_wait =
false;
1461 for (
int i = 0; i < pcsclite_max_reader_context; i++)
1464 if (sReadersContexts[i] && sReadersContexts[i]->vHandle != NULL)
1468 == sReadersContexts[i]->readerState.cardAtrLength)
1470 Log2(PCSC_LOG_DEBUG,
"Waiting init for reader: %s",
1471 sReadersContexts[i]->readerState.readerName);
1472 need_to_wait =
true;
1479 }
while (need_to_wait);
1484int RFStartSerialReaders(
const char *readerconf)
1490 ConfigFile = strdup(readerconf);
1492 rv = DBGetReaderListDir(readerconf, &reader_list);
1495 if (NULL == reader_list)
1502 (void)RFAddReader(reader_list[i].pcFriendlyname,
1503 reader_list[i].channelId,
1504 reader_list[i].pcLibpath, reader_list[i].pcDevicename);
1508 ConfigFileCRC += reader_list[i].pcFriendlyname[j];
1509 for (j=0; j<reader_list[i].
pcLibpath[j]; j++)
1510 ConfigFileCRC += reader_list[i].pcLibpath[j];
1512 ConfigFileCRC += reader_list[i].pcDevicename[j];
1515 free(reader_list[i].pcFriendlyname);
1516 free(reader_list[i].pcLibpath);
1517 free(reader_list[i].pcDevicename);
1524void RFReCheckReaderConf(
void)
1529 (void)DBGetReaderListDir(ConfigFile, &reader_list);
1532 if (NULL == reader_list)
1542 crc += reader_list[i].pcFriendlyname[j];
1543 for (j=0; j<reader_list[i].
pcLibpath[j]; j++)
1544 crc += reader_list[i].pcLibpath[j];
1546 crc += reader_list[i].pcDevicename[j];
1550 if (crc != ConfigFileCRC)
1552 Log2(PCSC_LOG_CRITICAL,
1553 "configuration file: %s has been modified. Recheck canceled",
1561 char present =
false;
1563 Log2(PCSC_LOG_DEBUG,
"refresh reader: %s",
1564 reader_list[i].pcFriendlyname);
1567 for (r = 0; r < pcsclite_max_reader_context; r++)
1569 if (sReadersContexts[r]->vHandle != 0)
1571 char lpcStripReader[MAX_READERNAME];
1575 strncpy(lpcStripReader,
1576 sReadersContexts[r]->readerState.readerName,
1577 sizeof(lpcStripReader));
1578 tmplen = strlen(lpcStripReader);
1579 lpcStripReader[tmplen - 6] = 0;
1581 if ((strcmp(reader_list[i].pcFriendlyname, lpcStripReader) == 0)
1582 && (reader_list[i].channelId == sReadersContexts[r]->port))
1590 if (
IFDStatusICC(sReadersContexts[r], &dwStatus,
false)
1593 Log2(PCSC_LOG_INFO,
"Reader %s disappeared",
1594 reader_list[i].pcFriendlyname);
1595 (void)RFRemoveReader(reader_list[i].pcFriendlyname,
1596 reader_list[i].channelId, REMOVE_READER_NO_FLAG);
1605 (void)RFAddReader(reader_list[i].pcFriendlyname,
1606 reader_list[i].channelId, reader_list[i].pcLibpath,
1607 reader_list[i].pcDevicename);
1610 free(reader_list[i].pcFriendlyname);
1611 free(reader_list[i].pcLibpath);
1612 free(reader_list[i].pcDevicename);
1626void 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.
LONG IFDStatusICC(READER_CONTEXT *rContext, PDWORD pdwStatus, bool hotplug)
Provide statistical information about the IFD and ICC including insertions, atr, powering status/etc.
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.
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.
union ReaderContext::@326266165201103155124353152063316062370301160101 psFunctions
driver functions
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.
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.