16 #if defined(HAVE_LIBUDEV) && defined(USE_USB)
38 extern char Add_Interface_In_Name;
39 extern char Add_Serial_In_Name;
41 pthread_mutex_t usbNotifierMutex;
43 static pthread_t usbNotifyThread;
44 static int driverSize = -1;
45 static char AraKiriHotPlug = FALSE;
50 static struct _driverTracker
53 unsigned int productID;
59 } *driverTracker = NULL;
60 #define DRIVER_TRACKER_SIZE_STEP 10
64 #define DRIVER_TRACKER_INITIAL_SIZE 200
75 static struct _readerTracker
78 char bInterfaceNumber;
84 static LONG HPReadBundleValues(
void)
88 struct dirent *currFP = NULL;
89 char fullPath[FILENAME_MAX];
90 char fullLibPath[FILENAME_MAX];
93 hpDir = opendir(PCSCLITE_HP_DROPDIR);
97 Log1(PCSC_LOG_ERROR,
"Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
98 Log1(PCSC_LOG_ERROR,
"Disabling USB support for pcscd.");
103 driverSize = DRIVER_TRACKER_INITIAL_SIZE;
104 driverTracker = calloc(driverSize,
sizeof(*driverTracker));
105 if (NULL == driverTracker)
107 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
108 (void)closedir(hpDir);
112 #define GET_KEY(key, values) \
113 rv = LTPBundleFindValueWithKey(&plist, key, values); \
116 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
121 while ((currFP = readdir(hpDir)) != 0)
123 if (strstr(currFP->d_name,
".bundle") != 0)
127 list_t *manuIDs, *productIDs, *readerNames;
135 (void)snprintf(fullPath,
sizeof(fullPath),
"%s/%s/Contents/Info.plist",
136 PCSCLITE_HP_DROPDIR, currFP->d_name);
137 fullPath[
sizeof(fullPath) - 1] =
'\0';
144 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
145 libraryPath = list_get_at(values, 0);
146 (
void)snprintf(fullLibPath, sizeof(fullLibPath),
147 "%s/%s/Contents/%s/%s",
148 PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
150 fullLibPath[sizeof(fullLibPath) - 1] = '\0';
152 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
153 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
154 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
156 if ((list_size(manuIDs) != list_size(productIDs))
157 || (list_size(manuIDs) != list_size(readerNames)))
159 Log2(PCSC_LOG_CRITICAL,
"Error parsing %s", fullPath);
160 (void)closedir(hpDir);
170 CFBundleName = strdup(list_get_at(values, 0));
173 for (alias=0; alias<list_size(manuIDs); alias++)
178 value = list_get_at(manuIDs, alias);
179 driverTracker[listCount].manuID = strtol(value, NULL, 16);
181 value = list_get_at(productIDs, alias);
182 driverTracker[listCount].productID = strtol(value, NULL, 16);
184 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
187 driverTracker[listCount].bundleName = strdup(currFP->d_name);
188 driverTracker[listCount].libraryPath = strdup(fullLibPath);
189 driverTracker[listCount].CFBundleName = CFBundleName;
192 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
193 driverTracker[listCount].readerName);
196 if (listCount >= driverSize)
201 driverSize += DRIVER_TRACKER_SIZE_STEP;
204 "Increase driverTracker to %d entries", driverSize);
206 driverTracker = realloc(driverTracker,
207 driverSize *
sizeof(*driverTracker));
208 if (NULL == driverTracker)
210 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
212 (void)closedir(hpDir);
217 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
219 driverTracker[i].manuID = 0;
220 driverTracker[i].productID = 0;
221 driverTracker[i].bundleName = NULL;
222 driverTracker[i].libraryPath = NULL;
223 driverTracker[i].readerName = NULL;
224 driverTracker[i].CFBundleName = NULL;
232 driverSize = listCount;
233 (void)closedir(hpDir);
236 Log2(PCSC_LOG_INFO,
"Found drivers for %d readers", listCount);
243 static struct _driverTracker *get_driver(
struct udev_device *dev,
244 const char *devpath,
struct _driverTracker **classdriver)
247 unsigned int idVendor, idProduct;
248 static struct _driverTracker *driver;
251 str = udev_device_get_sysattr_value(dev,
"idVendor");
254 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
257 idVendor = strtol(str, NULL, 16);
259 str = udev_device_get_sysattr_value(dev,
"idProduct");
262 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
265 idProduct = strtol(str, NULL, 16);
268 "Looking for a driver for VID: 0x%04X, PID: 0x%04X, path: %s",
269 idVendor, idProduct, devpath);
274 for (i=0; i<driverSize; i++)
276 if (driverTracker[i].libraryPath != NULL &&
277 idVendor == driverTracker[i].manuID &&
278 idProduct == driverTracker[i].productID)
280 if ((driverTracker[i].CFBundleName != NULL)
281 && (0 == strcmp(driverTracker[i].CFBundleName,
"CCIDCLASSDRIVER")))
282 *classdriver = &driverTracker[i];
285 driver = &driverTracker[i];
298 static void HPAddDevice(
struct udev_device *dev,
struct udev_device *parent,
302 char deviceName[MAX_DEVICENAME];
303 char fullname[MAX_READERNAME];
304 struct _driverTracker *driver, *classdriver;
305 const char *sSerialNumber = NULL, *sInterfaceName = NULL;
306 const char *sInterfaceNumber;
308 int bInterfaceNumber;
310 driver = get_driver(parent, devpath, &classdriver);
315 Log2(PCSC_LOG_DEBUG,
"%s is not a supported smart card reader",
321 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", driver->readerName);
323 sInterfaceNumber = udev_device_get_sysattr_value(dev,
"bInterfaceNumber");
324 if (sInterfaceNumber)
325 bInterfaceNumber = atoi(sInterfaceNumber);
327 bInterfaceNumber = 0;
329 (void)snprintf(deviceName,
sizeof(deviceName),
330 "usb:%04x/%04x:libudev:%d:%s", driver->manuID, driver->productID,
331 bInterfaceNumber, devpath);
332 deviceName[
sizeof(deviceName) -1] =
'\0';
334 (void)pthread_mutex_lock(&usbNotifierMutex);
339 if (NULL == readerTracker[i].fullName)
343 if (PCSCLITE_MAX_READERS_CONTEXTS == i)
346 "Not enough reader entries. Already found %d readers", i);
347 (void)pthread_mutex_unlock(&usbNotifierMutex);
351 if (Add_Interface_In_Name)
352 sInterfaceName = udev_device_get_sysattr_value(dev,
"interface");
354 if (Add_Serial_In_Name)
355 sSerialNumber = udev_device_get_sysattr_value(parent,
"serial");
358 strlcpy(fullname, driver->readerName,
sizeof(fullname));
363 strlcat(fullname,
" [",
sizeof(fullname));
364 strlcat(fullname, sInterfaceName,
sizeof(fullname));
365 strlcat(fullname,
"]",
sizeof(fullname));
373 if (!sInterfaceName || NULL == strstr(sInterfaceName, sSerialNumber))
375 strlcat(fullname,
" (",
sizeof(fullname));
376 strlcat(fullname, sSerialNumber,
sizeof(fullname));
377 strlcat(fullname,
")",
sizeof(fullname));
381 readerTracker[i].fullName = strdup(fullname);
382 readerTracker[i].devpath = strdup(devpath);
383 readerTracker[i].status = READER_PRESENT;
384 readerTracker[i].bInterfaceNumber = bInterfaceNumber;
386 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + i,
387 driver->libraryPath, deviceName);
390 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
393 if (classdriver && driver != classdriver)
396 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + i,
397 classdriver->libraryPath, deviceName);
400 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
403 readerTracker[i].status = READER_FAILED;
405 (void)CheckForOpenCT();
410 readerTracker[i].status = READER_FAILED;
412 (void)CheckForOpenCT();
416 (void)pthread_mutex_unlock(&usbNotifierMutex);
420 static void HPRescanUsbBus(
struct udev *udev)
423 struct udev_enumerate *enumerate;
424 struct udev_list_entry *devices, *dev_list_entry;
428 readerTracker[i].status = READER_ABSENT;
431 enumerate = udev_enumerate_new(udev);
432 udev_enumerate_add_match_subsystem(enumerate,
"usb");
433 udev_enumerate_scan_devices(enumerate);
434 devices = udev_enumerate_get_list_entry(enumerate);
437 udev_list_entry_foreach(dev_list_entry, devices)
440 struct udev_device *dev, *parent;
441 struct _driverTracker *driver, *classdriver;
443 int bInterfaceNumber;
444 const char *interface;
448 devpath = udev_list_entry_get_name(dev_list_entry);
449 dev = udev_device_new_from_syspath(udev, devpath);
456 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
461 devpath = udev_device_get_devnode(parent);
465 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
469 driver = get_driver(parent, devpath, &classdriver);
475 Log2(PCSC_LOG_DEBUG,
"Found matching USB device: %s", devpath);
479 bInterfaceNumber = 0;
480 interface = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
482 bInterfaceNumber = atoi(interface);
487 if (readerTracker[j].devpath
488 && (strcmp(readerTracker[j].devpath, devpath) == 0)
489 && (bInterfaceNumber == readerTracker[j].bInterfaceNumber))
492 readerTracker[j].status = READER_PRESENT;
495 Log2(PCSC_LOG_DEBUG,
"Refresh USB device: %s", devpath);
503 HPAddDevice(dev, parent, devpath);
506 udev_device_unref(dev);
510 udev_enumerate_unref(enumerate);
512 pthread_mutex_lock(&usbNotifierMutex);
516 if ((READER_ABSENT == readerTracker[i].status)
517 && (readerTracker[i].fullName != NULL))
519 Log4(PCSC_LOG_INFO,
"Removing USB device[%d]: %s at %s", i,
520 readerTracker[i].fullName, readerTracker[i].devpath);
522 RFRemoveReader(readerTracker[i].fullName,
523 PCSCLITE_HP_BASE_PORT + i);
525 readerTracker[i].status = READER_ABSENT;
526 free(readerTracker[i].devpath);
527 readerTracker[i].devpath = NULL;
528 free(readerTracker[i].fullName);
529 readerTracker[i].fullName = NULL;
533 pthread_mutex_unlock(&usbNotifierMutex);
536 static void HPEstablishUSBNotifications(
struct udev *udev)
538 struct udev_monitor *udev_monitor;
543 udev_monitor = udev_monitor_new_from_netlink(udev,
"udev");
546 r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor,
"usb",
550 Log2(PCSC_LOG_ERROR,
"udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r);
554 r = udev_monitor_enable_receiving(udev_monitor);
557 Log2(PCSC_LOG_ERROR,
"udev_monitor_enable_receiving() error: %d\n", r);
562 fd = udev_monitor_get_fd(udev_monitor);
564 while (!AraKiriHotPlug)
566 struct udev_device *dev, *parent;
567 const char *action, *devpath;
577 r = select(fd+1, &fds, NULL, NULL, NULL);
580 Log2(PCSC_LOG_ERROR,
"select(): %s", strerror(errno));
584 dev = udev_monitor_receive_device(udev_monitor);
587 Log1(PCSC_LOG_ERROR,
"udev_monitor_receive_device() error\n");
591 action = udev_device_get_action(dev);
592 if (0 == strcmp(
"remove", action))
594 Log1(PCSC_LOG_INFO,
"Device removed");
595 HPRescanUsbBus(udev);
599 if (strcmp(
"add", action))
602 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
604 devpath = udev_device_get_devnode(parent);
608 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
612 HPAddDevice(dev, parent, devpath);
615 udev_device_unref(dev);
619 for (i=0; i<driverSize; i++)
622 free(driverTracker[i].bundleName);
623 free(driverTracker[i].libraryPath);
624 free(driverTracker[i].readerName);
628 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
635 LONG HPSearchHotPluggables(
void)
641 readerTracker[i].status = READER_ABSENT;
642 readerTracker[i].bInterfaceNumber = 0;
643 readerTracker[i].devpath = NULL;
644 readerTracker[i].fullName = NULL;
647 return HPReadBundleValues();
654 LONG HPStopHotPluggables(
void)
656 AraKiriHotPlug = TRUE;
665 ULONG HPRegisterForHotplugEvents(
void)
669 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
673 Log1(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: "
674 PCSCLITE_HP_DROPDIR);
675 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
683 Log1(PCSC_LOG_ERROR,
"udev_new() failed");
687 HPRescanUsbBus(udev);
689 (void)ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
690 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, udev);
696 void HPReCheckSerialReaders(
void)
700 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