+ conn = NULL;
+ (void)sr_serial_extract_options(options, &conn, NULL);
+ conn_devices = NULL;
+ if (conn)
+ conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn);
+
+ libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist);
+ for (i = 0; devlist[i]; i++) {
+ bus = libusb_get_bus_number(devlist[i]);
+ addr = libusb_get_device_address(devlist[i]);
+ if (conn) {
+ /* Check if the connection matches the user spec. */
+ for (l = conn_devices; l; l = l->next) {
+ usb = l->data;
+ if (usb->bus == bus && usb->address == addr)
+ break;
+ }
+ if (!l)
+ continue;
+ }
+
+ libusb_get_device_descriptor(devlist[i], &des);
+
+ /*
+ * In theory we'd accept any USB device with a matching
+ * product string. In practice the enumeration takes a
+ * shortcut and only inspects devices when their USB VID
+ * matches the expectation. This avoids access to flaky
+ * devices which are unrelated to measurement purposes
+ * yet cause trouble when accessed including segfaults,
+ * while libusb won't transparently handle their flaws.
+ *
+ * See https://sigrok.org/bugzilla/show_bug.cgi?id=1115
+ * and https://github.com/sigrokproject/libsigrok/pull/166
+ * for a discussion.
+ */
+ if (des.idVendor != SCAN_EXPECTED_VENDOR)
+ continue;
+
+ if ((ret = libusb_open(devlist[i], &hdl)) < 0)
+ continue;
+
+ if (des.iProduct == 0) {
+ product[0] = '\0';
+ } else if ((ret = libusb_get_string_descriptor_ascii(hdl,
+ des.iProduct, (unsigned char *)product,
+ sizeof(product))) < 0) {
+ sr_warn("Failed to get product string descriptor: %s.",
+ libusb_error_name(ret));
+ continue;
+ }
+
+ if (des.iSerialNumber == 0) {
+ serial_num[0] = '\0';
+ } else if ((ret = libusb_get_string_descriptor_ascii(hdl,
+ des.iSerialNumber, (unsigned char *)serial_num,
+ sizeof(serial_num))) < 0) {
+ sr_warn("Failed to get serial number string descriptor: %s.",
+ libusb_error_name(ret));
+ continue;
+ }
+
+ libusb_close(hdl);
+
+ if (usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)) < 0)
+ continue;
+
+ if (!strcmp(product, "ChronoVu LA8"))
+ model = 0;
+ else if (!strcmp(product, "ChronoVu LA16"))
+ model = 1;
+ else
+ continue; /* Unknown iProduct string, ignore. */