question on filtering (upper) HIDClass

Hello.

I am trying to filter HIDClass (upper filter), in order that I get access to the HID report descriptor. For the time being, I am confining myself to my device, which is a composite USB device with two interfaces which are HID. At this moment, I have attached the filter manually by adding the UpperFilters multi-string for my HID device (in the HID enum section, not the USB enum section).

However, as soon as I insert my filter above HIDClass, the HID device ceases to work (it is an HID game controller), with code 41 in the device manager (XP) or it displays fine in the device manager, but the game controller properties are inaccessible. These failures occur despite the fact that the filter is basically a passthrough (I’ve removed my completion routines, and used the basic passthrough method for all except required functions, like PnP and Power). I’ve started working from the firefly sample, and thereafter tried a class upper filter from the WDK, with the same result. The latter filter is barebones indeed, and failure of the HID game controller hints that I am attaching the wrong part of the stack.

How should I attach above HIDClass, so I can have access to the input reports, as well as the HID report descriptor(s)? I do need to parse the HID report descriptors(s) so that I can make sense of the input reports. I can get raw input reports in URBs if I filter below HIDUsb, but interpreting them without the HID report descriptor is another matter.

thanks for any help,

Philip Lukidis

I am confused as to which part of the HID stack you want to filter. The
FDO part of HIDClass or one the raw PDOs that it enumerates? I think
you are trying to filter one of the PDOs. Have you tried attaching
firefly to the stack to see if it works? Or take firely, remove the
mouse specific goo and see if it works? Did you try this with a KMDF
driver vs a WDM driver?

Have you tried installing your driver as the FDO for the HID PDO stack
instead of a filter? It could be an issue that a FDO is required
otherwise things go haywire (I think this was true on win2k, but not for
XP, but it doesn’t hurt to try)

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Philip Lukidis
Sent: Friday, March 23, 2007 3:29 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] question on filtering (upper) HIDClass

Hello.

I am trying to filter HIDClass (upper filter), in order that I get
access to the HID report descriptor. For the time being, I am confining
myself to my device, which is a composite USB device with two interfaces
which are HID. At this moment, I have attached the filter manually by
adding the UpperFilters multi-string for my HID device (in the HID enum
section, not the USB enum section).

However, as soon as I insert my filter above HIDClass, the HID device
ceases to work (it is an HID game controller), with code 41 in the
device manager (XP) or it displays fine in the device manager, but the
game controller properties are inaccessible. These failures occur
despite the fact that the filter is basically a passthrough (I’ve
removed my completion routines, and used the basic passthrough method
for all except required functions, like PnP and Power). I’ve started
working from the firefly sample, and thereafter tried a class upper
filter from the WDK, with the same result. The latter filter is
barebones indeed, and failure of the HID game controller hints that I am
attaching the wrong part of the stack.

How should I attach above HIDClass, so I can have access to the input
reports, as well as the HID report descriptor(s)? I do need to parse
the HID report descriptors(s) so that I can make sense of the input
reports. I can get raw input reports in URBs if I filter below HIDUsb,
but interpreting them without the HID report descriptor is another
matter.

thanks for any help,

Philip Lukidis


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

Hello Doron, thank you for your reply. I should have specified that I am using the WDM firefly sample. I am attaching my filter as an upper filter in the Enum\HID registry section under the device instance, which I take to be the PDO (please correct me if I am wrong…). I am attaching an output from the debugger of where I am in the device stack:

1: kd> !devstack 0x84999e80
!DevObj !DrvObj !DevExt ObjectName

84999e80 \Driver\Firefly 84999f38 0000005a
8499ed48 \Driver\HidUsb 8499ee00 00000059

Note that while the listing says \Driver\HidUsb, I see HIDCLASS in the stack when my completion routine is called (I suppose it is listed thus because it is a port/miniport?).

I have modified firefly very slightly, removing WMI registration/deregistration, and adding some completion routine with traces. From what I see, the mouse specific section is in the WMI path only.

