drivers: Load firmware via new resource API

This commit is contained in:
Daniel Elstner 2015-09-26 22:41:05 +02:00
parent 7d89fd60e5
commit 8e2d6c9db7
13 changed files with 187 additions and 196 deletions

View File

@ -33,6 +33,8 @@
#define LOG_PREFIX "ezusb" #define LOG_PREFIX "ezusb"
#define FW_CHUNKSIZE (4 * 1024)
SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear) SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear)
{ {
int ret; int ret;
@ -50,46 +52,51 @@ SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear)
return ret; return ret;
} }
SR_PRIV int ezusb_install_firmware(libusb_device_handle *hdl, SR_PRIV int ezusb_install_firmware(struct sr_context *ctx,
const char *filename) libusb_device_handle *hdl,
const char *name)
{ {
FILE *fw; unsigned char *firmware;
int offset, chunksize, ret, result; size_t length, offset, chunksize;
unsigned char buf[4096]; int ret, result;
sr_info("Uploading firmware at %s", filename); /* Max size is 64 kiB since the value field of the setup packet,
if (!(fw = g_fopen(filename, "rb"))) { * which holds the firmware offset, is only 16 bit wide.
sr_err("Unable to open firmware file %s for reading: %s", */
filename, g_strerror(errno)); firmware = sr_resource_load(ctx, SR_RESOURCE_FIRMWARE,
name, &length, 1 << 16);
if (!firmware)
return SR_ERR; return SR_ERR;
}
sr_info("Uploading firmware '%s'.", name);
result = SR_OK; result = SR_OK;
offset = 0; offset = 0;
while (1) { while (offset < length) {
chunksize = fread(buf, 1, 4096, fw); chunksize = MIN(length - offset, FW_CHUNKSIZE);
if (chunksize == 0)
break;
ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR | ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, 0xa0, offset, LIBUSB_ENDPOINT_OUT, 0xa0, offset,
0x0000, buf, chunksize, 100); 0x0000, firmware + offset,
chunksize, 100);
if (ret < 0) { if (ret < 0) {
sr_err("Unable to send firmware to device: %s.", sr_err("Unable to send firmware to device: %s.",
libusb_error_name(ret)); libusb_error_name(ret));
result = SR_ERR; g_free(firmware);
break; return SR_ERR;
} }
sr_info("Uploaded %d bytes", chunksize); sr_info("Uploaded %zu bytes.", chunksize);
offset += chunksize; offset += chunksize;
} }
fclose(fw); g_free(firmware);
sr_info("Firmware upload done");
sr_info("Firmware upload done.");
return result; return result;
} }
SR_PRIV int ezusb_upload_firmware(libusb_device *dev, int configuration, SR_PRIV int ezusb_upload_firmware(struct sr_context *ctx, libusb_device *dev,
const char *filename) int configuration, const char *name)
{ {
struct libusb_device_handle *hdl; struct libusb_device_handle *hdl;
int ret; int ret;
@ -125,7 +132,7 @@ SR_PRIV int ezusb_upload_firmware(libusb_device *dev, int configuration,
if ((ezusb_reset(hdl, 1)) < 0) if ((ezusb_reset(hdl, 1)) < 0)
return SR_ERR; return SR_ERR;
if (ezusb_install_firmware(hdl, filename) < 0) if (ezusb_install_firmware(ctx, hdl, name) < 0)
return SR_ERR; return SR_ERR;
if ((ezusb_reset(hdl, 0)) < 0) if ((ezusb_reset(hdl, 0)) < 0)

View File

@ -90,17 +90,17 @@ static const int32_t trigger_matches[] = {
SR_TRIGGER_FALLING, SR_TRIGGER_FALLING,
}; };
static const char *sigma_firmware_files[] = { static const char sigma_firmware_files[][24] = {
/* 50 MHz, supports 8 bit fractions */ /* 50 MHz, supports 8 bit fractions */
FIRMWARE_DIR "/asix-sigma-50.fw", "asix-sigma-50.fw",
/* 100 MHz */ /* 100 MHz */
FIRMWARE_DIR "/asix-sigma-100.fw", "asix-sigma-100.fw",
/* 200 MHz */ /* 200 MHz */
FIRMWARE_DIR "/asix-sigma-200.fw", "asix-sigma-200.fw",
/* Synchronous clock from pin */ /* Synchronous clock from pin */
FIRMWARE_DIR "/asix-sigma-50sync.fw", "asix-sigma-50sync.fw",
/* Frequency counter */ /* Frequency counter */
FIRMWARE_DIR "/asix-sigma-phasor.fw", "asix-sigma-phasor.fw",
}; };
static int sigma_read(void *buf, size_t size, struct dev_context *devc) static int sigma_read(void *buf, size_t size, struct dev_context *devc)
@ -508,31 +508,20 @@ err:
* pulses used to program the FPGA. Note that the *bb_cmd must be free()'d * pulses used to program the FPGA. Note that the *bb_cmd must be free()'d
* by the caller of this function. * by the caller of this function.
*/ */
static int sigma_fw_2_bitbang(const char *filename, static int sigma_fw_2_bitbang(struct sr_context *ctx, const char *name,
uint8_t **bb_cmd, gsize *bb_cmd_size) uint8_t **bb_cmd, gsize *bb_cmd_size)
{ {
GMappedFile *file; size_t i, file_size, bb_size;
GError *error; char *firmware;
gsize i, file_size, bb_size;
gchar *firmware;
uint8_t *bb_stream, *bbs; uint8_t *bb_stream, *bbs;
uint32_t imm; uint32_t imm;
int bit, v; int bit, v;
int ret = SR_OK; int ret = SR_OK;
/* firmware = sr_resource_load(ctx, SR_RESOURCE_FIRMWARE,
* Map the file and make the mapped buffer writable. name, &file_size, 256 * 1024);
* NOTE: Using writable=TRUE does _NOT_ mean that file that is mapped if (!firmware)
* will be modified. It will not be modified until someone uses return SR_ERR;
* g_file_set_contents() on it.
*/
error = NULL;
file = g_mapped_file_new(filename, TRUE, &error);
g_assert_no_error(error);
file_size = g_mapped_file_get_length(file);
firmware = g_mapped_file_get_contents(file);
g_assert(firmware);
/* Weird magic transformation below, I have no idea what it does. */ /* Weird magic transformation below, I have no idea what it does. */
imm = 0x3f6df2ab; imm = 0x3f6df2ab;
@ -571,11 +560,12 @@ static int sigma_fw_2_bitbang(const char *filename,
*bb_cmd_size = bb_size; *bb_cmd_size = bb_size;
exit: exit:
g_mapped_file_unref(file); g_free(firmware);
return ret; return ret;
} }
static int upload_firmware(int firmware_idx, struct dev_context *devc) static int upload_firmware(struct sr_context *ctx,
int firmware_idx, struct dev_context *devc)
{ {
int ret; int ret;
unsigned char *buf; unsigned char *buf;
@ -614,7 +604,7 @@ static int upload_firmware(int firmware_idx, struct dev_context *devc)
return ret; return ret;
/* Prepare firmware. */ /* Prepare firmware. */
ret = sigma_fw_2_bitbang(firmware, &buf, &buf_size); ret = sigma_fw_2_bitbang(ctx, firmware, &buf, &buf_size);
if (ret != SR_OK) { if (ret != SR_OK) {
sr_err("An error occurred while reading the firmware: %s", sr_err("An error occurred while reading the firmware: %s",
firmware); firmware);
@ -677,10 +667,12 @@ static int dev_open(struct sr_dev_inst *sdi)
static int set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate) static int set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate)
{ {
struct dev_context *devc; struct dev_context *devc;
struct drv_context *drvc;
unsigned int i; unsigned int i;
int ret; int ret;
devc = sdi->priv; devc = sdi->priv;
drvc = sdi->driver->context;
ret = SR_OK; ret = SR_OK;
for (i = 0; i < ARRAY_SIZE(samplerates); i++) { for (i = 0; i < ARRAY_SIZE(samplerates); i++) {
@ -691,13 +683,13 @@ static int set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate)
return SR_ERR_SAMPLERATE; return SR_ERR_SAMPLERATE;
if (samplerate <= SR_MHZ(50)) { if (samplerate <= SR_MHZ(50)) {
ret = upload_firmware(0, devc); ret = upload_firmware(drvc->sr_ctx, 0, devc);
devc->num_channels = 16; devc->num_channels = 16;
} else if (samplerate == SR_MHZ(100)) { } else if (samplerate == SR_MHZ(100)) {
ret = upload_firmware(1, devc); ret = upload_firmware(drvc->sr_ctx, 1, devc);
devc->num_channels = 8; devc->num_channels = 8;
} else if (samplerate == SR_MHZ(200)) { } else if (samplerate == SR_MHZ(200)) {
ret = upload_firmware(2, devc); ret = upload_firmware(drvc->sr_ctx, 2, devc);
devc->num_channels = 4; devc->num_channels = 4;
} }

View File

@ -29,48 +29,48 @@ static const struct fx2lafw_profile supported_fx2[] = {
* ARMFLY AX-Pro * ARMFLY AX-Pro
*/ */
{ 0x08a9, 0x0014, "CWAV", "USBee AX", NULL, { 0x08a9, 0x0014, "CWAV", "USBee AX", NULL,
FIRMWARE_DIR "/fx2lafw-cwav-usbeeax.fw", "fx2lafw-cwav-usbeeax.fw",
0, NULL, NULL}, 0, NULL, NULL},
/* /*
* CWAV USBee DX * CWAV USBee DX
* XZL-Studio DX * XZL-Studio DX
*/ */
{ 0x08a9, 0x0015, "CWAV", "USBee DX", NULL, { 0x08a9, 0x0015, "CWAV", "USBee DX", NULL,
FIRMWARE_DIR "/fx2lafw-cwav-usbeedx.fw", "fx2lafw-cwav-usbeedx.fw",
DEV_CAPS_16BIT, NULL, NULL }, DEV_CAPS_16BIT, NULL, NULL },
/* /*
* CWAV USBee SX * CWAV USBee SX
*/ */
{ 0x08a9, 0x0009, "CWAV", "USBee SX", NULL, { 0x08a9, 0x0009, "CWAV", "USBee SX", NULL,
FIRMWARE_DIR "/fx2lafw-cwav-usbeesx.fw", "fx2lafw-cwav-usbeesx.fw",
0, NULL, NULL}, 0, NULL, NULL},
/* DreamSourceLab DSLogic (before FW upload) */ /* DreamSourceLab DSLogic (before FW upload) */
{ 0x2a0e, 0x0001, "DreamSourceLab", "DSLogic", NULL, { 0x2a0e, 0x0001, "DreamSourceLab", "DSLogic", NULL,
FIRMWARE_DIR "/dreamsourcelab-dslogic-fx2.fw", "dreamsourcelab-dslogic-fx2.fw",
DEV_CAPS_16BIT, NULL, NULL}, DEV_CAPS_16BIT, NULL, NULL},
/* DreamSourceLab DSLogic (after FW upload) */ /* DreamSourceLab DSLogic (after FW upload) */
{ 0x2a0e, 0x0001, "DreamSourceLab", "DSLogic", NULL, { 0x2a0e, 0x0001, "DreamSourceLab", "DSLogic", NULL,
FIRMWARE_DIR "/dreamsourcelab-dslogic-fx2.fw", "dreamsourcelab-dslogic-fx2.fw",
DEV_CAPS_16BIT, "DreamSourceLab", "DSLogic"}, DEV_CAPS_16BIT, "DreamSourceLab", "DSLogic"},
/* DreamSourceLab DSCope (before FW upload) */ /* DreamSourceLab DSCope (before FW upload) */
{ 0x2a0e, 0x0002, "DreamSourceLab", "DSCope", NULL, { 0x2a0e, 0x0002, "DreamSourceLab", "DSCope", NULL,
FIRMWARE_DIR "/dreamsourcelab-dscope-fx2.fw", "dreamsourcelab-dscope-fx2.fw",
DEV_CAPS_16BIT, NULL, NULL}, DEV_CAPS_16BIT, NULL, NULL},
/* DreamSourceLab DSCope (after FW upload) */ /* DreamSourceLab DSCope (after FW upload) */
{ 0x2a0e, 0x0002, "DreamSourceLab", "DSCope", NULL, { 0x2a0e, 0x0002, "DreamSourceLab", "DSCope", NULL,
FIRMWARE_DIR "/dreamsourcelab-dscope-fx2.fw", "dreamsourcelab-dscope-fx2.fw",
DEV_CAPS_16BIT, "DreamSourceLab", "DSCope"}, DEV_CAPS_16BIT, "DreamSourceLab", "DSCope"},
/* DreamSourceLab DSLogic Pro (before FW upload) */ /* DreamSourceLab DSLogic Pro (before FW upload) */
{ 0x2a0e, 0x0003, "DreamSourceLab", "DSLogic Pro", NULL, { 0x2a0e, 0x0003, "DreamSourceLab", "DSLogic Pro", NULL,
FIRMWARE_DIR "/dreamsourcelab-dslogic-pro-fx2.fw", "dreamsourcelab-dslogic-pro-fx2.fw",
DEV_CAPS_16BIT, NULL, NULL}, DEV_CAPS_16BIT, NULL, NULL},
/* DreamSourceLab DSLogic Pro (after FW upload) */ /* DreamSourceLab DSLogic Pro (after FW upload) */
{ 0x2a0e, 0x0003, "DreamSourceLab", "DSLogic Pro", NULL, { 0x2a0e, 0x0003, "DreamSourceLab", "DSLogic Pro", NULL,
FIRMWARE_DIR "/dreamsourcelab-dslogic-pro-fx2.fw", "dreamsourcelab-dslogic-pro-fx2.fw",
DEV_CAPS_16BIT, "DreamSourceLab", "DSLogic"}, DEV_CAPS_16BIT, "DreamSourceLab", "DSLogic"},
/* /*
@ -80,7 +80,7 @@ static const struct fx2lafw_profile supported_fx2[] = {
* Robomotic BugLogic 3 * Robomotic BugLogic 3
*/ */
{ 0x0925, 0x3881, "Saleae", "Logic", NULL, { 0x0925, 0x3881, "Saleae", "Logic", NULL,
FIRMWARE_DIR "/fx2lafw-saleae-logic.fw", "fx2lafw-saleae-logic.fw",
0, NULL, NULL}, 0, NULL, NULL},
/* /*
@ -89,14 +89,14 @@ static const struct fx2lafw_profile supported_fx2[] = {
* Braintechnology USB Interface V2.x * Braintechnology USB Interface V2.x
*/ */
{ 0x04B4, 0x8613, "Cypress", "FX2", NULL, { 0x04B4, 0x8613, "Cypress", "FX2", NULL,
FIRMWARE_DIR "/fx2lafw-cypress-fx2.fw", "fx2lafw-cypress-fx2.fw",
DEV_CAPS_16BIT, NULL, NULL }, DEV_CAPS_16BIT, NULL, NULL },
/* /*
* Braintechnology USB-LPS * Braintechnology USB-LPS
*/ */
{ 0x16d0, 0x0498, "Braintechnology", "USB-LPS", NULL, { 0x16d0, 0x0498, "Braintechnology", "USB-LPS", NULL,
FIRMWARE_DIR "/fx2lafw-braintechnology-usb-lps.fw", "fx2lafw-braintechnology-usb-lps.fw",
DEV_CAPS_16BIT, NULL, NULL }, DEV_CAPS_16BIT, NULL, NULL },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 } { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
@ -330,8 +330,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
sdi->conn = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]), sdi->conn = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
libusb_get_device_address(devlist[i]), NULL); libusb_get_device_address(devlist[i]), NULL);
} else { } else {
if (ezusb_upload_firmware(devlist[i], USB_CONFIGURATION, if (ezusb_upload_firmware(drvc->sr_ctx, devlist[i],
prof->firmware) == SR_OK) USB_CONFIGURATION, prof->firmware) == SR_OK)
/* Store when this device's FW was updated. */ /* Store when this device's FW was updated. */
devc->fw_updated = g_get_monotonic_time(); devc->fw_updated = g_get_monotonic_time();
else else

View File

@ -19,10 +19,6 @@
*/ */
#include <config.h> #include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <math.h> #include <math.h>
#include <glib.h> #include <glib.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
@ -35,24 +31,28 @@
#define USB_TIMEOUT (3 * 1000) #define USB_TIMEOUT (3 * 1000)
int dslogic_fpga_firmware_upload(const struct sr_dev_inst *sdi, SR_PRIV int dslogic_fpga_firmware_upload(const struct sr_dev_inst *sdi,
const char *filename) const char *name)
{ {
FILE *fw; uint64_t sum;
struct stat st; struct sr_resource bitstream;
struct drv_context *drvc;
struct sr_usb_dev_inst *usb; struct sr_usb_dev_inst *usb;
int chunksize, result, ret;
unsigned char *buf; unsigned char *buf;
int sum, transferred; ssize_t chunksize;
int transferred;
int result, ret;
uint8_t cmd[3]; uint8_t cmd[3];
sr_dbg("Uploading FPGA firmware at %s.", filename); drvc = sdi->driver->context;
usb = sdi->conn; usb = sdi->conn;
if (stat(filename, &st) < 0) {
sr_err("Unable to upload FPGA firmware: %s", g_strerror(errno)); sr_dbg("Uploading FPGA firmware '%s'.", name);
return SR_ERR;
} result = sr_resource_open(drvc->sr_ctx, &bitstream,
SR_RESOURCE_FIRMWARE, name);
if (result != SR_OK)
return result;
/* Tell the device firmware is coming. */ /* Tell the device firmware is coming. */
memset(cmd, 0, sizeof(cmd)); memset(cmd, 0, sizeof(cmd));
@ -60,22 +60,22 @@ int dslogic_fpga_firmware_upload(const struct sr_dev_inst *sdi,
LIBUSB_ENDPOINT_OUT, DS_CMD_FPGA_FW, 0x0000, 0x0000, LIBUSB_ENDPOINT_OUT, DS_CMD_FPGA_FW, 0x0000, 0x0000,
(unsigned char *)&cmd, sizeof(cmd), USB_TIMEOUT)) < 0) { (unsigned char *)&cmd, sizeof(cmd), USB_TIMEOUT)) < 0) {
sr_err("Failed to upload FPGA firmware: %s.", libusb_error_name(ret)); sr_err("Failed to upload FPGA firmware: %s.", libusb_error_name(ret));
return SR_ERR; sr_resource_close(drvc->sr_ctx, &bitstream);
}
buf = g_malloc(FW_BUFSIZE);
if (!(fw = g_fopen(filename, "rb"))) {
sr_err("Unable to open %s for reading: %s.", filename, g_strerror(errno));
return SR_ERR; return SR_ERR;
} }
/* Give the FX2 time to get ready for FPGA firmware upload. */ /* Give the FX2 time to get ready for FPGA firmware upload. */
g_usleep(FPGA_UPLOAD_DELAY); g_usleep(FPGA_UPLOAD_DELAY);
buf = g_malloc(FW_BUFSIZE);
sum = 0; sum = 0;
result = SR_OK; result = SR_OK;
while (1) { while (1) {
if ((chunksize = fread(buf, 1, FW_BUFSIZE, fw)) == 0) chunksize = sr_resource_read(drvc->sr_ctx, &bitstream,
buf, FW_BUFSIZE);
if (chunksize < 0)
result = SR_ERR;
if (chunksize <= 0)
break; break;
if ((ret = libusb_bulk_transfer(usb->devhdl, 2 | LIBUSB_ENDPOINT_OUT, if ((ret = libusb_bulk_transfer(usb->devhdl, 2 | LIBUSB_ENDPOINT_OUT,
@ -86,8 +86,8 @@ int dslogic_fpga_firmware_upload(const struct sr_dev_inst *sdi,
break; break;
} }
sum += transferred; sum += transferred;
sr_spew("Uploaded %d/%" PRIu64 " bytes.", sr_spew("Uploaded %" PRIu64 "/%" PRIu64 " bytes.",
sum, (uint64_t)st.st_size); sum, bitstream.size);
if (transferred != chunksize) { if (transferred != chunksize) {
sr_err("Short transfer while uploading FPGA firmware."); sr_err("Short transfer while uploading FPGA firmware.");
@ -95,15 +95,16 @@ int dslogic_fpga_firmware_upload(const struct sr_dev_inst *sdi,
break; break;
} }
} }
fclose(fw);
g_free(buf); g_free(buf);
sr_resource_close(drvc->sr_ctx, &bitstream);
if (result == SR_OK) if (result == SR_OK)
sr_dbg("FPGA firmware upload done."); sr_dbg("FPGA firmware upload done.");
return result; return result;
} }
int dslogic_start_acquisition(const struct sr_dev_inst *sdi) SR_PRIV int dslogic_start_acquisition(const struct sr_dev_inst *sdi)
{ {
struct dev_context *devc; struct dev_context *devc;
struct sr_usb_dev_inst *usb; struct sr_usb_dev_inst *usb;
@ -128,7 +129,7 @@ int dslogic_start_acquisition(const struct sr_dev_inst *sdi)
return SR_OK; return SR_OK;
} }
int dslogic_stop_acquisition(const struct sr_dev_inst *sdi) SR_PRIV int dslogic_stop_acquisition(const struct sr_dev_inst *sdi)
{ {
struct sr_usb_dev_inst *usb; struct sr_usb_dev_inst *usb;
struct dslogic_mode mode; struct dslogic_mode mode;
@ -149,7 +150,7 @@ int dslogic_stop_acquisition(const struct sr_dev_inst *sdi)
return SR_OK; return SR_OK;
} }
int dslogic_fpga_configure(const struct sr_dev_inst *sdi) SR_PRIV int dslogic_fpga_configure(const struct sr_dev_inst *sdi)
{ {
struct dev_context *devc; struct dev_context *devc;
struct sr_usb_dev_inst *usb; struct sr_usb_dev_inst *usb;

View File

@ -123,10 +123,10 @@ struct dslogic_fpga_config {
uint32_t end_sync; uint32_t end_sync;
}; };
int dslogic_fpga_firmware_upload(const struct sr_dev_inst *sdi, SR_PRIV int dslogic_fpga_firmware_upload(const struct sr_dev_inst *sdi,
const char *filename); const char *name);
int dslogic_start_acquisition(const struct sr_dev_inst *sdi); SR_PRIV int dslogic_start_acquisition(const struct sr_dev_inst *sdi);
int dslogic_stop_acquisition(const struct sr_dev_inst *sdi); SR_PRIV int dslogic_stop_acquisition(const struct sr_dev_inst *sdi);
int dslogic_fpga_configure(const struct sr_dev_inst *sdi); SR_PRIV int dslogic_fpga_configure(const struct sr_dev_inst *sdi);
#endif #endif

View File

@ -51,9 +51,9 @@
#define DEV_CAPS_16BIT (1 << DEV_CAPS_16BIT_POS) #define DEV_CAPS_16BIT (1 << DEV_CAPS_16BIT_POS)
#define DSLOGIC_FPGA_FIRMWARE FIRMWARE_DIR "/dreamsourcelab-dslogic-fpga.fw" #define DSLOGIC_FPGA_FIRMWARE "dreamsourcelab-dslogic-fpga.fw"
#define DSCOPE_FPGA_FIRMWARE FIRMWARE_DIR "/dreamsourcelab-dscope-fpga.fw" #define DSCOPE_FPGA_FIRMWARE "dreamsourcelab-dscope-fpga.fw"
#define DSLOGIC_PRO_FPGA_FIRMWARE FIRMWARE_DIR "/dreamsourcelab-dslogic-pro-fpga.fw" #define DSLOGIC_PRO_FPGA_FIRMWARE "dreamsourcelab-dslogic-pro-fpga.fw"
/* Protocol commands */ /* Protocol commands */
#define CMD_GET_FW_VERSION 0xb0 #define CMD_GET_FW_VERSION 0xb0

View File

@ -88,23 +88,23 @@ static const struct dso_profile dev_profiles[] = {
{ 0x04b4, 0x2090, 0x04b5, 0x2090, { 0x04b4, 0x2090, 0x04b5, 0x2090,
"Hantek", "DSO-2090", "Hantek", "DSO-2090",
buffersizes_32k, buffersizes_32k,
FIRMWARE_DIR "/hantek-dso-2090.fw" }, "hantek-dso-2090.fw" },
{ 0x04b4, 0x2150, 0x04b5, 0x2150, { 0x04b4, 0x2150, 0x04b5, 0x2150,
"Hantek", "DSO-2150", "Hantek", "DSO-2150",
buffersizes_32k, buffersizes_32k,
FIRMWARE_DIR "/hantek-dso-2150.fw" }, "hantek-dso-2150.fw" },
{ 0x04b4, 0x2250, 0x04b5, 0x2250, { 0x04b4, 0x2250, 0x04b5, 0x2250,
"Hantek", "DSO-2250", "Hantek", "DSO-2250",
buffersizes_512k, buffersizes_512k,
FIRMWARE_DIR "/hantek-dso-2250.fw" }, "hantek-dso-2250.fw" },
{ 0x04b4, 0x5200, 0x04b5, 0x5200, { 0x04b4, 0x5200, 0x04b5, 0x5200,
"Hantek", "DSO-5200", "Hantek", "DSO-5200",
buffersizes_14k, buffersizes_14k,
FIRMWARE_DIR "/hantek-dso-5200.fw" }, "hantek-dso-5200.fw" },
{ 0x04b4, 0x520a, 0x04b5, 0x520a, { 0x04b4, 0x520a, 0x04b5, 0x520a,
"Hantek", "DSO-5200A", "Hantek", "DSO-5200A",
buffersizes_512k, buffersizes_512k,
FIRMWARE_DIR "/hantek-dso-5200A.fw" }, "hantek-dso-5200A.fw" },
{ 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 },
}; };
@ -323,8 +323,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
sdi->connection_id = g_strdup(connection_id); sdi->connection_id = g_strdup(connection_id);
devices = g_slist_append(devices, sdi); devices = g_slist_append(devices, sdi);
devc = sdi->priv; devc = sdi->priv;
if (ezusb_upload_firmware(devlist[i], USB_CONFIGURATION, if (ezusb_upload_firmware(drvc->sr_ctx, devlist[i],
prof->firmware) == SR_OK) USB_CONFIGURATION, prof->firmware) == SR_OK)
/* Remember when the firmware on this device was updated */ /* Remember when the firmware on this device was updated */
devc->fw_updated = g_get_monotonic_time(); devc->fw_updated = g_get_monotonic_time();
else else

View File

@ -34,7 +34,7 @@
#define USB_INTERFACE 0 #define USB_INTERFACE 0
#define USB_CONFIGURATION 1 #define USB_CONFIGURATION 1
#define FX2_FIRMWARE FIRMWARE_DIR "/saleae-logic16-fx2.fw" #define FX2_FIRMWARE "saleae-logic16-fx2.fw"
#define MAX_RENUM_DELAY_MS 3000 #define MAX_RENUM_DELAY_MS 3000
#define NUM_SIMUL_TRANSFERS 32 #define NUM_SIMUL_TRANSFERS 32
@ -218,8 +218,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
libusb_get_bus_number(devlist[i]), libusb_get_bus_number(devlist[i]),
libusb_get_device_address(devlist[i]), NULL); libusb_get_device_address(devlist[i]), NULL);
} else { } else {
if (ezusb_upload_firmware(devlist[i], USB_CONFIGURATION, if (ezusb_upload_firmware(drvc->sr_ctx, devlist[i],
FX2_FIRMWARE) == SR_OK) USB_CONFIGURATION, FX2_FIRMWARE) == SR_OK)
/* Store when this device's FW was updated. */ /* Store when this device's FW was updated. */
devc->fw_updated = g_get_monotonic_time(); devc->fw_updated = g_get_monotonic_time();
else else

View File

@ -31,8 +31,8 @@
#include "libsigrok-internal.h" #include "libsigrok-internal.h"
#include "protocol.h" #include "protocol.h"
#define FPGA_FIRMWARE_18 FIRMWARE_DIR"/saleae-logic16-fpga-18.bitstream" #define FPGA_FIRMWARE_18 "saleae-logic16-fpga-18.bitstream"
#define FPGA_FIRMWARE_33 FIRMWARE_DIR"/saleae-logic16-fpga-33.bitstream" #define FPGA_FIRMWARE_33 "saleae-logic16-fpga-33.bitstream"
#define MAX_SAMPLE_RATE SR_MHZ(100) #define MAX_SAMPLE_RATE SR_MHZ(100)
#define MAX_4CH_SAMPLE_RATE SR_MHZ(50) #define MAX_4CH_SAMPLE_RATE SR_MHZ(50)
@ -465,13 +465,17 @@ static int configure_led(const struct sr_dev_inst *sdi)
static int upload_fpga_bitstream(const struct sr_dev_inst *sdi, static int upload_fpga_bitstream(const struct sr_dev_inst *sdi,
enum voltage_range vrange) enum voltage_range vrange)
{ {
uint64_t sum;
struct sr_resource bitstream;
struct dev_context *devc; struct dev_context *devc;
int offset, chunksize, ret; struct drv_context *drvc;
const char *filename; const char *name;
uint8_t len, buf[256 * 62], command[64]; ssize_t chunksize;
FILE *fw; int ret;
uint8_t command[64];
devc = sdi->priv; devc = sdi->priv;
drvc = sdi->driver->context;
if (devc->cur_voltage_range == vrange) if (devc->cur_voltage_range == vrange)
return SR_OK; return SR_OK;
@ -479,51 +483,51 @@ static int upload_fpga_bitstream(const struct sr_dev_inst *sdi,
if (devc->fpga_variant != FPGA_VARIANT_MCUPRO) { if (devc->fpga_variant != FPGA_VARIANT_MCUPRO) {
switch (vrange) { switch (vrange) {
case VOLTAGE_RANGE_18_33_V: case VOLTAGE_RANGE_18_33_V:
filename = FPGA_FIRMWARE_18; name = FPGA_FIRMWARE_18;
break; break;
case VOLTAGE_RANGE_5_V: case VOLTAGE_RANGE_5_V:
filename = FPGA_FIRMWARE_33; name = FPGA_FIRMWARE_33;
break; break;
default: default:
sr_err("Unsupported voltage range."); sr_err("Unsupported voltage range.");
return SR_ERR; return SR_ERR;
} }
sr_info("Uploading FPGA bitstream at %s.", filename); sr_info("Uploading FPGA bitstream '%s'.", name);
if (!(fw = g_fopen(filename, "rb"))) { ret = sr_resource_open(drvc->sr_ctx, &bitstream,
sr_err("Unable to open bitstream file %s for reading: %s.", SR_RESOURCE_FIRMWARE, name);
filename, g_strerror(errno)); if (ret != SR_OK)
return SR_ERR; return ret;
}
buf[0] = COMMAND_FPGA_UPLOAD_INIT; command[0] = COMMAND_FPGA_UPLOAD_INIT;
if ((ret = do_ep1_command(sdi, buf, 1, NULL, 0)) != SR_OK) { if ((ret = do_ep1_command(sdi, command, 1, NULL, 0)) != SR_OK) {
fclose(fw); sr_resource_close(drvc->sr_ctx, &bitstream);
return ret; return ret;
} }
sum = 0;
while (1) { while (1) {
chunksize = fread(buf, 1, sizeof(buf), fw); chunksize = sr_resource_read(drvc->sr_ctx, &bitstream,
&command[2], sizeof(command) - 2);
if (chunksize < 0) {
sr_resource_close(drvc->sr_ctx, &bitstream);
return SR_ERR;
}
if (chunksize == 0) if (chunksize == 0)
break; break;
command[0] = COMMAND_FPGA_UPLOAD_SEND_DATA;
command[1] = chunksize;
for (offset = 0; offset < chunksize; offset += 62) { ret = do_ep1_command(sdi, command, chunksize + 2,
len = (offset + 62 > chunksize ? NULL, 0);
chunksize - offset : 62); if (ret != SR_OK) {
command[0] = COMMAND_FPGA_UPLOAD_SEND_DATA; sr_resource_close(drvc->sr_ctx, &bitstream);
command[1] = len; return ret;
memcpy(command + 2, buf + offset, len);
ret = do_ep1_command(sdi, command, len + 2, NULL, 0);
if (ret != SR_OK) {
fclose(fw);
return ret;
}
} }
sum += chunksize;
sr_info("Uploaded %d bytes.", chunksize);
} }
fclose(fw); sr_resource_close(drvc->sr_ctx, &bitstream);
sr_info("FPGA bitstream upload done."); sr_info("FPGA bitstream upload (%" PRIu64 " bytes) done.", sum);
} }
/* This needs to be called before accessing any FPGA registers. */ /* This needs to be called before accessing any FPGA registers. */

View File

@ -18,8 +18,6 @@
*/ */
#include <config.h> #include <config.h>
#include <errno.h>
#include <sys/stat.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
#include <libsigrok/libsigrok.h> #include <libsigrok/libsigrok.h>
#include "libsigrok-internal.h" #include "libsigrok-internal.h"
@ -29,59 +27,47 @@
#define BITSTREAM_MAX_SIZE (256 * 1024) /* bitstream size limit for safety */ #define BITSTREAM_MAX_SIZE (256 * 1024) /* bitstream size limit for safety */
#define BITSTREAM_HEADER_SIZE 4 /* transfer header size in bytes */ #define BITSTREAM_HEADER_SIZE 4 /* transfer header size in bytes */
/* Load a bitstream file into memory. Returns a newly allocated array /* Load a bitstream file into memory. Returns a newly allocated array
* consisting of a 32-bit length field followed by the bitstream data. * consisting of a 32-bit length field followed by the bitstream data.
*/ */
static unsigned char *load_bitstream_file(const char *filename, int *length_p) static unsigned char *load_bitstream(struct sr_context *ctx,
const char *name, int *length_p)
{ {
struct stat statbuf; struct sr_resource rbf;
FILE *file;
unsigned char *stream; unsigned char *stream;
size_t length, count; ssize_t length, count;
/* Retrieve and validate the file size. */ if (sr_resource_open(ctx, &rbf, SR_RESOURCE_FIRMWARE, name) != SR_OK)
if (stat(filename, &statbuf) < 0) {
sr_err("Failed to access bitstream file: %s.",
g_strerror(errno));
return NULL; return NULL;
}
if (!S_ISREG(statbuf.st_mode)) { if (rbf.size == 0 || rbf.size > BITSTREAM_MAX_SIZE) {
sr_err("Bitstream is not a regular file.");
return NULL;
}
if (statbuf.st_size <= 0 || statbuf.st_size > BITSTREAM_MAX_SIZE) {
sr_err("Refusing to load bitstream of unreasonable size " sr_err("Refusing to load bitstream of unreasonable size "
"(%" PRIu64 " bytes).", (uint64_t)statbuf.st_size); "(%" PRIu64 " bytes).", rbf.size);
sr_resource_close(ctx, &rbf);
return NULL; return NULL;
} }
/* The message length includes the 4-byte header. */ /* The message length includes the 4-byte header. */
length = BITSTREAM_HEADER_SIZE + statbuf.st_size; length = BITSTREAM_HEADER_SIZE + rbf.size;
stream = g_try_malloc(length); stream = g_try_malloc(length);
if (!stream) { if (!stream) {
sr_err("Failed to allocate bitstream buffer."); sr_err("Failed to allocate bitstream buffer.");
return NULL; sr_resource_close(ctx, &rbf);
}
file = g_fopen(filename, "rb");
if (!file) {
sr_err("Failed to open bitstream file: %s.", g_strerror(errno));
g_free(stream);
return NULL; return NULL;
} }
/* Write the message length header. */ /* Write the message length header. */
*(uint32_t *)stream = GUINT32_TO_BE(length); *(uint32_t *)stream = GUINT32_TO_BE(length);
count = fread(stream + BITSTREAM_HEADER_SIZE, count = sr_resource_read(ctx, &rbf, stream + BITSTREAM_HEADER_SIZE,
length - BITSTREAM_HEADER_SIZE, 1, file); length - BITSTREAM_HEADER_SIZE);
if (count != 1) { sr_resource_close(ctx, &rbf);
sr_err("Failed to read bitstream file: %s.", g_strerror(errno));
fclose(file); if (count != length - BITSTREAM_HEADER_SIZE) {
sr_err("Failed to read bitstream '%s'.", name);
g_free(stream); g_free(stream);
return NULL; return NULL;
} }
fclose(file);
*length_p = length; *length_p = length;
return stream; return stream;
@ -90,27 +76,24 @@ static unsigned char *load_bitstream_file(const char *filename, int *length_p)
/* Load a Raw Binary File (.rbf) from the firmware directory and transfer /* Load a Raw Binary File (.rbf) from the firmware directory and transfer
* it to the device. * it to the device.
*/ */
SR_PRIV int lwla_send_bitstream(const struct sr_usb_dev_inst *usb, SR_PRIV int lwla_send_bitstream(struct sr_context *ctx,
const char *basename) const struct sr_usb_dev_inst *usb,
const char *name)
{ {
char *filename;
unsigned char *stream; unsigned char *stream;
int ret; int ret;
int length; int length;
int xfer_len; int xfer_len;
if (!usb || !basename) if (!ctx || !usb || !name)
return SR_ERR_BUG; return SR_ERR_BUG;
filename = g_build_filename(FIRMWARE_DIR, basename, NULL); stream = load_bitstream(ctx, name, &length);
sr_info("Downloading FPGA bitstream at '%s'.", filename);
stream = load_bitstream_file(filename, &length);
g_free(filename);
if (!stream) if (!stream)
return SR_ERR; return SR_ERR;
sr_info("Downloading FPGA bitstream '%s'.", name);
/* Transfer the entire bitstream in one URB. */ /* Transfer the entire bitstream in one URB. */
ret = libusb_bulk_transfer(usb->devhdl, EP_BITSTREAM, ret = libusb_bulk_transfer(usb->devhdl, EP_BITSTREAM,
stream, length, &xfer_len, USB_TIMEOUT_MS); stream, length, &xfer_len, USB_TIMEOUT_MS);

View File

@ -101,8 +101,9 @@ struct regval_pair {
unsigned int val; unsigned int val;
}; };
SR_PRIV int lwla_send_bitstream(const struct sr_usb_dev_inst *usb, SR_PRIV int lwla_send_bitstream(struct sr_context *ctx,
const char *basename); const struct sr_usb_dev_inst *usb,
const char *name);
SR_PRIV int lwla_send_command(const struct sr_usb_dev_inst *usb, SR_PRIV int lwla_send_command(const struct sr_usb_dev_inst *usb,
const uint16_t *command, int cmd_len); const uint16_t *command, int cmd_len);

View File

@ -748,10 +748,12 @@ SR_PRIV int lwla_init_device(const struct sr_dev_inst *sdi)
SR_PRIV int lwla_set_clock_config(const struct sr_dev_inst *sdi) SR_PRIV int lwla_set_clock_config(const struct sr_dev_inst *sdi)
{ {
struct dev_context *devc; struct dev_context *devc;
struct drv_context *drvc;
int ret; int ret;
enum clock_config choice; enum clock_config choice;
devc = sdi->priv; devc = sdi->priv;
drvc = sdi->driver->context;
if (sdi->status == SR_ST_INACTIVE) if (sdi->status == SR_ST_INACTIVE)
choice = CONF_CLOCK_NONE; choice = CONF_CLOCK_NONE;
@ -764,7 +766,8 @@ SR_PRIV int lwla_set_clock_config(const struct sr_dev_inst *sdi)
if (choice != devc->cur_clock_config) { if (choice != devc->cur_clock_config) {
devc->cur_clock_config = CONF_CLOCK_NONE; devc->cur_clock_config = CONF_CLOCK_NONE;
ret = lwla_send_bitstream(sdi->conn, bitstream_map[choice]); ret = lwla_send_bitstream(drvc->sr_ctx, sdi->conn,
bitstream_map[choice]);
if (ret == SR_OK) if (ret == SR_OK)
devc->cur_clock_config = choice; devc->cur_clock_config = choice;
return ret; return ret;

View File

@ -859,10 +859,10 @@ SR_PRIV int serial_timeout(struct sr_serial_dev_inst *port, int num_bytes);
#ifdef HAVE_LIBUSB_1_0 #ifdef HAVE_LIBUSB_1_0
SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear); SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear);
SR_PRIV int ezusb_install_firmware(libusb_device_handle *hdl, SR_PRIV int ezusb_install_firmware(struct sr_context *ctx, libusb_device_handle *hdl,
const char *filename); const char *name);
SR_PRIV int ezusb_upload_firmware(libusb_device *dev, int configuration, SR_PRIV int ezusb_upload_firmware(struct sr_context *ctx, libusb_device *dev,
const char *filename); int configuration, const char *name);
#endif #endif
/*--- hardware/usb.c --------------------------------------------------------*/ /*--- hardware/usb.c --------------------------------------------------------*/