Author Topic: USB HID Enumeration  (Read 12109 times)

0 Members and 1 Guest are viewing this topic.

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
USB HID Enumeration
« on: January 13, 2017, 02:48:37 pm »
Hello to everyone!

Is there USB HID enumeration experts on this forum? I am stuck and would appreciate help :)
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #1 on: January 13, 2017, 05:35:43 pm »
So do we need to pull information from you? What is the problem?
Alex
 

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
Re: USB HID Enumeration
« Reply #2 on: January 13, 2017, 09:28:30 pm »
Thanks for the reply, Alex!

I am trying to implement a HID with Microchip PIC. I want to implement USB code myself, so I do not use any library or third-party framework. I have studied USB transactions and higher level control transfers. I am able to enumerate till Windows requests the HID report descriptor. I transfer mine and get... the reset. I have tried differrent HID report descriptors -- the result is either a blue screen, or USB reset.

The request for HID report descriptor by Windows XP host looks very suspitious to me. Here is the setup data I receive:

81 06 00 22 00 00 5d 00

The length is 0x005d, where as my  HID report descriptor is of 29 byte only. Why? I have no idea at the moment.

I attach the log of my enumeration as seen by the device, and my descriptors. Do you see any problems? What to check else and where?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #3 on: January 13, 2017, 09:50:34 pm »
This https://github.com/ataradov/dgw/tree/master/embedded has a simple working implementation of a HID device for SAM D21. You can take a descriptor from there, it works under Windows, Linux and OS X for sure.

I don't know if your descriptors are correct, since I don't want to decode binary data, it is not 1970 anymore.

The length is 0x005d, where as my  HID report descriptor is of 29 byte only. Why? I have no idea at the moment.
Host does not know how big your descriptor is, so it requests a big number. You should respond with the actual number of bytes you have. My Win7 requests 97 (0x61) bytes, for example.
Alex
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #4 on: January 13, 2017, 10:04:10 pm »
Your descriptors appear to be correct (or at least parsable), so it must be something in a way you are sending them.

I'm attaching a handy USB descriptor parser. It is an HTML page that works offline. It parses your thing to this:
Quote
0x06, 0x00, 0xFF,  // Usage Page (Vendor Defined 0xFF00)
0x09, 0x01,        // Usage (0x01)
0xA1, 0x01,        // Collection (Application)
0x19, 0x01,        //   Usage Minimum (0x01)
0x29, 0x40,        //   Usage Maximum (0x40)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x75, 0x08,        //   Report Size (8)
0x95, 0x40,        //   Report Count (64)
0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x19, 0x01,        //   Usage Minimum (0x01)
0x29, 0x40,        //   Usage Maximum (0x40)
0x91, 0x00,        //   Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0,              // End Collection
// 29 bytes

Alex
 
The following users thanked this post: aandrew

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
Re: USB HID Enumeration
« Reply #5 on: January 18, 2017, 09:36:35 pm »
Alex, could you kindly tell me the idea of clear/set feature, e.g. udc_endpoint_clear_feature in udc.c? I do not know the chip you used and cannot see what it does. I get Clear Feature request now from the host, but do not know what it is supposed to do. Where is it specified?

 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #6 on: January 18, 2017, 09:46:23 pm »
Alex, could you kindly tell me the idea of clear/set feature, e.g. udc_endpoint_clear_feature in udc.c? I do not know the chip you used and cannot see what it does. I get Clear Feature request now from the host, but do not know what it is supposed to do. Where is it specified?
For endpoints, Clear Feature request must clear stall state of the corresponding endpoint. This is a part of the USB spec, although I don't know if hosts ever send this request. EDIT: apparently they do :)

In theory Set Feature for endpoint puts endpoint into the stall state, so this lets host to pause traffic from the endpoint. Clear Feature is used to reverse this process and enable the traffic.
Alex
 

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
Re: USB HID Enumeration
« Reply #7 on: January 18, 2017, 10:25:36 pm »
Thanks, Alex!

Now I get Clear Feature request. I enable endpoint 1 IN and arm endpoint 0 IN for the status ZLP. I see the status stage completes fine and then... reset and code 43 in Windows Device Manager. What am I missing? :)

UADDR=0a
PIR2.USBIF=1
UIE=00101011
UIR=01011100
UIR.TRNIF=1, usb transaction completed
USTAT=00000000
0400 34 08 00 05
0500 02 01 00 00 81 00 00 00
endpoint 0 setup
clear feature

UADDR=0a
PIR2.USBIF=1
UIE=00101011
UIR=01011100
UIR.TRNIF=1, usb transaction completed
USTAT=00000100
0404 64 00 40 05
0540
endpoint 0 in

