/* backend provides hotplug support */
struct libusb_device *dev;
+ if (usbi_backend->hotplug_poll)
+ usbi_backend->hotplug_poll();
+
usbi_mutex_lock(&ctx->usb_devs_lock);
list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) {
discdevs = discovered_devs_append(discdevs, dev);
* This function is executed when the user wishes to retrieve a list
* of USB devices connected to the system.
*
+ * If the backend has hotplug support, this function is not used!
+ *
* Return 0 on success, or a LIBUSB_ERROR code on failure.
*/
int (*get_device_list)(struct libusb_context *ctx,
struct discovered_devs **discdevs);
+ /* Apps which were written before hotplug support, may listen for
+ * hotplug events on their own and call libusb_get_device_list on
+ * device addition. In this case libusb_get_device_list will likely
+ * return a list without the new device in there, as the hotplug
+ * event thread will still be busy enumerating the device, which may
+ * take a while, or may not even have seen the event yet.
+ *
+ * To avoid this libusb_get_device_list will call this optional
+ * function for backends with hotplug support before copying
+ * ctx->usb_devs to the user. In this function the backend should
+ * ensure any pending hotplug events are fully processed before
+ * returning.
+ *
+ * Optional, should be implemented by backends with hotplug support.
+ */
+ void (*hotplug_poll)(void);
+
/* Open a device for I/O and other USB operations. The device handle
* is preallocated for you, you can retrieve the device in question
* through handle->dev.
return NULL;
}
+
+void linux_netlink_hotplug_poll(void)
+{
+ int r;
+
+ usbi_mutex_static_lock(&linux_hotplug_lock);
+ do {
+ r = linux_netlink_read_message();
+ } while (r == 0);
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
+}
static struct udev_monitor *udev_monitor = NULL;
static pthread_t linux_event_thread;
-static void udev_hotplug_event(void);
+static void udev_hotplug_event(struct udev_device* udev_dev);
static void *linux_udev_event_thread_main(void *arg);
int linux_udev_start_event_monitor(void)
static void *linux_udev_event_thread_main(void *arg)
{
+ struct udev_device* udev_dev;
struct pollfd fds = {.fd = udev_monitor_fd,
.events = POLLIN};
}
usbi_mutex_static_lock(&linux_hotplug_lock);
- udev_hotplug_event();
+ udev_dev = udev_monitor_receive_device(udev_monitor);
+ if (udev_dev)
+ udev_hotplug_event(udev_dev);
usbi_mutex_static_unlock(&linux_hotplug_lock);
}
dev_node, *sys_name);
}
-static void udev_hotplug_event(void)
+static void udev_hotplug_event(struct udev_device* udev_dev)
{
- struct udev_device* udev_dev;
const char* udev_action;
const char* sys_name = NULL;
uint8_t busnum = 0, devaddr = 0;
int detached;
int r;
- if (NULL == udev_monitor) {
- return;
- }
-
do {
- udev_dev = udev_monitor_receive_device(udev_monitor);
- if (!udev_dev) {
- usbi_err(NULL, "failed to read data from udev monitor socket.");
- return;
- }
-
udev_action = udev_device_get_action(udev_dev);
if (!udev_action) {
break;
return LIBUSB_SUCCESS;
}
+
+void linux_udev_hotplug_poll(void)
+{
+ struct udev_device* udev_dev;
+
+ usbi_mutex_static_lock(&linux_hotplug_lock);
+ do {
+ udev_dev = udev_monitor_receive_device(udev_monitor);
+ if (udev_dev) {
+ usbi_dbg("Handling hotplug event from hotplug_poll");
+ udev_hotplug_event(udev_dev);
+ }
+ } while (udev_dev);
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
+}
#endif
}
+static void op_hotplug_poll(void)
+{
+#if defined(USE_UDEV)
+ linux_udev_hotplug_poll();
+#else
+ linux_netlink_hotplug_poll();
+#endif
+}
+
static int _open_sysfs_attr(struct libusb_device *dev, const char *attr)
{
struct linux_device_priv *priv = _device_priv(dev);
.init = op_init,
.exit = op_exit,
.get_device_list = NULL,
+ .hotplug_poll = op_hotplug_poll,
.get_device_descriptor = op_get_device_descriptor,
.get_active_config_descriptor = op_get_active_config_descriptor,
.get_config_descriptor = op_get_config_descriptor,
int linux_udev_start_event_monitor(void);
int linux_udev_stop_event_monitor(void);
int linux_udev_scan_devices(struct libusb_context *ctx);
+void linux_udev_hotplug_poll(void);
#else
int linux_netlink_start_event_monitor(void);
int linux_netlink_stop_event_monitor(void);
+void linux_netlink_hotplug_poll(void);
#endif
void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name);
NULL, /* init() */
NULL, /* exit() */
obsd_get_device_list,
+ NULL, /* hotplug_poll */
obsd_open,
obsd_close,
wince_exit,
wince_get_device_list,
+ NULL, /* hotplug_poll */
wince_open,
wince_close,
windows_exit,
windows_get_device_list,
+ NULL, /* hotplug_poll */
windows_open,
windows_close,
-#define LIBUSB_NANO 10723
+#define LIBUSB_NANO 10724