共用方式為


如何連線到 USB 裝置 (UWP app)

在 Windows 中,您可以撰寫與 USB 裝置互動的 UWP 應用程式。

本文章說明:

  • 如何使用 DeviceWatcher 對象來偵測裝置
  • 如何開啟裝置以進行通訊
  • 當您完成使用裝置時,如何關閉裝置

重要 API

當您撰寫與 USB 裝置互動的 UWP 應用程式時,應用程式可以傳送控制命令、取得裝置資訊,以及在大量和中斷端點之間讀取和寫入數據。 您必須先找到裝置並建立連線,才能這麼做。

開始之前

  • 這是系列的第一個主題。 開始本教學課程之前,您必須先建立可在本教學課程中擴充的基本 Visual Studio 專案。 如需詳細資訊 ,請參閱開始使用UWP應用程式
  • 程式代碼範例是以 CustomUsbDeviceAccess 範例為基礎。 您可以從此程式代碼庫頁面下載完整的範例。
  • 教學課程中使用的USB裝置是 SuperMUTT 裝置。
  • 若要使用 Windows.Devices.Usb 命名空間來撰寫與 USB 裝置互動的 Windows 應用程式,裝置必須載入 Winusb.sys 驅動程式作為其函式驅動程式。 Winusb.sys 是由 Microsoft 提供,並隨附於 \Windows\System32\drivers 資料夾中的 Windows。

流程圖:尋找裝置

若要連線到 USB 裝置,您必須先根據各種探索模式尋找裝置,然後加以連線:

  • 使用特定裝置介面 GUID 連線到任何 USB 裝置。
  • 使用特定的廠商標識碼和產品標識符連線到 USB 裝置,且具有特定裝置介面 GUID。
  • 在沒有知道裝置介面 GUID 的情況下,使用特定的廠商標識碼和產品標識碼連線到 USB 裝置。
  • 連接到具有已知裝置類別的 USB 裝置。

usb 裝置探索。

重要概念

什麼是裝置介面 GUID?

核心模型驅動程式在初始化期間註冊並公開稱為 裝置介面 GUID 的 GUID。 一般而言,應用程式會使用公開的 GUID 來尋找相關聯的驅動程式及其裝置,然後開啟裝置的句柄。 擷取的句柄用於後續的讀取和寫入作業。

不過,在 Winusb.sys 的情況下,而不是公開裝置介面 GUID 的驅動程式,可以使用下列兩種方式之一來提供:

  • 在裝置的 MS OS 描述元中。 裝置製造商會將 DeviceInterfaceGUID 設定為裝置中擴充屬性描述項中的自定義屬性。 如需詳細資訊,請參閱 Microsoft OS 描述元中的檔。
  • 如果您透過自定義 INF 手動安裝 Winusb.sys,INF 會在 INF 中註冊 GUID。 請參閱 WinUSB (Winusb.sys) 安裝

如果找到裝置的裝置介面 GUID,您的 UWP app 可以找到符合該裝置介面 GUID 的所有裝置。

如何在 Windows 中顯示 USB 裝置識別?

每個USB裝置都必須有兩項資訊:廠商標識碼和產品標識碼。

USB-IF 會指派這些標識符,且裝置製造商必須在裝置中公開這些標識符。 因此,您可以如何取得該資訊?

  • 即使裝置未載入設備驅動器,也就是說,Windows 偵測到它為「未知的裝置」,您仍然可以在硬體標識元屬性值的 裝置管理員 中檢視標識碼。 該值是這兩個標識碼的組合。 例如,針對 SuperMUTT 裝置, 硬體識別碼 為 「USB\VID_045E&PID_F001」;廠商標識碼為 「0x045E」,而產品標識碼為 「0xF001」。。

  • 如果裝置有 INF,請從 [模型 ] 區段取得該字串。

  • 您可以檢查各種登入設定。 最簡單的方式是查看

    <HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USB\硬體標識碼>

    如需詳細資訊,請參閱 USB裝置登錄專案

  • 應用程式指令清單會使用硬體標識碼來識別裝置。

    <裝置標識碼=“vidpid:045e f001”>

