Author Topic: Error list for HID  (Read 24935 times)

sealion

  • Member
  • ***
  • Posts: 2
Error list for HID
« on: September 06, 2011, 02:46:55 pm »
Hi Jan,

where do you find the list of errors for HID APIs used? For instance: I received error 23 for HidD_GetInputReport()...?!

Thank you,
Larry

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Error list for HID
« Reply #1 on: September 06, 2011, 03:37:35 pm »
Error codes

http://msdn.microsoft.com/en-us/library/ms681381%28VS.85%29.aspx

Related info

http://msdn.microsoft.com/en-us/library/ms679360%28VS.85%29.aspx

It looks like 23 is CRC error, which in my experience is the response to just about any unexpected data, not necessarily a CRC error.

HidD_GetInputReport initiates a control transfer. The host expects the device to return a report in the transfer's Data stage.

Jan

Ray

  • Member
  • ***
  • Posts: 13
Re: Error list for HID
« Reply #2 on: November 30, 2011, 06:06:02 am »
Larry,

Did you ever sort this out? I have the same issue.

The host is not even trying to talk to the device (according to the bus analyser). The function fails before that stage.

Cheers,

Ray

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Error list for HID
« Reply #3 on: November 30, 2011, 02:27:48 pm »
If HidD_GetInputReport isn't resulting in any traffic, there is something wrong with the API call. I have example code here:

http://www.lvr.com/hidpage.htm#MyExampleCode

or post your code and maybe someone will see something.

Jan

Ray

  • Member
  • ***
  • Posts: 13
Re: Error list for HID
« Reply #4 on: December 01, 2011, 03:42:12 pm »
Jan,

Thanks for the response, and thanks for the forum and the dedication to trying to help out people like me.

 I made some modifications to the code and got it working correctly. Unfortunately I changed too many things at once and did not narrow down the exact cause of the problem. Some of the errors were fundemental coding issues, but for others that might have similar issues I will note what I found, warts and all:

 1) I changed the report descriptor in the firmware to designate a 2  byte report (report size 1, report count 16) rather than the 1 byte that I had left in there my initial version. I had thought that the Interrupt transfer would be the only thing affected by this because the other Control Transfers over endpoint 0 were not limited by the size in the report descriptor - it appears that my assumption was wrong as I sometimes forget that the generic functions are not limited to use on HIDs. When I reintroduced this error I got a new error code of 31. So that wasn't the intial problem, but nice to know. (I will have to try HIDD_GetFeature to see how that is treated - later).
 2)  I changed the buffer size from a hard coded value of 3 (report size is 2 + 1 for the report ID) to use the DevCaps instead (which still returned 3 anyway - after correcting the firmware in item 1 above that is.)
 3) I had passed a int* as the buffer instead of a char*. This was left over from me playing around to see what effect it might have because the HIDD_GetInputReport only specifies PVOID, and I was thinking that there might have been a byte aligning issue. This was probably the orignal cause of the error I was getting. I did not change the code back to check.
 4) I increased the size of my buffer from 3 to 255 as you had in your code example, but I did this before I corrected the buffer type, so when I fixed the other problems I went back to designate a value of 2 to see the effect and then 3 to check. I now dynamically allocate the buffer size with char* pBuffer = new BYTE[m_DeviceCaps.InputReportByteLength] and this works.
 5) At some point when changing from a static buffer (char[]) to a dynamically allocated buffer (char*) I tried to set the first byte to 0 (no report id used) with pBuffer = 0 instead of *pBuffer = 0. This brought up a new error, but this was easy enough to spot and correct.

I hope that this help someone else with similar issues.

Now to narrow down why my ReadFile is hanging even though the bus activity is clearly showing that the IN transaction on EP1 is obtaining the correct data every 4ms or so. Probably some fundemental thing wrong in the API call as was above.

Regards,

Ray.


Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Error list for HID
« Reply #5 on: December 01, 2011, 04:51:15 pm »
ReadFile returns when the HID's interrupt endpoint has sent a report whose size and report ID match the size and report ID specified in the HID's report descriptor.

If the endpoint is sending a number of bytes that doesn't correspond to the number of bytes specified, or if the endpoint is sending a report ID when the HID uses only the default ID, or if the endpoint is sending a report ID with an incorrect number of bytes, the HID driver ignores the data and ReadFile doesn't see it.

The ReadFile buffer needs to be at least large enough to hold the report plus one byte for the report ID. If the endpoint doesn't send a report ID, the buffer uses zero.

Thanks for sharing your debugging!

Jan
« Last Edit: December 01, 2011, 04:55:00 pm by Jan Axelson »

Ray

  • Member
  • ***
  • Posts: 13
Re: Error list for HID
« Reply #6 on: December 08, 2011, 05:33:53 am »
Jan,

I still have the ReadFile hang. I have tried to narrow down my error for days now, but no luck. Maybe someone can see some fundemental error in my work.

