summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-05-16 17:13:11 +0200
committerHans de Goede <hdegoede@redhat.com>2013-05-16 17:18:33 +0200
commitcf46b17f8287c1a6650687ad4f84bb05fbbe213e (patch)
tree28a8c67ed9c73e9d59e471953b04e64016876b3f
parentf168b3d23f8cff5d5986ddbd7c0dffcd5cb91347 (diff)
downloadlibusb-cf46b17f8287c1a6650687ad4f84bb05fbbe213e.tar.gz
linux: Deal with devices being enumerated before their parents are
The linux netlink enumeration code processes devices in readdir order, which means devices may get enumerated before their parent is, IE on my system readdir order is (ls -U) 1-1 usb4 2-1.8 6-0:1.0 1-1.4.3 1-1.4.4.1:1.0 2-1 usb5 6-1.4 6-1:1.0 1-1.4.4 1-1.4.4.1:1.1 6-1 usb6 3-0:1.0 2-1.8:1.0 1-0:1.0 1-1.4.4.1:1.2 7-1 usb7 1-1.4.3:1.0 2-1.8:1.1 1-1:1.0 usb1 1-1.4.4.1 1-1.4.4:1.0 2-1.8:1.2 6-1.4:1.0 usb2 1-1.4:1.0 4-0:1.0 7-0:1.0 2-0:1.0 usb3 1-1.4 5-0:1.0 7-1:1.0 2-1:1.0 So 1.4.4.1 will get added (way) before 1.4.4 and indeed: [ 0.002243] [00004055] libusbx: debug [linux_get_device_address] scan 1-1.4.4.1 Dev 0x1973bc0 (1-1.4.4.1) has parent (nil) This patch fixes this by forcing enumeration of the parent from linux_parent_dev. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--libusb/os/linux_usbfs.c14
-rw-r--r--libusb/version_nano.h2
2 files changed, 14 insertions, 2 deletions
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 0159f81..bb8e8c2 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -118,6 +118,7 @@ static usbi_mutex_static_t hotplug_lock = USBI_MUTEX_INITIALIZER;
static int linux_start_event_monitor(void);
static int linux_stop_event_monitor(void);
static int linux_scan_devices(struct libusb_context *ctx);
+static int sysfs_scan_device(struct libusb_context *ctx, const char *devname);
#if !defined(USE_UDEV)
static int linux_default_scan_devices (struct libusb_context *ctx);
@@ -1098,7 +1099,7 @@ static struct libusb_device *linux_parent_dev(struct libusb_context *ctx, const
{
struct libusb_device *dev, *parent_dev = NULL;
char *parent_sysfs_dir, *tmp;
- int ret;
+ int ret, add_parent = 1;
/* XXX -- can we figure out the topology when using usbfs? */
if (NULL == sysfs_dir || 0 == strncmp(sysfs_dir, "usb", 3)) {
@@ -1126,6 +1127,7 @@ static struct libusb_device *linux_parent_dev(struct libusb_context *ctx, const
}
}
+retry:
/* find the parent in the context */
usbi_mutex_lock(&ctx->usb_devs_lock);
list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) {
@@ -1137,6 +1139,14 @@ static struct libusb_device *linux_parent_dev(struct libusb_context *ctx, const
}
usbi_mutex_unlock(&ctx->usb_devs_lock);
+ if (!parent_dev && add_parent) {
+ usbi_dbg("parent_dev %s not enumerated yet, enumerating now",
+ parent_sysfs_dir);
+ sysfs_scan_device(ctx, parent_sysfs_dir);
+ add_parent = 0;
+ goto retry;
+ }
+
free (parent_sysfs_dir);
return parent_dev;
}
@@ -1305,6 +1315,7 @@ static int usbfs_get_device_list(struct libusb_context *ctx)
return r;
}
+#endif
static int sysfs_scan_device(struct libusb_context *ctx, const char *devname)
{
@@ -1320,6 +1331,7 @@ static int sysfs_scan_device(struct libusb_context *ctx, const char *devname)
devname);
}
+#if !defined(USE_UDEV)
static int sysfs_get_device_list(struct libusb_context *ctx)
{
DIR *devices = opendir(SYSFS_DEVICE_PATH);
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 9d2fc4a..880c722 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 10682
+#define LIBUSB_NANO 10683