Create a usb_bulk_transfer wrapper for libusb_bulk_transfer to cope with pipe errors.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
diff --git a/usbutils.c b/usbutils.c
index 3806276..e57b632 100644
--- a/usbutils.c
+++ b/usbutils.c
@@ -2163,6 +2163,30 @@ static char *find_end(unsigned char *buf, unsigned char *ptr, int ptrlen, int to
}
#define USB_MAX_READ 8192
+#define USB_RETRY_MAX 5
+
+static int
+usb_bulk_transfer(struct libusb_device_handle *dev_handle,
+ unsigned char endpoint, unsigned char *data, int length,
+ int *transferred, unsigned int timeout)
+{
+ int err, tries = 0;
+
+ err = libusb_bulk_transfer(dev_handle, endpoint, data, length,
+ transferred, timeout);
+ if (unlikely(err == LIBUSB_ERROR_PIPE)) {
+ do {
+ err = libusb_clear_halt(dev_handle, endpoint);
+ if (unlikely(err == LIBUSB_ERROR_NOT_FOUND ||
+ err == LIBUSB_ERROR_NO_DEVICE))
+ break;
+ err = libusb_bulk_transfer(dev_handle, endpoint, data,
+ length, transferred, timeout);
+ } while (err == LIBUSB_ERROR_PIPE && tries++ < USB_RETRY_MAX);
+ }
+
+ return err;
+}
int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, const char *end, __maybe_unused enum usb_cmds cmd, bool readonce)
{
@@ -2235,9 +2259,9 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
got = 0;
STATS_TIMEVAL(&tv_start);
- err = libusb_bulk_transfer(usbdev->handle,
- usbdev->found->eps[ep].ep,
- ptr, usbbufread, &got, timeout);
+ err = usb_bulk_transfer(usbdev->handle,
+ usbdev->found->eps[ep].ep,
+ ptr, usbbufread, &got, timeout);
cgtime(&tv_finish);
USB_STATS(cgpu, &tv_start, &tv_finish, err,
MODE_BULK_READ, cmd, first ? SEQ0 : SEQ1);
@@ -2325,9 +2349,9 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
}
got = 0;
STATS_TIMEVAL(&tv_start);
- err = libusb_bulk_transfer(usbdev->handle,
- usbdev->found->eps[ep].ep,
- ptr, usbbufread, &got, timeout);
+ err = usb_bulk_transfer(usbdev->handle,
+ usbdev->found->eps[ep].ep, ptr,
+ usbbufread, &got, timeout);
cgtime(&tv_finish);
USB_STATS(cgpu, &tv_start, &tv_finish, err,
MODE_BULK_READ, cmd, first ? SEQ0 : SEQ1);
@@ -2452,10 +2476,10 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
while (bufsiz > 0) {
sent = 0;
STATS_TIMEVAL(&tv_start);
- err = libusb_bulk_transfer(usbdev->handle,
- usbdev->found->eps[ep].ep,
- (unsigned char *)buf,
- bufsiz, &sent, timeout);
+ err = usb_bulk_transfer(usbdev->handle,
+ usbdev->found->eps[ep].ep,
+ (unsigned char *)buf, bufsiz, &sent,
+ timeout);
cgtime(&tv_finish);
USB_STATS(cgpu, &tv_start, &tv_finish, err,
MODE_BULK_WRITE, cmd, first ? SEQ0 : SEQ1);