I am developing an HID device using an LPC2141. For the descriptors I followed the instructions of the thread http://www.keil.com/forum/docs/thread11137.asp. Using USBSource I can see that enumeration works, that data is sent to the host and that data is received by my device. The LPC is able to recognize data and responses accordingly. I therefore strongly believe that my code for the LPC is correct.
The problem I have now is that I can not receive data on the host side. I am using the C# example from http://www.lvr.com/hidpage.htm which successfully sends data but always fails on receiving. Whenever I try to read from the device I get a "Readfile timeout" error. I am working on this bug now for days already but I really can't find a solution.
So does anyone have any hints regarding this issue? What about ReportIDs, I had problems with that when I tried to send data, do I have to watch out for that also when I try to receive data?
Below are my descriptors but I guess they are okay:
#define HID_INREPORT_SIZE 0x40 #define HID_OUTREPORT_SIZE 0x40 /* USB Standard Device Descriptor */ const BYTE USB_DeviceDescriptor[] = { USB_DEVICE_DESC_SIZE, /* bLength */ USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(0x0110), /* 1.10 */ /* bcdUSB */ 0x00, /* bDeviceClass */ 0x00, /* bDeviceSubClass */ 0x00, /* bDeviceProtocol */ USB_MAX_PACKET0, /* bMaxPacketSize0 */ WBVAL(0x1DA8), /* idVendor */ WBVAL(0x1301), /* idProduct */ WBVAL(0x0100), /* 1.00 */ /* bcdDevice */ 0x04, /* iManufacturer */ 0x12, /* iProduct */ 0x20, /* iSerialNumber */ 0x01 /* bNumConfigurations */ }; /* USB Configuration Descriptor */ /* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */ const BYTE USB_ConfigDescriptor[] = { /* Configuration 1 */ USB_CONFIGUARTION_DESC_SIZE, /* bLength */ USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL( /* wTotalLength */ USB_CONFIGUARTION_DESC_SIZE + USB_INTERFACE_DESC_SIZE + HID_DESC_SIZE + USB_ENDPOINT_DESC_SIZE + USB_ENDPOINT_DESC_SIZE ), 0x01, /* bNumInterfaces */ 0x01, /* bConfigurationValue */ 0x00, /* iConfiguration */ USB_CONFIG_BUS_POWERED /*|*/ /* bmAttributes */ /*USB_CONFIG_REMOTE_WAKEUP*/, USB_CONFIG_POWER_MA(500), /* bMaxPower */ /* 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 */ 0x5C, /* 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(1), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL( HID_INREPORT_SIZE ), /* wMaxPacketSize */ // = 64 byte 0x20, /* 32ms */ /* bInterval */ /* Endpoint, HID Interrupt Out */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_OUT(1), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL( HID_OUTREPORT_SIZE ), /* wMaxPacketSize */ // = 64 byte 0x20, /* 32ms */ /* bInterval */ /* Terminator */ 0 /* bLength */ };
For sending and receiving I am using circular buffers:
void USB_Configure_Event (void) { if (USB_Configuration) { /* Check if USB is configured */ usbtxbuf.data[0] = 0; usbtxbuf.data[1] = 255; USB_WriteEP(0x81, usbtxbuf.data, 2 ); } } void USB_EndPoint1 (DWORD event) { uint8 size; switch (event) { case USB_EVT_IN: if ( cbuf_hasMsgs( &usbtxqueue ) == ERR_CBUF_HASMSGS ) { // send message from queue if ( cbuf_get( &usbtxqueue, &usbtxbuf ) == ERR_NOERROR ) { USB_WriteEP(0x81, usbtxbuf.data, usbtxbuf.size ); } } else { // send bulk message usbtxbuf.size = 0; USB_WriteEP(0x81, usbtxbuf.data, usbtxbuf.size ); } break; case USB_EVT_OUT: size = USB_ReadEP( 0x01, rxbuf ); if ( size > 0 ) { cbuf_putdata( &usbrxqueue, MODULE_USB, rxbuf, size ); } break; } }
Finally I found the problem!
I am used to using write commands the way that I define the length of the data I wanna send. But with HID I guess this is different, so instead of using
USB_WriteEP(0x81, usbtxbuf.data, usbtxbuf.size );
I should have used
USB_WriteEP(0x81, usbtxbuf.data, INPUTREPORTSIZE );
So it is working now! :)
"But with HID I guess this is different"
You are right. The report format is defined in the report descriptor, ie. you have to send just the number of bytes defined in the report descriptor. Otherwise, the device driver on the PC drops your packet, because it is out of format.
When no report ID is used in your report descriptor, send just the contents of Output report. When any report ID is defined, place the report ID at the first byte, follows the contents of report.
If you want to send arbitrary number of bytes, you have to pad the report to the end.
Tsuneo