发送 HID 报告

本文介绍了用户模式应用程序和内核模式驱动程序如何向 HID 集合发送 HID 报告。

通过用户模式应用程序发送 HID 报告

用户模式应用程序使用 WriteFile 将输出报告持续发送到 HID 集合。 还可以使用 HidD_SetXxx 例程向集合发送输出报告和功能报告。 但是,只能使用 HidD_SetXxx 例程来设置集合的当前状态。 某些设备可能不支持 HidD_SetOutputReport,因此在使用此例程时会出现无响应的情况。

WriteFile 例程

使用写入请求将输出报告发送到 HID 集合。 用户模式应用程序创建输出报告后,可以使用 WriteFile 将输出报告发送到集合。

HidD_SetXxx 例程

使用这些 HIDClass 支持例程 向 HID 集合发送 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 时,应通过调用 IoCompleteRequestIoFreeIrp 来完成和释放 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 集合发送输出和功能报告: