diff --git a/driver-icarus.c b/driver-icarus.c index 12b0ca21..3c66c2f7 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -218,17 +218,20 @@ static int option_offset = -1; struct device_drv icarus_drv; -static void transfer(struct cgpu_info *icarus, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, enum usb_cmds cmd) +static void _transfer(struct cgpu_info *icarus, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint32_t *data, int siz, enum usb_cmds cmd) { int err; - err = usb_transfer(icarus, request_type, bRequest, wValue, wIndex, cmd); + err = usb_transfer_data(icarus, request_type, bRequest, wValue, wIndex, data, siz, cmd); applog(LOG_DEBUG, "%s%i: %s got err %d", icarus->drv->name, icarus->device_id, usb_cmdname(cmd), err); } +#define transfer(icarus, request_type, bRequest, wValue, wIndex, cmd) \ + _transfer(icarus, request_type, bRequest, wValue, wIndex, NULL, 0, cmd) + // TODO: handle baud static void icarus_initialise(struct cgpu_info *icarus, __maybe_unused int baud) { @@ -296,6 +299,19 @@ static void icarus_initialise(struct cgpu_info *icarus, __maybe_unused int baud) case IDENT_ICA: break; case IDENT_AMU: + // Set data control + transfer(icarus, CP210X_TYPE_OUT, CP210X_REQUEST_DATA, CP210X_VALUE_DATA, + icarus->usbdev->found->interface, C_SETDATA); + + if (icarus->usbinfo.nodev) + return; + + // Set the baud + uint32_t data = CP210X_DATA_BAUD; + _transfer(icarus, CP210X_TYPE_OUT, CP210X_REQUEST_BAUD, 0, + icarus->usbdev->found->interface, + &data, sizeof(data), C_SETBAUD); + break; case IDENT_CMR: break; diff --git a/usbutils.c b/usbutils.c index ae34eb94..fb1be64b 100644 --- a/usbutils.c +++ b/usbutils.c @@ -2160,15 +2160,16 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr return err; } -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) +int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint32_t *data, int siz, unsigned int timeout, enum usb_cmds cmd) { struct cg_usb_device *usbdev = cgpu->usbdev; #if DO_USB_STATS struct timeval tv_start, tv_finish; #endif - int err; + uint32_t *buf = NULL; + int err, i; - 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)); + USBDEBUG("USB debug: _usb_transfer(%s (nodev=%s),type=%"PRIu8",req=%"PRIu8",value=%"PRIu16",index=%"PRIu16",siz=%d,timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), request_type, bRequest, wValue, wIndex, siz, timeout, usb_cmdname(cmd)); if (cgpu->usbinfo.nodev) { #if DO_USB_STATS @@ -2177,15 +2178,34 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest return LIBUSB_ERROR_NO_DEVICE; } + USBDEBUG("USB debug: @_usb_transfer() data=%s", bin2hex((unsigned char *)data, (size_t)siz)); + + if (siz > 0) { + siz--; + siz >>= 2; + siz++; + buf = malloc(siz << 2); + if (unlikely(!buf)) + quit(1, "Failed to malloc in _usb_transfer"); + for (i = 0; i < siz; i++) + buf[i] = htole32(data[i]); + } + + USBDEBUG("USB debug: @_usb_transfer() buf=%s", bin2hex((unsigned char *)buf, (size_t)(siz << 2))); + STATS_TIMEVAL(&tv_start); err = libusb_control_transfer(usbdev->handle, request_type, - bRequest, htole16(wValue), htole16(wIndex), NULL, 0, + bRequest, htole16(wValue), htole16(wIndex), + (unsigned char *)buf, (uint16_t)(siz << 2), timeout == DEVTIMEOUT ? usbdev->found->timeout : timeout); 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 (buf) + free(buf); + if (NODEV(err)) release_cgpu(cgpu); diff --git a/usbutils.h b/usbutils.h index 35533854..7273e9f7 100644 --- a/usbutils.h +++ b/usbutils.h @@ -12,7 +12,8 @@ #include -// for 0x0403/0x6014 FT232H (and possibly others?) + +// For 0x0403:0x6014/0x6001 FT232H (and possibly others?) #define FTDI_TYPE_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT) #define FTDI_REQUEST_RESET ((uint8_t)0) @@ -45,6 +46,16 @@ #define FTDI_VALUE_FLOW 0 #define FTDI_VALUE_MODEM 0x0303 + +// For 0x10c4:0xea60 USB cp210x chip +#define CP210X_TYPE_OUT 0x41 + +#define CP210X_REQUEST_DATA 0x07 +#define CP210X_REQUEST_BAUD 0x1e + +#define CP210X_VALUE_DATA 0x0303 +#define CP210X_DATA_BAUD 0x0001c200 + // Use the device defined timeout #define DEVTIMEOUT 0 @@ -189,7 +200,7 @@ 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 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); +int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint32_t *data, int siz, unsigned int timeout, enum usb_cmds cmd); void usb_cleanup(); void usb_initialise(); @@ -227,6 +238,9 @@ void usb_initialise(); _usb_write(cgpu, ep, buf, bufsiz, wrote, timeout, cmd) #define usb_transfer(cgpu, typ, req, val, idx, cmd) \ - _usb_transfer(cgpu, typ, req, val, idx, DEVTIMEOUT, cmd) + _usb_transfer(cgpu, typ, req, val, idx, NULL, 0, DEVTIMEOUT, cmd) + +#define usb_transfer_data(cgpu, typ, req, val, idx, data, len, cmd) \ + _usb_transfer(cgpu, typ, req, val, idx, data, len, DEVTIMEOUT, cmd) #endif