Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
Robert Scheck
f12f257dd1 Import of libusb1-1.0.9-0.6.rc1.el6.src.rpm (from RHEL 6) for EPEL 5 2016-01-12 11:56:34 +01:00
13 changed files with 847 additions and 21 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/libusb-*.tar.bz2

View file

@ -0,0 +1,32 @@
From 1cc5b4a9fb984e83681ae5c797fa6b22bc20f809 Mon Sep 17 00:00:00 2001
From: Ludovic Rousseau <ludovic.rousseau+github@gmail.com>
Date: Fri, 16 Sep 2011 18:07:56 +0200
Subject: [PATCH 01/40] Correctly handle LIBUSB_TRANSFER_OVERFLOW in
libusb_control_transfer()
sync.c: In function `libusb_control_transfer':
sync.c:122: warning: enumeration value `LIBUSB_TRANSFER_OVERFLOW' not
handled in switch
Fixes #120.
---
libusb/sync.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libusb/sync.c b/libusb/sync.c
index d50413b..8eed47b 100644
--- a/libusb/sync.c
+++ b/libusb/sync.c
@@ -132,6 +132,9 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
case LIBUSB_TRANSFER_NO_DEVICE:
r = LIBUSB_ERROR_NO_DEVICE;
break;
+ case LIBUSB_TRANSFER_OVERFLOW:
+ r = LIBUSB_ERROR_OVERFLOW;
+ break;
default:
usbi_warn(HANDLE_CTX(dev_handle),
"unrecognised status code %d", transfer->status);
--
1.7.9.3

View file

@ -0,0 +1,37 @@
From 52508a86e26f0bc74b0a7a3b05ed08a29996b44c Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 20 Feb 2012 16:05:48 +0100
Subject: [PATCH 1/6] linux: Fix cancel_transfer return value when cancelling
a multi-urb transfer
If we fail to cancel the last urb of a multi-urb transfer because it
has already completed (errno == EINVAL on DISCARD_URB), then the entire
transfer has already completed, so returning NOT_FOUND is consistent with what
the documentation for libusb_cancel_transfer says.
But if we've successfully cancelled the last urb, and then another urb
fails with errno == EINVAL, this means that we've still cancelled the
transfer, as it has only *partially* completed.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
libusb/os/linux_usbfs.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 2b81189..099fc61 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -1466,7 +1466,8 @@ static int discard_urbs(struct usbi_transfer *itransfer, int first, int last_plu
if (EINVAL == errno) {
usbi_dbg("URB not found --> assuming ready to be reaped");
- ret = LIBUSB_ERROR_NOT_FOUND;
+ if (i == (last_plus_one - 1))
+ ret = LIBUSB_ERROR_NOT_FOUND;
} else if (ENODEV == errno) {
usbi_dbg("Device not found for URB --> assuming ready to be reaped");
ret = LIBUSB_ERROR_NO_DEVICE;
--
1.7.9.3

View file

@ -0,0 +1,46 @@
From e8c0b72bf8cc6d89c3546bbdbcc85b2c63086578 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 20 Feb 2012 16:12:19 +0100
Subject: [PATCH 2/6] Don't print errors when cancel_transfer fails with
NOT_FOUND
As stated in the documentation for libusb_cancel_transfer,
LIBUSB_ERROR_NOT_FOUND is an expected return value for
libusb_cancel_transfer (under certain circumstances) printing
an error each time this happens therefor is undesirable.
More so because under Linux IOCTL_USBFS_DISCARDURB sets errno
to EINVAL when the kernel could not find the urb in the kernels
urbs in flight list. Which means that the urb has already completed
at the host controller level, but it has not necessarily already
been reaped. IOW under Linux libusb_cancel_transfer may yield a
result of LIBUSB_ERROR_NOT_FOUND *before* the transfer's callback
has been called! So there is no way for an application to avoid
calling libusb_cancel_transfer on already completed transfers.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
libusb/io.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/libusb/io.c b/libusb/io.c
index bb6e275..9f46cf0 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -1351,8 +1351,11 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer)
usbi_mutex_lock(&itransfer->lock);
r = usbi_backend->cancel_transfer(itransfer);
if (r < 0) {
- usbi_err(TRANSFER_CTX(transfer),
- "cancel transfer failed error %d", r);
+ if (r != LIBUSB_ERROR_NOT_FOUND)
+ usbi_err(TRANSFER_CTX(transfer),
+ "cancel transfer failed error %d", r);
+ else
+ usbi_dbg("cancel transfer failed error %d", r);
if (r == LIBUSB_ERROR_NO_DEVICE)
itransfer->flags |= USBI_TRANSFER_DEVICE_DISAPPEARED;
--
1.7.9.3

View file

@ -0,0 +1,92 @@
From 3b6ed16cd2f098dd3920853d20940b3560c20ece Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 24 Feb 2012 10:24:00 +0100
Subject: [PATCH 3/6] linux: Fix handling of urb status codes
During testing of my usbredir code I hit a case where EOVERFLOW was not handled
in handle_control_completion. Instead of just fixing this one case I've audited
(and fixed where necessary) all handle_foo_completion functions to know about
all errors documented in linux/Documentation/usb/error-codes.txt.
Note that for handle_iso_completion this patch actually removes the handling
of some codes, since these can never occur on an iso urb (they can only
occur on the iso packets included in the urb, see the next patch in this
series). Also in case an unknown status is encountered on an iso urb, this
patch actually sets the urb's status to ERROR, rather then leaving it at
completed.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
libusb/os/linux_usbfs.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 099fc61..36d37a4 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -1952,6 +1952,7 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer,
case -ENOENT: /* cancelled */
case -ECONNRESET:
break;
+ case -ENODEV:
case -ESHUTDOWN:
usbi_dbg("device removed");
tpriv->reap_status = LIBUSB_TRANSFER_NO_DEVICE;
@@ -1970,6 +1971,8 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer,
case -ETIME:
case -EPROTO:
case -EILSEQ:
+ case -ECOMM:
+ case -ENOSR:
usbi_dbg("low level error %d", urb->status);
tpriv->reap_action = ERROR;
goto cancel_remaining;
@@ -2081,19 +2084,16 @@ static int handle_iso_completion(struct usbi_transfer *itransfer,
case 0:
break;
case -ENOENT: /* cancelled */
+ case -ECONNRESET:
break;
case -ESHUTDOWN:
usbi_dbg("device removed");
status = LIBUSB_TRANSFER_NO_DEVICE;
break;
- case -ETIME:
- case -EPROTO:
- case -EILSEQ:
- usbi_dbg("low-level USB error %d", urb->status);
- break;
default:
usbi_warn(TRANSFER_CTX(transfer),
"unrecognised urb status %d", urb->status);
+ status = LIBUSB_TRANSFER_ERROR;
break;
}
@@ -2139,6 +2139,7 @@ static int handle_control_completion(struct usbi_transfer *itransfer,
case -ENOENT: /* cancelled */
status = LIBUSB_TRANSFER_CANCELLED;
break;
+ case -ENODEV:
case -ESHUTDOWN:
usbi_dbg("device removed");
status = LIBUSB_TRANSFER_NO_DEVICE;
@@ -2147,9 +2148,15 @@ static int handle_control_completion(struct usbi_transfer *itransfer,
usbi_dbg("unsupported control request");
status = LIBUSB_TRANSFER_STALL;
break;
+ case -EOVERFLOW:
+ usbi_dbg("control overflow error");
+ status = LIBUSB_TRANSFER_OVERFLOW;
+ break;
case -ETIME:
case -EPROTO:
case -EILSEQ:
+ case -ECOMM:
+ case -ENOSR:
usbi_dbg("low-level bus error occurred");
status = LIBUSB_TRANSFER_ERROR;
break;
--
1.7.9.3

View file

@ -0,0 +1,68 @@
From 4c3e7f9818c0d1d0462fde6f219da65fb102a434 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 24 Feb 2012 11:15:30 +0100
Subject: [PATCH 4/6] linux: Translate linux iso pkt status codes to libusb
transfer status codes
During testing of my usbredir code I hit a scenario where my libusb app
was seeing EXDEV as status in the transfer's iso_packet_desc
This happened because we don't translate linux negative errno errors
stored in iso pkts status to libusb transfer status codes at all! So this
patch adds translation for this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
libusb/os/linux_usbfs.c | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 36d37a4..a7d8298 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -2053,7 +2053,41 @@ static int handle_iso_completion(struct usbi_transfer *itransfer,
struct usbfs_iso_packet_desc *urb_desc = &urb->iso_frame_desc[i];
struct libusb_iso_packet_descriptor *lib_desc =
&transfer->iso_packet_desc[tpriv->iso_packet_offset++];
- lib_desc->status = urb_desc->status;
+ lib_desc->status = LIBUSB_TRANSFER_COMPLETED;
+ switch (urb_desc->status) {
+ case 0:
+ break;
+ case -ENOENT: /* cancelled */
+ case -ECONNRESET:
+ break;
+ case -ENODEV:
+ case -ESHUTDOWN:
+ usbi_dbg("device removed");
+ lib_desc->status = LIBUSB_TRANSFER_NO_DEVICE;
+ break;
+ case -EPIPE:
+ usbi_dbg("detected endpoint stall");
+ lib_desc->status = LIBUSB_TRANSFER_STALL;
+ break;
+ case -EOVERFLOW:
+ usbi_dbg("overflow error");
+ lib_desc->status = LIBUSB_TRANSFER_OVERFLOW;
+ break;
+ case -ETIME:
+ case -EPROTO:
+ case -EILSEQ:
+ case -ECOMM:
+ case -ENOSR:
+ case -EXDEV:
+ usbi_dbg("low-level USB error %d", urb_desc->status);
+ lib_desc->status = LIBUSB_TRANSFER_ERROR;
+ break;
+ default:
+ usbi_warn(TRANSFER_CTX(transfer),
+ "unrecognised urb status %d", urb_desc->status);
+ lib_desc->status = LIBUSB_TRANSFER_ERROR;
+ break;
+ }
lib_desc->actual_length = urb_desc->actual_length;
}
--
1.7.9.3

View file

@ -0,0 +1,117 @@
From 1fabeefda0fb31aa36203aa8b3f07debdc83d22a Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 28 Jun 2012 16:40:52 +0200
Subject: [PATCH 1/6] linux_usbfs: Add support for the new get_capabilities
ioctl
There were a few (new) usbdevfs capabilities which libusbx could not
discover in any other way then checking the kernel version. There are 3
problems with this:
1) It is just not very pretty
2) Given the tendency of enterprise distros to backport stuff it is not
reliable
3) Some of these features turn out to not work with certain host controllers,
making depending on them based on the kernel version not a good idea
Therefor a new USBDEVFS_GET_CAPABILITIES ioctl has been added to the kernel
to offer a better way to find out a device's capabilities (technically
the capabilities of the host controller to which the device is attached,
but that does not matter).
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
libusb/os/linux_usbfs.c | 24 ++++++++++++++++++++----
libusb/os/linux_usbfs.h | 10 ++++++++++
2 files changed, 30 insertions(+), 4 deletions(-)
diff -up libusb-1.0.8/libusb/os/linux_usbfs.c.caps libusb-1.0.8/libusb/os/linux_usbfs.c
--- libusb-1.0.8/libusb/os/linux_usbfs.c.caps 2012-08-22 15:32:34.677822979 +0200
+++ libusb-1.0.8/libusb/os/linux_usbfs.c 2012-08-22 15:39:27.526002251 +0200
@@ -107,6 +107,7 @@ struct linux_device_priv {
struct linux_device_handle_priv {
int fd;
+ __u32 caps;
};
enum reap_action {
@@ -1139,6 +1140,7 @@ static int op_open(struct libusb_device_
{
struct linux_device_handle_priv *hpriv = __device_handle_priv(handle);
char filename[PATH_MAX];
+ int r;
__get_usbfs_path(handle->dev, filename);
usbi_dbg("opening %s", filename);
@@ -1161,6 +1163,18 @@ static int op_open(struct libusb_device_
}
}
+ r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
+ if (r < 0) {
+ if (errno == ENOTTY)
+ usbi_dbg("%s: getcap not available", filename);
+ else
+ usbi_err(HANDLE_CTX(handle),
+ "%s: getcap failed (%d)", filename, errno);
+ hpriv->caps = 0;
+ if (supports_flag_bulk_continuation)
+ hpriv->caps |= USBFS_CAP_BULK_CONTINUATION;
+ }
+
return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT);
}
@@ -1544,7 +1558,7 @@ static int submit_bulk_transfer(struct u
urb->type = urb_type;
urb->endpoint = transfer->endpoint;
urb->buffer = transfer->buffer + (i * MAX_BULK_BUFFER_LENGTH);
- if (supports_flag_bulk_continuation && !is_out)
+ if ((dpriv->caps & USBFS_CAP_BULK_CONTINUATION) && !is_out)
urb->flags = USBFS_URB_SHORT_NOT_OK;
if (i == num_urbs - 1 && last_urb_partial)
urb->buffer_length = transfer->length % MAX_BULK_BUFFER_LENGTH;
@@ -1553,7 +1567,7 @@ static int submit_bulk_transfer(struct u
else
urb->buffer_length = MAX_BULK_BUFFER_LENGTH;
- if (i > 0 && supports_flag_bulk_continuation)
+ if (i > 0 && (dpriv->caps & USBFS_CAP_BULK_CONTINUATION))
urb->flags |= USBFS_URB_BULK_CONTINUATION;
r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb);
diff -up libusb-1.0.8/libusb/os/linux_usbfs.h.caps libusb-1.0.8/libusb/os/linux_usbfs.h
--- libusb-1.0.8/libusb/os/linux_usbfs.h.caps 2011-02-07 11:53:41.000000000 +0100
+++ libusb-1.0.8/libusb/os/linux_usbfs.h 2012-08-22 15:33:21.224843100 +0200
@@ -21,6 +21,8 @@
#ifndef __LIBUSB_USBFS_H__
#define __LIBUSB_USBFS_H__
+#include <linux/types.h>
+
#define SYSFS_DEVICE_PATH "/sys/bus/usb/devices"
struct usbfs_ctrltransfer {
@@ -115,6 +117,11 @@ struct usbfs_hub_portinfo {
unsigned char port[127]; /* port to device num mapping */
};
+#define USBFS_CAP_ZERO_PACKET 0x01
+#define USBFS_CAP_BULK_CONTINUATION 0x02
+#define USBFS_CAP_NO_PACKET_SIZE_LIM 0x04
+#define USBFS_CAP_BULK_SCATTER_GATHER 0x08
+
#define IOCTL_USBFS_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer)
#define IOCTL_USBFS_BULK _IOWR('U', 2, struct usbfs_bulktransfer)
#define IOCTL_USBFS_RESETEP _IOR('U', 3, unsigned int)
@@ -134,5 +141,8 @@ struct usbfs_hub_portinfo {
#define IOCTL_USBFS_CLEAR_HALT _IOR('U', 21, unsigned int)
#define IOCTL_USBFS_DISCONNECT _IO('U', 22)
#define IOCTL_USBFS_CONNECT _IO('U', 23)
+#define IOCTL_USBFS_CLAIM_PORT _IOR('U', 24, unsigned int)
+#define IOCTL_USBFS_RELEASE_PORT _IOR('U', 25, unsigned int)
+#define IOCTL_USBFS_GET_CAPABILITIES _IOR('U', 26, __u32)
#endif
--
1.7.11.4

View file

@ -0,0 +1,141 @@
From 9b1b7e0acd9f41e6df213e9eeb744e970bdc1544 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 29 Jun 2012 12:16:11 +0200
Subject: [PATCH 2/6] linux_usbfs: Avoid unnecessary splitting of bulk
transfers (v2)
With the latest kernels it is no longer needed to always split large bulk
transfers into multiple urbs. This patch takes advantage of this by not
splitting when not necessary. Note that the non-split code path is in essence
using the old split code path with an urb count which is always 1.
This leads to more sane handling of large transfers with recent kernels,
although our splitting code is well tested, not splitting at all still is
a lot better :)
When used with a recent kernel, this also fixes the problems, on XHCI attached
devices, when a large bulk-in transfer ends with a short read in an urb other
then the last urb. For details on this see the mailinglist thread titled
"usbdevfs: BULK_CONTINUATION flag does not work with XHCI controller".
Changes in v2:
-avoid a divide by 0 on 0 size packets
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
libusb/os/linux_usbfs.c | 69 ++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 57 insertions(+), 12 deletions(-)
diff -up libusb-1.0.8/libusb/os/linux_usbfs.c.bulk libusb-1.0.8/libusb/os/linux_usbfs.c
--- libusb-1.0.8/libusb/os/linux_usbfs.c.bulk 2012-08-22 15:40:51.814038955 +0200
+++ libusb-1.0.8/libusb/os/linux_usbfs.c 2012-08-22 15:43:26.788106690 +0200
@@ -1519,6 +1519,7 @@ static int submit_bulk_transfer(struct u
struct usbfs_urb *urbs;
int is_out = (transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK)
== LIBUSB_ENDPOINT_OUT;
+ int bulk_buffer_len, use_bulk_continuation;
int r;
int i;
size_t alloc_size;
@@ -1526,16 +1527,54 @@ static int submit_bulk_transfer(struct u
if (tpriv->urbs)
return LIBUSB_ERROR_BUSY;
- /* usbfs places a 16kb limit on bulk URBs. we divide up larger requests
- * into smaller units to meet such restriction, then fire off all the
- * units at once. it would be simpler if we just fired one unit at a time,
- * but there is a big performance gain through doing it this way. */
- int num_urbs = transfer->length / MAX_BULK_BUFFER_LENGTH;
+ /*
+ * Older versions of usbfs place a 16kb limit on bulk URBs. We work
+ * around this by splitting large transfers into 16k blocks, and then
+ * submit all urbs at once. it would be simpler to submit one urb at
+ * a time, but there is a big performance gain doing it this way.
+ *
+ * Newer versions lift the 16k limit (USBFS_CAP_NO_PACKET_SIZE_LIM),
+ * using arbritary large transfers can still be a bad idea though, as
+ * the kernel needs to allocate physical contiguous memory for this,
+ * which may fail for large buffers.
+ *
+ * The kernel solves this problem by splitting the transfer into
+ * blocks itself when the host-controller is scatter-gather capable
+ * (USBFS_CAP_BULK_SCATTER_GATHER), which most controllers are.
+ *
+ * Last, there is the issue of short-transfers when splitting, for
+ * short split-transfers to work reliable USBFS_CAP_BULK_CONTINUATION
+ * is needed, but this is not always available.
+ */
+ if (dpriv->caps & USBFS_CAP_BULK_SCATTER_GATHER) {
+ /* Good! Just submit everything in one go */
+ bulk_buffer_len = transfer->length ? transfer->length : 1;
+ use_bulk_continuation = 0;
+ } else if (dpriv->caps & USBFS_CAP_BULK_CONTINUATION) {
+ /* Split the transfers and use bulk-continuation to
+ avoid issues with short-transfers */
+ bulk_buffer_len = MAX_BULK_BUFFER_LENGTH;
+ use_bulk_continuation = 1;
+ } else if (dpriv->caps & USBFS_CAP_NO_PACKET_SIZE_LIM) {
+ /* Don't split, assume the kernel can alloc the buffer
+ (otherwise the submit will fail with -ENOMEM) */
+ bulk_buffer_len = transfer->length ? transfer->length : 1;
+ use_bulk_continuation = 0;
+ } else {
+ /* Bad, splitting without bulk-continuation, short transfers
+ which end before the last urb will not work reliable! */
+ /* Note we don't warn here as this is "normal" on kernels <
+ 2.6.32 and not a problem for most applications */
+ bulk_buffer_len = MAX_BULK_BUFFER_LENGTH;
+ use_bulk_continuation = 0;
+ }
+
+ int num_urbs = transfer->length / bulk_buffer_len;
int last_urb_partial = 0;
if (transfer->length == 0) {
num_urbs = 1;
- } else if ((transfer->length % MAX_BULK_BUFFER_LENGTH) > 0) {
+ } else if ((transfer->length % bulk_buffer_len) > 0) {
last_urb_partial = 1;
num_urbs++;
}
@@ -1557,17 +1596,17 @@ static int submit_bulk_transfer(struct u
urb->usercontext = itransfer;
urb->type = urb_type;
urb->endpoint = transfer->endpoint;
- urb->buffer = transfer->buffer + (i * MAX_BULK_BUFFER_LENGTH);
- if ((dpriv->caps & USBFS_CAP_BULK_CONTINUATION) && !is_out)
+ urb->buffer = transfer->buffer + (i * bulk_buffer_len);
+ if (use_bulk_continuation && !is_out)
urb->flags = USBFS_URB_SHORT_NOT_OK;
if (i == num_urbs - 1 && last_urb_partial)
- urb->buffer_length = transfer->length % MAX_BULK_BUFFER_LENGTH;
+ urb->buffer_length = transfer->length % bulk_buffer_len;
else if (transfer->length == 0)
urb->buffer_length = 0;
else
- urb->buffer_length = MAX_BULK_BUFFER_LENGTH;
+ urb->buffer_length = bulk_buffer_len;
- if (i > 0 && (dpriv->caps & USBFS_CAP_BULK_CONTINUATION))
+ if (i > 0 && use_bulk_continuation)
urb->flags |= USBFS_URB_BULK_CONTINUATION;
r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb);
@@ -1649,7 +1688,13 @@ static int submit_iso_transfer(struct us
/* usbfs places a 32kb limit on iso URBs. we divide up larger requests
* into smaller units to meet such restriction, then fire off all the
* units at once. it would be simpler if we just fired one unit at a time,
- * but there is a big performance gain through doing it this way. */
+ * but there is a big performance gain through doing it this way.
+ *
+ * Newer kernels lift the 32k limit (USBFS_CAP_NO_PACKET_SIZE_LIM),
+ * using arbritary large transfers is still be a bad idea though, as
+ * the kernel needs to allocate physical contiguous memory for this,
+ * which may fail for large buffers.
+ */
/* calculate how many URBs we need */
for (i = 0; i < num_packets; i++) {
--
1.7.11.4

View file

@ -0,0 +1,65 @@
From daa923ac06cbf5bcac6922a9520aa7fc9919134e Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 28 Jul 2012 11:43:52 +0200
Subject: [PATCH 3/6] detach-kernel-driver: return ERROR_NOT_FOUND if usbfs is
already bound (v3)
Currently applications for devices which only are accessed from userspace
can use claim / release interface to make sure they don't get in each others
way. The same however does not work for applications which first need to detach
a "native" / in kernel driver, as this detach will not only detach native
drivers but also the usbfs driver, thus stealing the device from another
userspace / libusbx app.
This patch fixes libusb_detach_kernel_driver to only detach "real" kernel
drivers and not the special usbfs driver used for userspace access to
USB devices. If the usbfs driver is found LIBUSB_ERROR_NOT_FOUND will be
returned to indicate no driver was detached.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
libusb/core.c | 4 ++++
libusb/os/linux_usbfs.c | 6 ++++++
2 files changed, 10 insertions(+)
diff --git a/libusb/core.c b/libusb/core.c
index 7c2f4d7..4c513f7 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -1513,6 +1513,10 @@ int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev,
*
* This functionality is not available on Darwin or Windows.
*
+ * Note that libusb itself also talks to the device through a special kernel
+ * driver, if this driver is already attached to the device, this call will
+ * not detach it and return LIBUSB_ERROR_NOT_FOUND.
+ *
* \param dev a device handle
* \param interface_number the interface to detach the driver from
* \returns 0 on success
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 839ebde..1407866 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -1538,12 +1538,18 @@ static int op_detach_kernel_driver(struct libusb_device_handle *handle,
{
int fd = __device_handle_priv(handle)->fd;
struct usbfs_ioctl command;
+ struct usbfs_getdriver getdrv;
int r;
command.ifno = interface;
command.ioctl_code = IOCTL_USBFS_DISCONNECT;
command.data = NULL;
+ getdrv.interface = interface;
+ r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv);
+ if (r == 0 && strcmp(getdrv.driver, "usbfs") == 0)
+ return LIBUSB_ERROR_NOT_FOUND;
+
r = ioctl(fd, IOCTL_USBFS_IOCTL, &command);
if (r) {
if (errno == ENODATA)
--
1.7.11.4

View file

@ -0,0 +1,86 @@
From 78a150bfbbd84eb524e878bf05101c1ad2eac0b8 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 6 Jul 2012 14:35:53 +0200
Subject: [PATCH 3/3] linux_usbfs: Work around a driver binding race in reset
handling
I've been seeing these intermittent failures to reclaim an interface after
a device reset. After much debugging and inserting sleeps in strategic
places to make the race window larger I've found the following race:
1) A user is running some software using libusb which will automatically
detect, and "bind" to, any newly plugged in USB-devices. For example
a virtual machine viewer with automatic USB-redirection
2) The user plugs in a new usb-storage device
3) The usb-storage driver is not yet loaded, udev spawns
"modprobe usb-storage", this blocks on disk-io
4) The libusb app opens the device, claims all interfaces, does a device-reset
5) While the IOCTL_USBFS_RESET is running the modprobe completes
6) The driver registration blocks on an USB lock held by the reset code path
7) When the reset finishes the driver registration completes and the driver
binds itself to the device, before IOCTL_USBFS_RESET returns to userspace
8) libusb tries to re-claim all interfaces it had claimed before the reset
9) libusb fails as usb-storage is now bound to it
This patch works around this issue by simply unbinding the driver for all
interfaces which were claimed before the reset. Normally this is a no-op as
no driver (other then usbfs) can be bound for claimed interfaces before the
reset.
But as the above example shows, the exception is a driver completing
registration, and as part of this binding to any elegible devices, between
IOCTL_USBFS_RESET and our re-claiming of the interface. The largest part
of the race window here is the time IOCTL_USBFS_RESET takes, as that does a
fair amount of IO with the device. This part of the race window is
worked around by this patch.
This still leaves a theoretical race window where the driver registration
finishes between our driver-unbind and interface-reclaim, I'm afraid there
is nothing we can against this.
This patch also improves the error logging, and makes libusb_device_reset
properly return an error when re-claiming fails.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
libusb/os/linux_usbfs.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 3894554..10d138a 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -108,6 +108,9 @@ static int sysfs_can_relate_devices = 0;
/* do we have a descriptors file? */
static int sysfs_has_descriptors = 0;
+static int op_detach_kernel_driver(struct libusb_device_handle *handle,
+ int interface);
+
struct linux_device_priv {
char *sysfs_dir;
unsigned char *dev_descriptor;
@@ -1497,11 +1500,20 @@ static int op_reset_device(struct libusb_device_handle *handle)
/* And re-claim any interfaces which were claimed before the reset */
for (i = 0; i < USB_MAXINTERFACES; i++) {
if (handle->claimed_interfaces & (1L << i)) {
+ /*
+ * A driver may have completed modprobing during
+ * IOCTL_USBFS_RESET, and bound itself as soon as
+ * IOCTL_USBFS_RESET released the device lock
+ */
+ op_detach_kernel_driver(handle, i);
+
r = op_claim_interface(handle, i);
if (r) {
usbi_warn(HANDLE_CTX(handle),
- "failed to re-claim interface %d after reset", i);
+ "failed to re-claim interface %d after reset: %s",
+ i, libusb_error_name(r));
handle->claimed_interfaces &= ~(1L << i);
+ ret = LIBUSB_ERROR_NOT_FOUND;
}
}
}
--
1.7.11.2

