Obtaining HID Reports by Kernel-Mode Drivers
This topic discusses how a kernel-mode driver should use IRP_MJ_READ requests as its main approach for continuously obtaining HID input reports.
Consecutive read requests return input reports in the order in which they were received from the collection. The driver can also use IOCTL_HID_GET_Xxx requests to obtain input and feature reports. However, a driver should only use these I/O requests to obtain the current state of a device. If the driver attempts to use IOCTL_HID_GET_INPUT_REPORT to continuously obtain input reports, reports can be lost. In addition, some devices might not support IOCTL_HID_GET_INPUT_REPORT, and will become unresponsive if this request is used.
The following sections provide more information.
Non-WDM Windows 2000 drivers, and drivers for Windows XP and later versions, can use a single IRP for all read requests to a device. However, Windows 2000 WDM drivers must allocate a new IRP for each read request. For general information about how to use and reuse IRPs, see Handling IRPs and Reusing IRPs.
If a driver reuses an IRP, the IRP's IoCompletion routine should complete the request with a status of STATUS_MORE_PROCESSING_REQUIRED (and not free the IRP). When the driver no longer requires the IRP, it should complete and free the IRP by calling IoCompleteRequest and IoFreeIrp. For example, a driver might typically complete and free the IRP in its Unload routine, or after a device is removed.
If a driver uses an IRP for only one read request, the IRP's IoCompletion routine should complete and free the IRP, and return STATUS_SUCCESS.
Before a driver can request an input report, it must first allocate a zero-initialized input report buffer from nonpaged memory pool. The size, in bytes, of the buffer is specified by the InputReportByteLength member of a HID collection's HIDP_CAPS structure. A driver must then use an MDL to map the input report buffer for a read request. The driver calls IoAllocateMdl to allocate the MDL for an input report buffer, and sets the read IRP's Irp->MdlAddress member to the MDL address of the input report buffer. The driver should free the report buffer and the MDL when they are no longer required.
In addition to setting the read IRP's MDL address, the driver must also set the I/O stack location of the next lower-level driver. A driver obtains access to the I/O stack location of the next lower-level driver by calling IoGetNextIrpStackLocation. The driver sets the following members of the I/O stack location:
Set to the size, in bytes, of the read buffer. This must be greater than or equal to the value specified by the InputReportByteLength member of a HID collection's HIDP_CAPS structure.
Set to zero.
Set to zero.
Set to IRP_MJ_READ.
Set to the file object pointer that represents the open file on the HID collection.
After the driver has obtained an input report, it can access control data, as described in Interpreting HID Reports.
A driver can use the following I/O requests to obtain the most current input and feature reports from a HID collection:
Returns an input report from a HID collection (Windows XP and later versions).
Returns a feature report from a HID collection.
A driver can request the return of a specific report. To retrieve a specific report using these I/O requests, the driver first allocates the output report buffer, then zero-initializes the buffer, and sets the first byte in the buffer to the specific report ID. For more information, see Interpreting HID Reports.