]> sigrok.org Git - libsigrok.git/commitdiff
asix-sigma: prepare FTDI open/close for "optional open"
authorGerhard Sittig <redacted>
Fri, 15 May 2020 11:29:20 +0000 (13:29 +0200)
committerGerhard Sittig <redacted>
Fri, 29 May 2020 06:06:18 +0000 (08:06 +0200)
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.

src/hardware/asix-sigma/api.c
src/hardware/asix-sigma/protocol.c
src/hardware/asix-sigma/protocol.h

index 04bc74887de3604b51bec147ba9b1ed5abdcddd8..a9fa771846a6495bafd71579d6cca9f5534c34d3 100644 (file)
@@ -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,
index 60970a8d89d498755959ae8575b0d0756bfe6617..02b4b658bd7c2c91a81bf13393f252106f8a519d 100644 (file)
@@ -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)
                ;
 
index d2a190c99ee2bc14dea6c736166b0d9da130bebc..edd15dffdb1f03e65dd8ae3998160a0a85d7cfcc 100644 (file)
@@ -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,