共用方式為


如何傳送 USB 控制件傳輸 (UWP 應用程式)

本文示範:

  • 如何格式化 USB 設定封包
  • 如何從您的應用程式起始 USB 控制項傳輸

重要 API

與 USB 裝置通訊的應用程式通常會傳送數個控制傳輸要求。 這些要求會取得裝置的相關信息,並傳送硬體廠商所定義的控制命令。 在本主題中,您將瞭解如何控制傳輸,以及如何在 UWP 應用程式中格式化和傳送它們。

控制傳輸可以讀取或寫入設定資訊,或執行硬體廠商所定義的裝置特定功能。 如果傳輸執行寫入作業,則為 OUT 傳輸;讀取作業,它是 IN 傳輸。 無論方向為何,主機系統上的軟體,例如 UWP 應用程式,一律會建置並起始控件傳輸的要求。 有時,您的應用程式可以起始控制傳輸,以讀取或寫入數據。 在此情況下,您可能需要傳送額外的緩衝區。

為了容納所有類型的控制傳輸, Windows.Devices.Usb 提供下列方法:

適用於usb的 Windows 執行時間 API 的 usb 控制件傳輸。

USB 控制傳輸也可用來取得描述元數據或傳送標準命令。 不過,建議您呼叫 Windows.Devices.Usb 所提供的特定方法,而不是手動建置控件傳輸,以傳送這些類型的要求。 例如,若要選取替代設定,請呼叫 SelectSettingAsync,而不是呼叫 SendControlOutTransferAsync (UsbSetupPacket)。

不支援特定類型的標準要求控制傳輸。 不過,如果您的裝置屬於 Windows.Devices.Usb 支援的裝置類別,您可以傳送裝置類別規格所定義的一些要求。

在您開始使用 Intune 之前

  • 您必須開啟裝置並取得 UsbDevice 物件。 請參閱 如何連線到 USB 裝置 (UWP app)
  • 取得廠商定義控制項命令的相關信息。 這些命令通常會在硬體規格中定義。
  • 您可以在 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規格中。 設定封包欄位的值是由裝置的硬體規格所提供。

  1. 建立 UsbSetupPacket 物件。

  2. 藉由設定各種屬性,填入 UsbSetupPacket 物件。 下表顯示 USB 定義的設定封包欄位,以及對應至這些欄位的屬性:

    第9.3節中的欄位 屬性 說明
    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);
}