Problem with reading HID reports from host on OS X; missing reports and ENDPOINT_RWSTREAM_Timeout error.

271 views
Skip to first unread message

Liam Lacey

unread,
Nov 19, 2012, 7:11:54 AM11/19/12
to lufa-s...@googlegroups.com
Hey
Firstly, I posted a similar post last week however after a few bug fixes and a lot of testing I discovered most of what I stated at first was now obsolete so I deleted the post. However I'm still having report reading problems.

I'm using the LowLevel GenericHID demo to send and receive HID reports to and from a custom HID host application, in which I have used the HIDAPI library.

First problem: Not all of my out reports coming into the device are being received when the host is running on OS X, though on Windows everything seems to be fine. When logging within HIDAPI's hid_write() function all reports are definitely being sent with all the bytes and values intact. I've been testing things with two LUFA projects - one that is pretty much an unmodified version of the GenericHID demo (apart from adding my own code to the ProcessReport and CreateReport functions and some logging code within HID_Task() ), and one where I have taken the GenericHID demo and made it a composite HID/MIDI device. With the latter project, as well as not receiving every report sent, when sending reports from my host very quickly the received report size seems to change, receiving incomplete reports.

I'm fairly new to the HID protocol so I don't fully understand its inner workings. Does the device contain some kind of 'received reports' buffer or queue? If a report is received whilst there still an 'unread' report that was previously received, do any of the reports just simply get ignored? Also, would would be causing only a fraction of the reports to be received sometimes?

Second problem: Most of my successfully received/processed reports are returning 4/ENDPOINT_RWSTREAM_Timeout from the Endpoint_Read_Stream_LE() function. I have tried changing the USB_STREAM_TIMEOUT_MS value within LUFAConfig.h however I have noticed no change.

What does the ENDPOINT_RWSTREAM_Timeout actually mean and what causes it? 

Finally, as everything seems fine on Windows, I was wondering if there are any known differences between HID on these platforms. Is the data rate of HID known to be quicker on Windows?

Any help would be greatly appreciated as I have been pulling my hair out over this problem for a few days now!

I'm using an atmega32u4 16MHz CPU board.

Thanks.

Liam Lacey

unread,
Nov 27, 2012, 6:42:11 AM11/27/12
to lufa-s...@googlegroups.com
I should probably supply some code.
The following link is for the genericHID.c file for the composite MIDI/HID project. Currently it is setup to read HID reports that contain MIDI bytes that are then forwarded on through the MIDI device as MIDI messages, as well as sending HID reports back to the host containing the MIDI data recieved and a bunch of test variables. 

Dean Camera

unread,
Dec 16, 2012, 11:02:32 PM12/16/12
to lufa-s...@googlegroups.com
Liam,

Sorry I missed this one.

The HID class contains a single buffer for reports, which is is used to determine when a report needs to be sent to the host. There's no queue involved; since HID is designed for time critical but not integrity critical data, if multiple reports are queued up before they can be sent only the newest report is sent to the receiving device. This makes HID great for what it is designed to do - send human interaction data to a PC - but complicates things when you want to use it to send any old data in a reliable manner.

How long are the reports you are trying to send, how large is your GENERIC_REPORT_SIZE constant, and how large are the HID endpoints? Try to make sure that you send less than GENERIC_REPORT_SIZE reports in both directions, and make sure that GENERIC_REPORT_SIZE is less than the endpoint size by at least one byte just to keep things simple.

Cheers!
- Dean

Kaspar Bumke

unread,
Feb 9, 2013, 1:18:13 PM2/9/13
to lufa-s...@googlegroups.com
Hey Dean,

I work with Liam and I am just looking at these HID woes again. I am
re-designing our protocol to make efficient use of the endpoint size.
You said:

>GENERIC_REPORT_SIZE reports in both directions, and make sure that GENERIC_REPORT_SIZE is less than the endpoint size by at least one byte just to keep things simple.

What is that last byte used for? I was going just going to make the
GENERIC_REPORT_SIZE the same as the HID IN and OUT endpoints size
(both 64 bytes).

Regards,

Kaspar

Kaspar Bumke

unread,
Feb 11, 2013, 10:59:10 AM2/11/13
to lufa-s...@googlegroups.com
Thinking about this a bit further, say the endpoint size is 64 bytes
and the GENERIC_REPORT_SIZE is 4 bytes. Are they overwritten after 16
messages or are they overwritten after just 1?

Dean Camera

unread,
Feb 17, 2013, 9:58:14 AM2/17/13
to LUFA Library Support List
Kaspar,

> What is that last byte used for? I was going just going to make the
> GENERIC_REPORT_SIZE the same as the HID IN and OUT endpoints size
> (both 64 bytes).

The last (actually first) byte is used by the PC to tell the device
what report ID the data is being directed to. The HID protocol allows
for multiple different reports to be multiplexed through the same
physical endpoint (see the KeyboardMouse device demo) by assigning
each report a non-zero unique ID, and then prefixing reports with that
ID. This means that for a 64 byte endpoint, the first byte will
contain the report ID and the remaining data will belong to that
report.

If no report IDs are specified the host will assume that there is only
one report with ID 0x00.

> Thinking about this a bit further, say the endpoint size is 64 bytes
> and the GENERIC_REPORT_SIZE is 4 bytes. Are they overwritten after 16
> messages or are they overwritten after just 1?

Just one. HID reports are volatile and single buffered by design, so
that new report data immediately succeeds old data.

Cheers!
- Dean

On Feb 9, 7:18 pm, Kaspar Bumke <kaspar.bu...@gmail.com> wrote:
> Hey Dean,
>
> I work with Liam and I am just looking at theseHIDwoes again. I am
> re-designing our protocol to make efficient use of the endpoint size.
> You said:
>
> >GENERIC_REPORT_SIZE reports in both directions, and make sure that GENERIC_REPORT_SIZE is less than the endpoint size by at least one byte just to keep things simple.
>
> What is that last byte used for? I was going just going to make the
> GENERIC_REPORT_SIZE the same as theHIDIN and OUT endpoints size

Kaspar Bumke

unread,
Feb 18, 2013, 1:26:47 PM2/18/13
to lufa-s...@googlegroups.com
> The last (actually first) byte is used by the PC to tell the device
> what report ID the data is being directed to. The HID protocol allows
> for multiple different reports to be multiplexed through the same
> physical endpoint (see the KeyboardMouse device demo) by assigning
> each report a non-zero unique ID, and then prefixing reports with that
> ID. This means that for a 64 byte endpoint, the first byte will
> contain the report ID and the remaining data will belong to that
> report.

if you are building on the LowLevel demos and doing something like
below, then are you managing that multiplexing yourself and making use
of that first byte for it?

uint8_t data[GENERIC_REPORT_SIZE];
data[0] = 0x02;
Endpoint_Write_Stream_LE(&data, sizeof(data), NULL);

Are you also telling the receiving end to interpret this report as
Report 0x02, as in the "vendor usage" set by HID_RI_USAGE in the
"USB_Descriptor_HIDReport_Datatype_t"?

Kaspar Bumke

unread,
Feb 18, 2013, 5:08:59 PM2/18/13
to lufa-s...@googlegroups.com
I think I have figured this out but please confirm if this is correct:


if you are building on the LowLevel demos and doing something like
below, then are you managing that multiplexing yourself and making use
of that first byte for it?

Yes.

Are you also telling the receiving end to interpret this report as
Report 0x02, as in the "vendor usage" set by HID_RI_USAGE in the
"USB_Descriptor_HIDReport_
Datatype_t"?

Technically yes, and it's probably good practice to stick to that but you
could implement your own interpretation if you just want the
device to work with your (host) software.  It has no impact at the driver level.

Dean Camera

unread,
Feb 24, 2013, 9:48:51 AM2/24/13
to lufa-s...@googlegroups.com
Are you also telling the receiving end to interpret this report as
Report 0x02, as in the "vendor usage" set by HID_RI_USAGE in the
"USB_Descriptor_HIDReport_Datatype_t"?

Not quite - it's report index 0x02, as set by a HID_RI_REPORT_ID element in the HID descriptor. The usage page elements describe the usage of data within a report, while the report ID identifies the report itself.

You can see this in the KeyboardMouseMultiReport device class driver demo, where I define two report IDs; report 0x01 for mouse reports and 0x02 for keyboard reports. When I need to send a report for one of the two control inputs (keyboard or mouse) I use the first byte of the report to signal the host which of the two defined reports is contained in the remainder of the packet.

Cheers!
- Dean
Reply all
Reply to author
Forward
0 new messages