We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi everyone!
I've read lots of threads on this forum (with lot of Tsuneo Chinzei's really interesting posts) about this issue, but I'm still stuck with a problem. I'm using an NXP LPC1788. I've tested the USBHID demo with HIDClient.exe on the PC side. Everything works fine. I've wrote a simple C++ console program that made a single write/read operation, based on HIDClient.exe code, and everything is fine again. Now, I need to send/receive 8 bytes instead of a single one. I've started modifying firmware and sofware, following hints on this forum, and at the end I'm able to output 8 bytes, but not to get 8 byte in input.
I've changed the HID_ReportDescriptor structure like this:
const uint8_t HID_ReportDescriptor[] = { HID_UsagePageVendor(0x00), HID_Usage(0x01), HID_Collection(HID_Application), HID_UsagePage(HID_USAGE_PAGE_DEV_CONTROLS), HID_LogicalMin(0), HID_LogicalMax(255), HID_ReportCount(8), HID_ReportSize(8), HID_Usage(1), HID_Input(HID_Data | HID_Variable | HID_Absolute), HID_UsagePage(HID_USAGE_PAGE_DEV_CONTROLS), HID_Usage(1), HID_LogicalMin(0), HID_LogicalMax(255), HID_ReportCount(8), HID_ReportSize(8), HID_Output(HID_Data | HID_Variable | HID_Absolute), HID_EndCollection, };
I've redefined the InReport and OutReport variables as arrays of size 8, that will be copied/pasted on the EP0Buf array using a for loop (in single byte mode it's a simple assignation). I didn't change the wMaxPacketSize in the USB_ConfigDescriptor (so it's set to 4), because changing the value causes error in the output process, too.
Here is the source of the C++ console application that perform a single write/read:
#define MSG_SIZE 9 #include <windows.h> #include <stdio.h> #include "HID.h" int main() { BYTE outReport[MSG_SIZE]; BYTE inReport[IN_MSG_SIZE]; DWORD cnt; int totDevices; char buf[256]; outReport[0] = 0; inReport [0] = 0; // Check for all connected devices HID_Init(); totDevices = HID_FindDevices(); printf("%d Devices found\n", totDevices); if(totDevices < 1) { return 1; } for(int i = 0; i < totDevices; i++) { if (!HID_GetName(i, buf, sizeof(buf))) { sprintf(buf, "Device %d", i); } printf("%d: %s\n", i, buf); } // Open the first device printf("Open device 0..."); if(!HID_Open(0)) { printf("Can't open device 0\n"); return 2; } printf("OK\n"); // Perform a write test printf("Write test..."); outReport[1] = 0; if(!HID_Write(outReport, MSG_SIZE*sizeof(BYTE), &cnt)) { printf("write error\n"); return 3; } printf("OK\n"); // Perform a read test printf("Read test..."); if(!HID_Read(inReport, IN_MSG_SIZE*sizeof(BYTE), &cnt)) { printf("read error\n"); return 4; } printf("OK\n"); // Close device printf("Close device..."); HID_Close(); HID_UnInit(); printf("OK"); return 0; }
Write process goes well. The software get locked during the read process.
I've tested the firmware with the SimpleHIDWrite.exe tool and it works fine. So it seems more a software problem than a firmware one.
What could be worng? Is there someone that was able to tx/rx more that a single byte using a C++ interface? And is it correct to use arrays of size FIRMWARE_SIZE+1 on the software side? (HIDClient.exe uses arrays of size 2 to tx/rx a single byte. If I define arrays of size 8, write and read process fails, but didn't lock)
Thank to everyone! Massimo
Well... quite a fast updtate here.
I've read another thread that talks about wMaxPacketSize feature. I tried to modify it again. With wMaxPacketSize=0x04 (default) the read process still doeasn't work (output process works well) With wMaxPacketSize=0x08 the read process works (...hell! I was sure I've tried it!)
Furthermore, when I told you that the read process works with SimpleHIDWrite.exe I mean that I read the correct value when I click "Get Report" button. Now, I've noticed that with wMaxPacketSize=0x10, when I connect my device in SimpleHIDWrite.exe, a stream of (correct) Get Report will be promt, that's correct due to the USB_EndPoint1 event callback in the firmware.
Well, everything seems to work fine.
Just not to waste this post, I'll ask again: why do I need to send/receive data bigger than the size declared in the dirmware (FIRMWARE_SIZE+1)?
Thanks Massimo
Here we are again.
Since I'm using a request/answer protocol, I don't need to poll on InReport. So, as a first try, I commented the code inside USB_EndPoint1 event callback, so the firmware just answer to my read request inside HID_SetReport function. This happens when using SimpleHIDWrite, but the function won't be called by my sw. Again, I'm locked when trying to read InReport.
I've seen that SimpleHIDWrite calls USB_EndPoint0 (inside usbcore.c) several times for a single "Get Report" request, and finally goes to HID_GetReport (that sen InReport to PC). When I call HID_Read with my sw I just call USB_EndPoint0 once, and I never get to HID_GetReport function.
Did I miss something? Do I need a different flow when I request data?
Well, I managed to have a request-answer from the HID device by updating InReport and then calling USB_WriteEP(HID_EP_IN, &InReport[0], sizeof(InReport)) in the same function that process the ingoing OutReport message. It works, but is it the best and "cleaner" way to do this? Is it better to create a different endpoint or similar?
Thanks!