41 #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); \
73 extern char Add_Interface_In_Name;
74 extern char Add_Serial_In_Name;
76 static pthread_t usbNotifyThread;
77 static int driverSize = -1;
78 static struct udev *Udev;
84 static struct _driverTracker
87 unsigned int productID;
93 } *driverTracker = NULL;
94 #define DRIVER_TRACKER_SIZE_STEP 10
98 #define DRIVER_TRACKER_INITIAL_SIZE 200
103 static struct _readerTracker
111 static LONG HPReadBundleValues(
void)
115 struct dirent *currFP = NULL;
116 char fullPath[FILENAME_MAX];
117 char fullLibPath[FILENAME_MAX];
120 hpDir = opendir(PCSCLITE_HP_DROPDIR);
124 Log1(PCSC_LOG_ERROR,
"Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
125 Log1(PCSC_LOG_ERROR,
"Disabling USB support for pcscd.");
130 driverSize = DRIVER_TRACKER_INITIAL_SIZE;
131 driverTracker = calloc(driverSize,
sizeof(*driverTracker));
132 if (NULL == driverTracker)
134 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
135 (void)closedir(hpDir);
139 #define GET_KEY(key, values) \
140 rv = LTPBundleFindValueWithKey(&plist, key, values); \
143 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
148 while ((currFP = readdir(hpDir)) != 0)
150 if (strstr(currFP->d_name,
".bundle") != 0)
154 list_t *manuIDs, *productIDs, *readerNames;
162 (void)snprintf(fullPath,
sizeof(fullPath),
"%s/%s/Contents/Info.plist",
163 PCSCLITE_HP_DROPDIR, currFP->d_name);
164 fullPath[
sizeof(fullPath) - 1] =
'\0';
166 rv = bundleParse(fullPath, &plist);
171 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
172 libraryPath = list_get_at(values, 0);
173 (
void)snprintf(fullLibPath, sizeof(fullLibPath),
174 "%s/%s/Contents/%s/%s",
175 PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
177 fullLibPath[sizeof(fullLibPath) - 1] = '\0';
179 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
180 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
181 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
183 if ((list_size(manuIDs) != list_size(productIDs))
184 || (list_size(manuIDs) != list_size(readerNames)))
186 Log2(PCSC_LOG_CRITICAL,
"Error parsing %s", fullPath);
187 (void)closedir(hpDir);
192 rv = LTPBundleFindValueWithKey(&plist, PCSCLITE_HP_CFBUNDLE_NAME,
197 CFBundleName = strdup(list_get_at(values, 0));
200 for (alias=0; alias<list_size(manuIDs); alias++)
205 value = list_get_at(manuIDs, alias);
206 driverTracker[listCount].manuID = strtol(value, NULL, 16);
208 value = list_get_at(productIDs, alias);
209 driverTracker[listCount].productID = strtol(value, NULL, 16);
211 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
214 driverTracker[listCount].bundleName = strdup(currFP->d_name);
215 driverTracker[listCount].libraryPath = strdup(fullLibPath);
216 driverTracker[listCount].CFBundleName = CFBundleName;
219 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
220 driverTracker[listCount].readerName);
223 if (listCount >= driverSize)
228 driverSize += DRIVER_TRACKER_SIZE_STEP;
231 "Increase driverTracker to %d entries", driverSize);
233 driverTracker = realloc(driverTracker,
234 driverSize *
sizeof(*driverTracker));
235 if (NULL == driverTracker)
237 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
239 (void)closedir(hpDir);
244 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
246 driverTracker[i].manuID = 0;
247 driverTracker[i].productID = 0;
248 driverTracker[i].bundleName = NULL;
249 driverTracker[i].libraryPath = NULL;
250 driverTracker[i].readerName = NULL;
251 driverTracker[i].CFBundleName = NULL;
255 bundleRelease(&plist);
259 driverSize = listCount;
260 (void)closedir(hpDir);
263 Log2(PCSC_LOG_INFO,
"Found drivers for %d readers", listCount);
270 static struct _driverTracker *get_driver(
struct udev_device *dev,
271 const char *devpath,
struct _driverTracker **classdriver)
274 unsigned int idVendor, idProduct;
275 static struct _driverTracker *driver;
278 str = udev_device_get_sysattr_value(dev,
"idVendor");
281 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
284 idVendor = strtol(str, NULL, 16);
286 str = udev_device_get_sysattr_value(dev,
"idProduct");
289 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
292 idProduct = strtol(str, NULL, 16);
295 "Looking for a driver for VID: 0x%04X, PID: 0x%04X, path: %s",
296 idVendor, idProduct, devpath);
301 for (i=0; i<driverSize; i++)
303 if (driverTracker[i].libraryPath != NULL &&
304 idVendor == driverTracker[i].manuID &&
305 idProduct == driverTracker[i].productID)
307 if ((driverTracker[i].CFBundleName != NULL)
308 && (0 == strcmp(driverTracker[i].CFBundleName,
"CCIDCLASSDRIVER")))
309 *classdriver = &driverTracker[i];
312 driver = &driverTracker[i];
325 static void HPRemoveDevice(
struct udev_device *dev)
329 struct udev_device *parent;
337 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
342 devpath = udev_device_get_devnode(parent);
346 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
350 sysname = udev_device_get_sysname(dev);
353 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysname() failed");
359 if (readerTracker[i].fullName && !strcmp(sysname, readerTracker[i].sysname))
361 Log4(PCSC_LOG_INFO,
"Removing USB device[%d]: %s at %s", i,
362 readerTracker[i].fullName, readerTracker[i].devpath);
364 RFRemoveReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i);
366 free(readerTracker[i].devpath);
367 readerTracker[i].devpath = NULL;
368 free(readerTracker[i].fullName);
369 readerTracker[i].fullName = NULL;
370 free(readerTracker[i].sysname);
371 readerTracker[i].sysname = NULL;
378 static void HPAddDevice(
struct udev_device *dev)
381 char deviceName[MAX_DEVICENAME];
382 char fullname[MAX_READERNAME];
383 struct _driverTracker *driver, *classdriver;
384 const char *sSerialNumber = NULL, *sInterfaceName = NULL;
385 const char *sInterfaceNumber;
387 int bInterfaceNumber;
389 struct udev_device *parent;
397 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
402 devpath = udev_device_get_devnode(parent);
406 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
410 driver = get_driver(parent, devpath, &classdriver);
415 Log2(PCSC_LOG_DEBUG,
"%s is not a supported smart card reader",
421 sysname = udev_device_get_sysname(dev);
424 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysname() failed");
431 if (readerTracker[i].fullName && !strcmp(sysname, readerTracker[i].sysname))
435 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", driver->readerName);
437 sInterfaceNumber = udev_device_get_sysattr_value(dev,
"bInterfaceNumber");
438 if (sInterfaceNumber)
439 bInterfaceNumber = atoi(sInterfaceNumber);
441 bInterfaceNumber = 0;
443 (void)snprintf(deviceName,
sizeof(deviceName),
444 "usb:%04x/%04x:libudev:%d:%s", driver->manuID, driver->productID,
445 bInterfaceNumber, devpath);
446 deviceName[
sizeof(deviceName) -1] =
'\0';
451 if (NULL == readerTracker[i].fullName)
455 if (PCSCLITE_MAX_READERS_CONTEXTS == i)
458 "Not enough reader entries. Already found %d readers", i);
462 if (Add_Interface_In_Name)
463 sInterfaceName = udev_device_get_sysattr_value(dev,
"interface");
465 if (Add_Serial_In_Name)
466 sSerialNumber = udev_device_get_sysattr_value(parent,
"serial");
469 strlcpy(fullname, driver->readerName,
sizeof(fullname));
474 strlcat(fullname,
" [",
sizeof(fullname));
475 strlcat(fullname, sInterfaceName,
sizeof(fullname));
476 strlcat(fullname,
"]",
sizeof(fullname));
484 if (!sInterfaceName || NULL == strstr(sInterfaceName, sSerialNumber))
486 strlcat(fullname,
" (",
sizeof(fullname));
487 strlcat(fullname, sSerialNumber,
sizeof(fullname));
488 strlcat(fullname,
")",
sizeof(fullname));
492 readerTracker[i].fullName = strdup(fullname);
493 readerTracker[i].devpath = strdup(devpath);
494 readerTracker[i].sysname = strdup(sysname);
496 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + i,
497 driver->libraryPath, deviceName);
500 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
503 if (classdriver && driver != classdriver)
506 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + i,
507 classdriver->libraryPath, deviceName);
510 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
512 (void)CheckForOpenCT();
517 (void)CheckForOpenCT();
523 static void HPScanUSB(
struct udev *udev)
525 struct udev_enumerate *enumerate;
526 struct udev_list_entry *devices, *dev_list_entry;
529 enumerate = udev_enumerate_new(udev);
530 udev_enumerate_add_match_subsystem(enumerate,
"usb");
531 udev_enumerate_scan_devices(enumerate);
532 devices = udev_enumerate_get_list_entry(enumerate);
535 udev_list_entry_foreach(dev_list_entry, devices)
537 struct udev_device *dev;
542 devpath = udev_list_entry_get_name(dev_list_entry);
543 dev = udev_device_new_from_syspath(udev, devpath);
546 Log2(PCSC_LOG_DEBUG,
"Found matching USB device: %s", devpath);
551 udev_device_unref(dev);
555 udev_enumerate_unref(enumerate);
559 static void HPEstablishUSBNotifications(
void *arg)
561 struct udev_monitor *udev_monitor = arg;
566 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
567 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
570 fd = udev_monitor_get_fd(udev_monitor);
573 Log2(PCSC_LOG_ERROR,
"udev_monitor_get_fd() error: %d", fd);
582 struct udev_device *dev;
587 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
590 r = TEMP_FAILURE_RETRY(poll(&pfd, 1, -1));
593 Log2(PCSC_LOG_ERROR,
"select(): %s", strerror(errno));
597 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
599 dev = udev_monitor_receive_device(udev_monitor);
602 const char *action = udev_device_get_action(dev);
606 if (!strcmp(
"remove", action))
608 Log1(PCSC_LOG_INFO,
"USB Device removed");
612 if (!strcmp(
"add", action))
614 Log1(PCSC_LOG_INFO,
"USB Device add");
620 udev_device_unref(dev);
631 LONG HPSearchHotPluggables(
void)
637 readerTracker[i].devpath = NULL;
638 readerTracker[i].fullName = NULL;
639 readerTracker[i].sysname = NULL;
642 return HPReadBundleValues();
649 LONG HPStopHotPluggables(
void)
659 pthread_cancel(usbNotifyThread);
660 pthread_join(usbNotifyThread, NULL);
662 for (i=0; i<driverSize; i++)
665 free(driverTracker[i].bundleName);
666 free(driverTracker[i].libraryPath);
667 free(driverTracker[i].readerName);
676 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
684 ULONG HPRegisterForHotplugEvents(
void)
686 struct udev_monitor *udev_monitor;
691 Log1(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: "
692 PCSCLITE_HP_DROPDIR);
693 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
701 Log1(PCSC_LOG_ERROR,
"udev_new() failed");
705 udev_monitor = udev_monitor_new_from_netlink(Udev,
"udev");
706 if (NULL == udev_monitor)
708 Log1(PCSC_LOG_ERROR,
"udev_monitor_new_from_netlink() error");
713 r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor,
"usb",
717 Log2(PCSC_LOG_ERROR,
"udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r);
721 r = udev_monitor_enable_receiving(udev_monitor);
724 Log2(PCSC_LOG_ERROR,
"udev_monitor_enable_receiving() error: %d\n", r);
731 if (ThreadCreate(&usbNotifyThread, 0,
732 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, udev_monitor))
734 Log1(PCSC_LOG_ERROR,
"ThreadCreate() failed");
742 void HPReCheckSerialReaders(
void)
746 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
This keeps track of a list of currently available reader structures.
This provides a search API for hot pluggble devices.
#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
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.