发送 HID 报告
本文介绍了用户模式应用程序和内核模式驱动程序如何向 HID 集合发送 HID 报告。
通过用户模式应用程序发送 HID 报告
用户模式应用程序使用 WriteFile 将输出报告持续发送到 HID 集合。 还可以使用 HidD_SetXxx 例程向集合发送输出报告和功能报告。 但是,只能使用 HidD_SetXxx 例程来设置集合的当前状态。 某些设备可能不支持 HidD_SetOutputReport,因此在使用此例程时会出现无响应的情况。
WriteFile 例程
使用写入请求将输出报告发送到 HID 集合。 用户模式应用程序创建输出报告后,可以使用 WriteFile 将输出报告发送到集合。
HidD_SetXxx 例程
使用这些 HIDClass 支持例程 向 HID 集合发送 HID 报告:
- HidD_SetOutputReport:向 HID 集合发送输出报告(Windows XP 及更高版本)。
- HidD_SetFeature:向 HID 集合发送功能报告。
通过内核模式驱动程序发送 HID 报告
内核模式驱动程序使用 IRP_MJ_WRITE 请求持续向 HID 集合发送输出报告。 还可以使用 IOCTL_HID_SET_Xxx 请求向集合发送输出报告和功能报告。 但是,只能使用 IOCTL_HID_SET_Xxx 请求来设置集合的当前状态。 某些设备可能不支持 IOCTL_HID_SET_OUTPUT_REPORT 并在使用该请求时变得无响应。
IRP_MJ_WRITE 请求
非 WDM Windows 2000 驱动程序以及 Windows XP 和更高版本的驱动程序可以对发送到集合的所有写入请求使用单个 IRP。 但是,Windows 2000 WDM 驱动程序必须为每个写入请求分配一个新的 IRP。 有关如何使用和重用 IRP 的详细信息,请参阅处理 IRP 和重复使用 IRP。
如果驱动程序重复使用写 IRP,则 IRP 的 IoCompletion 例程应在状态为 STATUS_MORE_PROCESSING_REQUIRED 时完成请求(而不是释放 IRP)。 当驱动程序不再需要 IRP 时,应通过调用 IoCompleteRequest 和 IoFreeIrp 来完成和释放 IRP。 例如,驱动程序通常会在其 Unload 例程中完成并释放 IRP,或者在设备被移除后完成并释放 IRP。
如果驱动程序仅为一个写入请求使用 IRP,则 IRP 的 IoCompletion 例程应完成并释放 IRP,并返回 STATUS_SUCCESS。
当驱动程序发送输出报告时,必须首先初始化和设置输出报告缓冲区,如初始化 HID 报告中所述。 然后,驱动程序必须使用 MDL 映射写入请求的输出报告缓冲区。 驱动程序调用 IoAllocateMdl 为输出报告分配 MDL,并将写入 IRP's Irp->MdlAddress 成员设置为输出报告缓冲区的 MDL 地址。 当不再需要报告缓冲区和 MDL 时,驱动程序必须释放它们。
除了设置写入 IRP 的 MDL 地址外,驱动程序还必须设置下一级驱动程序的 I/O 堆栈位置。 驱动程序通过调用 IoGetNextIrpStackLocation 来访问下一级驱动程序的 I/O 堆栈位置。 驱动程序会设置 I/O 堆栈位置的以下成员:
- Parameters.Write.Length:设置为输出报告的长度(以字节为单位)。 将此成员设置为 HID 集合的输出报告长度,该长度由集合的 HIDP_CAPS 结构中的 OutputReportByteLength 成员指定。
- Parameters.Write.Key:设置为零。
- Parameters.Write.ByteOffset.QuadPart:设置为零。
- MajorFunction:设置为
IRP_MJ_WRITE
。 - FileObject:设置为表示 HID 集合上打开文件的文件对象指针。
IOCTL_HID_SET_Xxx 请求
还可以使用以下 I/O 请求向 HID 集合发送输出和功能报告:
- IOCTL_HID_SET_OUTPUT_REPORT:向集合发送输出报告(Windows XP 及更高版本)。
- IOCTL_HID_SET_FEATURE:将功能报告发送到集合。