共用方式為


如何撰寫第一個 USB 用戶端驅動程式 (UMDF)

在本文中,您將使用 Microsoft Visual Studio 2022 所提供的 使用者模式驅動程式、USB (UMDF V2) 範本來撰寫使用者模式驅動程序架構, (UMDF) 型用戶端驅動程式。 建置並安裝客戶端驅動程序之後,您會在 裝置管理員 中檢視用戶端驅動程式,並在調試程式中檢視驅動程序輸出。

UMDF (稱為本文中的架構,) 是以元件物件模型為基礎, (COM) 。 根據預設,每個架構對象都必須實作 IUnknown 及其方法 QueryInterfaceAddRefReleaseAddRefRelease 方法會管理物件的存留期,因此客戶端驅動程式不需要維護參考計數。 QueryInterface 方法可讓用戶端驅動程式取得 Windows Driver Frameworks 中其他架構物件的介面指標, (WDF) 物件模型。 架構物件會執行複雜的驅動程式工作,並與 Windows 互動。 某些架構物件會公開介面,讓用戶端驅動程式能夠與架構互動。

UMDF 型用戶端驅動程式會實作為同進程 COM 伺服器 (DLL) ,而 C++ 是撰寫 USB 裝置用戶端驅動程式的慣用語言。 一般而言,客戶端驅動程式會實作架構所公開的數個介面。 本文指的是將架構介面實作為回呼類別的用戶端驅動程式定義類別。 具現化這些類別之後,產生的回呼物件會與特定架構物件合作。 此合作關係可讓客戶端驅動程式有機會回應架構所報告的裝置或系統相關事件。 每當 Windows 通知架構有關特定事件時,架構就會叫用用戶端驅動程式的回呼,如果有的話。 否則,架構會繼續進行事件的默認處理。 範本程式代碼會定義驅動程式、裝置和佇列回呼類別。

如需範本所產生原始程式碼的說明,請參閱 瞭解 USB 用戶端驅動程式的 UMDF 範本程式碼

開始之前

若要開發、偵錯及安裝使用者模式驅動程式,您需要兩部計算機:

  • 執行 Windows 10 或更新版本的 Windows 作業系統的主電腦。 主計算機是您開發環境,您可以在其中撰寫和偵錯驅動程式。
  • 執行您要測試驅動程式版本的目標計算機,例如,Windows 11 版本 22H2。 目標電腦具有您想要偵錯的使用者模式驅動程式,以及其中一個調試程式。

在某些情況下,主計算機和目標計算機執行相同的 Windows 版本時,您只能有一部執行 Windows 10 或更新版本的 Windows 的電腦。 本文假設您使用兩部計算機來開發、偵錯及安裝您的使用者模式驅動程式。

開始之前,請確定您符合下列需求:

軟體需求

  • 主電腦具有 Visual Studio 2022。

  • 您的主電腦具有適用於 Windows 11 版本 22H2 的最新 Windows 驅動程式套件 (WDK) 。

    套件包含標頭、連結庫、工具、檔,以及開發、建置和偵錯 USB 用戶端驅動程式所需的偵錯工具。 您可以從 如何取得 WDK 取得最新版本的 WDK

  • 您的主電腦有適用於 Windows 的最新版偵錯工具。 您可以從 WDK 取得最新版本,也可以 下載並安裝適用於 Windows 的偵錯工具

  • 如果您使用兩部計算機,則必須設定主計算機和目標計算機以進行使用者模式偵錯。 如需詳細資訊,請參閱 在Visual Studio中設定 User-Mode 偵錯。

硬體需求

取得您將撰寫用戶端驅動程式的 USB 裝置。 在大部分情況下,您都會提供USB裝置及其硬體規格。 此規格描述裝置功能和支援的廠商命令。 使用規格來判斷 USB 驅動程式的功能和相關的設計決策。

如果您不熟悉 USB 驅動程式開發,請使用 OSR USB FX2 學習套件 來研究 WDK 隨附的 USB 範例。 它包含 USB FX2 裝置,以及實作用戶端驅動程式所需的所有硬體規格。

步驟 1:產生驅動程式程式代碼

如需撰寫 UMDF 驅動程式程式代碼的詳細資訊,請參閱 根據範本撰寫 UMDF 驅動程式