您的 UWP 應用程式可以找到符合特定廠商和產品識別碼的所有裝置。 您可以藉由指定裝置介面 GUID 來縮小搜尋結果範圍。

什麼是USB裝置類別?

大部分的 USB 裝置都符合 USB-IF 核准的裝置類別規格。 透過使用這些規格,類似本質的裝置可以標準方式呈現其功能。 這種方法的最大優點是裝置可以使用 Microsoft 提供的現成類別驅動程式或一般 Winusb.sys 驅動程式。

某些裝置可能未遵循 USB-IF 規格。 相反地,他們會公開 廠商定義的 功能。 針對這類裝置,廠商必須提供設備驅動器或 Winusb.sys。

無論裝置是廠商定義還是符合裝置類別,都必須描述此裝置類別相關信息:

  • 類別代碼:指出裝置所屬的裝置類別。
  • 子類別代碼:在裝置類別內,表示裝置的子類別。
  • 通訊協定程式代碼:裝置使用的通訊協定。

例如,SuperMUTT 裝置是廠商定義的裝置,而且類別代碼所指出的資訊是 FF。 如果您的裝置將類別代碼顯示為 FEh、子類別程式代碼顯示為 02h,以及通訊協定代碼 00h,您可以判斷裝置是符合類別規範的 IrDA 網橋裝置。 您的 UWP 應用程式可以與屬於這些裝置類別的裝置通訊:

  • ActiveSync
  • CdcControl
  • DeviceFirmwareUpdate
  • Irda
  • 測量
  • PalmSync
  • PersonalHealthcare
  • 實體
  • VendorSpecific

您的 UWP 應用程式可以找到符合一組特定類別、子類別和通訊協定代碼的所有裝置。

取得裝置的進階查詢語法 (AQS) 字串

(AQS) 產生進階查詢字串,其中包含您想要偵測之裝置的識別資訊。 您可以藉由指定廠商/產品識別碼、裝置介面 GUID 或裝置類別來產生字串。

  • 如果您想要提供廠商標識碼/產品標識符或裝置介面 GUID,請呼叫 GetDeviceSelector 的任何多載。

    在 SuperMUTT 裝置的範例中, GetDeviceSelector 會擷取類似此字串的 AQS 字串:

    "System.Devices.InterfaceClassGuid:="{DEE824EF-729B-4A0E-9C14-B7117D33A817}" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True AND System.DeviceInterface.WinUsb.UsbVendorId:=1118 AND System.DeviceInterface.WinUsb.UsbProductId:=61441"

    注意 請注意,出現在字串中的裝置介面 GUID 不是您指定的介面。 該 GUID 是由 UWP app Winusb.sys 註冊的實際裝置介面 GUID。

  • 如果您知道裝置的裝置類別或其類別、子類別和通訊協議代碼,請呼叫 GetDeviceClassSelector 來產生 AQS 字串。

    指定 ClassCodeSubclassCodeProtocolCode 屬性值,以建立 UsbDeviceClass 物件。 或者,如果您知道裝置的裝置類別,您可以指定特定的 UsbDeviceClasses 屬性來呼叫建構函式。

尋找裝置 — 基本方式

