64#include "configfile.h"
69static int maxReaderHandles = PCSC_MAX_READER_HANDLES;
70static DWORD dwNumReadersContexts = 0;
72static char *ConfigFile = NULL;
73static int ConfigFileCRC = 0;
75static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER;
76int16_t ReaderEvents = 1;
80static int RDR_CLIHANDLES_seeker(
const void *el,
const void *key)
84 if ((el == NULL) || (key == NULL))
86 Log3(PCSC_LOG_CRITICAL,
87 "RDR_CLIHANDLES_seeker called with NULL pointer: el=%p, key=%p",
117 removeReader(sReader);
122LONG RFAllocateReaderSpace(
unsigned int customMaxReaderHandles)
126 if (customMaxReaderHandles != 0)
127 maxReaderHandles = customMaxReaderHandles;
133 sReadersContexts[i]->
vHandle = NULL;
134 atomic_init(&sReadersContexts[i]->hLockId, 0);
135 atomic_init(&sReadersContexts[i]->contexts, 0);
136 atomic_init(&sReadersContexts[i]->reference, 0);
139 memset(readerStates[i].readerName, 0, MAX_READERNAME);
147 sReadersContexts[i]->
readerState = &readerStates[i];
151 return EHInitializeEventStructures();
154LONG RFAddReader(
const char *readerNameLong,
int port,
const char *library,
157 DWORD dwContext = 0, dwGetSize;
158 UCHAR ucGetData[1], ucThread[1];
162 char *readerName = NULL;
164 if ((readerNameLong == NULL) || (library == NULL) || (device == NULL))
168 const char *ro_filter =
SYS_GetEnv(
"PCSCLITE_FILTER_IGNORE_READER_NAMES");
174 filter = alloca(strlen(ro_filter)+1);
175 strcpy(filter, ro_filter);
180 next = strchr(filter,
':');
188 if (*filter && strstr(readerNameLong, filter))
191 "Reader name \"%s\" contains \"%s\": ignored",
192 readerNameLong, filter);
207 readerName = alloca(strlen(readerNameLong)+1);
208 strcpy(readerName, readerNameLong);
211 if (strlen(readerName) > MAX_READERNAME -
sizeof(
" 00 00"))
214 "Reader name too long: %zd chars instead of max %zd. Truncating!",
215 strlen(readerName), MAX_READERNAME -
sizeof(
" 00 00"));
216 readerName[MAX_READERNAME -
sizeof(
" 00 00")] =
'\0';
220 if (dwNumReadersContexts != 0)
224 if (sReadersContexts[i]->vHandle != 0)
226 char lpcStripReader[MAX_READERNAME];
230 strncpy(lpcStripReader,
231 sReadersContexts[i]->readerState->readerName,
232 sizeof(lpcStripReader));
233 tmplen = strlen(lpcStripReader);
234 lpcStripReader[tmplen - 6] = 0;
236 if ((strcmp(readerName, lpcStripReader) == 0)
237 && (port == sReadersContexts[i]->port)
238 && (strcmp(device, sReadersContexts[i]->device) == 0))
240 Log1(PCSC_LOG_ERROR,
"Duplicate reader found.");
250 if (sReadersContexts[i]->vHandle == 0)
264 parentNode = RFSetReaderName(sReadersContexts[dwContext], readerName,
269 sReadersContexts[dwContext]->
library = strdup(library);
270 sReadersContexts[dwContext]->
device = strdup(device);
271 sReadersContexts[dwContext]->
version = 0;
272 sReadersContexts[dwContext]->
port = port;
273 sReadersContexts[dwContext]->
mMutex = NULL;
274 sReadersContexts[dwContext]->
contexts = 0;
275 sReadersContexts[dwContext]->
pthThread = 0;
276 sReadersContexts[dwContext]->
hLockId = 0;
277 sReadersContexts[dwContext]->
LockCount = 0;
278 sReadersContexts[dwContext]->
vHandle = NULL;
279 sReadersContexts[dwContext]->
pFeeds = NULL;
280 sReadersContexts[dwContext]->
pMutex = NULL;
283 lrv = list_init(&sReadersContexts[dwContext]->handlesList);
286 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
290 lrv = list_attributes_seeker(&sReadersContexts[dwContext]->handlesList,
291 RDR_CLIHANDLES_seeker);
294 Log2(PCSC_LOG_CRITICAL,
295 "list_attributes_seeker failed with return value: %d", lrv);
299 (void)pthread_mutex_init(&sReadersContexts[dwContext]->handlesList_lock,
302 (void)pthread_mutex_init(&sReadersContexts[dwContext]->powerState_lock,
304 sReadersContexts[dwContext]->
powerState = POWER_STATE_UNPOWERED;
307 sReadersContexts[dwContext]->
reference = 1;
312 sReadersContexts[dwContext]->
pFeeds =
313 sReadersContexts[parentNode]->
pFeeds;
314 *(sReadersContexts[dwContext])->pFeeds += 1;
315 sReadersContexts[dwContext]->
vHandle =
316 sReadersContexts[parentNode]->
vHandle;
317 sReadersContexts[dwContext]->
mMutex =
318 sReadersContexts[parentNode]->
mMutex;
319 sReadersContexts[dwContext]->
pMutex =
320 sReadersContexts[parentNode]->
pMutex;
323 dwGetSize =
sizeof(ucThread);
327 if (rv ==
IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
329 Log1(PCSC_LOG_INFO,
"Driver is thread safe");
330 sReadersContexts[dwContext]->
mMutex = NULL;
331 sReadersContexts[dwContext]->
pMutex = NULL;
334 *(sReadersContexts[dwContext])->pMutex += 1;
337 if (sReadersContexts[dwContext]->pFeeds == NULL)
339 sReadersContexts[dwContext]->
pFeeds = malloc(
sizeof(
int));
345 *(sReadersContexts[dwContext])->pFeeds = 1;
348 if (sReadersContexts[dwContext]->mMutex == 0)
350 sReadersContexts[dwContext]->
mMutex =
351 malloc(
sizeof(pthread_mutex_t));
352 (void)pthread_mutex_init(sReadersContexts[dwContext]->mMutex, NULL);
355 if (sReadersContexts[dwContext]->pMutex == NULL)
357 sReadersContexts[dwContext]->
pMutex = malloc(
sizeof(
int));
358 *(sReadersContexts[dwContext])->pMutex = 1;
361 dwNumReadersContexts += 1;
363 rv = RFInitializeReader(sReadersContexts[dwContext]);
366 int log_level = PCSC_LOG_ERROR;
368 log_level = PCSC_LOG_INFO;
371 Log2(log_level,
"%s init failed.", readerName);
372 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
378 RESPONSECODE (*fct)(DWORD, int) = NULL;
380 dwGetSize =
sizeof(fct);
386 Log1(PCSC_LOG_INFO,
"Using the pcscd polling thread");
391 Log1(PCSC_LOG_INFO,
"Using the reader polling thread");
394 rv = EHSpawnEventHandler(sReadersContexts[dwContext]);
397 Log2(PCSC_LOG_ERROR,
"%s init failed.", readerName);
398 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
406 if (ReaderEvents < 0)
410 dwGetSize =
sizeof(ucGetData);
414 int nbSlots = ucGetData[0];
415 if (rv !=
IFD_SUCCESS || dwGetSize != 1 || nbSlots == 0)
430 for (j = 1; j < nbSlots; j++)
432 char *tmpReader = NULL;
433 DWORD dwContextB = 0;
434 RESPONSECODE (*fct)(DWORD, int) = NULL;
439 if (sReadersContexts[i]->vHandle == 0)
449 RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
456 sReadersContexts[dwContext]->readerState->readerName,
457 sizeof(sReadersContexts[dwContextB]->readerState->readerName));
458 snprintf(tmpReader + strlen(tmpReader) - 2, 3,
"%02X", j);
460 sReadersContexts[dwContextB]->
library =
461 sReadersContexts[dwContext]->
library;
462 sReadersContexts[dwContextB]->
device =
463 sReadersContexts[dwContext]->
device;
464 sReadersContexts[dwContextB]->
version =
465 sReadersContexts[dwContext]->
version;
466 sReadersContexts[dwContextB]->
port =
467 sReadersContexts[dwContext]->
port;
468 sReadersContexts[dwContextB]->
vHandle =
469 sReadersContexts[dwContext]->
vHandle;
470 sReadersContexts[dwContextB]->
mMutex =
471 sReadersContexts[dwContext]->
mMutex;
472 sReadersContexts[dwContextB]->
pMutex =
473 sReadersContexts[dwContext]->
pMutex;
474 sReadersContexts[dwContextB]->
slot =
475 sReadersContexts[dwContext]->
slot + j;
482 sReadersContexts[dwContextB]->
pFeeds =
483 sReadersContexts[dwContext]->
pFeeds;
486 *(sReadersContexts[dwContextB])->pFeeds += 1;
488 sReadersContexts[dwContextB]->
contexts = 0;
489 sReadersContexts[dwContextB]->
hLockId = 0;
490 sReadersContexts[dwContextB]->
LockCount = 0;
492 lrv = list_init(&sReadersContexts[dwContextB]->handlesList);
495 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
499 lrv = list_attributes_seeker(&sReadersContexts[dwContextB]->handlesList,
500 RDR_CLIHANDLES_seeker);
503 Log2(PCSC_LOG_CRITICAL,
504 "list_attributes_seeker failed with return value: %d", lrv);
508 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->handlesList_lock, NULL);
509 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->powerState_lock,
511 sReadersContexts[dwContextB]->
powerState = POWER_STATE_UNPOWERED;
514 sReadersContexts[dwContextB]->
reference = 1;
517 dwGetSize =
sizeof(ucThread);
521 if (rv ==
IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
523 Log1(PCSC_LOG_INFO,
"Driver is slot thread safe");
525 sReadersContexts[dwContextB]->
library =
526 strdup(sReadersContexts[dwContext]->library);
527 sReadersContexts[dwContextB]->
device =
528 strdup(sReadersContexts[dwContext]->device);
529 sReadersContexts[dwContextB]->
mMutex =
530 malloc(
sizeof(pthread_mutex_t));
531 (void)pthread_mutex_init(sReadersContexts[dwContextB]->mMutex,
534 sReadersContexts[dwContextB]->
pMutex = malloc(
sizeof(
int));
535 *(sReadersContexts[dwContextB])->pMutex = 1;
538 *(sReadersContexts[dwContextB])->pMutex += 1;
540 dwNumReadersContexts += 1;
542 rv = RFInitializeReader(sReadersContexts[dwContextB]);
546 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
551 dwGetSize =
sizeof(fct);
557 Log1(PCSC_LOG_INFO,
"Using the pcscd polling thread");
562 Log1(PCSC_LOG_INFO,
"Using the reader polling thread");
565 rv = EHSpawnEventHandler(sReadersContexts[dwContextB]);
568 Log2(PCSC_LOG_ERROR,
"%s init failed.", readerName);
569 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
577LONG RFRemoveReader(
const char *readerName,
int port,
int flags)
579 char lpcStripReader[MAX_READERNAME];
586 if (readerName == NULL)
590 extend =
SYS_GetEnv(
"PCSCLITE_FILTER_EXTEND_READER_NAMES");
592 extend_size = strlen(extend);
597 if (sReadersContexts[i] && (sReadersContexts[i]->vHandle != 0))
599 strncpy(lpcStripReader,
600 sReadersContexts[i]->readerState->readerName,
601 sizeof(lpcStripReader));
602 lpcStripReader[strlen(lpcStripReader) - 6 - extend_size] = 0;
605 if ((strncmp(readerName, lpcStripReader, MAX_READERNAME -
sizeof(
" 00 00")) == 0)
606 && (port == sReadersContexts[i]->port))
608 if (flags & REMOVE_READER_FLAG_REMOVED)
615 valueLength =
sizeof(tagValue);
627 UNREF_READER(sReadersContexts[i])
635 if (ReaderEvents < 0)
644 if (sContext -> pthThread)
645 EHDestroyEventHandler(sContext);
647 if ((NULL == sContext->
pMutex) || (NULL == sContext->
pFeeds))
650 "Trying to remove an already removed driver");
654 RFUnInitializeReader(sContext);
659 if (0 == *sContext->
pMutex)
661 (void)pthread_mutex_destroy(sContext->
mMutex);
673 if (*sContext->
pFeeds == 0)
689 while (list_size(&sContext->handlesList) != 0)
694 currentHandle = list_get_at(&sContext->handlesList, 0);
695 lrv = list_delete_at(&sContext->handlesList, 0);
697 Log2(PCSC_LOG_CRITICAL,
698 "list_delete_at failed with return value: %d", lrv);
704 list_destroy(&sContext->handlesList);
705 dwNumReadersContexts -= 1;
713LONG RFSetReaderName(
READER_CONTEXT * rContext,
const char *readerName,
714 const char *libraryName,
int port)
718 int currentDigit = -1;
719 int supportedChannels = 0;
722 const char *extend =
"";
726 usedDigits[i] =
false;
728 if (dwNumReadersContexts != 0)
732 if (sReadersContexts[i]->vHandle != 0)
734 if (strcmp(sReadersContexts[i]->library, libraryName) == 0)
740 valueLength =
sizeof(tagValue);
743 &valueLength, tagValue);
748 supportedChannels = tagValue[0];
750 "Support %d simultaneous readers", tagValue[0]);
753 supportedChannels = 1;
756 if ((((sReadersContexts[i]->port & 0xFFFF0000) ==
757 PCSCLITE_HP_BASE_PORT)
758 && (sReadersContexts[i]->port != port))
759 || (supportedChannels > 1))
775 currentDigit = strtol(reader + strlen(reader) - 5, NULL, 16);
778 usedDigits[currentDigit] =
true;
789 if (currentDigit != -1)
794 if (usedDigits[i] ==
false)
804 if (i >= supportedChannels)
806 Log3(PCSC_LOG_ERROR,
"Driver %s does not support more than "
807 "%d reader(s). Maybe the driver should support "
808 "TAG_IFD_SIMULTANEOUS_ACCESS", libraryName, supportedChannels);
814 extend =
SYS_GetEnv(
"PCSCLITE_FILTER_EXTEND_READER_NAMES");
821 readerName, extend, i);
824 rContext->
slot = i << 16;
829LONG RFReaderInfo(
const char *readerName,
READER_CONTEXT ** sReader)
833 if (readerName == NULL)
838 if (sReadersContexts[i]->vHandle != 0)
840 if (strcmp(readerName,
841 sReadersContexts[i]->readerState->readerName) == 0)
844 REF_READER(sReadersContexts[i])
846 *sReader = sReadersContexts[i];
861 if (sReadersContexts[i]->vHandle != 0)
864 (void)pthread_mutex_lock(&sReadersContexts[i]->handlesList_lock);
865 currentHandle = list_seek(&sReadersContexts[i]->handlesList,
867 (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock);
868 if (currentHandle != NULL)
871 REF_READER(sReadersContexts[i])
873 *sReader = sReadersContexts[i];
887 Log2(PCSC_LOG_INFO,
"Reusing already loaded driver for %s",
904 rv = DYN_GetAddress(rContext->
vHandle, &f,
"IFDHCreateChannelByName",
true);
908 rContext->
version = IFD_HVERSION_3_0;
912 rv = DYN_GetAddress(rContext->
vHandle, &f,
"IFDHCreateChannel",
false);
916 rContext->
version = IFD_HVERSION_2_0;
921 Log1(PCSC_LOG_CRITICAL,
"IFDHandler functions missing");
926 if (rContext->
version == IFD_HVERSION_2_0)
929#define GET_ADDRESS_OPTIONALv2(s, code) \
932 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s, false); \
933 if (SCARD_S_SUCCESS != rvl) \
937 rContext->psFunctions.psFunctions_v2.pvf ## s = f1; \
940#define GET_ADDRESSv2(s) \
941 GET_ADDRESS_OPTIONALv2(s, \
942 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
945 Log1(PCSC_LOG_INFO,
"Loading IFD Handler 2.0");
947 GET_ADDRESSv2(CreateChannel)
948 GET_ADDRESSv2(CloseChannel)
949 GET_ADDRESSv2(GetCapabilities)
950 GET_ADDRESSv2(SetCapabilities)
951 GET_ADDRESSv2(PowerICC)
952 GET_ADDRESSv2(TransmitToICC)
953 GET_ADDRESSv2(ICCPresence)
954 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
956 GET_ADDRESSv2(Control)
958 else if (rContext->version == IFD_HVERSION_3_0)
961#define GET_ADDRESS_OPTIONALv3(s, code) \
964 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s, false); \
965 if (SCARD_S_SUCCESS != rvl) \
969 rContext->psFunctions.psFunctions_v3.pvf ## s = f1; \
972#define GET_ADDRESSv3(s) \
973 GET_ADDRESS_OPTIONALv3(s, \
974 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
977 Log1(PCSC_LOG_INFO,
"Loading IFD Handler 3.0");
979 GET_ADDRESSv2(CreateChannel)
980 GET_ADDRESSv2(CloseChannel)
981 GET_ADDRESSv2(GetCapabilities)
982 GET_ADDRESSv2(SetCapabilities)
983 GET_ADDRESSv2(PowerICC)
984 GET_ADDRESSv2(TransmitToICC)
985 GET_ADDRESSv2(ICCPresence)
986 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
988 GET_ADDRESSv3(CreateChannelByName)
989 GET_ADDRESSv3(Control)
994 Log1(PCSC_LOG_CRITICAL,
"IFD Handler not 1.0/2.0 or 3.0");
1012 if (*rContext->
pFeeds == 1)
1014 Log1(PCSC_LOG_INFO,
"Unloading reader driver.");
1015 (void)DYN_CloseLibrary(rContext->
vHandle);
1036 (void)pthread_mutex_lock(&LockMutex);
1037 rv = RFCheckSharing(hCard, rContext);
1043 (void)pthread_mutex_unlock(&LockMutex);
1052 (void)pthread_mutex_lock(&LockMutex);
1053 rv = RFCheckSharing(hCard, rContext);
1076 (void)pthread_mutex_unlock(&LockMutex);
1085 (void)pthread_mutex_lock(&LockMutex);
1086 rv = RFCheckSharing(hCard, rContext);
1092 (void)pthread_mutex_unlock(&LockMutex);
1103 Log3(PCSC_LOG_INFO,
"Attempting startup of %s using %s",
1106#ifndef PCSCLITE_STATIC_DRIVER
1108 rv = RFLoadReader(rContext);
1111 Log2(PCSC_LOG_ERROR,
"RFLoadReader failed: 0x%lX", rv);
1116 rv = RFBindFunctions(rContext);
1120 Log2(PCSC_LOG_ERROR,
"RFBindFunctions failed: 0x%lX", rv);
1121 (void)RFUnloadReader(rContext);
1126 rContext->
vHandle = RFInitializeReader;
1134 int log_level = PCSC_LOG_CRITICAL;
1140 log_level = PCSC_LOG_INFO;
1144 Log3(log_level,
"Open Port 0x%X Failed (%s)",
1149 rContext->
slot = -1;
1157 Log2(PCSC_LOG_INFO,
"Attempting shutdown of %s.",
1161 if (rContext->
slot != -1)
1164 (void)RFUnBindFunctions(rContext);
1165 (void)RFUnloadReader(rContext);
1203 ret = RFReaderInfoById(randHandle, &dummy_reader);
1205 UNREF_READER(dummy_reader)
1216 int listLength, lrv;
1221 listLength = list_size(&rContext->handlesList);
1224 if (listLength >= maxReaderHandles)
1226 Log2(PCSC_LOG_CRITICAL,
1227 "Too many handles opened, exceeding configured max (%d)",
1234 if (NULL == newHandle)
1236 Log1(PCSC_LOG_CRITICAL,
"malloc failed");
1241 newHandle->
hCard = hCard;
1244 lrv = list_append(&rContext->handlesList, newHandle);
1248 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
1264 currentHandle = list_seek(&rContext->handlesList, &hCard);
1265 if (NULL == currentHandle)
1267 Log2(PCSC_LOG_CRITICAL,
"list_seek failed to locate hCard=%lX", hCard);
1272 lrv = list_delete(&rContext->handlesList, currentHandle);
1274 Log2(PCSC_LOG_CRITICAL,
1275 "list_delete failed with return value: %d", lrv);
1277 free(currentHandle);
1286void RFSetReaderEventState(
READER_CONTEXT * rContext, DWORD dwEvent)
1289 int list_index, listSize;
1293 listSize = list_size(&rContext->handlesList);
1295 for (list_index = 0; list_index < listSize; list_index++)
1297 currentHandle = list_get_at(&rContext->handlesList, list_index);
1298 if (NULL == currentHandle)
1300 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed at index %d",
1309 if (SCARD_REMOVED == dwEvent)
1323 DWORD dwEventStatus;
1326 currentHandle = list_seek(&rContext->handlesList, &hCard);
1328 if (NULL == currentHandle)
1331 Log2(PCSC_LOG_CRITICAL,
"list_seek failed for hCard 0x%lX", hCard);
1336 switch(dwEventStatus)
1362 currentHandle = list_seek(&rContext->handlesList, &hCard);
1364 if (NULL == currentHandle)
1384void RFCleanupReaders(
void)
1388 Log1(PCSC_LOG_INFO,
"entering cleaning function");
1391 if (sReadersContexts[i]->vHandle != 0)
1394 char lpcStripReader[MAX_READERNAME];
1396 Log2(PCSC_LOG_INFO,
"Stopping reader: %s",
1397 sReadersContexts[i]->readerState->readerName);
1399 strncpy(lpcStripReader,
1400 sReadersContexts[i]->readerState->readerName,
1401 sizeof(lpcStripReader));
1403 lpcStripReader[strlen(lpcStripReader) - 6] =
'\0';
1405 rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->port,
1406 REMOVE_READER_NO_FLAG);
1409 Log2(PCSC_LOG_ERROR,
"RFRemoveReader error: %s", rv2text(rv));
1412 free(sReadersContexts[i]);
1413 sReadersContexts[i] = NULL;
1430void RFWaitForReaderInit(
void)
1436 need_to_wait =
false;
1440 if (sReadersContexts[i] && sReadersContexts[i]->vHandle != NULL)
1444 == sReadersContexts[i]->readerState->cardAtrLength)
1446 Log2(PCSC_LOG_DEBUG,
"Waiting init for reader: %s",
1447 sReadersContexts[i]->readerState->readerName);
1448 need_to_wait =
true;
1455 }
while (need_to_wait);
1460int RFStartSerialReaders(
const char *readerconf)
1466 ConfigFile = strdup(readerconf);
1468 rv = DBGetReaderListDir(readerconf, &reader_list);
1471 if (NULL == reader_list)
1478 (void)RFAddReader(reader_list[i].pcFriendlyname,
1479 reader_list[i].channelId,
1480 reader_list[i].pcLibpath, reader_list[i].pcDevicename);
1484 ConfigFileCRC += reader_list[i].pcFriendlyname[j];
1485 for (j=0; j<reader_list[i].
pcLibpath[j]; j++)
1486 ConfigFileCRC += reader_list[i].pcLibpath[j];
1488 ConfigFileCRC += reader_list[i].pcDevicename[j];
1491 free(reader_list[i].pcFriendlyname);
1492 free(reader_list[i].pcLibpath);
1493 free(reader_list[i].pcDevicename);
1500void RFReCheckReaderConf(
void)
1505 (void)DBGetReaderListDir(ConfigFile, &reader_list);
1508 if (NULL == reader_list)
1518 crc += reader_list[i].pcFriendlyname[j];
1519 for (j=0; j<reader_list[i].
pcLibpath[j]; j++)
1520 crc += reader_list[i].pcLibpath[j];
1522 crc += reader_list[i].pcDevicename[j];
1526 if (crc != ConfigFileCRC)
1528 Log2(PCSC_LOG_CRITICAL,
1529 "configuration file: %s has been modified. Recheck canceled",
1537 char present =
false;
1539 Log2(PCSC_LOG_DEBUG,
"refresh reader: %s",
1540 reader_list[i].pcFriendlyname);
1545 if (sReadersContexts[r]->vHandle != 0)
1547 char lpcStripReader[MAX_READERNAME];
1551 strncpy(lpcStripReader,
1552 sReadersContexts[i]->readerState->readerName,
1553 sizeof(lpcStripReader));
1554 tmplen = strlen(lpcStripReader);
1555 lpcStripReader[tmplen - 6] = 0;
1557 if ((strcmp(reader_list[i].pcFriendlyname, lpcStripReader) == 0)
1558 && (reader_list[r].channelId == sReadersContexts[i]->port))
1569 Log2(PCSC_LOG_INFO,
"Reader %s disappeared",
1570 reader_list[i].pcFriendlyname);
1571 (void)RFRemoveReader(reader_list[i].pcFriendlyname,
1572 reader_list[r].channelId, REMOVE_READER_NO_FLAG);
1581 (void)RFAddReader(reader_list[i].pcFriendlyname,
1582 reader_list[i].channelId, reader_list[i].pcLibpath,
1583 reader_list[i].pcDevicename);
1586 free(reader_list[i].pcFriendlyname);
1587 free(reader_list[i].pcLibpath);
1588 free(reader_list[i].pcDevicename);
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_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()
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
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.
SCARDHANDLE hCard
hCard for this connection
_Atomic DWORD dwEventStatus
Recent event that must be sent.
RESPONSECODE(* pthCardEvent)(DWORD, int)
Card Event sync.
pthread_mutex_t * mMutex
Mutex for this connection.
pthread_mutex_t powerState_lock
powerState mutex
pthread_t pthThread
Event polling thread.
_Atomic int32_t contexts
Number of open contexts.
union ReaderContext::@3 psFunctions
driver functions
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.
struct pubReaderStatesList * readerState
link to the reader state
_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.
Define an exported public reader state structure so each application gets instant notification of cha...
_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.