The interesting thing is that I have no problem whatsoever if I attach firefly to a HID mouse, yet while if I can attach in the same manner to a game controller (again, as an upper filter in the Enum\HID section of the registry) IRP_MJ_READ for the game controller fails with 0xC00000E8, which means STATUS_INVALID_USER_BUFFER. This is most assuredly why I cannot get the properties of the game controller device in the control panel. Note that the flags for the next lower device of the filter do not specify buffered of direct I/O (flags: 0x3040), so I would guess that a user buffer is being used, and indeed, there is a usermode buffer in Irp->UserBuffer, which appears valid in the debugger, at least. Any idea on why IRP_MJ_READ is failing thus? Perhaps I should create my own read IRP, send it down, and complete the main IRP in my IRP_MJ_READ handler?

Note that the above tests were for Vista only (the failure mode on XP is different, DriverEntry is called, and then DriverUnload is immediately called without AddDevice being called, and Device Manager shows code 41). Strange.

I’m not sure I understand where you are proceeding with the statement “Have you tried installing your driver as the FDO for the HID PDO stack instead of a filter. It could be an issue that a FDO is required”. If possible, could you elaborate?

Thanks for any help with these questions,

Philip Lukidis

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Doron Holan
Sent: Friday, March 23, 2007 6:43 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] question on filtering (upper) HIDClass

I am confused as to which part of the HID stack you want to
filter. The
FDO part of HIDClass or one the raw PDOs that it enumerates? I think
you are trying to filter one of the PDOs. Have you tried attaching
firefly to the stack to see if it works? Or take firely, remove the
mouse specific goo and see if it works? Did you try this with a KMDF
driver vs a WDM driver?

Have you tried installing your driver as the FDO for the HID PDO stack
instead of a filter? It could be an issue that a FDO is required
otherwise things go haywire (I think this was true on win2k,
but not for
XP, but it doesn’t hurt to try)

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Philip Lukidis
Sent: Friday, March 23, 2007 3:29 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] question on filtering (upper) HIDClass

Hello.

I am trying to filter HIDClass (upper filter), in order that I get
access to the HID report descriptor. For the time being, I
am confining
myself to my device, which is a composite USB device with two
interfaces
which are HID. At this moment, I have attached the filter manually by
adding the UpperFilters multi-string for my HID device (in
the HID enum
section, not the USB enum section).

However, as soon as I insert my filter above HIDClass, the HID device
ceases to work (it is an HID game controller), with code 41 in the
device manager (XP) or it displays fine in the device manager, but the
game controller properties are inaccessible. These failures occur
despite the fact that the filter is basically a passthrough (I’ve
removed my completion routines, and used the basic passthrough method
for all except required functions, like PnP and Power). I’ve started
working from the firefly sample, and thereafter tried a class upper
filter from the WDK, with the same result. The latter filter is
barebones indeed, and failure of the HID game controller
hints that I am
attaching the wrong part of the stack.

How should I attach above HIDClass, so I can have access to the input
reports, as well as the HID report descriptor(s)? I do need to parse
the HID report descriptors(s) so that I can make sense of the input
reports. I can get raw input reports in URBs if I filter
below HIDUsb,
but interpreting them without the HID report descriptor is another
matter.

thanks for any help,

Philip Lukidis


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


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

Sorry, I am resending the message because the it was
previously rejected on the first attempt. My Apologies
if you have already received it.

Hello Doron, thank you for your reply. I should have
specified that I am using the WDM firefly sample. I am
attaching my filter as an upper filter in the Enum\HID
registry section under the device instance, which I take to
be the PDO (please correct me if I am wrong…). I am
attaching an output from the debugger of where I am in the
device stack:

1: kd> !devstack 0x84999e80
!DevObj !DrvObj !DevExt ObjectName
> 84999e80 \Driver\Firefly 84999f38 0000005a
8499ed48 \Driver\HidUsb 8499ee00 00000059

