Trying to send an InReport > 64 bytes. Read all threads(thanks Tsuneo) but still not working. That is too say, I'm using SimpleHIDWrite as my tester, 64-byte packets work fine. If I run this code, sending a 65-byte In Report using 2-packets, I get from SimplHIDWrite "Get Report Error: CRC mismatch (17)". Any help much appreciated!
BOOL HID_GetReport (void) { // ReportID = SetupPacket.wValue.WB.L; switch (SetupPacket.wValue.WB.H) { case HID_REPORT_INPUT: //We've been asked to report, go get report and send 1st packet GetInReport(); //memcpy(&EP0Buf[0],(u8*)&MyInReport[0],sizeof(MyInReport)); //memcpy(&EP0Buf[0],(u8*)&MyInReport[0],64); break; case HID_REPORT_OUTPUT: return (FALSE); // Not Supported case HID_REPORT_FEATURE: /* EP0Buf[] = ...; */ /* break; */ return (FALSE); // Not Supported } return (TRUE); } ******************************************************************* void GetInReport (void) { // Check if PBINT is pressed if((IOPIN0 & PBINT) == 0) { //just add some data for now MyInReport[0] = 0xC1; MyInReport[1] = 0xD1; MyInReport[63] = 0x63; } else { //just add some data for now MyInReport[0] = 0xC0; MyInReport[1] = 0xD0; MyInReport[63] = 0x63; } VICIntEnClr |= 0x00400000; // Disable USB Interrupt USB_WriteEP(0x81, &MyInReport[0], 64); //Send 1st packet, 64 bytes iNextInPacket = 1; //Set flag for EP1 ISR VICIntEnable |= 0x00400000; // Enable USB Interrupt } *********************************************************************** void USB_EndPoint1 (DWORD event) { switch (event) { case USB_EVT_IN: if(iNextInPacket) { //OK, more data, send second packet (1-byte, total of 65-byte report) iNextInPacket = 0; USB_WriteEP(0x81, &MyInReport[64], 1); } break; } }
Where are the functions located? I've just been through the same loop, (and have it working with 64 bytes), but I am sure I only had to modify the top end user files, and use Tsuneo's simplified settings.
HID_GetReport = hiduser.c
GetInReport = demo.c
USB_EndPoint1 = usbuser.c
This is just the HID example from Keil, I'm attempting to modify it to allow for multi-byte InReports. However when I cross 64-bytes, I get strange-ness from SimpleHIDWrite program.
I have new information. When I transmit multi-packet reports using the Endpoint ISR method, it works! When I use SmpleHIDWrite program to 'request' a report I.E. GetReport, this is what fails. I'm beginning to believe there is a problem with the SimpleHIDWrite program not being able to send a GetReport request > 64 bytes?
I think its deeper than that, from what I understand USB only supports 64 byte packages. Maybe worth looking on USB.org.
You don't touch to your MCU type number, but Keil's USB stack is almost common for various MCUs, except for the low-level routines. Get_Report process is also common. I picked up LPC17xx USBHID code here.
The problem lies in Keil's HID implementation.
USBHID example expects that the input report is loaded in InReport[] in GetInReport(). The report is copied to EP0Buf[] at HID_GetReport(), as follows.
hiduser.c uint32_t HID_GetReport (void) { /* ReportID = SetupPacket.wValue.WB.L; */ switch (SetupPacket.wValue.WB.H) { case HID_REPORT_INPUT: GetInReport(); EP0Buf[0] = InReport; break;
In USB_EndPoint0(), The address of EP0Buf[] is registered to EP0Data.pData after HID_GetReport() call. And then, the stack code takes care of the rest, including multi-packets transfer.
usbcore.c void USB_EndPoint0 (uint32_t event) { switch (event) { case USB_EVT_SETUP: USB_SetupStage(); USB_DirCtrlEP(SetupPacket.bmRequestType.BM.Dir); EP0Data.Count = SetupPacket.wLength; /* Number of bytes to transfer */ switch (SetupPacket.bmRequestType.BM.Type) { ... ... #if USB_CLASS case REQUEST_CLASS: switch (SetupPacket.bmRequestType.BM.Recipient) { ... case REQUEST_TO_INTERFACE: #if USB_HID if (SetupPacket.wIndex.WB.L == USB_HID_IF_NUM) { /* IF number correct? */ switch (SetupPacket.bRequest) { case HID_REQUEST_GET_REPORT: if (HID_GetReport()) { EP0Data.pData = EP0Buf; // <----------- the problem is here USB_DataInStage(); /* send requested data */ goto setup_class_ok; } break;
However, the size of EP0Buf[] is 64 bytes, at most. LPC17xx example sets it to 8.
usbcfg.h #define USB_MAX_PACKET0 8 usbcore.c uint8_t EP0Buf[USB_MAX_PACKET0];
The implementation of Control Transfer process supports multi-packets transfer, successfully. But above HID implementation spoils it. You may improve it as follows.
hiduser.c uint32_t HID_GetReport (void) { /* ReportID = SetupPacket.wValue.WB.L; */ switch (SetupPacket.wValue.WB.H) { case HID_REPORT_INPUT: // // fill your_custom_buffer[] with a input report, here // EP0Data.pData = your_custom_buffer; // pass your buffer to the stack
And comment "EP0Data.pData = EP0Buf;" line on USB_EndPoint0()
usbcore.c void USB_EndPoint0 (uint32_t event) { ... case HID_REQUEST_GET_REPORT: if (HID_GetReport()) { // EP0Data.pData = EP0Buf; // comment this line USB_DataInStage(); /* send requested data */
Tsuneo
Thanks, controller is LPC2148. I understand your fix and attempted, still get error from SimpleHIDWrite of "GET REPORT ERROR: Data error (cyclic redundancy error) (17)". We never even get to the HID_GetReport() code. Must be that it errors when attempting to do a GetReport call of > 64 bytes? Anyway, couldn't your fix just be to increase the size of EP0Buf?