diff options
author | Peter Stuge <peter@stuge.se> | 2010-06-25 08:08:13 +0200 |
---|---|---|
committer | Pete Batard <pbatard@gmail.com> | 2010-07-29 11:24:35 +0100 |
commit | bfd95f6a632e65b2b5bab0bead2d769ef0e72e6d (patch) | |
tree | f666d04dc8d5ec2dbd6e986de5d071b22cec38a0 | |
parent | db223f0879ce811988f5784f0b21b8f0bafb2992 (diff) | |
download | libusb-bfd95f6a632e65b2b5bab0bead2d769ef0e72e6d.tar.gz |
Linux: Handle early complete of multi-URB transfer
-rw-r--r-- | libusb/os/linux_usbfs.c | 18 |
1 files 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) |