針對 USB 特定程式代碼,請在 Visual Studio 2022 中選取下列選項

  1. 在 [ 新增專案 ] 對話框的頂端搜尋方塊中,輸入 USB。
  2. 在中間窗格中,選取 [ 使用者模式驅動程式]、[USB (UMDF V2) ]。
  3. 選取 [下一步] 。
  4. 輸入專案名稱、選擇儲存位置,然後選取 [ 建立]。

下列螢幕快照顯示USB User-Mode 驅動程式範本的 [新增專案] 對話方塊。

Visual Studio 建立專案選項的螢幕快照。

Visual Studio 建立專案組態畫面的螢幕快照。

本文假設項目的名稱 MyUSBDriver_UMDF_。 其中包含下列檔案:

檔案 Description
Driver.h;Driver.c 包含驅動程式模組進入點的實作。 DriverEntry 和 WDFDRIVER 相關功能和回呼。
Device.h;Device.c WDFDEVICE 和 WDFUSBDEVICE 相關功能和回呼。
Queue.h;Queue.c WDFQUEUE 相關功能和回呼。
Trace.h 定義裝置介面 GUID。 它也會宣告追蹤函式和宏。
<項目名稱>.inf 在目標電腦上安裝客戶端驅動程式所需的 INF 檔案。

步驟 2:新增裝置的相關信息

在建置驅動程式之前,您必須新增裝置的相關信息,特別是硬體標識碼。 若要提供硬體識別碼:

  1. [方案總管] 視窗中,以滑鼠右鍵按兩下MyUSBDriver_UMDF_,然後選擇 [屬性]。
  2. [MyUSBDriver_UMDF_屬性頁 ] 視窗中,移至 [ 設定屬性 > 驅動程序安裝 > 部署],如下所示。 Visual Studio 2022 屬性頁視窗的螢幕快照。
  3. 部署之前,請檢查 [移除舊版驅動程式]。
  4. 針對 [目標裝置名稱],選取您為測試和偵錯設定的計算機名稱。
  5. 選取 [硬體標識符驅動程式更新],然後輸入驅動程式的硬體識別碼。 在此練習中,硬體標識碼為 Root\MyUSBDriver_UMDF_。 選取 [確定]。

注意

在此練習中,硬體標識碼不會識別實際的硬體片段。 它會識別一個虛構的裝置,該裝置會在裝置樹狀結構中指定為根節點的子系。 針對實際的硬體,請勿選取 [硬體標識符驅動程式更新]。 請改為選取 [安裝並驗證]。 您可以在驅動程序的資訊中看到硬體識別碼, (INF) 檔案。 在 [方案總管] 視窗中,移至 [MyUSBDriver_UMDF_>驅動程序檔案],然後按兩下 MyUSBDriver_UMDF_.inf。 硬體標識符位於 [Standard.NT$ARCH$] 底下。

所有UMDF型USB用戶端驅動程式都需要兩個 Microsoft 提供的驅動程式:反映器和 WinUSB。

  • 反映器:如果您的驅動程式成功載入,反映器會載入為核心模式堆疊中最上層的驅動程式。 反映器必須是核心模式堆疊中的最上層驅動程式。 為了符合此需求,範本的 INF 檔案會將反映器指定為服務,並將 WinUSB 指定為 INF 中的較低篩選驅動程式:

    [MyDevice_Install.NT.Services]
    AddService=WUDFRd,0x000001fa,WUDFRD_ServiceInstall  ; flag 0x2 sets this as the service for the device
    AddService=WinUsb,0x000001f8,WinUsb_ServiceInstall  ; this service is installed because its a filter.
    
  • WinUSB:安裝套件必須包含 Winusb.sys 的壓縮器,因為針對用戶端驅動程式,WinUSB 是核心模式 USB 驅動程式堆棧的網關。 另一個載入的元件是客戶端驅動程式主機進程 (Wudfhost.exe) 中名為 WinUsb.dll 的使用者模式 DLL。 Winusb.dll 會公開 WinUSB 函式 ,以簡化用戶端驅動程式與 WinUSB 之間的通訊程式。

步驟 3:建置 USB 用戶端驅動程式程式代碼

