From: Gerhard Sittig Date: Fri, 15 May 2020 11:29:20 +0000 (+0200) Subject: asix-sigma: prepare FTDI open/close for "optional open" X-Git-Url: http://sigrok.org/gitweb/?p=libsigrok.git;a=commitdiff_plain;h=7fe1f91f7550d63ea4a09c0f0e1ce5b88c59c6fb asix-sigma: prepare FTDI open/close for "optional open" Move all of the FTDI connection handling from api.c to protocol.c, and prepare "forced" and "optional" open/close. This allows future driver code to gracefully handle situations where FPGA registers need to get accessed, while the caller may be inside or outside the "opened" period of the session. This is motivated by automatic netlist type and sample rate detection, to avoid the cost of repeated firmware uploads. --- diff --git a/src/hardware/asix-sigma/api.c b/src/hardware/asix-sigma/api.c index 04bc7488..a9fa7718 100644 --- a/src/hardware/asix-sigma/api.c +++ b/src/hardware/asix-sigma/api.c @@ -63,7 +63,7 @@ static const int32_t trigger_matches[] = { static void clear_helper(struct dev_context *devc) { - ftdi_deinit(&devc->ftdic); + (void)sigma_force_close(devc); } static int dev_clear(const struct sr_dev_driver *di) @@ -239,11 +239,13 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) devc->id.serno = serno_num; devc->id.prefix = serno_pre; devc->id.type = dev_type; - devc->samplerate = samplerates[0]; sr_sw_limits_init(&devc->cfg_limits); - devc->firmware_idx = SIGMA_FW_NONE; devc->capture_ratio = 50; devc->use_triggers = 0; + + /* TODO Retrieve some of this state from hardware? */ + devc->firmware_idx = SIGMA_FW_NONE; + devc->samplerate = samplerates[0]; } libusb_free_device_list(devlist, 1); g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free); @@ -254,9 +256,6 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) static int dev_open(struct sr_dev_inst *sdi) { struct dev_context *devc; - long vid, pid; - const char *serno; - int ret; devc = sdi->priv; @@ -264,37 +263,17 @@ static int dev_open(struct sr_dev_inst *sdi) sr_err("OMEGA support is not implemented yet."); return SR_ERR_NA; } - vid = devc->id.vid; - pid = devc->id.pid; - serno = sdi->serial_num; - - ret = ftdi_init(&devc->ftdic); - if (ret < 0) { - sr_err("Cannot initialize FTDI context (%d): %s.", - ret, ftdi_get_error_string(&devc->ftdic)); - return SR_ERR_IO; - } - ret = ftdi_usb_open_desc_index(&devc->ftdic, vid, pid, NULL, serno, 0); - if (ret < 0) { - sr_err("Cannot open device (%d): %s.", - ret, ftdi_get_error_string(&devc->ftdic)); - return SR_ERR_IO; - } - return SR_OK; + return sigma_force_open(sdi); } static int dev_close(struct sr_dev_inst *sdi) { struct dev_context *devc; - int ret; devc = sdi->priv; - ret = ftdi_usb_close(&devc->ftdic); - ftdi_deinit(&devc->ftdic); - - return (ret == 0) ? SR_OK : SR_ERR; + return sigma_force_close(devc); } static int config_get(uint32_t key, GVariant **data, diff --git a/src/hardware/asix-sigma/protocol.c b/src/hardware/asix-sigma/protocol.c index 60970a8d..02b4b658 100644 --- a/src/hardware/asix-sigma/protocol.c +++ b/src/hardware/asix-sigma/protocol.c @@ -58,6 +58,119 @@ static const char *firmware_files[] = { #define SIGMA_FIRMWARE_SIZE_LIMIT (256 * 1024) +static int sigma_ftdi_open(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + int vid, pid; + const char *serno; + int ret; + + devc = sdi->priv; + if (!devc) + return SR_ERR_ARG; + + if (devc->ftdi.is_open) + return SR_OK; + + vid = devc->id.vid; + pid = devc->id.pid; + serno = sdi->serial_num; + if (!vid || !pid || !serno || !*serno) + return SR_ERR_ARG; + + ret = ftdi_init(&devc->ftdi.ctx); + if (ret < 0) { + sr_err("Cannot initialize FTDI context (%d): %s.", + ret, ftdi_get_error_string(&devc->ftdi.ctx)); + return SR_ERR_IO; + } + ret = ftdi_usb_open_desc_index(&devc->ftdi.ctx, + vid, pid, NULL, serno, 0); + if (ret < 0) { + sr_err("Cannot open device (%d): %s.", + ret, ftdi_get_error_string(&devc->ftdi.ctx)); + return SR_ERR_IO; + } + devc->ftdi.is_open = TRUE; + + return SR_OK; +} + +static int sigma_ftdi_close(struct dev_context *devc) +{ + int ret; + + ret = ftdi_usb_close(&devc->ftdi.ctx); + devc->ftdi.is_open = FALSE; + devc->ftdi.must_close = FALSE; + ftdi_deinit(&devc->ftdi.ctx); + + return ret == 0 ? SR_OK : SR_ERR_IO; +} + +SR_PRIV int sigma_check_open(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + int ret; + + if (!sdi) + return SR_ERR_ARG; + devc = sdi->priv; + if (!devc) + return SR_ERR_ARG; + + if (devc->ftdi.is_open) + return SR_OK; + + ret = sigma_ftdi_open(sdi); + if (ret != SR_OK) + return ret; + devc->ftdi.must_close = TRUE; + + return ret; +} + +SR_PRIV int sigma_check_close(struct dev_context *devc) +{ + int ret; + + if (!devc) + return SR_ERR_ARG; + + if (devc->ftdi.must_close) { + ret = sigma_ftdi_close(devc); + if (ret != SR_OK) + return ret; + devc->ftdi.must_close = FALSE; + } + + return SR_OK; +} + +SR_PRIV int sigma_force_open(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + int ret; + + if (!sdi) + return SR_ERR_ARG; + devc = sdi->priv; + if (!devc) + return SR_ERR_ARG; + + ret = sigma_ftdi_open(sdi); + if (ret != SR_OK) + return ret; + devc->ftdi.must_close = FALSE; + + return SR_OK; +} + +SR_PRIV int sigma_force_close(struct dev_context *devc) +{ + return sigma_ftdi_close(devc); +} + /* * BEWARE! Error propagation is important, as are kinds of return values. * @@ -77,10 +190,10 @@ static int sigma_read_raw(struct dev_context *devc, void *buf, size_t size) { int ret; - ret = ftdi_read_data(&devc->ftdic, (unsigned char *)buf, size); + ret = ftdi_read_data(&devc->ftdi.ctx, (unsigned char *)buf, size); if (ret < 0) { sr_err("USB data read failed: %s", - ftdi_get_error_string(&devc->ftdic)); + ftdi_get_error_string(&devc->ftdi.ctx)); } return ret; @@ -90,10 +203,10 @@ static int sigma_write_raw(struct dev_context *devc, const void *buf, size_t siz { int ret; - ret = ftdi_write_data(&devc->ftdic, buf, size); + ret = ftdi_write_data(&devc->ftdi.ctx, buf, size); if (ret < 0) { sr_err("USB data write failed: %s", - ftdi_get_error_string(&devc->ftdic)); + ftdi_get_error_string(&devc->ftdi.ctx)); } else if ((size_t)ret != size) { sr_err("USB data write length mismatch."); } @@ -459,7 +572,7 @@ static int sigma_fpga_init_bitbang_once(struct dev_context *devc) if (ret != SR_OK) return ret; g_usleep(10 * 1000); - ftdi_usb_purge_buffers(&devc->ftdic); + ftdi_usb_purge_buffers(&devc->ftdi.ctx); /* * Wait until the FPGA asserts INIT_B. Check in a maximum number @@ -677,16 +790,16 @@ static int upload_firmware(struct sr_context *ctx, struct dev_context *devc, devc->state.state = SIGMA_CONFIG; /* Set the cable to bitbang mode. */ - ret = ftdi_set_bitmode(&devc->ftdic, BB_PINMASK, BITMODE_BITBANG); + ret = ftdi_set_bitmode(&devc->ftdi.ctx, BB_PINMASK, BITMODE_BITBANG); if (ret < 0) { sr_err("Could not setup cable mode for upload: %s", - ftdi_get_error_string(&devc->ftdic)); + ftdi_get_error_string(&devc->ftdi.ctx)); return SR_ERR; } - ret = ftdi_set_baudrate(&devc->ftdic, BB_BITRATE); + ret = ftdi_set_baudrate(&devc->ftdi.ctx, BB_BITRATE); if (ret < 0) { sr_err("Could not setup bitrate for upload: %s", - ftdi_get_error_string(&devc->ftdic)); + ftdi_get_error_string(&devc->ftdi.ctx)); return SR_ERR; } @@ -714,13 +827,13 @@ static int upload_firmware(struct sr_context *ctx, struct dev_context *devc, } /* Leave bitbang mode and discard pending input data. */ - ret = ftdi_set_bitmode(&devc->ftdic, 0, BITMODE_RESET); + ret = ftdi_set_bitmode(&devc->ftdi.ctx, 0, BITMODE_RESET); if (ret < 0) { sr_err("Could not setup cable mode after upload: %s", - ftdi_get_error_string(&devc->ftdic)); + ftdi_get_error_string(&devc->ftdi.ctx)); return SR_ERR; } - ftdi_usb_purge_buffers(&devc->ftdic); + ftdi_usb_purge_buffers(&devc->ftdi.ctx); while (sigma_read_raw(devc, &pins, sizeof(pins)) > 0) ; diff --git a/src/hardware/asix-sigma/protocol.h b/src/hardware/asix-sigma/protocol.h index d2a190c9..edd15dff 100644 --- a/src/hardware/asix-sigma/protocol.h +++ b/src/hardware/asix-sigma/protocol.h @@ -325,7 +325,10 @@ struct dev_context { uint16_t prefix; enum asix_device_type type; } id; - struct ftdi_context ftdic; + struct { + struct ftdi_context ctx; + gboolean is_open, must_close; + } ftdi; uint64_t samplerate; struct sr_sw_limits cfg_limits; /* Configured limits (user specified). */ struct sr_sw_limits acq_limits; /* Acquisition limits (internal use). */ @@ -343,6 +346,12 @@ struct dev_context { extern SR_PRIV const uint64_t samplerates[]; extern SR_PRIV const size_t samplerates_count; +/* "Automatic" and forced USB connection open/close support. */ +SR_PRIV int sigma_check_open(const struct sr_dev_inst *sdi); +SR_PRIV int sigma_check_close(struct dev_context *devc); +SR_PRIV int sigma_force_open(const struct sr_dev_inst *sdi); +SR_PRIV int sigma_force_close(struct dev_context *devc); + SR_PRIV int sigma_write_register(struct dev_context *devc, uint8_t reg, uint8_t *data, size_t len); SR_PRIV int sigma_set_register(struct dev_context *devc,