You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							200 lines
						
					
					
						
							6.3 KiB
						
					
					
				
			
		
		
	
	
							200 lines
						
					
					
						
							6.3 KiB
						
					
					
				# --- T2-COPYRIGHT-NOTE-BEGIN --- | 
						|
# This copyright note is auto-generated by ./scripts/Create-CopyPatch. | 
						|
#  | 
						|
# T2 SDE: package/.../libusb/speedup-v2.patch | 
						|
# Copyright (C) 2006 The T2 SDE Project | 
						|
#  | 
						|
# More information can be found in the files COPYING and README. | 
						|
#  | 
						|
# This patch file is dual-licensed. It is available under the license the | 
						|
# patched project is licensed under, as long as it is an OpenSource license | 
						|
# as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms | 
						|
# of the GNU General Public License as published by the Free Software | 
						|
# Foundation; either version 2 of the License, or (at your option) any later | 
						|
# version. | 
						|
# --- T2-COPYRIGHT-NOTE-END --- | 
						|
 | 
						|
2x speedup for the SANE/Avision driver. | 
						|
 | 
						|
  - Rene Rebe <[email protected]> | 
						|
 | 
						|
--- libusb-0.1.11/linux.c	2006-03-02 15:33:58.000000000 +0000 | 
						|
+++ libusb-0.1.11-improved/linux.c	2006-03-03 08:26:55.000000000 +0000 | 
						|
@@ -162,11 +162,14 @@ | 
						|
 static int usb_urb_transfer(usb_dev_handle *dev, int ep, int urbtype, | 
						|
 	char *bytes, int size, int timeout) | 
						|
 { | 
						|
-  struct usb_urb urb; | 
						|
+  int nurbs; | 
						|
+  struct usb_urb* urbs; | 
						|
   unsigned int bytesdone = 0, requested; | 
						|
   struct timeval tv, tv_ref, tv_now; | 
						|
   struct usb_urb *context; | 
						|
-  int ret, waiting; | 
						|
+  int rc = 0, ret = 0, waiting, i; | 
						|
+ | 
						|
+  fd_set writefds; | 
						|
  | 
						|
   /* | 
						|
    * HACK: The use of urb.usercontext is a hack to get threaded applications | 
						|
@@ -190,36 +193,47 @@ | 
						|
     tv_ref.tv_sec++; | 
						|
   } | 
						|
  | 
						|
-  do { | 
						|
-    fd_set writefds; | 
						|
+  /* allocate and fill all URBs */ | 
						|
+  nurbs = (size + MAX_READ_WRITE - 1) / MAX_READ_WRITE; | 
						|
+  //fprintf (stderr, "nurbs: %d\n", nurbs); | 
						|
+  urbs = malloc (sizeof(struct usb_urb) * nurbs); | 
						|
+  for (i = 0; i < nurbs; ++i) { | 
						|
  | 
						|
-    requested = size - bytesdone; | 
						|
+    requested = size - i * MAX_READ_WRITE; | 
						|
     if (requested > MAX_READ_WRITE) | 
						|
       requested = MAX_READ_WRITE; | 
						|
  | 
						|
-    urb.type = urbtype; | 
						|
-    urb.endpoint = ep; | 
						|
-    urb.flags = 0; | 
						|
-    urb.buffer = bytes + bytesdone; | 
						|
-    urb.buffer_length = requested; | 
						|
-    urb.signr = 0; | 
						|
-    urb.actual_length = 0; | 
						|
-    urb.number_of_packets = 0;	/* don't do isochronous yet */ | 
						|
-    urb.usercontext = NULL; | 
						|
+    urbs[i].type = urbtype; | 
						|
+    urbs[i].endpoint = ep; | 
						|
+    urbs[i].flags = 0; | 
						|
+    urbs[i].buffer = bytes + i * MAX_READ_WRITE; | 
						|
+    urbs[i].buffer_length = requested; | 
						|
+    urbs[i].signr = 0; | 
						|
+    urbs[i].actual_length = 0; | 
						|
+    urbs[i].number_of_packets = 0;	/* don't do isochronous yet */ | 
						|
+    urbs[i].usercontext = NULL; | 
						|
  | 
						|
-    ret = ioctl(dev->fd, IOCTL_USB_SUBMITURB, &urb); | 
						|
+    //fprintf (stderr, "submitting urb %d\n", i); | 
						|
+    ret = ioctl(dev->fd, IOCTL_USB_SUBMITURB, &urbs[i]); | 
						|
     if (ret < 0) { | 
						|
       USB_ERROR_STR(-errno, "error submitting URB: %s", strerror(errno)); | 
						|
-      return ret; | 
						|
+			rc = ret; | 
						|
+      goto end; | 
						|
     } | 
						|
+  } | 
						|
  | 
						|
-    FD_ZERO(&writefds); | 
						|
-    FD_SET(dev->fd, &writefds); | 
						|
+  FD_ZERO(&writefds); | 
						|
+  FD_SET(dev->fd, &writefds); | 
						|
  | 
						|
-restart: | 
						|
+  /* wait 'till all URBs completed */ | 
						|
+  for (i = 0; i < nurbs; ) { | 
						|
     waiting = 1; | 
						|
     context = NULL; | 
						|
-    while (!urb.usercontext && ((ret = ioctl(dev->fd, IOCTL_USB_REAPURBNDELAY, &context)) == -1) && waiting) { | 
						|
+    //fprintf (stderr, "waiting for URB %d\n", i); | 
						|
+ | 
						|
+    while (!urbs[i].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 | 
						|
@@ -229,52 +243,66 @@ | 
						|
         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))) | 
						|
+           ((tv_now.tv_sec == tv_ref.tv_sec) && (tv_now.tv_usec >= tv_ref.tv_usec))) | 
						|
           waiting = 0; | 
						|
       } | 
						|
     } | 
						|
  | 
						|
