仮想 HID フレームワーク (VHF) を使用して、HID ソース ドライバーを作成します。Write a HID source driver by using Virtual HID Framework (VHF)

要約Summary

  • オペレーティング システムに読み取りの HID レポートを送信するカーネル モード ドライバー フレームワーク (KMDF) HID ソース ドライバーを記述します。Write a Kernel-Mode Driver Framework (KMDF)HID source driver that submits HID Read Reports to the operating system.
  • 仮想の HID デバイス スタックの HID ソース ドライバーには、下位のフィルターとして VHF ドライバーを読み込みます。Load the VHF driver as the lower filter to the HID source driver in the virtual HID device stack.

適用対象Applies to

  • Windows 10Windows 10
  • HID デバイスのドライバー開発者向けDriver developers for HID devices

重要な APIImportant APIs

オペレーティング システムに HID ソース ドライバー HID レポート データの記述方法について説明します。Learn about writing a HID source driver that reports HID data to the operating system.

HID の入力デバイスでは、次のように – キーボード、マウス、ペン、タッチ、またはボタン、さまざまなレポートを送信しますオペレーティング システム、デバイスの目的を理解し、必要なアクションを実行できるようにします。A HID input device, such as – a keyboard, mouse, pen, touch, or button, sends various reports to the operating system so that it can understand the purpose of the device and take necessary action. レポートは、の形式でHID コレクションHID の使用します。The reports are in the form of HID collections and HID Usages. デバイスなど、Windows でサポートされるうちいくつかのさまざまなトランスポート経由でそれらのレポートを送信するI2C 経由で非表示にUSB 経由で HIDします。The device sends those reports over various transports, some of which are supported by Windows, such as HID over I2C and HID over USB. 場合によっては、トランスポートは、Windows でサポートされていない可能性があります。 またはレポートが実際のハードウェアに直接マップがいません。In some cases, the transport might not be supported by Windows, or the reports might not directly map to real hardware. 非 GPIO ボタンやセンサーなどの仮想ハードウェアの別のソフトウェア コンポーネントによって送信される HID 形式のデータのストリームがあります。It can be a stream of data in the HID format that is sent by another software component for virtual hardware such as, for non-GPIO buttons or sensors. たとえば、加速度計データから、携帯電話、PC にワイヤレス接続で送信しながら、ゲーム コント ローラーとして動作するかを検討してください。For example, consider accelerometer data from a phone that is behaving as a game controller, sent wirelessly to a PC. 別の例では、コンピューターをリモートから入力を受け取り Miracast デバイス UIBC プロトコルを使用しています。In another example, a computer can receive remote input from a Miracast device by using the UIBC protocol.

Windows の以前のバージョンで新しいトランスポート (実際のハードウェアまたはソフトウェア) をサポートするために記述しなければ、 HID トランスポート ミニドライバー Hidclass.sys、Microsoft 提供のインボックス クラス ドライバーにバインドします。In previous versions of Windows, to support new transports (real hardware or software), you had to write a HID transport minidriver and bind it to the Microsoft-provided in-box class driver, Hidclass.sys. など、クラス/ミニ ドライバー ペアに、HID コレクションが提供されている最上位のコレクション上位レベルのドライバーとアプリケーションのユーザー モードにします。The class/mini driver pair provided the HID collections, such as Top-Level Collections to upper-level drivers and user-mode applications. モデルでは、課題は、書き込み、ミニドライバーは、複雑な作業をすることができます。In that model, the challenge was writing the minidriver, which can be a complex task.

Windows 10 以降、新しい仮想 HID フレームワーク (VHF) トランスポート ミニドライバーを記述する必要はありません。Starting in Windows 10, the new Virtual HID Framework (VHF) eliminates the need to write a transport minidriver. 代わりにか WDM、KMDF のプログラミング インターフェイスを使用して、HID ソース ドライバーを作成することができます。Instead you can write a HID source driver by using KMDF or WDM programming interfaces. フレームワークは、ドライバーによって使用されるプログラミング要素を公開するための Microsoft から提供された静的ライブラリで構成されます。The framework consists of a Microsoft-provided static library that exposes programming elements used by your driver. 1 つまたは複数の子デバイスを列挙し、構築して仮想 HID ツリーの管理を実行する Microsoft 提供のインボックス ドライバーも含まれています。It also includes a Microsoft-provided in-box driver that enumerates one or more child devices and proceeds to build and manage a virtual HID tree.

  VHF をこのリリースでは、カーネル モードでのみ HID ソース ドライバーをサポートしています。Note  In this release, VHF supports a HID source driver only in kernel mode.

このトピックでは、フレームワーク、仮想の HID デバイス ツリー、および構成シナリオのアーキテクチャについて説明します。This topic describes the architecture of the framework, the virtual HID device tree, and the configuration scenarios.

仮想の HID デバイス ツリーVirtual HID device tree

この図では、デバイス ツリーは、ドライバーとその関連するデバイス オブジェクトを示します。In this image, the device tree shows the drivers and their associated device objects.

仮想の hid デバイス ツリー

HID ソース ドライバー (ドライバー)HID source driver (your driver)

HID のソースのドライバーは Vhfkm.lib へのリンクし、Vhf.h にはそのビルド プロジェクトが含まれています。The HID source driver links to Vhfkm.lib and includes Vhf.h in its build project. いずれかを使用して、ドライバーを記述できますWindows Driver Model (WDM) の一部であるカーネル モード ドライバー フレームワーク (KMDF)、または、 Windows Driver Frameworks (WDF)します。The driver can be written by using either Windows Driver Model (WDM) or Kernel-Mode Driver Framework (KMDF) that is part of the Windows Driver Frameworks (WDF). ドライバー、フィルター ドライバーまたはデバイス スタックの関数のドライバーとして読み込むことができます。The driver can be loaded as a filter driver or a function driver in the device stack.

VHF スタティック ライブラリ (vhfkm.lib)VHF static library (vhfkm.lib)

スタティック ライブラリには、Windows 10 用 Windows Driver Kit (WDK) では含まれます。The static library is included in the Windows Driver Kit (WDK) for Windows 10. ライブラリは、ルーチンには、HID ソース ドライバーによって使用されているコールバック関数などのプログラミング インターフェイスを公開します。The library exposes programming interfaces such as routines and callback functions that are used by your HID source driver. ドライバーが関数を呼び出すときに、スタティック ライブラリは、要求を処理する VHF ドライバーに要求を転送します。When your driver calls a function, the static library forwards the request to the VHF driver that handles the request.

VHF ドライバー (Vhf.sys)VHF driver (Vhf.sys)

Microsoft 提供のインボックス ドライバー。A Microsoft-provided in-box driver. このドライバーは HID ソース デバイス スタックで、ドライバーの下に下位のフィルター ドライバーとして読み込む必要があります。This driver must be loaded as a lower filter driver below your driver in the HID source device stack. 動的に VHF ドライバーは、子デバイスを列挙し、HID ソースのドライバーで指定されている 1 つまたは複数の HID デバイスの物理デバイス オブジェクト (PDO) を作成します。The VHF driver dynamically enumerates child devices and creates physical device objects (PDO) for one or more HID devices that are specified by your HID source driver. 列挙子のデバイスのトランスポートの HID ミニ ドライバー機能も実装します。It also implements the HID Transport mini-driver functionality of the enumerated child devices.

HID クラス ドライバーのペア (Hidclass.sys、Mshidkmdf.sys)HID class driver pair (Hidclass.sys, Mshidkmdf.sys)

Hidclass/Mshidkmdf ペアを列挙最上位のコレクション (TLC)実際の HID デバイスのこれらのコレクションを列挙する方法に似ています。The Hidclass/Mshidkmdf pair enumerates Top-Level Collections (TLC) similar to how it enumerates those collections for a real HID device. HID クライアントは、要求および実際の HID デバイスと同じよう TLCs の使用を続行できます。A HID client can continue to request and consume the TLCs just like a real HID device. このドライバーのペアは、デバイス スタックの関数のドライバーとしてインストールされます。This driver pair is installed as the function driver in the device stack.

  一部のシナリオでは HID クライアント HID データのソースを識別する必要があります。Note  In some scenarios, a HID client might need to identify the source of HID data. など、システムを組み込みセンサーして、同じ種類のリモートのセンサーからデータを受信します。For example, a system has a built-in sensor and receives data from a remote sensor of the same type. システムは、信頼性を 1 つのセンサーを選択する場合があります。The system might want to choose one sensor to be more reliable. 2 つのセンサーを区別するためには、コンテナー id が、TLC の HID クライアント クエリ、システムに接続されています。To differentiate between the two sensors connected to the system, the HID client queries for the container ID of the TLC. この場合は、HID ソースのドライバーは VHF によって仮想 HID デバイスのコンテナーの ID として報告されるコンテナー ID を提供できます。In this case, a HID source driver can provide the container ID, which is reported as the container ID of the virtual HID device by VHF.

HID クライアント (アプリケーション)HID client (application)

クエリを実行し、HID デバイス スタックによって報告される TLCs を使用します。Queries and consumes the TLCs that are reported by the HID device stack.

ヘッダーとライブラリの要件Header and library requirements

この手順では、オペレーティング システムにそのレポート ヘッドセット ボタンの単純な HID ソース ドライバーを記述する方法について説明します。This procedure describes how to write a simple HID source driver that reports headset buttons to the operating system. ここでは、このコードを実装するドライバーは VHF を使用して、ヘッドセット ボタンを報告する HID ソースとして機能するように変更されている既存の KMDF オーディオ ドライバーを指定できます。In this case, the driver that implements this code can be an existing KMDF audio driver that has been modified to act as a HID source reporting headset buttons by using VHF.

  1. Windows 10 の WDK に含まれる Vhf.h が含まれます。Include Vhf.h, included in the WDK for Windows 10.
  2. WDK に含まれる vhfkm.lib にリンクします。Link to vhfkm.lib, included in the WDK.
  3. デバイスがオペレーティング システムに報告する HID レポート記述子を作成します。Create a HID Report Descriptor that your device wants to report to the operating system. この例では、HID レポート記述子には、ヘッドセット ボタンがについて説明します。In this example, the HID Report Descriptor describes the headset buttons. レポートには、HID 入力レポート、サイズ 8 ビット (1 バイト) を指定します。The report specifies a HID Input Report, size 8 bits (1 byte). 最初の 3 つのビットはヘッドセットのミドル ネーム、ボリュームをおよびボリューム ダウン ボタンです。The first three bits are for the headset middle, volume-up, and volume-down buttons. 残りのビットは、使用されません。The remaining bits are unused.
UCHAR HeadSetReportDescriptor[] = {
    0x05, 0x01,         // USAGE_PAGE (Generic Desktop Controls)
    0x09, 0x0D,         // USAGE (Portable Device Buttons)
    0xA1, 0x01,         // COLLECTION (Application)
    0x85, 0x01,         //   REPORT_ID (1)
    0x05, 0x09,         //   USAGE_PAGE (Button Page)
    0x09, 0x01,         //   USAGE (Button 1 - HeadSet : middle button)
    0x09, 0x02,         //   USAGE (Button 2 - HeadSet : volume up button)
    0x09, 0x03,         //   USAGE (Button 3 - HeadSet : volume down button)
    0x15, 0x00,         //   LOGICAL_MINIMUM (0)
    0x25, 0x01,         //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,         //   REPORT_SIZE (1)
    0x95, 0x03,         //   REPORT_COUNT (3)
    0x81, 0x02,         //   INPUT (Data,Var,Abs)
    0x95, 0x05,         //   REPORT_COUNT (5)
    0x81, 0x03,         //   INPUT (Cnst,Var,Abs)
    0xC0,               // END_COLLECTION
};

仮想 HID デバイスを作成します。Create a virtual HID device

