39#if defined(HAVE_LIBUDEV) && defined(USE_USB)
59#ifndef TEMP_FAILURE_RETRY
60#define TEMP_FAILURE_RETRY(expression) \
62 ({ long int __result; \
63 do __result = (long int) (expression); \
64 while (__result == -1L && errno == EINTR); \
70extern bool Add_Interface_In_Name;
71extern bool Add_Serial_In_Name;
73static pthread_t usbNotifyThread;
74static int driverSize = -1;
75static struct udev *Udev;
76static struct udev_monitor *Udev_monitor;
82static struct _driverTracker
85 unsigned int productID;
91} *driverTracker = NULL;
92#define DRIVER_TRACKER_SIZE_STEP 10
96#define DRIVER_TRACKER_INITIAL_SIZE 200
107struct _readerTracker *readerTracker = NULL;
108int readerTrackerNbEntries = -1;
111static LONG HPReadBundleValues(
const char * hpDirPath)
115 struct dirent *currFP = NULL;
116 char fullPath[FILENAME_MAX];
117 char fullLibPath[FILENAME_MAX];
120 hpDir = opendir(hpDirPath);
124 Log2(PCSC_LOG_ERROR,
"Cannot open PC/SC drivers directory: %s", hpDirPath);
125 Log1(PCSC_LOG_ERROR,
"Disabling USB support for pcscd.");
130 driverSize = DRIVER_TRACKER_INITIAL_SIZE;
131 driverTracker = calloc(driverSize,
sizeof(*driverTracker));
132 if (NULL == driverTracker)
134 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
135 (void)closedir(hpDir);
139#define GET_KEY(key, values) \
140 rv = LTPBundleFindValueWithKey(&plist, key, values); \
143 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
148 while ((currFP = readdir(hpDir)) != 0)
150 if (strstr(currFP->d_name,
".bundle") != 0)
154 list_t *manuIDs, *productIDs, *readerNames;
162 (void)snprintf(fullPath,
sizeof(fullPath),
"%s/%s/Contents/Info.plist",
163 hpDirPath, currFP->d_name);
164 fullPath[
sizeof(fullPath) - 1] =
'\0';
166 rv = bundleParse(fullPath, &plist);
171 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
172 libraryPath = list_get_at(values, 0);
173 (void)snprintf(fullLibPath,
sizeof(fullLibPath),
174 "%s/%s/Contents/%s/%s",
175 hpDirPath, currFP->d_name, PCSC_ARCH,
177 fullLibPath[
sizeof(fullLibPath) - 1] =
'\0';
179 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
180 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
181 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
183 if ((list_size(manuIDs) != list_size(productIDs))
184 || (list_size(manuIDs) != list_size(readerNames)))
186 Log2(PCSC_LOG_CRITICAL,
"Error parsing %s", fullPath);
187 (void)closedir(hpDir);
192 rv = LTPBundleFindValueWithKey(&plist, PCSCLITE_HP_CFBUNDLE_NAME,
197 CFBundleName = list_get_at(values, 0);
200 for (alias=0; alias<list_size(manuIDs); alias++)
205 value = list_get_at(manuIDs, alias);
206 driverTracker[listCount].manuID = strtol(value, NULL, 16);
208 value = list_get_at(productIDs, alias);
209 driverTracker[listCount].productID = strtol(value, NULL, 16);
211 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
214 driverTracker[listCount].bundleName = strdup(currFP->d_name);
215 driverTracker[listCount].libraryPath = strdup(fullLibPath);
216 driverTracker[listCount].CFBundleName = CFBundleName ? strdup(CFBundleName) : NULL;
219 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
220 driverTracker[listCount].readerName);
223 if (listCount >= driverSize)
228 driverSize += DRIVER_TRACKER_SIZE_STEP;
231 "Increase driverTracker to %d entries", driverSize);
234 void* tmp = realloc(driverTracker,
235 driverSize *
sizeof(*driverTracker));
240 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
242 (void)closedir(hpDir);
248 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
250 driverTracker[i].manuID = 0;
251 driverTracker[i].productID = 0;
252 driverTracker[i].bundleName = NULL;
253 driverTracker[i].libraryPath = NULL;
254 driverTracker[i].readerName = NULL;
255 driverTracker[i].CFBundleName = NULL;
259 bundleRelease(&plist);
263 driverSize = listCount;
264 (void)closedir(hpDir);
267 Log2(PCSC_LOG_INFO,
"Found drivers for %d readers", listCount);
274 static struct _driverTracker *get_driver(
struct udev_device *dev,
275 const char *devpath,
struct _driverTracker **classdriver)
278 unsigned int idVendor, idProduct;
279 static struct _driverTracker *driver;
282 str = udev_device_get_sysattr_value(dev,
"idVendor");
285 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
288 idVendor = strtol(str, NULL, 16);
290 str = udev_device_get_sysattr_value(dev,
"idProduct");
293 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
296 idProduct = strtol(str, NULL, 16);
302 "Looking for a driver for VID: 0x%04X, PID: 0x%04X, path: %s",
303 idVendor, idProduct, devpath);
308 for (i=0; i<driverSize; i++)
310 if (driverTracker[i].libraryPath != NULL &&
311 idVendor == driverTracker[i].manuID &&
312 idProduct == driverTracker[i].productID)
314 if ((driverTracker[i].CFBundleName != NULL)
315 && (0 == strcmp(driverTracker[i].CFBundleName,
"CCIDCLASSDRIVER")))
316 *classdriver = &driverTracker[i];
319 driver = &driverTracker[i];
332static void HPRemoveDevice(
struct udev_device *dev)
337 sysname = udev_device_get_sysname(dev);
340 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysname() failed");
344 for (i=0; i<readerTrackerNbEntries; i++)
346 if (readerTracker[i].fullName && !strcmp(sysname, readerTracker[i].sysname))
348 Log4(PCSC_LOG_INFO,
"Removing USB device[%d]: %s at %s", i,
349 readerTracker[i].fullName, readerTracker[i].devpath);
351 RFRemoveReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i, REMOVE_READER_FLAG_REMOVED);
353 free(readerTracker[i].devpath);
354 readerTracker[i].devpath = NULL;
355 free(readerTracker[i].fullName);
356 readerTracker[i].fullName = NULL;
357 free(readerTracker[i].sysname);
358 readerTracker[i].sysname = NULL;
365static void HPAddDevice(
struct udev_device *dev)
368 char *deviceName = NULL;
369 char *fullname = NULL;
370 struct _driverTracker *driver, *classdriver;
371 const char *sSerialNumber = NULL, *sInterfaceName = NULL;
372 const char *sInterfaceNumber;
374 int bInterfaceNumber;
376 struct udev_device *parent;
378 const char *ignoreprop;
385 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
390 devpath = udev_device_get_devnode(parent);
394 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
398 driver = get_driver(parent, devpath, &classdriver);
403 Log2(PCSC_LOG_DEBUG,
"%s is not a supported smart card reader",
409 sysname = udev_device_get_sysname(dev);
412 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysname() failed");
416 ignoreprop = udev_device_get_property_value(parent,
"PCSCLITE_IGNORE");
417 if (ignoreprop && !strcmp(ignoreprop,
"1"))
420 "Device %s at %s (%s) has PCSCLITE_IGNORE set: ignored",
421 driver->readerName, devpath, sysname);
426 for (index=0; index<readerTrackerNbEntries; index++)
428 if (readerTracker[index].fullName && !strcmp(sysname, readerTracker[index].sysname))
432 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", driver->readerName);
434 sInterfaceNumber = udev_device_get_sysattr_value(dev,
"bInterfaceNumber");
435 if (sInterfaceNumber)
436 bInterfaceNumber = atoi(sInterfaceNumber);
438 bInterfaceNumber = 0;
440 a = asprintf(&deviceName,
"usb:%04x/%04x:libudev:%d:%s",
441 driver->manuID, driver->productID, bInterfaceNumber, devpath);
444 Log1(PCSC_LOG_ERROR,
"asprintf() failed");
449 for (index=0; index<readerTrackerNbEntries; index++)
451 if (NULL == readerTracker[index].fullName)
456 if (readerTrackerNbEntries == index)
458 int new_size = readerTrackerNbEntries + 2;
459 Log3(PCSC_LOG_DEBUG,
"increase from %d to %d readers", readerTrackerNbEntries, new_size);
460 readerTracker = realloc(readerTracker, new_size *
sizeof(*readerTracker));
461 for (
int i=readerTrackerNbEntries; i<new_size; i++)
463 readerTracker[i].devpath = NULL;
464 readerTracker[i].fullName = NULL;
465 readerTracker[i].sysname = NULL;
468 index = readerTrackerNbEntries;
469 readerTrackerNbEntries = new_size;
472 if (Add_Interface_In_Name)
473 sInterfaceName = udev_device_get_sysattr_value(dev,
"interface");
475 if (Add_Serial_In_Name)
476 sSerialNumber = udev_device_get_sysattr_value(parent,
"serial");
479 fullname = strdup(driver->readerName);
486 char *tmpInterfaceName = strdup(sInterfaceName);
489 for (
size_t i=0; i<strlen(tmpInterfaceName); i++)
491 if (! isascii(tmpInterfaceName[i]))
492 tmpInterfaceName[i] =
'.';
496 a = asprintf(&result,
"%s [%s]", fullname, tmpInterfaceName);
499 Log1(PCSC_LOG_ERROR,
"asprintf() failed");
500 free(tmpInterfaceName);
505 free(tmpInterfaceName);
514 if (!sInterfaceName || NULL == strstr(sInterfaceName, sSerialNumber))
519 a = asprintf(&result,
"%s (%s)", fullname, sSerialNumber);
522 Log1(PCSC_LOG_ERROR,
"asprintf() failed");
531 readerTracker[index].fullName = strdup(fullname);
532 readerTracker[index].devpath = strdup(devpath);
533 readerTracker[index].sysname = strdup(sysname);
535 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + index,
536 driver->libraryPath, deviceName);
539 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
542 if (classdriver && driver != classdriver)
545 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + index,
546 classdriver->libraryPath, deviceName);
549 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
551 (void)CheckForOpenCT();
556 (void)CheckForOpenCT();
563 free(readerTracker[index].devpath);
564 readerTracker[index].devpath = NULL;
565 free(readerTracker[index].fullName);
566 readerTracker[index].fullName = NULL;
567 free(readerTracker[index].sysname);
568 readerTracker[index].sysname = NULL;
577static void HPScanUSB(
struct udev *udev)
579 struct udev_enumerate *enumerate;
580 struct udev_list_entry *devices, *dev_list_entry;
583 enumerate = udev_enumerate_new(udev);
584 udev_enumerate_add_match_subsystem(enumerate,
"usb");
585 udev_enumerate_scan_devices(enumerate);
586 devices = udev_enumerate_get_list_entry(enumerate);
589 udev_list_entry_foreach(dev_list_entry, devices)
591 struct udev_device *dev;
596 devpath = udev_list_entry_get_name(dev_list_entry);
597 dev = udev_device_new_from_syspath(udev, devpath);
600 Log2(PCSC_LOG_DEBUG,
"Found matching USB device: %s", devpath);
605 udev_device_unref(dev);
609 udev_enumerate_unref(enumerate);
613static void * HPEstablishUSBNotifications(
void *arg)
615 struct udev_monitor *udev_monitor = arg;
620 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
621 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
624 fd = udev_monitor_get_fd(udev_monitor);
627 Log2(PCSC_LOG_ERROR,
"udev_monitor_get_fd() error: %d", fd);
636 struct udev_device *dev;
641 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
644 r = TEMP_FAILURE_RETRY(poll(&pfd, 1, -1));
647 Log2(PCSC_LOG_ERROR,
"select(): %s", strerror(errno));
651 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
653 dev = udev_monitor_receive_device(udev_monitor);
656 const char *action = udev_device_get_action(dev);
660 if (!strcmp(
"remove", action))
662 Log1(PCSC_LOG_INFO,
"USB Device removed");
666 if (!strcmp(
"add", action))
668 Log1(PCSC_LOG_INFO,
"USB Device add");
674 udev_device_unref(dev);
685LONG HPSearchHotPluggables(
const char * hpDirPath)
687 readerTrackerNbEntries = 2;
688 readerTracker = calloc(readerTrackerNbEntries,
sizeof(*readerTracker));
690 return HPReadBundleValues(hpDirPath);
697LONG HPStopHotPluggables(
void)
707 pthread_cancel(usbNotifyThread);
708 pthread_join(usbNotifyThread, NULL);
710 for (i=0; i<driverSize; i++)
713 free(driverTracker[i].bundleName);
714 free(driverTracker[i].libraryPath);
715 free(driverTracker[i].readerName);
716 free(driverTracker[i].CFBundleName);
721 udev_monitor_unref(Udev_monitor);
726 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
734ULONG HPRegisterForHotplugEvents(
const char * hpDirPath)
741 Log2(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: %s",
743 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
751 Log1(PCSC_LOG_ERROR,
"udev_new() failed");
755 Udev_monitor = udev_monitor_new_from_netlink(Udev,
"udev");
756 if (NULL == Udev_monitor)
758 Log1(PCSC_LOG_ERROR,
"udev_monitor_new_from_netlink() error");
763 r = udev_monitor_filter_add_match_subsystem_devtype(Udev_monitor,
"usb",
767 Log2(PCSC_LOG_ERROR,
"udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r);
771 r = udev_monitor_enable_receiving(Udev_monitor);
774 Log2(PCSC_LOG_ERROR,
"udev_monitor_enable_receiving() error: %d\n", r);
781 if (ThreadCreate(&usbNotifyThread, 0,
782 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, Udev_monitor))
784 Log1(PCSC_LOG_ERROR,
"ThreadCreate() failed");
792void HPReCheckSerialReaders(
void)
796 Log0(PCSC_LOG_ERROR);
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
#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.
This keeps track of a list of currently available reader structures.
This handles abstract system level calls.