Asynchous IO using a WDF parallel IO queue

I have a USB device and a corresponding USB driver. I am using an interrupt
pipe to handle the occasional data that comes in from the USB device after
the USB device has received it from a separate infrared remote device. The
application has sent the driver an event object that the driver is using to
signal when data has been received.

I haven’t done this yet but it looks like an overlapped IOCTL should be used
where the application sends the IOCTL and the driver fills a buffer supplied
by the IOCTL when data has been received on the interrupt pipe. I have used
the interrupt pipe and external signaled event before but I have never used
overlapped I/O so I’m looking for a little reassurance that I’m approaching
this in the right way. I would create a parallel IO queue just for this
task. All other IOCTLs I’m handling with a default serial queue.

I have been trying to get the 1394 sample running to see exactly how the
overlapped I/O works but I’m having some trouble. In my case, the
Win1394.exe starts, I attach WinDbg to the process, I put a breakpoint at
Win1394!w1394_AddVirtualDriver, break, step through it, and find that the
1394API.dll call to AddVirtualDriver is never executed because the
1394API.dll module does not load. I forced the 1394API.dll load using
WinDbg but it still didn’t execute.

So, if there is a better or different way to transfer this asychronous data
from the USB interrupt pipe to the application, please point me in the right
direction.

Thanks
-Dave

David Voeller wrote:

I have a USB device and a corresponding USB driver. I am using an interrupt
pipe to handle the occasional data that comes in from the USB device after
the USB device has received it from a separate infrared remote device.

Why does it use an interrupt pipe? If it is “occasional data”, it would
make more sense to use a bulk pipe, so as not to block out bandwidth
unnecessarily.

The
application has sent the driver an event object that the driver is using to
signal when data has been received.

I haven’t done this yet but it looks like an overlapped IOCTL should be used
where the application sends the IOCTL and the driver fills a buffer supplied
by the IOCTL when data has been received on the interrupt pipe. I have used
the interrupt pipe and external signaled event before but I have never used
overlapped I/O so I’m looking for a little reassurance that I’m approaching
this in the right way. I would create a parallel IO queue just for this
task. All other IOCTLs I’m handling with a default serial queue.

You don’t really need overlapped I/O for this. Just have the app launch
a separate thread, submit the ioctl, and wait. The only reason you
would need overlapped I/O is if you were doing other I/O on the same
handle, and you didn’t want to open a new handle just for this task.

Remember that the use of overlapped I/O by the application is entirely
irrelevant to the driver. The only difference is in the way the
application gets its response. The driver treats the IRPs just the same.

So, if there is a better or different way to transfer this asychronous data
from the USB interrupt pipe to the application, please point me in the right
direction.

A blocked ioctl is a fine way to get this kind of notification. I use
it regularly. It is philosophically similar to the event method, with
the added benefit that you can return information when you complete the IRP.

The overlapped I/O question is really separate; it’s an application
implementation issue. There are good samples on the web showing how to
do overlapped I/O properly.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

For completeness, if you are going to pass a process context specific
handle (like a handle to an event) you must call
ObReferenceObjectByHanle in your WDFDEVICE’s EvtIoInCallerContext
callback and not in your EvtIoDefault/Ioctl callback. Why? Because
EvtIoDefault/Ioctl are not guaranteed to be in the context of the
calling process when they are invoked and if you made the ObRef call in
EvtIoDefault/Ioctl you could be referencing a random handle table.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Thursday, November 30, 2006 4:07 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Asynchous IO using a WDF parallel IO queue

David Voeller wrote:

I have a USB device and a corresponding USB driver. I am using an
interrupt
pipe to handle the occasional data that comes in from the USB device
after
the USB device has received it from a separate infrared remote device.

Why does it use an interrupt pipe? If it is “occasional data”, it would
make more sense to use a bulk pipe, so as not to block out bandwidth
unnecessarily.

The
application has sent the driver an event object that the driver is
using to
signal when data has been received.

I haven’t done this yet but it looks like an overlapped IOCTL should
be used
where the application sends the IOCTL and the driver fills a buffer
supplied
by the IOCTL when data has been received on the interrupt pipe. I
have used
the interrupt pipe and external signaled event before but I have never
used
overlapped I/O so I’m looking for a little reassurance that I’m
approaching
this in the right way. I would create a parallel IO queue just for
this
task. All other IOCTLs I’m handling with a default serial queue.

You don’t really need overlapped I/O for this. Just have the app launch
a separate thread, submit the ioctl, and wait. The only reason you
would need overlapped I/O is if you were doing other I/O on the same
handle, and you didn’t want to open a new handle just for this task.

