42 #if defined(HAVE_LIBUDEV) && defined(USE_USB) 64 extern char Add_Interface_In_Name;
65 extern char Add_Serial_In_Name;
67 pthread_mutex_t usbNotifierMutex;
69 static pthread_t usbNotifyThread;
70 static int driverSize = -1;
71 static char AraKiriHotPlug = FALSE;
76 static struct _driverTracker
79 unsigned int productID;
85 } *driverTracker = NULL;
86 #define DRIVER_TRACKER_SIZE_STEP 10 90 #define DRIVER_TRACKER_INITIAL_SIZE 200 101 static struct _readerTracker
103 readerState_t status;
104 char bInterfaceNumber;
110 static LONG HPReadBundleValues(
void)
114 struct dirent *currFP = NULL;
115 char fullPath[FILENAME_MAX];
116 char fullLibPath[FILENAME_MAX];
119 hpDir = opendir(PCSCLITE_HP_DROPDIR);
123 Log1(PCSC_LOG_ERROR,
"Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
124 Log1(PCSC_LOG_ERROR,
"Disabling USB support for pcscd.");
129 driverSize = DRIVER_TRACKER_INITIAL_SIZE;
130 driverTracker = calloc(driverSize,
sizeof(*driverTracker));
131 if (NULL == driverTracker)
133 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
134 (void)closedir(hpDir);
138 #define GET_KEY(key, values) \ 139 rv = LTPBundleFindValueWithKey(&plist, key, values); \ 142 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \ 147 while ((currFP = readdir(hpDir)) != 0)
149 if (strstr(currFP->d_name,
".bundle") != 0)
153 list_t *manuIDs, *productIDs, *readerNames;
161 (void)snprintf(fullPath,
sizeof(fullPath),
"%s/%s/Contents/Info.plist",
162 PCSCLITE_HP_DROPDIR, currFP->d_name);
163 fullPath[
sizeof(fullPath) - 1] =
'\0';
170 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
171 libraryPath = list_get_at(values, 0);
172 (void)snprintf(fullLibPath,
sizeof(fullLibPath),
173 "%s/%s/Contents/%s/%s",
174 PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
176 fullLibPath[
sizeof(fullLibPath) - 1] =
'\0';
178 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
179 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
180 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
182 if ((list_size(manuIDs) != list_size(productIDs))
183 || (list_size(manuIDs) != list_size(readerNames)))
185 Log2(PCSC_LOG_CRITICAL,
"Error parsing %s", fullPath);
186 (void)closedir(hpDir);
196 CFBundleName = strdup(list_get_at(values, 0));
199 for (alias=0; alias<list_size(manuIDs); alias++)
204 value = list_get_at(manuIDs, alias);
205 driverTracker[listCount].manuID = strtol(value, NULL, 16);
207 value = list_get_at(productIDs, alias);
208 driverTracker[listCount].productID = strtol(value, NULL, 16);
210 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
213 driverTracker[listCount].bundleName = strdup(currFP->d_name);
214 driverTracker[listCount].libraryPath = strdup(fullLibPath);
215 driverTracker[listCount].CFBundleName = CFBundleName;
218 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
219 driverTracker[listCount].readerName);
222 if (listCount >= driverSize)
227 driverSize += DRIVER_TRACKER_SIZE_STEP;
230 "Increase driverTracker to %d entries", driverSize);
232 driverTracker = realloc(driverTracker,
233 driverSize *
sizeof(*driverTracker));
234 if (NULL == driverTracker)
236 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
238 (void)closedir(hpDir);
243 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
245 driverTracker[i].manuID = 0;
246 driverTracker[i].productID = 0;
247 driverTracker[i].bundleName = NULL;
248 driverTracker[i].libraryPath = NULL;
249 driverTracker[i].readerName = NULL;
250 driverTracker[i].CFBundleName = NULL;
258 driverSize = listCount;
259 (void)closedir(hpDir);
262 Log2(PCSC_LOG_INFO,
"Found drivers for %d readers", listCount);
269 static struct _driverTracker *get_driver(
struct udev_device *dev,
270 const char *devpath,
struct _driverTracker **classdriver)
273 unsigned int idVendor, idProduct;
274 static struct _driverTracker *driver;
277 str = udev_device_get_sysattr_value(dev,
"idVendor");
280 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
283 idVendor = strtol(str, NULL, 16);
285 str = udev_device_get_sysattr_value(dev,
"idProduct");
288 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
291 idProduct = strtol(str, NULL, 16);
294 "Looking for a driver for VID: 0x%04X, PID: 0x%04X, path: %s",
295 idVendor, idProduct, devpath);
300 for (i=0; i<driverSize; i++)
302 if (driverTracker[i].libraryPath != NULL &&
303 idVendor == driverTracker[i].manuID &&
304 idProduct == driverTracker[i].productID)
306 if ((driverTracker[i].CFBundleName != NULL)
307 && (0 == strcmp(driverTracker[i].CFBundleName,
"CCIDCLASSDRIVER")))
308 *classdriver = &driverTracker[i];
311 driver = &driverTracker[i];
324 static void HPAddDevice(
struct udev_device *dev,
struct udev_device *parent,
328 char deviceName[MAX_DEVICENAME];
329 char fullname[MAX_READERNAME];
330 struct _driverTracker *driver, *classdriver;
331 const char *sSerialNumber = NULL, *sInterfaceName = NULL;
332 const char *sInterfaceNumber;
334 int bInterfaceNumber;
336 driver = get_driver(parent, devpath, &classdriver);
341 Log2(PCSC_LOG_DEBUG,
"%s is not a supported smart card reader",
347 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", driver->readerName);
349 sInterfaceNumber = udev_device_get_sysattr_value(dev,
"bInterfaceNumber");
350 if (sInterfaceNumber)
351 bInterfaceNumber = atoi(sInterfaceNumber);
353 bInterfaceNumber = 0;
355 (void)snprintf(deviceName,
sizeof(deviceName),
356 "usb:%04x/%04x:libudev:%d:%s", driver->manuID, driver->productID,
357 bInterfaceNumber, devpath);
358 deviceName[
sizeof(deviceName) -1] =
'\0';
360 (void)pthread_mutex_lock(&usbNotifierMutex);
365 if (NULL == readerTracker[i].fullName)
369 if (PCSCLITE_MAX_READERS_CONTEXTS == i)
372 "Not enough reader entries. Already found %d readers", i);
373 (void)pthread_mutex_unlock(&usbNotifierMutex);
377 if (Add_Interface_In_Name)
378 sInterfaceName = udev_device_get_sysattr_value(dev,
"interface");
380 if (Add_Serial_In_Name)
381 sSerialNumber = udev_device_get_sysattr_value(parent,
"serial");
384 strlcpy(fullname, driver->readerName,
sizeof(fullname));
389 strlcat(fullname,
" [",
sizeof(fullname));
390 strlcat(fullname, sInterfaceName,
sizeof(fullname));
391 strlcat(fullname,
"]",
sizeof(fullname));
399 if (!sInterfaceName || NULL == strstr(sInterfaceName, sSerialNumber))
401 strlcat(fullname,
" (",
sizeof(fullname));
402 strlcat(fullname, sSerialNumber,
sizeof(fullname));
403 strlcat(fullname,
")",
sizeof(fullname));
407 readerTracker[i].fullName = strdup(fullname);
408 readerTracker[i].devpath = strdup(devpath);
409 readerTracker[i].status = READER_PRESENT;
410 readerTracker[i].bInterfaceNumber = bInterfaceNumber;
412 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + i,
413 driver->libraryPath, deviceName);
416 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
419 if (classdriver && driver != classdriver)
422 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + i,
423 classdriver->libraryPath, deviceName);
426 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
429 readerTracker[i].status = READER_FAILED;
431 (void)CheckForOpenCT();
436 readerTracker[i].status = READER_FAILED;
438 (void)CheckForOpenCT();
442 (void)pthread_mutex_unlock(&usbNotifierMutex);
446 static void HPRescanUsbBus(
struct udev *udev)
449 struct udev_enumerate *enumerate;
450 struct udev_list_entry *devices, *dev_list_entry;
454 readerTracker[i].status = READER_ABSENT;
457 enumerate = udev_enumerate_new(udev);
458 udev_enumerate_add_match_subsystem(enumerate,
"usb");
459 udev_enumerate_scan_devices(enumerate);
460 devices = udev_enumerate_get_list_entry(enumerate);
463 udev_list_entry_foreach(dev_list_entry, devices)
466 struct udev_device *dev, *parent;
467 struct _driverTracker *driver, *classdriver;
469 int bInterfaceNumber;
470 const char *interface;
474 devpath = udev_list_entry_get_name(dev_list_entry);
475 dev = udev_device_new_from_syspath(udev, devpath);
482 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
487 devpath = udev_device_get_devnode(parent);
491 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
495 driver = get_driver(parent, devpath, &classdriver);
501 Log2(PCSC_LOG_DEBUG,
"Found matching USB device: %s", devpath);
505 bInterfaceNumber = 0;
506 interface = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
508 bInterfaceNumber = atoi(interface);
513 if (readerTracker[j].devpath
514 && (strcmp(readerTracker[j].devpath, devpath) == 0)
515 && (bInterfaceNumber == readerTracker[j].bInterfaceNumber))
518 readerTracker[j].status = READER_PRESENT;
521 Log2(PCSC_LOG_DEBUG,
"Refresh USB device: %s", devpath);
529 HPAddDevice(dev, parent, devpath);
532 udev_device_unref(dev);
536 udev_enumerate_unref(enumerate);
538 pthread_mutex_lock(&usbNotifierMutex);
542 if ((READER_ABSENT == readerTracker[i].status)
543 && (readerTracker[i].fullName != NULL))
545 Log4(PCSC_LOG_INFO,
"Removing USB device[%d]: %s at %s", i,
546 readerTracker[i].fullName, readerTracker[i].devpath);
548 RFRemoveReader(readerTracker[i].fullName,
549 PCSCLITE_HP_BASE_PORT + i);
551 readerTracker[i].status = READER_ABSENT;
552 free(readerTracker[i].devpath);
553 readerTracker[i].devpath = NULL;
554 free(readerTracker[i].fullName);
555 readerTracker[i].fullName = NULL;
559 pthread_mutex_unlock(&usbNotifierMutex);
562 static void HPEstablishUSBNotifications(
struct udev *udev)
564 struct udev_monitor *udev_monitor;
569 udev_monitor = udev_monitor_new_from_netlink(udev,
"udev");
572 r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor,
"usb",
576 Log2(PCSC_LOG_ERROR,
"udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r);
580 r = udev_monitor_enable_receiving(udev_monitor);
583 Log2(PCSC_LOG_ERROR,
"udev_monitor_enable_receiving() error: %d\n", r);
588 fd = udev_monitor_get_fd(udev_monitor);
590 while (!AraKiriHotPlug)
592 struct udev_device *dev, *parent;
593 const char *action, *devpath;
603 r = select(fd+1, &fds, NULL, NULL, NULL);
606 Log2(PCSC_LOG_ERROR,
"select(): %s", strerror(errno));
610 dev = udev_monitor_receive_device(udev_monitor);
613 Log1(PCSC_LOG_ERROR,
"udev_monitor_receive_device() error\n");
617 action = udev_device_get_action(dev);
618 if (0 == strcmp(
"remove", action))
620 Log1(PCSC_LOG_INFO,
"Device removed");
621 HPRescanUsbBus(udev);
625 if (strcmp(
"add", action))
628 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
630 devpath = udev_device_get_devnode(parent);
634 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
638 HPAddDevice(dev, parent, devpath);
641 udev_device_unref(dev);
645 for (i=0; i<driverSize; i++)
648 free(driverTracker[i].bundleName);
649 free(driverTracker[i].libraryPath);
650 free(driverTracker[i].readerName);
654 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
661 LONG HPSearchHotPluggables(
void)
667 readerTracker[i].status = READER_ABSENT;
668 readerTracker[i].bInterfaceNumber = 0;
669 readerTracker[i].devpath = NULL;
670 readerTracker[i].fullName = NULL;
673 return HPReadBundleValues();
680 LONG HPStopHotPluggables(
void)
682 AraKiriHotPlug = TRUE;
691 ULONG HPRegisterForHotplugEvents(
void)
695 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
699 Log1(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: " 700 PCSCLITE_HP_DROPDIR);
701 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
709 Log1(PCSC_LOG_ERROR,
"udev_new() failed");
713 HPRescanUsbBus(udev);
715 (void)ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
716 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, udev);
722 void HPReCheckSerialReaders(
void)
726 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