若要建置驅動程式:

  1. 在 Visual Studio 2022 中開啟驅動程式專案或方案。
  2. 以滑鼠右鍵按兩下 方案總管 中的方案,然後選取 [Configuration Manager]。
  3. Configuration Manager 中,選取 Active Solution Configuration (,例如[錯] 或 [發行) ] 和 [作用中解決方案平臺] (,例如,對應至您感興趣的組建類型 x64) 。
  4. 確認您的裝置介面 GUID 在整個專案中都正確無誤。
    • 裝置介面 GUID 定義於 Trace.h 中,並從 Device.c 中參考 MyUSBDriverUMDFCreateDevice 。 當您使用名稱MyUSBDriver_UMDF_建立專案時,Visual Studio 2022 會以名稱GUID_DEVINTERFACE_MyUSBDriver_UMDF_定義裝置介面 GUID,但會以不正確的參數 &GUID_DEVINTERFACE_MyUSBDriverUMDF呼叫 WdfDeviceCreateDeviceInterface 。 將不正確的參數取代為 Trace.h 中定義的名稱,以確保驅動程式正確建置。
  5. 從 [建置] 功能表中,選取 [建置解決方案]。

如需詳細資訊,請參閱 建置驅動程式

步驟 4:設定計算機進行測試和偵錯

若要測試和偵錯驅動程式,您可以在主計算機和目標計算機上的驅動程式上執行調試程式。 到目前為止,您已在主計算機上使用 Visual Studio 來建置驅動程式。 接下來,您必須設定目標計算機。 若要設定目標計算機,請遵循布建 計算機以進行驅動程式部署和測試中的指示。

步驟 5:啟用核心偵錯的追蹤

範本程式代碼包含數個追蹤訊息 (TraceEvents) ,可協助您追蹤函數調用。 原始程式碼中的所有函式都包含追蹤訊息,可標記例程的進入和結束。 針對錯誤,追蹤訊息包含錯誤碼和有意義的字串。 因為已為您的驅動程式專案啟用WPP追蹤,所以在建置程式期間建立的PDB符號檔包含追蹤訊息格式設定指示。 如果您設定 WPP 追蹤的主電腦和目標電腦,驅動程式可以將追蹤訊息傳送至檔案或調試程式。

設定主計算機以進行WPP追蹤

  1. 從 PDB 符號檔擷取追蹤訊息格式指示,以 (TMF) 檔案建立追蹤訊息格式。

    您可以使用 Tracepdb.exe 來建立TMF檔案。 此工具位於 WDK 的安裝資料夾>Windows Kits\10\bin\<architecture> 資料夾中。< 下列命令會建立驅動程序專案的TMF檔案。

    tracepdb -f <PDBFiles> -p <TMFDirectory>
    

    -f 選項會指定 PDB 符號檔的位置和名稱。 -p 選項會指定 Tracepdb 所建立之 TMF 檔案的位置。 如需詳細資訊,請參閱 Tracepdb 命令

    指定位置有三個檔案,每個 C 程式代碼檔案在專案中一個。 它們會指定 GUID 檔名。

  2. 在除錯程式中,輸入下列命令:

    .load Wmitrace
    .chain
    !wmitrace.searchpath + <TMF file location>
    

這些命令:

  • 載入 Wmitrace.dll 延伸模組。
  • 確認已載入調試程式擴充功能。
  • 將TMF檔案的位置新增至調試程式的搜尋路徑。

輸出看起來會像這樣:

Trace Format search path is: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE;c:\drivers\tmf

設定目標計算機以進行WPP追蹤

  1. 請確定您的目標電腦上有 Tracelog 工具。 此工具位於 WDK 的 install_folder>Windows Kits\10\Tools\<arch> 資料夾中。< 如需詳細資訊,請參閱 Tracelog 命令語法

  2. 開啟 命令視窗 ,並以系統管理員身分執行。

  3. 輸入以下命令:

    tracelog -start MyTrace -guid \#c918ee71-68c7-4140-8f7d-c907abbcb05d -flag 0xFFFF -level 7-rt -kd
    

此命令會啟動名為 MyTrace 的追蹤作業階段。

guid 自變數會指定追蹤提供者的 GUID,這是客戶端驅動程式。 您可以從 Visual Studio 2022 專案中的 Trace.h 取得 GUID。 另一個選項是輸入下列命令,並在 .guid 檔案中指定 GUID。 檔案包含連字元格式的 GUID:

tracelog -start MyTrace -guid c:\\drivers\\Provider.guid -flag 0xFFFF -level 7-rt -kd

您可以輸入下列命令來停止追蹤工作階段:

tracelog -stop MyTrace