Remember that the use of overlapped I/O by the application is entirely
irrelevant to the driver. The only difference is in the way the
application gets its response. The driver treats the IRPs just the
same.

So, if there is a better or different way to transfer this asychronous
data
from the USB interrupt pipe to the application, please point me in the
right
direction.

A blocked ioctl is a fine way to get this kind of notification. I use
it regularly. It is philosophically similar to the event method, with
the added benefit that you can return information when you complete the
IRP.

The overlapped I/O question is really separate; it’s an application
implementation issue. There are good samples on the web showing how to
do overlapped I/O properly.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Thanks for the suggestions. I’m still dealing with no power because of the
snow storm (St. Louis) but I will hopefully get to the suggestions soon.

“David Voeller” wrote in message news:xxxxx@ntdev…
>I have a USB device and a corresponding USB driver. I am using an
>interrupt pipe to handle the occasional data that comes in from the USB
>device after the USB device has received it from a separate infrared remote
>device. The application has sent the driver an event object that the
>driver is using to signal when data has been received.
>
> I haven’t done this yet but it looks like an overlapped IOCTL should be
> used where the application sends the IOCTL and the driver fills a buffer
> supplied by the IOCTL when data has been received on the interrupt pipe.
> I have used the interrupt pipe and external signaled event before but I
> have never used overlapped I/O so I’m looking for a little reassurance
> that I’m approaching this in the right way. I would create a parallel IO
> queue just for this task. All other IOCTLs I’m handling with a default
> serial queue.
>
> I have been trying to get the 1394 sample running to see exactly how the
> overlapped I/O works but I’m having some trouble. In my case, the
> Win1394.exe starts, I attach WinDbg to the process, I put a breakpoint at
> Win1394!w1394_AddVirtualDriver, break, step through it, and find that the
> 1394API.dll call to AddVirtualDriver is never executed because the
> 1394API.dll module does not load. I forced the 1394API.dll load using
> WinDbg but it still didn’t execute.
>
> So, if there is a better or different way to transfer this asychronous
> data from the USB interrupt pipe to the application, please point me in
> the right direction.
>
> Thanks
> -Dave
>
>

Tim,

I’m using an interrupt pipe because I don’t know when the data is going to
be coming. It is occasional but also totally random.

In this case there is other I/O for this handle going on at the same time.
There are all kinds of IOCTLs from the application that get handled using
the bulk pipe to the device. The entire time this is going on the interrupt
pipe is waiting for this occasional/random data.

I saw on a separate thread that Don Burn generally doesn’t care for the
event model and would rather use the inverted call model
http://www.osronline.com/article.cfm?id=94. From what I have read so far,
I’m still leaning toward doing overlapped I/O.

I see some application examples at http://support.microsoft.com/kb/156932
and http://www.codeproject.com/win32/overlappedio.asp. I’ll also look at
http://www.microsoft.com/whdc/driver/tips/OverlappedIo.mspx.

Doron,
I’m calling

ObReferenceObjectByHandle(
hBuffer, // Handle
EVENT_MODIFY_STATE, // Desired Access
*ExEventObjectType, // Optional Object Type
pIRP->RequestorMode, // AccessMode
(PVOID*)&g_pAsyncResponseEvent,
NULL
);

when the context of the IOCTL which has the created event from the
application.

-Dave

“Tim Roberts” wrote in message news:xxxxx@ntdev…
> David Voeller wrote:
>> I have a USB device and a corresponding USB driver. I am using an
>> interrupt
>> pipe to handle the occasional data that comes in from the USB device
>> after
>> the USB device has received it from a separate infrared remote device.
>
> Why does it use an interrupt pipe? If it is “occasional data”, it would
> make more sense to use a bulk pipe, so as not to block out bandwidth
> unnecessarily.
>
>> The
>> application has sent the driver an event object that the driver is using
>> to
>> signal when data has been received.
>>
>> I haven’t done this yet but it looks like an overlapped IOCTL should be
>> used
>> where the application sends the IOCTL and the driver fills a buffer
>> supplied
>> by the IOCTL when data has been received on the interrupt pipe. I have
>> used
>> the interrupt pipe and external signaled event before but I have never
>> used
>> overlapped I/O so I’m looking for a little reassurance that I’m
>> approaching
>> this in the right way. I would create a parallel IO queue just for this
>> task. All other IOCTLs I’m handling with a default serial queue.
>>
>
> You don’t really need overlapped I/O for this. Just have the app launch
> a separate thread, submit the ioctl, and wait. The only reason you
> would need overlapped I/O is if you were doing other I/O on the same
> handle, and you didn’t want to open a new handle just for this task.
>
> Remember that the use of overlapped I/O by the application is entirely
> irrelevant to the driver. The only difference is in the way the
> application gets its response. The driver treats the IRPs just the same.
>
>> So, if there is a better or different way to transfer this asychronous
>> data
>> from the USB interrupt pipe to the application, please point me in the
>> right
>> direction.
>>
>
> A blocked ioctl is a fine way to get this kind of notification. I use
> it regularly. It is philosophically similar to the event method, with
> the added benefit that you can return information when you complete the
> IRP.
>
> The overlapped I/O question is really separate; it’s an application
> implementation issue. There are good samples on the web showing how to
> do overlapped I/O properly.
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>