初期化を VHF_CONFIG 構造を呼び出すことによって、 VHF_CONFIG_INIT マクロと、呼び出し、 VhfCreate メソッド。Initialize a VHF_CONFIG structure by calling the VHF_CONFIG_INIT macro and then call the VhfCreate method. ドライバーを呼び出す必要がありますVhfCreateパッシブで_後レベル、 WdfDeviceCreate 呼び出し、通常、ドライバーの EvtDriverDeviceAdd コールバック関数。The driver must call VhfCreate at PASSIVE_LEVEL after the WdfDeviceCreate call, typically, in the driver's EvtDriverDeviceAdd callback function.

VhfCreate 呼び出し、ドライバーは非同期的に処理されたか、設定のデバイス情報 (ベンダーと製品 Id) にする必要がある操作など、特定の構成オプションを指定できます。In the VhfCreate call, the driver can specify certain configuration options, such as operations that must be processed asynchronously or setting device information (vendor/product IDs).

たとえば、アプリケーションは、TLC を要求します。For example, an application requests a TLC. ペアが要求の種類を決定し、適切な作成 HID クラス ドライバーのペアは、その要求を受信したときにHID ミニドライバー IOCTL要求および VHF に転送します。When the HID class driver pair receives that request, the pair determines the type of request and creates an appropriate HID Minidriver IOCTL request and forwards it to VHF. IOCTL 要求を取得するには、時に VHF 要求を処理、処理に HID ソース ドライバーに依存したり、ステータスの要求を完了_いない_サポートされています。Upon getting the IOCTL request, VHF can handle the request, rely on the HID source driver to process it, or complete the request with STATUS_NOT_SUPPORTED.

VHF では、これらの Ioctl を処理します。VHF handles these IOCTLs:

要求が場合GetFeatureSetFeatureWriteReport、またはGetInputReport、HID ソース ドライバーが登録されている、対応するコールバック関数、VHF では、コールバック関数を呼び出します。If the request is GetFeature, SetFeature, WriteReport, or GetInputReport, and the HID source driver registered a corresponding callback function, VHF invokes the callback function. その関数内で、HID ソース ドライバーは、取得または HID データ HID 仮想デバイスを設定します。Within that function, the HID source driver can get or set HID data for the HID virtual device. VHF の状態で要求が完了すると、ドライバーがコールバックを登録しない場合_いない_サポートされています。If the driver doesn't register a callback, VHF completes the request with status STATUS_NOT_SUPPORTED.

VHF は、これらの Ioctl の HID ソース ドライバー実装イベントのコールバック関数を呼び出します。VHF invokes HID source driver-implemented event callback functions for these IOCTLs:

その他のHID ミニドライバー IOCTL、VHF 状態要求が完了すると_いない_サポートされています。For any other HID Minidriver IOCTL, VHF completes the request with STATUS_NOT_SUPPORTED.

呼び出すことによって仮想 HID デバイスが削除された、 VhfDeleteします。The virtual HID device is deleted by calling the VhfDelete. EvtVhfCleanup ドライバーでは、仮想の HID デバイスのリソースが割り当てられている場合は、callback は必須です。The EvtVhfCleanup callback is required if the driver allocated resources for the virtual HID device. ドライバーを実装する必要があります、 EvtVhfCleanup関数し、その関数へのポインターを指定、 EvtVhfCleanupのメンバー VHF_CONFIG.The driver must implement the EvtVhfCleanup function and specify a pointer to that function in the EvtVhfCleanup member of VHF_CONFIG. EvtVhfCleanupする前に呼び出される、 VhfDelete呼び出しが完了します。EvtVhfCleanup is invoked before the VhfDelete call completes. 詳細については、次を参照してください。仮想 HID デバイスを削除します。For more information, see Delete the virtual HID device.

  非同期の操作の完了後、ドライバーを呼び出す必要があります VhfAsyncOperationComplete 操作の結果を設定します。Note  After an asynchronous operation completes, the driver must call VhfAsyncOperationComplete to set the results of the operation. または、コールバックから戻った後に後で、イベント コールバックからメソッドを呼び出すことができます。You can call the method from the event callback or at a later time after returning from the callback.

