USB Report Descriptors, inconsistent/lacking documentation.

Quoting from ther USB spec for HID Descriptors: http://www.usb.org/developers/hidpage/HID1_11.pdf “the value bNumDescriptors identifies the number of additional class specific descriptors present. This number must be at least one (1) as a Report
descriptor will always be present.”

The format of the HID descriptor defined in hidport.h is:
typedef struct _HID_DESCRIPTOR
{
UCHAR bLength;
UCHAR bDescriptorType;
USHORT bcdHID;
UCHAR bCountry;
UCHAR bNumDescriptors;

/*
* This is an array of one OR MORE descriptors.
*/
struct _HID_DESCRIPTOR_DESC_LIST {
UCHAR bReportType;
USHORT wReportLength;
} DescriptorList [1];

} HID_DESCRIPTOR, * PHID_DESCRIPTOR;

Which in renaming the members of the embdedded structure from those in the spec, to include the word ‘report’, backs this statement up, and actual data says there is one: 09 21 00 01 00 01 22 34 <– the 0x22 is the type and 0x34 the length of tyher report derscriptor.

The problem is, what does ‘present’ mean? It isn’t in the config descriptor which is where the HID descriptor is, so in the complete absence of documentation in the MDSN for this descriptor type, I had a dig around in some Linux code for a host and discovered the report descriptor is obtained not from the device, like the other descriptors, but from an interface.

Microsoft include a define for this, URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE, but not a macro (UsbBuildGetDescriptorRequest being the macro to get a descriptor from a devcice).

What is also odd is that the report descriptor doesnt follow the format of the other descriptors in having a USB_COMMON_DESCRIPTOR type header at its start. (In fact it is just an array of chars).

What is also inconsistent is that when using this define you don’t need to specify an interface index like you do when using URB_FUNCTION_VENDOR_INTERFACE.

So why the oversight? Why the missing macro and why is the descriptor structure different from the others, including the HID descriptor? And why no interface index?

Something else, the HID descriptor documented here: https://msdn.microsoft.com/en-us/windows/hardware/commercialize/design/component-guidelines/windows-precision-touchpad-required-hid-descriptors has member variables that match the spec, and not the ones in hidport.h

Not a big problem, provided you know where to look in linux to see how a USB host works, but it would be nice to have better consistency and documentaion in the MSDN.

xxxxx@hotmail.com wrote:

Quoting from ther USB spec for HID Descriptors: http://www.usb.org/developers/hidpage/HID1_11.pdf “the value bNumDescriptors identifies the number of additional class specific descriptors present. This number must be at least one (1) as a Report
descriptor will always be present.”

The problem is, what does ‘present’ mean? It isn’t in the config descriptor which is where the HID descriptor is, so in the complete absence of documentation in the MDSN for this descriptor type, I had a dig around in some Linux code for a host and discovered the report descriptor is obtained not from the device, like the other descriptors, but from an interface.

Right, it is a separate descriptor type, fetched with a separate
GET_DESCRIPTOR request, just like the string descriptors. Section 7.1.1
talks about that.

Microsoft include a define for this, URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE, but not a macro (UsbBuildGetDescriptorRequest being the macro to get a descriptor from a devcice).

What is also odd is that the report descriptor doesnt follow the format of the other descriptors in having a USB_COMMON_DESCRIPTOR type header at its start. (In fact it is just an array of chars).

Right. Again, the very spec you cited has those exact words:

6.2.2. Report Descriptor
The Report descriptor is unlike other descriptors in that it is not
simply a table of values.

What is also inconsistent is that when using this define you don’t need to specify an interface index like you do when using URB_FUNCTION_VENDOR_INTERFACE.

The request on the wire requires an interface number in wIndex, but in
this case the USB driver stack is filling that in for you. It knows
what interface number your driver was assigned, and a HID driver is
always assigned one interface. In the case of
URB_FUNCTION_VENDOR_INTERFACE, it’s possible for that request to be
called when you have multiple interfaces (like USB Audio or USB Video),
so it can’t automatically fill in the correct. value.

So why the oversight? Why the missing macro and why is the descriptor structure different from the others, including the HID descriptor? And why no interface index?

The macro is trivial to write. The general “get descriptor” macros are
useful for ALL USB devices. The “get report descriptor” macro is only
applicable to one class of devices (HID).

The descriptor structure is different because there’s no reason not to
be. That’s just the way the HID interface was designed 20 years ago.

You don’t need to specify the interface because the USB stack already
knows what interface you are handling. It will fill in the wIndex value
on your behalf.

Not a big problem, provided you know where to look in linux to see how a USB host works, but it would be nice to have better consistency and documentaion in the MSDN.

If you want to know how USB devices work, you look in the USB
specifications. That’s where the rubber meets the road. There’s really
no need for Microsoft to duplicate the thorough and quite readable USB
specs.


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

Makes sense Tim, thanks for taking the time to reply.

It would be nice to have the ‘get descriptor from interface’ and report descriptors documented by the MSDN the same way the other descriptors are. After all, after you have read the spec, you still need the API documented to know how to get what you want.

I did read the USB spec on HID devices, but it doesn’t say that the HID descriptor is obtained from the device and the report descriptor from the interface though. Perhaps one is supposed to just know this, perhaps it becomes apparent after working only on USB devices. You don’t get that depth of exposure in any one field in Europe, there just isn’t a big demand for Kernel work, so when your time is split between not only all the Microsoft Kernel technologies, but also Linux, you can see where precise documentary is needed.

I had exactly the same issue last month about MDL transfer buffers in a URB. The URB buffer size and MDL buffer size were different. The MSDN didnt go into any detail on this, it documented them the same. and the replies from this forum were a mixture of superior ‘you are illiterate’ to ‘you are supposed to know this if you have been working in the field long enough’.

That isn’t a valid response though. The MSDN documentation IS lacking on those buffer sizes and it IS lacking on report descriptors.

I will send MSFT another response to their documentation, I don’t know if it will achieve anything though.

SO basicaly https://msdn.microsoft.com/en-us/library/windows/hardware/ff540357(v=vs.85).aspx
"DescriptorType

Indicates what type of descriptor is being retrieved or set. One of the following values must be specified:

USB_DEVICE_DESCRIPTOR_TYPE
USB_CONFIGURATION_DESCRIPTOR_TYPE
USB_STRING_DESCRIPTOR_TYPE"

Fails to mention it can also be a HID_REPORT_DESCRIPTOR_TYPE

Al;ready sent feedback to MSFT on this.

xxxxx@hotmail.com wrote:

SO basicaly https://msdn.microsoft.com/en-us/library/windows/hardware/ff540357(v=vs.85).aspx
"DescriptorType

Indicates what type of descriptor is being retrieved or set. One of the following values must be specified:

USB_DEVICE_DESCRIPTOR_TYPE
USB_CONFIGURATION_DESCRIPTOR_TYPE
USB_STRING_DESCRIPTOR_TYPE"

Fails to mention it can also be a HID_REPORT_DESCRIPTOR_TYPE

Already sent feedback to MSFT on this.

It can be any arbitrary number at all. Several classes define their own
descriptors, and it’s perfectly valid to have custom descriptors of your
own invention. You have to have an understanding of the USB
specifications before you start interpreting the API documents.


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

MSFT: “One of the following values must be specified:”

You: “It can be any arbitrary number at all”

You see why I think the documentation is inadequate Tim?

It is all very well saying ‘read the spec’, I did, but it doesnt say the HID descriptor is got from the device and the report descriptor from the interface, even though the HID descriptor describes a report descriptor.

Now no doubt after many years of deep meditaiton on the subject you can intuit this and realise the MSDN is lacking, and plain wrong, but I would rather spend my time working on my design Tim.

The documentaiton is wrong. Period. You said so yourself. :slight_smile:

xxxxx@hotmail.com wrote:

MSFT: “One of the following values must be specified:”

You: “It can be any arbitrary number at all”

You see why I think the documentation is inadequate Tim?

I agree the documentation is wrong here.

It is all very well saying ‘read the spec’, I did, but it doesnt say the HID descriptor is got from the device and the report descriptor from the interface, even though the HID descriptor describes a report descriptor.

The spec certainly does say exactly that. The HID descriptor is part of
the configuration descriptor, which is always a device request. The
report descriptor is a HID-class-specific descriptor, and section 7.1.1
of the HID spec states that HID class descriptors use bmRequestType
0x81, which aims at an interface.

Now no doubt after many years of deep meditaiton on the subject you can intuit this and realise the MSDN is lacking, and plain wrong, but I would rather spend my time working on my design Tim.

To a certain extent, I’m playing devil’s advocate here. Your arguments
are not entirely without merit. However, the fact is that the Windows
kernel USB APIs map quite directly to the requests in the USB spec.
Knowing the USB spec, one can intuit exactly what the Windows requests
must be doing.


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

Yeah, OK, I see it now.
“7.1.1 Get_Descriptor Request
The Get_Descriptor HID Class Descriptor
bmRequestType 10000001”

If only I could apply the same enthusiasm to reading the USB spec as I can a good book…

:slight_smile:

xxxxx@hotmail.com wrote:

Yeah, OK, I see it now.
“7.1.1 Get_Descriptor Request
The Get_Descriptor HID Class Descriptor
bmRequestType 10000001”

If only I could apply the same enthusiasm to reading the USB spec as I can a good book…

:wink:

To be fair, I’ve read a large number of specs in my career, and in my
opinion the USB specs are among the most readable. The problem is
figuring out which section really apply to you, and which can be skimmed.


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

Among the most readable, the most tutorial, and the most accurate. The USB family of specs definitely does not suck. Long? Yes. Spread across multiple,different specs? Yes. But definitely clear.

Nothing takes the place of actual,implementation experience, of course.

Peter
OSR
@OSRDrivers

@Tim “You don’t need to specify the interface because the USB stack already knows what interface you are handling…and a HID driver is always assigned one interface”

A multifunction HID device has multiple interfaces, traditionally handled by usbccgp.sys. However the architecture replaces this driver so has to get the report descriptors from, in this case, one of three interfaces.

What I found was that the hardware returned the report descriptors in logical order, even if urb.UrbControlDescriptorRequest.Index is set to zero. The hardware also returns the correct descriptor if the interface is specified.

What is frustrating about all this though is the MSDNs complete lack off mention of HID_REPORT_DESCRIPTOR_TYPE as a valid vale for DescriptorType, and in fact it’s completely wrong statement that DescriptorType MUST be either device, config or string.

Reading this immediately makes you drop this as an avenue of investigaiton for getting the report descriptors, even if yopu later read in the USB spec that they can be obtained from an interface, you wonder just where MSFT burried this funcitonality.

Thats why I had a look at some Linux host code, and bingo. There it was. It is exactly the same route for report descriptors as for the others, just that ‘device’ is changed to ‘interface’, and you realise the MSDN had you fooled all along.

I tell you what, it would be nice if MSFT read the USB spec! :slight_smile: