summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Dickens <christopher.a.dickens@gmail.com>2013-06-27 09:14:15 -0700
committerHans de Goede <hdegoede@redhat.com>2013-08-21 15:58:00 +0200
commit6732582bb17662aa02a913008be899ef9ace5870 (patch)
tree6c9534fdff1757f5e94135c4f876b6ecf953904c
parenta06eafdc528d5f3ea21a26c34ceaa13e09dfd4f3 (diff)
downloadlibusb-6732582bb17662aa02a913008be899ef9ace5870.tar.gz
linux: Handle device disconnection early when possible
If a device is open, the device's fd will trigger a POLLERR condition once it is removed. Sometimes this can occur well before the udev monitor sends the remove event. This can also be caught early if the device is not currently open but an attempt to open it is made. In both situations, this can be caught early and processed so that the device does not continue to show up in the device list after it has been disconnected but before the udev monitor processes the event. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--libusb/os/linux_netlink.c2
-rw-r--r--libusb/os/linux_udev.c2
-rw-r--r--libusb/os/linux_usbfs.c23
-rw-r--r--libusb/os/linux_usbfs.h2
-rw-r--r--libusb/version_nano.h2
5 files changed, 25 insertions, 6 deletions
diff --git a/libusb/os/linux_netlink.c b/libusb/os/linux_netlink.c
index 40f3fef..f1c1be1 100644
--- a/libusb/os/linux_netlink.c
+++ b/libusb/os/linux_netlink.c
@@ -293,7 +293,7 @@ static int linux_netlink_read_message(void)
/* signal device is available (or not) to all contexts */
if (detached)
- linux_hotplug_disconnected(busnum, devaddr, sys_name);
+ linux_device_disconnected(busnum, devaddr, sys_name);
else
linux_hotplug_enumerate(busnum, devaddr, sys_name);
diff --git a/libusb/os/linux_udev.c b/libusb/os/linux_udev.c
index 70f632d..99ac943 100644
--- a/libusb/os/linux_udev.c
+++ b/libusb/os/linux_udev.c
@@ -240,7 +240,7 @@ static void udev_hotplug_event(struct udev_device* udev_dev)
if (strncmp(udev_action, "add", 3) == 0) {
linux_hotplug_enumerate(busnum, devaddr, sys_name);
} else if (detached) {
- linux_hotplug_disconnected(busnum, devaddr, sys_name);
+ linux_device_disconnected(busnum, devaddr, sys_name);
} else {
usbi_err(NULL, "ignoring udev action %s", udev_action);
}
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 8c0ef6f..142fa2b 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -1090,7 +1090,7 @@ void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_na
usbi_mutex_static_unlock(&active_contexts_lock);
}
-void linux_hotplug_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name)
+void linux_device_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name)
{
struct libusb_context *ctx;
struct libusb_device *dev;
@@ -1265,8 +1265,20 @@ static int op_open(struct libusb_device_handle *handle)
int r;
hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0);
- if (hpriv->fd < 0)
+ if (hpriv->fd < 0) {
+ if (hpriv->fd == LIBUSB_ERROR_NO_DEVICE) {
+ /* device will still be marked as attached if hotplug monitor thread
+ * hasn't processed remove event yet */
+ usbi_mutex_static_lock(&linux_hotplug_lock);
+ if (handle->dev->attached) {
+ usbi_dbg("open failed with no device, but device still attached");
+ linux_device_disconnected(handle->dev->bus_number,
+ handle->dev->device_address, NULL);
+ }
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
+ }
return hpriv->fd;
+ }
r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
if (r < 0) {
@@ -2500,6 +2512,13 @@ static int op_handle_events(struct libusb_context *ctx,
if (pollfd->revents & POLLERR) {
usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->fd);
usbi_handle_disconnect(handle);
+ /* device will still be marked as attached if hotplug monitor thread
+ * hasn't processed remove event yet */
+ usbi_mutex_static_lock(&linux_hotplug_lock);
+ if (handle->dev->attached)
+ linux_device_disconnected(handle->dev->bus_number,
+ handle->dev->device_address, NULL);
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
continue;
}
diff --git a/libusb/os/linux_usbfs.h b/libusb/os/linux_usbfs.h
index 499bab7..1f5b191 100644
--- a/libusb/os/linux_usbfs.h
+++ b/libusb/os/linux_usbfs.h
@@ -170,7 +170,7 @@ void linux_netlink_hotplug_poll(void);
#endif
void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name);
-void linux_hotplug_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name);
+void linux_device_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name);
int linux_get_device_address (struct libusb_context *ctx, int detached,
uint8_t *busnum, uint8_t *devaddr, const char *dev_node,
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 4c3e712..b5a3ca9 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 10816
+#define LIBUSB_NANO 10817