26 #include <sys/types.h>
42 #include "configfile.h"
52 static int maxReaderHandles = PCSC_MAX_READER_HANDLES;
53 static DWORD dwNumReadersContexts = 0;
55 static char *ConfigFile = NULL;
56 static int ConfigFileCRC = 0;
58 static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER;
60 #define IDENTITY_SHIFT 16
62 static int RDR_CLIHANDLES_seeker(
const void *el,
const void *key)
66 if ((el == NULL) || (key == NULL))
68 Log3(PCSC_LOG_CRITICAL,
69 "RDR_CLIHANDLES_seeker called with NULL pointer: el=%p, key=%p",
81 LONG RFAllocateReaderSpace(
unsigned int customMaxReaderHandles)
85 if (customMaxReaderHandles != 0)
86 maxReaderHandles = customMaxReaderHandles;
92 sReadersContexts[i]->
vHandle = NULL;
95 memset(readerStates[i].readerName, 0, MAX_READERNAME);
102 sReadersContexts[i]->
readerState = &readerStates[i];
106 return EHInitializeEventStructures();
109 LONG RFAddReader(
const char *readerName,
int port,
const char *library,
112 DWORD dwContext = 0, dwGetSize;
113 UCHAR ucGetData[1], ucThread[1];
118 if ((readerName == NULL) || (library == NULL) || (device == NULL))
122 if (strlen(readerName) > MAX_READERNAME -
sizeof(
" 00 00"))
125 "Reader name too long: %zd chars instead of max %zd",
126 strlen(readerName), MAX_READERNAME -
sizeof(
" 00 00"));
131 if (dwNumReadersContexts != 0)
135 if (sReadersContexts[i]->vHandle != 0)
137 char lpcStripReader[MAX_READERNAME];
141 strncpy(lpcStripReader,
142 sReadersContexts[i]->readerState->readerName,
143 sizeof(lpcStripReader));
144 tmplen = strlen(lpcStripReader);
145 lpcStripReader[tmplen - 6] = 0;
147 if ((strcmp(readerName, lpcStripReader) == 0) &&
148 (port == sReadersContexts[i]->port))
150 Log1(PCSC_LOG_ERROR,
"Duplicate reader found.");
160 if (sReadersContexts[i]->vHandle == 0)
167 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
174 parentNode = RFSetReaderName(sReadersContexts[dwContext], readerName,
179 sReadersContexts[dwContext]->
library = strdup(library);
180 sReadersContexts[dwContext]->
device = strdup(device);
181 sReadersContexts[dwContext]->
version = 0;
182 sReadersContexts[dwContext]->
port = port;
183 sReadersContexts[dwContext]->
mMutex = NULL;
184 sReadersContexts[dwContext]->
contexts = 0;
185 sReadersContexts[dwContext]->
pthThread = 0;
186 sReadersContexts[dwContext]->
hLockId = 0;
187 sReadersContexts[dwContext]->
LockCount = 0;
188 sReadersContexts[dwContext]->
vHandle = NULL;
189 sReadersContexts[dwContext]->
pFeeds = NULL;
190 sReadersContexts[dwContext]->
pMutex = NULL;
193 (dwContext + 1) << IDENTITY_SHIFT;
195 lrv = list_init(&sReadersContexts[dwContext]->handlesList);
198 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
202 lrv = list_attributes_seeker(&sReadersContexts[dwContext]->handlesList,
203 RDR_CLIHANDLES_seeker);
206 Log2(PCSC_LOG_CRITICAL,
207 "list_attributes_seeker failed with return value: %d", lrv);
211 (void)pthread_mutex_init(&sReadersContexts[dwContext]->handlesList_lock,
214 (void)pthread_mutex_init(&sReadersContexts[dwContext]->powerState_lock,
219 if (parentNode >= 0 && parentNode < PCSCLITE_MAX_READERS_CONTEXTS)
221 sReadersContexts[dwContext]->
pFeeds =
222 sReadersContexts[parentNode]->
pFeeds;
223 *(sReadersContexts[dwContext])->pFeeds += 1;
224 sReadersContexts[dwContext]->
vHandle =
225 sReadersContexts[parentNode]->
vHandle;
226 sReadersContexts[dwContext]->
mMutex =
227 sReadersContexts[parentNode]->
mMutex;
228 sReadersContexts[dwContext]->
pMutex =
229 sReadersContexts[parentNode]->
pMutex;
232 dwGetSize =
sizeof(ucThread);
236 if (rv ==
IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
238 Log1(PCSC_LOG_INFO,
"Driver is thread safe");
239 sReadersContexts[dwContext]->
mMutex = NULL;
240 sReadersContexts[dwContext]->
pMutex = NULL;
243 *(sReadersContexts[dwContext])->pMutex += 1;
246 if (sReadersContexts[dwContext]->pFeeds == NULL)
248 sReadersContexts[dwContext]->
pFeeds = malloc(
sizeof(
int));
254 *(sReadersContexts[dwContext])->pFeeds = 1;
257 if (sReadersContexts[dwContext]->mMutex == 0)
259 sReadersContexts[dwContext]->
mMutex =
260 malloc(
sizeof(pthread_mutex_t));
261 (void)pthread_mutex_init(sReadersContexts[dwContext]->mMutex, NULL);
264 if (sReadersContexts[dwContext]->pMutex == NULL)
266 sReadersContexts[dwContext]->
pMutex = malloc(
sizeof(
int));
267 *(sReadersContexts[dwContext])->pMutex = 1;
270 dwNumReadersContexts += 1;
272 rv = RFInitializeReader(sReadersContexts[dwContext]);
276 Log2(PCSC_LOG_ERROR,
"%s init failed.", readerName);
277 (void)RFRemoveReader(readerName, port);
283 RESPONSECODE (*fct)(DWORD, int) = NULL;
285 dwGetSize =
sizeof(fct);
291 Log1(PCSC_LOG_INFO,
"Using the pcscd polling thread");
296 Log1(PCSC_LOG_INFO,
"Using the reader polling thread");
299 rv = EHSpawnEventHandler(sReadersContexts[dwContext]);
302 Log2(PCSC_LOG_ERROR,
"%s init failed.", readerName);
303 (void)RFRemoveReader(readerName, port);
309 dwGetSize =
sizeof(ucGetData);
313 if (rv !=
IFD_SUCCESS || dwGetSize != 1 || ucGetData[0] == 0)
318 if (rv ==
IFD_SUCCESS && dwGetSize == 1 && ucGetData[0] == 1)
328 for (j = 1; j < ucGetData[0]; j++)
330 char *tmpReader = NULL;
331 DWORD dwContextB = 0;
332 RESPONSECODE (*fct)(DWORD, int) = NULL;
337 if (sReadersContexts[i]->vHandle == 0)
344 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
347 RFRemoveReader(readerName, port);
353 (void)strlcpy(tmpReader,
354 sReadersContexts[dwContext]->readerState->readerName,
356 snprintf(tmpReader + strlen(tmpReader) - 2, 3,
"%02X", j);
358 sReadersContexts[dwContextB]->
library =
359 sReadersContexts[dwContext]->
library;
360 sReadersContexts[dwContextB]->
device =
361 sReadersContexts[dwContext]->
device;
362 sReadersContexts[dwContextB]->
version =
363 sReadersContexts[dwContext]->
version;
364 sReadersContexts[dwContextB]->
port =
365 sReadersContexts[dwContext]->
port;
366 sReadersContexts[dwContextB]->
vHandle =
367 sReadersContexts[dwContext]->
vHandle;
368 sReadersContexts[dwContextB]->
mMutex =
369 sReadersContexts[dwContext]->
mMutex;
370 sReadersContexts[dwContextB]->
pMutex =
371 sReadersContexts[dwContext]->
pMutex;
372 sReadersContexts[dwContextB]->
slot =
373 sReadersContexts[dwContext]->
slot + j;
380 sReadersContexts[dwContextB]->
pFeeds =
381 sReadersContexts[dwContext]->
pFeeds;
384 *(sReadersContexts[dwContextB])->pFeeds += 1;
386 sReadersContexts[dwContextB]->
contexts = 0;
387 sReadersContexts[dwContextB]->
hLockId = 0;
388 sReadersContexts[dwContextB]->
LockCount = 0;
390 (dwContextB + 1) << IDENTITY_SHIFT;
392 lrv = list_init(&sReadersContexts[dwContextB]->handlesList);
395 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
399 lrv = list_attributes_seeker(&sReadersContexts[dwContextB]->handlesList,
400 RDR_CLIHANDLES_seeker);
403 Log2(PCSC_LOG_CRITICAL,
404 "list_attributes_seeker failed with return value: %d", lrv);
408 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->handlesList_lock, NULL);
409 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->powerState_lock,
414 dwGetSize =
sizeof(ucThread);
418 if (rv ==
IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
420 sReadersContexts[dwContextB]->
mMutex =
421 malloc(
sizeof(pthread_mutex_t));
422 (void)pthread_mutex_init(sReadersContexts[dwContextB]->mMutex,
425 sReadersContexts[dwContextB]->
pMutex = malloc(
sizeof(
int));
426 *(sReadersContexts[dwContextB])->pMutex = 1;
429 *(sReadersContexts[dwContextB])->pMutex += 1;
431 dwNumReadersContexts += 1;
433 rv = RFInitializeReader(sReadersContexts[dwContextB]);
437 (void)RFRemoveReader(readerName, port);
442 dwGetSize =
sizeof(fct);
448 Log1(PCSC_LOG_INFO,
"Using the pcscd polling thread");
453 Log1(PCSC_LOG_INFO,
"Using the reader polling thread");
456 rv = EHSpawnEventHandler(sReadersContexts[dwContextB]);
459 Log2(PCSC_LOG_ERROR,
"%s init failed.", readerName);
460 (void)RFRemoveReader(readerName, port);
468 LONG RFRemoveReader(
const char *readerName,
int port)
473 if (readerName == NULL)
477 RFReaderInfoNamePort(port, readerName, &sContext))
480 if (sContext -> pthThread)
481 (void)EHDestroyEventHandler(sContext);
483 if ((NULL == sContext->
pMutex) || (NULL == sContext->
pFeeds))
486 "Trying to remove an already removed driver");
490 rv = RFUnInitializeReader(sContext);
497 if (0 == *sContext->
pMutex)
499 (void)pthread_mutex_destroy(sContext->
mMutex);
511 if (*sContext->
pFeeds == 0)
528 while (list_size(&(sContext->handlesList)) != 0)
533 currentHandle = list_get_at(&(sContext->handlesList), 0);
534 lrv = list_delete_at(&(sContext->handlesList), 0);
536 Log2(PCSC_LOG_CRITICAL,
537 "list_delete_at failed with return value: %d", lrv);
543 list_destroy(&(sContext->handlesList));
544 dwNumReadersContexts -= 1;
553 LONG RFSetReaderName(
READER_CONTEXT * rContext,
const char *readerName,
554 const char *libraryName,
int port)
558 int currentDigit = -1;
559 int supportedChannels = 0;
565 usedDigits[i] = FALSE;
567 if (dwNumReadersContexts != 0)
571 if (sReadersContexts[i]->vHandle != 0)
573 if (strcmp(sReadersContexts[i]->library, libraryName) == 0)
579 valueLength =
sizeof(tagValue);
582 &valueLength, tagValue);
587 supportedChannels = tagValue[0];
589 "Support %d simultaneous readers", tagValue[0]);
592 supportedChannels = 1;
595 if ((((sReadersContexts[i]->port & 0xFFFF0000) ==
596 PCSCLITE_HP_BASE_PORT)
597 && (sReadersContexts[i]->port != port))
598 || (supportedChannels > 1))
614 currentDigit = strtol(reader + strlen(reader) - 5, NULL, 16);
617 usedDigits[currentDigit] = TRUE;
628 if (currentDigit != -1)
633 if (usedDigits[i] == FALSE)
637 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
639 Log2(PCSC_LOG_ERROR,
"Max number of readers reached: %d", PCSCLITE_MAX_READERS_CONTEXTS);
643 if (i >= supportedChannels)
645 Log3(PCSC_LOG_ERROR,
"Driver %s does not support more than "
646 "%d reader(s). Maybe the driver should support "
647 "TAG_IFD_SIMULTANEOUS_ACCESS", libraryName, supportedChannels);
657 rContext->
slot = i << 16;
662 LONG RFReaderInfo(
const char *readerName,
READER_CONTEXT ** sReader)
666 if (readerName == NULL)
671 if (sReadersContexts[i]->vHandle != 0)
673 if (strcmp(readerName,
674 sReadersContexts[i]->readerState->readerName) == 0)
676 *sReader = sReadersContexts[i];
685 LONG RFReaderInfoNamePort(
int port,
const char *readerName,
688 char lpcStripReader[MAX_READERNAME];
693 if (sReadersContexts[i]->vHandle != 0)
697 strncpy(lpcStripReader,
698 sReadersContexts[i]->readerState->readerName,
699 sizeof(lpcStripReader));
700 tmplen = strlen(lpcStripReader);
701 lpcStripReader[tmplen - 6] = 0;
703 if ((strcmp(readerName, lpcStripReader) == 0) &&
704 (port == sReadersContexts[i]->port))
706 *sReader = sReadersContexts[i];
715 LONG RFReaderInfoById(DWORD dwIdentity,
READER_CONTEXT * * sReader)
720 dwIdentity = dwIdentity >> IDENTITY_SHIFT;
721 dwIdentity = dwIdentity << IDENTITY_SHIFT;
725 if (dwIdentity == sReadersContexts[i]->dwIdentity)
727 *sReader = sReadersContexts[i];
739 Log2(PCSC_LOG_INFO,
"Reusing already loaded driver for %s",
753 rv = DYN_GetAddress(rContext->
vHandle, &f,
"IFDHCreateChannelByName");
757 rContext->
version = IFD_HVERSION_3_0;
761 rv = DYN_GetAddress(rContext->
vHandle, &f,
"IFDHCreateChannel");
765 rContext->
version = IFD_HVERSION_2_0;
770 Log1(PCSC_LOG_CRITICAL,
"IFDHandler functions missing");
775 if (rContext->
version == IFD_HVERSION_2_0)
778 #define GET_ADDRESS_OPTIONALv2(s, code) \
781 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s); \
782 if (SCARD_S_SUCCESS != rvl) \
786 rContext->psFunctions.psFunctions_v2.pvf ## s = f1; \
789 #define GET_ADDRESSv2(s) \
790 GET_ADDRESS_OPTIONALv2(s, \
791 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
794 Log1(PCSC_LOG_INFO,
"Loading IFD Handler 2.0");
796 GET_ADDRESSv2(CreateChannel)
797 GET_ADDRESSv2(CloseChannel)
798 GET_ADDRESSv2(GetCapabilities)
799 GET_ADDRESSv2(SetCapabilities)
800 GET_ADDRESSv2(PowerICC)
801 GET_ADDRESSv2(TransmitToICC)
802 GET_ADDRESSv2(ICCPresence)
803 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
805 GET_ADDRESSv2(Control)
807 else if (rContext->version == IFD_HVERSION_3_0)
810 #define GET_ADDRESS_OPTIONALv3(s, code) \
813 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s); \
814 if (SCARD_S_SUCCESS != rvl) \
818 rContext->psFunctions.psFunctions_v3.pvf ## s = f1; \
821 #define GET_ADDRESSv3(s) \
822 GET_ADDRESS_OPTIONALv3(s, \
823 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
826 Log1(PCSC_LOG_INFO,
"Loading IFD Handler 3.0");
828 GET_ADDRESSv2(CreateChannel)
829 GET_ADDRESSv2(CloseChannel)
830 GET_ADDRESSv2(GetCapabilities)
831 GET_ADDRESSv2(SetCapabilities)
832 GET_ADDRESSv2(PowerICC)
833 GET_ADDRESSv2(TransmitToICC)
834 GET_ADDRESSv2(ICCPresence)
835 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
837 GET_ADDRESSv3(CreateChannelByName)
838 GET_ADDRESSv3(Control)
843 Log1(PCSC_LOG_CRITICAL,
"IFD Handler not 1.0/2.0 or 3.0");
861 if (*rContext->
pFeeds == 1)
863 Log1(PCSC_LOG_INFO,
"Unloading reader driver.");
864 (void)DYN_CloseLibrary(&rContext->
vHandle);
884 (void)pthread_mutex_lock(&LockMutex);
885 rv = RFCheckSharing(hCard, rContext);
891 (void)pthread_mutex_unlock(&LockMutex);
900 (void)pthread_mutex_lock(&LockMutex);
901 rv = RFCheckSharing(hCard, rContext);
909 (void)pthread_mutex_unlock(&LockMutex);
918 (void)pthread_mutex_lock(&LockMutex);
919 rv = RFCheckSharing(hCard, rContext);
925 (void)pthread_mutex_unlock(&LockMutex);
935 Log3(PCSC_LOG_INFO,
"Attempting startup of %s using %s",
938 #ifndef PCSCLITE_STATIC_DRIVER
940 rv = RFLoadReader(rContext);
943 Log2(PCSC_LOG_ERROR,
"RFLoadReader failed: 0x%lX", rv);
948 rv = RFBindFunctions(rContext);
952 Log2(PCSC_LOG_ERROR,
"RFBindFunctions failed: 0x%lX", rv);
953 (void)RFUnloadReader(rContext);
958 rContext->
vHandle = RFInitializeReader;
966 Log3(PCSC_LOG_CRITICAL,
"Open Port 0x%X Failed (%s)",
986 Log2(PCSC_LOG_INFO,
"Attempting shutdown of %s.",
990 if (rContext->
slot != -1)
993 (void)RFUnBindFunctions(rContext);
994 (void)RFUnloadReader(rContext);
1021 randHandle = SYS_RandomInt(10, 65000);
1027 if (sReadersContexts[i]->vHandle != 0)
1030 list_t * l = &sReadersContexts[i]->handlesList;
1032 (void)pthread_mutex_lock(&sReadersContexts[i]->handlesList_lock);
1033 list_iterator_start(l);
1034 while (list_iterator_hasnext(l))
1036 currentHandle = list_iterator_next(l);
1037 if (((LONG)rContext->
dwIdentity + randHandle) ==
1038 (currentHandle->
hCard))
1041 randHandle = SYS_RandomInt(10, 65000);
1042 list_iterator_stop(l);
1043 (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock);
1047 list_iterator_stop(l);
1048 (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock);
1063 if (sReadersContexts[i]->vHandle != 0)
1066 (void)pthread_mutex_lock(&sReadersContexts[i]->handlesList_lock);
1067 currentHandle = list_seek(&sReadersContexts[i]->handlesList,
1069 (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock);
1070 if (currentHandle != NULL)
1086 int listLength, lrv;
1091 listLength = list_size(&(rContext->handlesList));
1094 if (listLength >= maxReaderHandles)
1096 Log2(PCSC_LOG_CRITICAL,
1097 "Too many handles opened, exceeding configured max (%d)",
1104 if (NULL == newHandle)
1106 Log1(PCSC_LOG_CRITICAL,
"malloc failed");
1111 newHandle->
hCard = hCard;
1114 lrv = list_append(&(rContext->handlesList), newHandle);
1118 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
1134 currentHandle = list_seek(&(rContext->handlesList), &hCard);
1135 if (NULL == currentHandle)
1137 Log2(PCSC_LOG_CRITICAL,
"list_seek failed to locate hCard=%lX", hCard);
1142 lrv = list_delete(&(rContext->handlesList), currentHandle);
1144 Log2(PCSC_LOG_CRITICAL,
1145 "list_delete failed with return value: %d", lrv);
1147 free(currentHandle);
1156 LONG RFSetReaderEventState(
READER_CONTEXT * rContext, DWORD dwEvent)
1159 int list_index, listSize;
1163 listSize = list_size(&(rContext->handlesList));
1165 for (list_index = 0; list_index < listSize; list_index++)
1167 currentHandle = list_get_at(&(rContext->handlesList), list_index);
1168 if (NULL == currentHandle)
1170 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed at index %d",
1195 currentHandle = list_seek(&(rContext->handlesList), &hCard);
1197 if (NULL == currentHandle)
1200 Log2(PCSC_LOG_CRITICAL,
"list_seek failed for hCard 0x%lX", hCard);
1230 currentHandle = list_seek(&(rContext->handlesList), &hCard);
1232 if (NULL == currentHandle)
1252 void RFCleanupReaders(
void)
1256 Log1(PCSC_LOG_INFO,
"entering cleaning function");
1259 if (sReadersContexts[i]->vHandle != 0)
1262 char lpcStripReader[MAX_READERNAME];
1264 Log2(PCSC_LOG_INFO,
"Stopping reader: %s",
1265 sReadersContexts[i]->readerState->readerName);
1267 strncpy(lpcStripReader,
1268 sReadersContexts[i]->readerState->readerName,
1269 sizeof(lpcStripReader));
1271 lpcStripReader[strlen(lpcStripReader) - 6] =
'\0';
1273 rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->port);
1276 Log2(PCSC_LOG_ERROR,
"RFRemoveReader error: 0x%08lX", rv);
1286 void RFWaitForReaderInit(
void)
1288 int i, need_to_wait;
1292 need_to_wait = FALSE;
1296 if (sReadersContexts[i]->vHandle != NULL)
1300 == sReadersContexts[i]->readerState->cardAtrLength)
1302 Log2(PCSC_LOG_DEBUG,
"Waiting init for reader: %s",
1303 sReadersContexts[i]->readerState->readerName);
1304 need_to_wait = TRUE;
1311 }
while (need_to_wait);
1316 int RFStartSerialReaders(
const char *readerconf)
1322 ConfigFile = strdup(readerconf);
1324 rv = DBGetReaderListDir(readerconf, &reader_list);
1327 if (NULL == reader_list)
1334 (void)RFAddReader(reader_list[i].pcFriendlyname,
1335 reader_list[i].channelId,
1336 reader_list[i].pcLibpath, reader_list[i].pcDevicename);
1340 ConfigFileCRC += reader_list[i].pcFriendlyname[j];
1341 for (j=0; j<reader_list[i].
pcLibpath[j]; j++)
1342 ConfigFileCRC += reader_list[i].pcLibpath[j];
1344 ConfigFileCRC += reader_list[i].pcDevicename[j];
1347 free(reader_list[i].pcFriendlyname);
1348 free(reader_list[i].pcLibpath);
1349 free(reader_list[i].pcDevicename);
1356 void RFReCheckReaderConf(
void)
1361 (void)DBGetReaderListDir(ConfigFile, &reader_list);
1364 if (NULL == reader_list)
1374 crc += reader_list[i].pcFriendlyname[j];
1375 for (j=0; j<reader_list[i].
pcLibpath[j]; j++)
1376 crc += reader_list[i].pcLibpath[j];
1378 crc += reader_list[i].pcDevicename[j];
1382 if (crc != ConfigFileCRC)
1384 Log2(PCSC_LOG_CRITICAL,
1385 "configuration file: %s has been modified. Recheck canceled",
1393 char present = FALSE;
1395 Log2(PCSC_LOG_DEBUG,
"refresh reader: %s",
1396 reader_list[i].pcFriendlyname);
1401 if (sReadersContexts[r]->vHandle != 0)
1403 char lpcStripReader[MAX_READERNAME];
1407 strncpy(lpcStripReader,
1408 sReadersContexts[i]->readerState->readerName,
1409 sizeof(lpcStripReader));
1410 tmplen = strlen(lpcStripReader);
1411 lpcStripReader[tmplen - 6] = 0;
1413 if ((strcmp(reader_list[i].pcFriendlyname, lpcStripReader) == 0)
1414 && (reader_list[r].channelId == sReadersContexts[i]->port))
1425 Log2(PCSC_LOG_INFO,
"Reader %s disappeared",
1426 reader_list[i].pcFriendlyname);
1427 (void)RFRemoveReader(reader_list[i].pcFriendlyname,
1428 reader_list[r].channelId);
1437 (void)RFAddReader(reader_list[i].pcFriendlyname,
1438 reader_list[i].channelId, reader_list[i].pcLibpath,
1439 reader_list[i].pcDevicename);
1442 free(reader_list[i].pcFriendlyname);
1443 free(reader_list[i].pcLibpath);
1444 free(reader_list[i].pcDevicename);