X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fserial-lcr%2Fapi.c;h=dd8f83081e81cb6e299db02745761594dde89be3;hb=50bc52f3a6102ad687c8abe11cf1e39ab44b1e6a;hp=002fb5bf3293db1142e206fbdee6aa366d745d87;hpb=bf5c4d46f8453f810b6f7615d2c16c9f752f9246;p=libsigrok.git diff --git a/src/hardware/serial-lcr/api.c b/src/hardware/serial-lcr/api.c index 002fb5bf..dd8f8308 100644 --- a/src/hardware/serial-lcr/api.c +++ b/src/hardware/serial-lcr/api.c @@ -85,44 +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; - 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); /* @@ -134,12 +106,18 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) * probed device's expected format. */ serial_flush(serial); - devices = NULL; + if (lcr->packet_request) { + ret = lcr->packet_request(serial); + if (ret < 0) { + sr_err("Failed to request packet: %d.", ret); + 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 @@ -153,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); @@ -163,11 +160,31 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) sdi->priv = devc; devc->lcr_info = lcr; sr_sw_limits_init(&devc->limits); + ch_fmts = lcr->channel_formats; for (ch_idx = 0; ch_idx < lcr->channel_count; ch_idx++) { - snprintf(ch_name, sizeof(ch_name), "P%zu", ch_idx + 1); + fmt = (ch_fmts && ch_fmts[ch_idx]) ? ch_fmts[ch_idx] : "P%zu"; + 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; + + serial_flush(serial); + if (lcr->packet_request) { + ret = lcr->packet_request(serial); + if (ret < 0) { + sr_err("Failed to request packet: %d.", ret); + return ret; + } + } /* * Receive a few more packets (and process them!) to have the @@ -182,11 +199,57 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) len = sizeof(buf); scan_packet_check_setup(sdi); ret = serial_stream_detect(serial, buf, &len, - lcr->packet_size, scan_packet_check_func, 1000); + lcr->packet_size, scan_packet_check_func, 1500); 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); } @@ -323,8 +386,9 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) .dev_acquisition_stop = std_serial_dev_acquisition_stop, \ .context = NULL, \ }, \ - vendor, model, ES51919_CHANNEL_COUNT, \ + vendor, model, ES51919_CHANNEL_COUNT, NULL, \ ES51919_COMM_PARAM, ES51919_PACKET_SIZE, \ + 0, NULL, \ es51919_packet_valid, es51919_packet_parse, \ NULL, NULL, es51919_config_list, \ }).di @@ -335,3 +399,36 @@ SR_REGISTER_DEV_DRIVER_LIST(lcr_es51919_drivers, LCR_ES51919("peaktech-2170", "PeakTech", "2170"), LCR_ES51919("uni-t-ut612", "UNI-T", "UT612"), ); + +#define LCR_VC4080(id, vendor, model) \ + &((struct lcr_info) { \ + { \ + .name = id, \ + .longname = vendor " " model, \ + .api_version = 1, \ + .init = std_init, \ + .cleanup = std_cleanup, \ + .scan = scan, \ + .dev_list = std_dev_list, \ + .dev_clear = std_dev_clear, \ + .config_get = config_get, \ + .config_set = config_set, \ + .config_list = config_list, \ + .dev_open = std_serial_dev_open, \ + .dev_close = std_serial_dev_close, \ + .dev_acquisition_start = dev_acquisition_start, \ + .dev_acquisition_stop = std_serial_dev_acquisition_stop, \ + .context = NULL, \ + }, \ + vendor, model, \ + VC4080_CHANNEL_COUNT, vc4080_channel_formats, \ + VC4080_COMM_PARAM, VC4080_PACKET_SIZE, \ + 500, vc4080_packet_request, \ + vc4080_packet_valid, vc4080_packet_parse, \ + NULL, NULL, vc4080_config_list, \ + }).di + +SR_REGISTER_DEV_DRIVER_LIST(lcr_vc4080_drivers, + LCR_VC4080("peaktech-2165", "PeakTech", "2165"), + LCR_VC4080("voltcraft-4080", "Voltcraft", "4080"), +);