46 #include <sys/types.h>
72 #define BUS_DEVICE_STRSIZE 10+1+10+1+10+1
74 #define READER_ABSENT 0
75 #define READER_PRESENT 1
76 #define READER_FAILED 2
81 extern char Add_Interface_In_Name;
82 extern char Add_Serial_In_Name;
87 pthread_mutex_t usbNotifierMutex;
89 static pthread_t usbNotifyThread;
90 static int driverSize = -1;
91 static char AraKiriHotPlug = FALSE;
92 static int rescan_pipe[] = { -1, -1 };
93 extern int HPForceReaderPolling;
96 #define IFD_GENERATE_HOTPLUG 1
101 static struct _driverTracker
104 unsigned int productID;
111 } *driverTracker = NULL;
112 #define DRIVER_TRACKER_SIZE_STEP 8
117 static struct _readerTracker
120 char bus_device[BUS_DEVICE_STRSIZE];
124 static LONG HPAddHotPluggable(
struct libusb_device *dev,
125 struct libusb_device_descriptor desc,
126 const char bus_device[],
127 const struct libusb_interface *idesc,
128 struct _driverTracker *driver,
129 struct _driverTracker *classdriver);
130 static LONG HPRemoveHotPluggable(
int reader_index);
132 static LONG HPReadBundleValues(
void)
136 struct dirent *currFP = NULL;
137 char fullPath[FILENAME_MAX];
138 char fullLibPath[FILENAME_MAX];
141 hpDir = opendir(PCSCLITE_HP_DROPDIR);
145 Log1(PCSC_LOG_ERROR,
"Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
146 Log1(PCSC_LOG_ERROR,
"Disabling USB support for pcscd.");
151 driverTracker = calloc(DRIVER_TRACKER_SIZE_STEP,
sizeof(*driverTracker));
152 if (NULL == driverTracker)
154 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
157 driverSize = DRIVER_TRACKER_SIZE_STEP;
159 #define GET_KEY(key, values) \
160 rv = LTPBundleFindValueWithKey(&plist, key, values); \
163 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
168 while ((currFP = readdir(hpDir)) != 0)
170 if (strstr(currFP->d_name,
".bundle") != 0)
174 list_t *manuIDs, *productIDs, *readerNames;
183 snprintf(fullPath,
sizeof(fullPath),
"%s/%s/Contents/Info.plist",
184 PCSCLITE_HP_DROPDIR, currFP->d_name);
185 fullPath[
sizeof(fullPath) - 1] =
'\0';
187 rv = bundleParse(fullPath, &plist);
192 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
193 libraryPath = list_get_at(values, 0);
194 (void)snprintf(fullLibPath,
sizeof(fullLibPath),
195 "%s/%s/Contents/%s/%s",
196 PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
198 fullLibPath[
sizeof(fullLibPath) - 1] =
'\0';
201 GET_KEY(PCSCLITE_HP_CPCTKEY_NAME, &values)
202 ifdCapabilities = strtol(list_get_at(values, 0), NULL, 16);
204 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
205 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
206 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
209 rv = LTPBundleFindValueWithKey(&plist, PCSCLITE_HP_CFBUNDLE_NAME,
214 CFBundleName = strdup(list_get_at(values, 0));
217 for (alias=0; alias<list_size(manuIDs); alias++)
222 value = list_get_at(manuIDs, alias);
223 driverTracker[listCount].manuID = strtol(value, NULL, 16);
225 value = list_get_at(productIDs, alias);
226 driverTracker[listCount].productID = strtol(value, NULL, 16);
228 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
231 driverTracker[listCount].bundleName = strdup(currFP->d_name);
232 driverTracker[listCount].libraryPath = strdup(fullLibPath);
233 driverTracker[listCount].ifdCapabilities = ifdCapabilities;
234 driverTracker[listCount].CFBundleName = CFBundleName;
237 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
238 driverTracker[listCount].readerName);
241 if (listCount >= driverSize)
246 driverSize += DRIVER_TRACKER_SIZE_STEP;
249 "Increase driverTracker to %d entries", driverSize);
251 void* tmp = realloc(driverTracker,
252 driverSize *
sizeof(*driverTracker));
256 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
264 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
266 driverTracker[i].manuID = 0;
267 driverTracker[i].productID = 0;
268 driverTracker[i].bundleName = NULL;
269 driverTracker[i].libraryPath = NULL;
270 driverTracker[i].readerName = NULL;
271 driverTracker[i].ifdCapabilities = 0;
272 driverTracker[i].CFBundleName = NULL;
276 bundleRelease(&plist);
280 driverSize = listCount;
285 Log1(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR);
286 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
290 Log2(PCSC_LOG_INFO,
"Found drivers for %d readers", listCount);
296 static struct _driverTracker *get_driver(
unsigned int idVendor,
297 unsigned int idProduct,
struct _driverTracker **classdriver)
300 static struct _driverTracker *driver;
304 "Looking for a driver for VID: 0x%04X, PID: 0x%04X",
305 idVendor, idProduct);
311 for (i=0; i<driverSize; i++)
313 if (driverTracker[i].libraryPath != NULL &&
314 idVendor == driverTracker[i].manuID &&
315 idProduct == driverTracker[i].productID)
317 if ((driverTracker[i].CFBundleName != NULL)
318 && (0 == strcmp(driverTracker[i].CFBundleName,
"CCIDCLASSDRIVER")))
319 *classdriver = &driverTracker[i];
322 driver = &driverTracker[i];
334 static void HPRescanUsbBus(
void)
337 char bus_device[BUS_DEVICE_STRSIZE];
338 libusb_device **devs, *dev;
343 readerTracker[i].status = READER_ABSENT;
345 cnt = libusb_get_device_list(ctx, &devs);
348 Log2(PCSC_LOG_CRITICAL,
"libusb_get_device_list() failed: %s",
349 libusb_error_name(cnt));
355 while ((dev = devs[cnt++]) != NULL)
357 struct libusb_device_descriptor desc;
358 struct libusb_config_descriptor *config_desc;
359 uint8_t bus_number = libusb_get_bus_number(dev);
360 uint8_t device_address = libusb_get_device_address(dev);
361 struct _driverTracker *driver, *classdriver;
364 int r = libusb_get_device_descriptor(dev, &desc);
368 "failed to get device descriptor for %d/%d: %s",
369 bus_number, device_address, libusb_error_name(r));
373 r = libusb_get_active_config_descriptor(dev, &config_desc);
376 Log4(PCSC_LOG_ERROR,
"failed to get device config for %d/%d: %s",
377 bus_number, device_address, libusb_error_name(r));
381 driver = get_driver(desc.idVendor, desc.idProduct, &classdriver);
386 Log3(PCSC_LOG_DEBUG,
"%d/%d is not a supported smart card reader",
387 bus_number, device_address);
393 Log3(PCSC_LOG_DEBUG,
"Found matching USB device: %d:%d",
394 bus_number, device_address);
397 for (interface = 0;
interface < config_desc->bNumInterfaces;
403 snprintf(bus_device, BUS_DEVICE_STRSIZE,
"%d:%d:%d",
404 bus_number, device_address, interface);
405 bus_device[BUS_DEVICE_STRSIZE - 1] =
'\0';
411 if (strncmp(readerTracker[j].bus_device,
412 bus_device, BUS_DEVICE_STRSIZE) == 0)
415 readerTracker[j].status = READER_PRESENT;
418 Log2(PCSC_LOG_DEBUG,
"Refresh USB device: %s",
427 HPAddHotPluggable(dev, desc, bus_device,
428 &config_desc->interface[interface], driver, classdriver);
431 libusb_free_config_descriptor(config_desc);
439 if ((readerTracker[i].status == READER_ABSENT) &&
440 (readerTracker[i].fullName != NULL))
441 HPRemoveHotPluggable(i);
448 for (i=0; i<driverSize; i++)
451 free(driverTracker[i].bundleName);
452 free(driverTracker[i].libraryPath);
453 free(driverTracker[i].readerName);
454 free(driverTracker[i].CFBundleName);
458 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
459 pthread_exit(&retval);
463 libusb_free_device_list(devs, 1);
466 static void * HPEstablishUSBNotifications(
int pipefd[2])
472 r = libusb_init(ctx);
475 Log2(PCSC_LOG_CRITICAL,
"libusb_init failed: %s", libusb_error_name(r));
477 kill(getpid(), SIGTERM);
485 if (write(pipefd[1], &c, 1) == -1)
487 Log2(PCSC_LOG_ERROR,
"write: %s", strerror(errno));
493 for (i=0; i<driverSize; i++)
494 if (driverTracker[i].libraryPath)
495 if ((driverTracker[i].ifdCapabilities & IFD_GENERATE_HOTPLUG) == 0)
498 "Driver %s does not support IFD_GENERATE_HOTPLUG. Using active polling instead.",
499 driverTracker[i].bundleName);
500 if (HPForceReaderPolling < 1)
501 HPForceReaderPolling = 1;
505 if (HPForceReaderPolling)
508 "Polling forced every %d second(s)", HPForceReaderPolling);
514 while (!AraKiriHotPlug)
524 if (pipe(rescan_pipe) == -1)
526 Log2(PCSC_LOG_ERROR,
"pipe: %s", strerror(errno));
529 while (read(rescan_pipe[0], &dummy,
sizeof(dummy)) > 0)
531 Log1(PCSC_LOG_INFO,
"Reload serial configuration");
534 RFReCheckReaderConf();
536 Log1(PCSC_LOG_INFO,
"End reload serial configuration");
538 close(rescan_pipe[0]);
545 LONG HPSearchHotPluggables(
void)
551 readerTracker[i].status = READER_ABSENT;
552 readerTracker[i].bus_device[0] =
'\0';
553 readerTracker[i].fullName = NULL;
556 if (HPReadBundleValues() > 0)
561 if (pipe(pipefd) == -1)
563 Log2(PCSC_LOG_ERROR,
"pipe: %s", strerror(errno));
567 ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
568 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd);
571 if (read(pipefd[0], &c, 1) == -1)
573 Log2(PCSC_LOG_ERROR,
"read: %s", strerror(errno));
585 LONG HPStopHotPluggables(
void)
587 AraKiriHotPlug = TRUE;
588 if (rescan_pipe[1] >= 0)
590 close(rescan_pipe[1]);
597 static LONG HPAddHotPluggable(
struct libusb_device *dev,
598 struct libusb_device_descriptor desc,
599 const char bus_device[],
600 const struct libusb_interface *idesc,
601 struct _driverTracker *driver,
602 struct _driverTracker *classdriver)
605 uint8_t iInterface = 0;
606 uint8_t iSerialNumber = 0;
607 char deviceName[MAX_DEVICENAME];
609 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", bus_device);
611 snprintf(deviceName,
sizeof(deviceName),
"usb:%04x/%04x:libusb-1.0:%s",
612 desc.idVendor, desc.idProduct, bus_device);
614 deviceName[
sizeof(deviceName) -1] =
'\0';
616 pthread_mutex_lock(&usbNotifierMutex);
621 if (readerTracker[i].fullName == NULL)
628 "Not enough reader entries. Already found %d readers", i);
629 pthread_mutex_unlock(&usbNotifierMutex);
633 strncpy(readerTracker[i].bus_device, bus_device,
634 sizeof(readerTracker[i].bus_device));
635 readerTracker[i].bus_device[
sizeof(readerTracker[i].bus_device) - 1] =
'\0';
636 readerTracker[i].fullName = NULL;
638 if (Add_Interface_In_Name && idesc->num_altsetting > 0)
639 iInterface = idesc->altsetting[0].iInterface;
641 if (Add_Serial_In_Name)
642 iSerialNumber = desc.iSerialNumber;
644 if (iSerialNumber != 0 || iInterface != 0)
646 libusb_device_handle *device;
649 ret = libusb_open(dev, &device);
652 Log2(PCSC_LOG_ERROR,
"libusb_open failed: %s",
653 libusb_error_name(ret));
657 unsigned char interfaceName[MAX_READERNAME];
658 unsigned char serialNumber[MAX_READERNAME];
659 char fullname[MAX_READERNAME * 3];
661 int ret_interface = 0;
666 ret_interface = libusb_get_string_descriptor_ascii(device,
667 iInterface, interfaceName,
sizeof interfaceName);
668 if (ret_interface < 0)
671 "libusb_get_string_descriptor_ascii failed: %s",
672 libusb_error_name(ret_interface));
678 ret_serial = libusb_get_string_descriptor_ascii(device,
679 iSerialNumber, serialNumber,
sizeof serialNumber);
683 "libusb_get_string_descriptor_ascii failed: %s",
684 libusb_error_name(ret_serial));
688 libusb_close(device);
690 if (ret_interface > 0 && ret_serial > 0)
692 snprintf(fullname,
sizeof(fullname),
"%s [%s] (%s)",
693 driver->readerName, interfaceName, serialNumber);
697 if (ret_interface > 0)
699 snprintf(fullname,
sizeof(fullname),
"%s [%s]",
700 driver->readerName, interfaceName);
706 snprintf(fullname,
sizeof(fullname),
"%s (%s)",
707 driver->readerName, serialNumber);
712 if (fullname[0] !=
'\0')
713 readerTracker[i].fullName = strdup(fullname);
717 if (readerTracker[i].fullName == NULL)
718 readerTracker[i].fullName = strdup(driver->readerName);
721 ret = RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
722 driver->libraryPath, deviceName);
724 readerTracker[i].status = READER_PRESENT;
727 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
730 if (classdriver && driver != classdriver)
733 ret = RFAddReader(readerTracker[i].fullName,
734 PCSCLITE_HP_BASE_PORT + i,
735 classdriver->libraryPath, deviceName);
738 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
740 readerTracker[i].status = READER_FAILED;
744 readerTracker[i].status = READER_FAILED;
747 if (READER_FAILED == readerTracker[i].status)
748 (void)CheckForOpenCT();
750 pthread_mutex_unlock(&usbNotifierMutex);
755 static LONG HPRemoveHotPluggable(
int reader_index)
757 pthread_mutex_lock(&usbNotifierMutex);
759 Log3(PCSC_LOG_INFO,
"Removing USB device[%d]: %s", reader_index,
760 readerTracker[reader_index].bus_device);
762 RFRemoveReader(readerTracker[reader_index].fullName,
763 PCSCLITE_HP_BASE_PORT + reader_index);
764 free(readerTracker[reader_index].fullName);
765 readerTracker[reader_index].status = READER_ABSENT;
766 readerTracker[reader_index].bus_device[0] =
'\0';
767 readerTracker[reader_index].fullName = NULL;
769 pthread_mutex_unlock(&usbNotifierMutex);
777 ULONG HPRegisterForHotplugEvents(
void)
779 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
783 void HPReCheckSerialReaders(
void)
786 if (rescan_pipe[1] >= 0)
789 if (write(rescan_pipe[1], &dummy,
sizeof(dummy)) == -1)
790 Log2(PCSC_LOG_ERROR,
"write: %s", strerror(errno));