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 += \
--- /dev/null
+/*
+ * 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;
+}
+
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
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;
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;
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;
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;
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) {
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;
* 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 {
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));
/**
* 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;
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)
#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;
*/
int64_t fw_updated;
+ /* Supported samplerates */
+ const uint64_t *samplerates;
+ int num_samplerates;
+
/* Device/capture settings */
uint64_t cur_samplerate;
uint64_t limit_samples;
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);
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