From: Chris Dickens Date: Thu, 22 Jan 2015 08:25:16 +0000 (-0800) Subject: linux_usbfs: Update MAX_ISO_BUFFER_LENGTH X-Git-Tag: upstream/1.0.21~203 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=51b10191033ca3a3819dcf46e1da2465b99497c2;p=platform%2Fupstream%2Flibusb.git linux_usbfs: Update MAX_ISO_BUFFER_LENGTH Newer kernels have raised the maximum length of individual ISO packets and URBs. There's no easy way to detect the limit, so we will define MAX_ISO_BUFFER_LENGTH as the largest known limit. If a user runs this on an earlier kernel and submits an ISO transfer that is too large, they will receive LIBUSB_ERROR_INVALID_PARAM. The documentation has been updated to note this behavior, under "Considerations for isochronous transfers". Closes #23 Signed-off-by: Chris Dickens --- diff --git a/libusb/io.c b/libusb/io.c index 9614086..d8a2bd6 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -466,6 +466,14 @@ if (r == 0 && actual_length == sizeof(data)) { * libusb_get_iso_packet_buffer() and libusb_get_iso_packet_buffer_simple() * functions may help you here. * + * Note: Some operating systems (e.g. Linux) may impose limits on the + * length of individual isochronous packets and/or the total length of the + * isochronous transfer. Such limits can be difficult for libusb to detect, + * so the library will simply try and submit the transfer as set up by you. + * If the transfer fails to submit because it is too large, + * libusb_submit_transfer() will return + * \ref libusb_error::LIBUSB_ERROR_INVALID_PARAM "LIBUSB_ERROR_INVALID_PARAM". + * * \section asyncmem Memory caveats * * In most circumstances, it is not safe to use stack memory for transfer diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 05cf909..101cc95 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -1942,15 +1942,11 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) unsigned int packet_len; unsigned char *urb_buffer = transfer->buffer; - /* 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. - * - * 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. + /* usbfs places arbitrary limits on iso URBs. this limit has changed + * at least three times, and it's difficult to accurately detect which + * limit this running kernel might impose. so we attempt to submit + * whatever the user has provided. if the kernel rejects the request + * due to its size, we return an error indicating such to the user. */ /* calculate how many URBs we need */ @@ -1961,11 +1957,14 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) if (packet_len > space_remaining) { num_urbs++; this_urb_len = packet_len; + /* check that we can actually support this packet length */ + if (this_urb_len > MAX_ISO_BUFFER_LENGTH) + return LIBUSB_ERROR_INVALID_PARAM; } else { this_urb_len += packet_len; } } - usbi_dbg("need %d 32k URBs for transfer", num_urbs); + usbi_dbg("need %d %dk URBs for transfer", num_urbs, MAX_ISO_BUFFER_LENGTH / 1024); alloc_size = num_urbs * sizeof(*urbs); urbs = calloc(1, alloc_size); @@ -2033,6 +2032,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) if (r < 0) { if (errno == ENODEV) { r = LIBUSB_ERROR_NO_DEVICE; + } else if (errno == EINVAL) { + usbi_warn(TRANSFER_CTX(transfer), + "submiturb failed, transfer too large"); + r = LIBUSB_ERROR_INVALID_PARAM; } else { usbi_err(TRANSFER_CTX(transfer), "submiturb failed error %d errno=%d", r, errno); diff --git a/libusb/os/linux_usbfs.h b/libusb/os/linux_usbfs.h index f2404ab..43fe11b 100644 --- a/libusb/os/linux_usbfs.h +++ b/libusb/os/linux_usbfs.h @@ -81,7 +81,7 @@ struct usbfs_iso_packet_desc { unsigned int status; }; -#define MAX_ISO_BUFFER_LENGTH 32768 +#define MAX_ISO_BUFFER_LENGTH 49152 * 128 #define MAX_BULK_BUFFER_LENGTH 16384 #define MAX_CTRL_BUFFER_LENGTH 4096 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 70d5df1..bc6bfe4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10951 +#define LIBUSB_NANO 10952