74#define BUS_DEVICE_STRSIZE 10+1+10+1+10+1
76#define READER_ABSENT 0
77#define READER_PRESENT 1
78#define READER_FAILED 2
80extern bool Add_Interface_In_Name;
81extern bool Add_Serial_In_Name;
86pthread_mutex_t usbNotifierMutex;
88static pthread_t usbNotifyThread;
89static int driverSize = -1;
90static bool AraKiriHotPlug =
false;
91static int rescan_pipe[] = { -1, -1 };
92extern int HPForceReaderPolling;
95#define IFD_GENERATE_HOTPLUG 1
100static struct _driverTracker
103 unsigned int productID;
110} *driverTracker = NULL;
111#define DRIVER_TRACKER_SIZE_STEP 8
116static struct _readerTracker
119 char bus_device[BUS_DEVICE_STRSIZE];
123static LONG HPAddHotPluggable(
struct libusb_device *dev,
124 struct libusb_device_descriptor desc,
125 const char bus_device[],
126 const struct libusb_interface *idesc,
127 struct _driverTracker *driver,
128 struct _driverTracker *classdriver);
129static LONG HPRemoveHotPluggable(
int reader_index);
130static void HPCleanupHotPluggable(
int reader_index);
132static LONG HPReadBundleValues(
const char * hpDirPath)
136 struct dirent *currFP = NULL;
137 char fullPath[FILENAME_MAX];
138 char fullLibPath[FILENAME_MAX];
141 hpDir = opendir(hpDirPath);
145 Log2(PCSC_LOG_ERROR,
"Cannot open PC/SC drivers directory: %s",
147 Log1(PCSC_LOG_ERROR,
"Disabling USB support for pcscd.");
152 driverTracker = calloc(DRIVER_TRACKER_SIZE_STEP,
sizeof(*driverTracker));
153 if (NULL == driverTracker)
155 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
158 driverSize = DRIVER_TRACKER_SIZE_STEP;
160#define GET_KEY(key, values) \
161 rv = LTPBundleFindValueWithKey(&plist, key, values); \
164 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
169 while ((currFP = readdir(hpDir)) != 0)
171 if (strstr(currFP->d_name,
".bundle") != 0)
175 list_t *manuIDs, *productIDs, *readerNames;
184 snprintf(fullPath,
sizeof(fullPath),
"%s/%s/Contents/Info.plist",
185 hpDirPath, currFP->d_name);
186 fullPath[
sizeof(fullPath) - 1] =
'\0';
193 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
194 libraryPath = list_get_at(values, 0);
195 (void)snprintf(fullLibPath,
sizeof(fullLibPath),
196 "%s/%s/Contents/%s/%s",
197 hpDirPath, currFP->d_name, PCSC_ARCH,
199 fullLibPath[
sizeof(fullLibPath) - 1] =
'\0';
202 GET_KEY(PCSCLITE_HP_CPCTKEY_NAME, &values)
203 ifdCapabilities = strtol(list_get_at(values, 0), NULL, 16);
205 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
206 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
207 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
215 CFBundleName = list_get_at(values, 0);
218 for (alias=0; alias<list_size(manuIDs); alias++)
223 value = list_get_at(manuIDs, alias);
224 driverTracker[listCount].manuID = strtol(value, NULL, 16);
226 value = list_get_at(productIDs, alias);
227 driverTracker[listCount].productID = strtol(value, NULL, 16);
229 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
232 driverTracker[listCount].bundleName = strdup(currFP->d_name);
233 driverTracker[listCount].libraryPath = strdup(fullLibPath);
234 driverTracker[listCount].ifdCapabilities = ifdCapabilities;
235 driverTracker[listCount].CFBundleName =
236 CFBundleName ? strdup(CFBundleName) : NULL;
239 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
240 driverTracker[listCount].readerName);
243 if (listCount >= driverSize)
248 driverSize += DRIVER_TRACKER_SIZE_STEP;
251 "Increase driverTracker to %d entries", driverSize);
253 void* tmp = realloc(driverTracker,
254 driverSize *
sizeof(*driverTracker));
258 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
266 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
268 driverTracker[i].manuID = 0;
269 driverTracker[i].productID = 0;
270 driverTracker[i].bundleName = NULL;
271 driverTracker[i].libraryPath = NULL;
272 driverTracker[i].readerName = NULL;
273 driverTracker[i].ifdCapabilities = 0;
274 driverTracker[i].CFBundleName = NULL;
282 driverSize = listCount;
287 Log2(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: %s",
289 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
293 Log2(PCSC_LOG_INFO,
"Found drivers for %d readers", listCount);
299static struct _driverTracker *get_driver(
unsigned int idVendor,
300 unsigned int idProduct,
struct _driverTracker **classdriver)
303 static struct _driverTracker *driver;
307 "Looking for a driver for VID: 0x%04X, PID: 0x%04X",
308 idVendor, idProduct);
314 for (i=0; i<driverSize; i++)
316 if (driverTracker[i].libraryPath != NULL &&
317 idVendor == driverTracker[i].manuID &&
318 idProduct == driverTracker[i].productID)
320 if ((driverTracker[i].CFBundleName != NULL)
321 && (0 == strcmp(driverTracker[i].CFBundleName,
"CCIDCLASSDRIVER")))
322 *classdriver = &driverTracker[i];
325 driver = &driverTracker[i];
337static void HPRescanUsbBus(
void)
340 char bus_device[BUS_DEVICE_STRSIZE];
341 libusb_device **devs, *dev;
346 readerTracker[i].status = READER_ABSENT;
348 cnt = libusb_get_device_list(ctx, &devs);
351 Log2(PCSC_LOG_CRITICAL,
"libusb_get_device_list() failed: %s",
352 libusb_error_name(cnt));
358 while ((dev = devs[cnt++]) != NULL)
360 struct libusb_device_descriptor desc;
361 struct libusb_config_descriptor *config_desc;
362 uint8_t bus_number = libusb_get_bus_number(dev);
363 uint8_t device_address = libusb_get_device_address(dev);
364 struct _driverTracker *driver, *classdriver;
367 int r = libusb_get_device_descriptor(dev, &desc);
371 "failed to get device descriptor for %d/%d: %s",
372 bus_number, device_address, libusb_error_name(r));
376 r = libusb_get_active_config_descriptor(dev, &config_desc);
379 Log4(PCSC_LOG_ERROR,
"failed to get device config for %d/%d: %s",
380 bus_number, device_address, libusb_error_name(r));
384 driver = get_driver(desc.idVendor, desc.idProduct, &classdriver);
389 Log3(PCSC_LOG_DEBUG,
"%d/%d is not a supported smart card reader",
390 bus_number, device_address);
392 libusb_free_config_descriptor(config_desc);
397 Log3(PCSC_LOG_DEBUG,
"Found matching USB device: %d:%d",
398 bus_number, device_address);
401 for (interface = 0;
interface < config_desc->bNumInterfaces;
407 snprintf(bus_device, BUS_DEVICE_STRSIZE,
"%d:%d:%d",
408 bus_number, device_address, interface);
409 bus_device[BUS_DEVICE_STRSIZE - 1] =
'\0';
415 if (strncmp(readerTracker[j].bus_device,
416 bus_device, BUS_DEVICE_STRSIZE) == 0)
419 readerTracker[j].status = READER_PRESENT;
422 Log2(PCSC_LOG_DEBUG,
"Refresh USB device: %s",
431 HPAddHotPluggable(dev, desc, bus_device,
432 &config_desc->interface[interface], driver, classdriver);
435 libusb_free_config_descriptor(config_desc);
443 if ((readerTracker[i].status == READER_ABSENT) &&
444 (readerTracker[i].fullName != NULL))
445 HPRemoveHotPluggable(i);
449 libusb_free_device_list(devs, 1);
457 if (readerTracker[i].fullName != NULL)
458 HPCleanupHotPluggable(i);
461 for (i=0; i<driverSize; i++)
464 free(driverTracker[i].bundleName);
465 free(driverTracker[i].libraryPath);
466 free(driverTracker[i].readerName);
467 free(driverTracker[i].CFBundleName);
471 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
472 pthread_exit(&retval);
476static void * HPEstablishUSBNotifications(
int pipefd[2])
482 r = libusb_init(ctx);
485 Log2(PCSC_LOG_CRITICAL,
"libusb_init failed: %s", libusb_error_name(r));
487 kill(getpid(), SIGTERM);
495 if (write(pipefd[1], &c, 1) == -1)
497 Log2(PCSC_LOG_ERROR,
"write: %s", strerror(errno));
503 for (
int i=0; i<driverSize; i++)
504 if (driverTracker[i].libraryPath)
505 if ((driverTracker[i].ifdCapabilities & IFD_GENERATE_HOTPLUG) == 0)
508 "Driver %s does not support IFD_GENERATE_HOTPLUG. Using active polling instead.",
509 driverTracker[i].bundleName);
510 if (HPForceReaderPolling < 1)
511 HPForceReaderPolling = 1;
515 if (HPForceReaderPolling)
518 "Polling forced every %d second(s)", HPForceReaderPolling);
524 while (!AraKiriHotPlug)
535 if (pipe(rescan_pipe) == -1)
537 Log2(PCSC_LOG_ERROR,
"pipe: %s", strerror(errno));
540 while (read(rescan_pipe[0], &dummy,
sizeof(dummy)) > 0)
542 Log1(PCSC_LOG_INFO,
"Reload serial configuration");
545 RFReCheckReaderConf();
547 Log1(PCSC_LOG_INFO,
"End reload serial configuration");
549 close(rescan_pipe[0]);
556LONG HPSearchHotPluggables(
const char * hpDirPath)
560 AraKiriHotPlug =
false;
563 readerTracker[i].status = READER_ABSENT;
564 readerTracker[i].bus_device[0] =
'\0';
565 readerTracker[i].fullName = NULL;
568 if (HPReadBundleValues(hpDirPath) > 0)
573 if (pipe(pipefd) == -1)
575 Log2(PCSC_LOG_ERROR,
"pipe: %s", strerror(errno));
579 ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
580 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd);
583 if (read(pipefd[0], &c, 1) == -1)
585 Log2(PCSC_LOG_ERROR,
"read: %s", strerror(errno));
597LONG HPStopHotPluggables(
void)
599 AraKiriHotPlug =
true;
600 if (rescan_pipe[1] >= 0)
602 close(rescan_pipe[1]);
609static LONG HPAddHotPluggable(
struct libusb_device *dev,
610 struct libusb_device_descriptor desc,
611 const char bus_device[],
612 const struct libusb_interface *idesc,
613 struct _driverTracker *driver,
614 struct _driverTracker *classdriver)
617 uint8_t iInterface = 0;
618 uint8_t iSerialNumber = 0;
621 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", bus_device);
623 i = asprintf(&deviceName,
"usb:%04x/%04x:libusb-1.0:%s",
624 desc.idVendor, desc.idProduct, bus_device);
627 Log1(PCSC_LOG_ERROR,
"asprintf() failed");
631 pthread_mutex_lock(&usbNotifierMutex);
636 if (readerTracker[i].fullName == NULL)
643 "Not enough reader entries. Already found %d readers", i);
644 pthread_mutex_unlock(&usbNotifierMutex);
648 strncpy(readerTracker[i].bus_device, bus_device,
649 sizeof(readerTracker[i].bus_device));
650 readerTracker[i].bus_device[
sizeof(readerTracker[i].bus_device) - 1] =
'\0';
651 readerTracker[i].fullName = NULL;
653 if (Add_Interface_In_Name && idesc->num_altsetting > 0)
654 iInterface = idesc->altsetting[0].iInterface;
656 if (Add_Serial_In_Name)
657 iSerialNumber = desc.iSerialNumber;
659 if (iSerialNumber != 0 || iInterface != 0)
661 libusb_device_handle *device;
664 ret = libusb_open(dev, &device);
667 Log2(PCSC_LOG_ERROR,
"libusb_open failed: %s",
668 libusb_error_name(ret));
672 unsigned char interfaceName[MAX_READERNAME];
673 unsigned char serialNumber[MAX_READERNAME];
674 char fullname[MAX_READERNAME * 3];
676 int ret_interface = 0;
681 ret_interface = libusb_get_string_descriptor_ascii(device,
682 iInterface, interfaceName,
sizeof interfaceName);
683 if (ret_interface < 0)
686 "libusb_get_string_descriptor_ascii failed: %s",
687 libusb_error_name(ret_interface));
693 ret_serial = libusb_get_string_descriptor_ascii(device,
694 iSerialNumber, serialNumber,
sizeof serialNumber);
698 "libusb_get_string_descriptor_ascii failed: %s",
699 libusb_error_name(ret_serial));
703 libusb_close(device);
705 if (ret_interface > 0 && ret_serial > 0)
707 snprintf(fullname,
sizeof(fullname),
"%s [%s] (%s)",
708 driver->readerName, interfaceName, serialNumber);
712 if (ret_interface > 0)
714 snprintf(fullname,
sizeof(fullname),
"%s [%s]",
715 driver->readerName, interfaceName);
721 snprintf(fullname,
sizeof(fullname),
"%s (%s)",
722 driver->readerName, serialNumber);
727 if (fullname[0] !=
'\0')
728 readerTracker[i].fullName = strdup(fullname);
732 if (readerTracker[i].fullName == NULL)
733 readerTracker[i].fullName = strdup(driver->readerName);
736 ret = RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
737 driver->libraryPath, deviceName);
739 readerTracker[i].status = READER_PRESENT;
742 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
745 if (classdriver && driver != classdriver)
748 ret = RFAddReader(readerTracker[i].fullName,
749 PCSCLITE_HP_BASE_PORT + i,
750 classdriver->libraryPath, deviceName);
753 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
755 readerTracker[i].status = READER_FAILED;
759 readerTracker[i].status = READER_FAILED;
762 if (READER_FAILED == readerTracker[i].status)
763 (void)CheckForOpenCT();
765 pthread_mutex_unlock(&usbNotifierMutex);
772static LONG HPRemoveHotPluggable(
int reader_index)
774 pthread_mutex_lock(&usbNotifierMutex);
776 Log3(PCSC_LOG_INFO,
"Removing USB device[%d]: %s", reader_index,
777 readerTracker[reader_index].bus_device);
779 RFRemoveReader(readerTracker[reader_index].fullName,
780 PCSCLITE_HP_BASE_PORT + reader_index, REMOVE_READER_FLAG_REMOVED);
781 HPCleanupHotPluggable(reader_index);
783 pthread_mutex_unlock(&usbNotifierMutex);
788static void HPCleanupHotPluggable(
int reader_index)
790 free(readerTracker[reader_index].fullName);
791 readerTracker[reader_index].status = READER_ABSENT;
792 readerTracker[reader_index].bus_device[0] =
'\0';
793 readerTracker[reader_index].fullName = NULL;
799ULONG HPRegisterForHotplugEvents(
const char * hpDirPath)
803 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
807void HPReCheckSerialReaders(
void)
810 if (rescan_pipe[1] >= 0)
813 if (write(rescan_pipe[1], &dummy,
sizeof(dummy)) == -1)
814 Log2(PCSC_LOG_ERROR,
"write: %s", strerror(errno));
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
#define SCARD_S_SUCCESS
No error was encountered.
This provides a search API for hot pluggble devices.
Reads lexical config files and updates database.
int LTPBundleFindValueWithKey(list_t *l, const char *key, list_t **values)
Find an optional key in a configuration file No error is logged if the key is not found.
void bundleRelease(list_t *l)
Free the list created by bundleParse()
int bundleParse(const char *fileName, list_t *l)
Parse a Info.plist file and file a list.
This keeps a list of defines for pcsc-lite.
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
This keeps track of a list of currently available reader structures.
This handles abstract system level calls.
int SYS_Sleep(int)
Makes the current process sleep for some seconds.
This defines some structures and #defines to be used over the transport layer.
This keeps a list of Windows(R) types.