diff options
author | Hans de Goede <hdegoede@redhat.com> | 2013-05-16 17:13:11 +0200 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2013-05-16 17:18:33 +0200 |
commit | cf46b17f8287c1a6650687ad4f84bb05fbbe213e (patch) | |
tree | 28a8c67ed9c73e9d59e471953b04e64016876b3f | |
parent | f168b3d23f8cff5d5986ddbd7c0dffcd5cb91347 (diff) | |
download | libusb-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.c | 14 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
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 |