}
+
+close(fd);
+ }
+
+ /*
+ * There should be one device left in the devices list and that should be
+ * the root device
+ */
+ for (i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) {
+if (devices[i])
+ bus->root_dev = devices[i];
+ }
+
+ return 0;
+}
+
+static int check_usb_vfs(const char *dirname)
+{
+ DIR *dir;
+ struct dirent *entry;
+ int found = 0;
+
+ dir = opendir(dirname);
+ if (!dir)
+return 0;
+
+ while ((entry = readdir(dir)) != NULL) {
+/* Skip anything starting with a . */
+if (entry->d_name[0] == '.')
+ continue;
+
+/* We assume if we find any files that it must be the right place */
+found = 1;
+break;
+ }
+
+ closedir(dir);
+
+ return found;
+}
+
+void usb_os_init(void)
+{
+ /* Find the path to the virtual filesystem */
+ if (getenv("USB_DEVFS_PATH")) {
+if (check_usb_vfs(getenv("USB_DEVFS_PATH"))) {
+ strncpy(usb_path, getenv("USB_DEVFS_PATH"), sizeof(usb_path) - 1);
+ usb_path[sizeof(usb_path) - 1] = 0;
+} else if (usb_debug)
+ fprintf(stderr, "usb_os_init: couldn't find USB VFS in USB_DEVFS_PATH\n");
+ }
+
+ if (!usb_path[0]) {
+if (check_usb_vfs("/dev/bus/usb")) {
+ strncpy(usb_path, "/dev/bus/usb", sizeof(usb_path) - 1);
+ usb_path[sizeof(usb_path) - 1] = 0;
+} else if (check_usb_vfs("/proc/bus/usb")) {
+ strncpy(usb_path, "/proc/bus/usb", sizeof(usb_path) - 1);
+ usb_path[sizeof(usb_path) - 1] = 0;
+} else
+ usb_path[0] = 0; /* No path, no USB support */
+ }
+
+ if (usb_debug) {
+if (usb_path[0])
+ fprintf(stderr, "usb_os_init: Found USB VFS at %s\n", usb_path);
+else
+ fprintf(stderr, "usb_os_init: No USB VFS found, is it mounted?\n");
+ }
+}
+
+int usb_resetep(usb_dev_handle *dev, unsigned int ep)
+{
+ int ret;
+
+ ret = ioctl(dev->fd, IOCTL_USB_RESETEP, &ep);
+ if (ret)
+USB_ERROR_STR(-errno, "could not reset ep %d: %s", ep,
+ strerror(errno));
+
+ return 0;
+}
+
+int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
+{
+ int ret;
+
+ ret = ioctl(dev->fd, IOCTL_USB_CLEAR_HALT, &ep);
+ if (ret)
+USB_ERROR_STR(-errno, "could not clear/halt ep %d: %s", ep,
+ strerror(errno));
+
+ return 0;
+}
+
+int usb_reset(usb_dev_handle *dev)
+{
+ int ret;
+
+ ret = ioctl(dev->fd, IOCTL_USB_RESET, NULL);
+ if (ret)
+ USB_ERROR_STR(-errno, "could not reset: %s", strerror(errno));
+
+ return 0;
+}
+
+int usb_get_driver_np(usb_dev_handle *dev, int interface, char *name,
+ unsigned int namelen)
+{
+ struct usb_getdriver getdrv;
+ int ret;
+
+ getdrv.interface = interface;
+ ret = ioctl(dev->fd, IOCTL_USB_GETDRIVER, &getdrv);
+ if (ret)
+USB_ERROR_STR(-errno, "could not get bound driver: %s", strerror(errno));
+
+ strncpy(name, getdrv.driver, namelen - 1);
+ name[namelen - 1] = 0;
+
+ return 0;
+}
+
+int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface)
+{
+ struct usb_ioctl command;
+ int ret;
+
+ command.ifno = interface;
+ command.ioctl_code = IOCTL_USB_DISCONNECT;
+ command.data = NULL;
+
+ ret = ioctl(dev->fd, IOCTL_USB_IOCTL, &command);
+ if (ret)
+USB_ERROR_STR(-errno, "could not detach kernel driver from interface %d: %s",
+interface, strerror(errno));
+
+ return 0;
+}
+
=== modified file '.pc/applied-patches'
--- .pc/applied-patches 2014-07-03 20:17:03 +
+++ .pc/applied-patches 2015-05-17 16:46:05 +
@@ -10,4 +10,5 @@
09_dummy.diff
10_hurd.diff
11_transfer_timeout.diff
+12_hang_after_resume.diff
91_ac_prog_cxx.diff
=== modified file 'debian/changelog'
=== added file 'debian/patches/12_hang_after_resume.diff'
--- debian/patches/12_hang_after_resume.diff 1970-01-01 00:00:00 +
+++ debian/patches/12_hang_after_resume.diff 2015-05-17 16:45:30 +
@@ -0,0 +1,47 @@
+Description: Fix occasional hang after suspend/resume.
+ After suspend/resume linux kernel may loose our requests, and
+ usb_urb_transfer() will wait forever for lost requests to complete. With this
+ patch lost request are properly handled.
+ Also fixes race condition leading to stack corruption.
+Author: Alexander Ponyatykh
+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/libusb/+bug/1455924
+Forwarded: no
+Last-Update: 2015-05-17
+===
+--- a/linux.c
b/linux.c
+@@ -166,7 +166,7 @@
+ int bytesdone = 0, requested;
+ struct timeval tv, tv_ref, tv_now;
+ struct usb_urb *context;
+- int ret, waiting;
++ int ret, waiting, our_urb_dequeued;
+
+ /*
+* HACK: The use of urb.usercontext is a hack to get threaded applications
+@@ -277,7 +277,24 @@
+ * then we need to reap it or else the next time we call this function,
+ * we'll get the previous com