+ /*
+ * The firmware is V-USB based. The USB VID:PID identification
+ * is shared across several projects. Need to inspect the vendor
+ * and product _strings_ to actually identify the device.
+ *
+ * The USB serial number need not be present nor reliable. The
+ * HID report contains a five character string which may serve
+ * as an identification for boards (is said to differ between
+ * boards). The last byte encodes the current relays state.
+ */
+ devs = hid_enumerate(VENDOR_ID, PRODUCT_ID);
+ for (curdev = devs; curdev; curdev = curdev->next) {
+ if (!curdev->vendor_id || !curdev->product_id)
+ continue;
+ if (!curdev->manufacturer_string || !curdev->product_string)
+ continue;
+ if (!*curdev->manufacturer_string || !*curdev->product_string)
+ continue;
+ if (conn && strcmp(curdev->path, conn) != 0) {
+ sr_dbg("skipping %s, conn= mismatch", curdev->path);
+ continue;
+ }
+ sr_dbg("checking %04hx:%04hx, vendor %ls, product %ls.",
+ curdev->vendor_id, curdev->product_id,
+ curdev->manufacturer_string, curdev->product_string);
+
+ /* Check USB details retrieved by enumeration. */
+ ws = curdev->manufacturer_string;
+ if (!ws || !wcslen(ws))
+ continue;
+ snprintf(nonws, sizeof(nonws), "%ls", ws);
+ if (strcmp(nonws, VENDOR_STRING) != 0)
+ continue;
+ ws = curdev->product_string;
+ if (!ws || !wcslen(ws))
+ continue;
+ snprintf(nonws, sizeof(nonws), "%ls", ws);
+ s = nonws;
+ if (!g_str_has_prefix(s, PRODUCT_STRING_PREFIX))
+ continue;
+ s += strlen(PRODUCT_STRING_PREFIX);
+ ret = sr_atoul_base(s, &relay_count, &endp, 10);
+ if (ret != SR_OK || !endp || *endp)
+ continue;
+ sr_info("Found: HID path %s, relay count %lu.",
+ curdev->path, relay_count);
+
+ /* Identify device by communicating to it. */
+ sdi = probe_device(curdev->path, relay_count);
+ if (!sdi) {
+ sr_warn("Failed to communicate to %s.", curdev->path);
+ continue;
+ }
+
+ /* Amend driver instance from USB enumeration details. */
+ sdi->vendor = g_strdup_printf("%ls", curdev->manufacturer_string);
+ sdi->model = g_strdup_printf("%ls", curdev->product_string);
+ sdi->conn = g_strdup(curdev->path);
+ sdi->driver = &dcttech_usbrelay_driver_info;
+ sdi->inst_type = SR_INST_USB;
+
+ devices = g_slist_append(devices, sdi);
+ }
+ hid_free_enumeration(devs);