16 #if defined(HAVE_LIBUDEV) && defined(USE_USB)
34 #define ADD_SERIAL_NUMBER
35 #define ADD_INTERFACE_NAME
40 pthread_mutex_t usbNotifierMutex;
42 static pthread_t usbNotifyThread;
43 static int driverSize = -1;
44 static char AraKiriHotPlug = FALSE;
49 static struct _driverTracker
52 unsigned int productID;
58 } *driverTracker = NULL;
59 #define DRIVER_TRACKER_SIZE_STEP 10
63 #define DRIVER_TRACKER_INITIAL_SIZE 200
74 static struct _readerTracker
77 char bInterfaceNumber;
83 static LONG HPReadBundleValues(
void)
87 struct dirent *currFP = NULL;
88 char fullPath[FILENAME_MAX];
89 char fullLibPath[FILENAME_MAX];
92 hpDir = opendir(PCSCLITE_HP_DROPDIR);
96 Log1(PCSC_LOG_ERROR,
"Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
97 Log1(PCSC_LOG_ERROR,
"Disabling USB support for pcscd.");
102 driverSize = DRIVER_TRACKER_INITIAL_SIZE;
103 driverTracker = calloc(driverSize,
sizeof(*driverTracker));
104 if (NULL == driverTracker)
106 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
107 (void)closedir(hpDir);
111 #define GET_KEY(key, values) \
112 rv = LTPBundleFindValueWithKey(&plist, key, values); \
115 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
120 while ((currFP = readdir(hpDir)) != 0)
122 if (strstr(currFP->d_name,
".bundle") != 0)
126 list_t *manuIDs, *productIDs, *readerNames;
134 (void)snprintf(fullPath,
sizeof(fullPath),
"%s/%s/Contents/Info.plist",
135 PCSCLITE_HP_DROPDIR, currFP->d_name);
136 fullPath[
sizeof(fullPath) - 1] =
'\0';
143 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
144 libraryPath = list_get_at(values, 0);
145 (
void)snprintf(fullLibPath, sizeof(fullLibPath),
146 "%s/%s/Contents/%s/%s",
147 PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
149 fullLibPath[sizeof(fullLibPath) - 1] = '\0';
151 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
152 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
153 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
161 CFBundleName = strdup(list_get_at(values, 0));
164 for (alias=0; alias<list_size(manuIDs); alias++)
169 value = list_get_at(manuIDs, alias);
170 driverTracker[listCount].manuID = strtol(value, NULL, 16);
172 value = list_get_at(productIDs, alias);
173 driverTracker[listCount].productID = strtol(value, NULL, 16);
175 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
178 driverTracker[listCount].bundleName = strdup(currFP->d_name);
179 driverTracker[listCount].libraryPath = strdup(fullLibPath);
180 driverTracker[listCount].CFBundleName = CFBundleName;
183 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
184 driverTracker[listCount].readerName);
187 if (listCount >= driverSize)
192 driverSize += DRIVER_TRACKER_SIZE_STEP;
195 "Increase driverTracker to %d entries", driverSize);
197 driverTracker = realloc(driverTracker,
198 driverSize *
sizeof(*driverTracker));
199 if (NULL == driverTracker)
201 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
203 (void)closedir(hpDir);
208 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
210 driverTracker[i].manuID = 0;
211 driverTracker[i].productID = 0;
212 driverTracker[i].bundleName = NULL;
213 driverTracker[i].libraryPath = NULL;
214 driverTracker[i].readerName = NULL;
215 driverTracker[i].CFBundleName = NULL;
223 driverSize = listCount;
224 (void)closedir(hpDir);
227 Log2(PCSC_LOG_INFO,
"Found drivers for %d readers", listCount);
234 static struct _driverTracker *get_driver(
struct udev_device *dev,
235 const char *devpath,
struct _driverTracker **classdriver)
238 unsigned int idVendor, idProduct;
239 static struct _driverTracker *driver;
242 str = udev_device_get_sysattr_value(dev,
"idVendor");
245 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
248 idVendor = strtol(str, NULL, 16);
250 str = udev_device_get_sysattr_value(dev,
"idProduct");
253 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
256 idProduct = strtol(str, NULL, 16);
259 "Looking for a driver for VID: 0x%04X, PID: 0x%04X, path: %s",
260 idVendor, idProduct, devpath);
265 for (i=0; i<driverSize; i++)
267 if (driverTracker[i].libraryPath != NULL &&
268 idVendor == driverTracker[i].manuID &&
269 idProduct == driverTracker[i].productID)
271 if ((driverTracker[i].CFBundleName != NULL)
272 && (0 == strcmp(driverTracker[i].CFBundleName,
"CCIDCLASSDRIVER")))
273 *classdriver = &driverTracker[i];
276 driver = &driverTracker[i];
289 static void HPAddDevice(
struct udev_device *dev,
struct udev_device *parent,
293 char deviceName[MAX_DEVICENAME];
294 char fullname[MAX_READERNAME];
295 struct _driverTracker *driver, *classdriver;
296 const char *sSerialNumber = NULL, *sInterfaceName = NULL;
297 const char *sInterfaceNumber;
299 int bInterfaceNumber;
301 driver = get_driver(parent, devpath, &classdriver);
306 Log2(PCSC_LOG_DEBUG,
"%s is not a supported smart card reader",
312 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", driver->readerName);
314 sInterfaceNumber = udev_device_get_sysattr_value(dev,
"bInterfaceNumber");
315 if (sInterfaceNumber)
316 bInterfaceNumber = atoi(sInterfaceNumber);
318 bInterfaceNumber = 0;
320 (void)snprintf(deviceName,
sizeof(deviceName),
321 "usb:%04x/%04x:libudev:%d:%s", driver->manuID, driver->productID,
322 bInterfaceNumber, devpath);
323 deviceName[
sizeof(deviceName) -1] =
'\0';
325 (void)pthread_mutex_lock(&usbNotifierMutex);
330 if (NULL == readerTracker[i].fullName)
334 if (PCSCLITE_MAX_READERS_CONTEXTS == i)
337 "Not enough reader entries. Already found %d readers", i);
338 (void)pthread_mutex_unlock(&usbNotifierMutex);
342 #ifdef ADD_INTERFACE_NAME
343 sInterfaceName = udev_device_get_sysattr_value(dev,
"interface");
346 #ifdef ADD_SERIAL_NUMBER
347 sSerialNumber = udev_device_get_sysattr_value(parent,
"serial");
351 strlcpy(fullname, driver->readerName,
sizeof(fullname));
356 strlcat(fullname,
" [",
sizeof(fullname));
357 strlcat(fullname, sInterfaceName,
sizeof(fullname));
358 strlcat(fullname,
"]",
sizeof(fullname));
366 if (!sInterfaceName || NULL == strstr(sInterfaceName, sSerialNumber))
368 strlcat(fullname,
" (",
sizeof(fullname));
369 strlcat(fullname, sSerialNumber,
sizeof(fullname));
370 strlcat(fullname,
")",
sizeof(fullname));
374 readerTracker[i].fullName = strdup(fullname);
375 readerTracker[i].devpath = strdup(devpath);
376 readerTracker[i].status = READER_PRESENT;
377 readerTracker[i].bInterfaceNumber = bInterfaceNumber;
379 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + i,
380 driver->libraryPath, deviceName);
383 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
386 if (classdriver && driver != classdriver)
389 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + i,
390 classdriver->libraryPath, deviceName);
393 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
396 readerTracker[i].status = READER_FAILED;
398 (void)CheckForOpenCT();
403 readerTracker[i].status = READER_FAILED;
405 (void)CheckForOpenCT();
409 (void)pthread_mutex_unlock(&usbNotifierMutex);
413 static void HPRescanUsbBus(
struct udev *udev)
416 struct udev_enumerate *enumerate;
417 struct udev_list_entry *devices, *dev_list_entry;
421 readerTracker[i].status = READER_ABSENT;
424 enumerate = udev_enumerate_new(udev);
425 udev_enumerate_add_match_subsystem(enumerate,
"usb");
426 udev_enumerate_scan_devices(enumerate);
427 devices = udev_enumerate_get_list_entry(enumerate);
430 udev_list_entry_foreach(dev_list_entry, devices)
433 struct udev_device *dev, *parent;
434 struct _driverTracker *driver, *classdriver;
436 int bInterfaceNumber;
437 const char *interface;
441 devpath = udev_list_entry_get_name(dev_list_entry);
442 dev = udev_device_new_from_syspath(udev, devpath);
449 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
454 devpath = udev_device_get_devnode(parent);
458 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
462 driver = get_driver(parent, devpath, &classdriver);
468 Log2(PCSC_LOG_DEBUG,
"Found matching USB device: %s", devpath);
472 bInterfaceNumber = 0;
473 interface = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
475 bInterfaceNumber = atoi(interface);
480 if (readerTracker[j].devpath
481 && (strcmp(readerTracker[j].devpath, devpath) == 0)
482 && (bInterfaceNumber == readerTracker[j].bInterfaceNumber))
485 readerTracker[j].status = READER_PRESENT;
488 Log2(PCSC_LOG_DEBUG,
"Refresh USB device: %s", devpath);
496 HPAddDevice(dev, parent, devpath);
499 udev_device_unref(dev);
503 udev_enumerate_unref(enumerate);
505 pthread_mutex_lock(&usbNotifierMutex);
509 if ((READER_ABSENT == readerTracker[i].status)
510 && (readerTracker[i].fullName != NULL))
512 Log4(PCSC_LOG_INFO,
"Removing USB device[%d]: %s at %s", i,
513 readerTracker[i].fullName, readerTracker[i].devpath);
515 RFRemoveReader(readerTracker[i].fullName,
516 PCSCLITE_HP_BASE_PORT + i);
518 readerTracker[i].status = READER_ABSENT;
519 free(readerTracker[i].devpath);
520 readerTracker[i].devpath = NULL;
521 free(readerTracker[i].fullName);
522 readerTracker[i].fullName = NULL;
526 pthread_mutex_unlock(&usbNotifierMutex);
529 static void HPEstablishUSBNotifications(
struct udev *udev)
531 struct udev_monitor *udev_monitor;
536 udev_monitor = udev_monitor_new_from_netlink(udev,
"udev");
539 r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor,
"usb",
543 Log2(PCSC_LOG_ERROR,
"udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r);
547 r = udev_monitor_enable_receiving(udev_monitor);
550 Log2(PCSC_LOG_ERROR,
"udev_monitor_enable_receiving() error: %d\n", r);
555 fd = udev_monitor_get_fd(udev_monitor);
557 while (!AraKiriHotPlug)
559 struct udev_device *dev, *parent;
560 const char *action, *devpath;
570 r = select(fd+1, &fds, NULL, NULL, NULL);
573 Log2(PCSC_LOG_ERROR,
"select(): %s", strerror(errno));
577 dev = udev_monitor_receive_device(udev_monitor);
580 Log1(PCSC_LOG_ERROR,
"udev_monitor_receive_device() error\n");
584 action = udev_device_get_action(dev);
585 if (0 == strcmp(
"remove", action))
587 Log1(PCSC_LOG_INFO,
"Device removed");
588 HPRescanUsbBus(udev);
592 if (strcmp(
"add", action))
595 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
597 devpath = udev_device_get_devnode(parent);
601 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
605 HPAddDevice(dev, parent, devpath);
608 udev_device_unref(dev);
612 for (i=0; i<driverSize; i++)
615 free(driverTracker[i].bundleName);
616 free(driverTracker[i].libraryPath);
617 free(driverTracker[i].readerName);
621 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
628 LONG HPSearchHotPluggables(
void)
634 readerTracker[i].status = READER_ABSENT;
635 readerTracker[i].bInterfaceNumber = 0;
636 readerTracker[i].devpath = NULL;
637 readerTracker[i].fullName = NULL;
640 return HPReadBundleValues();
647 LONG HPStopHotPluggables(
void)
649 AraKiriHotPlug = TRUE;
658 ULONG HPRegisterForHotplugEvents(
void)
662 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
666 Log1(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: "
667 PCSCLITE_HP_DROPDIR);
668 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
676 Log1(PCSC_LOG_ERROR,
"udev_new() failed");
680 HPRescanUsbBus(udev);
682 (void)ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
683 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, udev);
689 void HPReCheckSerialReaders(
void)
693 Log0(PCSC_LOG_ERROR);
This handles abstract system level calls.
Reads lexical config files and updates database.
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
prototypes of strlcpy()/strlcat() imported from OpenBSD
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...
This keeps track of a list of currently available reader structures.
This provides a search API for hot pluggble devices.
int bundleParse(const char *fileName, list_t *l)
Parse a Info.plist file and file a list.
void bundleRelease(list_t *l)
Free the list created by bundleParse()
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
#define SCARD_S_SUCCESS
error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx