初めての USB クライアント ドライバーの記述方法 (UMDF)

このトピックでは、Microsoft Visual Studio 2019 で提供されている USB User-Mode ドライバー テンプレートを使用して、ユーザー モード ドライバー フレームワーク (UMDF) ベースのクライアント ドライバーを作成します。 クライアント ドライバーをビルドしてインストールした後、デバイス マネージャーでクライアント ドライバー表示し、デバッガーでドライバーの出力を表示します。

UMDF (このトピックではフレームワークと呼ばれます) は、コンポーネント オブジェクト モデル (COM) に基づいています。 すべてのフレームワーク オブジェクトは、 IUnknown とそのメソッド、 QueryInterfaceAddRefRelease を既定で実装する必要があります。 AddRef メソッドと Release メソッドはオブジェクトの有効期間を管理するため、クライアント ドライバーは参照カウントを維持する必要はありません。 QueryInterface メソッドを使用すると、クライアント ドライバーは、Windows Driver Frameworks (WDF) オブジェクト モデル内の他のフレームワーク オブジェクトへのインターフェイス ポインターを取得できます。 フレームワーク オブジェクトは、複雑なドライバー タスクを実行し、Windowsと対話します。 特定のフレームワーク オブジェクトは、クライアント ドライバーがフレームワークと対話できるようにするインターフェイスを公開します。

UMDF ベースのクライアント ドライバーはインプロセス COM サーバー (DLL) として実装され、C++ は USB デバイスのクライアント ドライバーを記述するための推奨される言語です。 通常、クライアント ドライバーはフレームワークによって公開される複数のインターフェイスを実装します。 このトピックでは、コールバック クラスとしてフレームワーク インターフェイスを実装するクライアント ドライバー定義クラスを参照します。 これらのクラスがインスタンス化されると、結果のコールバック オブジェクトは特定のフレームワーク オブジェクトと連携します。 このパートナーシップにより、クライアント ドライバーは、フレームワークによって報告されるデバイスまたはシステム関連のイベントに応答できるようになります。 特定のイベントWindowsフレームワークに通知するたびに、フレームワークはクライアント ドライバーのコールバック (使用可能な場合) を呼び出します。 それ以外の場合、フレームワークはイベントの既定の処理を続行します。 テンプレート コードでは、ドライバー、デバイス、キューのコールバック クラスを定義します。

テンプレートによって生成されるソース コードの詳細については、「 USB クライアント ドライバーの UMDF テンプレート コードについて」を参照してください。

前提条件

ユーザー モード ドライバーを開発、デバッグ、インストールするには、次の 2 つのコンピューターが必要です。

  • Windows オペレーティング システムWindows 7 以降のバージョンを実行しているホスト コンピューター。 ホスト コンピューターは開発環境であり、ドライバーの記述とデバッグを行います。
  • ドライバーをテストするオペレーティング システムのバージョン (Windows 10、バージョン 1903 など) を実行しているターゲット コンピューター。 ターゲット コンピューターには、デバッグするユーザー モード ドライバーとデバッガーのいずれかが用意されています。

ホスト コンピューターとターゲット コンピューターが同じバージョンのWindowsを実行している場合、Windowsの 7 以降のバージョンWindows実行しているコンピューターは 1 台だけです。 このトピックでは、ユーザー モード ドライバーの開発、デバッグ、インストールに 2 台のコンピューターを使用していることを前提としています。

開始する前に、次の要件を満たしていることを確認してください。

ソフトウェア要件

  • ホスト コンピューターに 2019 Visual Studioがあります。

  • ホスト コンピューターには、Windows 10 バージョン 1903 の最新のWindows ドライバー キット (WDK) があります。

    このキットには、USB クライアント ドライバーの開発、ビルド、デバッグに必要なヘッダー、ライブラリ、ツール、ドキュメント、デバッグ ツールが含まれます。 WDK の最新バージョンは、WDK を 取得する方法から入手できます。

  • ホスト コンピューターには、Windows用の最新バージョンのデバッグ ツールがあります。 WDK から最新バージョンを取得することも、Windowsのデバッグ ツールをダウンロードしてインストールすることもできます。

  • 2 台のコンピューターを使用している場合は、ユーザー モード デバッグ用にホスト コンピューターとターゲット コンピューターを構成する必要があります。 詳細については、「Visual StudioでのデバッグUser-Mode設定」を参照してください。

ハードウェア要件

クライアント ドライバーを記述する USB デバイスを取得します。 ほとんどの場合、USB デバイスとそのハードウェア仕様が提供されます。 この仕様では、デバイスの機能とサポートされているベンダー コマンドについて説明します。 仕様を使用して、USB ドライバーの機能と、関連する設計上の決定を決定します。

USB ドライバーの開発に慣れている場合は、 OSR USB FX2 ラーニング キット を使用して、WDK に含まれる USB サンプルを調わせてください。 これには、USB FX2 デバイスと、クライアント ドライバーを実装するために必要なすべてのハードウェア仕様が含まれています。

Instructions

手順 1: Visual Studio 2019 USB ドライバー テンプレートを使用して UMDF ドライバー コードを生成する

UMDF ドライバー コードの生成手順については、「 テンプレートに基づく UMDF ドライバーの記述」を参照してください。

USB 固有のコードの場合は、Visual Studio 2019 で次のオプションを選択します

  1. [新しいProject] ダイアログ ボックスの上部にある検索ボックスに「USB」と入力します
  2. 中央のウィンドウで、 ユーザー モード ドライバー、USB (UMDF V2) を選択します。
  3. 次になめる。
  4. プロジェクト名を入力し、保存場所を選択して、[ 作成] をクリックします。

次のスクリーン ショットは、USB User-Mode ドライバー テンプレートの [新しいProject] ダイアログ ボックスを示しています。

visual studio new project options.

visual studio new project options second screen.

このトピックでは、プロジェクトの名前が "MyUSBDriver_UMDF_" であることを前提としています。 次のファイルが含まれます。

ファイル 説明
Driver.h;Driver.c IDriverEntry インターフェイスを実装するコールバック クラスを宣言して定義します。 このクラスは、フレームワーク ドライバー オブジェクトによって呼び出されるメソッドを定義します。 このクラスの主な目的は、クライアント ドライバーのデバイス オブジェクトを作成することです。
Device.h;Device.c IPnpCallbackHardware インターフェイスを実装するコールバック クラスを宣言して定義します。 このクラスは、フレームワーク デバイス オブジェクトによって呼び出されるメソッドを定義します。 このクラスの主な目的は、プラグ アンド プレイ (PnP) 状態の変化の結果として発生するイベントを処理することです。 クラスは、システムに読み込まれている限り、クライアント ドライバーに必要なリソースを割り当てて初期化します。
IoQueue.h;IoQueue.c IQueueCallbackDeviceIoControl インターフェイスを実装するコールバック クラスを宣言して定義します。 このクラスは、フレームワーク キュー オブジェクトによって呼び出されるメソッドを定義します。 このクラスの目的は、フレームワークでキューに入っている I/O 要求を取得することです。
Internal.h USB デバイスと通信するクライアント ドライバーとユーザー アプリケーションによって共有される一般的な宣言を提供します。 また、トレース関数とマクロも宣言します。
Dllsup.cpp ドライバー モジュールのエントリ ポイントの実装が含まれています。
<name.inf Project> ターゲット コンピューターにクライアント ドライバーをインストールするために必要な INF ファイル。
Exports.def ドライバー モジュールのエントリ ポイント関数名をエクスポートする DEF ファイル。

手順 2: INF ファイルを変更して、デバイスに関する情報を追加する

ドライバーをビルドする前に、デバイスに関する情報 (具体的にはハードウェア ID 文字列) を使用してテンプレート INF ファイルを変更する必要があります。

ハードウェア ID 文字列を指定するには

  1. USB デバイスをホスト コンピューターに接続し、デバイスWindows列挙できるようにします。

  2. デバイス マネージャーを開き、デバイスのプロパティを開きます。

  3. [ 詳細 ] タブの [プロパティ] で [ ハードワード ID] を 選択します

    デバイスのハードウェア ID がリスト ボックスに表示されます。 ハードウェア ID 文字列を選択して長押し (または右クリック) し、コピーします。

  4. ソリューション エクスプローラーで、[ドライバー ファイル] を展開し、INF を開きます。

  5. 次のハードウェア ID 文字列を置き換えます。

    [Standard.NT$ARCH$]

    %DeviceName%=MyDevice_Install, USB\VID_vvvv&PID_pppp

ドライバーの情報 (INF) ファイルの AddReg エントリに注目してください。

[CoInstallers_AddReg] ;

HKR,,CoInstallers32,0x00010008,"WudfCoinstaller.dll"

HKR,,CoInstallers32,0x00010008,"WudfUpdate_01011.dll"

HKR,,CoInstallers32,0x00010008,"WdfCoInstaller01011.dll,WdfCoInstaller"

HKR,,CoInstallers32,0x00010008,"WinUsbCoinstaller2.dll"

  • WudfCoinstaller.dll (構成共同インストーラー)
  • <WUDFUpdate_version>.dll (再頒布可能な共同インストーラー)
  • Wdfcoinstallerversion<>.dll (KMDF の共同インストーラー)
  • Winusbcoinstaller2.dll ((Winusb.sys の共同インストーラー)
  • MyUSBDriver_UMDF_.dll (クライアント ドライバー モジュール)

INF AddReg ディレクティブが UMDF 再頒布可能共同インストーラー (WUDFUpdate_<version>.dll) を参照している場合は、構成共同インストーラー (WUDFCoInstaller.dll) への参照を行う必要はありません。 INF で両方の共同インストーラーを参照すると、インストール エラーが発生します。

UMDF ベースのすべての USB クライアント ドライバーには、リフレクターと WinUSB の 2 つの Microsoft 提供ドライバーが必要です。

  • リフレクター- ドライバーが正常に読み込まれた場合、リフレクターはカーネル モード スタックの最上位ドライバーとして読み込まれます。 リフレクターは、カーネル モード スタックの最上位ドライバーである必要があります。 この要件を満たすために、テンプレートの INF ファイルでは、サービスとしてリフレクターを指定し、INF の下位フィルター ドライバーとして WinUSB を指定します。

    [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 はカーネル モード USB ドライバー スタックへのゲートウェイであるため、インストール パッケージにはWinusb.sys用のコインストーラーが含まれている必要があります。 読み込まれるもう 1 つのコンポーネントは、クライアント ドライバーのホスト プロセス (Wudfhost.exe) で、WinUsb.dllという名前のユーザー モード DLL です。 Winusb.dllは、クライアント ドライバーと WinUSB の間の通信プロセスを簡略化する WinUSB 関数を公開します。

手順 3: USB クライアント ドライバー コードをビルドする

ドライバーをビルドするには

  1. Visual Studio 2019 でドライバー プロジェクトまたはソリューションを開きます。
  2. ソリューション エクスプローラーでソリューションを右クリックし、[Configuration Manager] を選択します。
  3. Configuration Managerから、目的のビルドの種類に対応する Active Solution Configuration (デバッグリリースなど) と Active Solution Platform (Win32 など) を選択します。
  4. プロジェクト全体でデバイス インターフェイス GUID が正確であることを確認します。
    • デバイス インターフェイス GUID は Trace.h で定義され、Device.c から参照されます MyUSBDriverUMDFCreateDevice 。 "MyUSBDriver_UMDF_" という名前のプロジェクトを作成すると、Visual Studio 2019 では、デバイス インターフェイス GUID が名前GUID_DEVINTERFACE_MyUSBDriver_UMDF_で定義されますが、正しくないパラメーター "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 コマンド」を参照してください。

    指定した場所に、3 つのファイル (プロジェクト内の .c ファイルごとに 1 つ) が表示されます。 GUID ファイル名を指定します。

  2. デバッガーで、次のコマンドを入力します。

.load Wmitrace

.chain

!wmitrace.searchpath +***&lt;TMF file location&gt;

これらのコマンドでは次のことが行われます。

  • Wmitrace.dll拡張子を読み込みます。
  • デバッガー拡張機能が読み込まれる Verfies。
  • デバッガー拡張機能の検索パスに 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 2019 プロジェクトで 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. ソリューション エクスプローラー ウィンドウで、プロジェクト名>パッケージを選択して保持 (または右クリック)< し、[プロパティ] を選択します。
  2. 左側のウィンドウで、 Configuration Properties > Driver Install > Deployment に移動します。
  3. [展開を有効にする] をオンにし、[ドライバー ストアへのインポート] をオンにします。
  4. [リモート コンピューター名] には、ターゲット コンピューターの名前を指定します。
  5. [Install and Verify (インストールと確認)] を選びます。
  6. [OK] を選択します。
  7. [デバッグ] メニューの [デバッグ開始] をクリックするか、キーボードで F5 キーを押します。

注意

[ハードウェア ID ドライバー更新プログラム] でデバイスのハードウェア ID を指定しないでください。 ハードウェア ID は、ドライバーの情報 (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 クライアント ドライバー用にシステムに読み込まれたモジュールを示しています。

user mode client driver architecture.

各モジュールの目的を次に示します。

  • アプリケーション: USB デバイスと通信するための I/O 要求を発行するユーザー モード プロセス。
  • I/O マネージャー— 受信したアプリケーション要求を表す I/O 要求パケット (IRP) を作成し、ターゲット デバイスのカーネル モード デバイス スタックの最上位に転送する、Windows コンポーネントです。
  • リフレクター: カーネル モード デバイス スタック (WUDFRd.sys) の上部にインストールされている Microsoft 提供のカーネル モード ドライバー。 リフレクターは、I/O マネージャーから受信した IRP をクライアント ドライバー ホスト プロセスにリダイレクトします。 要求を受信すると、フレームワークとクライアント ドライバーが要求を処理します。
  • ホスト プロセス — ユーザー モード ドライバーが実行されるプロセス (Wudfhost.exe)。 また、フレームワークと I/O ディスパッチャーもホストします。
  • クライアント ドライバー: USB デバイスのユーザー モード関数ドライバー。
  • UMDF: クライアント ドライバーの代わりに、Windowsとのほとんどの対話を処理するフレームワーク モジュール。 クライアント ドライバーが一般的なドライバー タスクを実行するために使用できるユーザー モード デバイス ドライバー インターフェイス (DDI) を公開します。
  • ディスパッチャー— ホスト プロセスで実行されるメカニズム。は、ユーザー モード ドライバーによって処理され、ユーザー モード スタックの一番下に達した後に、カーネル モードに要求を転送する方法を決定します。 図では、ディスパッチャーは要求をユーザー モード DLL に転送Winusb.dll。
  • Winusb.dll: クライアント ドライバーと WinUSB (Winusb.sys、カーネル モードで読み込まれる) 間の通信プロセスを簡略化する WinUSB Functions を公開する Microsoft 提供のユーザー モード DLL。
  • Winusb.sys: USB デバイスのすべての UMDF クライアント ドライバーに必要な Microsoft 提供のドライバー。 ドライバーは、リフレクターの下にインストールし、カーネル モードで USB ドライバー スタックへのゲートウェイとして機能する必要があります。 詳細については、 WinUSB を参照してください。
  • USB ドライバー スタック—MICROSOFT によって提供される一連のドライバーで、USB デバイスとのプロトコル レベルの通信を処理します。 詳細については、Windowsの USB ホスト側ドライバーに関するページを参照してください。

アプリケーションが USB ドライバー スタックの要求を行うたびに、Windows I/O マネージャーはリフレクターに要求を送信し、ユーザー モードでクライアント ドライバーに送信します。 クライアント ドライバーは、 WinUSB 関数 を内部的に呼び出して WinUSB に要求を送信する特定の UMDF メソッドを呼び出すことによって要求を処理します。 要求を受信すると、WinUSB は要求を処理するか、USB ドライバー スタックに転送します。

USB クライアント ドライバーの UMDF テンプレート コードについて
USB デバイスの UMDF ドライバーで USB 選択的一時停止とシステム ウェイクを有効にする方法
USB クライアント ドライバー開発の概要