David Voeller wrote:

I’m using an interrupt pipe because I don’t know when the data is going to
be coming. It is occasional but also totally random.

But don’t you see that you have described the perfect scenario for a
bulk pipe? By making it an interrupt pipe, you are reserving space in
each frame (modulo your interval), whether you use it or not. If you
don’t use it, that fraction of the bus is simply wasted – no one else
can use it while you have it reserved. By making it a bulk pipe, you
will still read the data randomly when it comes in, but you won’t limit
bandwidth to the other pipes and devices on the bus.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

As long as you are making the ObReferenceObjectByHandle in EvtIoInCallerContext, it should work (assuming correct input). I think that Tim is suggesting converting your interrupt endpoint to a bulk endpoint and not using your current bulk endpoint for the occassional data.

d

The interrupt pipe is guaranteed to respond which is one of the things we
want. We use it to get remote control key presses and we don’t want to miss
a key press from a user or make it seem like there is a delay when the user
presses the key. Also, there is a very small amount of data that is
transferred on the interrupt pipe when it isn’t NAKing on every poll period.
In our case, I think that moving the interrupt pipe functionality over to a
bulk pipe (Phillips USB controller so we only have 2 pipes to configure
which would make 2 bulk pipes instead of a bulk and interrupt pipe) would be
a mistake if for no other reason than we might miss a remote control key
press when something like the USB printer starts to take up all of the bulk
bandwidth to print.

“Tim Roberts” wrote in message news:xxxxx@ntdev…
> David Voeller wrote:
>> I’m using an interrupt pipe because I don’t know when the data is going
>> to
>> be coming. It is occasional but also totally random.
>>
>
> But don’t you see that you have described the perfect scenario for a
> bulk pipe? By making it an interrupt pipe, you are reserving space in
> each frame (modulo your interval), whether you use it or not. If you
> don’t use it, that fraction of the bus is simply wasted – no one else
> can use it while you have it reserved. By making it a bulk pipe, you
> will still read the data randomly when it comes in, but you won’t limit
> bandwidth to the other pipes and devices on the bus.
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>

This is actually the perfect scenario for an interrupt endpoint and is
what this endpoint type was designed for. Using the bulk pipe will end
up “wasting” more bandwidth since it will poll at every possible
opportunity.

Now, the “wasted” bandwidth in the common case is the time it takes for
an IN token followed by a NAK.

For interrupt, you will see one of these for each period.

For bulk, all of the asynchronous transfers are attempted in a round
robin fashion. Thus the frequency of these will be based on the number
of endpoints with active transfers.

So if you have lots of active asynchronous transfers that are sustained,
then yes, bulk may use less bandwidth, but the more common case is that
there are only a handful of active asynchronous transfers in which case
Interrupt endpoints would be polled less often than Bulk ones.

Now, if you are worried about the bandwidth reservation itself, this is
rarely an issue for modern systems with several USB2.0 controllers.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Tuesday, December 05, 2006 10:15 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Asynchous IO using a WDF parallel IO queue

David Voeller wrote:

I’m using an interrupt pipe because I don’t know when the data is
going to
be coming. It is occasional but also totally random.

But don’t you see that you have described the perfect scenario for a
bulk pipe? By making it an interrupt pipe, you are reserving space in
each frame (modulo your interval), whether you use it or not. If you
don’t use it, that fraction of the bus is simply wasted – no one else
can use it while you have it reserved. By making it a bulk pipe, you
will still read the data randomly when it comes in, but you won’t limit
bandwidth to the other pipes and devices on the bus.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Randy Aull wrote:

This is actually the perfect scenario for an interrupt endpoint and is
what this endpoint type was designed for. Using the bulk pipe will end
up “wasting” more bandwidth since it will poll at every possible
opportunity.

You are correct. My thinking was flawed.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.