NTSTATUS
VhfSourceCreateDevice(
_Inout_ PWDFDEVICE_INIT DeviceInit
)

{
    WDF_OBJECT_ATTRIBUTES   deviceAttributes;
    PDEVICE_CONTEXT deviceContext;
    VHF_CONFIG vhfConfig;
    WDFDEVICE device;
    NTSTATUS status;

    PAGED_CODE();

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
    deviceAttributes.EvtCleanupCallback = VhfSourceDeviceCleanup;

    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);

    if (NT_SUCCESS(status))
    {
        deviceContext = DeviceGetContext(device);

        VHF_CONFIG_INIT(&vhfConfig,
            WdfDeviceWdmGetDeviceObject(device),
            sizeof(VhfHeadSetReportDescriptor),
            VhfHeadSetReportDescriptor);

        status = VhfCreate(&vhfConfig, &deviceContext->VhfHandle);

        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "VhfCreate failed %!STATUS!", status);
            goto Error;
        }

        status = VhfStart(deviceContext->VhfHandle);
        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "VhfStart failed %!STATUS!", status);
            goto Error;
        }

    }

Error:
    return status;
}

HID 入力レポートを送信します。Submit the HID input report

レポートを送信する HID 入力呼び出して VhfReadReportSubmitします。Submit the HID input report by calling VhfReadReportSubmit.

通常、HID デバイスでは、割り込みを介して入力のレポートを送信して状態の変更に関する情報を送信します。Typically, a HID device sends information about state changes by sending input reports through interrupts. たとえば、ヘッドセット デバイス ボタンの状態が変更されたときに、レポートを送信可能性があります。For example, the headset device might send a report when the state of a button changes. このようなイベントでは、ドライバーの割り込みサービス ルーチン (ISR) が呼び出されます。In such an event, the driver's interrupt service routine (ISR) is invoked. ルーチン、ドライバーは遅延プロシージャ呼び出し (DPC) を入力のレポートを処理し、オペレーティング システムに情報を送信する、VHF に送信をスケジュール可能性があります。In that routine, the driver might schedule a deferred procedure call (DPC) that processes the input report and submits it to VHF, which sends the information to the operating system. 既定では、VHF バッファーのレポートとでやり取りされるように入力の HID レポートを送信する HID ソースのドライバーを開始できます。By default, VHF buffers the report and the HID source driver can start submitting HID Input Reports as they come in. これは、複雑な同期を実装する HID ソース ドライバーの必要がありません。This and eliminates the need for the HID source driver to implement complex synchronization.

HID ソースのドライバーでは、保留中のレポートのバッファリング ポリシーを実装することで、入力のレポートを送信できます。The HID source driver can submit input reports by implementing the buffering policy for pending reports. 重複するバッファリングを避けるためには、HID ソースのドライバーを実装できます、 EvtVhfReadyForNextReadReport VHF にこのコールバックが呼び出されるかどうかのコールバック関数と保持を追跡します。To avoid duplicate buffering, the HID source driver can implement the EvtVhfReadyForNextReadReport callback function and keep track of whether VHF invoked this callback. HID のソースのドライバーを呼び出すことができる場合、呼び出された以前 VhfReadReportSubmit レポートを送信します。If it was previously invoked, the HID source driver can call VhfReadReportSubmit to submit a report. 待機するEvtVhfReadyForNextReadReportを呼び出すことができる前に呼び出されるVhfReadReportSubmitもう一度です。It must wait for EvtVhfReadyForNextReadReport to get invoked before it can call VhfReadReportSubmit again.

VOID
MY_SubmitReadReport(
    PMY_CONTEXT  Context,
    BUTTON_TYPE  ButtonType,
    BUTTON_STATE ButtonState
    )
{
    PDEVICE_CONTEXT deviceContext = (PDEVICE_CONTEXT)(Context);

    if (ButtonState == ButtonStateUp) {
        deviceContext->VhfHidReport.ReportBuffer[0] &= ~(0x01 << ButtonType);
    } else {
        deviceContext->VhfHidReport.ReportBuffer[0] |=  (0x01 << ButtonType);
    }

    status = VhfSubmitReadReport(deviceContext->VhfHandle, &deviceContext->VhfHidReport);

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,"VhfSubmitReadReport failed %!STATUS!", status);
    }
}

