Commit 527c6ee25506b2796a2e2128189933673c37bfe2

Kano 2013-06-25T21:35:21

usbutils optional cps IO control - but not enabled

diff --git a/driver-icarus.c b/driver-icarus.c
index bfa78c0..5c10248 100644
--- a/driver-icarus.c
+++ b/driver-icarus.c
@@ -255,6 +255,9 @@ static void icarus_initialise(struct cgpu_info *icarus, int baud)
 	if (icarus->usbinfo.nodev)
 		return;
 
+	usb_set_cps(icarus, baud / 10);
+//	usb_enable_cps(icarus);
+
 	switch (icarus->usbdev->ident) {
 		case IDENT_BLT:
 		case IDENT_LLT:
diff --git a/usbutils.c b/usbutils.c
index 620a108..2d5b6f4 100644
--- a/usbutils.c
+++ b/usbutils.c
@@ -2312,6 +2312,21 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
 			}
 			got = 0;
 
+			if (first && usbdev->usecps) {
+				if (usbdev->last_write_tv.tv_sec && usbdev->last_write_siz) {
+					struct timeval now;
+					double need;
+
+					cgtime(&now);
+					need = (double)(usbdev->last_write_siz) /
+						(double)(usbdev->cps) -
+						tdiff(&(usbdev->last_write_tv), &now);
+
+					// Simple error condition check/avoidance '< 1.0'
+					if (need > 0.0 && need < 1.0)
+						nmsleep((unsigned int)(need * 1000.0));
+				}
+			}
 			STATS_TIMEVAL(&tv_start);
 			err = usb_bulk_transfer(usbdev->handle,
 						usbdev->found->eps[ep].ep,
@@ -2403,6 +2418,21 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
 				usbbufread = bufleft;
 		}
 		got = 0;
