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;
81static struct _driverTracker
84 unsigned int productID;
90} *driverTracker = NULL;
91#define DRIVER_TRACKER_SIZE_STEP 10
95#define DRIVER_TRACKER_INITIAL_SIZE 200
100static struct _readerTracker
108static LONG HPReadBundleValues(
const char * hpDirPath)
112 struct dirent *currFP = NULL;
113 char fullPath[FILENAME_MAX];
114 char fullLibPath[FILENAME_MAX];
117 hpDir = opendir(hpDirPath);
121 Log2(PCSC_LOG_ERROR,
"Cannot open PC/SC drivers directory: %s", hpDirPath);
122 Log1(PCSC_LOG_ERROR,
"Disabling USB support for pcscd.");
127 driverSize = DRIVER_TRACKER_INITIAL_SIZE;
128 driverTracker = calloc(driverSize,
sizeof(*driverTracker));
129 if (NULL == driverTracker)
131 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
132 (void)closedir(hpDir);
136#define GET_KEY(key, values) \
137 rv = LTPBundleFindValueWithKey(&plist, key, values); \
140 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
145 while ((currFP = readdir(hpDir)) != 0)
147 if (strstr(currFP->d_name,
".bundle") != 0)
151 list_t *manuIDs, *productIDs, *readerNames;
159 (void)snprintf(fullPath,
sizeof(fullPath),
"%s/%s/Contents/Info.plist",
160 hpDirPath, currFP->d_name);
161 fullPath[
sizeof(fullPath) - 1] =
'\0';
168 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
169 libraryPath = list_get_at(values, 0);
170 (void)snprintf(fullLibPath,
sizeof(fullLibPath),
171 "%s/%s/Contents/%s/%s",
172 hpDirPath, currFP->d_name, PCSC_ARCH,
174 fullLibPath[
sizeof(fullLibPath) - 1] =
'\0';
176 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
177 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
178 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
180 if ((list_size(manuIDs) != list_size(productIDs))
181 || (list_size(manuIDs) != list_size(readerNames)))
183 Log2(PCSC_LOG_CRITICAL,
"Error parsing %s", fullPath);
184 (void)closedir(hpDir);
194 CFBundleName = strdup(list_get_at(values, 0));
197 for (alias=0; alias<list_size(manuIDs); alias++)
202 value = list_get_at(manuIDs, alias);
203 driverTracker[listCount].manuID = strtol(value, NULL, 16);
205 value = list_get_at(productIDs, alias);
206 driverTracker[listCount].productID = strtol(value, NULL, 16);
208 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
211 driverTracker[listCount].bundleName = strdup(currFP->d_name);
212 driverTracker[listCount].libraryPath = strdup(fullLibPath);
213 driverTracker[listCount].CFBundleName = CFBundleName;
216 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
217 driverTracker[listCount].readerName);
220 if (listCount >= driverSize)
225 driverSize += DRIVER_TRACKER_SIZE_STEP;
228 "Increase driverTracker to %d entries", driverSize);
231 void* tmp = realloc(driverTracker,
232 driverSize *
sizeof(*driverTracker));
237 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
239 (void)closedir(hpDir);
245 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
247 driverTracker[i].manuID = 0;
248 driverTracker[i].productID = 0;
249 driverTracker[i].bundleName = NULL;
250 driverTracker[i].libraryPath = NULL;
251 driverTracker[i].readerName = NULL;
252 driverTracker[i].CFBundleName = NULL;
260 driverSize = listCount;
261 (void)closedir(hpDir);
264 Log2(PCSC_LOG_INFO,
"Found drivers for %d readers", listCount);
271 static struct _driverTracker *get_driver(
struct udev_device *dev,
272 const char *devpath,
struct _driverTracker **classdriver)
275 unsigned int idVendor, idProduct;
276 static struct _driverTracker *driver;
279 str = udev_device_get_sysattr_value(dev,
"idVendor");
282 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
285 idVendor = strtol(str, NULL, 16);
287 str = udev_device_get_sysattr_value(dev,
"idProduct");
290 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
293 idProduct = strtol(str, NULL, 16);
299 "Looking for a driver for VID: 0x%04X, PID: 0x%04X, path: %s",
300 idVendor, idProduct, devpath);
305 for (i=0; i<driverSize; i++)
307 if (driverTracker[i].libraryPath != NULL &&
308 idVendor == driverTracker[i].manuID &&
309 idProduct == driverTracker[i].productID)
311 if ((driverTracker[i].CFBundleName != NULL)
312 && (0 == strcmp(driverTracker[i].CFBundleName,
"CCIDCLASSDRIVER")))
313 *classdriver = &driverTracker[i];
316 driver = &driverTracker[i];
329static void HPRemoveDevice(
struct udev_device *dev)
334 sysname = udev_device_get_sysname(dev);
337 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysname() failed");
343 if (readerTracker[i].fullName && !strcmp(sysname, readerTracker[i].sysname))
345 Log4(PCSC_LOG_INFO,
"Removing USB device[%d]: %s at %s", i,
346 readerTracker[i].fullName, readerTracker[i].devpath);
348 RFRemoveReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i, REMOVE_READER_FLAG_REMOVED);
350 free(readerTracker[i].devpath);
351 readerTracker[i].devpath = NULL;
352 free(readerTracker[i].fullName);
353 readerTracker[i].fullName = NULL;
354 free(readerTracker[i].sysname);
355 readerTracker[i].sysname = NULL;
362static void HPAddDevice(
struct udev_device *dev)
365 char *deviceName = NULL;
366 char *fullname = NULL;
367 struct _driverTracker *driver, *classdriver;
368 const char *sSerialNumber = NULL, *sInterfaceName = NULL;
369 const char *sInterfaceNumber;
371 int bInterfaceNumber;
373 struct udev_device *parent;
381 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
386 devpath = udev_device_get_devnode(parent);
390 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
394 driver = get_driver(parent, devpath, &classdriver);
399 Log2(PCSC_LOG_DEBUG,
"%s is not a supported smart card reader",
405 sysname = udev_device_get_sysname(dev);
408 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysname() failed");
415 if (readerTracker[index].fullName && !strcmp(sysname, readerTracker[index].sysname))
419 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", driver->readerName);
421 sInterfaceNumber = udev_device_get_sysattr_value(dev,
"bInterfaceNumber");
422 if (sInterfaceNumber)
423 bInterfaceNumber = atoi(sInterfaceNumber);
425 bInterfaceNumber = 0;
427 a = asprintf(&deviceName,
"usb:%04x/%04x:libudev:%d:%s",
428 driver->manuID, driver->productID, bInterfaceNumber, devpath);
431 Log1(PCSC_LOG_ERROR,
"asprintf() failed");
438 if (NULL == readerTracker[index].fullName)
445 "Not enough reader entries. Already found %d readers", index);
449 if (Add_Interface_In_Name)
450 sInterfaceName = udev_device_get_sysattr_value(dev,
"interface");
452 if (Add_Serial_In_Name)
453 sSerialNumber = udev_device_get_sysattr_value(parent,
"serial");
456 fullname = strdup(driver->readerName);
463 char *tmpInterfaceName = strdup(sInterfaceName);
466 for (
size_t i=0; i<strlen(tmpInterfaceName); i++)
468 if (! isascii(tmpInterfaceName[i]))
469 tmpInterfaceName[i] =
'.';
473 a = asprintf(&result,
"%s [%s]", fullname, tmpInterfaceName);
476 Log1(PCSC_LOG_ERROR,
"asprintf() failed");
477 free(tmpInterfaceName);
482 free(tmpInterfaceName);
491 if (!sInterfaceName || NULL == strstr(sInterfaceName, sSerialNumber))
496 a = asprintf(&result,
"%s (%s)", fullname, sSerialNumber);
499 Log1(PCSC_LOG_ERROR,
"asprintf() failed");
508 readerTracker[index].fullName = strdup(fullname);
509 readerTracker[index].devpath = strdup(devpath);
510 readerTracker[index].sysname = strdup(sysname);
512 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + index,
513 driver->libraryPath, deviceName);
516 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
519 if (classdriver && driver != classdriver)
522 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + index,
523 classdriver->libraryPath, deviceName);
526 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
528 (void)CheckForOpenCT();
533 (void)CheckForOpenCT();
540 free(readerTracker[index].devpath);
541 readerTracker[index].devpath = NULL;
542 free(readerTracker[index].fullName);
543 readerTracker[index].fullName = NULL;
544 free(readerTracker[index].sysname);
545 readerTracker[index].sysname = NULL;
554static void HPScanUSB(
struct udev *udev)
556 struct udev_enumerate *enumerate;
557 struct udev_list_entry *devices, *dev_list_entry;
560 enumerate = udev_enumerate_new(udev);
561 udev_enumerate_add_match_subsystem(enumerate,
"usb");
562 udev_enumerate_scan_devices(enumerate);
563 devices = udev_enumerate_get_list_entry(enumerate);
566 udev_list_entry_foreach(dev_list_entry, devices)
568 struct udev_device *dev;
573 devpath = udev_list_entry_get_name(dev_list_entry);
574 dev = udev_device_new_from_syspath(udev, devpath);
577 Log2(PCSC_LOG_DEBUG,
"Found matching USB device: %s", devpath);
582 udev_device_unref(dev);
586 udev_enumerate_unref(enumerate);
590static void * HPEstablishUSBNotifications(
void *arg)
592 struct udev_monitor *udev_monitor = arg;
597 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
598 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
601 fd = udev_monitor_get_fd(udev_monitor);
604 Log2(PCSC_LOG_ERROR,
"udev_monitor_get_fd() error: %d", fd);
613 struct udev_device *dev;
618 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
621 r = TEMP_FAILURE_RETRY(poll(&pfd, 1, -1));
624 Log2(PCSC_LOG_ERROR,
"select(): %s", strerror(errno));
628 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
630 dev = udev_monitor_receive_device(udev_monitor);
633 const char *action = udev_device_get_action(dev);
637 if (!strcmp(
"remove", action))
639 Log1(PCSC_LOG_INFO,
"USB Device removed");
643 if (!strcmp(
"add", action))
645 Log1(PCSC_LOG_INFO,
"USB Device add");
651 udev_device_unref(dev);
662LONG HPSearchHotPluggables(
const char * hpDirPath)
668 readerTracker[i].devpath = NULL;
669 readerTracker[i].fullName = NULL;
670 readerTracker[i].sysname = NULL;
673 return HPReadBundleValues(hpDirPath);
680LONG HPStopHotPluggables(
void)
690 pthread_cancel(usbNotifyThread);
691 pthread_join(usbNotifyThread, NULL);
693 for (i=0; i<driverSize; i++)
696 free(driverTracker[i].bundleName);
697 free(driverTracker[i].libraryPath);
698 free(driverTracker[i].readerName);
707 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
715ULONG HPRegisterForHotplugEvents(
const char * hpDirPath)
717 struct udev_monitor *udev_monitor;
723 Log2(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: %s",
725 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
733 Log1(PCSC_LOG_ERROR,
"udev_new() failed");
737 udev_monitor = udev_monitor_new_from_netlink(Udev,
"udev");
738 if (NULL == udev_monitor)
740 Log1(PCSC_LOG_ERROR,
"udev_monitor_new_from_netlink() error");
745 r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor,
"usb",
749 Log2(PCSC_LOG_ERROR,
"udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r);
753 r = udev_monitor_enable_receiving(udev_monitor);
756 Log2(PCSC_LOG_ERROR,
"udev_monitor_enable_receiving() error: %d\n", r);
763 if (ThreadCreate(&usbNotifyThread, 0,
764 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, udev_monitor))
766 Log1(PCSC_LOG_ERROR,
"ThreadCreate() failed");
774void HPReCheckSerialReaders(
void)
778 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.
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.
#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.