39 #if defined(HAVE_LIBUDEV) && defined(USE_USB) 57 #ifndef TEMP_FAILURE_RETRY 58 #define TEMP_FAILURE_RETRY(expression) \ 60 ({ long int __result; \ 61 do __result = (long int) (expression); \ 62 while (__result == -1L && errno == EINTR); \ 71 extern char Add_Interface_In_Name;
72 extern char Add_Serial_In_Name;
74 static pthread_t usbNotifyThread;
75 static int driverSize = -1;
76 static struct udev *Udev;
82 static struct _driverTracker
85 unsigned int productID;
91 } *driverTracker = NULL;
92 #define DRIVER_TRACKER_SIZE_STEP 10 96 #define DRIVER_TRACKER_INITIAL_SIZE 200 101 static struct _readerTracker
109 static LONG HPReadBundleValues(
void)
113 struct dirent *currFP = NULL;
114 char fullPath[FILENAME_MAX];
115 char fullLibPath[FILENAME_MAX];
118 hpDir = opendir(PCSCLITE_HP_DROPDIR);
122 Log1(PCSC_LOG_ERROR,
"Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
123 Log1(PCSC_LOG_ERROR,
"Disabling USB support for pcscd.");
128 driverSize = DRIVER_TRACKER_INITIAL_SIZE;
129 driverTracker = calloc(driverSize,
sizeof(*driverTracker));
130 if (NULL == driverTracker)
132 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
133 (void)closedir(hpDir);
137 #define GET_KEY(key, values) \ 138 rv = LTPBundleFindValueWithKey(&plist, key, values); \ 141 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \ 146 while ((currFP = readdir(hpDir)) != 0)
148 if (strstr(currFP->d_name,
".bundle") != 0)
152 list_t *manuIDs, *productIDs, *readerNames;
160 (void)snprintf(fullPath,
sizeof(fullPath),
"%s/%s/Contents/Info.plist",
161 PCSCLITE_HP_DROPDIR, currFP->d_name);
162 fullPath[
sizeof(fullPath) - 1] =
'\0';
164 rv = bundleParse(fullPath, &plist);
169 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
170 libraryPath = list_get_at(values, 0);
171 (void)snprintf(fullLibPath,
sizeof(fullLibPath),
172 "%s/%s/Contents/%s/%s",
173 PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
175 fullLibPath[
sizeof(fullLibPath) - 1] =
'\0';
177 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
178 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
179 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
181 if ((list_size(manuIDs) != list_size(productIDs))
182 || (list_size(manuIDs) != list_size(readerNames)))
184 Log2(PCSC_LOG_CRITICAL,
"Error parsing %s", fullPath);
185 (void)closedir(hpDir);
190 rv = LTPBundleFindValueWithKey(&plist, PCSCLITE_HP_CFBUNDLE_NAME,
195 CFBundleName = strdup(list_get_at(values, 0));
198 for (alias=0; alias<list_size(manuIDs); alias++)
203 value = list_get_at(manuIDs, alias);
204 driverTracker[listCount].manuID = strtol(value, NULL, 16);
206 value = list_get_at(productIDs, alias);
207 driverTracker[listCount].productID = strtol(value, NULL, 16);
209 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
212 driverTracker[listCount].bundleName = strdup(currFP->d_name);
213 driverTracker[listCount].libraryPath = strdup(fullLibPath);
214 driverTracker[listCount].CFBundleName = CFBundleName;
217 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
218 driverTracker[listCount].readerName);
221 if (listCount >= driverSize)
226 driverSize += DRIVER_TRACKER_SIZE_STEP;
229 "Increase driverTracker to %d entries", driverSize);
232 void* tmp = realloc(driverTracker,
233 driverSize *
sizeof(*driverTracker));
238 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
240 (void)closedir(hpDir);
246 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
248 driverTracker[i].manuID = 0;
249 driverTracker[i].productID = 0;
250 driverTracker[i].bundleName = NULL;
251 driverTracker[i].libraryPath = NULL;
252 driverTracker[i].readerName = NULL;
253 driverTracker[i].CFBundleName = NULL;
257 bundleRelease(&plist);
261 driverSize = listCount;
262 (void)closedir(hpDir);
265 Log2(PCSC_LOG_INFO,
"Found drivers for %d readers", listCount);
272 static struct _driverTracker *get_driver(
struct udev_device *dev,
273 const char *devpath,
struct _driverTracker **classdriver)
276 unsigned int idVendor, idProduct;
277 static struct _driverTracker *driver;
280 str = udev_device_get_sysattr_value(dev,
"idVendor");
283 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
286 idVendor = strtol(str, NULL, 16);
288 str = udev_device_get_sysattr_value(dev,
"idProduct");
291 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysattr_value() failed");
294 idProduct = strtol(str, NULL, 16);
300 "Looking for a driver for VID: 0x%04X, PID: 0x%04X, path: %s",
301 idVendor, idProduct, devpath);
306 for (i=0; i<driverSize; i++)
308 if (driverTracker[i].libraryPath != NULL &&
309 idVendor == driverTracker[i].manuID &&
310 idProduct == driverTracker[i].productID)
312 if ((driverTracker[i].CFBundleName != NULL)
313 && (0 == strcmp(driverTracker[i].CFBundleName,
"CCIDCLASSDRIVER")))
314 *classdriver = &driverTracker[i];
317 driver = &driverTracker[i];
330 static void HPRemoveDevice(
struct udev_device *dev)
334 struct udev_device *parent;
342 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
347 devpath = udev_device_get_devnode(parent);
351 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
355 sysname = udev_device_get_sysname(dev);
358 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysname() failed");
364 if (readerTracker[i].fullName && !strcmp(sysname, readerTracker[i].sysname))
366 Log4(PCSC_LOG_INFO,
"Removing USB device[%d]: %s at %s", i,
367 readerTracker[i].fullName, readerTracker[i].devpath);
369 RFRemoveReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i);
371 free(readerTracker[i].devpath);
372 readerTracker[i].devpath = NULL;
373 free(readerTracker[i].fullName);
374 readerTracker[i].fullName = NULL;
375 free(readerTracker[i].sysname);
376 readerTracker[i].sysname = NULL;
383 static void HPAddDevice(
struct udev_device *dev)
386 char *deviceName = NULL;
387 char *fullname = NULL;
388 struct _driverTracker *driver, *classdriver;
389 const char *sSerialNumber = NULL, *sInterfaceName = NULL;
390 const char *sInterfaceNumber;
392 int bInterfaceNumber;
394 struct udev_device *parent;
402 parent = udev_device_get_parent_with_subsystem_devtype(dev,
"usb",
407 devpath = udev_device_get_devnode(parent);
411 Log1(PCSC_LOG_ERROR,
"udev_device_get_devnode() failed");
415 driver = get_driver(parent, devpath, &classdriver);
420 Log2(PCSC_LOG_DEBUG,
"%s is not a supported smart card reader",
426 sysname = udev_device_get_sysname(dev);
429 Log1(PCSC_LOG_ERROR,
"udev_device_get_sysname() failed");
436 if (readerTracker[index].fullName && !strcmp(sysname, readerTracker[index].sysname))
440 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", driver->readerName);
442 sInterfaceNumber = udev_device_get_sysattr_value(dev,
"bInterfaceNumber");
443 if (sInterfaceNumber)
444 bInterfaceNumber = atoi(sInterfaceNumber);
446 bInterfaceNumber = 0;
448 a = asprintf(&deviceName,
"usb:%04x/%04x:libudev:%d:%s",
449 driver->manuID, driver->productID, bInterfaceNumber, devpath);
452 Log1(PCSC_LOG_ERROR,
"asprintf() failed");
459 if (NULL == readerTracker[index].fullName)
466 "Not enough reader entries. Already found %d readers", index);
470 if (Add_Interface_In_Name)
471 sInterfaceName = udev_device_get_sysattr_value(dev,
"interface");
473 if (Add_Serial_In_Name)
474 sSerialNumber = udev_device_get_sysattr_value(parent,
"serial");
477 fullname = strdup(driver->readerName);
485 a = asprintf(&result,
"%s [%s]", fullname, sInterfaceName);
488 Log1(PCSC_LOG_ERROR,
"asprintf() failed");
501 if (!sInterfaceName || NULL == strstr(sInterfaceName, sSerialNumber))
506 a = asprintf(&result,
"%s (%s)", fullname, sSerialNumber);
509 Log1(PCSC_LOG_ERROR,
"asprintf() failed");
518 readerTracker[index].fullName = strdup(fullname);
519 readerTracker[index].devpath = strdup(devpath);
520 readerTracker[index].sysname = strdup(sysname);
522 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + index,
523 driver->libraryPath, deviceName);
526 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
529 if (classdriver && driver != classdriver)
532 ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + index,
533 classdriver->libraryPath, deviceName);
536 Log2(PCSC_LOG_ERROR,
"Failed adding USB device: %s",
538 (void)CheckForOpenCT();
543 (void)CheckForOpenCT();
550 free(readerTracker[index].devpath);
551 readerTracker[index].devpath = NULL;
552 free(readerTracker[index].fullName);
553 readerTracker[index].fullName = NULL;
554 free(readerTracker[index].sysname);
555 readerTracker[index].sysname = NULL;
564 static void HPScanUSB(
struct udev *udev)
566 struct udev_enumerate *enumerate;
567 struct udev_list_entry *devices, *dev_list_entry;
570 enumerate = udev_enumerate_new(udev);
571 udev_enumerate_add_match_subsystem(enumerate,
"usb");
572 udev_enumerate_scan_devices(enumerate);
573 devices = udev_enumerate_get_list_entry(enumerate);
576 udev_list_entry_foreach(dev_list_entry, devices)
578 struct udev_device *dev;
583 devpath = udev_list_entry_get_name(dev_list_entry);
584 dev = udev_device_new_from_syspath(udev, devpath);
587 Log2(PCSC_LOG_DEBUG,
"Found matching USB device: %s", devpath);
592 udev_device_unref(dev);
596 udev_enumerate_unref(enumerate);
600 static void * HPEstablishUSBNotifications(
void *arg)
602 struct udev_monitor *udev_monitor = arg;
607 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
608 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
611 fd = udev_monitor_get_fd(udev_monitor);
614 Log2(PCSC_LOG_ERROR,
"udev_monitor_get_fd() error: %d", fd);
623 struct udev_device *dev;
628 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
631 r = TEMP_FAILURE_RETRY(poll(&pfd, 1, -1));
634 Log2(PCSC_LOG_ERROR,
"select(): %s", strerror(errno));
638 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
640 dev = udev_monitor_receive_device(udev_monitor);
643 const char *action = udev_device_get_action(dev);
647 if (!strcmp(
"remove", action))
649 Log1(PCSC_LOG_INFO,
"USB Device removed");
653 if (!strcmp(
"add", action))
655 Log1(PCSC_LOG_INFO,
"USB Device add");
661 udev_device_unref(dev);
672 LONG HPSearchHotPluggables(
void)
678 readerTracker[i].devpath = NULL;
679 readerTracker[i].fullName = NULL;
680 readerTracker[i].sysname = NULL;
683 return HPReadBundleValues();
690 LONG HPStopHotPluggables(
void)
700 pthread_cancel(usbNotifyThread);
701 pthread_join(usbNotifyThread, NULL);
703 for (i=0; i<driverSize; i++)
706 free(driverTracker[i].bundleName);
707 free(driverTracker[i].libraryPath);
708 free(driverTracker[i].readerName);
717 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
725 ULONG HPRegisterForHotplugEvents(
void)
727 struct udev_monitor *udev_monitor;
732 Log1(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: " 733 PCSCLITE_HP_DROPDIR);
734 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
742 Log1(PCSC_LOG_ERROR,
"udev_new() failed");
746 udev_monitor = udev_monitor_new_from_netlink(Udev,
"udev");
747 if (NULL == udev_monitor)
749 Log1(PCSC_LOG_ERROR,
"udev_monitor_new_from_netlink() error");
754 r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor,
"usb",
758 Log2(PCSC_LOG_ERROR,
"udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r);
762 r = udev_monitor_enable_receiving(udev_monitor);
765 Log2(PCSC_LOG_ERROR,
"udev_monitor_enable_receiving() error: %d\n", r);
772 if (ThreadCreate(&usbNotifyThread, 0,
773 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, udev_monitor))
775 Log1(PCSC_LOG_ERROR,
"ThreadCreate() failed");
783 void HPReCheckSerialReaders(
void)
787 Log0(PCSC_LOG_ERROR);
#define SCARD_S_SUCCESS
No error was encountered.
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)
This keeps track of a list of currently available reader structures.
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
This provides a search API for hot pluggble devices.