Author Topic: Polling rate problem for HID IN interrupt endpoint  (Read 34831 times)

Adrien Decostre

  • Member
  • ***
  • Posts: 12
Polling rate problem for HID IN interrupt endpoint
« on: August 01, 2011, 07:45:30 am »
Dear all,

I am currently doing some transfer performance tests between a HID device and a WinXP PC and I don't manage to reach transfer rate above about 260kBytes/sec.

The device under test is based on a ARM926  evaluation board and is configured as a HID device and is defined as 'vendor specific' usage. For the considered throughput tests, it constantly sends data to the host via the interrupt IN endpoint. On the WinXp  host PC, I am using the Windows DDK API to read the data coming from the USB device.

The device is correctly recognized as a generic HID device by Windows. Via a USB packet sniffer, I could see that the sizes of exchanged packets match the size defined in the HID report descriptor. However, the bus is polled only with a period of 1ms while the 'bInterval' field is set to 1 (for a high speed device).

I suspect that the problem comes from wrong descriptors definition. Would anyone have already met similar problem with HID devices?
Would this problem be a limitation of the 'vendor defined” usage?
Would this problem be connected to any particular Windows settings?
How can I be sure that the device is well operating in high-speed mode (and not in full speed mode)?

The USB descriptors have been added hereafter, maybe this can give more insight to the problem.

Thanks in advance for any help or information concerning this problem.

Best regards

Adrien


USB sniffer snapshot:
Code: [Select]
Type Seq Elapsed Duration Request Request Details I/O Driver Name Status
URB 39559 103.642837 s Bulk or Interrupt Transfer 255 bytes buffer in hhdusbh32
URB 39560 103.642840 s Bulk or Interrupt Transfer 255 bytes buffer in usbccgp
URB 39561 103.642842 s Bulk or Interrupt Transfer 255 bytes buffer in usbccgp
URB 39562 103.642845 s Bulk or Interrupt Transfer 255 bytes buffer in hhdusbh32
URB 39563 103.642847 s Bulk or Interrupt Transfer 255 bytes buffer in ACPI
URB 39564 103.642849 s Bulk or Interrupt Transfer 255 bytes buffer in usbhub
URB 39565-39564 103.643946 s 1.097 ms Bulk or Interrupt Transfer Input Report len:255 in usbhub Success (Success)
URB 39566-39563 103.643949 s 1.102 ms Bulk or Interrupt Transfer Input Report len:255 in ACPI Success (Success)
URB 39567-39562 103.643951 s 1.106 ms Bulk or Interrupt Transfer Input Report len:255 in hhdusbh32 Success (Success)
URB 39568-39561 103.643953 s 1.111 ms Bulk or Interrupt Transfer Input Report len:255 in usbccgp Success (Success)
URB 39569-39560 103.643956 s 1.116 ms Bulk or Interrupt Transfer Input Report len:255 in usbccgp Success (Success)
URB 39570-39559 103.643958 s 1.121 ms Bulk or Interrupt Transfer Input Report len:255 in hhdusbh32 Success (Success)
URB 39571 103.643962 s Bulk or Interrupt Transfer 255 bytes buffer in hhdusbh32
URB 39572 103.643964 s Bulk or Interrupt Transfer 255 bytes buffer in usbccgp
URB 39573 103.643967 s Bulk or Interrupt Transfer 255 bytes buffer in usbccgp
URB 39574 103.643969 s Bulk or Interrupt Transfer 255 bytes buffer in hhdusbh32
URB 39575 103.643972 s Bulk or Interrupt Transfer 255 bytes buffer in ACPI
URB 39576 103.643974 s Bulk or Interrupt Transfer 255 bytes buffer in usbhub
URB 39577-39576 103.644946 s 972 us Bulk or Interrupt Transfer Input Report len:255 in usbhub Success (Success)
URB 39578-39575 103.644948 s 977 us Bulk or Interrupt Transfer Input Report len:255 in ACPI Success (Success)
URB 39579-39574 103.644950 s 981 us Bulk or Interrupt Transfer Input Report len:255 in hhdusbh32 Success (Success)
URB 39580-39573 103.644953 s 986 us Bulk or Interrupt Transfer Input Report len:255 in usbccgp Success (Success)
URB 39581-39572 103.644955 s 991 us Bulk or Interrupt Transfer Input Report len:255 in usbccgp Success (Success)
URB 39582-39571 103.644958 s 996 us Bulk or Interrupt Transfer Input Report len:255 in hhdusbh32 Success (Success)

