Hello experts!
I'm trying to modify our existing HID descriptor and message handling that is based on one of Keil's examples, in such a way that our LPC2478-based hardware would use an OUT interrupt endpoint for receiving data from the PC.
What I currently have is a composite device that consists of an HID (on Interface 0) and MSC (on Interface 1). This setup was working already, and both HID and MSC were OK.
Now, I want to change the HID in such a way that the OUT data is sent to an OUT endpoint that I have set up just for the HID, and not via endpoint 0.
This is the relevant part from the USB_ConfigDescriptor:
/* Interface 0, Alternate Setting 0, HID Class */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x00, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ 0x02, /* bNumEndpoints */ USB_DEVICE_CLASS_HUMAN_INTERFACE, /* bInterfaceClass */ HID_SUBCLASS_NONE, /* bInterfaceSubClass */ HID_PROTOCOL_NONE, /* bInterfaceProtocol */ USB_STR_INTERFACE_OFFSET, /* iInterface */ /* HID Class Descriptor */ /* HID_DESC_OFFSET = 0x0012 */ HID_DESC_SIZE, /* bLength */ HID_HID_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(0x0100), /* 1.00 */ /* bcdHID */ 0x00, /* bCountryCode */ 0x01, /* bNumDescriptors */ HID_REPORT_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(HID_REPORT_DESC_SIZE), /* wDescriptorLength */ /* Endpoint, HID Interrupt In */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_IN(7), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL(64), /* wMaxPacketSize */ 1, /* bInterval */ /* Endpoint, HID Interrupt Out */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_OUT(7), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL(64), /* wMaxPacketSize */ 1, /* bInterval */
I have a native testing program (that measures the transfer speed) that writes data to my device via WriteFile(...). The testing app seems to work, because when I remove the OUT endpoint from the descriptor, Windows uses the fallback via endpoint 0 feature reports, and the program works without problems.
This is what I see in USBlyzer when I use the additional OUT enpoint, as from the descriptor above:
URB 8798 0:00:01.109 Bulk or Interrupt Transfer Output Report len:64 19 00 00 00 00 00 00 00... out 01:00:07 8A1FA5E0h 000000c8 usbccgp 8A155A58h URB 8799-8785 0:00:01.109 Bulk or Interrupt Transfer Input Report len:64 02 2C 00 00 00 00 00 00... in 01:00:87 8A9D4DE8h USBPDO-9 usbhub 8A1FF008h Success (Success) URB 8800-8784 0:00:01.109 Bulk or Interrupt Transfer Input Report len:64 02 2C 00 00 00 00 00 00... in 01:00:87 8A1FA5E0h 000000c8 usbccgp 8A1FF008h Success (Success) URB 8801 0:00:01.109 Bulk or Interrupt Transfer Output Report len:64 19 00 00 00 00 00 00 00... out 01:00:07 8A9D4DE8h USBPDO-9 usbhub 8A155A58h URB 8802 0:00:01.109 Bulk or Interrupt Transfer 64 bytes buffer in 01:00:87 8A1FA5E0h 000000c8 usbccgp 8A1FF008h URB 8803 0:00:01.109 Bulk or Interrupt Transfer 64 bytes buffer in 01:00:87 8A9D4DE8h USBPDO-9 usbhub 8A1FF008h URB 8804-8793 0:00:01.109 Bulk or Interrupt Transfer Input Report len:64 02 2E 00 00 00 00 00 00... in 01:00:87 8A9D4DE8h USBPDO-9 usbhub 8A222008h Success (Success) URB 8805-8792 0:00:01.109 Bulk or Interrupt Transfer Input Report len:64 02 2E 00 00 00 00 00 00... in 01:00:87 8A1FA5E0h 000000c8 usbccgp 8A222008h Success (Success) URB 8806 0:00:01.109 Bulk or Interrupt Transfer 64 bytes buffer in 01:00:87 8A1FA5E0h 000000c8 usbccgp 8A222008h URB 8807 0:00:01.109 Bulk or Interrupt Transfer 64 bytes buffer in 01:00:87 8A9D4DE8h USBPDO-9 usbhub 8A222008h ... 6 more input reports like in the 4 lines above this line ... URB 8828-8801 0:00:01.109 Bulk or Interrupt Transfer 64 bytes buffer out 01:00:07 8A9D4DE8h USBPDO-9 usbhub 8A155A58h Success (Success) URB 8829-8798 0:00:01.109 Bulk or Interrupt Transfer 64 bytes buffer out 01:00:07 8A1FA5E0h 000000c8 usbccgp 8A155A58h Success (Success)
The output report that sends "19 00 00 00 00 00 00 00..." is what I'm interested in, what my testing app sends. To me it looks like my device behaves correctly because of the two "Success" messages at the end.
The problem is that the call to WriteFile(...) never returns and the program hangs terribly (sometimes I have to restart the Win XP that I'm testing on).
The reason why I want to use the OUT endpoint of the HID is that I plan to add a few more HIDs to my composite device, and then hopefully to get a bigger overall transfer rate to the device. (The introduction of the Mass Storage Class was made for the same reason, but then we found out that some customers cannot use it).
I'm really looking forward to any tips, because I've already sunk quite a few days into making this work.
Best regards, Florian
I have an impression that the problem lies in the PC application side. Check the parameters passed to the WriteFile() Is the buffer established well (dangling pointer) ? When the PC application runs on debugger, does the debugger catch any exception?
At least, the sniffer trace tells that the WriteFile call succeeds on the PC device driver / device side.
> The testing app seems to work, because when I remove the OUT endpoint from the descriptor, Windows uses the fallback via endpoint 0 feature reports, and the program works without problems.
The problem may be hidden when the default endpoint is applied. I believe the sniffer trace is more reliable than above estimation.
Tsuneo
Hello Tsuneo,
Thanks for replying so fast! I had hoped you would answer my question, after seeing how many other people you helped around here.
My previous testing program was written in Delphi, using the TJvHidDevice library. To make sure the problem is not caused by a bug of that HID lib, I now donwloaded another one, written in C#, from
"-message) but afterwards it hangs. Again I sometimes had to kill the virtual machine, because I couldn't kill the app.
How could we fix the problem? Is there some "known good" HID implementation for the NXP devices that uses an OUT endpoint? Would you check the relevant code snippets of my current implementation if I post them here? Any other ideas?
Hello again,
I tried finding the problem, and found out that the problem does not lie in the testing program. I used the C# program that I mentioned in the last post and sent lots of reports to a different HID, no problems. (I used the Keil ULink2 adapter for this purpose, as I found out that it also uses an OUT interrupt endpoint).
Next, I listed the Interface descriptor, HID descriptor, and Endpoint Descriptors of the Keil device, and made sure that my device reported the same.
I just found out that the call to USB_ReadEP doesn't return. (Handler code follows, orange LED is on, but the green one not)
void USB_EndPoint1 (U32 event) { switch (event) { case USB_EVT_IN: GetInReport(); USB_WriteEP(HID_EP1_IN, InReport, HID_IN_REPORT_LENGTH); break; case USB_EVT_OUT: LED_ORANGE_ON; USB_ReadEP(1, EP0Data.pData); LED_GREEN_ON; break; } }
What could be the problem?
The error was found: I forgot to initialize EP0Data.pData
Hello experts,
after the fix mentioned in the previous message, I got my device to accept data sent to it via an OUT interrupt endpoint (via WriteFile).
Now I want to get a speed increase by using two OUT interrupt endpoints. I made a composite device that contains a second HID, with different IN/OUT endpoints. The composite device enumerates correctly.
The problem is now that - once again - I cannot send OUT interrupt packets to the device any more. I tried sending data to the endpoint of the first HID (that previously was the only HID), and even though the code for handling its endpoints wasn't changed, I had the old symptoms again: The testing app would crash so badly that I had to power off my VM.
Do you have any idea what could be wrong?
Could it be that the HID_ReportDescriptor has to be changed or that it has to be different for each HID? Are there any other requirements? Should this work with HID version 1.10?
Please help me, best regards,
Florian
> The error was found: I forgot to initialize EP0Data.pData
Congratulation.
Umm.. I can't understand what is going on your firmware. EP0Data.pData is dedicated to the control request handling on the stack. For interrupt IN/OUT endpoint, separated buffers are assigned. I don't see any relation with the clues you shown ...
thanks for your help.
We are now also considering accessing our devices via different USB device classes.
The requirement is that we want to transfer data TO the device as fast as possible and that our software on Windows should require NO installation and NO admin priviledges (e.g. it should be runnable from a USB stick).
I've seen your example code for a CDC project over at: www.cygnal.org/.../000945.html .
How is it about CDC, would it be possible to fulfill the above requirements? Are you aware of another demo app that works on NXP's LPCXXXX devices?
Best regards, and thanks again! Florian
> How is it about CDC, would it be possible to fulfill the above requirements?
CDC requires installation of INF file for Windows.
Windows have in-box class drivers AND default INF files for these classes - Audio - Bluetooth (Vista and later) - CCID (over "internet" install from Windows Update server) - HID - Hub - IrDA bridge (Vista and later) - Mass Storage - Printer - PTP (Still Image) - RNDIS (Vista and later) - Video
> The requirement is that we want to transfer data TO the device as fast as possible
Roughly speaking, how fast does it? 10 ms, 1 ms or less?
Thanks for the fast reply.
The latency is not an issue, even 100ms would be OK. What matters to us is to transfer a data block of around 100KB..500KB as fast as possible. So, we are more interested in high bandwidth than in low latency.
Hello Tsuneo and other experts,
we have now decided that we want to use multiple HID endpoints, and I finally got it to work.
I'm using 5 HIDs with Interrupt OUT endpoints, configured with a bInterval of 1ms to send data to our device.
When I measured the bandwidth, I got around 320KB/s on Win 7, but only 160KB/s on Win XP. It seems that Win XP ignores the bInterval of 1ms of the device and instead "rounds up" to 2ms. I think it is not a limitation of the USB physical hardware because I get the speed limit at around 160KB/s even when running inside a VM on the Win 7 instance that gets the full speed.
Do you have any tips for increasing the bandwidth on Windows XP?
Looking forward to your replies,