62b6a91
--- libusb-0.1.12/linux.c	2008-07-01 12:24:36.000000000 +0200
62b6a91
+++ libusb/linux.c	2008-06-30 15:21:09.000000000 +0200
62b6a91
@@ -166,7 +166,7 @@
62b6a91
   int bytesdone = 0, requested;
62b6a91
   struct timeval tv, tv_ref, tv_now;
62b6a91
   struct usb_urb *context;
62b6a91
-  int ret, waiting;
62b6a91
+  int ret, tdout, rc;
62b6a91
 
62b6a91
   /*
62b6a91
    * HACK: The use of urb.usercontext is a hack to get threaded applications
62b6a91
@@ -184,7 +184,6 @@
62b6a91
   gettimeofday(&tv_ref, NULL);
62b6a91
   tv_ref.tv_sec = tv_ref.tv_sec + timeout / 1000;
62b6a91
   tv_ref.tv_usec = tv_ref.tv_usec + (timeout % 1000) * 1000;
62b6a91
-
62b6a91
   if (tv_ref.tv_usec > 1000000) {
62b6a91
     tv_ref.tv_usec -= 1000000;
62b6a91
     tv_ref.tv_sec++;
62b6a91
@@ -216,65 +215,67 @@
62b6a91
     FD_ZERO(&writefds);
62b6a91
     FD_SET(dev->fd, &writefds);
62b6a91
 
62b6a91
-restart:
62b6a91
-    waiting = 1;
62b6a91
-    context = NULL;
62b6a91
-    while (!urb.usercontext && ((ret = ioctl(dev->fd, IOCTL_USB_REAPURBNDELAY, &context)) == -1) && waiting) {
62b6a91
-      tv.tv_sec = 0;
62b6a91
-      tv.tv_usec = 1000; // 1 msec
62b6a91
-      select(dev->fd + 1, NULL, &writefds, NULL, &tv;; //sub second wait
62b6a91
-
62b6a91
-      if (timeout) {
62b6a91
-        /* compare with actual time, as the select timeout is not that precise */
62b6a91
+    /* Now wait for our urb to turn up */
62b6a91
+    tdout = 0;
62b6a91
+    for (;;) {
62b6a91
+      ret = 0;
62b6a91
+      if (urb.usercontext) {
62b6a91
+	break;				/* Another thread found our URB for us */
62b6a91
+      }
62b6a91
+      context = NULL;
62b6a91
+      ret = ioctl(dev->fd, IOCTL_USB_REAPURBNDELAY, &context);
62b6a91
+      if (ret == 0 && context) {	/* Found something */
62b6a91
+        if (context == &urb) {		/* Got the URB we were waiting for */
62b6a91
+	  break;
62b6a91
+	}
62b6a91
+	/* Must be some other threads. Mark it and keep waiting for ours */
62b6a91
+        context->usercontext = URB_USERCONTEXT_COOKIE;
62b6a91
+      } else {
62b6a91
+	if (errno != EAGAIN) {
62b6a91
+          fprintf(stderr, "error reaping URB: %s", strerror(errno));
62b6a91
+	  break;
62b6a91
+	}
62b6a91
+	/* We are still waiting. See if we've timed out */
62b6a91
         gettimeofday(&tv_now, NULL);
62b6a91
-
62b6a91
         if ((tv_now.tv_sec > tv_ref.tv_sec) ||
62b6a91
-            ((tv_now.tv_sec == tv_ref.tv_sec) && (tv_now.tv_usec >= tv_ref.tv_usec)))
62b6a91
-          waiting = 0;
62b6a91
+            ((tv_now.tv_sec == tv_ref.tv_sec) && (tv_now.tv_usec >= tv_ref.tv_usec))) {
62b6a91
+	  if (tdout) {	/* Second time we've timed out. Discard must have failed */
62b6a91
+	    break;
62b6a91
+	  }
62b6a91
+          tdout = 1;
62b6a91
+	  /* Discard our URB and continue waiting a while for it to turn up */	
62b6a91
+	  ret = ioctl(dev->fd, IOCTL_USB_DISCARDURB, &urb;;
62b6a91
+          if (ret < 0 && errno != EINVAL && usb_debug >= 1) {
62b6a91
+            fprintf(stderr, "error discarding URB: %s", strerror(errno));
62b6a91
+          }
62b6a91
+	  /* Allow another 100msec for discard to occur. Should normally happen faster than this. */
62b6a91
+          tv_ref.tv_sec = tv_now.tv_sec + 100 / 1000;
62b6a91
+          tv_ref.tv_usec = tv_now.tv_usec + (100 % 1000) * 1000;
62b6a91
+          if (tv_ref.tv_usec > 1000000) {
62b6a91
+            tv_ref.tv_usec -= 1000000;
62b6a91
+            tv_ref.tv_sec++;
62b6a91
+          }
62b6a91
+        }
62b6a91
       }
62b6a91
+      /* Sleep for 2msec to wait for things to happen */
62b6a91
+      tv.tv_sec = 0;
62b6a91
+      tv.tv_usec = 2000; 	/* 2 msec */
62b6a91
+      select(dev->fd + 1, NULL, &writefds, NULL, &tv;; 
62b6a91
     }
62b6a91
 
62b6a91
-    if (context && context != &urb) {
62b6a91
-      context->usercontext = URB_USERCONTEXT_COOKIE;
62b6a91
-      /* We need to restart since we got a successful URB, but not ours */
62b6a91
-      goto restart;
62b6a91
-    }
62b6a91
-
62b6a91
-    /*
62b6a91
-     * If there was an error, that wasn't EAGAIN (no completion), then
62b6a91
-     * something happened during the reaping and we should return that
62b6a91
-     * error now
62b6a91
-     */
62b6a91
-    if (ret < 0 && !urb.usercontext && errno != EAGAIN)
62b6a91
-      USB_ERROR_STR(-errno, "error reaping URB: %s", strerror(errno));
62b6a91
+    if (ret < 0 || tdout)	/* We didn't get a sucessful URB back */
62b6a91
+      break;
62b6a91
 
62b6a91
     bytesdone += urb.actual_length;
62b6a91
-  } while ((ret == 0 || urb.usercontext) && bytesdone < size && urb.actual_length == requested);
62b6a91
-
62b6a91
-  /* If the URB didn't complete in success or error, then let's unlink it */
62b6a91
-  if (ret < 0 && !urb.usercontext) {
62b6a91
-    int rc;
62b6a91
+  } while (bytesdone < size && urb.actual_length == requested);
62b6a91
 
62b6a91
-    if (!waiting)
62b6a91
-      rc = -ETIMEDOUT;
62b6a91
-    else
62b6a91
-      rc = urb.status;
62b6a91
-
62b6a91
-    ret = ioctl(dev->fd, IOCTL_USB_DISCARDURB, &urb;;
62b6a91
-    if (ret < 0 && errno != EINVAL && usb_debug >= 1)
62b6a91
-      fprintf(stderr, "error discarding URB: %s", strerror(errno));
62b6a91
-
62b6a91
-    /*
62b6a91
-     * When the URB is unlinked, it gets moved to the completed list and
62b6a91
-     * then we need to reap it or else the next time we call this function,
62b6a91
-     * we'll get the previous completion and exit early
62b6a91
-     */
62b6a91
-    ioctl(dev->fd, IOCTL_USB_REAPURB, &context);
62b6a91
-
62b6a91
-    return rc;
62b6a91
-  }
62b6a91
-
62b6a91
-  return bytesdone;
62b6a91
+  if (tdout)
62b6a91
+    rc = -ETIMEDOUT;
62b6a91
+  else if (ret < 0)
62b6a91
+    rc = urb.status;
62b6a91
+  else
62b6a91
+    rc = bytesdone; 
62b6a91
+  return rc;
62b6a91
 }
62b6a91
 
62b6a91
 int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
62b6a91
--- libusb-0.1.12/linux.h	2005-02-02 23:00:07.000000000 +0100
62b6a91
+++ libusb/linux.h	2008-06-30 15:21:09.000000000 +0200
62b6a91
@@ -69,7 +69,7 @@
62b6a91
 	int number_of_packets;
62b6a91
 	int error_count;
62b6a91
 	unsigned int signr;  /* signal to be sent on error, -1 if none should be sent */
62b6a91
-	void *usercontext;
62b6a91
+	volatile void *usercontext;
62b6a91
 	struct usb_iso_packet_desc iso_frame_desc[0];
62b6a91
 };
62b6a91
 
62b6a91
--- libusb-0.1.12/Makefile.am	2006-03-04 03:52:46.000000000 +0100
62b6a91
+++ libusb/Makefile.am	2008-06-30 15:21:08.000000000 +0200
62b6a91
@@ -41,7 +41,7 @@
62b6a91
 endif
62b6a91
 endif
62b6a91
 
62b6a91
-AM_CFLAGS += $(AM_CFLAGS_EXT)
62b6a91
+AM_CFLAGS += $(AM_CFLAGS_EXT) -pthread
62b6a91
 
62b6a91
 AM_CPPFLAGS = -I.
62b6a91
 AM_CXXFLAGS =