HID report descriptor (as seen by USBLyzer):
Code: [Select]
Interface 1 HID Report Descriptor Vendor-Defined 1
Item Tag (Value) Raw Data
Usage Page (Vendor-Defined 1) 06 00 FF 
Usage (Vendor-Defined 1) 09 01 
Collection (Application) A1 01 
    Usage (Vendor-Defined 1) 09 01 
    Logical Minimum (0) 15 00 
    Logical Maximum (255) 26 FF 00 
    Report Count (8) 95 08 
    Report Size (255) 75 FF 
    Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02 
    Usage (Vendor-Defined 1) 09 01 
    Logical Minimum (0) 15 00 
    Logical Maximum (255) 26 FF 00 
    Report Count (8) 95 08 
    Report Size (255) 75 FF 
    Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 02 
End Collection C0 

USB descriptors (as seen by USBLyzer):
Code: [Select]
Device Descriptor BIDULE
Offset Field Size Value Description
0 bLength 1 12h 
1 bDescriptorType 1 01h Device
2 bcdUSB 2 0200h USB Spec 2.0
4 bDeviceClass 1 00h Class info in Ifc Descriptors
5 bDeviceSubClass 1 00h 
6 bDeviceProtocol 1 00h 
7 bMaxPacketSize0 1 40h 64 bytes
8 idVendor 2 0525h Netchip Technology, Inc.
10 idProduct 2 A4A4h 
12 bcdDevice 2 0100h 1.00
14 iManufacturer 1 01h "Licensed to Code, LLC"
15 iProduct 1 02h "BIDULE"
16 iSerialNumber 1 03h "gb7pzguz7eafahyd22ya2dmt2tlmf5jf3yp2ntw1md065owkywphbrcr5xj7y89"
17 bNumConfigurations 1 01h 

Device Qualifier Descriptor
Offset Field Size Value Description
0 bLength 1 0Ah 
1 bDescriptorType 1 06h Device Qualifier
2 bcdUSB 2 0200h USB Spec 2.0
4 bDeviceClass 1 00h Class info in Ifc Descriptors
5 bDeviceSubClass 1 00h 
6 bDeviceProtocol 1 00h 
7 bMaxPacketSize0 1 40h 64 bytes
8 bNumConfigurations 1 01h 
9 bReserved 1 00h 

Configuration Descriptor 3 Self Powered
Offset Field Size Value Description
0 bLength 1 09h 
1 bDescriptorType 1 02h Configuration
2 wTotalLength 2 0040h 
4 bNumInterfaces 1 01h 
5 bConfigurationValue 1 03h 
6 iConfiguration 1 04h "The Configuration"
7 bmAttributes 1 C0h Self Powered
 4..0: Reserved  ...00000   
 5: Remote Wakeup  ..0.....  No
 6: Self Powered  .1......  Yes
 7: Reserved (set to one)
(bus-powered for 1.0)  1.......   
8 bMaxPower 1 01h 2 mA

Interface Descriptor 0/0 HID, 2 Endpoints
Offset Field Size Value Description
0 bLength 1 09h 
1 bDescriptorType 1 04h Interface
2 bInterfaceNumber 1 01h 
3 bAlternateSetting 1 00h 
4 bNumEndpoints 1 02h 
5 bInterfaceClass 1 03h HID
6 bInterfaceSubClass 1 00h 
7 bInterfaceProtocol 1 00h 
8 iInterface 1 05h "Source/Sink"

HID Descriptor
Offset Field Size Value Description
0 bLength 1 09h 
1 bDescriptorType 1 21h HID
2 bcdHID 2 0101h 1.01
4 bCountryCode 1 00h 
5 bNumDescriptors 1 01h 
6 bDescriptorType 1 22h Report
7 wDescriptorLength 2 0022h 34 bytes