I have verified on the bus that I am actually seeing 2 bytes of data. The Host is sending an ACK in response.
The report descriptor declares 2 bytes (16 x 1bit) for the input report.
The Get_Report is working via HIDD_GetInputReport
My WriteFile is working.
I have used CreateFile for Synchronous access.
I use the InputReportByteLength member of the Attributes structure to set the report size (3 in my case).
I have set the polling rate to 1ms to make sure there is no chance of a delay in filling the buffer, and the bus analyser sees a packet every ms as expected.

I could try to use asynchronous access, but that would just mean my program wouldn't hang, but if I would still never see a report if they are being dropped by the driver.

Report Descriptor
Code: [Select]
db 0x06, 0x00, 0xFF ;USAGE_PAGE (Vendor Defined Page 1)
db 0x09, 0x01 ;USAGE (I/O Device)
db 0xA1, 0x01 ;COLLECTION (Physical)
db 0x19, 0x01 ; Usage_Minimum (Button 1)
db 0x29, 0x08 ; Usage_Maximum (Button 8)
db 0x15, 0x00 ; Logical_Minimum (0)
db 0x25, 0x01 ; Logical_Maximum (1)
db 0x75, 0x01 ; Report_Size (1)- 1 bit report size
db 0x95, 0x10 ; Report_Count (16) - 16 x 1 bit reports (2 bytes in total)
db 0x81, 0x02 ; Input (Data,Var,Abs)
db 0x19, 0x01 ; Usage_Minimum (Led 1)
db 0x29, 0x08 ; Usage_Maximum (Led 8)
db 0x95, 0x08 ; Report Size (8) - 8 x 1 bit reports (1 byte in total)
db 0x91, 0x02 ; Output (Data,Var,Abs)
db 0xC0 ;END_COLLECTION


CreateFile() - the Handle returned works for the WriteFile, HIDD_GetInputReport and HIDD_SetOutputReport
Code: [Select]
m_DeviceHandle = CreateFile(pDeviceInterfaceDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING ,
FILE_ATTRIBUTE_NORMAL ,
NULL);


Call to the member function and initial buffer declarations
Code: [Select]
CHIDDevice a(0x4242,0x0001, 0x0100);
.
.
BYTE* pInbuf = new BYTE[a.GetDevCaps().InputReportByteLength];
.
.
.
a.GetData(pInbuf, 0, true);


Member Function Getdata() that calls ReadFile()
Code: [Select]
int CHIDDevice::GetData(BYTE* pBuffer, BYTE rptID, bool Interrupt)
{

DWORD BytesRead = 0;

if (!pBuffer) return CHIDDeviceError_BufferError;
pBuffer[0] = rptID;

if (!m_DeviceHandle) return CHIDDeviceError_NoDevice;

if (Interrupt)
{
if(!ReadFile( m_DeviceHandle,
pBuffer,
m_DeviceCaps.InputReportByteLength ,
&BytesRead,
NULL))
{
return CHIDDeviceError_ReadBuffer;
}
}
else
{

if (!HidD_GetInputReport(
m_DeviceHandle,
pBuffer,
m_DeviceCaps.InputReportByteLength
))
{
return CHIDDeviceError_ReadBuffer;
}
}
return CHIDDeviceError_NoError;
}

I am at a loss.

Ray.



Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Error list for HID
« Reply #7 on: December 08, 2011, 10:09:44 am »
Does the endpoint number that is sending the data match the endpoint number in the HID descriptor for an interrupt IN endpoint?

Jan

Ray

  • Member
  • ***
  • Posts: 13
Re: Error list for HID
« Reply #8 on: December 08, 2011, 03:00:26 pm »
Jan,

Yes (I assume that you actually meant the Enpoint Descriptor and not the HID Descriptor). The endpoint is 1 when looking at the bus. I am using a PIC18F4550 chip, so I am putting the Interrupt data into Buffer Descriptor 3 (EP1) and Get_Report data in Buffer Descriptor 1 (EP0). It is getting the right data becuase I am sending different data from EP0 as compared to EP1 so that I could be sure when I see it at the host (..if I see it at he host). I can see the correct data on the bus corresponding to EP1 (BD3).

Endpoint Descriptor
Code: [Select]
db 0x07 ;length
db 0x05 ;descriptor type
db 0x81 ;bEndpointAddress (bit 7 = 1 for input - to the PC, EP1)
db 0x03 ;bmAttributes (bits 1..0 == 11 for Interrupt)
db EP1MAXPSIZE ;currently set to 0x08
db 0x00
db .1 ;the polling rate - 1ms

Thanks

Ray

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Error list for HID
« Reply #9 on: December 08, 2011, 04:34:45 pm »
Yes, I meant report descriptor.

One more thing to try. In case Windows or the driver is "remembering" previous descriptors, either change the PID or follow this procedure to cause Windows to forget what it knows about the device:

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

Jan

Ray

  • Member
  • ***
  • Posts: 13
