X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Ffx2lafw%2Fapi.c;h=255788bfdd0731233ca75e0a9454bb7021ce5de2;hb=204dd31fa1074a78fbe3bf04208776a4a3615a1c;hp=d4643ff760f491e2269602000345f0739c5e6511;hpb=4d7b36a0b59ec1c9d2aad42d1859dbbd7a88ffc6;p=libsigrok.git
diff --git a/src/hardware/fx2lafw/api.c b/src/hardware/fx2lafw/api.c
index d4643ff7..255788bf 100644
--- a/src/hardware/fx2lafw/api.c
+++ b/src/hardware/fx2lafw/api.c
@@ -18,82 +18,123 @@
* along with this program. If not, see .
*/
+#include
#include "protocol.h"
+#include
static const struct fx2lafw_profile supported_fx2[] = {
/*
* CWAV USBee AX
- * EE Electronics ESLA201A
- * ARMFLY AX-Pro
+ * ARMFLY AX-Pro (clone of the CWAV USBee AX)
+ * ARMFLY Mini-Logic (clone of the CWAV USBee AX)
+ * EE Electronics ESLA201A (clone of the CWAV USBee AX)
+ * HT USBee-AxPro (clone of the CWAV USBee AX)
+ * MCU123 USBee AX Pro clone (clone of the CWAV USBee AX)
+ * Noname LHT00SU1 (clone of the CWAV USBee AX)
+ * XZL_Studio AX (clone of the CWAV USBee AX)
*/
{ 0x08a9, 0x0014, "CWAV", "USBee AX", NULL,
- FIRMWARE_DIR "/fx2lafw-cwav-usbeeax.fw",
- 0, NULL, NULL},
+ "fx2lafw-cwav-usbeeax.fw",
+ DEV_CAPS_AX_ANALOG, NULL, NULL},
+
/*
* CWAV USBee DX
- * XZL-Studio DX
+ * HT USBee-DxPro (clone of the CWAV USBee DX), not yet supported!
+ * XZL-Studio DX (clone of the CWAV USBee DX)
*/
{ 0x08a9, 0x0015, "CWAV", "USBee DX", NULL,
- FIRMWARE_DIR "/fx2lafw-cwav-usbeedx.fw",
+ "fx2lafw-cwav-usbeedx.fw",
DEV_CAPS_16BIT, NULL, NULL },
/*
* CWAV USBee SX
*/
{ 0x08a9, 0x0009, "CWAV", "USBee SX", NULL,
- FIRMWARE_DIR "/fx2lafw-cwav-usbeesx.fw",
+ "fx2lafw-cwav-usbeesx.fw",
+ 0, NULL, NULL},
+
+ /*
+ * CWAV USBee ZX
+ */
+ { 0x08a9, 0x0005, "CWAV", "USBee ZX", NULL,
+ "fx2lafw-cwav-usbeezx.fw",
0, NULL, NULL},
/*
* Saleae Logic
- * EE Electronics ESLA100
- * Robomotic MiniLogic
- * Robomotic BugLogic 3
+ * EE Electronics ESLA100 (clone of the Saleae Logic)
+ * Hantek 6022BL in LA mode (clone of the Saleae Logic)
+ * Instrustar ISDS205X in LA mode (clone of the Saleae Logic)
+ * Robomotic MiniLogic (clone of the Saleae Logic)
+ * Robomotic BugLogic 3 (clone of the Saleae Logic)
+ * MCU123 Saleae Logic clone (clone of the Saleae Logic)
*/
{ 0x0925, 0x3881, "Saleae", "Logic", NULL,
- FIRMWARE_DIR "/fx2lafw-saleae-logic.fw",
+ "fx2lafw-saleae-logic.fw",
0, NULL, NULL},
/*
* Default Cypress FX2 without EEPROM, e.g.:
* Lcsoft Mini Board
* Braintechnology USB Interface V2.x
+ * fx2grok-tiny
*/
{ 0x04B4, 0x8613, "Cypress", "FX2", NULL,
- FIRMWARE_DIR "/fx2lafw-cypress-fx2.fw",
+ "fx2lafw-cypress-fx2.fw",
DEV_CAPS_16BIT, NULL, NULL },
/*
* Braintechnology USB-LPS
*/
{ 0x16d0, 0x0498, "Braintechnology", "USB-LPS", NULL,
- FIRMWARE_DIR "/fx2lafw-braintechnology-usb-lps.fw",
+ "fx2lafw-braintechnology-usb-lps.fw",
DEV_CAPS_16BIT, NULL, NULL },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+ /*
+ * sigrok FX2 based 8-channel logic analyzer
+ * fx2grok-flat (before and after renumeration)
+ */
+ { 0x1d50, 0x608c, "sigrok", "FX2 LA (8ch)", NULL,
+ "fx2lafw-sigrok-fx2-8ch.fw",
+ 0, NULL, NULL},
+
+ /*
+ * sigrok FX2 based 16-channel logic analyzer
+ */
+ { 0x1d50, 0x608d, "sigrok", "FX2 LA (16ch)", NULL,
+ "fx2lafw-sigrok-fx2-16ch.fw",
+ DEV_CAPS_16BIT, NULL, NULL },
+
+ /*
+ * usb-c-grok
+ */
+ { 0x1d50, 0x608f, "sigrok", "usb-c-grok", NULL,
+ "fx2lafw-usb-c-grok.fw",
+ 0, NULL, NULL},
+
+ ALL_ZERO
};
-static const int32_t hwopts[] = {
+static const uint32_t scanopts[] = {
SR_CONF_CONN,
+ SR_CONF_PROBE_NAMES,
};
-static const int32_t hwcaps[] = {
+static const uint32_t drvopts[] = {
SR_CONF_LOGIC_ANALYZER,
- SR_CONF_TRIGGER_MATCH,
- SR_CONF_SAMPLERATE,
-
- /* These are really implemented in the driver, not the hardware. */
- SR_CONF_LIMIT_SAMPLES,
- SR_CONF_CONTINUOUS,
};
-static const char *channel_names[] = {
- "0", "1", "2", "3", "4", "5", "6", "7",
- "8", "9", "10", "11", "12", "13", "14", "15",
- NULL,
+static const uint32_t devopts[] = {
+ SR_CONF_CONTINUOUS,
+ SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
+ SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
+ SR_CONF_CONN | SR_CONF_GET,
+ SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
+ SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
+ SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
};
-static const int32_t soft_trigger_matches[] = {
+static const int32_t trigger_matches[] = {
SR_TRIGGER_ZERO,
SR_TRIGGER_ONE,
SR_TRIGGER_RISING,
@@ -118,42 +159,68 @@ static const uint64_t samplerates[] = {
SR_MHZ(12),
SR_MHZ(16),
SR_MHZ(24),
+ SR_MHZ(48),
};
-SR_PRIV struct sr_dev_driver fx2lafw_driver_info;
-static struct sr_dev_driver *di = &fx2lafw_driver_info;
+static const char *channel_names_logic[] = {
+ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+ "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
+};
+
+static const char *channel_names_analog[] = {
+ "A0", "A1", "A2", "A3",
+};
-static int init(struct sr_context *sr_ctx)
+static gboolean is_plausible(const struct libusb_device_descriptor *des)
{
- return std_init(sr_ctx, di, LOG_PREFIX);
+ int i;
+
+ for (i = 0; supported_fx2[i].vid; i++) {
+ if (des->idVendor != supported_fx2[i].vid)
+ continue;
+ if (des->idProduct == supported_fx2[i].pid)
+ return TRUE;
+ }
+
+ return FALSE;
}
-static GSList *scan(GSList *options)
+static GSList *scan(struct sr_dev_driver *di, GSList *options)
{
struct drv_context *drvc;
struct dev_context *devc;
struct sr_dev_inst *sdi;
struct sr_usb_dev_inst *usb;
struct sr_channel *ch;
+ struct sr_channel_group *cg;
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;
- int devcnt, num_logic_channels, ret, i, j;
+ int ret, i;
+ size_t j, num_logic_channels, num_analog_channels;
const char *conn;
- char manufacturer[64], product[64];
+ const char *probe_names;
+ char manufacturer[64], product[64], serial_num[64], connection_id[64];
+ size_t ch_max, ch_idx;
+ const char *channel_name;
- drvc = di->priv;
+ drvc = di->context;
conn = NULL;
+ probe_names = NULL;
for (l = options; l; l = l->next) {
src = l->data;
switch (src->key) {
case SR_CONF_CONN:
conn = g_variant_get_string(src->data, NULL);
break;
+ case SR_CONF_PROBE_NAMES:
+ probe_names = g_variant_get_string(src->data, NULL);
+ break;
}
}
if (conn)
@@ -179,14 +246,17 @@ static GSList *scan(GSList *options)
continue;
}
- if ((ret = libusb_get_device_descriptor( devlist[i], &des)) != 0) {
- sr_warn("Failed to get device descriptor: %s.",
- libusb_error_name(ret));
+ libusb_get_device_descriptor( devlist[i], &des);
+
+ if (!is_plausible(&des))
continue;
- }
- if ((ret = libusb_open(devlist[i], &hdl)) < 0)
+ if ((ret = libusb_open(devlist[i], &hdl)) < 0) {
+ sr_warn("Failed to open potential device with "
+ "VID:PID %04x:%04x: %s.", des.idVendor,
+ des.idProduct, libusb_error_name(ret));
continue;
+ }
if (des.iManufacturer == 0) {
manufacturer[0] = '\0';
@@ -208,48 +278,101 @@ static GSList *scan(GSList *options)
continue;
}
+ if (des.iSerialNumber == 0) {
+ serial_num[0] = '\0';
+ } else if ((ret = libusb_get_string_descriptor_ascii(hdl,
+ des.iSerialNumber, (unsigned char *) serial_num,
+ sizeof(serial_num))) < 0) {
+ sr_warn("Failed to get serial number string descriptor: %s.",
+ libusb_error_name(ret));
+ continue;
+ }
+
libusb_close(hdl);
+ if (usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)) < 0)
+ continue;
+
prof = NULL;
for (j = 0; supported_fx2[j].vid; j++) {
if (des.idVendor == supported_fx2[j].vid &&
des.idProduct == supported_fx2[j].pid &&
(!supported_fx2[j].usb_manufacturer ||
!strcmp(manufacturer, supported_fx2[j].usb_manufacturer)) &&
- (!supported_fx2[j].usb_manufacturer ||
+ (!supported_fx2[j].usb_product ||
!strcmp(product, supported_fx2[j].usb_product))) {
prof = &supported_fx2[j];
break;
}
}
- /* Skip if the device was not found. */
if (!prof)
continue;
- devcnt = g_slist_length(drvc->instances);
- sdi = sr_dev_inst_new(devcnt, SR_ST_INITIALIZING,
- prof->vendor, prof->model, prof->model_version);
- if (!sdi)
- return NULL;
- sdi->driver = di;
+ sdi = g_malloc0(sizeof(struct sr_dev_inst));
+ sdi->status = SR_ST_INITIALIZING;
+ sdi->vendor = g_strdup(prof->vendor);
+ sdi->model = g_strdup(prof->model);
+ sdi->version = g_strdup(prof->model_version);
+ sdi->serial_num = g_strdup(serial_num);
+ sdi->connection_id = g_strdup(connection_id);
+
+ devc = fx2lafw_dev_new();
+ devc->profile = prof;
+ sdi->priv = devc;
+ devices = g_slist_append(devices, sdi);
/* Fill in channellist according to this device's profile. */
num_logic_channels = prof->dev_caps & DEV_CAPS_16BIT ? 16 : 8;
+ if (num_logic_channels > ARRAY_SIZE(channel_names_logic))
+ num_logic_channels = ARRAY_SIZE(channel_names_logic);
+ num_analog_channels = prof->dev_caps & DEV_CAPS_AX_ANALOG ? 1 : 0;
+ if (num_analog_channels > ARRAY_SIZE(channel_names_analog))
+ num_analog_channels = ARRAY_SIZE(channel_names_analog);
+
+ /*
+ * Allow user specs to override the builtin probe names.
+ *
+ * Implementor's note: Because the device's number of
+ * logic channels is not known at compile time, and thus
+ * the location of the analog channel names is not known
+ * at compile time, and the construction of a list with
+ * default names at runtime is not done here, and we
+ * don't want to keep several default lists around, this
+ * implementation only supports to override the names of
+ * logic probes. The use case which motivated the config
+ * key is protocol decoders, which are logic only.
+ */
+ ch_max = num_logic_channels;
+ devc->channel_names = sr_parse_probe_names(probe_names,
+ channel_names_logic, ch_max, ch_max, &ch_max);
+ ch_idx = 0;
+
+ /* Logic channels, all in one channel group. */
+ cg = sr_channel_group_new(sdi, "Logic", NULL);
for (j = 0; j < num_logic_channels; j++) {
- if (!(ch = sr_channel_new(j, SR_CHANNEL_LOGIC, TRUE,
- channel_names[j])))
- return NULL;
- sdi->channels = g_slist_append(sdi->channels, ch);
+ channel_name = devc->channel_names[j];
+ ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_LOGIC,
+ TRUE, channel_name);
+ cg->channels = g_slist_append(cg->channels, ch);
}
- devc = fx2lafw_dev_new();
- devc->profile = prof;
- sdi->priv = devc;
- drvc->instances = g_slist_append(drvc->instances, sdi);
- devices = g_slist_append(devices, sdi);
+ for (j = 0; j < num_analog_channels; j++) {
+ channel_name = channel_names_analog[j];
+ ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG,
+ TRUE, channel_name);
+
+ /* Every analog channel gets its own channel group. */
+ cg = sr_channel_group_new(sdi, channel_name, NULL);
+ cg->channels = g_slist_append(NULL, ch);
+ }
+
+ devc->samplerates = samplerates;
+ devc->num_samplerates = ARRAY_SIZE(samplerates);
+ has_firmware = usb_match_manuf_prod(devlist[i],
+ "sigrok", "fx2lafw");
- if (fx2lafw_check_conf_profile(devlist[i])) {
+ if (has_firmware) {
/* Already has the firmware, so fix the new address. */
sr_dbg("Found an fx2lafw device.");
sdi->status = SR_ST_INACTIVE;
@@ -257,13 +380,17 @@ static GSList *scan(GSList *options)
sdi->conn = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
libusb_get_device_address(devlist[i]), NULL);
} else {
- if (ezusb_upload_firmware(devlist[i], USB_CONFIGURATION,
- prof->firmware) == SR_OK)
+ if (ezusb_upload_firmware(drvc->sr_ctx, devlist[i],
+ USB_CONFIGURATION, prof->firmware) == SR_OK) {
/* Store when this device's FW was updated. */
devc->fw_updated = g_get_monotonic_time();
- else
+ } else {
sr_err("Firmware upload failed for "
- "device %d.", devcnt);
+ "device %d.%d (logical), name %s.",
+ libusb_get_bus_number(devlist[i]),
+ libusb_get_device_address(devlist[i]),
+ prof->firmware);
+ }
sdi->inst_type = SR_INST_USB;
sdi->conn = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
0xff, NULL);
@@ -272,16 +399,22 @@ static GSList *scan(GSList *options)
libusb_free_device_list(devlist, 1);
g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free);
- return devices;
+ return std_scan_complete(di, devices);
+}
+
+static void clear_helper(struct dev_context *devc)
+{
+ g_slist_free(devc->enabled_analog_channels);
}
-static GSList *dev_list(void)
+static int dev_clear(const struct sr_dev_driver *di)
{
- return ((struct drv_context *)(di->priv))->instances;
+ return std_dev_clear_with_callback(di, (std_dev_clear_callback)clear_helper);
}
static int dev_open(struct sr_dev_inst *sdi)
{
+ struct sr_dev_driver *di = sdi->driver;
struct sr_usb_dev_inst *usb;
struct dev_context *devc;
int ret;
@@ -345,7 +478,7 @@ static int dev_open(struct sr_dev_inst *sdi)
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;
@@ -356,41 +489,24 @@ static int dev_close(struct sr_dev_inst *sdi)
struct sr_usb_dev_inst *usb;
usb = sdi->conn;
- if (usb->devhdl == NULL)
- return SR_ERR;
- sr_info("fx2lafw: Closing device %d on %d.%d interface %d.",
- sdi->index, usb->bus, usb->address, USB_INTERFACE);
+ if (!usb->devhdl)
+ return SR_ERR_BUG;
+
+ sr_info("Closing device on %d.%d (logical) / %s (physical) interface %d.",
+ usb->bus, usb->address, sdi->connection_id, USB_INTERFACE);
libusb_release_interface(usb->devhdl, USB_INTERFACE);
libusb_close(usb->devhdl);
usb->devhdl = NULL;
- sdi->status = SR_ST_INACTIVE;
return SR_OK;
}
-static int cleanup(void)
-{
- int ret;
- struct drv_context *drvc;
-
- if (!(drvc = di->priv))
- return SR_OK;
-
- ret = std_dev_clear(di, NULL);
-
- g_free(drvc);
- di->priv = NULL;
-
- return ret;
-}
-
-static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
- const struct sr_channel_group *cg)
+static int config_get(uint32_t key, GVariant **data,
+ const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
{
struct dev_context *devc;
struct sr_usb_dev_inst *usb;
- char str[128];
(void)cg;
@@ -399,7 +515,7 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
devc = sdi->priv;
- switch (id) {
+ switch (key) {
case SR_CONF_CONN:
if (!sdi->conn)
return SR_ERR_ARG;
@@ -408,8 +524,10 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
/* Device still needs to re-enumerate after firmware
* upload, so we don't know its (future) address. */
return SR_ERR;
- snprintf(str, 128, "%d.%d", usb->bus, usb->address);
- *data = g_variant_new_string(str);
+ *data = g_variant_new_printf("%d.%d", usb->bus, usb->address);
+ break;
+ case SR_CONF_LIMIT_FRAMES:
+ *data = g_variant_new_uint64(devc->limit_frames);
break;
case SR_CONF_LIMIT_SAMPLES:
*data = g_variant_new_uint64(devc->limit_samples);
@@ -417,6 +535,9 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
case SR_CONF_SAMPLERATE:
*data = g_variant_new_uint64(devc->cur_samplerate);
break;
+ case SR_CONF_CAPTURE_RATIO:
+ *data = g_variant_new_uint64(devc->capture_ratio);
+ break;
default:
return SR_ERR_NA;
}
@@ -424,78 +545,33 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
return SR_OK;
}
-static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
- const struct sr_channel_group *cg)
+static int config_set(uint32_t key, GVariant *data,
+ const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
{
struct dev_context *devc;
- uint64_t arg;
- unsigned int i;
- int ret;
+ int idx;
(void)cg;
if (!sdi)
return SR_ERR_ARG;
- if (sdi->status != SR_ST_ACTIVE)
- return SR_ERR;
-
devc = sdi->priv;
- ret = SR_OK;
-
- switch (id)
- {
- case SR_CONF_SAMPLERATE:
- arg = g_variant_get_uint64(data);
- for (i = 0; i < ARRAY_SIZE(samplerates); i++) {
- if (samplerates[i] == arg) {
- devc->cur_samplerate = arg;
- break;
- }
- }
- if (i == ARRAY_SIZE(samplerates))
- ret = SR_ERR_ARG;
- break;
- case SR_CONF_LIMIT_SAMPLES:
- devc->limit_samples = g_variant_get_uint64(data);
- break;
- default:
- ret = SR_ERR_NA;
- }
-
- return ret;
-}
-
-static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
- const struct sr_channel_group *cg)
-{
- GVariant *gvar;
- GVariantBuilder gvb;
-
- (void)sdi;
- (void)cg;
-
switch (key) {
- case SR_CONF_SCAN_OPTIONS:
- *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
- hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
+ case SR_CONF_SAMPLERATE:
+ if ((idx = std_u64_idx(data, devc->samplerates, devc->num_samplerates)) < 0)
+ return SR_ERR_ARG;
+ devc->cur_samplerate = devc->samplerates[idx];
break;
- case SR_CONF_DEVICE_OPTIONS:
- *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
- hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
+ case SR_CONF_LIMIT_FRAMES:
+ devc->limit_frames = g_variant_get_uint64(data);
break;
- case SR_CONF_SAMPLERATE:
- 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));
- g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar);
- *data = g_variant_builder_end(&gvb);
+ case SR_CONF_LIMIT_SAMPLES:
+ devc->limit_samples = g_variant_get_uint64(data);
break;
- case SR_CONF_TRIGGER_MATCH:
- *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
- soft_trigger_matches, ARRAY_SIZE(soft_trigger_matches),
- sizeof(int32_t));
+ case SR_CONF_CAPTURE_RATIO:
+ devc->capture_ratio = g_variant_get_uint64(data);
break;
default:
return SR_ERR_NA;
@@ -504,125 +580,57 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
return SR_OK;
}
-static int receive_data(int fd, int revents, void *cb_data)
-{
- struct timeval tv;
- struct drv_context *drvc;
-
- (void)fd;
- (void)revents;
- (void)cb_data;
-
- drvc = di->priv;
-
- tv.tv_sec = tv.tv_usec = 0;
- libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv);
-
- return TRUE;
-}
-
-static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
+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;
- struct drv_context *drvc;
- struct sr_usb_dev_inst *usb;
- struct sr_trigger *trigger;
- struct libusb_transfer *transfer;
- unsigned int i, timeout, num_transfers;
- int ret;
- unsigned char *buf;
- size_t size;
-
- if (sdi->status != SR_ST_ACTIVE)
- return SR_ERR_DEV_CLOSED;
-
- drvc = di->priv;
- devc = sdi->priv;
- usb = sdi->conn;
-
- devc->cb_data = cb_data;
- devc->sent_samples = 0;
- devc->acq_aborted = FALSE;
- devc->empty_transfer_count = 0;
-
- if ((trigger = sr_session_trigger_get(sdi->session))) {
- devc->stl = soft_trigger_logic_new(sdi, trigger);
- devc->trigger_fired = FALSE;
- } else
- devc->trigger_fired = TRUE;
-
- timeout = fx2lafw_get_timeout(devc);
- num_transfers = fx2lafw_get_number_of_transfers(devc);
- size = fx2lafw_get_buffer_size(devc);
- devc->submitted_transfers = 0;
-
- devc->transfers = g_try_malloc0(sizeof(*devc->transfers) * num_transfers);
- if (!devc->transfers) {
- sr_err("USB transfers malloc failed.");
- return SR_ERR_MALLOC;
- }
-
- devc->num_transfers = num_transfers;
- for (i = 0; i < num_transfers; i++) {
- if (!(buf = g_try_malloc(size))) {
- sr_err("USB transfer buffer malloc failed.");
- return SR_ERR_MALLOC;
- }
- transfer = libusb_alloc_transfer(0);
- libusb_fill_bulk_transfer(transfer, usb->devhdl,
- 2 | LIBUSB_ENDPOINT_IN, buf, size,
- fx2lafw_receive_transfer, (void *)sdi, timeout);
- if ((ret = libusb_submit_transfer(transfer)) != 0) {
- sr_err("Failed to submit transfer: %s.",
- libusb_error_name(ret));
- libusb_free_transfer(transfer);
- g_free(buf);
- fx2lafw_abort_acquisition(devc);
- return SR_ERR;
- }
- devc->transfers[i] = transfer;
- devc->submitted_transfers++;
- }
- devc->ctx = drvc->sr_ctx;
+ devc = (sdi) ? sdi->priv : NULL;
- usb_source_add(sdi->session, devc->ctx, timeout, receive_data, NULL);
-
- /* Send header packet to the session bus. */
- std_session_send_df_header(cb_data, LOG_PREFIX);
-
- if ((ret = fx2lafw_command_start_acquisition(sdi)) != SR_OK) {
- fx2lafw_abort_acquisition(devc);
- return ret;
+ switch (key) {
+ case SR_CONF_SCAN_OPTIONS:
+ case SR_CONF_DEVICE_OPTIONS:
+ if (cg)
+ return SR_ERR_NA;
+ return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
+ case SR_CONF_SAMPLERATE:
+ if (!devc)
+ return SR_ERR_NA;
+ *data = std_gvar_samplerates(devc->samplerates, devc->num_samplerates);
+ break;
+ case SR_CONF_TRIGGER_MATCH:
+ *data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
+ break;
+ default:
+ return SR_ERR_NA;
}
return SR_OK;
}
-static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
+static int dev_acquisition_stop(struct sr_dev_inst *sdi)
{
- (void)cb_data;
-
fx2lafw_abort_acquisition(sdi->priv);
return SR_OK;
}
-SR_PRIV struct sr_dev_driver fx2lafw_driver_info = {
+static struct sr_dev_driver fx2lafw_driver_info = {
.name = "fx2lafw",
.longname = "fx2lafw (generic driver for FX2 based LAs)",
.api_version = 1,
- .init = init,
- .cleanup = cleanup,
+ .init = std_init,
+ .cleanup = std_cleanup,
.scan = scan,
- .dev_list = dev_list,
- .dev_clear = NULL,
+ .dev_list = std_dev_list,
+ .dev_clear = dev_clear,
.config_get = config_get,
.config_set = config_set,
.config_list = config_list,
.dev_open = dev_open,
.dev_close = dev_close,
- .dev_acquisition_start = dev_acquisition_start,
+ .dev_acquisition_start = fx2lafw_start_acquisition,
.dev_acquisition_stop = dev_acquisition_stop,
- .priv = NULL,
+ .context = NULL,
};
+SR_REGISTER_DEV_DRIVER(fx2lafw_driver_info);