Browse Source

Treat any unexpected timeouts waiting for async transfers as though there may be a usb halt condition and attempt to clear the halt before cancelling the tranfer.

nfactor-troky
Con Kolivas 11 years ago
parent
commit
603bba67b9
  1. 16
      usbutils.c

16
usbutils.c

@ -2228,6 +2228,7 @@ static void LIBUSB_CALL bulk_callback(struct libusb_transfer *transfer) @@ -2228,6 +2228,7 @@ static void LIBUSB_CALL bulk_callback(struct libusb_transfer *transfer)
* use our own timer to cancel the request if we go beyond the timeout. */
static int callback_wait(struct usb_transfer *ut, int *transferred, unsigned int timeout)
{
struct libusb_transfer *transfer= ut->transfer;
struct timespec ts_now, ts_end;
struct timeval tv_now;
int ret;
@ -2239,15 +2240,22 @@ static int callback_wait(struct usb_transfer *ut, int *transferred, unsigned int @@ -2239,15 +2240,22 @@ static int callback_wait(struct usb_transfer *ut, int *transferred, unsigned int
timeraddspec(&ts_end, &ts_now);
ret = pthread_cond_timedwait(&ut->cond, &ut->mutex, &ts_end);
if (ret) {
libusb_cancel_transfer(ut->transfer);
/* Assume that if we timed out on the conditional then the
* transfer has stalled for some reason and attempt to clear
* a halt as a solution. Then cancel the transaction, treating
* it the same as a timeout. */
libusb_clear_halt(transfer->dev_handle, transfer->endpoint);
libusb_cancel_transfer(transfer);
/* Now wait for the callback function to be invoked. */
pthread_cond_wait(&ut->cond, &ut->mutex);
/* Fake the timed out message since it's effectively that */
ret = LIBUSB_TRANSFER_TIMED_OUT;
} else
ret = ut->transfer->status;
ret = transfer->status;
/* No need to sort out mutexes here since they won't be reused */
*transferred = ut->transfer->actual_length;
libusb_free_transfer(ut->transfer);
*transferred = transfer->actual_length;
libusb_free_transfer(transfer);
return ret;
}

Loading…
Cancel
Save