]> sigrok.org Git - libsigrok.git/commitdiff
serial-lcr: move probe, dev inst creation, data read out of scan
authorGerhard Sittig <redacted>
Sun, 16 Jun 2019 12:51:16 +0000 (14:51 +0200)
committerUwe Hermann <redacted>
Wed, 31 Jul 2019 13:23:03 +0000 (15:23 +0200)
Move the initial device probe (LCR packet validity check), the creation
of the device instance after successful probe, and the subsequent packet
inspection after resource allocation out of the scan routine. This shall
improve readability of the serial-lcr driver's probe logic, and reduces
diffs when handling of multiple connections gets added later.

Add a developer comment, the serial-lcr driver needs to handle multiple
connections when the conn= spec is ambiguous (multiple cables of the
same type, with the same VID:PID).

src/hardware/serial-lcr/api.c

index 0919ae8891f71e580b7b74287adcc4f50edc4311..50b3f49361ef3db95334f62d6c8ca65796e87e77 100644 (file)
@@ -85,46 +85,16 @@ static gboolean scan_packet_check_func(const uint8_t *buf)
        return TRUE;
 }
 
-static GSList *scan(struct sr_dev_driver *di, GSList *options)
+static int scan_lcr_port(const struct lcr_info *lcr,
+       const char *conn, struct sr_serial_dev_inst *serial)
 {
-       struct lcr_info *lcr;
-       struct sr_config *src;
-       GSList *l, *devices;
-       const char *conn, *serialcomm;
-       struct sr_serial_dev_inst *serial;
+       size_t len;
        uint8_t buf[128];
-       size_t len, dropped;
        int ret;
-       struct sr_dev_inst *sdi;
-       struct dev_context *devc;
-       size_t ch_idx;
-       const char **ch_fmts;
-       const char *fmt;
-       char ch_name[8];
-
-       lcr = (struct lcr_info *)di;
-
-       /* Get serial port name and communication parameters. */
-       conn = NULL;
-       serialcomm = lcr->comm;
-       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_SERIALCOMM:
-                       serialcomm = g_variant_get_string(src->data, NULL);
-                       break;
-               }
-       }
-       if (!conn)
-               return NULL;
+       size_t dropped;
 
-       /* Open the serial port. */
-       serial = sr_serial_dev_inst_new(conn, serialcomm);
        if (serial_open(serial, SERIAL_RDWR) != SR_OK)
-               return NULL;
+               return SR_ERR_IO;
        sr_info("Probing serial port %s.", conn);
 
        /*
@@ -135,20 +105,19 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
         * send data periodically. So we check if the packets match the
         * probed device's expected format.
         */
-       devices = NULL;
        serial_flush(serial);
        if (lcr->packet_request) {
                ret = lcr->packet_request(serial);
                if (ret < 0) {
                        sr_err("Failed to request packet: %d.", ret);
-                       goto scan_cleanup;
+                       goto scan_port_cleanup;
                }
        }
        len = sizeof(buf);
        ret = serial_stream_detect(serial, buf, &len,
                lcr->packet_size, lcr->packet_valid, 3000);
        if (ret != SR_OK)
-               goto scan_cleanup;
+               goto scan_port_cleanup;
 
        /*
         * If the packets were found to match after more than two packets
@@ -162,6 +131,25 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 
        /* Create a device instance for the found device. */
        sr_info("Found %s %s device on port %s.", lcr->vendor, lcr->model, conn);
+
+scan_port_cleanup:
+       /* Keep serial port open if probe succeeded. */
+       if (ret != SR_OK)
+               serial_close(serial);
+
+       return ret;
+}
+
+static struct sr_dev_inst *create_lcr_sdi(struct lcr_info *lcr,
+       struct sr_serial_dev_inst *serial)
+{
+       struct sr_dev_inst *sdi;
+       struct dev_context *devc;
+       size_t ch_idx;
+       const char **ch_fmts;
+       const char *fmt;
+       char ch_name[8];
+
        sdi = g_malloc0(sizeof(*sdi));
        sdi->status = SR_ST_INACTIVE;
        sdi->vendor = g_strdup(lcr->vendor);
@@ -178,7 +166,16 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
                snprintf(ch_name, sizeof(ch_name), fmt, ch_idx + 1);
                sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, ch_name);
        }
-       devices = g_slist_append(devices, sdi);
+
+       return sdi;
+}
+
+static int read_lcr_port(struct sr_dev_inst *sdi,
+       const struct lcr_info *lcr, struct sr_serial_dev_inst *serial)
+{
+       size_t len;
+       uint8_t buf[128];
+       int ret;
 
        /*
         * Receive a few more packets (and process them!) to have the
@@ -196,8 +193,54 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
                lcr->packet_size, scan_packet_check_func, 1000);
        scan_packet_check_setup(NULL);
 
-scan_cleanup:
-       serial_close(serial);
+       return ret;
+}
+
+static GSList *scan(struct sr_dev_driver *di, GSList *options)
+{
+       struct lcr_info *lcr;
+       struct sr_config *src;
+       GSList *l, *devices;
+       const char *conn, *serialcomm;
+       struct sr_serial_dev_inst *serial;
+       int ret;
+       struct sr_dev_inst *sdi;
+
+       lcr = (struct lcr_info *)di;
+
+       /* Get serial port name and communication parameters. */
+       conn = NULL;
+       serialcomm = lcr->comm;
+       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_SERIALCOMM:
+                       serialcomm = g_variant_get_string(src->data, NULL);
+                       break;
+               }
+       }
+       if (!conn)
+               return NULL;
+
+       devices = NULL;
+       /* TODO Handle ambiguous conn= specs, see serial-dmm. */
+
+       /* Open the serial port, check data packets. */
+       serial = sr_serial_dev_inst_new(conn, serialcomm);
+       ret = scan_lcr_port(lcr, conn, serial);
+       if (ret != SR_OK) {
+               /* Probe failed, release 'serial'. */
+               sr_serial_dev_inst_free(serial);
+       } else {
+               /* Create and return device instance, keep 'serial' alive. */
+               sdi = create_lcr_sdi(lcr, serial);
+               devices = g_slist_append(devices, sdi);
+               (void)read_lcr_port(sdi, lcr, serial);
+               serial_close(serial);
+       }
 
        return std_scan_complete(di, devices);
 }