Browse Source

Merge branch 'hashbuster_micro' into bfgminer

Luke Dashjr 12 years ago
parent
commit
dbc2396252
4 changed files with 192 additions and 18 deletions
  1. 18 14
      driver-hashbuster2.c
  2. 135 0
      lowl-usb.c
  3. 9 0
      lowl-usb.h
  4. 30 4
      util.h

+ 18 - 14
driver-hashbuster2.c

@@ -30,9 +30,8 @@
 BFG_REGISTER_DRIVER(hashbuster2_drv)
 BFG_REGISTER_DRIVER(hashbuster2_drv)
 
 
 static
 static
-bool hashbuster2_io(libusb_device_handle * const h, unsigned char *buf, unsigned char *cmd)
+bool hashbuster2_io(struct lowl_usb_endpoint * const h, unsigned char *buf, unsigned char *cmd)
 {
 {
-	int result;
 	char x[0x81];
 	char x[0x81];
 	
 	
 	bool rv = true;
 	bool rv = true;
@@ -44,8 +43,10 @@ bool hashbuster2_io(libusb_device_handle * const h, unsigned char *buf, unsigned
 	
 	
 	do // Workaround for PIC USB buffer corruption. We should repeat last packet if receive FF
 	do // Workaround for PIC USB buffer corruption. We should repeat last packet if receive FF
 	{
 	{
-		libusb_bulk_transfer(h, 0x01, cmd, 64, &result, 0);
-		libusb_bulk_transfer(h, 0x81, buf, 64, &result, 0);
+		do
+		{
+			usb_write(h, cmd, 64);
+		} while (usb_read(h, buf, 64) != 64);
 	} while(buf[0]==0xFF);
 	} while(buf[0]==0xFF);
 	
 	
 	if (unlikely(opt_dev_protocol))
 	if (unlikely(opt_dev_protocol))
@@ -57,7 +58,7 @@ bool hashbuster2_io(libusb_device_handle * const h, unsigned char *buf, unsigned
 }
 }
 
 
 static
 static
-bool hashbuster2_spi_config(libusb_device_handle * const h, const uint8_t mode, const uint8_t miso, const uint32_t freq)
+bool hashbuster2_spi_config(struct lowl_usb_endpoint * const h, const uint8_t mode, const uint8_t miso, const uint32_t freq)
 {
 {
 	uint8_t buf[0x40] = {'\x01', '\x01'};
 	uint8_t buf[0x40] = {'\x01', '\x01'};
 	if (!hashbuster2_io(h, buf, buf))
 	if (!hashbuster2_io(h, buf, buf))
@@ -66,7 +67,7 @@ bool hashbuster2_spi_config(libusb_device_handle * const h, const uint8_t mode,
 }
 }
 
 
 static
 static
-bool hashbuster2_spi_disable(libusb_device_handle * const h)
+bool hashbuster2_spi_disable(struct lowl_usb_endpoint * const h)
 {
 {
 	uint8_t buf[0x40] = {'\x01', '\x00'};
 	uint8_t buf[0x40] = {'\x01', '\x00'};
 	if (!hashbuster2_io(h, buf, buf))
 	if (!hashbuster2_io(h, buf, buf))
@@ -75,7 +76,7 @@ bool hashbuster2_spi_disable(libusb_device_handle * const h)
 }
 }
 
 
 static
 static
-bool hashbuster2_spi_reset(libusb_device_handle * const h, uint8_t chips)
+bool hashbuster2_spi_reset(struct lowl_usb_endpoint * const h, uint8_t chips)
 {
 {
 	uint8_t buf[0x40] = {'\x02', '\x00', chips};
 	uint8_t buf[0x40] = {'\x02', '\x00', chips};
 	if (!hashbuster2_io(h, buf, buf))
 	if (!hashbuster2_io(h, buf, buf))
@@ -84,7 +85,7 @@ bool hashbuster2_spi_reset(libusb_device_handle * const h, uint8_t chips)
 }
 }
 
 
 static
 static
-bool hashbuster2_spi_transfer(libusb_device_handle * const h, void * const buf, const void * const data, size_t datasz)
+bool hashbuster2_spi_transfer(struct lowl_usb_endpoint * const h, void * const buf, const void * const data, size_t datasz)
 {
 {
 	if (datasz > HASHBUSTER_MAX_BYTES_PER_SPI_TRANSFER)
 	if (datasz > HASHBUSTER_MAX_BYTES_PER_SPI_TRANSFER)
 		return false;
 		return false;
@@ -101,7 +102,7 @@ bool hashbuster2_spi_transfer(libusb_device_handle * const h, void * const buf,
 static
 static
 bool hashbuster2_spi_txrx(struct spi_port * const port)
 bool hashbuster2_spi_txrx(struct spi_port * const port)
 {
 {
-	libusb_device_handle * const h = port->userp;
+	struct lowl_usb_endpoint * const h = port->userp;
 	const uint8_t *wrbuf = spi_gettxbuf(port);
 	const uint8_t *wrbuf = spi_gettxbuf(port);
 	uint8_t *rdbuf = spi_getrxbuf(port);
 	uint8_t *rdbuf = spi_getrxbuf(port);
 	size_t bufsz = spi_getbufsz(port);
 	size_t bufsz = spi_getbufsz(port);
@@ -158,22 +159,24 @@ bool hashbuster2_lowl_probe(const struct lowlevel_device_info * const info)
 	libusb_open(dev, &h);
 	libusb_open(dev, &h);
 	libusb_set_configuration(h, 1);
 	libusb_set_configuration(h, 1);
 	libusb_claim_interface(h, 0);
 	libusb_claim_interface(h, 0);
+	struct lowl_usb_endpoint * const ep = usb_open_ep_pair(h, 0x81, 64, 0x01, 64);
+	usb_ep_set_timeouts_ms(ep, 100, 0);
 	
 	
 	unsigned char OUTPacket[64];
 	unsigned char OUTPacket[64];
 	unsigned char INPacket[64];
 	unsigned char INPacket[64];
 	OUTPacket[0] = 0xFE;
 	OUTPacket[0] = 0xFE;
-	hashbuster2_io(h, INPacket, OUTPacket);
+	hashbuster2_io(ep, INPacket, OUTPacket);
 	if (INPacket[1] == 0x18)
 	if (INPacket[1] == 0x18)
 	{
 	{
 		// Turn on miner PSU
 		// Turn on miner PSU
 		OUTPacket[0] = 0x10;
 		OUTPacket[0] = 0x10;
 		OUTPacket[1] = 0x00;
 		OUTPacket[1] = 0x00;
 		OUTPacket[2] = 0x01;
 		OUTPacket[2] = 0x01;
-		hashbuster2_io(h, INPacket, OUTPacket);
+		hashbuster2_io(ep, INPacket, OUTPacket);
 	}
 	}
 	
 	
 	OUTPacket[0] = '\x20';
 	OUTPacket[0] = '\x20';
-	hashbuster2_io(h, INPacket, OUTPacket);
+	hashbuster2_io(ep, INPacket, OUTPacket);
 	if (!memcmp(INPacket, "\x20\0", 2))
 	if (!memcmp(INPacket, "\x20\0", 2))
 	{
 	{
 		// 64-bit LE serial number
 		// 64-bit LE serial number
@@ -191,7 +194,7 @@ bool hashbuster2_lowl_probe(const struct lowlevel_device_info * const info)
 	port = malloc(sizeof(*port));
 	port = malloc(sizeof(*port));
 	port->cgpu = &dummy_cgpu;
 	port->cgpu = &dummy_cgpu;
 	port->txrx = hashbuster2_spi_txrx;
 	port->txrx = hashbuster2_spi_txrx;
-	port->userp=h;
+	port->userp = ep;
 	port->repr = hashbuster2_drv.dname;
 	port->repr = hashbuster2_drv.dname;
 	port->logprio = LOG_DEBUG;
 	port->logprio = LOG_DEBUG;
 	port->speed = 100000;
 	port->speed = 100000;
@@ -202,6 +205,7 @@ bool hashbuster2_lowl_probe(const struct lowlevel_device_info * const info)
 	{
 	{
 		applog(LOG_WARNING, "%s: No chips found on %s", __func__, serial);
 		applog(LOG_WARNING, "%s: No chips found on %s", __func__, serial);
 fail:
 fail:
+		usb_close_ep(ep);
 		free(port);
 		free(port);
 		free(serial);
 		free(serial);
 		libusb_release_interface(h, 0);
 		libusb_release_interface(h, 0);
@@ -278,7 +282,7 @@ bool hashbuster2_get_stats(struct cgpu_info * const cgpu)
 	
 	
 	struct bitfury_device * const bitfury = cgpu->device_data;
 	struct bitfury_device * const bitfury = cgpu->device_data;
 	struct spi_port * const spi = bitfury->spi;
 	struct spi_port * const spi = bitfury->spi;
-	libusb_device_handle * const h = spi->userp;
+	struct lowl_usb_endpoint * const h = spi->userp;
 	uint8_t buf[0x40] = {'\x04'};
 	uint8_t buf[0x40] = {'\x04'};
 	if (!hashbuster2_io(h, buf, buf))
 	if (!hashbuster2_io(h, buf, buf))
 		return false;
 		return false;

+ 135 - 0
lowl-usb.c

@@ -180,6 +180,141 @@ void cgpu_copy_libusb_strings(struct cgpu_info *cgpu, libusb_device *usb)
 }
 }
 #endif
 #endif
 
 
+struct lowl_usb_endpoint {
+	struct libusb_device_handle *devh;
+	
+	unsigned char endpoint_r;
+	int packetsz_r;
+	bytes_t _buf_r;
+	unsigned timeout_ms_r;
+	
+	unsigned char endpoint_w;
+	int packetsz_w;
+	unsigned timeout_ms_w;
+};
+
+struct lowl_usb_endpoint *usb_open_ep(struct libusb_device_handle * const devh, const uint8_t epid, const int pktsz)
+{
+	struct lowl_usb_endpoint * const ep = malloc(sizeof(*ep));
+	ep->devh = devh;
+	if (epid & 0x80)
+	{
+		// Read endpoint
+		ep->endpoint_r = epid;
+		ep->packetsz_r = pktsz;
+		bytes_init(&ep->_buf_r);
+	}
+	else
+	{
+		// Write endpoint
+		ep->endpoint_w = epid;
+		ep->packetsz_w = epid;
+		ep->packetsz_r = -1;
+	}
+	return ep;
+};
+
+struct lowl_usb_endpoint *usb_open_ep_pair(struct libusb_device_handle * const devh, const uint8_t epid_r, const int pktsz_r, const uint8_t epid_w, const int pktsz_w)
+{
+	struct lowl_usb_endpoint * const ep = malloc(sizeof(*ep));
+	*ep = (struct lowl_usb_endpoint){
+		.devh = devh,
+		.endpoint_r = epid_r,
+		.packetsz_r = pktsz_r,
+		._buf_r = BYTES_INIT,
+		.endpoint_w = epid_w,
+		.packetsz_w = pktsz_w,
+	};
+	return ep;
+}
+
+void usb_ep_set_timeouts_ms(struct lowl_usb_endpoint * const ep, const unsigned timeout_ms_r, const unsigned timeout_ms_w)
+{
+	ep->timeout_ms_r = timeout_ms_r;
+	ep->timeout_ms_w = timeout_ms_w;
+}
+
+ssize_t usb_read(struct lowl_usb_endpoint * const ep, void * const data, size_t datasz)
+{
+	unsigned timeout;
+	size_t xfer;
+	if ( (xfer = bytes_len(&ep->_buf_r)) < datasz)
+	{
+		bytes_extend_buf(&ep->_buf_r, datasz + ep->packetsz_r - 1);
+		unsigned char *p = &bytes_buf(&ep->_buf_r)[xfer];
+		int pxfer;
+		int rem = datasz - xfer, rsz;
+		timeout = xfer ? 0 : ep->timeout_ms_r;
+		while (rem > 0)
+		{
+			rsz = (rem / ep->packetsz_r) * ep->packetsz_r;
+			if (rsz < rem)
+				rsz += ep->packetsz_r;
+			switch (libusb_bulk_transfer(ep->devh, ep->endpoint_r, p, rsz, &pxfer, timeout))
+			{
+				case 0:
+				case LIBUSB_ERROR_TIMEOUT:
+					if (!pxfer)
+						// Behaviour is like tcsetattr-style timeout
+						return 0;
+					p += pxfer;
+					rem -= pxfer;
+					// NOTE: Need to maintain _buf_r length so data is saved in case of error
+					xfer += pxfer;
+					bytes_resize(&ep->_buf_r, xfer);
+					break;
+				case LIBUSB_ERROR_PIPE:
+				case LIBUSB_ERROR_NO_DEVICE:
+					errno = EPIPE;
+					return -1;
+				default:
+					errno = EIO;
+					return -1;
+			}
+			timeout = 0;
+		}
+	}
+	memcpy(data, bytes_buf(&ep->_buf_r), datasz);
+	bytes_shift(&ep->_buf_r, datasz);
+	return datasz;
+}
+
+ssize_t usb_write(struct lowl_usb_endpoint * const ep, const void * const data, size_t datasz)
+{
+	unsigned timeout = ep->timeout_ms_w;
+	unsigned char *p = (void*)data;
+	size_t rem = datasz;
+	int pxfer;
+	while (rem > 0)
+	{
+		switch (libusb_bulk_transfer(ep->devh, ep->endpoint_w, p, rem, &pxfer, timeout))
+		{
+			case 0:
+			case LIBUSB_ERROR_TIMEOUT:
+				p += pxfer;
+				rem -= pxfer;
+				break;
+			case LIBUSB_ERROR_PIPE:
+			case LIBUSB_ERROR_NO_DEVICE:
+				errno = EPIPE;
+				return (datasz - rem) ?: -1;
+			default:
+				errno = EIO;
+				return (datasz - rem) ?: -1;
+		}
+		timeout = 0;
+	}
+	errno = 0;
+	return datasz;
+}
+
+void usb_close_ep(struct lowl_usb_endpoint * const ep)
+{
+	if (ep->packetsz_r != -1)
+		bytes_free(&ep->_buf_r);
+	free(ep);
+}
+
 void lowl_usb_close(struct libusb_device_handle * const devh)
 void lowl_usb_close(struct libusb_device_handle * const devh)
 {
 {
 	libusb_close(devh);
 	libusb_close(devh);

+ 9 - 0
lowl-usb.h

@@ -9,4 +9,13 @@ extern struct device_drv *bfg_claim_usb(struct device_drv * const, const bool ve
 
 
 extern void cgpu_copy_libusb_strings(struct cgpu_info *, libusb_device *);
 extern void cgpu_copy_libusb_strings(struct cgpu_info *, libusb_device *);
 
 
+struct lowl_usb_endpoint;
+
+extern struct lowl_usb_endpoint *usb_open_ep(struct libusb_device_handle *, uint8_t epid, int pktsz);
+extern struct lowl_usb_endpoint *usb_open_ep_pair(struct libusb_device_handle *, uint8_t epid_r, int pktsz_r, uint8_t epid_w, int pktsz_w);
+extern void usb_ep_set_timeouts_ms(struct lowl_usb_endpoint *, unsigned timeout_ms_r, unsigned timeout_ms_w);
+extern ssize_t usb_read(struct lowl_usb_endpoint *, void *, size_t);
+extern ssize_t usb_write(struct lowl_usb_endpoint *, const void *, size_t);
+extern void usb_close_ep(struct lowl_usb_endpoint *);
+
 #endif
 #endif

+ 30 - 4
util.h

@@ -233,9 +233,8 @@ ssize_t bytes_find(const bytes_t * const b, const uint8_t needle)
 extern void _bytes_alloc_failure(size_t);
 extern void _bytes_alloc_failure(size_t);
 
 
 static inline
 static inline
-void bytes_resize(bytes_t *b, size_t newsz)
+void bytes_extend_buf(bytes_t * const b, const size_t newsz)
 {
 {
-	b->sz = newsz;
 	if (newsz <= b->allocsz)
 	if (newsz <= b->allocsz)
 		return;
 		return;
 	
 	
@@ -250,11 +249,33 @@ void bytes_resize(bytes_t *b, size_t newsz)
 }
 }
 
 
 static inline
 static inline
-void bytes_append(bytes_t *b, const void *add, size_t addsz)
+void bytes_resize(bytes_t * const b, const size_t newsz)
+{
+	bytes_extend_buf(b, newsz);;
+	b->sz = newsz;
+}
+
+static inline
+void *bytes_preappend(bytes_t * const b, const size_t addsz)
+{
+	size_t origsz = bytes_len(b);
+	bytes_extend_buf(b, origsz + addsz);
+	return &bytes_buf(b)[origsz];
+}
+
+static inline
+void bytes_postappend(bytes_t * const b, const size_t addsz)
 {
 {
 	size_t origsz = bytes_len(b);
 	size_t origsz = bytes_len(b);
 	bytes_resize(b, origsz + addsz);
 	bytes_resize(b, origsz + addsz);
-	memcpy(&bytes_buf(b)[origsz], add, addsz);
+}
+
+static inline
+void bytes_append(bytes_t * const b, const void * const add, const size_t addsz)
+{
+	void * const appendbuf = bytes_preappend(b, addsz);
+	memcpy(appendbuf, add, addsz);
+	bytes_postappend(b, addsz);
 }
 }
 
 
 static inline
 static inline
@@ -283,6 +304,11 @@ void bytes_cpy(bytes_t *dst, const bytes_t *src)
 static inline
 static inline
 void bytes_shift(bytes_t *b, size_t shift)
 void bytes_shift(bytes_t *b, size_t shift)
 {
 {
+	if (shift >= b->sz)
+	{
+		b->sz = 0;
+		return;
+	}
 	b->sz -= shift;
 	b->sz -= shift;
 	memmove(bytes_buf(b), &bytes_buf(b)[shift], bytes_len(b));
 	memmove(bytes_buf(b), &bytes_buf(b)[shift], bytes_len(b));
 }
 }