]> sigrok.org Git - libsigrok.git/commitdiff
fx2lafw: scan/firmware support for DSLogic.
authorBert Vermeulen <redacted>
Sat, 3 May 2014 16:37:00 +0000 (09:37 -0700)
committerUwe Hermann <redacted>
Thu, 19 Mar 2015 17:25:55 +0000 (18:25 +0100)
Makefile.am
hardware/fx2lafw/dslogic.c [new file with mode: 0644]
src/hardware/fx2lafw/api.c
src/hardware/fx2lafw/protocol.c
src/hardware/fx2lafw/protocol.h

index 0d45f7c45638fdce57f8aae49ae7375a6276b43e..9ea9788c34177cfd9f53eb6aca35b8ef7ea5c588 100644 (file)
@@ -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 (file)
index 0000000..714d441
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#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;
+}
+
index 213be9cf2d72488a9a5d3a216e086829c3dfc2b6..ccd769b2162e0cb43406924c90f7d59d57bf979d 100644 (file)
@@ -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;
index bc3228f12d23fff44b4013da873011c4d4c5932c..7c230f71144560630ff91bf22f9586f7fd9fdda0 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <glib.h>
+#include <glib/gstdio.h>
 #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)
index 48be99309f13ddafa2805ca52a8359e7de0210b6..f8c2f3e28046dabd8a30fb39fec0602cc17d3c36 100644 (file)
 
 #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