问题描述
我一直在开发一个使用 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,它解决了问题。所以我想那只是谷歌,在我问这个问题之前就解决了问题。