X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fsysclk-lwla%2Fapi.c;h=154d4f9000ee6247fb583f78eee49b93e0febbb5;hb=e57057aee778e723da572a6b5e2bd01526cc7beb;hp=066f914db1016615c9ede8898e192366bdb282c0;hpb=ce3ecb70494b5bcf483607d6ecf0906394623601;p=libsigrok.git diff --git a/src/hardware/sysclk-lwla/api.c b/src/hardware/sysclk-lwla/api.c index 066f914d..154d4f90 100644 --- a/src/hardware/sysclk-lwla/api.c +++ b/src/hardware/sysclk-lwla/api.c @@ -17,11 +17,12 @@ * along with this program. If not, see . */ +#include #include #include #include #include -#include "libsigrok.h" +#include #include "libsigrok-internal.h" #include "protocol.h" @@ -100,10 +101,10 @@ static struct sr_dev_inst *dev_inst_new(void) devc->samplerate = DEFAULT_SAMPLERATE; sdi->priv = devc; - for (i = NUM_CHANNELS; i > 0; --i) { + for (i = 0; i < NUM_CHANNELS; ++i) { /* The LWLA series simply number channels from CH1 to CHxx. */ - g_snprintf(name, sizeof(name), "CH%d", i); - sr_channel_new(sdi, i - 1, SR_CHANNEL_LOGIC, TRUE, name); + g_snprintf(name, sizeof(name), "CH%d", i + 1); + sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, name); } return sdi; @@ -118,7 +119,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) struct sr_config *src; const char *conn; - drvc = di->priv; + drvc = di->context; conn = USB_VID_PID; for (node = options; node != NULL; node = node->next) { @@ -158,7 +159,7 @@ static GSList *dev_list(const struct sr_dev_driver *di) { struct drv_context *drvc; - drvc = di->priv; + drvc = di->context; return drvc->instances; } @@ -186,61 +187,82 @@ static int dev_open(struct sr_dev_inst *sdi) struct sr_usb_dev_inst *usb; int ret; - drvc = di->priv; + drvc = di->context; if (!drvc) { sr_err("Driver was not initialized."); return SR_ERR; } - + if (sdi->status != SR_ST_INACTIVE) { + sr_err("Device already open."); + return SR_ERR; + } usb = sdi->conn; ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb); if (ret != SR_OK) return ret; + /* Set the configuration twice to trigger a lightweight reset. + */ + ret = libusb_set_configuration(usb->devhdl, USB_CONFIG); + if (ret == 0) + ret = libusb_set_configuration(usb->devhdl, USB_CONFIG); + if (ret != 0) { + sr_err("Failed to set USB configuration: %s.", + libusb_error_name(ret)); + sr_usb_close(usb); + return SR_ERR; + } + ret = libusb_claim_interface(usb->devhdl, USB_INTERFACE); if (ret < 0) { sr_err("Failed to claim interface: %s.", libusb_error_name(ret)); + sr_usb_close(usb); return SR_ERR; } - - sdi->status = SR_ST_INITIALIZING; + sdi->status = SR_ST_ACTIVE; ret = lwla_init_device(sdi); - - if (ret == SR_OK) - sdi->status = SR_ST_ACTIVE; - + if (ret != SR_OK) { + sr_usb_close(usb); + sdi->status = SR_ST_INACTIVE; + } return ret; } static int dev_close(struct sr_dev_inst *sdi) { struct sr_usb_dev_inst *usb; + struct dev_context *devc; + int ret; - if (!di->priv) { + if (!di->context) { sr_err("Driver was not initialized."); return SR_ERR; } - usb = sdi->conn; - if (!usb->devhdl) + devc = sdi->priv; + + if (sdi->status == SR_ST_INACTIVE) return SR_OK; + if (devc && devc->acquisition) { + sr_err("Attempt to close device during acquisition."); + return SR_ERR; + } sdi->status = SR_ST_INACTIVE; /* Trigger download of the shutdown bitstream. */ - if (lwla_set_clock_config(sdi) != SR_OK) + ret = lwla_set_clock_config(sdi); + if (ret != SR_OK) sr_err("Unable to shut down device."); libusb_release_interface(usb->devhdl, USB_INTERFACE); - libusb_close(usb->devhdl); + sr_usb_close(usb); - usb->devhdl = NULL; - - return SR_OK; + return ret; } static int cleanup(const struct sr_dev_driver *di) @@ -412,12 +434,84 @@ static int config_channel_set(const struct sr_dev_inst *sdi, return SR_OK; } +static int prepare_trigger_masks(const struct sr_dev_inst *sdi) +{ + uint64_t trigger_mask; + uint64_t trigger_values; + uint64_t trigger_edge_mask; + uint64_t channel_bit; + struct dev_context *devc; + struct sr_trigger *trigger; + struct sr_trigger_stage *stage; + struct sr_trigger_match *match; + const GSList *node; + + devc = sdi->priv; + + trigger = sr_session_trigger_get(sdi->session); + if (!trigger || !trigger->stages) + return SR_OK; + + if (trigger->stages->next) { + sr_err("This device only supports 1 trigger stage."); + return SR_ERR_ARG; + } + stage = trigger->stages->data; + + trigger_mask = 0; + trigger_values = 0; + trigger_edge_mask = 0; + + for (node = stage->matches; node; node = node->next) { + match = node->data; + + if (!match->channel->enabled) + continue; /* ignore disabled channel */ + + channel_bit = (uint64_t)1 << match->channel->index; + trigger_mask |= channel_bit; + + switch (match->match) { + case SR_TRIGGER_ZERO: + break; + case SR_TRIGGER_ONE: + trigger_values |= channel_bit; + break; + case SR_TRIGGER_RISING: + trigger_values |= channel_bit; + /* Fall through for edge mask. */ + case SR_TRIGGER_FALLING: + trigger_edge_mask |= channel_bit; + break; + default: + sr_err("Unsupported trigger match for CH%d.", + match->channel->index + 1); + return SR_ERR_ARG; + } + } + devc->trigger_mask = trigger_mask; + devc->trigger_values = trigger_values; + devc->trigger_edge_mask = trigger_edge_mask; + + return SR_OK; +} + static int config_commit(const struct sr_dev_inst *sdi) { - if (sdi->status != SR_ST_ACTIVE) { - sr_err("Device not ready (status %d).", (int)sdi->status); + struct dev_context *devc; + int rc; + + if (sdi->status != SR_ST_ACTIVE) + return SR_ERR_DEV_CLOSED; + + devc = sdi->priv; + if (devc->acquisition) { + sr_err("Acquisition still in progress?"); return SR_ERR; } + rc = prepare_trigger_masks(sdi); + if (rc != SR_OK) + return rc; return lwla_set_clock_config(sdi); } @@ -482,7 +576,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) return SR_ERR_DEV_CLOSED; devc = sdi->priv; - drvc = di->priv; + drvc = di->context; if (devc->acquisition) { sr_err("Acquisition still in progress?"); @@ -492,13 +586,13 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) if (!acq) return SR_ERR_MALLOC; + devc->cancel_requested = FALSE; devc->stopping_in_progress = FALSE; devc->transfer_error = FALSE; sr_info("Starting acquisition."); devc->acquisition = acq; - lwla_convert_trigger(sdi); ret = lwla_setup_acquisition(sdi); if (ret != SR_OK) { sr_err("Failed to set up acquisition."); @@ -527,15 +621,18 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) { + struct dev_context *devc; + (void)cb_data; + devc = sdi->priv; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; - sr_dbg("Stopping acquisition."); - - sdi->status = SR_ST_STOPPING; - + if (devc->acquisition && !devc->cancel_requested) { + devc->cancel_requested = TRUE; + sr_dbg("Stopping acquisition."); + } return SR_OK; } @@ -557,5 +654,5 @@ SR_PRIV struct sr_dev_driver sysclk_lwla_driver_info = { .dev_close = dev_close, .dev_acquisition_start = dev_acquisition_start, .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, + .context = NULL, };