HID Injector Sample Question - need output report

I am new to driver development and have been looking for a driver sample that utilizes the Virtual HID Framework (VHF).

I came across the HID Injector sample, which appears to be what I have been looking for. It has the ability to receive HID input reports from an application and relay those reports to the operation system.

What is lacking is the ability to receive an output report from the operation system and relay it back to an application.

Here is what I have done so far to add this functionality.

  1. I added a callback (EvtVhfAsyncOperationWriteReport) to the VHF configuration for write report reception.

This seems to be working fine. I am using a keyboard (with LED capabilities) simulator as my HID descriptor. Whenever I press the CAPS LOCK on my keyboard, I see my callback being triggered and my KdPrint statements showing the expected output report in WinDbg.

  1. I added a callback (EvtIoRead) to the default queue configuration to handle read requests. This callback is triggered each time an application attempts a read from the device. I also verified this to be working in WinDbg.

So, how do I relay the report that I receive in the EvtVhfAsyncOperationWriteReport callback to the EvtIoRead request callback?

I was thinking of using a manual queue. Whenever the EvtVhfAsyncOperationWriteReport is triggered, it will take the received HID Transfer Packet convert it to a WDFREQUEST and write that request to the manual queue.

Likewise, whenever the EvtIoRead is triggered, it would read the queued request from the manual queue, extract the report information and then populate the WDFREQUEST and it received with the read request and pass it back to the calling application.

Is that a reasonable approach?

Any help provided is greatly appreciated.

You don’t want to use a WDFQUEUE for this. People read “queue” and they immediately thing, you know, of normal queues… singly or doubly linked lists. That’s not what a WDFQUEUE is. Rather, it’s a mechanism for storing and dispatching WDFREQUESTS according to various rules the driver writer establishes.

When you’re called at your EvtIoRead Event Processing Callback, you HAVE a WDFREQUEST… You simply want to save that HID Transfer Packet that you’re getting SOMEPLACE, retrieve that data, and return it to whoever sent you the read (you’d get the Output Buffer from the received WDFREQUEST that you get at EvtIoRead using WdfRequestRetrieveOutputBuffer, and copy the HID Transfer Packet to that buffer using memcpy (or, RtlCopyMemory if you want to be all kernel-mode correct and fancy).

The question becomes: HOW are you getting the HID Transfer Packet? What memory are you receiving that data into? If you’re allocating memory into which the HID Transfer Packet is stored with a WDFMEMORY Object (that’d be nice and handy), then you can store that Memory Object in a WDFCOLLECTION.

THEN, when you get called at EvtIoRead, grab the first Memory Object in the Collection, copy the buffer contents to the Request (as described above), and you’re good to go. Well, you have to free the Memory at some point, of course.

Hope that helps,

Peter

Thank you Peter! That worked!

Glad to hear that! Yay!!!

Peter

@jtomczyk, would you mind posting where you found the code? The GitHub repo I find references to has been archived and the code removed in the migration.

I got it from here:

https://github.com/ms-iot/samples