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;
298 int bInterfaceNumber;
300 driver = get_driver(parent, devpath, &classdriver);
305 Log2(PCSC_LOG_DEBUG,
"%s is not a supported smart card reader",
311 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", driver->readerName);
313 bInterfaceNumber = atoi(udev_device_get_sysattr_value(dev,
314 "bInterfaceNumber"));
315 (void)snprintf(deviceName,
sizeof(deviceName),
316 "usb:%04x/%04x:libudev:%d:%s", driver->manuID, driver->productID,
317 bInterfaceNumber, devpath);
318 deviceName[
sizeof(deviceName) -1] =
'\0';
320 (void)pthread_mutex_lock(&usbNotifierMutex);
325 if (NULL == readerTracker[i].fullName)
329 if (PCSCLITE_MAX_READERS_CONTEXTS == i)
332 "Not enough reader entries. Already found %d readers", i);
333 (void)pthread_mutex_unlock(&usbNotifierMutex);
337 #ifdef ADD_INTERFACE_NAME
338 sInterfaceName = udev_device_get_sysattr_value(dev,
"interface");
341 #ifdef ADD_SERIAL_NUMBER
342 sSerialNumber = udev_device_get_sysattr_value(parent,
"serial");
346 strlcpy(fullname, driver->readerName,
sizeof(fullname));
351 strlcat(fullname,
" [",
sizeof(fullname));
352 strlcat(fullname, sInterfaceName,
sizeof(fullname));
353 strlcat(fullname,
"]",
sizeof(fullname));
361 if (!sInterfaceName || NULL == strstr(sInterfaceName, sSerialNumber))
363 strlcat(fullname,
" (",
sizeof(fullname));
364 strlcat(fullname, sSerialNumber,
sizeof(fullname));
365 strlcat(fullname,
")",
sizeof(fullname));
369 readerTracker[i].fullName = strdup(fullname);
370 readerTracker[i].devpath = strdup(devpath);
371 readerTracker[i].status = READER_PRESENT;
372 readerTracker[i].bInterfaceNumber = bInterfaceNumber;
374 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + i,
375 driver->libraryPath, deviceName);
378 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
381 if (classdriver && driver != classdriver)
384 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + i,
385 classdriver->libraryPath, deviceName);
388 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
391 readerTracker[i].status = READER_FAILED;
393 (void)CheckForOpenCT();
398 readerTracker[i].status = READER_FAILED;
400 (void)CheckForOpenCT();
404 (void)pthread_mutex_unlock(&usbNotifierMutex);
408 static void HPRescanUsbBus(
struct udev *udev)
411 struct udev_enumerate *enumerate;
412 struct udev_list_entry *devices, *dev_list_entry;
416 readerTracker[i].status = READER_ABSENT;
419 enumerate = udev_enumerate_new(udev);
420 udev_enumerate_add_match_subsystem(enumerate,
"usb");
421 udev_enumerate_scan_devices(enumerate);
422 devices = udev_enumerate_get_list_entry(enumerate);
425 udev_list_entry_foreach(dev_list_entry, devices)
428 struct udev_device *dev, *parent;
429 struct _driverTracker *driver, *classdriver;
431 int bInterfaceNumber;
432 const char *interface;
436 devpath = udev_list_entry_get_name(dev_list_entry);
437 dev = udev_device_new_from_syspath(udev, devpath);
444 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
449 devpath = udev_device_get_devnode(parent);
453 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
457 driver = get_driver(parent, devpath, &classdriver);
463 Log2(PCSC_LOG_DEBUG,
"Found matching USB device: %s", devpath);
467 bInterfaceNumber = 0;
468 interface = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
470 bInterfaceNumber = atoi(interface);
475 if (readerTracker[j].devpath
476 && (strcmp(readerTracker[j].devpath, devpath) == 0)
477 && (bInterfaceNumber == readerTracker[j].bInterfaceNumber))
480 readerTracker[j].status = READER_PRESENT;
483 Log2(PCSC_LOG_DEBUG,
"Refresh USB device: %s", devpath);
491 HPAddDevice(dev, parent, devpath);
494 udev_device_unref(dev);
498 udev_enumerate_unref(enumerate);
500 pthread_mutex_lock(&usbNotifierMutex);
504 if ((READER_ABSENT == readerTracker[i].status)
505 && (readerTracker[i].fullName != NULL))
508 Log3(PCSC_LOG_INFO,
"Removing USB device[%d]: %s", i,
509 readerTracker[i].devpath);
511 RFRemoveReader(readerTracker[i].fullName,
512 PCSCLITE_HP_BASE_PORT + i);
514 readerTracker[i].status = READER_ABSENT;
515 free(readerTracker[i].devpath);
516 readerTracker[i].devpath = NULL;
517 free(readerTracker[i].fullName);
518 readerTracker[i].fullName = NULL;
522 pthread_mutex_unlock(&usbNotifierMutex);
525 static void HPEstablishUSBNotifications(
struct udev *udev)
527 struct udev_monitor *udev_monitor;
532 udev_monitor = udev_monitor_new_from_netlink(udev,
"udev");
535 r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor,
"usb",
539 Log2(PCSC_LOG_ERROR,
"udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r);
543 r = udev_monitor_enable_receiving(udev_monitor);
546 Log2(PCSC_LOG_ERROR,
"udev_monitor_enable_receiving() error: %d\n", r);
551 fd = udev_monitor_get_fd(udev_monitor);
553 while (!AraKiriHotPlug)
555 struct udev_device *dev, *parent;
556 const char *action, *devpath;
566 r = select(fd+1, &fds, NULL, NULL, NULL);
569 Log2(PCSC_LOG_ERROR,
"select(): %s", strerror(errno));
573 dev = udev_monitor_receive_device(udev_monitor);
576 Log1(PCSC_LOG_ERROR,
"udev_monitor_receive_device() error\n");
580 action = udev_device_get_action(dev);
581 if (0 == strcmp(
"remove", action))
583 Log1(PCSC_LOG_INFO,
"Device removed");
584 HPRescanUsbBus(udev);
588 if (strcmp(
"add", action))
591 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
593 devpath = udev_device_get_devnode(parent);
597 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
601 HPAddDevice(dev, parent, devpath);
604 udev_device_unref(dev);
608 for (i=0; i<driverSize; i++)
611 free(driverTracker[i].bundleName);
612 free(driverTracker[i].libraryPath);
613 free(driverTracker[i].readerName);
617 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
624 LONG HPSearchHotPluggables(
void)
630 readerTracker[i].status = READER_ABSENT;
631 readerTracker[i].bInterfaceNumber = 0;
632 readerTracker[i].devpath = NULL;
633 readerTracker[i].fullName = NULL;
636 return HPReadBundleValues();
643 LONG HPStopHotPluggables(
void)
645 AraKiriHotPlug = TRUE;
654 ULONG HPRegisterForHotplugEvents(
void)
658 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
662 Log1(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: "
663 PCSCLITE_HP_DROPDIR);
664 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
672 Log1(PCSC_LOG_ERROR,
"udev_new() failed");
676 HPRescanUsbBus(udev);
678 (void)ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
679 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, udev);
685 void HPReCheckSerialReaders(
void)
689 Log0(PCSC_LOG_ERROR);