這是尋找USB裝置的最簡單方式。 如需詳細資訊,請參閱 快速入門:列舉常用的裝置

  1. 將擷取的 AQS 字串傳遞至 FindAllAsync。 呼叫會擷取 DeviceInformationCollection 物件。
  2. 迴圈查看集合。 每個反覆項目都會取得 DeviceInformation 物件。
  3. 取得 DeviceInformation.Id 屬性值。 字串值是裝置實例路徑。 例如,“\\?\USB#VID_045E&PID_078F#6&1b8ff026&0&5#{dee824ef-729b-4a0e-9c14-b7117d33a817}”。
  4. 傳遞裝置實例字串並取得 UsbDevice 物件,以呼叫 FromIdAsync。 然後,您可以使用 UsbDevice 對象來執行其他作業,例如傳送控件傳輸。 當應用程式使用 UsbDevice 物件完成時,應用程式必須呼叫 Close 來釋放它。 注意 當 UWP 應用程式暫停時,裝置會自動關閉。 若要避免針對未來的作業使用過時句柄,應用程式必須釋放 UsbDevice 參考。
    private async void OpenDevice()
    {
        UInt32 vid = 0x045E;
        UInt32 pid = 0x0611;

        string aqs = UsbDevice.GetDeviceSelector(vid, pid);

        var myDevices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(aqs);

        try
        {
            usbDevice = await UsbDevice.FromIdAsync(myDevices[0].Id);
        }
        catch (Exception exception)
        {
            ShowStatus(exception.Message.ToString());
        }
        finally
        {
            ShowStatus("Opened device for communication.");
        }

    }

尋找裝置—使用 DeviceWatcher

或者,您可以動態列舉裝置。 然後,如果新增或移除裝置,或裝置屬性變更,您的應用程式可以接收通知。 如需詳細資訊,請參閱 如何在新增、移除或變更裝置時取得通知

DeviceWatcher 物件可讓應用程式在從系統新增和移除裝置時動態偵測裝置。

  1. 建立 DeviceWatcher 物件,以偵測裝置在系統新增或移除時。 您必須呼叫 CreateWatcher 並指定 AQS 字串來建立物件。

  2. DeviceWatcher 對象上實作和註冊已新增移除事件的處理程式。 當系統新增或移除具有相同識別資訊) 的裝置 (時,就會叫用這些事件處理程式。

  3. 啟動和停止 DeviceWatcher 物件。

    應用程式必須藉由呼叫 Start 來啟動 DeviceWatcher 物件,讓它可以在系統新增或移除裝置時開始偵測裝置。 相反地,當不再需要偵測裝置時,應用程式必須藉由呼叫Stop來停止DeviceWatcher。 此範例有兩個按鈕,可讓用戶啟動和停止 DeviceWatcher

此程式代碼範例示範如何建立並啟動裝置監看員,以尋找 SuperMUTT 裝置的實例。

void CreateSuperMuttDeviceWatcher(void)
{
    UInt32 vid = 0x045E;
    UInt32 pid = 0x0611;

    string aqs = UsbDevice.GetDeviceSelector(vid, pid);

    var superMuttWatcher = DeviceInformation.CreateWatcher(aqs);

    superMuttWatcher.Added += new TypedEventHandler<DeviceWatcher, DeviceInformation>
                              (this.OnDeviceAdded);

    superMuttWatcher.Removed += new TypedEventHandler<DeviceWatcher, DeviceInformationUpdate>
                            (this.OnDeviceRemoved);

    superMuttWatcher.Start();
 }

開啟裝置

若要開啟裝置,應用程式必須呼叫 static 方法 FromIdAsync 並傳遞從 DeviceInformation.Id) 取得的裝置實例路徑 (,以啟動異步操作。 該作業取得的結果是 UsbDevice 物件,用於與裝置的未來通訊,例如執行數據傳輸。

使用 UsbDevice 物件完成之後,您必須釋放它。 藉由釋放 物件,所有擱置的數據傳輸都會取消。 這些作業的完成回呼例程仍會以已取消的錯誤或作業完成來叫用。

C++ 應用程式必須使用 delete 關鍵詞來釋放參考。 C#/VB 應用程式必須呼叫 UsbDevice.Dispose 方法。 JavaScript 應用程式必須呼叫 UsbDevice.Close

如果裝置正在使用中或找不到 ,FromIdAsync 就會失敗。