Commit 527fe05848f5e84b41a7e7383bc3652949055b85

Kano 2013-05-09T11:48:09

Merge branch 'usb'

diff --git a/driver-modminer.c b/driver-modminer.c
index fff0225..8d609df 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 ac98ec6..f4efe61 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 a4f054b..2c4f642 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)