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);
/*
* 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
/* 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);
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
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);
}