diff --git a/driver-modminer.c b/driver-modminer.c index fff02250..8d609dfb 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -103,7 +103,7 @@ static void do_ping(struct cgpu_info *modminer) modminer->drv->name, modminer->fpgaid, amount, err); // Clear any outstanding data - while ((err = usb_read(modminer, buf, sizeof(buf)-1, &amount, C_CLEAR)) == 0 && amount > 0) + while ((err = usb_read_once(modminer, buf, sizeof(buf)-1, &amount, C_CLEAR)) == 0 && amount > 0) applog(LOG_DEBUG, "%s%u: clear got %d", modminer->drv->name, modminer->fpgaid, amount); @@ -141,7 +141,7 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic goto unshin; } - if ((err = usb_read(modminer, buf, sizeof(buf)-1, &amount, C_GETVERSION)) < 0 || amount < 1) { + if ((err = usb_read_once(modminer, buf, sizeof(buf)-1, &amount, C_GETVERSION)) < 0 || amount < 1) { if (err < 0) applog(LOG_ERR, "%s detect (%s) no version reply (%d)", modminer->drv->dname, devpath, err); diff --git a/usbutils.c b/usbutils.c index ac98ec69..f4efe61e 100644 --- a/usbutils.c +++ b/usbutils.c @@ -154,7 +154,7 @@ static struct usb_find_devices find_dev[] = { .idProduct = 0x6001, .kernel = 0, .config = 1, - .interface = 1, + .interface = 0, .timeout = AVALON_TIMEOUT_MS, .epcount = ARRAY_SIZE(ava_eps), .eps = ava_eps }, @@ -202,6 +202,17 @@ static const char *BLANK = ""; static const char *space = " "; static const char *nodatareturned = "no data returned "; +#if 0 // enable USBDEBUG - only during development testing + static const char *debug_true_str = "true"; + static const char *debug_false_str = "false"; + static const char *nodevstr = "=NODEV"; + #define bool_str(boo) ((boo) ? debug_true_str : debug_false_str) + #define isnodev(err) (NODEV(err) ? nodevstr : BLANK) + #define USBDEBUG(fmt, ...) applog(LOG_WARNING, fmt, ##__VA_ARGS__) +#else + #define USBDEBUG(fmt, ...) +#endif + // For device limits by driver static struct driver_count { uint32_t count; @@ -1311,6 +1322,8 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u goto cldame; } if (strcmp((char *)man, found->iManufacturer)) { + applog(LOG_DEBUG, "USB init, iManufacturer mismatch %s", + devstr); bad = USB_INIT_IGNORE; goto cldame; } @@ -1329,6 +1342,8 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u goto cldame; } if (strcmp((char *)prod, found->iProduct)) { + applog(LOG_DEBUG, "USB init, iProduct mismatch %s", + devstr); bad = USB_INIT_IGNORE; goto cldame; } @@ -1358,8 +1373,11 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u goto cldame; } - if ((int)(config->bNumInterfaces) <= found->interface) + if ((int)(config->bNumInterfaces) <= found->interface) { + applog(LOG_DEBUG, "USB init bNumInterfaces <= interface %s", + devstr); goto cldame; + } for (i = 0; i < found->epcount; i++) found->eps[i].found = false; @@ -1381,9 +1399,13 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u } } - for (i = 0; i < found->epcount; i++) - if (found->eps[i].found == false) + for (i = 0; i < found->epcount; i++) { + if (found->eps[i].found == false) { + applog(LOG_DEBUG, "USB init found == false %s", + devstr); goto cldame; + } + } err = libusb_claim_interface(cgusb->handle, found->interface); if (err) { @@ -1815,7 +1837,7 @@ static void rejected_inc(struct cgpu_info *cgpu) #define USB_MAX_READ 8192 -int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, const char *end, enum usb_cmds cmd, bool ftdi) +int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, const char *end, enum usb_cmds cmd, bool ftdi, bool readonce) { struct cg_usb_device *usbdev = cgpu->usbdev; #if DO_USB_STATS @@ -1824,7 +1846,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro struct timeval read_start, tv_finish; unsigned int initial_timeout; double max, done; - int err, got, tot; + int bufleft, err, got, tot; bool first = true; unsigned char *search; int endlen; @@ -1833,6 +1855,8 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro unsigned char usbbuf[USB_MAX_READ+4], *ptr; size_t usbbufread; + USBDEBUG("USB debug: _usb_read(%s (nodev=%s),ep=%d,buf=%p,bufsiz=%zu,proc=%p,timeout=%u,end=%s,cmd=%s,ftdi=%s,readonce=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), ep, buf, bufsiz, processed, timeout, end ? (char *)str_text((char *)end) : "NULL", usb_cmdname(cmd), bool_str(ftdi), bool_str(readonce)); + if (bufsiz > USB_MAX_READ) quit(1, "%s USB read request %d too large (max=%d)", cgpu->drv->name, bufsiz, USB_MAX_READ); @@ -1849,32 +1873,60 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro timeout = usbdev->found->timeout; if (end == NULL) { - if (ftdi) - usbbufread = bufsiz + 2; - else - usbbufread = bufsiz; - got = 0; - STATS_TIMEVAL(&tv_start); - err = libusb_bulk_transfer(usbdev->handle, - usbdev->found->eps[ep].ep, - usbbuf, usbbufread, &got, timeout); - STATS_TIMEVAL(&tv_finish); - USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0); - usbbuf[got] = '\0'; - - if (ftdi) { - // first 2 bytes returned are an FTDI status - if (got > 2) { - got -= 2; - memmove(usbbuf, usbbuf+2, got+1); - } else { - got = 0; - usbbuf[0] = '\0'; + tot = 0; + ptr = usbbuf; + bufleft = bufsiz; + err = LIBUSB_SUCCESS; + initial_timeout = timeout; + max = ((double)timeout) / 1000.0; + cgtime(&read_start); + while (bufleft > 0) { + if (ftdi) + usbbufread = bufleft + 2; + else + usbbufread = bufleft; + got = 0; + STATS_TIMEVAL(&tv_start); + err = libusb_bulk_transfer(usbdev->handle, + usbdev->found->eps[ep].ep, + ptr, usbbufread, &got, timeout); + STATS_TIMEVAL(&tv_finish); + USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, first ? SEQ0 : SEQ1); + ptr[got] = '\0'; + + USBDEBUG("USB debug: @_usb_read(%s (nodev=%s)) first=%s err=%d%s got=%d ptr='%s' usbbufread=%zu", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), bool_str(first), err, isnodev(err), got, (char *)str_text((char *)ptr), usbbufread); + + if (ftdi) { + // first 2 bytes returned are an FTDI status + if (got > 2) { + got -= 2; + memmove(ptr, ptr+2, got+1); + } else { + got = 0; + *ptr = '\0'; + } } + + tot += got; + + if (err || readonce) + break; + + ptr += got; + bufleft -= got; + + first = false; + + done = tdiff(&tv_finish, &read_start); + // N.B. this is return LIBUSB_SUCCESS with whatever size has already been read + if (unlikely(done >= max)) + break; + + timeout = initial_timeout - (done * 1000); } - *processed = got; - memcpy((char *)buf, (const char *)usbbuf, (got < (int)bufsiz) ? got + 1 : (int)bufsiz); + *processed = tot; + memcpy((char *)buf, (const char *)usbbuf, (tot < (int)bufsiz) ? tot + 1 : (int)bufsiz); if (NODEV(err)) release_cgpu(cgpu); @@ -1884,16 +1936,17 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro tot = 0; ptr = usbbuf; + bufleft = bufsiz; endlen = strlen(end); err = LIBUSB_SUCCESS; initial_timeout = timeout; max = ((double)timeout) / 1000.0; cgtime(&read_start); - while (bufsiz) { + while (bufleft > 0) { if (ftdi) - usbbufread = bufsiz + 2; + usbbufread = bufleft + 2; else - usbbufread = bufsiz; + usbbufread = bufleft; got = 0; STATS_TIMEVAL(&tv_start); err = libusb_bulk_transfer(usbdev->handle, @@ -1903,6 +1956,8 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, first ? SEQ0 : SEQ1); ptr[got] = '\0'; + USBDEBUG("USB debug: @_usb_read(%s (nodev=%s)) first=%s err=%d%s got=%d ptr='%s' usbbufread=%zu", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), bool_str(first), err, isnodev(err), got, (char *)str_text((char *)ptr), usbbufread); + if (ftdi) { // first 2 bytes returned are an FTDI status if (got > 2) { @@ -1916,7 +1971,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro tot += got; - if (err) + if (err || readonce) break; // WARNING - this will return data past END ('if' there is extra data) @@ -1938,7 +1993,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro } ptr += got; - bufsiz -= got; + bufleft -= got; first = false; @@ -1967,6 +2022,8 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr #endif int err, sent; + USBDEBUG("USB debug: _usb_write(%s (nodev=%s),ep=%d,buf='%s',bufsiz=%zu,proc=%p,timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), ep, (char *)str_text(buf), bufsiz, processed, timeout, usb_cmdname(cmd)); + if (cgpu->usbinfo.nodev) { *processed = 0; #if DO_USB_STATS @@ -1985,6 +2042,8 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr STATS_TIMEVAL(&tv_finish); USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0); + 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); + *processed = sent; if (NODEV(err)) @@ -2001,6 +2060,8 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest #endif int err; + USBDEBUG("USB debug: _usb_transfer(%s (nodev=%s),type=%"PRIu8",req=%"PRIu8",value=%"PRIu16",index=%"PRIu16",timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), request_type, bRequest, wValue, wIndex, timeout, usb_cmdname(cmd)); + if (cgpu->usbinfo.nodev) { #if DO_USB_STATS rejected_inc(cgpu); @@ -2015,6 +2076,8 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest STATS_TIMEVAL(&tv_finish); USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0); + USBDEBUG("USB debug: @_usb_transfer(%s (nodev=%s)) err=%d%s", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), err, isnodev(err)); + if (NODEV(err)) release_cgpu(cgpu); diff --git a/usbutils.h b/usbutils.h index a4f054ba..2c4f6424 100644 --- a/usbutils.h +++ b/usbutils.h @@ -150,26 +150,29 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); struct api_data *api_usb_stats(int *count); void update_usb_stats(struct cgpu_info *cgpu); -int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, const char *end, enum usb_cmds cmd, bool ftdi); +int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, const char *end, enum usb_cmds cmd, bool ftdi, bool readonce); int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, enum usb_cmds); int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned int timeout, enum usb_cmds cmd); void usb_cleanup(); void usb_initialise(); #define usb_read(cgpu, buf, bufsiz, read, cmd) \ - _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false) + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false, false) + +#define usb_read_once(cgpu, buf, bufsiz, read, cmd) \ + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false, true) #define usb_read_nl(cgpu, buf, bufsiz, read, cmd) \ - _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, "\n", cmd, false) + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, "\n", cmd, false, false) #define usb_read_ep(cgpu, ep, buf, bufsiz, read, cmd) \ - _usb_read(cgpu, ep, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false) + _usb_read(cgpu, ep, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false, false) #define usb_read_timeout(cgpu, buf, bufsiz, read, timeout, cmd) \ - _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, timeout, NULL, cmd, false) + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, timeout, NULL, cmd, false, false) #define usb_read_ep_timeout(cgpu, ep, buf, bufsiz, read, timeout, cmd) \ - _usb_read(cgpu, ep, buf, bufsiz, read, timeout, NULL, cmd, false) + _usb_read(cgpu, ep, buf, bufsiz, read, timeout, NULL, cmd, false, false) #define usb_write(cgpu, buf, bufsiz, wrote, cmd) \ _usb_write(cgpu, DEFAULT_EP_OUT, buf, bufsiz, wrote, DEVTIMEOUT, cmd) @@ -183,11 +186,14 @@ void usb_initialise(); #define usb_write_ep_timeout(cgpu, ep, buf, bufsiz, wrote, timeout, cmd) \ _usb_write(cgpu, ep, buf, bufsiz, wrote, timeout, cmd) +#define usb_ftdi_read(cgpu, buf, bufsiz, read, cmd) \ + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, true, false) + #define usb_ftdi_read_nl(cgpu, buf, bufsiz, read, cmd) \ - _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, "\n", cmd, true) + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, "\n", cmd, true, false) #define usb_ftdi_read_ok(cgpu, buf, bufsiz, read, cmd) \ - _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, "OK\n", cmd, true) + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, "OK\n", cmd, true, false) #define usb_transfer(cgpu, typ, req, val, idx, cmd) \ _usb_transfer(cgpu, typ, req, val, idx, DEVTIMEOUT, cmd)