Imitate a transaction translator for all usb1.1 device writes to compensate for variable quality hubs and operating system support.
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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
diff --git a/usbutils.c b/usbutils.c
index 05f7654..8030ed0 100644
--- a/usbutils.c
+++ b/usbutils.c
@@ -21,6 +21,7 @@
static pthread_mutex_t cgusb_lock;
static pthread_mutex_t cgusbres_lock;
static cglock_t cgusb_fd_lock;
+static cgtimer_t usb11_cgt;
#define NODEV(err) ((err) != LIBUSB_SUCCESS && (err) != LIBUSB_ERROR_TIMEOUT)
@@ -2411,17 +2412,22 @@ static int callback_wait(struct usb_transfer *ut, int *transferred, unsigned int
}
static int usb_submit_transfer(struct usb_transfer *ut, struct libusb_transfer *transfer,
- bool cancellable)
+ bool cancellable, bool tt)
{
int err;
INIT_LIST_HEAD(&ut->list);
cg_wlock(&cgusb_fd_lock);
+ /* Imitate a transaction translator for writes to usb1.1 devices */
+ if (tt)
+ cgsleep_ms_r(&usb11_cgt, 1);
err = libusb_submit_transfer(transfer);
if (likely(!err))
ut->cancellable = cancellable;
list_add(&ut->list, &ut_list);
+ if (tt)
+ cgtimer_time(&usb11_cgt);
cg_wunlock(&cgusb_fd_lock);
return err;
@@ -2431,7 +2437,7 @@ static int
usb_bulk_transfer(struct cgpu_info *cgpu, struct cg_usb_device *usbdev, int intinfo,
int epinfo, unsigned char *data, int length, int *transferred,
unsigned int timeout, __maybe_unused int mode, enum usb_cmds cmd,
- __maybe_unused int seq, bool cancellable)
+ __maybe_unused int seq, bool cancellable, bool tt)
{
int bulk_timeout, callback_timeout = timeout, pipe_retries = 0;
struct libusb_device_handle *dev_handle = usbdev->handle;
@@ -2480,7 +2486,7 @@ pipe_retry:
libusb_fill_bulk_transfer(ut.transfer, dev_handle, endpoint, buf, length,
transfer_callback, &ut, bulk_timeout);
STATS_TIMEVAL(&tv_start);
- err = usb_submit_transfer(&ut, ut.transfer, cancellable);
+ err = usb_submit_transfer(&ut, ut.transfer, cancellable, tt);
errn = errno;
if (!err)
err = callback_wait(&ut, transferred, callback_timeout);
@@ -2578,7 +2584,7 @@ int _usb_read(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_t
while (bufleft > 0 && !eom) {
err = usb_bulk_transfer(cgpu, usbdev, intinfo, epinfo, ptr, usbbufread,
&got, timeout, MODE_BULK_READ, cmd,
- first ? SEQ0 : SEQ1, cancellable);
+ first ? SEQ0 : SEQ1, cancellable, false);
cgtime(&tv_finish);
ptr[got] = '\0';
@@ -2706,7 +2712,7 @@ int _usb_write(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_
}
err = usb_bulk_transfer(cgpu, usbdev, intinfo, epinfo, (unsigned char *)buf,
tosend, &sent, timeout, MODE_BULK_WRITE,
- cmd, first ? SEQ0 : SEQ1, false);
+ cmd, first ? SEQ0 : SEQ1, false, usb11);
cgtime(&tv_finish);
USBDEBUG("USB debug: @_usb_write(%s (nodev=%s)) err=%d%s sent=%d", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), err, isnodev(err), sent);
@@ -2759,6 +2765,7 @@ static int usb_control_transfer(struct cgpu_info *cgpu, libusb_device_handle *de
struct usb_transfer ut;
unsigned char buf[70];
int err, transferred;
+ bool tt = false;
if (unlikely(cgpu->shutdown))
return libusb_control_transfer(dev_handle, bmRequestType, bRequest, wValue, wIndex, buffer, wLength, timeout);
@@ -2766,11 +2773,14 @@ static int usb_control_transfer(struct cgpu_info *cgpu, libusb_device_handle *de
init_usb_transfer(&ut);
libusb_fill_control_setup(buf, bmRequestType, bRequest, wValue,
wIndex, wLength);
- if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
+ if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) {
memcpy(buf + LIBUSB_CONTROL_SETUP_SIZE, buffer, wLength);
+ if (cgpu->usbdev->descriptor->bcdUSB < 0x0200)
+ tt = true;
+ }
libusb_fill_control_transfer(ut.transfer, dev_handle, buf, transfer_callback,
&ut, 0);
- err = usb_submit_transfer(&ut, ut.transfer, false);
+ err = usb_submit_transfer(&ut, ut.transfer, false, tt);
if (!err)
err = callback_wait(&ut, &transferred, timeout);
if (err == LIBUSB_SUCCESS && transferred) {