+ /* Open the serial port. */
+ serial = sr_serial_dev_inst_new(conn, serialcomm);
+ if (serial_open(serial, SERIAL_RDWR) != SR_OK)
+ return NULL;
+ sr_info("Probing serial port %s.", conn);
+
+ /*
+ * See if we can detect a device of specified type.
+ *
+ * No supported device provides a means to "identify" yet. No
+ * supported device requires "packet request" yet. They all just
+ * send data periodically. So we check if the packets match the
+ * probed device's expected format.
+ */
+ serial_flush(serial);
+ devices = NULL;
+ len = sizeof(buf);
+ ret = serial_stream_detect(serial, buf, &len,
+ lcr->packet_size, lcr->packet_valid, 3000);
+ if (ret != SR_OK)
+ goto scan_cleanup;
+
+ /*
+ * If the packets were found to match after more than two packets
+ * got dropped, something is wrong. This is worth warning about,
+ * but isn't fatal. The dropped bytes might be due to nonstandard
+ * cables that ship with some devices.
+ */
+ dropped = len - lcr->packet_size;
+ if (dropped > 2 * lcr->packet_size)
+ sr_warn("Had to drop unexpected amounts of data.");
+
+ /* Create a device instance for the found device. */
+ sr_info("Found %s %s device on port %s.", lcr->vendor, lcr->model, conn);
+ sdi = g_malloc0(sizeof(*sdi));
+ sdi->status = SR_ST_INACTIVE;
+ sdi->vendor = g_strdup(lcr->vendor);
+ sdi->model = g_strdup(lcr->model);
+ sdi->inst_type = SR_INST_SERIAL;
+ sdi->conn = serial;
+ devc = g_malloc0(sizeof(*devc));
+ sdi->priv = devc;
+ devc->lcr_info = lcr;
+ sr_sw_limits_init(&devc->limits);
+ for (ch_idx = 0; ch_idx < lcr->channel_count; ch_idx++) {
+ snprintf(ch_name, sizeof(ch_name), "P%zu", ch_idx + 1);
+ sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, ch_name);
+ }
+ devices = g_slist_append(devices, sdi);
+
+ /*
+ * Receive a few more packets (and process them!) to have the
+ * current output frequency and circuit model parameter values
+ * detected. The above "stream detect" phase only synchronized
+ * to the packets by checking their validity, but it cannot
+ * provide details. This phase here runs a modified "checker"
+ * routine which also extracts details from LCR packets after
+ * the device got detected and parameter storage was prepared.
+ */
+ sr_info("Retrieving current acquisition parameters.");
+ len = sizeof(buf);
+ scan_packet_check_setup(sdi);
+ ret = serial_stream_detect(serial, buf, &len,
+ lcr->packet_size, scan_packet_check_func, 1000);
+ scan_packet_check_setup(NULL);
+
+scan_cleanup:
+ serial_close(serial);
+
+ return std_scan_complete(di, devices);
+}
+
+static int config_get(uint32_t key, GVariant **data,
+ const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
+{
+ struct dev_context *devc;
+ const struct lcr_info *lcr;
+
+ if (!sdi)
+ return SR_ERR_ARG;
+ devc = sdi->priv;
+
+ switch (key) {
+ case SR_CONF_LIMIT_FRAMES:
+ case SR_CONF_LIMIT_MSEC:
+ return sr_sw_limits_config_get(&devc->limits, key, data);
+ case SR_CONF_OUTPUT_FREQUENCY:
+ *data = g_variant_new_double(devc->output_freq);
+ return SR_OK;
+ case SR_CONF_EQUIV_CIRCUIT_MODEL:
+ if (!devc->circuit_model)
+ return SR_ERR_NA;
+ *data = g_variant_new_string(devc->circuit_model);
+ return SR_OK;
+ default:
+ lcr = devc->lcr_info;
+ if (!lcr)
+ return SR_ERR_NA;
+ if (!lcr->config_get)
+ return SR_ERR_NA;
+ return lcr->config_get(key, data, sdi, cg);
+ }
+ /* UNREACH */
+}
+
+static int config_set(uint32_t key, GVariant *data,
+ const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
+{
+ struct dev_context *devc;
+ const struct lcr_info *lcr;
+
+ if (!sdi)
+ return SR_ERR_ARG;
+ devc = sdi->priv;
+
+ switch (key) {
+ case SR_CONF_LIMIT_FRAMES:
+ case SR_CONF_LIMIT_MSEC:
+ return sr_sw_limits_config_set(&devc->limits, key, data);
+ default:
+ lcr = devc->lcr_info;
+ if (!lcr)
+ return SR_ERR_NA;
+ if (!lcr->config_set)
+ return SR_ERR_NA;
+ return lcr->config_set(key, data, sdi, cg);
+ }
+ /* UNREACH */
+}
+
+static int config_list(uint32_t key, GVariant **data,
+ const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
+{
+ struct dev_context *devc;
+ const struct lcr_info *lcr;
+
+ switch (key) {
+ case SR_CONF_SCAN_OPTIONS:
+ case SR_CONF_DEVICE_OPTIONS:
+ return STD_CONFIG_LIST(key, data, sdi, cg,
+ scanopts, drvopts, devopts);
+ default:
+ break;
+ }
+
+ if (!sdi)
+ return SR_ERR_ARG;
+ devc = sdi->priv;
+ switch (key) {
+ default:
+ lcr = devc->lcr_info;
+ if (!lcr || !lcr->config_list)
+ return SR_ERR_NA;
+ return lcr->config_list(key, data, sdi, cg);
+ }
+ /* UNREACH */
+}
+
+static int dev_acquisition_start(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ struct sr_serial_dev_inst *serial;
+
+ devc = sdi->priv;
+
+ /*
+ * Clear values that were gathered during scan or in a previous
+ * acquisition, so that this acquisition's data feed immediately
+ * starts with meta packets before first measurement values, and
+ * also communicates subsequent parameter changes.
+ */
+ devc->output_freq = 0;
+ devc->circuit_model = NULL;
+
+ sr_sw_limits_acquisition_start(&devc->limits);
+ std_session_send_df_header(sdi);
+
+ serial = sdi->conn;
+ serial_source_add(sdi->session, serial, G_IO_IN, 50,
+ lcr_receive_data, (void *)sdi);
+
+ return SR_OK;