diff options
| -rw-r--r-- | contrib/libusb-Fix-Zero-Length-Packet-issue.patch | 71 | ||||
| -rw-r--r-- | usbmuxd/usb-linux.c | 29 |
2 files changed, 100 insertions, 0 deletions
diff --git a/contrib/libusb-Fix-Zero-Length-Packet-issue.patch b/contrib/libusb-Fix-Zero-Length-Packet-issue.patch new file mode 100644 index 0000000..40fc2dc --- /dev/null +++ b/contrib/libusb-Fix-Zero-Length-Packet-issue.patch | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | >From e6a34fe2fcd69d05411d3a8d41c8e897c9c337e1 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nikias Bassen <nikias@gmx.li> | ||
| 3 | Date: Mon, 17 Aug 2009 00:48:17 +0200 | ||
| 4 | Subject: [PATCH] Fix Zero Length Packet issue, new LIBUSB_TRANSFER_ZERO_PACKET flag. | ||
| 5 | |||
| 6 | This patch fixes the Zero Length Packet issue by allowing the client | ||
| 7 | program to specify the LIBUSB_TRANSFER_ZERO_PACKET flag when calling | ||
| 8 | libusb_submit_transfer. This will pass the URB_ZERO_PACKET flag to the | ||
| 9 | appropriate ioctl and thus triggers zero-length packet processing | ||
| 10 | inside the kernel. This patch will also pass the URB_SHORT_NOT_OK flag | ||
| 11 | if LIBUSB_TRANSFER_SHORT_NOT_OK is specified. | ||
| 12 | --- | ||
| 13 | libusb/libusb.h | 5 ++++- | ||
| 14 | libusb/os/linux_usbfs.c | 5 +++++ | ||
| 15 | libusb/os/linux_usbfs.h | 8 +++++--- | ||
| 16 | 3 files changed, 14 insertions(+), 4 deletions(-) | ||
| 17 | |||
| 18 | diff --git a/libusb/libusb.h b/libusb/libusb.h | ||
| 19 | index 1126380..1dc7ae0 100644 | ||
| 20 | --- a/libusb/libusb.h | ||
| 21 | +++ b/libusb/libusb.h | ||
| 22 | @@ -672,7 +672,10 @@ enum libusb_transfer_flags { | ||
| 23 | * If this flag is set, it is illegal to call libusb_free_transfer() | ||
| 24 | * from your transfer callback, as this will result in a double-free | ||
| 25 | * when this flag is acted upon. */ | ||
| 26 | - LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2 | ||
| 27 | + LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2, | ||
| 28 | + | ||
| 29 | + /** zero-terminate a packet that is N*wMaxPacketSize bytes long */ | ||
| 30 | + LIBUSB_TRANSFER_ZERO_PACKET = 1<<3 | ||
| 31 | }; | ||
| 32 | |||
| 33 | /** \ingroup asyncio | ||
| 34 | diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c | ||
| 35 | index 1280188..81a9498 100644 | ||
| 36 | --- a/libusb/os/linux_usbfs.c | ||
| 37 | +++ b/libusb/os/linux_usbfs.c | ||
| 38 | @@ -1307,6 +1307,11 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer, | ||
| 39 | else | ||
| 40 | urb->buffer_length = MAX_BULK_BUFFER_LENGTH; | ||
| 41 | |||
| 42 | + if (transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) | ||
| 43 | + urb->flags |= USBFS_URB_SHORT_NOT_OK; | ||
| 44 | + if (transfer->flags & LIBUSB_TRANSFER_ZERO_PACKET) | ||
| 45 | + urb->flags |= USBFS_URB_ZERO_PACKET; | ||
| 46 | + | ||
| 47 | r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb); | ||
| 48 | if (r < 0) { | ||
| 49 | int j; | ||
| 50 | diff --git a/libusb/os/linux_usbfs.h b/libusb/os/linux_usbfs.h | ||
| 51 | index fdf5e9b..4660e3b 100644 | ||
| 52 | --- a/libusb/os/linux_usbfs.h | ||
| 53 | +++ b/libusb/os/linux_usbfs.h | ||
| 54 | @@ -60,9 +60,11 @@ struct usbfs_getdriver { | ||
| 55 | char driver[USBFS_MAXDRIVERNAME + 1]; | ||
| 56 | }; | ||
| 57 | |||
| 58 | -#define USBFS_URB_DISABLE_SPD 1 | ||
| 59 | -#define USBFS_URB_ISO_ASAP 2 | ||
| 60 | -#define USBFS_URB_QUEUE_BULK 0x10 | ||
| 61 | +#define USBFS_URB_SHORT_NOT_OK 0x01 | ||
| 62 | +#define USBFS_URB_ISO_ASAP 0x02 | ||
| 63 | +#define USBFS_URB_NO_FSBR 0x20 | ||
| 64 | +#define USBFS_URB_ZERO_PACKET 0x40 | ||
| 65 | +#define USBFS_URB_NO_INTERRUPT 0x80 | ||
| 66 | |||
| 67 | enum usbfs_urb_type { | ||
| 68 | USBFS_URB_TYPE_ISO = 0, | ||
| 69 | -- | ||
| 70 | 1.6.0.4 | ||
| 71 | |||
diff --git a/usbmuxd/usb-linux.c b/usbmuxd/usb-linux.c index fb22d03..2d6053e 100644 --- a/usbmuxd/usb-linux.c +++ b/usbmuxd/usb-linux.c | |||
| @@ -33,6 +33,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| 33 | #include "log.h" | 33 | #include "log.h" |
| 34 | #include "device.h" | 34 | #include "device.h" |
| 35 | 35 | ||
| 36 | #ifndef LIBUSB_TRANSFER_ZERO_PACKET | ||
| 37 | #warning Your libusb is missing proper Zero Length Packet support! | ||
| 38 | #warning | ||
| 39 | #warning If you are using a recent libusb Git, things may or may not work. | ||
| 40 | #warning If you are using libusb 1.0.2 or earlier, things will definitely not work | ||
| 41 | #warning properly. | ||
| 42 | #warning | ||
| 43 | #warning Please apply the patch in the contrib/ directory to your libusb 1.0 tree. | ||
| 44 | #define EXPLICIT_ZLP_TRANSACTION | ||
| 45 | #endif | ||
| 46 | |||
| 36 | // interval for device connection/disconnection polling, in milliseconds | 47 | // interval for device connection/disconnection polling, in milliseconds |
| 37 | // we need this because there is currently no asynchronous device discovery mechanism in libusb | 48 | // we need this because there is currently no asynchronous device discovery mechanism in libusb |
| 38 | #define DEVICE_POLL_TIME 1000 | 49 | #define DEVICE_POLL_TIME 1000 |
| @@ -134,15 +145,33 @@ int usb_send(struct usb_device *dev, const unsigned char *buf, int length) | |||
| 134 | struct libusb_transfer *xfer = libusb_alloc_transfer(0); | 145 | struct libusb_transfer *xfer = libusb_alloc_transfer(0); |
| 135 | libusb_fill_bulk_transfer(xfer, dev->dev, BULK_OUT, (void*)buf, length, tx_callback, dev, 0); | 146 | libusb_fill_bulk_transfer(xfer, dev->dev, BULK_OUT, (void*)buf, length, tx_callback, dev, 0); |
| 136 | xfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK; | 147 | xfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK; |
| 148 | #ifndef EXPLICIT_ZLP_TRANSACTION | ||
| 137 | if (length % dev->wMaxPacketSize == 0) { | 149 | if (length % dev->wMaxPacketSize == 0) { |
| 138 | xfer->flags |= LIBUSB_TRANSFER_ZERO_PACKET; | 150 | xfer->flags |= LIBUSB_TRANSFER_ZERO_PACKET; |
| 139 | } | 151 | } |
| 152 | #endif | ||
| 140 | if((res = libusb_submit_transfer(xfer)) < 0) { | 153 | if((res = libusb_submit_transfer(xfer)) < 0) { |
| 141 | usbmuxd_log(LL_ERROR, "Failed to submit TX transfer %p len %d to device %d-%d: %d", buf, length, dev->bus, dev->address, res); | 154 | usbmuxd_log(LL_ERROR, "Failed to submit TX transfer %p len %d to device %d-%d: %d", buf, length, dev->bus, dev->address, res); |
| 142 | libusb_free_transfer(xfer); | 155 | libusb_free_transfer(xfer); |
| 143 | return res; | 156 | return res; |
| 144 | } | 157 | } |
| 145 | collection_add(&dev->tx_xfers, xfer); | 158 | collection_add(&dev->tx_xfers, xfer); |
| 159 | #ifdef EXPLICIT_ZLP_TRANSACTION | ||
| 160 | if (length % dev->wMaxPacketSize == 0) { | ||
| 161 | usbmuxd_log(LL_DEBUG, "Send ZLP"); | ||
| 162 | // Send Zero Length Packet | ||
| 163 | xfer = libusb_alloc_transfer(0); | ||
| 164 | void *buffer = malloc(1); | ||
| 165 | libusb_fill_bulk_transfer(xfer, dev->dev, BULK_OUT, buffer, 0, tx_callback, dev, 0); | ||
| 166 | xfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK; | ||
| 167 | if((res = libusb_submit_transfer(xfer)) < 0) { | ||
| 168 | usbmuxd_log(LL_ERROR, "Failed to submit TX ZLP transfer to device %d-%d: %d", dev->bus, dev->address, res); | ||
| 169 | libusb_free_transfer(xfer); | ||
| 170 | return res; | ||
| 171 | } | ||
| 172 | collection_add(&dev->tx_xfers, xfer); | ||
| 173 | } | ||
| 174 | #endif | ||
| 146 | return 0; | 175 | return 0; |
| 147 | } | 176 | } |
| 148 | 177 | ||