+		if (first && usbdev->usecps) {
+			if (usbdev->last_write_tv.tv_sec && usbdev->last_write_siz) {
+				struct timeval now;
+				double need;
+
+				cgtime(&now);
+				need = (double)(usbdev->last_write_siz) /
+					(double)(usbdev->cps) -
+					tdiff(&(usbdev->last_write_tv), &now);
+
+				// Simple error condition check/avoidance '< 1.0'
+				if (need > 0.0 && need < 1.0)
+					nmsleep((unsigned int)(need * 1000.0));
+			}
+		}
 		STATS_TIMEVAL(&tv_start);
 		err = usb_bulk_transfer(usbdev->handle,
 					usbdev->found->eps[ep].ep, ptr,
@@ -2531,6 +2561,23 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
 	cgtime(&read_start);
 	while (bufsiz > 0) {
 		sent = 0;
+		if (usbdev->usecps) {
+			if (usbdev->last_write_tv.tv_sec && usbdev->last_write_siz) {
+				struct timeval now;
+				double need;
+
+				cgtime(&now);
+				need = (double)(usbdev->last_write_siz) /
+					(double)(usbdev->cps) -
+					tdiff(&(usbdev->last_write_tv), &now);
+
+				// Simple error condition check/avoidance '< 1.0'
+				if (need > 0.0 && need < 1.0)
+					nmsleep((unsigned int)(need * 1000.0));
+			}
+			cgtime(&(usbdev->last_write_tv));
+			usbdev->last_write_siz = bufsiz;
+		}
 		STATS_TIMEVAL(&tv_start);
 		err = usb_bulk_transfer(usbdev->handle,
 					usbdev->found->eps[ep].ep,
@@ -2608,6 +2655,23 @@ int __usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bReques
 
 	USBDEBUG("USB debug: @_usb_transfer() buf=%s", bin2hex((unsigned char *)buf, (size_t)siz));
 
+	if (usbdev->usecps) {
+		if (usbdev->last_write_tv.tv_sec && usbdev->last_write_siz) {
+			struct timeval now;
+			double need;
+
+			cgtime(&now);
+			need = (double)(usbdev->last_write_siz) /
+				(double)(usbdev->cps) -
+				tdiff(&(usbdev->last_write_tv), &now);
+
+			// Simple error condition check/avoidance '< 1.0'
+			if (need > 0.0 && need < 1.0)
+				nmsleep((unsigned int)(need * 1000.0));
+		}
+		cgtime(&(usbdev->last_write_tv));
+		usbdev->last_write_siz = siz;
+	}
 	STATS_TIMEVAL(&tv_start);
 	cg_rlock(&cgusb_fd_lock);
 	err = libusb_control_transfer(usbdev->handle, request_type,
@@ -2665,6 +2729,21 @@ int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRe
 
 	*amount = 0;
 
+	if (usbdev->usecps) {
+		if (usbdev->last_write_tv.tv_sec && usbdev->last_write_siz) {
+			struct timeval now;
+			double need;
+
+			cgtime(&now);
+			need = (double)(usbdev->last_write_siz) /
+				(double)(usbdev->cps) -
+				tdiff(&(usbdev->last_write_tv), &now);
+
+			// Simple error condition check/avoidance '< 1.0'
+			if (need > 0.0 && need < 1.0)
+				nmsleep((unsigned int)(need * 1000.0));
+		}
+	}
 	STATS_TIMEVAL(&tv_start);
 	cg_rlock(&cgusb_fd_lock);
 	err = libusb_control_transfer(usbdev->handle, request_type,
@@ -2814,6 +2893,42 @@ uint32_t usb_buffer_size(struct cgpu_info *cgpu)
 	return ret;
 }
 
+void usb_set_cps(struct cgpu_info *cgpu, int cps)
+{
+	int pstate;
+
+	DEVLOCK(cgpu, pstate);
+
+	if (cgpu->usbdev)
+		cgpu->usbdev->cps = cps;
+
+	DEVUNLOCK(cgpu, pstate);
+}
+
+void usb_enable_cps(struct cgpu_info *cgpu)
+{
+	int pstate;
+
+	DEVLOCK(cgpu, pstate);
+
+	if (cgpu->usbdev)
+		cgpu->usbdev->usecps = true;
+
+	DEVUNLOCK(cgpu, pstate);
+}
+
+void usb_disable_cps(struct cgpu_info *cgpu)
+{
+	int pstate;
+
+	DEVLOCK(cgpu, pstate);
+
+	if (cgpu->usbdev)
+		cgpu->usbdev->usecps = false;
+
+	DEVUNLOCK(cgpu, pstate);
+}
+
 // Need to set all devices with matching usbdev
 void usb_set_dev_start(struct cgpu_info *cgpu)
 {
diff --git a/usbutils.h b/usbutils.h
index 0b8406a..e2cd05a 100644
--- a/usbutils.h
+++ b/usbutils.h
@@ -168,6 +168,7 @@ struct cg_usb_device {
 	enum sub_ident ident;
 	uint16_t usbver;
 	int cps;
+	bool usecps;
 	char *prod_string;
 	char *manuf_string;
 	char *serial_string;
@@ -177,6 +178,8 @@ struct cg_usb_device {
 	uint32_t bufsiz;
 	uint32_t bufamt;
 	uint16_t PrefPacketSize;
+	struct timeval last_write_tv;
+	size_t last_write_siz;
 };
 
 #define USB_NOSTAT 0
@@ -298,6 +301,9 @@ void usb_buffer_enable(struct cgpu_info *cgpu);
 void usb_buffer_disable(struct cgpu_info *cgpu);
 void usb_buffer_clear(struct cgpu_info *cgpu);
 uint32_t usb_buffer_size(struct cgpu_info *cgpu);
+void usb_set_cps(struct cgpu_info *cgpu, int cps);
+void usb_enable_cps(struct cgpu_info *cgpu);
+void usb_disable_cps(struct cgpu_info *cgpu);
 void usb_set_dev_start(struct cgpu_info *cgpu);
 void usb_cleanup();
 void usb_initialise();