I wrote a filter driver that loads below usbhid.sys and above the composite device driver.
The driver loads for a specific interface of a specific hid device and part of the filtering it does entails dropping reports that match given rules.
In order to hide a report from the upper drivers, I install a completion routine on he way down of the URB and attempt a resubmit of the same URB in my completion routine.
When resubmitting I make sure to rebuild the URB with UsbBuildInterruptOrBulkTransferRequest just reusing the PipeHandle, TransferBuffer, TransferBufferLength and TransferFlags.
What I notice is that, when I do that, the device gets reset and reenumerated. With a hardware USB logger I can see that the host stops sending IN packets letting frames go though unused and when 10ms go by, it resets the bus. Of course, if I don’t resubmit the URB, USB events go though without issues.
There’s also another interesting bit to this issue: the USB report that matches the rule and triggers the resubmit, actually goes through. And also, even funnier, if it weren’t for the USB logger, besides a strange pause when pressing the button, the bus reset is completely transparent to the system: the device gets reenumerated by the lower layers but my filter driver doesn’t see anything. It doesn’t get unload/readloaded or anything like that.
Of course the problem is there and, at the very least, it causes the device to hang for a second to get reenumerated (by reenumerated I mean that I actually see a bus reset and the device discovery that follows).
I’d like to understand the issue here but also I’m interested in knowing what would be the correct procedure to resubmit an URB from inside a completion routine (not of the driver that generated the URB).
On Thu, Nov 25, 2010 at 8:22 AM, wrote: > There’s also another interesting bit to this issue: the USB report that matches the rule and triggers the resubmit, actually goes through.
I don’t understand that sentence. Are you saying that your attempt to filter out this report fails and the report gets delivered to the hidclass driver?
I also don’t understand why you are filtering hids at this level. Seems wrong. You can drop reports in a standard mouse filter.
Sorry, I meant that I see that report in my filter driver (which is obvious because it’s the one that actually triggers the resubmit) but I also see the following one. So basically from the filter perspective the device seems always online.
I filter data at USB level because I need to send also some vendor specific device requests (not HID requests) and I haven’t found a way to target the USB PDO from a driver that lives in the HID stack.
I’m not sure about this, but it might be related to state of the URB. As I can make out from your post, you are submitting the same URB that you got from upper driver. Instead wouldn’t it be better to create a new URB and submit it from the filter driver, since you are resubmitting it later. Analogous to IRPs, where we reinitialize an IRP with IoReuseIrp(), before reusing it, same way the URB should also be reinitialized.
You could divide this functionality into two filters, one at the usb
FDO level and one at the HID FDO level. It might seem like twice the
work, but really it isn’t. Anyway, I don’t know offhand why
resubmitting the interrupt URB results in a reset, but if I were you
and I was determined to not break my design up into two filters, I
would consider intercepting all URB IRPs from above, issuing my own
URB IRPs to the usb device, and completing the upper IRPs with the
reports I wanted to let through.
Mark Roddy
On Thu, Nov 25, 2010 at 9:10 AM, wrote: > Sorry, I meant that I see that report in my filter driver (which is obvious because it’s the one that actually triggers the resubmit) but I also see the following one. So basically from the filter perspective the device seems always online. > > I filter data at USB level because I need to send also some vendor specific device requests (not HID requests) and I haven’t found a way to target the USB PDO from a driver that lives in the HID stack. > > Thanks! > Marco. > > — > NTDEV is sponsored by OSR > > For our schedule of WDF, WDM, debugging and other seminars visit: > http://www.osr.com/seminars > > To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer >
Is your completion routine returning STATUS_MORE_PROCESSING_REQUIRED in the cases where it filters out the completed URB and resubmits the Irp/URB? Maybe you are not doing that and then the completion continues on up to HIDUSB.SYS which then gets confused about the completion status of the Irp/URB, which then triggers the error recovery logic in HIDUSB.SYS.
The error recovery logic in HIDUSB.SYS will reset and re-enumerate the device on the bus, but the re-enumeration will be hidden from PnP but USBHUB.SYS. It sounds as though your filter driver is triggering the error recovery logic in HIDUSB.SYS, which is only triggered by the completion of the Interrupt IN Irp/URB with a non-successful status.
Regarding splitting the driver in two, it would certainly an interesting solution although it would require 2 separate inf files, so separate certification processes. Also at that point I would need to figure a sort of inter driver communication so that the HID section can actually trigger the vendor requests as needed.
I did try regenerating the URBs by using a continuous reader which worked ok for all the devices with only one interface. On this specific one it doesn’t work by simply “stalling” the bus (in the sense that once started the device stops receiving IN requests thus stopping any communication).
I will try generating the URBs manually though since it’s my best shot at this point.
Regarding the status returned by the completion routine, I’m using kmdf, so I suppose, as long as I don’t call WdfRequestComplete, the completion always exits with more processing required.
The comment is interesting though since my driver sits below hidusb therefore it should be possible to at least see a bus reset request coming through. Correct?
Not that I could do anything about it but at least I could look at the enemy in the face.
Regarding splitting the driver in two, it would certainly an interesting solution although it would require 2 separate inf files, so separate certification processes. Also at that point I would need to figure a sort of inter driver communication so that the HID section can actually trigger the vendor requests as needed.
You can certainly install a device, its LowerFilter, and its UpperFilter
in a single INF file. Installing a filter driver is nothing more than
copying the file, creating a service, and adding the registry entry.
Regarding the status returned by the completion routine, I’m using kmdf, so I suppose, as long as I don’t call WdfRequestComplete, the completion always exits with more processing required.
The comment is interesting though since my driver sits below hidusb therefore it should be possible to at least see a bus reset request coming through. Correct?
Not at all. It’s possible for a bus reset to be requested from above
via an URB, but it’s also possible for the host controller driver or the
hub driver to diagnose some error condition and request a reset. In
that case, you would never know about it
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
He can use the same INF only if the 2 stacks are in the same device class. If the lower stack is in HID and the upper stack is in the keyboard class, he must still use 2 INFs
d
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, November 29, 2010 11:37 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] USB bus reset upon URB resubmit.
Regarding splitting the driver in two, it would certainly an interesting solution although it would require 2 separate inf files, so separate certification processes. Also at that point I would need to figure a sort of inter driver communication so that the HID section can actually trigger the vendor requests as needed.
You can certainly install a device, its LowerFilter, and its UpperFilter in a single INF file. Installing a filter driver is nothing more than copying the file, creating a service, and adding the registry entry.
Regarding the status returned by the completion routine, I’m using kmdf, so I suppose, as long as I don’t call WdfRequestComplete, the completion always exits with more processing required.
The comment is interesting though since my driver sits below hidusb therefore it should be possible to at least see a bus reset request coming through. Correct?
Not at all. It’s possible for a bus reset to be requested from above via an URB, but it’s also possible for the host controller driver or the hub driver to diagnose some error condition and request a reset. In that case, you would never know about it
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
Regarding the inf file: right now I’m installing a lower filter of hidusb (so, matching device ids of the type USB.…). In order to take advantage of the HID filtering options, I’d need to install something on the HID stack (therefore matching device ids of type HID.…) which would require 2 different infs, right?
Look at input.inf. hidusb, hidclass, and hidparse are all installed by
this inf file and all of these device drivers are in HIDClass.
Mark Roddy
On Mon, Nov 29, 2010 at 3:34 PM, wrote: > Regarding the inf file: right now I’m installing a lower filter of hidusb (so, matching device ids of the type USB.…). In order to take advantage of the HID filtering options, I’d need to install something on the HID stack (therefore matching device ids of type HID.…) which would require 2 different infs, right? > > > > — > NTDEV is sponsored by OSR > > For our schedule of WDF, WDM, debugging and other seminars visit: > http://www.osr.com/seminars > > To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer >