static void HPEstablishUSBNotifications(void) { int i, do_polling; /* libusb default is /dev/bus/usb but the devices are not yet visible there * when a hotplug is requested */ setenv("USB_DEVFS_PATH", "/proc/bus/usb", 0); usb_init(); /* scan the USB bus for devices at startup */ HPRescanUsbBus(); /* if at least one driver do not have IFD_GENERATE_HOTPLUG */ do_polling = FALSE; for (i=0; i<driverSize; i++) if (driverTracker[i].libraryPath) if ((driverTracker[i].ifdCapabilities & IFD_GENERATE_HOTPLUG) == 0) { Log2(PCSC_LOG_INFO, "Driver %s does not support IFD_GENERATE_HOTPLUG. Using active polling instead.", driverTracker[i].bundleName); if (HPForceReaderPolling < 1) HPForceReaderPolling = 1; break; } if (HPForceReaderPolling) { Log2(PCSC_LOG_INFO, "Polling forced every %d second(s)", HPForceReaderPolling); do_polling = TRUE; } if (do_polling) { while (!AraKiriHotPlug) { SYS_Sleep(HPForceReaderPolling); HPRescanUsbBus(); } } else { char dummy; pipe(rescan_pipe); while (read(rescan_pipe[0], &dummy, sizeof(dummy)) > 0) { Log1(PCSC_LOG_INFO, "Reload serial configuration"); HPRescanUsbBus(); RFReCheckReaderConf(); Log1(PCSC_LOG_INFO, "End reload serial configuration"); } close(rescan_pipe[0]); rescan_pipe[0] = -1; } }
/** * Sets up callbacks for device hotplug events. */ ULONG HPRegisterForHotplugEvents(void) { struct udev *udev; (void)pthread_mutex_init(&usbNotifierMutex, NULL); if (driverSize <= 0) { Log1(PCSC_LOG_INFO, "No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR); Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd"); return 0; } /* Create the udev object */ udev = udev_new(); if (!udev) { Log1(PCSC_LOG_ERROR, "udev_new() failed"); return 0; } HPRescanUsbBus(udev); (void)ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED, (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, udev); return 0; } /* HPRegisterForHotplugEvents */
static void HPEstablishUSBNotifications(struct udev *udev) { struct udev_monitor *udev_monitor; int r, i; int fd; fd_set fds; udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); /* filter only the interfaces */ r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_interface"); if (r) { Log2(PCSC_LOG_ERROR, "udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r); return; } r = udev_monitor_enable_receiving(udev_monitor); if (r) { Log2(PCSC_LOG_ERROR, "udev_monitor_enable_receiving() error: %d\n", r); return; } /* udev monitor file descriptor */ fd = udev_monitor_get_fd(udev_monitor); while (!AraKiriHotPlug) { struct udev_device *dev, *parent; const char *action, *devpath; #ifdef DEBUG_HOTPLUG Log0(PCSC_LOG_INFO); #endif FD_ZERO(&fds); FD_SET(fd, &fds); /* wait for a udev event */ r = select(fd+1, &fds, NULL, NULL, NULL); if (r < 0) { Log2(PCSC_LOG_ERROR, "select(): %s", strerror(errno)); return; } dev = udev_monitor_receive_device(udev_monitor); if (!dev) { Log1(PCSC_LOG_ERROR, "udev_monitor_receive_device() error\n"); return; } action = udev_device_get_action(dev); if (0 == strcmp("remove", action)) { Log1(PCSC_LOG_INFO, "Device removed"); HPRescanUsbBus(udev); continue; } if (strcmp("add", action)) continue; parent = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device"); devpath = udev_device_get_devnode(parent); if (!devpath) { /* the device disapeared? */ Log1(PCSC_LOG_ERROR, "udev_device_get_devnode() failed"); continue; } HPAddDevice(dev, parent, devpath); /* free device */ udev_device_unref(dev); } for (i=0; i<driverSize; i++) { /* free strings allocated by strdup() */ free(driverTracker[i].bundleName); free(driverTracker[i].libraryPath); free(driverTracker[i].readerName); } free(driverTracker); Log1(PCSC_LOG_INFO, "Hotplug stopped"); } /* HPEstablishUSBNotifications */