Creating IORequests from within KMDF driver - possible? How?

Hi, I have the following scenario: the Windows machine communicates via a serial line with a remote device. The protocol requires that an acknowledgement is sent back within a very short time, for certain messages. The time is so short that it’s likely that the application code, that receives the message, would occasionally fail to send back the required response, within the given time limits.

Because the acknowledgement is relatively simple, I had a thought of writing a filter driver, that will be attached to the serial port where the communication takes place. This driver would monitor incoming read requests and when the one that requires acknowledment is completed, I simply initiate sending of acknowledgment via the serial line from within the filter driver. This would save the round trip to the application level and also make the application code a bit simpler, as a part of the protocol would be handled inside the kernel driver.

I wonder if this scenario is possible - I see no reason why it shouldn’t be. However, I’m relatively new to drivers and only wrote code that handles WDFREQUEST objects. I don’t know how I could initiate the write operation (for the acknowledgement) on the same device (serial port), and whether there are particular steps or gotchas I need to be aware of for this to work?

Any hints/tips would be very much appreciated.

1 create the request with WdfRequestCreate 2 format the request for write 3 send it to the wdfiotarget that represents the serial port For 3 if you are a filter in the stack you can use the local io target WdfDeviceGetIoTarget to send it down the stack

Hi Doron, thanks for the prompt response. I was aware of (1) before making the original post. My problem was that I could not find any examples or documentation on how to proceed after creating an empty request. I suppose the code exists somewhere in the kernel, but that code is not visible to me.

I’ve checked KMDF documentation again after your reply, but I still couldn’t find a simple example on how to create a typical request, eg. for writing to a device, that would work. Maybe it’s there and I just missed it - if you know where I should look, that would be great help.

Also, I’m not sure about the lifecycle of the request object. Am I supposed to register a handler that gets invoked when the request is complete, so that I can decide whether to reuse it or destroy it, or that’s not an option and the framework takes over the managing of the request’s lifecycle after it was created?

(3) is an excellent idea, thanks for that.

PS. sorry, just found it as soon as I made the previous post: WdfIoTargetFormatRequestForWrite, correct? I found it in Developing drivers with… book, there were no links from the online documentation I could see.

see WdfIoTargetFormatRequestForWrite. it is really as simple as the list above. If you really want to see the same thing in a sample, see https://github.com/microsoft/Windows-driver-samples/blob/29709008d34efefd594d7da5ef67ee0d66f615fd/bluetooth/serialhcibus/Fdo.c#L1575

Windows-driver-samples/bluetooth/serialhcibus / Fdo.c : FdoWriteDeviceIO which calls HLP_AllocateResourceForWrite and WdfIoTargetFormatRequestForWrite

Thanks Doron, it looks exactly like what I was looking for, I’ll follow it up

how quickly does the response need to be sent?

In less than 20ms, in one case. In some other cases, less than 40ms. The application that communicates is written in C#, which adds another layer of uncertainty re how responsive it can be.

No matter what language you write it, 20 ms is too tight for a UM guaranteed response - thread quanta are around 15 ms. C# code certainly runs more slowly than it might, but that’s not likely an important factor in this case. The application will likely be more complicated to write (not less) because you have to handle the case where you have already responded, but can’t actually handle the data. And the driver may still miss this deadline, but your approach seems reasonable given these circumstances