-    if (context && context != &urb) { | 
						|
+    /* mark done */ | 
						|
+    if (context) { | 
						|
+      //fprintf (stderr, "marking URB %p done.\n", context); | 
						|
       context->usercontext = URB_USERCONTEXT_COOKIE; | 
						|
-      /* We need to restart since we got a successful URB, but not ours */ | 
						|
-      goto restart; | 
						|
+ | 
						|
+      /* is it ours? */ | 
						|
+      //if (context && context == &urbs[i]) | 
						|
+        //fprintf (stderr, "which was the one we have been waiting for.\n"); | 
						|
     } | 
						|
  | 
						|
+    /* done= */ | 
						|
+    if (urbs[i].usercontext) { | 
						|
+      bytesdone += context->actual_length; | 
						|
+      ++i; /* next URB */ | 
						|
+      continue; | 
						|
+    } | 
						|
+ | 
						|
+    fprintf (stderr, "here, error?\n"); | 
						|
+ | 
						|
     /* | 
						|
      * If there was an error, that wasn't EAGAIN (no completion), then | 
						|
      * something happened during the reaping and we should return that | 
						|
      * error now | 
						|
      */ | 
						|
-    if (ret < 0 && !urb.usercontext && errno != EAGAIN) | 
						|
+    if (ret < 0 && !urbs[i].usercontext && errno != EAGAIN) | 
						|
       USB_ERROR_STR(-errno, "error reaping URB: %s", strerror(errno)); | 
						|
  | 
						|
-    bytesdone += urb.actual_length; | 
						|
-  } 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 && !urbs[i].usercontext) { | 
						|
  | 
						|
-  /* If the URB didn't complete in success or error, then let's unlink it */ | 
						|
-  if (ret < 0 && !urb.usercontext) { | 
						|
-    int rc; | 
						|
+      if (!waiting) | 
						|
+        rc = -ETIMEDOUT; | 
						|
+      else | 
						|
+        rc = urbs[i].status; | 
						|
+ | 
						|
+      ret = ioctl(dev->fd, IOCTL_USB_DISCARDURB, &urbs[i]); | 
						|
+      if (ret < 0 && errno != EINVAL && usb_debug >= 1) | 
						|
+        fprintf(stderr, "error discarding URB: %s", strerror(errno)); | 
						|
+ | 
						|
+      /* | 
						|
+       * When the URB is unlinked, it gets moved to the completed list and | 
						|
+       * then we need to reap it or else the next time we call this function, | 
						|
+       * we'll get the previous completion and exit early | 
						|
+       */ | 
						|
+      ioctl(dev->fd, IOCTL_USB_REAPURB, &context); | 
						|
  | 
						|
-    if (!waiting) | 
						|
-      rc = -ETIMEDOUT; | 
						|
-    else | 
						|
-      rc = urb.status; | 
						|
- | 
						|
-    ret = ioctl(dev->fd, IOCTL_USB_DISCARDURB, &urb); | 
						|
-    if (ret < 0 && errno != EINVAL && usb_debug >= 1) | 
						|
-      fprintf(stderr, "error discarding URB: %s", strerror(errno)); | 
						|
- | 
						|
-    /* | 
						|
-     * When the URB is unlinked, it gets moved to the completed list and | 
						|
-     * then we need to reap it or else the next time we call this function, | 
						|
-     * we'll get the previous completion and exit early | 
						|
-     */ | 
						|
-    ioctl(dev->fd, IOCTL_USB_REAPURB, &context); | 
						|
- | 
						|
-    return rc; | 
						|
+      goto end; | 
						|
+    } | 
						|
   } | 
						|
  | 
						|
-  return bytesdone; | 
						|
+	rc = bytesdone; | 
						|
+ | 
						|
+ end: | 
						|
+  free (urbs); | 
						|
+  return rc; | 
						|
 } | 
						|
  | 
						|
 int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
 | 
						|
 |