步驟 6:在目標計算機上部署驅動程式

  1. [方案總管] 視窗中,以滑鼠右鍵按兩下專案名稱 (MyUSBDriver_UMDF_) ,然後選擇 [屬性]。
  2. 在左窗格中,流覽至 [ 組態屬性 > 驅動程式安裝 > 部署]。
  3. 針對 [目標裝置名稱],指定目標計算機的名稱。
  4. 選取 [安裝/重新安裝] 和 [驗證]。
  5. 選取 [確定]。
  6. 在 [ 錯] 功能表上,選擇 [ 開始偵錯],或在鍵盤上按 F5

注意

請勿在 [硬體標識符驅動程式更新] 底下指定裝置的硬體識別碼。 硬體標識碼只能在驅動程式的資訊 (INF) 檔案中指定。

步驟 7:在 裝置管理員 中檢視驅動程式

  1. 輸入下列命令以開啟 裝置管理員

    devmgmt
    
  2. 確認 裝置管理員 顯示下列節點。

    USB 裝置

    MyUSBDriver_UMDF_Device

步驟 8:在調試程式中檢視輸出

確認追蹤訊息出現在主電腦上的 [調試程序即時運算視窗 ] 中。

輸出應如下所示:

[0]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::OnPrepareHardware Entry
[0]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::OnPrepareHardware Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::CreateInstanceAndInitialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Initialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Initialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::CreateInstanceAndInitialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Configure Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::CreateInstanceAndInitialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::Initialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::Initialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::CreateInstanceAndInitialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Configure Exit

備註

讓我們看看架構和客戶端驅動程式如何一起運作,以與 Windows 互動,並處理傳送至 USB 裝置的要求。 此圖顯示針對 UMDF 型 USB 用戶端驅動程式在系統中載入的模組。

使用者模式客戶端驅動程式架構的圖表。

每個模組的用途如下所述:

  • 應用程式 — 使用者模式程式,會發出 I/O 要求來與 USB 裝置通訊。
  • I/O 管理員 — 建立 I/O 要求封包的 Windows 元件, (IRP) 代表所接收的應用程式要求,並將其轉送至目標裝置的核心模式裝置堆疊頂端。
  • 反映器 — Microsoft 提供的內核模式驅動程式,安裝在內核模式裝置堆疊 (WUDFRd.sys) 頂端。 反映程式會將從 I/O 管理員接收的 IRP 重新導向至用戶端驅動程式主機進程。 收到要求時,架構和用戶端驅動程序會處理要求。
  • 主機進程 — 使用者模式驅動程式執行 (Wudfhost.exe) 的程式。 它也會裝載架構和 I/O 發送器。
  • 用戶端驅動程式 — USB 裝置的使用者模式函式驅動程式。
  • UMDF — 代表用戶端驅動程序處理大部分與 Windows 互動的架構模組。 它會公開使用者模式設備驅動器介面, (DIS) 客戶端驅動程式可用來執行一般驅動程式工作。
  • 發送器—在主機進程中執行的機制;決定在使用者模式驅動程序處理要求之後,如何將要求轉送到核心模式,並已到達使用者模式堆棧底部。 在圖例中,發送器會將要求轉送至使用者模式 DLL,Winusb.dll。
  • Winusb.dll — Microsoft 提供的使用者模式 DLL,可公開 WinUSB Functions ,以簡化用戶端驅動程式與 WinUSB (Winusb.sys 之間的通訊程式,以核心模式載入) 。
  • Winusb.sys — 所有適用於 USB 裝置的 UMDF 用戶端驅動程式都需要 Microsoft 提供的驅動程式。 驅動程式必須安裝在反映器下方,並作為核心模式中USB驅動程式堆疊的閘道。 如需詳細資訊,請參閱 WinUSB
  • USB 驅動程式堆疊 — Microsoft 提供的一組驅動程式,可處理與 USB 裝置的通訊協定層級通訊。 如需詳細資訊,請參閱 Windows 中的 USB 主機端驅動程式

每當應用程式提出 USB 驅動程式堆疊的要求時,Windows I/O 管理員會將要求傳送至反映器,以在使用者模式中將要求導向至用戶端驅動程式。 用戶端驅動程式會藉由呼叫特定的 UMDF 方法來處理要求,此方法會在內部呼叫 WinUSB Functions 以將要求傳送至 WinUSB。 收到要求時,WinUSB 會處理要求,或將其轉送至USB驅動程式堆疊。