HID レポートを取得する

この記事では、ユーザーモード アプリケーションとカーネルモード ドライバーが HID コレクションから HID レポートを取得する方法について説明します。

ユーザー モード アプリケーションによる HID レポートの取得

このセクションでは、ReadFile または HidD_GetXxx ルーチンを使用したユーザーモード アプリケーションによる HID 入力レポートまたは HID 機能レポートの取得について説明します。

ただし、アプリケーションでは、HidD_GetXxx ルーチンのみを使用して、デバイスの現在の状態を取得する必要があります。 アプリケーションが HidD_GetInputReport を使用して入力レポートを継続的に取得しようとすると、レポートが失われる可能性があります。 さらに、一部のデバイスは HidD_GetInputReport をサポートしていないため、このルーチンを使用すると応答しなくなります。

ReadFile の使用

アプリケーションは、CreateFile を使用して取得した開いているファイル ハンドルを使って、コレクション上のファイルを開きます。 アプリケーションが ReadFile を呼び出すと、HID クライアント ドライバーはリング バッファーでレポートをバッファーするため、重複する I/O をアプリケーションで指定する必要はありません。 ただし、アプリケーションは重複した I/O を使用することで、未処理の読み取り要求を複数持つことができます。

HidD_GetXxx ルーチンの使用

アプリケーションは、次の HIDClass サポート ルーチンを使用して、HID コレクションから最新の入力レポートと機能レポートを取得できます。

  • HidD_GetInputReport: HID コレクション (Windows XP 以降のバージョン) から入力レポートを返します。
  • HidD_GetFeature: HID コレクションから機能レポートを返します。

アプリケーションは、特定のレポートを返すように要求できます。 HidD_GetXxx ルーチンを使用して特定のレポートを取得するために、アプリケーションはレポート出力バッファーを割り当て、バッファーをゼロ初期化し、バッファー内の最初のバイトを特定のレポート ID に設定します。 詳細については、「HID レポートを初期化する」を参照してください。

カーネル モード ドライバーによる HID レポートの取得

このセクションでは、HID 入力レポートを継続的に取得するための主要なアプローチとして、カーネルモード ドライバーが IRP_MJ_READ 要求を使用する方法について説明します。

読み取り要求が連続している場合は、コレクションから受信した順序で入力レポートが返されます。 ドライバーは、IOCTL_HID_GET_Xxx 要求を使用して入力レポートと機能レポートを取得することもできます。 ただし、デバイスの現在の状態を取得するには、IOCTL_HID_GET_Xxx 要求のみを使用する必要があります。 ドライバーが IOCTL_HID_GET_INPUT_REPORT を使用して入力レポートを継続的に取得しようとすると、レポートが失われる可能性があります。 さらに、一部のデバイスは IOCTL_HID_GET_INPUT_REPORT をサポートしていないため、この要求が使用されると応答しなくなります。

IRP_MJ_READ 要求の使用

入出力要求パケット (IRP) の使用方法と再利用方法に関する一般的な情報については、「IRP の処理」と「IRP の再利用」を参照してください。

ドライバーが IRP を再利用する場合、IRP の IoCompletion ルーチンは、状態が STATUS_MORE_PROCESSING_REQUIRED (IRP を解放しない) で要求を完了する必要があります。 ドライバーが IRP を必要としなくなった場合は、IoCompleteRequestIoFreeIrp を呼び出して IRP を完了し、解放する必要があります。 たとえば、ドライバーは通常、そのアンロード ルーチンで、またはデバイスが削除された後に IRP を完了し、解放する可能性があります。

ドライバーが 1 つの読み取り要求にのみ IRP を使用する場合、IRP の IoCompletion ルーチンは IRP を完了して解放し、STATUS_SUCCESS を返す必要があります。

ドライバーは、入力レポートを要求する前に、最初に非ページ メモリ プールからゼロに初期化された入力レポート バッファーを割り当てる必要があります。 バッファーのサイズ (バイト単位) は、HID コレクションの HIDP_CAPS 構造体の InputReportByteLength メンバーによって指定されます。 その後、ドライバーは MDL を使用して、読み取り要求の入力レポート バッファーをマップする必要があります。 ドライバーは、IoAllocateMdl を呼び出して入力レポート バッファーの MDL を割り当て、読み取り IRP の Irp->MdlAddress メンバーを入力レポート バッファーの MDL アドレスに設定します。 レポート バッファーと MDL は、不要になったら解放する必要があります。

ドライバーは、読み取り IRP の MDL アドレスを設定するだけでなく、次の下位レベルのドライバーの I/O スタックの場所も設定する必要があります。 ドライバーは、IoGetNextIrpStackLocation を呼び出すことで、次の下位レベルのドライバーの I/O スタックの場所へのアクセスを取得します。 ドライバーは、I/O スタックの場所の次のメンバーを設定します。

  • Parameters.Read.Length: 読み取りバッファーのサイズ (バイト単位) に設定します。 このサイズは、HID コレクションの HIDP_CAPS 構造体の InputReportByteLength メンバーによって指定された値以上である必要があります。
  • Parameters.Read.Key: 0 に設定します。
  • Parameters.Read.ByteOffset.QuadPart: 0 に設定します。
  • MajorFunction: IRP_MJ_READ に設定します。
  • FileObject: HID コレクションで開いているファイルを表すファイル オブジェクト ポインターに設定します。

ドライバーは、入力レポートを取得すると、「HID レポートを解釈する」で説明されているように、制御データにアクセスできるようになります。

IOCTL_HID_GET_Xxx 要求の使用

ドライバーは、次の I/O 要求を使用して、HID コレクションから最新の入力レポートと機能レポートを取得できます。

ドライバーは、特定のレポートを返すように要求できます。 これらの I/O 要求を使用して特定のレポートを取得するために、ドライバーはまず出力レポート バッファーを割り当て、バッファーをゼロ初期化してから、バッファー内の最初のバイトを特定のレポート ID に設定します。

詳細については、「HID レポートを解釈する」を参照してください。