SOURCES: libusb-urb.patch (NEW) - hack to get threaded apps workin...

freetz freetz at pld-linux.org
Sat Jan 7 14:44:14 CET 2006


Author: freetz                       Date: Sat Jan  7 13:44:14 2006 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- hack to get threaded apps working again / make use of new /dev/bus/usb
  interface introduced in linux 2.6.14

---- Files affected:
SOURCES:
   libusb-urb.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/libusb-urb.patch
diff -u /dev/null SOURCES/libusb-urb.patch:1.1
--- /dev/null	Sat Jan  7 14:44:14 2006
+++ SOURCES/libusb-urb.patch	Sat Jan  7 14:44:09 2006
@@ -0,0 +1,117 @@
+--- libusb-0.1.10a.orig/linux.c
++++ libusb-0.1.10a/linux.c
+@@ -156,6 +156,8 @@
+   return ret;
+ }
+ 
++#define URB_USERCONTEXT_COOKIE		((void *)0x1)
++
+ /* Reading and writing are the same except for the endpoint */
+ static int usb_urb_transfer(usb_dev_handle *dev, int ep, int urbtype,
+ 	char *bytes, int size, int timeout)
+@@ -163,14 +165,16 @@
+   struct usb_urb urb;
+   unsigned int bytesdone = 0, requested;
+   struct timeval tv, tv_ref, tv_now;
+-  void *context;
++  struct usb_urb *context;
+   int ret, waiting;
+ 
+   /*
+-   * FIXME: The use of the URB interface is incorrect here if there are
+-   * multiple callers at the same time. We assume we're the only caller
+-   * and if we get completions from another caller, this code will fail
+-   * in interesting ways.
++   * HACK: The use of urb.usercontext is a hack to get threaded applications
++   * sort of working again. Threaded support is still not recommended, but
++   * this should allow applications to work in the common cases. Basically,
++   * if we get the completion for an URB we're not waiting for, then we update
++   * the usercontext pointer to 1 for the other threads URB and it will see
++   * the change after it wakes up from the the timeout. Ugly, but it works.
+    */
+ 
+   /*
+@@ -198,10 +202,10 @@
+     urb.flags = 0;
+     urb.buffer = bytes + bytesdone;
+     urb.buffer_length = requested;
+-    urb.usercontext = (void *)ep;
+     urb.signr = 0;
+     urb.actual_length = 0;
+     urb.number_of_packets = 0;	/* don't do isochronous yet */
++    urb.usercontext = NULL;
+ 
+     ret = ioctl(dev->fd, IOCTL_USB_SUBMITURB, &urb);
+     if (ret < 0) {
+@@ -212,18 +216,28 @@
+     FD_ZERO(&writefds);
+     FD_SET(dev->fd, &writefds);
+ 
++restart:
+     waiting = 1;
+-    while (((ret = ioctl(dev->fd, IOCTL_USB_REAPURBNDELAY, &context)) == -1) && waiting) {
++    context = NULL;
++    while (!urb.usercontext && ((ret = ioctl(dev->fd, IOCTL_USB_REAPURBNDELAY, &context)) == -1) && waiting) {
+       tv.tv_sec = 0;
+       tv.tv_usec = 1000; // 1 msec
+       select(dev->fd + 1, NULL, &writefds, NULL, &tv); //sub second wait
+ 
+-      /* compare with actual time, as the select timeout is not that precise */
+-      gettimeofday(&tv_now, NULL);
++      if (timeout) {
++        /* compare with actual time, as the select timeout is not that precise */
++        gettimeofday(&tv_now, NULL);
++
++        if ((tv_now.tv_sec > tv_ref.tv_sec) ||
++            ((tv_now.tv_sec == tv_ref.tv_sec) && (tv_now.tv_usec >= tv_ref.tv_usec)))
++          waiting = 0;
++      }
++    }
+ 
+-      if ((tv_now.tv_sec > tv_ref.tv_sec) ||
+-          ((tv_now.tv_sec == tv_ref.tv_sec) && (tv_now.tv_usec >= tv_ref.tv_usec)))
+-        waiting = 0;
++    if (context && context != &urb) {
++      context->usercontext = URB_USERCONTEXT_COOKIE;
++      /* We need to restart since we got a successful URB, but not ours */
++      goto restart;
+     }
+ 
+     /*
+@@ -231,14 +245,14 @@
+      * something happened during the reaping and we should return that
+      * error now
+      */
+-    if (ret < 0 && errno != EAGAIN)
++    if (ret < 0 && !urb.usercontext && errno != EAGAIN)
+       USB_ERROR_STR(-errno, "error reaping URB: %s", strerror(errno));
+ 
+     bytesdone += urb.actual_length;
+-  } while (ret == 0 && bytesdone < size && urb.actual_length == requested);
++  } while ((ret == 0 || urb.usercontext) && bytesdone < size && urb.actual_length == requested);
+ 
+   /* If the URB didn't complete in success or error, then let's unlink it */
+-  if (ret < 0) {
++  if (ret < 0 && !urb.usercontext) {
+     int rc;
+ 
+     if (!waiting)
+@@ -619,14 +633,11 @@
+   }
+ 
+   if (!usb_path[0]) {
+-    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 if (check_usb_vfs("/sys/bus/usb")) { /* 2.6 Kernel with sysfs */
+-      strncpy(usb_path, "/sys/bus/usb", sizeof(usb_path) -1);
++    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("/dev/usb")) {
+-      strncpy(usb_path, "/dev/usb", sizeof(usb_path) - 1);
++    } 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 */
================================================================


More information about the pld-cvs-commit mailing list