WebUSB API 将原始数据发送到串行 USB 设备

WebUSB API send raw data to serial USB device

无法定义要发送到我的串行设备(通过 USB 连接)的数据。

我如何获得设备:

function callTransfer(temp1) {
    temp1.controlTransferOut({
        requestType: 'standard',
        recipient: 'device',
        request: 0x07,
        value: 0x08,
        index: 0x04
    })
        .then(() => {
            console.log('sent req'); device.transferIn(1, 32)
        }) // Waiting for 32 bytes of data from endpoint #1.
        .then(result => {
            console.log(result);
        })
        .catch(error => {
            console.log(error);
        });
}

navigator.usb.requestDevice({
    filters: [{}]
}).then((selectedDevice) => {
    device = selectedDevice;
    return device.open()
        .then(() => device.reset())
        .then(() => device.selectConfiguration(1))
        .then(() => device.claimInterface(device.configuration.interfaces[0].interfaceNumber))
        .then(() => {
            callTransfer(device);
        })
});

之后我可以进入 wireshark 并读取值:

recipient = usb.bmRequestType (but not freely definable it is an enum - link see below)
request = usb.setup.bRequest
value = usb.setup.wValue
index = usb.setup.wIndex

但对于我的设备,我还需要设置 usb.LanguageId、usb.DescriptorIndex 等等。 此外,收件人不属于这 4 enums

有没有办法发送原始数据或设置更多属性?

知道有 transferOut 功能,但是当我尝试它时,它只是在最后转储它,这对我的问题不起作用。

尝试更改收件人或请求参数,但它不起作用,或者更糟的是,向 controlTransferOut 对象添加更多参数似乎也没有任何改变。

资源:

  1. WICG
  2. MDN web docs
  3. Google Developers Web Updates
  4. WebUSB API Arduino example code
  5. Google Developers Building a Device for WebUSB

您发送的请求看起来像 SET_DESCRIPTOR 请求。既然你提到了语言 ID,我假设你正在尝试设置一个字符串描述符。设置字符串描述符时,语言 ID 和描述符索引参数应分别设置在 "index" 参数和 "value" 参数的低字节中。 "value" 参数的高字节应设置为 0x03,以指示您正在设置字符串描述符。 "data" 参数应该是一个 ArrayBuffer 包含您要发送到设备的描述符。

来源:https://www.beyondlogic.org/usbnutshell/usb6.shtml

bmRequestType 字段是根据 "recipient" 和 "requestType" 参数以及您调用的是 controlTransferIn() 还是 controlTransferOut() 设置的。这使您可以完全控制该字段。

来源:https://wicg.github.io/webusb/#control-transfer

这可能有助于解释您要完成的任务。我不知道接受 SET_DESCRIPTOR 请求的 USB 串行设备。回答此类问题时,您要连接的设备的文档很有帮助。

这就是我想出的(非常感谢@Reilly Grant)

加载设备

let y;
navigator.usb.requestDevice({
    filters: [{}]
}).then((selectedDevice) => {
    device = selectedDevice;
    return device.open()
        .then(() => device.reset())
        .then(() => device.selectConfiguration(1))
        .then(() => device.claimInterface(device.configuration.interfaces[0].interfaceNumber))
        .then(() => {
            y = device;
        })
});

请求设备名称(仅举个例子)

y.controlTransferIn({
        requestType: 'standard',
        recipient: 'device',
        request: 0x06,
        value: 0x0302,
        index: 0x409
    }, 255)
        .then(result => {
            let decoder = new TextDecoder()
            console.log(decoder.decode(result.data));
            console.log('sent req');
        }).catch(error => {
            console.log(error);
        });

这些资源对我有帮助:

仔细阅读。这需要一点时间,但一切都是值得的!

此外,如果您不知道,可以像这样添加多个十六进制值:0x2341,其中 23 是第一对,41 是第二对。

如果您遇到问题 unloading/unbinding 设备检查其他 post: Unbinding USB Interface to use Chrome Web USB API


在分解 USBControlTransferParameters(controlTransferIn 的对象)之后

要知道要发送每个参数检查"Standard Device Requests"。 在我的示例中,我想获取设备的名称。所以我检查了 bRequest(wireshark 中的信息),它说 "GET_DESCRIPTOR" 你会在它旁边找到 0x06,这是请求参数(再次检查 "Standard Device Requests" Table)。您还可以从 wireshark 获取 requestType 和收件人(您会在 bmRequestType 下找到它,但不要被愚弄这些数字不起作用所以只需检查它显示的 requestType 和收件人并将它们填写为字符串。值是棘手的原因对于此请求,您必须添加 2 个十六进制值(索引和描述符类型 | 按此顺序执行,我认为 beyondlogic 的文档在这里是错误的)。在 wireshark 中,它是 DescriptorIndex 和 bDescriptorType。所以最后你得到了索引,我认为你可以将它留空,意思是 0x00,但它是为了定义语言,所以我添加了它(在 wireshark 中它是 LanguageId)。然后 255 是我从 wireshark 再次获得的长度,但它应该是 return 的长度.


如果使用linux

设置权限

它将发送如下错误消息:访问被拒绝

最后查看此页面:Access USB Devices on the Web

SUBSYSTEM=="usb", ATTR{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"