WDF serial not functionally equivalent to serial.sys

The documentation on the the WDF version of the serial.sys drivers says it’s functionally equivalent, but I have found that it doesn’t handle asynchronous I/O the same.

I’m using Boost and IOCP to perform multiple asynchronous reads. My test application opens COM1 initiates 3 reads, closes and repeats one more time. When I use the original serial.sys the reads get canceled and everything works just fine. When I use wdfserial.sys the reads block and execution doesn’t continue until there is something to read.

Has anyone seen similar behavior? I have a driver based on the wdfserial sample that isn’t handling IOCP properly and would really like to avoid porting all those changes back into the wdm driver to get around this “issue”. Primarily because I don’t understand why the wdm driver works when the wdf version doesn’t.

Shane Corbin wrote:

The documentation on the the WDF version of the serial.sys
drivers says it’s functionally equivalent, but I have found that
it doesn’t handle asynchronous I/O the same.

I believe that.

My test application opens COM1 initiates 3 reads, closes and
repeats one more time.

Sorry … what does that mean exactly?

I’ll just post my example source to avoid ambiguity in my explanation…
http://pastebin.com/YJPs4f67

Digging into this further it looks like the new wdf version isn’t canceling the “current” read irp, whereas the wdm version of serial.sys is somehow cancelling it.

With 3 reads it looks like 2 of them get inserted into a queue for reading, when the COM closes it gets a SerialEvtCanceldOnQueue() and cancels the two in the queue. However, the current read doesn’t get cancelled in the wdf version and instead I’m stuck in a loop in the SerialIntervalReadTimeout() routine because SerialCancelCurrentRead() never got called. Had it gotten called extension->CountOnLastRead = SERIAL_COMPLETE_READ_CANCEL would have gotten set and I would break from having SerialIntervalReadTimeout() called continuously.

There seems to be a fundamental difference in the wdm vs wdf drivers such that the cancel routine isn’t getting assigned, but I’m having trouble figuring out how to appropriately assign it.

That looks like a fundamental bug in WDF serial

It looks like in the wdf serial sample, in the read.c file within the SerialUpdateAndSwitchToUser() function there is a section #if 0’d out that would have set the cancel routine. Trying to add it back in using SerialSetCancelRoutine() instead of IoSetCancelRoutine() I still can’t get it to work. I keep getting ASSERT failures and I can’t explain why.

I wonder why that section is ifdefd out of the sample.

> It looks like in the wdf serial sample

WDF queues automatically support cancellation, so, maybe IoSetCancelRoutine should not be used.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Stepping through the execution 2 of my 3 read requests are in the queue when I close the serial port the third is the current read request and is not in the queue. It is the current request that fails to get cancelled properly.

Shane Corbin wrote:

Stepping through the execution 2 of my 3 read requests are
in the queue when I close the serial port the third is the current
read request and is not in the queue. It is the current request
that fails to get cancelled properly.

Here’s what I don’t understand (admittedly because I am not familiar with the WDF serial example). Why is there the notion of a “current request” at all? Isn’t the current request merely the one in the front of the queue? Seems to me the driver should not be taking it out of the queue, at all, unless it is about to complete it.