WebUSB .claimInterface 永远不会在 Windows 上返回

问题描述

我一直在开发一个使用 WebUSB 的网站。 WebUSB 库 100% 在 Linux 和 Android 上工作。不幸的是,在 Windows 上, .claimInterface 返回的承诺永远不会返回任何东西。当我为了兴趣再次运行 claimInterface 时,返回的 promise 会返回错误“正在更改状态的操作”,确认第一个 claimInterface 函数仍然很忙。

这个问题只在声明接口1时出现,声明接口0有效,但是这个接口对我没有用。 USB 设备不是标准的(下面演示的描述符),所以它可能与设备配置有关,但由于缺少日志真的很难判断。

我确实尝试查看 chrome://device-log?refresh=1 以获取其他日志,但仅显示插件事件。我还在 chrome://flags/#new-usb-backend 启用了新的 USB 后端,但无济于事。我还尝试使用 --enable-loging --v1 运行 chrome,但似乎唯一相关的错误是:ERROR:device_event_log_impl.cc(211)] [01:32:33.170] USB: usb_device_handle_win.cc:1020 Failed to read descriptor from node connection: A device attached to the system is not functioning. (0x1F)

但是在我什至连接设备之前就记录了这个错误,也讨论了 here,所以我什至不知道它是否相关。

Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            2 Communications
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idvendor           0xXXXX XXX
  idProduct          0xXXXX 
  bcdDevice            1.01
  iManufacturer           1 XXX
  iProduct                2 XXX
  iSerial                 3 XXX
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0030
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x40
      (Missing must-be-set bit!)
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      1 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              32
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      1 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              32
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              32
can't get device qualifier: Resource temporarily unavailable
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0001
  Self Powered

驱动程序安装几乎与之前描述的 WinUSB method 相同。

[Version]
DriverVer=XX/XX/XXXX,X.X.X.X
Signature = "$Windows NT$"
Class = USBDevice
ClassGuid = {88BAE032-5A81-49f0-BC3D-A4FF138216D6}
Provider = %ManufacturerName%
CatalogFile = XXX.cat

[ClassInstall32]
AddReg = ClassInstall_AddReg

[ClassInstall_AddReg]
HKR,%ClassName%
HKR,NoInstallClass,1
HKR,IconPath,%rEG_MULTI_SZ%,"%systemroot%\system32\setupapi.dll,-20"
HKR,LowerlogoVersion,5.2

[WinUSBDeviceClassReg]
HKR,Icon,-20

[Manufacturer]
%ManufacturerName% = Standard,NTx86,NTamd64

[Standard.NTx86]
%DeviceName% = USB_Install,USB\%vendorID%&%ProductID%

[Standard.NTamd64]
%DeviceName% = USB_Install,USB\%vendorID%&%ProductID%

[USB_Install]
Include=winusb.inf
Needs=WINUSB.NT

[USB_Install.Services]
Include=winusb.inf
Needs=WINUSB.NT.Services

[USB_Install.HW]
AddReg=Dev_AddReg

[Dev_AddReg]
HKR,DeviceInterfaceGUIDs,0x10000,{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}

[Strings]
ManufacturerName = "XXX"
ClassName="Universal Serial Bus devices"
DeviceName = "XXX"
vendorID = "VID_XXX"
ProductID = "PID_XXX"

以及我用来测试库的 React 应用程序。

import { useEffect,useState } from 'react';

export default function App() {
  const [devices,setDevices] = useState([]);

  useEffect(function () {
    update()
    navigator.usb.addEventListener("connect",update);
    navigator.usb.addEventListener("disconnect",update);
  },[])

  return (
    <div className="App">
      <button onClick={refresh}>
        <div>Refresh</div>
      </button>
      <button onClick={connect}>
        <div>Connect</div>
      </button>
    </div>
  );


  function connect() {
    let _device = devices[0]
    if (_device) {
      _device
      .open()
      .then(function () {
        _device
          .selectConfiguration(1)
          .then(function () {
            console.log("Connecting to interface")
            _device
              .claimInterface(1)
              .then(function () {
                console.log("Success");
              })
              .catch(console.error);
          })
          .catch(console.error);
      })
      .catch(console.error);
    } 
  }

  function update() {
    navigator.usb.getDevices().then(function (_devices) {
      setDevices(_devices)
    });
  }
  
  function refresh() {
    navigator.usb
      ?.requestDevice({
        filters: [{ vendorId: 0xXXXX,productId: 0xXXXX }],})
      .then(update)
      .catch(console.error);
  }
}

解决方法

我下载了 goole-chrome canary 89.0.4387.0,它解决了问题。所以我想那只是谷歌,在我问这个问题之前就解决了问题。