【问题标题】:WebUSB API send raw data to serial USB deviceWebUSB API 将原始数据发送到串行 USB 设备
【发布时间】:2020-06-07 21:14:09
【问题描述】:

无法定义要发送到我的串行设备(通过 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

【问题讨论】:

  • 如果你想在控制台运行。在某些情况下似乎受到限制。

标签: google-chrome serial-port driver webapi webusb


【解决方案1】:

您发送的请求看起来像一个 SET_DESCRIPTOR 请求。由于您提到了语言 ID,我假设您正在尝试设置字符串描述符。设置字符串描述符时,应分别在“index”参数和“value”参数的低字节中设置语言 ID 和描述符索引参数。 “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 串行设备。回答此类问题时,您要连接的设备的文档很有帮助。

【讨论】:

  • 首先感谢您的精彩解释。现在将尝试所有这些。关于你的问题。目前,我正试图从 8devices 的“USB 到 CAN 转换器”中获取一些东西。在等待 ELM327 设备时,我想了解这个 API(这似乎非常具有挑战性)。这是为获取设备名称而发送的内容(来自wireshark):justpaste.it/61qr5
  • 所以看起来像“in”我无法设置任何数据属性。有了 out 我可以,但我不知道如何设置语言 id 之类的东西,因为它都将其转储到“数据片段”。 jsfiddle.net/e8s0haLn(你得把它从jsfiddle复制出来)
【解决方案2】:

这就是我想出的(非常感谢@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 是第二对。

如果您在卸载/解除绑定设备时遇到问题,请查看此其他帖子: Unbinding USB Interface to use Chrome Web USB API


以下是USBControlTransferParameters(controlTransferIn的对象)的细分

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


如果使用 linux,请设置权限

它将发送一条错误消息,例如:拒绝访问

在最后结帐此页面:Access USB Devices on the Web

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

【讨论】:

  • 这是对如何使用 API 发送标准控制传输的一个很好的探索,但请注意,如果您只想要产品、制造商或序列号字符串,这些字符串已经被浏览器读取并可作为字段使用USBDevice 对象。此示例将帮助您处理任何其他字符串描述符。
  • USB 字符串应该是 UTF-16(小端序),所以你应该像这样构造 TextDecoder,除非你知道这个设备不符合规范。 new TextDecoder("utf-16le")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 2019-08-27
  • 1970-01-01
相关资源
最近更新 更多