UADDR=00
PIR2.USBIF=1
UIE=00101011
UIR=01010101
UIR.URSTIF=1, usb reset detected

 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #8 on: January 18, 2017, 10:31:42 pm »
I have no idea. I would strongly suggest to use Linux for debugging USB devices. Linux is way more descriptive with what's wrong with the device.
Alex
 

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
Re: USB HID Enumeration
« Reply #9 on: January 18, 2017, 11:59:09 pm »
Alex, if I change bNumEndpoints to zero in the interface descriptor, it enumerates OK. However, I see 2 devices: HID-compliant device and USB Human Interface Device. Why?.. :)
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #10 on: January 19, 2017, 12:03:24 am »
Alex, if I change bNumEndpoints to zero in the interface descriptor, it enumerates OK. However, I see 2 devices: HID-compliant device and USB Human Interface Device. Why?.. :)
You are doing something non-standard, so absolutely any behavior is normal. I have no idea what windows does on the inside when it sees malformed descriptors.
Alex
 

Offline John_ITIC

  • Frequent Contributor
  • **
  • Posts: 522
  • Country: us
  • ITIC Protocol Analyzers
    • International Test Instruments Corporation
Re: USB HID Enumeration
« Reply #11 on: January 20, 2017, 03:19:08 am »
Normally a hardware USB analyzer is needed when software analyzers can not be used due to system crashes. PM me if you need to buy one and I can give you a good price.
/John.
Pocket-Sized USB 2.0 LS/FS/HS Protocol Analyzer Model 1480A with OTG decoding.
Pocket-sized PCI Express 1.1 Protocol Analyzer Model 2500A. 2.5 Gbps with x1, x2 and x4 lane widths.
https://www.internationaltestinstruments.com
 

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
Re: USB HID Enumeration
« Reply #12 on: January 23, 2017, 10:32:07 am »
I agree the analyser would be great to have, but I do not have one.

I have found the problem. It was the way I controlled the endpoint 1 for interrupts IN and OUT transfers. It looks like Windows built-in HID driver expects the endpoints defined in the interface to reply with NAK's or data after SetConfiguration is done. I did not do that properly initially, hence the reset.

I attach the enumeration log I see in a successful case.

Could somebody tell me the idea with HID reports? Does host buffer them once it receives some? When does host send a report? Basically, I want to transfer some data to and from my HID running on the microcontroller.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #13 on: January 23, 2017, 05:13:43 pm »
It looks like Windows built-in HID driver expects the endpoints defined in the interface to reply with NAK's or data after SetConfiguration is done. I did not do that properly initially, hence the reset.
During the configuration stage only control endpoint needs to send ZLP. In general, all endpoints must send NACK or STALL in response to request if they don't have data. This should be done by the hardware, since software can't be fast enough.

Could somebody tell me the idea with HID reports?
Depends on a report configuration. If it looks like a keyboard or a mouse, then they become corresponding devices.

Does host buffer them once it receives some?
If it is just an arbitrary data, then noting is buffered unless there is a client attached, in which case requests are forwarded to that client.

When does host send a report?
Only when requested by the client.

Basically, I want to transfer some data to and from my HID running on the microcontroller.
Here is example of PC side of things for Windows and Linux - https://github.com/ataradov/dgw/tree/master/cli
Alex
 

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
Re: USB HID Enumeration
« Reply #14 on: January 23, 2017, 06:59:17 pm »
Thanks, Alex! I appreciate you helping me.

In my case, endpoint 1 was declared for both IN and OUT interrupt transfers. However, I simply forgot to enable it. Host receives nothing polling the endpoint IN, desides the device malfunctions and resets it.

I could enumerate when I removed the descriptors of endpoint 1 in the interface. Then, I realized I forgot to enable the endpoint 1. I also forgot to initialize the buffer descriptors of endpoint 1 properly for a couple of tries and got a bit confused. Anyway, finally it all looks logic and expected. Now I want to continue with the application for Windows. That's why I asked about the reports. I will study your code, Alex, as well as Windows documentation on HID.
 

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
Re: USB HID Enumeration
« Reply #15 on: February 20, 2017, 10:13:22 pm »
I am puzzled again. Please help.

I have the followig HID report descriptor:

06 00 ff 09 01 a1 01 15 00 26 ff 00 75 08 95 40 09 01 81 02 95 40 09 01 91
02 95 01 09 01 b1 02 c0

