+ struct sr_dev_inst *sdi;
+ struct sr_config *conf;
+ struct sr_serial_dev_inst *serial;
+ struct sr_channel_group *cg;
+ struct sr_channel *ch;
+ struct dev_context *devc;
+ const char *custom_serial_parameters[2];
+ const char **serial_parameters;
+ const char *conn, *serialcomm;
+ GSList *l;
+ struct itech_it8500_cmd_packet *cmd, *response;
+ uint8_t fw_major, fw_minor;
+ const uint8_t *p;
+ char *unit_model, *unit_serial, *unit_barcode;
+ double max_i, max_v, min_v, max_p, max_r, min_r;
+ uint64_t max_samplerate;
+
+ size_t u, i;
+ int ret;
+
+ cmd = g_malloc0(sizeof(*cmd));
+ devc = g_malloc0(sizeof(*devc));
+ sdi = g_malloc0(sizeof(*sdi));
+ if (!cmd || !devc || !sdi)
+ return NULL;
+
+ serial = NULL;
+ response = NULL;
+ unit_model = NULL;
+ unit_serial = NULL;
+
+ /*
+ * Use a list of typical parameters for serial communication by
+ * default. Prefer user specified parameters when available.
+ * Lack of a user specified serial port is fatal.
+ */
+ conn = NULL;
+ serialcomm = NULL;
+ serial_parameters = default_serial_parameters;
+ for (l = options; l; l = l->next) {
+ conf = l->data;
+ switch (conf->key) {
+ case SR_CONF_CONN:
+ conn = g_variant_get_string(conf->data, NULL);
+ break;
+ case SR_CONF_SERIALCOMM:
+ serialcomm = g_variant_get_string(conf->data, NULL);
+ custom_serial_parameters[0] = serialcomm;
+ custom_serial_parameters[1] = NULL;
+ serial_parameters = custom_serial_parameters;
+ break;
+ }
+ }
+ if (!conn)
+ goto error;
+
+ /*
+ * Try different serial parameters in the list
+ * until we get a response (or none at all).
+ */
+ sr_info("Probing serial port: %s", conn);
+ for (i = 0; (serialcomm = serial_parameters[i]); i++) {
+ serial = sr_serial_dev_inst_new(conn, serialcomm);
+ if (serial_open(serial, SERIAL_RDWR) != SR_OK)
+ goto error;
+ serial_flush(serial);
+
+ cmd->address = 0xff; /* Use "broadcast" address. */
+ cmd->command = CMD_GET_MODEL_INFO;
+ if (itech_it8500_send_cmd(serial, cmd, &response) == SR_OK)
+ break;
+
+ serial_close(serial);
+ sr_serial_dev_inst_free(serial);
+ serial = NULL;
+ }
+ if (!serialcomm)
+ goto error;
+
+ /*
+ * The "dense" response string consists of several fields. Grab
+ * integer data before putting terminators in their place to
+ * grab text strings afterwards. Order is important here.
+ */
+ devc->address = response->address;
+ fw_major = response->data[6];
+ fw_minor = response->data[5];
+ response->data[5] = 0;
+ unit_model = g_strdup((const char *)&response->data[0]);
+ response->data[17] = 0;
+ unit_serial = g_strdup((const char *)&response->data[7]);
+ sr_info("Model name: %s (v%x.%02x)", unit_model, fw_major, fw_minor);
+ sr_info("Address: %d", devc->address);
+ sr_info("Serial number: %s", unit_serial);
+
+ sdi->status = SR_ST_INACTIVE;
+ sdi->conn = serial;
+ sdi->inst_type = SR_INST_SERIAL;
+ sdi->driver = &itech_it8500_driver_info;
+ sdi->priv = devc;
+ g_mutex_init(&devc->mutex);
+
+ /*
+ * Calculate maxium "safe" sample rate based on serial connection
+ * speed / bitrate.
+ */
+ max_samplerate = serial->comm_params.bit_rate * 15 / 9600;
+ if (max_samplerate < 15)
+ max_samplerate = 10;
+ if (max_samplerate > MAX_SAMPLE_RATE)
+ max_samplerate = MAX_SAMPLE_RATE;
+ devc->max_sample_rate_idx = 0;
+ for (u = 0; u < ARRAY_SIZE(samplerates); u++) {
+ if (samplerates[u] > max_samplerate)
+ break;
+ devc->max_sample_rate_idx = u;
+ }
+ devc->sample_rate = DEFAULT_SAMPLE_RATE;
+
+ /*
+ * Get full serial number (barcode).
+ */
+ cmd->address = devc->address;
+ cmd->command = CMD_GET_BARCODE_INFO;
+ if (itech_it8500_send_cmd(serial, cmd, &response) == SR_OK) {
+ unit_barcode = g_malloc0(IT8500_DATA_LEN + 1);
+ memcpy(unit_barcode, response->data, IT8500_DATA_LEN);
+ sr_info("Barcode: %s", response->data);
+ g_free(unit_barcode);
+ }