View file

@ -1,21 +0,0 @@
# Makefile for source rpm: libusb1
# $Id$
NAME := libusb1
SPECFILE = $(firstword $(wildcard *.spec))
define find-makefile-common
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
endef
MAKEFILE_COMMON := $(shell $(find-makefile-common))
ifeq ($(MAKEFILE_COMMON),)
# attept a checkout
define checkout-makefile-common
test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2
endef
MAKEFILE_COMMON := $(shell $(checkout-makefile-common))
endif
include $(MAKEFILE_COMMON)

161
libusb1.spec Normal file
View file

@ -0,0 +1,161 @@
Summary: A library which allows userspace access to USB devices
Name: libusb1
Version: 1.0.9
Release: 0.6.rc1%{?dist}
Source0: libusb-1.0.9-rc1.tar.bz2
#Source0: http://downloads.sourceforge.net/libusb/libusb-%{version}.tar.bz2
Patch1: 0001-Correctly-handle-LIBUSB_TRANSFER_OVERFLOW-in-libusb_.patch
Patch2: 0002-linux-Fix-cancel_transfer-return-value-when-cancelli.patch
Patch3: 0003-Don-t-print-errors-when-cancel_transfer-fails-with-N.patch
Patch4: 0004-linux-Fix-handling-of-urb-status-codes.patch
Patch5: 0005-linux-Translate-linux-iso-pkt-status-codes-to-libusb.patch
# For rhbz#830751
Patch6: 0006-linux_usbfs-Add-support-for-the-new-get_capabilities.patch
Patch7: 0007-linux_usbfs-Avoid-unnecessary-splitting-of-bulk-tran.patch
# For rhbz#820205
Patch8: 0008-detach-kernel-driver-return-ERROR_NOT_FOUND-if-usbfs.patch
Patch9: 0009-linux_usbfs-Work-around-a-driver-binding-race-in-res.patch
License: LGPLv2+
Group: System Environment/Libraries
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
URL: http://libusb.wiki.sourceforge.net/Libusb1.0
ExcludeArch: s390 s390x
BuildRequires: doxygen
%description
This package provides a way for applications to access USB devices. Note that
this library is not compatible with the original libusb-0.1 series.
%package devel
Summary: Development files for libusb
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
Requires: pkgconfig
%description devel
This package contains the header files, libraries and documentation needed to
develop applications that use libusb1.
%package static
Summary: Static development files for libusb
Group: Development/Libraries
Requires: %{name}-devel = %{version}-%{release}
%description static
This package contains static libraries to develop applications that use libusb1.
%prep
%setup -q -n libusb-1.0.8
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%build
%configure
make CFLAGS="$RPM_OPT_FLAGS"
pushd doc
make docs
popd
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
# Our snapshot reports itself as 1.0.8, change the pkg-config file version to
# 1.0.9 so that configure checks by apps who need the new 1.0.9 succeed
sed -i 's/1\.0\.8/1.0.9/' %{buildroot}/%{_libdir}/pkgconfig/libusb-1.0.pc
%clean
rm -rf $RPM_BUILD_ROOT
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%defattr(-,root,root)
%doc AUTHORS COPYING README NEWS ChangeLog
%{_libdir}/*.so.*
%files devel
%defattr(-,root,root)
%doc doc/html examples/*.c
%{_libdir}/pkgconfig/libusb-1.0.pc
%{_includedir}/*
%{_libdir}/*.so
%files static
%defattr(-,root,root)
%{_libdir}/*.a
%changelog
* Wed Aug 22 2012 Hans de Goede <hdegoede@redhat.com> - 1.0.9-0.6.rc1
- Don't split bulk transfers unnecessary
- Resolves: rhbz#830751
- Don't let disconnect_kernel_driver detach the usbfs driver
- Resolves: rhbz#820205
* Wed Mar 14 2012 Hans de Goede <hdegoede@redhat.com> - 1.0.9-0.5.rc1
- Add some small error handling fixes
- Related: rhbz#758094
* Tue Jan 17 2012 Hans de Goede <hdegoede@redhat.com> - 1.0.9-0.4.rc1
- Fix previous changelog entry to refer to the right bug
- Related: rhbz#758094
* Wed Jan 11 2012 Marc-Andre Lureau <marcandre.lureau@redhat.com> 1.0.9-0.3.rc1
- update to 1.0.9rc1, sync with f16
- Resolves: rhbz#758094
* Mon Sep 28 2009 Jindrich Novy <jnovy@redhat.com> 1.0.3-1
- update to 1.0.3
* Sat Jul 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
* Mon Jun 15 2009 Jindrich Novy <jnovy@redhat.com> 1.0.2-1
- update to 1.0.2
* Wed May 13 2009 Jindrich Novy <jnovy@redhat.com> 1.0.1-1
- update to 1.0.1
* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
* Mon Dec 15 2008 - Bastien Nocera <bnocera@redhat.com> - 1.0.0-1
- Update to 1.0.0
* Fri Nov 21 2008 - Bastien Nocera <bnocera@redhat.com> - 0.9.4-1
- Update to 0.9.4
* Tue Sep 23 2008 Jindrich Novy <jnovy@redhat.com> 0.9.3-0.1
- update to 0.9.3
* Sun Jul 06 2008 - Bastien Nocera <bnocera@redhat.com> - 0.9.1
- Update to 0.9.1
* Mon May 26 2008 Jindrich Novy <jnovy@redhat.com> 0.9.0-0.4
- update to official beta
* Thu May 23 2008 Jindrich Novy <jnovy@redhat.com> 0.9.0-0.3.gitbef33bb
- update comment on how the tarball was created
- use abbreviated git hash within package name to avoid conflicts
- add to %%description that libusb1 is incompatible with libsub-0.1
* Thu May 22 2008 Jindrich Novy <jnovy@redhat.com> 0.9.0-0.2.gitbef33bb
- add info on how the snapshot tarball was created
* Wed May 21 2008 Jindrich Novy <jnovy@redhat.com> 0.9.0-0.1.gitbef33bb
- use proper version to denote it is a git snapshot
* Thu May 15 2008 Jindrich Novy <jnovy@redhat.com> 0.9.0-0.1
- initial packaging

View file

@ -0,0 +1 @@
389dd12f7da1411aac2524c5de35e2f5 libusb-1.0.9-rc1.tar.bz2