From 3b6d9ac82e2599cad7817d21e909a42275ddc4c4 Mon Sep 17 00:00:00 2001 From: Peter Stuge Date: Fri, 25 Jun 2010 08:08:13 +0200 Subject: [PATCH] Linux: Handle early complete of multi-URB transfer --- libusb/os/linux_usbfs.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 67d2a87..d0db7e2 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -1415,7 +1415,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer, } /* if it's not the first URB that failed, the situation is a bit - * tricky. we must discard all previous URBs. there are + * tricky. we may need to discard all previous URBs. there are * complications: * - discarding is asynchronous - discarded urbs will be reaped * later. the user must not have freed the transfer when the @@ -1423,15 +1423,23 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer, * freed memory. * - the earlier URBs may have completed successfully and we do * not want to throw away any data. - * so, in this case we discard all the previous URBs BUT we report - * that the transfer was submitted successfully. then later when - * the final discard completes we can report error to the user. + * - this URB failing may be no error; EREMOTEIO means that + * this transfer simply didn't need all the URBs we submitted + * so, we report that the transfer was submitted successfully and + * in case of error we discard all previous URBs. later when + * the final reap completes we can report error to the user, + * or success if an earlier URB was completed successfully. */ - tpriv->reap_action = SUBMIT_FAILED; + tpriv->reap_action = EREMOTEIO == errno ? COMPLETED_EARLY : SUBMIT_FAILED; /* The URBs we haven't submitted yet we count as already * retired. */ tpriv->num_retired += num_urbs - i; + + /* If we completed short then don't try to discard. */ + if (COMPLETED_EARLY == tpriv->reap_action) + return 0; + for (j = 0; j < i; j++) { int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, &urbs[j]); if (tmp && errno != EINVAL) -- 2.7.4