diff --git a/Makefile.am b/Makefile.am index 0d45f7c4..9ea9788c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -224,7 +224,8 @@ if HW_FX2LAFW libsigrok_la_SOURCES += \ src/hardware/fx2lafw/protocol.h \ src/hardware/fx2lafw/protocol.c \ - src/hardware/fx2lafw/api.c + src/hardware/fx2lafw/api.c \ + src/hardware/fx2lafw/dslogic.c endif if HW_GMC_MH_1X_2X libsigrok_la_SOURCES += \ diff --git a/hardware/fx2lafw/dslogic.c b/hardware/fx2lafw/dslogic.c new file mode 100644 index 00000000..714d4415 --- /dev/null +++ b/hardware/fx2lafw/dslogic.c @@ -0,0 +1,91 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2013 Bert Vermeulen + * Copyright (C) 2012 Joel Holdsworth + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include "protocol.h" + +#define FW_BUFSIZE 4096 +int dslogic_fpga_firmware_upload(struct libusb_device_handle *hdl, + const char *filename) +{ + FILE *fw; + struct stat st; + int chunksize, result, ret; + unsigned char *buf; + int sum, transferred; + + sr_info("Uploading FPGA firmware at %s.", filename); + + if (stat(filename, &st) < 0) { + sr_err("Unable to upload FPGA firmware: %s", strerror(errno)); + return SR_ERR; + } + + /* Tell the device firmware is coming. */ + if ((ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR | + LIBUSB_ENDPOINT_OUT, CMD_DSLOGIC_CONFIG, 0x0000, 0x0000, + NULL, 0, 3000)) < 0) { + sr_err("Failed to upload FPGA firmware: %s.", libusb_error_name(ret)); + return SR_ERR; + } + buf = g_malloc(FW_BUFSIZE); + + if ((fw = g_fopen(filename, "rb")) == NULL) { + sr_err("Unable to open %s for reading: %s.", filename, strerror(errno)); + return SR_ERR; + } + + /* Give the FX2 time to get ready for FPGA firmware upload. */ + g_usleep(10 * 1000); + + sum = 0; + result = SR_OK; + while (1) { + if ((chunksize = fread(buf, 1, FW_BUFSIZE, fw)) == 0) + break; + + if ((ret = libusb_bulk_transfer(hdl, 2 | LIBUSB_ENDPOINT_OUT, + buf, chunksize, &transferred, 1000)) < 0) { + sr_err("Unable to configure FPGA firmware: %s.", + libusb_error_name(ret)); + result = SR_ERR; + break; + } + sum += transferred; + sr_info("Uploaded %d/%d bytes.", sum, st.st_size); + + if (transferred != chunksize) { + sr_err("Short transfer while uploading FPGA firmware."); + result = SR_ERR; + break; + } + } + fclose(fw); + if (result == SR_OK) + sr_info("FPGA firmware upload done."); + + return result; +} + diff --git a/src/hardware/fx2lafw/api.c b/src/hardware/fx2lafw/api.c index 213be9cf..ccd769b2 100644 --- a/src/hardware/fx2lafw/api.c +++ b/src/hardware/fx2lafw/api.c @@ -44,6 +44,20 @@ static const struct fx2lafw_profile supported_fx2[] = { FIRMWARE_DIR "/fx2lafw-cwav-usbeesx.fw", 0, NULL, NULL}, + /* + * DreamSourceLab DSLogic (before FW upload) + */ + { 0x2a0e, 0x0001, "DreamSourceLab", "DSLogic", NULL, + FIRMWARE_DIR "/dreamsourcelab-dslogic-fx2.fw", + DEV_CAPS_16BIT, NULL, NULL}, + + /* + * DreamSourceLab DSLogic (after FW upload) + */ + { 0x2a0e, 0x0001, "DreamSourceLab", "DSLogic", NULL, + FIRMWARE_DIR "/dreamsourcelab-dslogic-fx2.fw", + DEV_CAPS_16BIT, "DreamSourceLab", "DSLogic"}, + /* * Saleae Logic * EE Electronics ESLA100 @@ -123,6 +137,25 @@ static const uint64_t samplerates[] = { SR_MHZ(24), }; +static const uint64_t dslogic_samplerates[] = { + SR_KHZ(10), + SR_KHZ(20), + SR_KHZ(50), + SR_KHZ(100), + SR_KHZ(200), + SR_KHZ(500), + SR_MHZ(1), + SR_MHZ(2), + SR_MHZ(5), + SR_MHZ(10), + SR_MHZ(20), + SR_MHZ(25), + SR_MHZ(50), + SR_MHZ(100), + SR_MHZ(200), + SR_MHZ(400), +}; + SR_PRIV struct sr_dev_driver fx2lafw_driver_info; static struct sr_dev_driver *di = &fx2lafw_driver_info; @@ -141,6 +174,7 @@ static GSList *scan(GSList *options) struct sr_config *src; const struct fx2lafw_profile *prof; GSList *l, *devices, *conn_devices; + gboolean has_firmware; struct libusb_device_descriptor des; libusb_device **devlist; struct libusb_device_handle *hdl; @@ -266,7 +300,21 @@ static GSList *scan(GSList *options) drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); - if (fx2lafw_check_conf_profile(devlist[i])) { + if (strcmp(prof->model, "DSLogic")) { + devc->dslogic = FALSE; + devc->samplerates = samplerates; + devc->num_samplerates = ARRAY_SIZE(samplerates); + has_firmware = match_manuf_prod(devlist[i], + "sigrok", "fx2lafw"); + } else { + devc->dslogic = TRUE; + devc->samplerates = dslogic_samplerates; + devc->num_samplerates = ARRAY_SIZE(dslogic_samplerates); + has_firmware = match_manuf_prod(devlist[i], + "DreamSourceLab", "DSLogic"); + } + + if (has_firmware) { /* Already has the firmware, so fix the new address. */ sr_dbg("Found an fx2lafw device."); sdi->status = SR_ST_INACTIVE; @@ -362,9 +410,15 @@ static int dev_open(struct sr_dev_inst *sdi) return SR_ERR; } + if (devc->dslogic) { + if ((ret = dslogic_fpga_firmware_upload(usb->devhdl, + DSLOGIC_FPGA_FIRMWARE)) != SR_OK) + return ret; + } + if (devc->cur_samplerate == 0) { /* Samplerate hasn't been set; default to the slowest one. */ - devc->cur_samplerate = samplerates[0]; + devc->cur_samplerate = devc->samplerates[0]; } return SR_OK; @@ -499,10 +553,10 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { + struct dev_context *devc; GVariant *gvar; GVariantBuilder gvb; - (void)sdi; (void)cg; switch (key) { @@ -519,9 +573,12 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst * devopts, ARRAY_SIZE(devopts), sizeof(uint32_t)); break; case SR_CONF_SAMPLERATE: + if (!sdi->priv) + return SR_ERR_ARG; + devc = sdi->priv; g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); - gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates, - ARRAY_SIZE(samplerates), sizeof(uint64_t)); + gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), devc->samplerates, + devc->num_samplerates, sizeof(uint64_t)); g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar); *data = g_variant_builder_end(&gvb); break; diff --git a/src/hardware/fx2lafw/protocol.c b/src/hardware/fx2lafw/protocol.c index bc3228f1..7c230f71 100644 --- a/src/hardware/fx2lafw/protocol.c +++ b/src/hardware/fx2lafw/protocol.c @@ -18,22 +18,10 @@ * along with this program. If not, see . */ +#include +#include #include "protocol.h" -/* Protocol commands */ -#define CMD_GET_FW_VERSION 0xb0 -#define CMD_START 0xb1 -#define CMD_GET_REVID_VERSION 0xb2 - -#define CMD_START_FLAGS_WIDE_POS 5 -#define CMD_START_FLAGS_CLK_SRC_POS 6 - -#define CMD_START_FLAGS_SAMPLE_8BIT (0 << CMD_START_FLAGS_WIDE_POS) -#define CMD_START_FLAGS_SAMPLE_16BIT (1 << CMD_START_FLAGS_WIDE_POS) - -#define CMD_START_FLAGS_CLK_30MHZ (0 << CMD_START_FLAGS_CLK_SRC_POS) -#define CMD_START_FLAGS_CLK_48MHZ (1 << CMD_START_FLAGS_CLK_SRC_POS) - #pragma pack(push, 1) struct version_info { @@ -69,13 +57,14 @@ static int command_get_fw_version(libusb_device_handle *devhdl, static int command_get_revid_version(struct sr_dev_inst *sdi, uint8_t *revid) { + struct dev_context *devc = sdi->priv; struct sr_usb_dev_inst *usb = sdi->conn; libusb_device_handle *devhdl = usb->devhdl; - int ret; + int cmd, ret; + cmd = devc->dslogic ? CMD_DSLOGIC_GET_REVID_VERSION : CMD_GET_REVID_VERSION; ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR | - LIBUSB_ENDPOINT_IN, CMD_GET_REVID_VERSION, 0x0000, 0x0000, - revid, 1, 100); + LIBUSB_ENDPOINT_IN, cmd, 0x0000, 0x0000, revid, 1, 100); if (ret < 0) { sr_err("Unable to get REVID: %s.", libusb_error_name(ret)); @@ -149,10 +138,11 @@ SR_PRIV int fx2lafw_command_start_acquisition(const struct sr_dev_inst *sdi) /** * Check the USB configuration to determine if this is an fx2lafw device. * - * @return TRUE if the device's configuration profile match fx2lafw - * configuration, FALSE otherwise. + * @return TRUE if the device's configuration profile matches fx2lafw + * configuration, FALSE otherwise. */ -SR_PRIV gboolean fx2lafw_check_conf_profile(libusb_device *dev) +SR_PRIV gboolean match_manuf_prod(libusb_device *dev, const char *manufacturer, + const char *product) { struct libusb_device_descriptor des; struct libusb_device_handle *hdl; @@ -170,18 +160,17 @@ SR_PRIV gboolean fx2lafw_check_conf_profile(libusb_device *dev) break; if (libusb_get_string_descriptor_ascii(hdl, - des.iManufacturer, strdesc, sizeof(strdesc)) < 0) + des.iManufacturer, strdesc, sizeof(strdesc)) < 0) break; - if (strncmp((const char *)strdesc, "sigrok", 6)) + if (strncmp((const char *)strdesc, manufacturer, 6)) break; if (libusb_get_string_descriptor_ascii(hdl, des.iProduct, strdesc, sizeof(strdesc)) < 0) break; - if (strncmp((const char *)strdesc, "fx2lafw", 7)) + if (strncmp((const char *)strdesc, product, 7)) break; - /* If we made it here, it must be an fx2lafw. */ ret = TRUE; } if (hdl) diff --git a/src/hardware/fx2lafw/protocol.h b/src/hardware/fx2lafw/protocol.h index 48be9930..f8c2f3e2 100644 --- a/src/hardware/fx2lafw/protocol.h +++ b/src/hardware/fx2lafw/protocol.h @@ -51,6 +51,31 @@ #define DEV_CAPS_16BIT (1 << DEV_CAPS_16BIT_POS) +#define DSLOGIC_FPGA_FIRMWARE FIRMWARE_DIR "/dreamsourcelab-dslogic-fpga.fw" + +/* Protocol commands */ +#define CMD_GET_FW_VERSION 0xb0 +#define CMD_START 0xb1 +#define CMD_GET_REVID_VERSION 0xb2 + +#define CMD_START_FLAGS_WIDE_POS 5 +#define CMD_START_FLAGS_CLK_SRC_POS 6 + +#define CMD_START_FLAGS_SAMPLE_8BIT (0 << CMD_START_FLAGS_WIDE_POS) +#define CMD_START_FLAGS_SAMPLE_16BIT (1 << CMD_START_FLAGS_WIDE_POS) + +#define CMD_START_FLAGS_CLK_30MHZ (0 << CMD_START_FLAGS_CLK_SRC_POS) +#define CMD_START_FLAGS_CLK_48MHZ (1 << CMD_START_FLAGS_CLK_SRC_POS) + +/* Modified protocol commands & flags used by DSLogic */ +#define CMD_DSLOGIC_GET_REVID_VERSION 0xb1 +#define CMD_DSLOGIC_START 0xb2 +#define CMD_DSLOGIC_CONFIG 0xb3 +#define CMD_DSLOGIC_SETTING 0xb4 + +#define CMD_START_FLAGS_DSLOGIC_STOP_POS 7 +#define CMD_START_FLAGS_DSLOGIC_STOP (1 << CMD_START_FLAGS_DSLOGIC_STOP_POS) + struct fx2lafw_profile { uint16_t vid; uint16_t pid; @@ -77,6 +102,10 @@ struct dev_context { */ int64_t fw_updated; + /* Supported samplerates */ + const uint64_t *samplerates; + int num_samplerates; + /* Device/capture settings */ uint64_t cur_samplerate; uint64_t limit_samples; @@ -96,10 +125,14 @@ struct dev_context { unsigned int num_transfers; struct libusb_transfer **transfers; struct sr_context *ctx; + + /* Is this a DSLogic? */ + gboolean dslogic; }; SR_PRIV int fx2lafw_command_start_acquisition(const struct sr_dev_inst *sdi); -SR_PRIV gboolean fx2lafw_check_conf_profile(libusb_device *dev); +SR_PRIV gboolean match_manuf_prod(libusb_device *dev, const char *manufacturer, + const char *product); SR_PRIV int fx2lafw_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di); SR_PRIV struct dev_context *fx2lafw_dev_new(void); SR_PRIV void fx2lafw_abort_acquisition(struct dev_context *devc); @@ -108,4 +141,6 @@ SR_PRIV size_t fx2lafw_get_buffer_size(struct dev_context *devc); SR_PRIV unsigned int fx2lafw_get_number_of_transfers(struct dev_context *devc); SR_PRIV unsigned int fx2lafw_get_timeout(struct dev_context *devc); +int dslogic_fpga_firmware_upload(struct libusb_device_handle *hdl, + const char *filename); #endif