Fix Windows bug with libusb_reset_device returning SUCCESS for disconnected device Symptoms (new in latest libusb perhaps) on Windows 7, using WinUSB v6.1.7600.16385 kernel driver: - Unplug device during mining - libusb read/write operations return -1 LIBUSB_ERROR_IO - libusb reset returns 0 LIBUSB_SUCCESS ... hence the error checking ends up infinite looping (or until timeout) trying to issue a reset, as it believes each reset has succeeded. This change only allows a reset once per failed read or write operation - if the first reset fails, don't bother trying again. Conflicts: usbutils.c
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
diff --git a/usbutils.c b/usbutils.c
index c305f6c..df724cf 100644
--- a/usbutils.c
+++ b/usbutils.c
@@ -2891,7 +2891,7 @@ int _usb_read(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_t
{
unsigned char *ptr, usbbuf[USB_READ_BUFSIZE];
struct timeval read_start, tv_finish;
- int bufleft, err, got, tot, pstate;
+ int bufleft, err, got, tot, pstate, tried_reset;
struct cg_usb_device *usbdev;
unsigned int initial_timeout;
bool first = true;
@@ -2946,6 +2946,7 @@ int _usb_read(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_t
initial_timeout = timeout;
cgtime(&read_start);
+ tried_reset = 0;
while (bufleft > 0 && !eom) {
err = usb_perform_transfer(cgpu, usbdev, intinfo, epinfo, ptr, usbbufread,
&got, timeout, MODE_BULK_READ, cmd,
@@ -2976,11 +2977,14 @@ int _usb_read(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_t
if (err && err != LIBUSB_ERROR_TIMEOUT) {
applog(LOG_WARNING, "%s %i %s usb read err:(%d) %s", cgpu->drv->name,
cgpu->device_id, usb_cmdname(cmd), err, libusb_error_name(err));
- if (err != LIBUSB_ERROR_NO_DEVICE) {
+ if (err != LIBUSB_ERROR_NO_DEVICE && !tried_reset) {
err = libusb_reset_device(usbdev->handle);
+ tried_reset = 1; // don't call reset twice in a row
applog(LOG_WARNING, "%s %i attempted reset got err:(%d) %s",
cgpu->drv->name, cgpu->device_id, err, libusb_error_name(err));
}
+ } else {
+ tried_reset = 0;
}
ptr += got;
bufleft -= got;
@@ -3040,7 +3044,7 @@ int _usb_write(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_
struct timeval write_start, tv_finish;
struct cg_usb_device *usbdev;
unsigned int initial_timeout;
- int err, sent, tot, pstate;
+ int err, sent, tot, pstate, tried_reset;
bool first = true;
double done;
@@ -3065,6 +3069,7 @@ int _usb_write(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_
err = LIBUSB_SUCCESS;
initial_timeout = timeout;
cgtime(&write_start);
+ tried_reset = 0;
while (bufsiz > 0) {
int tosend = bufsiz;
@@ -3094,11 +3099,14 @@ int _usb_write(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_
if (err) {
applog(LOG_WARNING, "%s %i %s usb write err:(%d) %s", cgpu->drv->name,
cgpu->device_id, usb_cmdname(cmd), err, libusb_error_name(err));
- if (err != LIBUSB_ERROR_NO_DEVICE) {
+ if (err != LIBUSB_ERROR_NO_DEVICE && !tried_reset) {
err = libusb_reset_device(usbdev->handle);
+ tried_reset = 1; // don't try reset twice in a row
applog(LOG_WARNING, "%s %i attempted reset got err:(%d) %s",
cgpu->drv->name, cgpu->device_id, err, libusb_error_name(err));
}
+ } else {
+ tried_reset = 0;
}
if (err)
break;