WebHID:未找到兼容设备,但设备显示在 Chrome 设备日志中?

WebHID: no compatible device found, but device shows up in Chrome device log?

对于初学者,我使用了 navigator.hid.requestDevice,没有任何过滤器。所以我可以在添加自定义过滤器之前查看哪些设备可用,但我的设备没有显示在 HID 浏览器设备选择器中。

但是,在 chrome 设备日志中 chrome://device-log/ 我可以看到带有 HID 和 USB 标签的设备的 connection/disconnection 事件:

我认为此设备不在阻止列表中,所以我不确定为什么在请求 HID 设备时它没有显示为选项。它也显示在 HID 类别下设备管理器的 Windows 中。

如果我使用 navigator.usb,则设备会在请求时显示,但打开设备时会出现安全错误,这可能意味着它需要 WinUSB 驱动程序。它是一个 HID USB 设备,可与 WebHID 和 WebUSB 之外的库一起使用。

没有显示的任何原因?

编辑 1:

我的设备出现在 chrome://usb-internals/ 中,我看到它说 HID 被 WebUSB 阻止了。还不确定如何解决这个问题。

编辑 2:

使用 Chrome Canary 和 devtools 控制台在使用 HID 设备选择器时提供了一条调试消息:Chooser dialog is not displaying a device blocked by the HID blocklist: vendorId=7992, productId=258, name='TEST', serial=''

查看 HID 黑名单 https://github.com/WICG/webhid/blob/main/blocklist.txt 我仍然没有发现供应商 ID 或产品 ID 有问题。使用页面和用法也不匹配,但是调试消息没有提到这些,所以很难说出确切原因。

编辑 3:

使用 chrome canary 103.0.5034.0 新输出给出了此设备被阻止的原因:

Chooser dialog is not displaying a device blocked by the HID blocklist: vendorId=7992, productId=258, name='TEST', serial='', numberOfCollections=1, numberOfProtectedInputReports=0, numberOfProtectedOutputReports=0, numberOfProtectedFeatureReports=0

如果您在未定义任何过滤器时在浏览器选择器中看到它,则表示此设备确实未列入黑名单。

我建议您从 https://nondebug.github.io/webhid-explorer/ 中获取 vendorIdproductId 等信息。连接设备后,查看 vendorIdproductId 信息并将它们用作过滤器:

const filters = [{ vendorId: 0x1234, productId: 0x5678 }];

const [device] = await navigator.hid.requestDevice({ filters });

更一般地说,https://web.dev/hid/ 是开始使用 WebHID 的重要资源。

编辑 1

如果您在没有任何过滤器时在浏览器选择器中看不到您的设备,但在 about:device-log 中看到 "HID device added",这意味着浏览器选择器正在隐藏它(或者因为它有 top-level collection 和 FIDO 用途或被列入黑名单(https://github.com/WICG/webhid/blob/main/blocklist.txt). See Chromium source code at chrome/browser/ui/hid/hid_chooser_controller.cc:


bool HidChooserController::DisplayDevice(
    const device::mojom::HidDeviceInfo& device) const {
  // Check if `device` has a top-level collection with a FIDO usage. FIDO
  // devices may be displayed if the origin is privileged or the blocklist is
  // disabled.
  const bool has_fido_collection =
      base::Contains(device.collections, device::mojom::kPageFido,
                     [](const auto& c) { return c->usage->usage_page; });
  if (has_fido_collection) {
    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
            switches::kDisableHidBlocklist) ||
        (chooser_context_ &&
         chooser_context_->IsFidoAllowedForOrigin(origin_))) {
      return FilterMatchesAny(device) && !IsExcluded(device);
    }
    VLOG(1) << "Not displaying a FIDO HID device.";
    return false;
  }

  if (!device::HidBlocklist::IsDeviceExcluded(device))
    return FilterMatchesAny(device) && !IsExcluded(device);

  VLOG(1) << "Not displaying a device blocked by the HID blocklist.";
  return false;
}

编辑 2

请注意,如果您的设备没有任何 collection,它可能会被列入黑名单。请参阅 HidBlocklist::IsDeviceExcluded() 源代码。是这样吗?

顺便说一下,可以通过 运行 Chrome 和一个特殊的标志来禁用 HID 黑名单:

$ chrome --disable-hid-blocklist

参见 Run Chromium with flags 页。

我要特别感谢 François Beaufort 为我指明了正确的方向并将调试日志添加到 Chrome Canary 专门用于 WebHID 测试。

问题是 WebHID 看到输入和输出报告的数量均为 0,并阻止设备出现在 HID 设备选择器中。同样,我使用的设备在 Windows 上本机工作,所以这个问题在使用 WebHID.

之前一直隐藏着

确切的问题出在 HID 描述符的输入和输出部分中设备固件的 HID 描述符中。虽然我不能共享整个描述符,但输入和输出部分看起来如下修复:

0x81, 0x00, // INPUT (Data, Var, Abs)
...
...
...
0x91, 0x01, // OUTPUT (Data, Var, Abs)

第一个值 0x810x91 是正确的,但第二个值需要更改为上述值才能工作。修改固件后,设备会立即使用 WebHID 设备选择器显示。现在与 WebHID 的通信工作正常,设备在 Windows 上仍然可以正常工作。