Inject additional IPRs in lower filter driver

We have a well working LowerFilter HIDclass filter driver.

For various reasons we like to inject additional IRPs on the way up to the HIDclass driver, for example to simulate momentum scrolling or a mouse button lift.

Right now we park one IRP and complete it when needed. But if we park more than one IRP the device doesn’t work any more as we don’t get any new IRPs in, so this is a doggy solution.

Is it somehow possible to inject additional IRPs on the way up? What would be the best way to do this?

If it’s not possible would it be possible to redirect IRPs from the PDO sideband communication into the actual device stream? How could this be done?

Any guidance is appreciated.

Well, I used the wrong terminology in my question. Of course I mean a WDF-Request, not an IPR.

If you want to inject keyboard and mouse packets in a simple way you are too far down in the stack. Instead you should be a device upper filter in the hid keyboard and mouse stacks and you can easily inject data via the service callback without messing around with io requests. The only effective way to IMMEDIATELY inject as a lower filter below the mini port is to 1 send you own requests down to the hardware 2 when the hw request completes if there are no queued hid requests, queue the data. If there are pended hid requests, complete one with the data 3 for incoming hid requests, if there is queued data, complete it with the data. If no data is queued, queue the request 4 When you want to inject data, complete the pended hid request with it. If no pended hid request, queue the data and add logic to 3 to check for it.

Thanks Doran, your help is much appreciated.

The lower filter driver has to be in place to make the raw input stream HID compliant, there is no way around this.

Using an additional upper filter driver would require syncing both drivers (injecting the additional input at the right time).

Not sure what is wiser in terms of maintenance and complexity:

  • Having two different drivers and syncing both with some kind of inter-driver-communication.

  • Have only the lower filter driver and sending down WDF requests to the hardware as Doran suggests.

IMHO one driver working on its own is far simpler than two drivers trying to coordinate state.

Thanks again Doran. My gut feeling tells me that as well. Will try to stay with the one lower filter driver.

One more question about sending down my own requests to the hardware, as there isn’t much in the documentation. Is this correct:

  1. Create my own requests with WdfRequestCreateFromIrp() using a IRP from the HID request,
  2. Send it down to the hardware with my own completion routine.
  3. In the completion routine, buffer the data and then use WdfObjectDelete().
  4. Copy the data into the initial HID request and call WdfRequestComplete() for the HID request.

Or in 1. must I use WdfRequestCreate() to built the request from scratch?

Is this a USB device? If so, your implementation will be much simpler as you can use the continuous reader functionality in WDFUSBPIPE, https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/how-to-use-the-continous-reader-for-getting-data-from-a-usb-endpoint--umdf- . The trick as a lower filter is create the WDFUSBDEVICE with the select config that is sent down by hidclass and not selecting a config on your own.

If you are not controlling a usb device, step one is to create your own request (or perhaps 2) and start sending it in EvtDeviceSelfManagedIoInit. When the request completes, your simplest choice is to reuse the request (WdfRequestReuse), not delete it. In the completion routine, you check to see if you have a queued HID request from above. If yes, copy the data and complete it. If there is no queued HID request from above, you must copy the data into your own storage and then when the hid request from above arrives, copy the data into it in the dispatch routine

It’s a hybrid device: USB or Bluetooth, the user can choose what connection to use. The filter driver handles the URB and BRB processing currently in a very similar way. There is unfortunately no Bluetooth continuous reader, but we’ll figure it out, if you have a link to some example code that would be great (haven’t search for it yet).

Again thanks for all your advice, it really helps a lot.

I can’t think of a good continuous reader example on which you can start from. You should use a WDFQUEUE to pend all of the upper HID requests that are sent to your driver.