如何发送 USB 控制传输(UWP 应用)
本文演示了:
- 如何设置 USB 设置数据包的格式
- 如何从应用启动 USB 控制传输
重要的 API
与 USB 设备通信的应用通常发送多个控制传输请求。 这些请求获取有关设备的信息,并发送硬件供应商定义的控制命令。 在本主题中,你将了解控制传输以及如何在 UWP 应用中格式化和发送它们。
控制传输可以读取或写入配置信息,或者执行硬件供应商定义的特定于设备的函数。 如果传输执行写入操作,则是 OUT 传输;如果执行读取操作,则是 IN 传输。 无论方向如何,主机系统上的软件(如 UWP 应用)始终生成并发起控制传输请求。 有时,应用可以发起读取或写入数据的控制传输。 在这种情况下,可能需要发送额外的缓冲区。在这种情况下,
为了适应所有类型的控制传输,Windows.Devices.Usb 提供了以下方法:
- SendControlOutTransferAsync (UsbSetupPacket)
- SendControlInTransferAsync (UsbSetupPacket)
- SendControlOutTransferAsync(UsbSetupPacket,IBuffer)
- SendControlInTransferAsync(UsbSetupPacket,IBuffer)
USB 控制传输还用于获取描述符数据或发送标准命令。 但是,建议你通过调用 Windows.Devices.Usb 提供的特定方法而不是手动生成控制传输来发送这些类型的请求。 例如,若要选择备用设置,请调用 SelectSettingAsync,而不是调用 SendControlOutTransferAsync (UsbSetupPacket)。
不支持某些类型的标准请求的控制传输。 但是,如果你的设备属于 Windows.Devices.Usb 支持的设备类,则可以根据设备类规范的定义发送一些请求。
准备工作
- 必须打开设备,并获取 UsbDevice 对象。 请阅读如何连接 USB 设备(UWP 应用)。
- 获取有关供应商定义的控制命令的信息。 这些命令通常在硬件规范中定义。
- 可以在 CustomUsbDeviceAccess 示例、Scenario2_ControlTransfer.cpp 和 Scenario2_ControlTransfer.h 中看到本主题中显示的完整代码。
步骤 1:填充设置数据包
在本主题中,我们将向以各种模式闪烁灯光的设备发送控制传输。 为了填充设置数据包,必须知道控制命令是由硬件供应商定义的:
- bmRequestType (D7):OUT
- bmRequestType (D4):设备
- bmRequestType (D6…D5):供应商
- bRequest:0x03
- wValue:0-7(该范围内的任何数字,包括在内)
- wIndex:0
- wLength:0
对于控制传输,必须填充一个设置数据包,其中包含有关传输的所有信息;无论请求读取还是写入数据、请求类型等。 设置数据包的格式在官方 USB 规范中定义。 设置数据包字段的值由设备的硬件规范提供。
创建 UsbSetupPacket 对象。
通过设置各种属性填充 UsbSetupPacket 对象。 下表显示了 USB 定义的设置数据包字段,以及与这些字段对应的属性:
第 9.3 节中的字段 properties 说明 bmRequestType (D7) UsbControlRequestType.Direction 请求的方向。 请求是从主机到设备(输出传输)还是设备到主机(输入传输) bmRequestType (D4) UsbControlRequestType.Recipient 请求的接收方。 所有控制传输都以默认终结点为目标。 但是,接收方可能是设备、接口、终结点或其他。 有关 USB 设备、接口、终结点层次结构的详细信息,请参阅“设备布局”。 bmRequestType (D6…D5) UsbControlRequestType.ControlTransferType 请求类别。 标准、类或供应商。 bRequest UsbSetupPacket.Request 请求类型。 如果请求是标准请求(例如,GET_DESCRIPTOR 请求),则请求由 USB 规范定义。 否则,可能由供应商定义。 wValue UsbSetupPacket.Value 取决于请求的类型。 wIndex UsbSetupPacket.Index 取决于请求的类型。 wLength UsbSetupPacket.Length 此请求中发送或接收的数据包的长度。
![注意] 对于某些控制传输,可能需要提供 bmRequestType 作为原始字节。 在这种情况下,可以在 UsbControlRequestType.AsByte 属性中设置字节。
步骤 2:启动异步操作以发送控制传输
若要发送控制传输,必须具有 UsbDevice 对象。 控制传输可能需要也可能不需要设置数据包后面的数据包。
若要启动控制传输,请调用 SendControlInTransferAsync 或 SendControlOutTransferAsync 的替代。 如果传输使用数据包,则调用 SendControlOutTransferAsync(UsbSetupPacket,IBuffer)、SendControlInTransferAsync(UsbSetupPacket,IBuffer)。 这些方法采用一个附加参数,其中包含要从设备写入或从设备接收数据的数据。 使用流程图确定要调用的替代。
调用将启动并进行异步操作。 操作完成后,调用将返回包含操作结果的 IAsyncOperation 对象。 对于 OUT 传输,该对象返回传输中发送的字节数。 对于 IN 传输,对象包含缓冲区,其中包含从设备读取的数据。
USB 控制传输代码示例
此示例代码显示了如何发送控制传输,以更改 SuperMUTT 设备上的闪烁模式。 传输的设置数据包包含供应商定义的命令。 该示例位于 Scenario2_ControlTransfer.cpp 中。
async Task SetSuperMuttLedBlinkPatternAsync(Byte pattern)
{
UsbSetupPacket initSetupPacket = new UsbSetupPacket
{
RequestType = new UsbControlRequestType
{
Direction = UsbTransferDirection.Out,
Recipient = UsbControlRecipient.Device,
ControlTransferType = UsbControlTransferType.Vendor
},
Request = SuperMutt.VendorCommand.SetLedBlinkPattern,
Value = pattern,
Length = 0
};
UInt32 bytesTransferred = await EventHandlerForDevice.Current.Device.SendControlOutTransferAsync(initSetupPacket);
MainPage.Current.NotifyUser("The Led blink pattern is set to " + pattern.ToString(), NotifyType.StatusMessage);
}
此示例代码显示了如何发送控制传输,以更改 SuperMUTT 设备上的闪烁模式。 传输的设置数据包包含供应商定义的命令。 该示例位于 Scenario2_ControlTransfer.cpp 中。
async Task<IBuffer> SendVendorControlTransferInToDeviceRecipientAsync(Byte vendorCommand, UInt32 dataPacketLength)
{
// Data will be written to this buffer when we receive it
var buffer = new Windows.Storage.Streams.Buffer(dataPacketLength);
UsbSetupPacket initSetupPacket = new UsbSetupPacket
{
RequestType = new UsbControlRequestType
{
Direction = UsbTransferDirection.In,
Recipient = UsbControlRecipient.Device,
ControlTransferType = UsbControlTransferType.Vendor,
},
Request = vendorCommand,
Length = dataPacketLength
};
return await EventHandlerForDevice.Current.Device.SendControlInTransferAsync(initSetupPacket, buffer);
}