Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,9 @@ if HW_DREAMSOURCELAB_DSLOGIC
src_libdrivers_la_SOURCES += \
src/hardware/dreamsourcelab-dslogic/protocol.h \
src/hardware/dreamsourcelab-dslogic/protocol.c \
src/hardware/dreamsourcelab-dslogic/protocol_v1.c \
src/hardware/dreamsourcelab-dslogic/protocol_v2.h \
src/hardware/dreamsourcelab-dslogic/protocol_v2.c \
src/hardware/dreamsourcelab-dslogic/api.c
endif
if HW_FLUKE_45
Expand Down
2 changes: 2 additions & 0 deletions contrib/60-libsigrok.rules
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0003", ENV{ID_SIGROK}="1"
ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0002", ENV{ID_SIGROK}="1"
# DreamSourceLab DSLogic Plus
ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0020", ENV{ID_SIGROK}="1"
# DreamSourceLab DSLogic Plus (hardware revision)
ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0034", ENV{ID_SIGROK}="1"
# DreamSourceLab DSLogic Basic
ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0021", ENV{ID_SIGROK}="1"

Expand Down
97 changes: 86 additions & 11 deletions src/hardware/dreamsourcelab-dslogic/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,39 @@
#include <config.h>
#include <math.h>
#include "protocol.h"
#include "protocol_v2.h"

static const struct dslogic_profile supported_device[] = {
/* DreamSourceLab DSLogic */
{ 0x2a0e, 0x0001, "DreamSourceLab", "DSLogic", NULL,
"dreamsourcelab-dslogic-fx2.fw",
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024},
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024,
DSL_PROTO_V1, &dslogic_v1_ops},
/* DreamSourceLab DSCope */
{ 0x2a0e, 0x0002, "DreamSourceLab", "DSCope", NULL,
"dreamsourcelab-dscope-fx2.fw",
0, "DreamSourceLab", "DSCope", 256 * 1024 * 1024},
0, "DreamSourceLab", "DSCope", 256 * 1024 * 1024,
DSL_PROTO_V1, &dslogic_v1_ops},
/* DreamSourceLab DSLogic Pro */
{ 0x2a0e, 0x0003, "DreamSourceLab", "DSLogic Pro", NULL,
"dreamsourcelab-dslogic-pro-fx2.fw",
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024},
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024,
DSL_PROTO_V1, &dslogic_v1_ops},
/* DreamSourceLab DSLogic Plus */
{ 0x2a0e, 0x0020, "DreamSourceLab", "DSLogic Plus", NULL,
"dreamsourcelab-dslogic-plus-fx2.fw",
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024},
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024,
DSL_PROTO_V1, &dslogic_v1_ops},
/* DreamSourceLab DSLogic Plus (hardware revision, PID 0x0034) */
{ 0x2a0e, 0x0034, "DreamSourceLab", "DSLogic Plus", NULL,
"dreamsourcelab-dslogic-plus-fx2.fw",
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024,
DSL_PROTO_V2, &dslogic_v2_ops},
/* DreamSourceLab DSLogic Basic */
{ 0x2a0e, 0x0021, "DreamSourceLab", "DSLogic Basic", NULL,
"dreamsourcelab-dslogic-basic-fx2.fw",
0, "DreamSourceLab", "DSLogic", 256 * 1024},
0, "DreamSourceLab", "DSLogic", 256 * 1024,
DSL_PROTO_V1, &dslogic_v1_ops},

ALL_ZERO
};
Expand All @@ -65,6 +76,8 @@ static const uint32_t devopts[] = {
SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
SR_CONF_EXTERNAL_CLOCK | SR_CONF_GET | SR_CONF_SET,
SR_CONF_CLOCK_EDGE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
SR_CONF_RLE | SR_CONF_GET | SR_CONF_SET,
SR_CONF_FILTER | SR_CONF_GET | SR_CONF_SET,
};

static const int32_t trigger_matches[] = {
Expand Down Expand Up @@ -255,7 +268,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)

devc->samplerates = samplerates;
devc->num_samplerates = ARRAY_SIZE(samplerates);
has_firmware = usb_match_manuf_prod(devlist[i], "DreamSourceLab", "USB-based Instrument");
has_firmware = usb_match_manuf_prod(devlist[i], "DreamSourceLab", "USB-based Instrument")
|| usb_match_manuf_prod(devlist[i], "DreamSourceLab", "USB-based DSL Instrument v2");

