Browse Source

libztex: Download mining firmware to all devices with dummy firmware

When one or more ZTEX devices with dummy firmware are found on startup,
the correct firmware is downloaded to each device, and then USB devices
are rescanned until all devices have reattached with the mining firmware.

This allows to discover and configure all ZTEX devices and start mining
directly, without first running the ZTEX Java software to download a
firmware to the device.
nfactor-troky
Peter Stuge 12 years ago committed by Denis Ahrens
parent
commit
584dc5acd5
  1. 252
      libztex.c

252
libztex.c

@ -2,6 +2,8 @@
* libztex.c - Ztex 1.15x fpga board support library * libztex.c - Ztex 1.15x fpga board support library
* *
* Copyright (c) 2012 nelisky.btc@gmail.com * Copyright (c) 2012 nelisky.btc@gmail.com
* Copyright (c) 2012 Denis Ahrens <denis@h3q.com>
* Copyright (c) 2012 Peter Stuge <peter@stuge.se>
* *
* This work is based upon the Java SDK provided by ztex which is * This work is based upon the Java SDK provided by ztex which is
* Copyright (C) 2009-2011 ZTEX GmbH. * Copyright (C) 2009-2011 ZTEX GmbH.
@ -47,21 +49,147 @@
#define CAPABILITY_MULTI_FPGA 0,7 #define CAPABILITY_MULTI_FPGA 0,7
static bool libztex_checkDevice(struct libusb_device *dev) enum check_result {
CHECK_ERROR,
CHECK_IS_NOT_ZTEX,
CHECK_OK,
CHECK_RESCAN,
};
static enum check_result libztex_checkDevice(struct libusb_device *dev)
{ {
FILE *fp = NULL;
libusb_device_handle *hndl = NULL;
struct libusb_device_descriptor desc; struct libusb_device_descriptor desc;
int err; int i, ret = CHECK_ERROR, err, cnt;
size_t got_bytes, length;
unsigned char buf[64], *fw_buf;
char *firmware = "ztex_ufm1_15y1.bin";
err = libusb_get_device_descriptor(dev, &desc); err = libusb_get_device_descriptor(dev, &desc);
if (unlikely(err != 0)) { if (unlikely(err != 0)) {
applog(LOG_ERR, "Ztex check device: Failed to open read descriptor with error %d", err); applog(LOG_ERR, "Ztex check device: Failed to open read descriptor with error %d", err);
return false; return CHECK_ERROR;
} }
if (!(desc.idVendor == LIBZTEX_IDVENDOR && desc.idProduct == LIBZTEX_IDPRODUCT)) {
if (desc.idVendor != LIBZTEX_IDVENDOR || desc.idProduct != LIBZTEX_IDPRODUCT) {
applog(LOG_DEBUG, "Not a ZTEX device %0.4x:%0.4x", desc.idVendor, desc.idProduct); applog(LOG_DEBUG, "Not a ZTEX device %0.4x:%0.4x", desc.idVendor, desc.idProduct);
return false; return CHECK_IS_NOT_ZTEX;
} }
return true;
err = libusb_open(dev, &hndl);
if (err != LIBUSB_SUCCESS) {
applog(LOG_ERR, "%s: Can not open ZTEX device: %s", __func__, libusb_error_name(err));
goto done;
}
cnt = libusb_control_transfer(hndl, 0xc0, 0x22, 0, 0, buf, 40, 500);
if (unlikely(cnt < 0)) {
applog(LOG_ERR, "Ztex check device: Failed to read ztex descriptor with err %d", cnt);
goto done;
}
if (buf[0] != 40 || buf[1] != 1 || buf[2] != 'Z' || buf[3] != 'T' || buf[4] != 'E' || buf[5] != 'X') {
applog(LOG_ERR, "Ztex check device: Error reading ztex descriptor");
goto done;
}
if (buf[6] != 10)
{
ret = CHECK_IS_NOT_ZTEX;
goto done;
}
// 15 = 1.15y 13 = 1.15d or 1.15x
switch(buf[7])
{
case 13:
applog(LOG_ERR, "Found ztex board 1.15d or 1.15x but currently unsupported!");
ret = CHECK_IS_NOT_ZTEX;
goto done;
case 15:
applog(LOG_ERR, "Found ztex board 1.15y");
break;
default:
applog(LOG_ERR, "Found unknown ztex board");
ret = CHECK_IS_NOT_ZTEX;
goto done;
}
// testing for dummy firmware
if (buf[8] != 0) {
ret = CHECK_OK;
goto done;
}
applog(LOG_ERR, "Found dummy firmware, trying to send mining firmware: %s", firmware);
// reset 1
buf[0] = 1;
cnt = libusb_control_transfer(hndl, 0x40, 0xA0, 0xE600, 0, buf, 1,1000);
if (cnt < 0)
{
applog(LOG_ERR, "Ztex reset 1 failed: %s", libusb_error_name(cnt));
goto done;
}
fp = open_bitstream("ztex", firmware);
if (!fp) {
applog(LOG_ERR, "failed to open firmware file '%s'", firmware);
goto done;
}
if (0 != fseek(fp, 0, SEEK_END)) {
applog(LOG_ERR, "Ztex firmware fseek: %s", strerror(errno));
goto done;
}
length = ftell(fp);
rewind(fp);
fw_buf = malloc(length);
if (!fw_buf) {
applog(LOG_ERR, "%s: Can not allocate memory: %s", __func__, strerror(errno));
goto done;
}
got_bytes = fread(fw_buf, 1, length, fp);
fclose(fp);
fp = NULL;
if (got_bytes < length) {
applog(LOG_ERR, "%s: Incomplete firmware read: %d/%d", __func__, got_bytes, length);
goto done;
}
for (i = 0; i < length; i+= 256) {
// firmware wants data in small chunks like 256 bytes
int numbytes = (length - i) < 256 ? (length - i) : 256;
int k = libusb_control_transfer(hndl, 0x40, 0xA0, i, 0, fw_buf + i, numbytes, 1000);
if (k < numbytes)
{
applog(LOG_ERR, "Ztex device: Failed to write firmware at %d with: %s", i, libusb_error_name(k));
goto done;
}
}
// reset 0
buf[0] = 0;
err = libusb_control_transfer(hndl, 0x40, 0xA0, 0xE600, 0, buf, 1,1000);
if (err < 0)
{
applog(LOG_ERR, "Ztex reset 0 failed: %s", libusb_error_name(err));
goto done;
}
applog(LOG_ERR, "Ztex device: succesfully wrote firmware");
ret = CHECK_RESCAN;
done:
if (fp)
fclose(fp);
if (hndl)
libusb_close(hndl);
return ret;
} }
static bool libztex_checkCapability(struct libztex_device *ztex, int i, int j) static bool libztex_checkCapability(struct libztex_device *ztex, int i, int j)
@ -408,35 +536,21 @@ int libztex_suspend(struct libztex_device *ztex) {
} }
int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** ztex) { int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** ztex) {
struct libztex_device *newdev; struct libztex_device *newdev = *ztex;
int i, cnt, err; int i, cnt, err;
unsigned char buf[64]; unsigned char buf[64];
uint16_t langid; uint16_t langid;
newdev = malloc(sizeof(struct libztex_device)); err = libusb_open(dev, &newdev->hndl);
newdev->bitFileName = NULL; if (err != LIBUSB_SUCCESS) {
newdev->numberOfFpgas = -1; applog(LOG_ERR, "%s: Can not open ZTEX device: %s", __func__, libusb_error_name(err));
newdev->valid = false; return CHECK_ERROR;
newdev->hndl = NULL; }
*ztex = newdev;
err = libusb_get_device_descriptor(dev, &newdev->descriptor); err = libusb_get_device_descriptor(dev, &newdev->descriptor);
if (unlikely(err != 0)) { if (unlikely(err != 0)) {
applog(LOG_ERR, "Ztex check device: Failed to open read descriptor with error %d", err); applog(LOG_ERR, "Ztex check device: Failed to open read descriptor with error %d", err);
return err; return CHECK_ERROR;
}
// Check vendorId and productId
if (!(newdev->descriptor.idVendor == LIBZTEX_IDVENDOR &&
newdev->descriptor.idProduct == LIBZTEX_IDPRODUCT)) {
applog(LOG_ERR, "Not a ztex device? %0.4X, %0.4X", newdev->descriptor.idVendor, newdev->descriptor.idProduct);
return 1;
}
err = libusb_open(dev, &newdev->hndl);
if (unlikely(err != 0)) {
applog(LOG_ERR, "Ztex check device: Failed to open handle with error %d", err);
return err;
} }
/* We open code string descriptor retrieval and ASCII decoding here /* We open code string descriptor retrieval and ASCII decoding here
@ -587,52 +701,104 @@ void libztex_destroy_device(struct libztex_device* ztex)
int libztex_scanDevices(struct libztex_dev_list*** devs_p) int libztex_scanDevices(struct libztex_dev_list*** devs_p)
{ {
int usbdevices[LIBZTEX_MAX_DESCRIPTORS]; int usbdevices[LIBZTEX_MAX_DESCRIPTORS];
struct libztex_dev_list **devs; struct libztex_dev_list **devs = NULL;
struct libztex_device *ztex; struct libusb_device_descriptor dev_descr;
int found = 0, pos = 0, err; struct libztex_device *ztex = NULL;
libusb_device **list; int found, max_found = 0, pos = 0, err, rescan, ret = 0;
ssize_t cnt, i = 0; libusb_device **list = NULL;
ssize_t cnt, i;
do {
cnt = libusb_get_device_list(NULL, &list); cnt = libusb_get_device_list(NULL, &list);
if (unlikely(cnt < 0)) { if (unlikely(cnt < 0)) {
applog(LOG_ERR, "Ztex scan devices: Failed to list usb devices with err %d", cnt); applog(LOG_ERR, "Ztex scan devices: Failed to list usb devices with err %d", cnt);
return 0; goto done;
} }
for (i = 0; i < cnt; i++) { for (found = rescan = i = 0; i < cnt; i++) {
if (libztex_checkDevice(list[i])) { err = libztex_checkDevice(list[i]);
switch (err) {
case CHECK_ERROR:
applog(LOG_ERR, "Ztex: Can not check device: %s", libusb_error_name(err));
continue;
case CHECK_IS_NOT_ZTEX:
continue;
case CHECK_OK:
// Got one! // Got one!
usbdevices[found] = i; usbdevices[found++] = i;
break;
case CHECK_RESCAN:
rescan = 1;
found++; found++;
break;
} }
} }
if (found < max_found)
rescan = 1;
else if (found > max_found)
max_found = found;
if (rescan)
libusb_free_device_list(list, 1);
} while (rescan);
if (0 == found)
goto done;
devs = malloc(sizeof(struct libztex_dev_list *) * found); devs = malloc(sizeof(struct libztex_dev_list *) * found);
if (devs == NULL) { if (devs == NULL) {
applog(LOG_ERR, "Ztex scan devices: Failed to allocate memory"); applog(LOG_ERR, "Ztex scan devices: Failed to allocate memory");
return 0; goto done;
} }
for (i = 0; i < found; i++) { for (i = 0; i < found; i++) {
if (!ztex) {
ztex = malloc(sizeof(*ztex));
if (!ztex) {
applog(LOG_ERR, "%s: Can not allocate memory for device struct: %s", __func__, strerror(errno));
goto done;
}
}
ztex->bitFileName = NULL;
ztex->numberOfFpgas = -1;
ztex->valid = false;
err = libztex_prepare_device(list[usbdevices[i]], &ztex); err = libztex_prepare_device(list[usbdevices[i]], &ztex);
if (unlikely(err != 0)) if (unlikely(err != 0)) {
applog(LOG_ERR, "prepare device: %d", err); applog(LOG_ERR, "prepare device: %d", err);
// check if valid
if (!ztex->valid) {
libztex_destroy_device(ztex); libztex_destroy_device(ztex);
ztex = NULL;
continue; continue;
} }
devs[pos] = malloc(sizeof(struct libztex_dev_list)); devs[pos] = malloc(sizeof(struct libztex_dev_list));
if (NULL == devs[pos]) {
applog(LOG_ERR, "%s: Can not allocate memory for device: %s", __func__, strerror(errno));
libztex_destroy_device(ztex);
ztex = NULL;
continue;
}
devs[pos]->dev = ztex; devs[pos]->dev = ztex;
ztex = NULL;
devs[pos]->next = NULL; devs[pos]->next = NULL;
if (pos > 0) if (pos > 0)
devs[pos - 1]->next = devs[pos]; devs[pos - 1]->next = devs[pos];
pos++; pos++;
} }
libusb_free_device_list(list, 1); ret = pos;
done:
if (ret > 0)
*devs_p = devs; *devs_p = devs;
return pos; else if (devs)
free(devs);
if (list)
libusb_free_device_list(list, 1);
return ret;
} }
int libztex_sendHashData(struct libztex_device *ztex, unsigned char *sendbuf) int libztex_sendHashData(struct libztex_device *ztex, unsigned char *sendbuf)

Loading…
Cancel
Save