+ /* Accept user specs for conn= and probe names. */
+ conn = DEFAULT_CONN;
+ probe_names = NULL;
+ 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_PROBE_NAMES:
+ probe_names = g_variant_get_string(src->data, NULL);
+ break;
+ }
+ }
+
+ /*
+ * By default search for all devices with the expected VID/PID.
+ * Accept external specs in either "bus.addr" or "vid.pid" form.
+ * As an alternative accept "sn=..." specs and keep using the
+ * default VID/PID in that case. This should result in maximum
+ * usability while still using a maximum amount of common code.
+ */
+ want_snr = NULL;
+ if (g_str_has_prefix(conn, "sn=")) {
+ want_snr = conn + strlen("sn=");
+ conn = DEFAULT_CONN;
+ sr_info("Searching default %s and serial number %s.",
+ conn, want_snr);
+ }
+ conn_devices = sr_usb_find(ctx->libusb_ctx, conn);
+ if (!conn_devices)
+ return devices;
+
+ /*
+ * Iterate over all devices that have the matching VID/PID.
+ * Skip those which we cannot open. Skip those which don't
+ * match additional serial number conditions. Allocate the
+ * structs for found devices "early", to re-use common code
+ * for communication to the firmware. Release these structs
+ * when identification fails or the device does not match.
+ *
+ * Notice that the scan for devices uses the USB string for
+ * the serial number, and does a weak check (partial match).
+ * This allows users to either use lsusb(8) or gf(1) output
+ * as well as match lazily when only part of the serial nr is
+ * known and becomes unique. Matching against serial nr and
+ * finding multiple devices is as acceptable, just might be a
+ * rare use case. Failure in this stage is silent, there are
+ * legal reasons why we cannot access a device during scan.
+ *
+ * Once a device was found usable, we get its serial number
+ * and version details by means of firmware communication.
+ * To verify that the firmware is operational and that the
+ * protocol works to a minimum degree. And to present data
+ * in --scan output which matches the vendor's gf(1) utility.
+ * This version detail is _not_ checked against conn= specs
+ * because users may specify the longer text string with
+ * more leading digits from lsusb(8) output. That test would
+ * fail when executed against the shorter firmware output.
+ */
+ for (l = conn_devices; l; l = l->next) {
+ usb = l->data;
+
+ ret = sr_usb_open(ctx->libusb_ctx, usb);
+ if (ret != SR_OK)
+ continue;
+
+ skip_device = FALSE;
+ if (want_snr) do {
+ dev = libusb_get_device(usb->devhdl);
+ ret = libusb_get_device_descriptor(dev, &des);
+ if (ret != 0 || !des.iSerialNumber) {
+ skip_device = TRUE;
+ break;
+ }
+ ret = libusb_get_string_descriptor_ascii(usb->devhdl,
+ des.iSerialNumber,
+ (uint8_t *)serno_txt, sizeof(serno_txt));
+ if (ret < 0) {
+ skip_device = TRUE;
+ break;
+ }
+ match = strstr(serno_txt, want_snr);
+ skip_device = !match;
+ sr_dbg("got serno %s, checking %s, match %d",
+ serno_txt, want_snr, !!match);
+ } while (0);
+ if (skip_device) {
+ sr_usb_close(usb);
+ continue;
+ }
+
+ sdi = g_malloc0(sizeof(*sdi));
+ sdi->conn = usb;
+ sdi->inst_type = SR_INST_USB;
+ sdi->status = SR_ST_INACTIVE;
+ devc = g_malloc0(sizeof(*devc));
+ sdi->priv = devc;
+ devc->sdi = sdi;
+ devc->usb_comm_buffer = NULL;
+
+ /*
+ * Get the serial number by way of device communication.
+ * Get the firmware version. Failure is fatal.
+ */
+ ret = greatfet_get_serial_number(sdi);
+ if (ret != SR_OK || !devc->serial_number) {
+ sr_err("Cannot get serial number.");
+ greatfet_free_sdi(sdi);
+ continue;
+ }
+ ret = greatfet_get_version_number(sdi);
+ if (ret != SR_OK || !devc->firmware_version) {
+ sr_err("Cannot get firmware version.");
+ greatfet_free_sdi(sdi);
+ continue;
+ }
+
+ /* Continue filling in sdi and devc. */
+ snprintf(conn_id, sizeof(conn_id), "%u.%u",
+ usb->bus, usb->address);
+ sdi->connection_id = g_strdup(conn_id);
+ sr_usb_close(usb);
+
+ sdi->vendor = g_strdup(VENDOR_TEXT);
+ sdi->model = g_strdup(MODEL_TEXT);
+ sdi->version = g_strdup(devc->firmware_version);
+ sdi->serial_num = g_strdup(devc->serial_number);
+
+ /* Create the "Logic" channel group. */
+ ch_off = 0;
+ ch_max = ARRAY_SIZE(channel_names);
+ devc->channel_names = sr_parse_probe_names(probe_names,
+ channel_names, ch_max, ch_max, &ch_max);
+ devc->channel_count = ch_max;
+ cg = sr_channel_group_new(sdi, "Logic", NULL);
+ for (ch_idx = 0; ch_idx < ch_max; ch_idx++) {
+ enabled = ch_idx < 8;
+ ch = sr_channel_new(sdi, ch_off,
+ SR_CHANNEL_LOGIC, enabled,
+ devc->channel_names[ch_idx]);
+ ch_off++;
+ cg->channels = g_slist_append(cg->channels, ch);
+ }
+
+ sr_sw_limits_init(&devc->sw_limits);
+ devc->samplerate = DEFAULT_SAMPLERATE;
+ devc->acquisition.bandwidth_threshold = BANDWIDTH_THRESHOLD;
+ devc->acquisition.control_interface = CONTROL_INTERFACE;
+ devc->acquisition.samples_interface = SAMPLES_INTERFACE;
+ devc->acquisition.acquisition_state = ACQ_IDLE;
+
+ devices = g_slist_append(devices, sdi);
+ }
+ g_slist_free(conn_devices);