|
|
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 =
|