Note that while the listing says \Driver\HidUsb, I see
HIDCLASS in the stack when my completion routine is called (I
suppose it is listed thus because it is a port/miniport?).

I have modified firefly very slightly, removing WMI
registration/deregistration, and adding some completion
routine with traces. From what I see, the mouse specific
section is in the WMI path only.

The interesting thing is that I have no problem whatsoever if
I attach firefly to a HID mouse, yet while if I can attach in
the same manner to a game controller (again, as an upper
filter in the Enum\HID section of the registry) IRP_MJ_READ
for the game controller fails with 0xC00000E8, which means
STATUS_INVALID_USER_BUFFER. This is most assuredly why I
cannot get the properties of the game controller device in
the control panel. Note that the flags for the next lower
device of the filter do not specify buffered of direct I/O
(flags: 0x3040), so I would guess that a user buffer is being
used, and indeed, there is a usermode buffer in
Irp->UserBuffer, which appears valid in the debugger, at
least. Any idea on why IRP_MJ_READ is failing thus? Perhaps
I should create my own read IRP, send it down, and complete
the main IRP in my IRP_MJ_READ handler?

Note that the above tests were for Vista only (the failure
mode on XP is different, DriverEntry is called, and then
DriverUnload is immediately called without AddDevice being
called, and Device Manager shows code 41). Strange.

I’m not sure I understand where you are proceeding with the
statement “Have you tried installing your driver as the FDO
for the HID PDO stack instead of a filter. It could be an
issue that a FDO is required”. If possible, could you elaborate?

Thanks for any help with these questions,

Philip Lukidis

You are filtering the right device, the HIDClass FDO would have had a PDO (in !devstack) enumerated by another driver (like hidusb or usbccgp). You don’t see HIDClass is in the !devstack output because HIDClass does not have a driver object, hidusb has one though. HIDClass takes over hidusb’s driver object.

If you had started with the KMDF version, this woudld have worked out of the box ;). HIDClass is goofy, it sets the DeviceObject->Flags related to buffered or direct I/O during IRP_MN_START_DEVICE, not when it creates the device. This is normally not an issue b/c the PDO is marked as raw and typically does not have a filter on top of it which needs get these flags. If you need to set DO_DIRECT_IO or DO_BUFFERED_IO in your IRP_MN_START_DEVICE handler after the PDO has completed the IRP successfully back to your driver. As I said, KMDF handles this for you already ;).

d

Doron, thank you for your help, that was indeed it. It now works in Vista and XP (I had another issue on my XP machine which I cannot reproduce anymore).

Concerning the issue in retrospect, it does seem rather obvious, but I had assumed that IRP_MJ_READ was using a usermode buffer in Irp->UserBuffer (which was valid) and therefore no flags were necessary. The WDK says that topmost drivers can indeed avoid using buffered or direct I/O (under the section “Using Neither Buffered Nor Direct I/O”).

I’ll check over the KMDF example in order to see if there are any other points to mine from it.

thanks for your help,

Philip Lukidis

>

Doron, thank you for your help, that was indeed it. It now
works in Vista and XP (I had another issue on my XP machine
which I cannot reproduce anymore).

Concerning the issue in retrospect, it does seem rather
obvious, but I had assumed that IRP_MJ_READ was using a
usermode buffer in Irp->UserBuffer (which was valid) and
therefore no flags were necessary. The WDK says that topmost
drivers can indeed avoid using buffered or direct I/O (under
the section “Using Neither Buffered Nor Direct I/O”).

I’ll check over the KMDF example in order to see if there are
any other points to mine from it.

thanks for your help,

Philip Lukidis

Hello Doron, I have two more questions that I hope you could help me, time permitting:
a) Concerning the upper filter of HIDClass, I was wondering how I could easily know when the interface is active, so that I could send ZwOpenFile as Firefly does and obtain the FILE_OBJECT. The interface does not seem to be immediately active as soon as IRP_MN_START_DEVICE completes (though it subsequently is after IRP_MN_QUERY_DEVICE_STATE completes). I thought of using IoRegisterPlugPlayNotification, with EventCategoryDeviceInterfaceChange. I used the GUID which IoGetDeviceProperty(DevicePropertyClassGuid) returned me. However, I never found that my PnP notification routine was called. I suppose that I could queue work item after I see the first IRP_MJ_CREATE coming down the stack, but I was wondering if there was a better way to do this.

b) Is there a way to get the raw report descriptor from an HIDClass filter? Or is this impossible from the current filter’s position? Sending IOCTL_HID_GET_REPORT_DESCRIPTOR seems to be a fruitless endeavour (perhaps the IOCTL is not being sent to the minidriver itself?).

thanks for any help,

Philip Lukidis

Phil, this one is just for you, http://blogs.msdn.com/doronh/archive/2007/03/26/filtering-hid-collections-and-setting-i-o-flags.aspx … but it does not answer your new questions.

  1. a stack cannot be opened via a handle until the IRP_MN_START_DEVICE IRP returned back to the PnP manager (an event that you do not have visibility to directly). Using query device state or a work item will not work 100% of the time, the work item can race with the start irp completing for instance. IoRegisterPlugPlayNotification is what you should use, do not use the class GUID retrieved through IoGetDeviceProperty (that is the GUID used to identify the class of the device in th INF), use GUID_DEVINTERFACE_HID (in hidclass.h). In the notification function, you open up the interface (since this is a KMDF driver, you can use a WDFIOTARGET) and then get the PDO (WdfIoTargetWdmGetTargetPhysicalDevice) and compare it to your WDFDEVICE’s PDO (WdfDeviceWdmGetPhysicalDevice), if they are the same you opened up your device.

IoGetDeviceInterfaces() provides some promise here, you provide the HID GUID and your PDO and you should just get the string without registering for PnP notifications on the arrival of the GUID, but the problem remains…when does the GUID come online? I guess what you can do is call IoGetDeviceInterfaces from your arrival notification routine if you have not yet opened up your device. This saves the step of opening up the device to get its PDO. Once you open the device, you can unregister your interface arrival notification routine.

When opening your WDFIOTARGET against your device, you should specify EvtIoTargetQueryRemove, EvtIoTargetRemoveCanceled, EvtIoTargetRemoveComplete so that you close the handle when the device is query removed, otherwise your open handle will prevent the graceful remove of your driver.

Hmm, maybe I should write another blog entry on this ;)…

  1. IOCTL_HID_GET_REPORT_DESCRIPTOR is not an upper device interface for the HIDClass PDO, it is an interface between the class driver and the HID miniport

d

Thank you for your answer Doron, that answers my question concerning getting the opening the stack. Concerning the report descriptor, I’ll have to try to attaching another filter somewhere else, should I find that I need it. Right now, I’m not 100% sure that I will need it, but I was hoping that I could easily retrieve it from the current filter.

thank you for your help,

Philip Lukidis

-----Original Message-----
From: xxxxx@lists.osr.com on behalf of xxxxx@Microsoft.com
Sent: Tue 3/27/2007 5:57 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] question on filtering (upper) HIDClass

Phil, this one is just for you, http://blogs.msdn.com/doronh/archive/2007/03/26/filtering-hid-collections-and-setting-i-o-flags.aspx … but it does not answer your new questions.

  1. a stack cannot be opened via a handle until the IRP_MN_START_DEVICE IRP returned back to the PnP manager (an event that you do not have visibility to directly). Using query device state or a work item will not work 100% of the time, the work item can race with the start irp completing for instance. IoRegisterPlugPlayNotification is what you should use, do not use the class GUID retrieved through IoGetDeviceProperty (that is the GUID used to identify the class of the device in th INF), use GUID_DEVINTERFACE_HID (in hidclass.h). In the notification function, you open up the interface (since this is a KMDF driver, you can use a WDFIOTARGET) and then get the PDO (WdfIoTargetWdmGetTargetPhysicalDevice) and compare it to your WDFDEVICE’s PDO (WdfDeviceWdmGetPhysicalDevice), if they are the same you opened up your device.

IoGetDeviceInterfaces() provides some promise here, you provide the HID GUID and your PDO and you should just get the string without registering for PnP notifications on the arrival of the GUID, but the problem remains…when does the GUID come online? I guess what you can do is call IoGetDeviceInterfaces from your arrival notification routine if you have not yet opened up your device. This saves the step of opening up the device to get its PDO. Once you open the device, you can unregister your interface arrival notification routine.

When opening your WDFIOTARGET against your device, you should specify EvtIoTargetQueryRemove, EvtIoTargetRemoveCanceled, EvtIoTargetRemoveComplete so that you close the handle when the device is query removed, otherwise your open handle will prevent the graceful remove of your driver.

Hmm, maybe I should write another blog entry on this ;)…

  1. IOCTL_HID_GET_REPORT_DESCRIPTOR is not an upper device interface for the HIDClass PDO, it is an interface between the class driver and the HID miniport

d


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

Actually Doron, I had forgotten to thank you for having taken the time to create a new entry in your blog. Well, in actual fact, I did not check the date of the entry until later this morning, so I thought it was an older entry which I had missed. Many thanks for this, and your help.

Philip Lukidis

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com]On Behalf Of Philip Lukidis
Sent: Tuesday, March 27, 2007 8:00 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] question on filtering (upper) HIDClass

Thank you for your answer Doron, that answers my question concerning getting the opening the stack. Concerning the report descriptor, I’ll have to try to attaching another filter somewhere else, should I find that I need it. Right now, I’m not 100% sure that I will need it, but I was hoping that I could easily retrieve it from the current filter.

thank you for your help,

Philip Lukidis

-----Original Message-----
From: xxxxx@lists.osr.com on behalf of xxxxx@Microsoft.com
Sent: Tue 3/27/2007 5:57 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] question on filtering (upper) HIDClass

Phil, this one is just for you, http://blogs.msdn.com/doronh/archive/2007/03/26/filtering-hid-collections-and-setting-i-o-flags.aspx … but it does not answer your new questions.

  1. a stack cannot be opened via a handle until the IRP_MN_START_DEVICE IRP returned back to the PnP manager (an event that you do not have visibility to directly). Using query device state or a work item will not work 100% of the time, the work item can race with the start irp completing for instance. IoRegisterPlugPlayNotification is what you should use, do not use the class GUID retrieved through IoGetDeviceProperty (that is the GUID used to identify the class of the device in th INF), use GUID_DEVINTERFACE_HID (in hidclass.h). In the notification function, you open up the interface (since this is a KMDF driver, you can use a WDFIOTARGET) and then get the PDO (WdfIoTargetWdmGetTargetPhysicalDevice) and compare it to your WDFDEVICE’s PDO (WdfDeviceWdmGetPhysicalDevice), if they are the same you opened up your device.

IoGetDeviceInterfaces() provides some promise here, you provide the HID GUID and your PDO and you should just get the string without registering for PnP notifications on the arrival of the GUID, but the problem remains…when does the GUID come online? I guess what you can do is call IoGetDeviceInterfaces from your arrival notification routine if you have not yet opened up your device. This saves the step of opening up the device to get its PDO. Once you open the device, you can unregister your interface arrival notification routine.

When opening your WDFIOTARGET against your device, you should specify EvtIoTargetQueryRemove, EvtIoTargetRemoveCanceled, EvtIoTargetRemoveComplete so that you close the handle when the device is query removed, otherwise your open handle will prevent the graceful remove of your driver.

Hmm, maybe I should write another blog entry on this ;)…

  1. IOCTL_HID_GET_REPORT_DESCRIPTOR is not an upper device interface for the HIDClass PDO, it is an interface between the class driver and the HID miniport

d


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


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