Endpoint Descriptor 83 3 In, Interrupt, 125 us
Offset Field Size Value Description
0 bLength 1 07h 
1 bDescriptorType 1 05h Endpoint
2 bEndpointAddress 1 83h 3 In
3 bmAttributes 1 03h Interrupt
 1..0: Transfer Type  ......11  Interrupt
 7..2: Reserved  000000..   
4 wMaxPacketSize 2 0400h 1024 bytes
6 bInterval 1 01h 125 us

Endpoint Descriptor 04 4 Out, Interrupt, 125 us
Offset Field Size Value Description
0 bLength 1 07h 
1 bDescriptorType 1 05h Endpoint
2 bEndpointAddress 1 04h 4 Out
3 bmAttributes 1 03h Interrupt
 1..0: Transfer Type  ......11  Interrupt
 7..2: Reserved  000000..   
4 wMaxPacketSize 2 0400h 1024 bytes
6 bInterval 1 01h 125 us

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #1 on: August 01, 2011, 12:17:40 pm »
If the interrupt endpoint is sending > 64 bytes/transaction, it's operating at high speed.

The host controller should reserve the requested bandwidth for the endpoints, but the driver might not be able to request transfers fast enough to use all of the reserved bandwidth.

The USB sniffer snapshot appears to show a transfer every ms., but each transfer consists of 2 or more Seq items (transactions?) The report size is 8 * 255 bytes, so each request for a report would need at least 2 transactions. The sniffer doesn't show the timing of the transactions within the transfer, which might be at the requested rate of 125 microsecs.

Be sure the endpoint isn't NAKing. To increase the throughput, you could try putting more data in each report so there are fewer transfers with more data in each.

To comply with the USB 2.0 spec, interrupt endpoints in the default interface should have a wMaxPacketSize <= 64. It's possible the Windows driver doesn't enforce this but it might in the future. The Windows HID driver doesn't support alternate interfaces, so 64 is the maximum unless you use a custom driver.

Jan

Adrien Decostre

  • Member
  • ***
  • Posts: 12
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #2 on: August 02, 2011, 10:27:29 am »
Dear Jan,

Thanks for your fast answer.

The throughput has indeed been increased by setting larger packet size. For report_count and report_size set respectively to 1024 and 8, the throughput measured with a usb sniffing tool was about 1MBytes/sec.

However, increasing the report size has caused other problems. For test purpose, I have a small host application reading and processing the HID reports (this application uses the Windows DDK and is based on your Generic_HID_winAPI example). The test application works correctly for report_size set to 255bytes but does not return any data if the report_size is set to 512 bytes. The ReadFile function hangs (for synchronous usage) or returns a time-out error (for asynchronous usage). On the sniffer log, the transfers are well correctly displayed so I suppose that the problem must come from the host test application of the host driver.
Would the hidusb.sys driver prevent transfer of reports larger than 255bytes?

Thanks in advance for your answer.

Adrien

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #3 on: August 02, 2011, 11:06:02 am »
Windows may be remembering the previous descriptors. Use a different Product ID or in Device Manager, with the device attached, click uninstall, then detach and reattach. See:

http://www.janaxelson.com/forum/index.php?topic=420.msg1498#msg1498

Be sure the ReadFile buffer is large enough to hold the data.

Jan
« Last Edit: June 27, 2015, 09:53:50 am by Jan Axelson »

Adrien Decostre

  • Member
  • ***
  • Posts: 12
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #4 on: August 03, 2011, 08:35:02 am »
Dear Jan,

Thanks for these suggestions.

Unfortunately, these did not solve my issue.
The size of the buffer give to the 'readfile' function is 8192 bytes, so this should be OK for report size of 512 bytes.
I also tired the procedure described by Geoff but the problem is still present after re-connection.

I will further look at it and will keep you inform as soon I resolve this issue.

Best regards.

Adrien


Adrien Decostre

  • Member
  • ***
  • Posts: 12
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #5 on: August 03, 2011, 09:20:42 am »
OK, I finally “solve” it, or at least I found a workaround for it.

The problem was that the report size was set to 512 bytes while the transfer size was 510 bytes. If the transfer size is set to 512 bytes, the data are correctly retrieved via the ReadFile & GetOverlappedResult functions (in the both cases, the data were correctly captured by the usb sniffer).
Apparently, transfers smaller than the report size are discarded. This is quite strange and I did not observe this behavior when working with report size of 255bytes. I am still missing something ...
If someone would have any idea to explain this, I would be very interested to hear it.

Best regards.

Adrien

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #6 on: August 03, 2011, 09:28:29 am »
I'm not sure where you set the transfer size (device firmware?), but ReadFile returns only complete reports as specified in the report descriptor and ignores any other received data. The ReadFile buffer must be large enough to fit the entire report (or the largest report if using report IDs).

Jan

Adrien Decostre

  • Member
  • ***
  • Posts: 12
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #7 on: August 03, 2011, 09:33:01 am »
To come back to my initial question, I now achieve about 1MBytes/sec data rate with report size of 1024 bytes (input interrupt endpoint for a vendor specific hid device).
For a WinXP platform, I had expected to reach 8MBytes/sec. I am still missing a part of the puzzle...

Adrien

Adrien Decostre

  • Member
  • ***
  • Posts: 12
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #8 on: August 03, 2011, 09:42:04 am »
Jan,

Quote
I'm not sure where you set the transfer size (device firmware?), but ReadFile returns only complete reports as specified in the report descriptor and ignores any other received data. The ReadFile buffer must be large enough to fit the entire report (or the largest report if using report IDs).

I am setting the transfer on the device firmware (a ARM processor on which I use the gadgetfs framework to access the usb kernel driver from user-space).
The ReadFile buffer is several times larger than the report size (about a factor 15) such that it can hold several reports without losing data.

So, as I understand your comment, if I want to send a transfer with less data than the specified report size, it will be needed to do some zero "fulling" operation.

Thanks again for your valuable comments

Best regards

Adrien
« Last Edit: August 04, 2011, 10:32:03 am by Adrien Decostre »

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #9 on: August 03, 2011, 09:54:43 am »
Yes, HID data is always in reports that must match the size defined in the report descriptor.

Jan

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #10 on: August 03, 2011, 10:10:22 am »
To come back to my initial question, I now achieve about 1MBytes/sec data rate with report size of 1024 bytes (input interrupt endpoint for a vendor specific hid device).
For a WinXP platform, I had expected to reach 8MBytes/sec. I am still missing a part of the puzzle...

Adrien

Each request for a HID report results in a USB transfer. If the transfer size > wMaxPacketSize, the transfer consists of multiple transactions.

The host controller reserves the requested bandwidth, but that doesn't guarantee that the host driver can request transfers at the maximum possible rate. That's why larger transfers can result in greater throughput. For the transaction attempts within a transfer, the host adheres to the requested max latency, but the delays between transfers can be longer.

You could increase the report size to 2048 bytes and see if the throughput rises.

Jan

Adrien Decostre

  • Member
  • ***
  • Posts: 12
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #11 on: August 03, 2011, 10:57:20 am »
Indeed, I had not yet tried report size of 1024 bytes because I thought this was not interesting since the maximum packet size for interrupt is limited to 1024 bytes (at least to my knowledge).
I was clearly wrong  :). Tests with a report size of 4096 bytes have led to a measured data rate of about 3.3MBytes/sec:
  • report size: 1024bytes     measured data rate ~1MBytes/sec
  • report size: 2048bytes     measured data rate ~2MBytes/sec
  • report size: 4096bytes     measured data rate ~3.3MBytes/sec

As you explained, each transfer is then splits in multiple transactions.

The data rate saturates for report size of 4096 bytes (the increase factor is lower than when switching from 1024 bytes to 2048 bytes). This matches with what is observed via the sniffer: the time elapsed between the transfer request and the transfer completion is now about 1.2ms (while it was about 1ms for smaller report).

I have also done some tests with 8192 bytes reports but there were no data sent on the bus. The usb transfers failed and the reported urb status were "USBD_STATUS_XACT_ERROR". I must further investigate what is then happening.

Best regards

Adrien

coolsunny2012

  • Member
  • ***
  • Posts: 19
Re: Polling rate problem for HID IN interrupt endpoint
« Reply #12 on: June 20, 2012, 11:56:42 am »
Can you share the collection table that does set the report size to 1024 bytes. I am trying to figure out how to increase the report size to 1024 bytes. I am able to increase the report size to 255 bytes.