if (has_firmware) {
/* Already has the firmware, so fix the new address. */
Expand Down Expand Up @@ -298,6 +312,8 @@ static int dev_open(struct sr_dev_inst *sdi)
devc = sdi->priv;
usb = sdi->conn;

devc->ops = devc->profile->ops;

/*
* If the firmware was recently uploaded, wait up to MAX_RENUM_DELAY_MS
* milliseconds for the FX2 to renumerate.
Expand Down Expand Up @@ -332,7 +348,22 @@ static int dev_open(struct sr_dev_inst *sdi)
return SR_ERR;
}

ret = libusb_claim_interface(usb->devhdl, USB_INTERFACE);
/*
* Retry claim on transient BUSY: after a close/reopen cycle (e.g.
* pulseview "Stop" then "Run" again) the kernel-side endpoint state
* can take a few ms to settle, during which claim returns BUSY even
* though no other process holds the interface.
*/
{
int attempt;
ret = LIBUSB_ERROR_BUSY;
for (attempt = 0; attempt < 10; attempt++) {
ret = libusb_claim_interface(usb->devhdl, USB_INTERFACE);
if (ret != LIBUSB_ERROR_BUSY)
break;
g_usleep(50 * 1000);
}
}
if (ret != 0) {
switch (ret) {
case LIBUSB_ERROR_BUSY:
Expand All @@ -352,8 +383,15 @@ static int dev_open(struct sr_dev_inst *sdi)
}


if ((ret = dslogic_fpga_firmware_upload(sdi)) != SR_OK)
return ret;
if ((ret = devc->ops->fpga_firmware_upload(sdi)) != SR_OK)
goto fail_release;
if ((ret = devc->ops->security_check(sdi)) != SR_OK)
goto fail_release;
/* DSView writes VTH_ADDR right after dsl_dev_open returns
* (dslogic.c). Without this, the FPGA threshold DAC
* is uninitialised and subsequent arm-sequence status polls may
* stall. Use a sensible default (1.0V on 3.3V logic). */
(void)devc->ops->set_voltage_threshold(sdi, 1.0, 1.0);

if (devc->cur_samplerate == 0) {
/* Samplerate hasn't been set; default to the slowest one. */
Expand All @@ -362,10 +400,23 @@ static int dev_open(struct sr_dev_inst *sdi)

if (devc->cur_threshold == 0.0) {
devc->cur_threshold = thresholds[1][0];
return dslogic_set_voltage_threshold(sdi, devc->cur_threshold);
return devc->ops->set_voltage_threshold(sdi, devc->cur_threshold, devc->cur_threshold);
}

return SR_OK;

fail_release:
/*
* dev_open failed AFTER we claimed the interface. libsigrok will not
* call dev_close on a dev_open that returned non-OK, so we must
* unwind the claim ourselves. Without this, the next dev_open's
* libusb_claim_interface returns LIBUSB_ERROR_BUSY (the kernel
* thinks the interface is still in use by us).
*/
libusb_release_interface(usb->devhdl, USB_INTERFACE);
libusb_close(usb->devhdl);
usb->devhdl = NULL;
return ret;
}

static int dev_close(struct sr_dev_inst *sdi)
Expand Down Expand Up @@ -434,6 +485,12 @@ static int config_get(uint32_t key, GVariant **data,
case SR_CONF_EXTERNAL_CLOCK:
*data = g_variant_new_boolean(devc->external_clock);
break;
case SR_CONF_RLE:
*data = g_variant_new_boolean(devc->rle_mode);
break;
case SR_CONF_FILTER:
*data = g_variant_new_boolean(devc->filter);
break;
case SR_CONF_CONTINUOUS:
*data = g_variant_new_boolean(devc->continuous_mode);
break;
Expand Down Expand Up @@ -484,14 +541,32 @@ static int config_set(uint32_t key, GVariant *data,
return dslogic_fpga_firmware_upload(sdi);
} else {
g_variant_get(data, "(dd)", &low, &high);
return dslogic_set_voltage_threshold(sdi, (low + high) / 2.0);
return devc->ops->set_voltage_threshold(sdi, low, high);
}
break;
case SR_CONF_EXTERNAL_CLOCK:
devc->external_clock = g_variant_get_boolean(data);
break;
case SR_CONF_RLE:
devc->rle_mode = g_variant_get_boolean(data);
break;
case SR_CONF_FILTER:
devc->filter = g_variant_get_boolean(data);
break;
case SR_CONF_CONTINUOUS:
devc->continuous_mode = g_variant_get_boolean(data);
if (devc->profile->protocol_version == DSL_PROTO_V2) {
/* Re-pick the channel mode for the new stream/buffer
* choice; uses current samplerate + enabled-channel
* count as hints. */
uint16_t m = enabled_channel_mask(sdi);
unsigned int hi = 0, i;
for (i = 0; i < 16; i++)
if (m & (1U << i)) hi = i + 1;
devc->ch_mode_id = dslogic_plus_auto_pick_mode_id(
devc->cur_samplerate, devc->continuous_mode,
hi ? hi : 1);
}
break;
case SR_CONF_CLOCK_EDGE:
if ((idx = std_str_idx(data, ARRAY_AND_SIZE(signal_edges))) < 0)
Expand Down
Loading