仮想の HID デバイスを削除します。Delete the virtual HID device

呼び出すことにより、仮想の HID デバイスを削除 VhfDeleteします。Delete the virtual HID device by calling VhfDelete.

VhfDelete 同期呼び出すことができるまたは Wait パラメーターの値を非同期的を指定します。VhfDelete can be called synchronous or asynchronously by specifying the Wait parameter. 同期呼び出しでは、パッシブに、メソッドを呼び出す必要があります_からなど、レベル、 EvtCleanupCallback のデバイス オブジェクト。For a synchronous call, the method must be called at PASSIVE_LEVEL, such as from EvtCleanupCallback of the device object. VhfDelete仮想 HID デバイスを削除した後に返されます。VhfDelete returns after deleting the virtual HID device. ドライバーを呼び出す場合VhfDelete VHF を呼び出すし、すぐに返されます。 非同期的に EvtVhfCleanup 削除操作が完了した後。If the driver calls VhfDelete asynchronously, it returns immediately and VHF invokes EvtVhfCleanup after the delete operation is complete. ディスパッチの最大のメソッドを呼び出すことができます_レベル。The method can be called at maximum DISPATCH_LEVEL. この場合、ドライバーを登録して、実装がある必要があります、 EvtVhfCleanupコールバック関数が、以前に呼び出されたときに VhfCreateします。In this case, the driver must have registered and implemented an EvtVhfCleanup callback function when it previously called VhfCreate. HID のソースのドライバーが仮想の HID デバイスを削除するときのイベントのシーケンスを次に示します。Here is the sequence of events when HID source driver wants to delete the virtual HID device:

  1. VHF への呼び出しを開始する HID ソース ドライバーを停止します。HID source driver stops initiating calls into VHF.
  2. HID ソース呼び出し VhfDelete 待機を FALSE に設定します。HID source calls VhfDelete with Wait set to FALSE.
  3. VHF は、HID ソース ドライバーによって実装されるコールバック関数の呼び出しを停止します。VHF stops invoking callback functions implemented by the HID source driver.
  4. VHF PnP マネージャーに存在しないデバイスをレポート作成を開始します。VHF starts reporting the device as missing to PnP Manager. この時点では、VhfDelete 呼び出しを返す可能性があります。At this point, the VhfDelete call might return.
  5. デバイスが紛失したデバイスとして報告されると、VHF を呼び出す EvtVhfCleanup HID ソースのドライバーには、その実装が登録されている場合。When the device is reported as a missing device, VHF invokes EvtVhfCleanup if the HID source driver registered its implementation.
  6. EvtVhfCleanup 返します、VHF のクリーンアップを実行します。After EvtVhfCleanup returns, VHF performs its cleanup.
VOID
VhfSourceDeviceCleanup(
_In_ WDFOBJECT DeviceObject
)
{
    PDEVICE_CONTEXT deviceContext;

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");

    deviceContext = DeviceGetContext(DeviceObject);

    if (deviceContext->VhfHandle != WDF_NO_HANDLE)
    {
        VhfDelete(deviceContext->VhfHandle, TRUE);
    }

}

HID ソース ドライバーをインストールします。Install the HID source driver

HID ソースのドライバーをインストールする INF ファイルで宣言すること Vhf.sys 低いフィルター ドライバーとして HID ソース ドライバーを使用することを確認、 AddReg ディレクティブします。In the INF file that installs the HID source driver, make sure that you declare Vhf.sys as a lower filter driver to your HID source driver by using the AddReg Directive.

[HIDVHF_Inst.NT.HW]
AddReg = HIDVHF_Inst.NT.AddReg

[HIDVHF_Inst.NT.AddReg]
HKR,,"LowerFilters",0x00010000,"vhf"

ヒューマン インターフェイス デバイスHuman Interface Device