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
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!