如何連線到 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 裝置。
重要概念
什麼是裝置介面 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 字串。
指定 ClassCode、SubclassCode 和 ProtocolCode 屬性值,以建立 UsbDeviceClass 物件。 或者,如果您知道裝置的裝置類別,您可以指定特定的 UsbDeviceClasses 屬性來呼叫建構函式。
尋找裝置 — 基本方式
這是尋找USB裝置的最簡單方式。 如需詳細資訊,請參閱 快速入門:列舉常用的裝置。
- 將擷取的 AQS 字串傳遞至 FindAllAsync。 呼叫會擷取 DeviceInformationCollection 物件。
- 迴圈查看集合。 每個反覆項目都會取得 DeviceInformation 物件。
- 取得 DeviceInformation.Id 屬性值。 字串值是裝置實例路徑。 例如,“\\?\USB#VID_045E&PID_078F#6&1b8ff026&0&5#{dee824ef-729b-4a0e-9c14-b7117d33a817}”。
- 傳遞裝置實例字串並取得 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 物件可讓應用程式在從系統新增和移除裝置時動態偵測裝置。
建立 DeviceWatcher 物件,以偵測裝置在系統新增或移除時。 您必須呼叫 CreateWatcher 並指定 AQS 字串來建立物件。
在 DeviceWatcher 對象上實作和註冊已新增和移除事件的處理程式。 當系統新增或移除具有相同識別資訊) 的裝置 (時,就會叫用這些事件處理程式。
啟動和停止 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 就會失敗。