Re: Error list for HID
« Reply #10 on: December 13, 2011, 07:31:37 pm »
Thanks Jan.

I tried uninstalling, uninstalling and rebooting, new PID, new Version Number. Then I changed the polling rate and the rate at which I made the data available (available more often than polled and then NAKed due to lower rate of data available than polled - operatated as expected on the bus). I then went back to only 1 byte transfer (per the examples I had used to base my project on) but no joy there either. All the while the expected data was on the bus,IN, DATA0, EP1, ACKed et al.

I then went over all the Descriptors to make sure that they were all correct, not just the Report Descriptor. They seem to be.

I did note however that the HID 1.11 stated this (section 4.4):

The Interrupt pipe are used for:
  • Receiving asynchronous (unrequested) data from the device.
  • Transmitting low latency data to the device.

Is it that my PC is actually doing what it is meant to, and I NEED to be performing OVERLAPPED reads? Or is it that the term asynchronous here is actually just 'unrequested', and does not align itself with the usage by Microsoft?

I also read somewhere that someone was having an unrelated problem due to the fact that they were stepping through the code in VC++. I built a release version of the software and ran it from the command line to see if that affected anything. Sadly not.

I will now try an asynchronous (overlapped) call to ReadFile as you have done in your book.

VERY FRUSTRATING  >:(

Regards,

Ray

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Error list for HID
« Reply #11 on: December 13, 2011, 10:29:45 pm »
The term asynchronous means 'unrequested' and can use synchronous or asynchronous transfers on the host.

As a sanity check, you could try my PIC HID firmware with my host application with no changes. If that works, look for differences.

Jan

Ray

  • Member
  • ***
  • Posts: 13
Re: Error list for HID
« Reply #12 on: April 04, 2012, 07:23:52 pm »
Jan,

I finally got some time to try different solutions and review your generic HID host software and PIC 18F4550 Firmware.

I had the same issues using your host software. So it would seem for the moment at least that my Host Software might be OK, except for the fact that it is not working.

My firmware is written in assembler, but I changed it to operate in a similar manner to yours. Instead of arming the IN Interrupt endpoint every 4ms (if a report has been read - ie the UOWN bit of the USTAT register was clear), I went with your approach, arming the Interrupt IN endpoint when an Interrupt OUT is sent, and returning the values sent to the host.

I have now had limited success.

  • I have sent a single Interrupt OUT and then managed to return the value with ReadFile(). Sending a subsequent Interrupt OUT followed by a call to ReadFile still hangs. I have verified the IN transaction on the bus. It was correct, and was ACKed.
  • I have sent two or more Interrupt OUTs prior to a call to ReadFile, but only the first call to ReadFile() does not hang. My buffer is confirmed as being the default 32 reports in size, so there should be space.
  • I have sent two of more Interrupt OUTs and requested double the number if bytes to be read using ReadFile() and doubled the buffer sent to match , but only the first report is returned. The number of bytes transmitted returned by readfile is also only equal to a single report. I have checked the contents of the rest of the returned buffer just in case, but there is no data there (I zeroed ou the data prior to the call)
  • I have verified all the traffic on the bus. An OUT transfer is followed very closely by an IN transfer, as expected, in all cases (my polling period is set at 100ms). The IN transfers are all ACKed by the Host, but it just does not seem to be making it into the buffer.

I wonder if using a buffer that is an array of char is messing things up. I know C++ deals with char arrays a little differently at times, but I have been checking the contents of the buffer in Debug mode to make sure that the values are correct. The character array is created at runtime with a call:
          char* pBuffer = new char[sizeofinputbuffer];

I am also using report IDs. I have verfied that the correct report ID is on the bus, and that the size of the report in the attributes includes this. I am sending two bytes of data plus 1 byte with the report ID. I only did this because I could not get the default with no report ID to work at all. I have also verified that for the call to ReadFile that is successful includes the report ID correctly in the first byte, and it does (or it wouldn't have been successful).

I don't see what I have fundementally changed between my first version and the new one that might stop the call to ReadFile from hanging everytime, to now only hanging after the first call.

Any further ideas? If not I will just keep plugging away and trying seemingly worthless tests to see if anything changes. Anything I find I will post here for any others with similar problems.

Regards,

Ray

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Error list for HID
« Reply #13 on: April 04, 2012, 09:18:22 pm »
When the receiver is ACKing but ignoring received data, check the data-toggle value included with the sent data.

Jan

Ray

  • Member
  • ***
  • Posts: 13
Re: Error list for HID
« Reply #14 on: April 05, 2012, 07:42:07 pm »
Jan,

Thankyou. It all works now. I had been resetting the DATA toggle to 0 after a complete transfer, but maintaining the toggle betwen transactions within a transfer. I did not realise that it was maintained between transfers also. I see that you actually made this point clearer in the third edition of USB complete, not to say that it said anything to the contrary in the Second.

I think that all the effort was not lost though (for me), as I have a MUCH better understanding of USB2 as a result.

Regards,

Ray.