0x06, 0x00, 0xFF,  // Usage Page (Vendor Defined 0xFF00)
0x09, 0x01,        // Usage (0x01)
0xA1, 0x01,        // Collection (Application)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x75, 0x08,        //   Report Size (8 )
0x95, 0x40,        //   Report Count (64)
0x09, 0x01,        //   Usage (0x01)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x40,        //   Report Count (64)
0x09, 0x01,        //   Usage (0x01)
0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x01,        //   Report Count (1)
0x09, 0x01,        //   Usage (0x01)
0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0,              // End Collection

// 33 bytes

It defines the input and output reports of 64 bytes.

Why do I get Windows returning 65 in HIDP_CAPS.InputReportByteLength and HIDP_CAPS.OutputReportByteLength?

Where does HIDP_CAPS.FeatureReportByteLength = 2 come from?

Any ideas?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #16 on: February 20, 2017, 10:17:22 pm »
Why do I get Windows returning 65 in HIDP_CAPS.InputReportByteLength and HIDP_CAPS.OutputReportByteLength?
This is normal. Those values indicate the size of the chunk you need to write into a file corresponding to the device. The first byte is always "Report ID" and the rest is an actual payload. Same goes for reading, the first read byte is report ID.

Where does HIDP_CAPS.FeatureReportByteLength = 2 come from?
No idea on this one.
Alex
 

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
Re: USB HID Enumeration
« Reply #17 on: February 20, 2017, 10:19:27 pm »
Alex, thanks a lot! I am glad you are around here and helping.

How do I know the report ID value? Where does it come from? :)
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #18 on: February 20, 2017, 10:20:57 pm »
If you only have one report (as you do in this case), then it is always 0. And then it just increments by one for each report type supported by the device.
Alex
 

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
Re: USB HID Enumeration
« Reply #19 on: February 20, 2017, 10:23:55 pm »
OK. Zero it is.

Now, if report length is of 65 bytes, does it come in 2 USB transactions? First of 64 bytes and second of 1 byte?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #20 on: February 20, 2017, 10:29:04 pm »
No, the report itself is 64 bytes. Added 1 byte is an OS abstraction. So you need to add 1 byte (0) in front of your data when you do WriteFile() and discard the first byte after ReadFile().

And you need to specify 65 bytes length for reading/writing.

Example: https://github.com/ataradov/edbg/blob/master/dbg_win.c
Alex
 

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
Re: USB HID Enumeration
« Reply #21 on: February 20, 2017, 10:32:53 pm »
H-m, that's unexpected and very interesting. How do you know all that, Alex? Is there a good documentation or source of information?

I'll continue and see how it goes.

Thanks!
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #22 on: February 20, 2017, 10:37:12 pm »
H-m, that's unexpected and very interesting. How do you know all that, Alex? Is there a good documentation or source of information?
I originally implemented this stuff on Linux, and there are some good examples with explanations for that.

Later, when I did a Windows port, I just assumed that things are similar. So I just tried the same thing, and it worked. I originally just had a fixed report size, so detecting was not an issue.

Later, when I got to reading CAPS, I saw that it returns 1 byte more than needed, and I just assumed that it included that report ID byte.

So a lot of assumptions and experimenting.
Alex
 
The following users thanked this post: digsys

Offline BamburTopic starter

  • Regular Contributor
  • *
  • Posts: 70
Re: USB HID Enumeration
« Reply #23 on: February 23, 2017, 09:14:29 pm »
I got sending and receiving reports working.

UADDR=05
PIR2.USBIF=1
UIE=00101011
UIR=01011100
UIR.TRNIF=1, usb transaction completed
USTAT=00001000
0408 04 40 80 05
0580 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19
1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34
 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40
endpoint 1 out

UADDR=05
PIR2.USBIF=1
UIE=00101011
UIR=01011100
UIR.TRNIF=1, usb transaction completed
USTAT=00001100
040c 24 40 80 05
0580 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19
1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34
 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40
endpoint 1 in

As Alex said, I need to provide a buffer one byte longer than the report length:

BYTE out[65]; for (BYTE i = 0; i < 65; i += 1) out[ i ] = i;

HID receives 64 bytes only, though. What a mess :)

Is it OK to have endpoint 1 bidirectional? It works, but is it inline with the spec?


« Last Edit: February 23, 2017, 09:18:50 pm by Bambur »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11996
  • Country: us
    • Personal site
Re: USB HID Enumeration
« Reply #24 on: February 23, 2017, 09:23:18 pm »
HID receives 64 bytes, though. What a mess :)
Well, this is a consequence of using a 'file' as an abstraction for everything and the need to communicate more than one piece of information.

is it inline with the spec?
Absolutely.

Some hardware implementations only support one way communication on a particular endpoint index, so I just pick different numbers even on the ones that support bidirectional operation. This way all my descriptors on all hardware platforms are the same.
Alex
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf