I am working on a STM32L496 and I try to get 2 HID devices running on one USB port / device.
The first one is a keyboard HID (USBD_Config_HID_0), the second one is a custom HID Interface (USBD_Config_HID_1).
I set both HID descriptors to 'User Provided HID Report Descriptor' with no report IDs.
I can send keyboard codes on the USBD_Config_HID_0 by using USBD_HID_GetReportTrigger(0, 0, buf, len).
But what do I have to use to send data via the custom HID interface (USBD_Config_HID_1) ?
'USBD_HID_GetReportTrigger(1, 0, buf, len)' or 'USBD_HID_GetReportTrigger(0, 1, buf, len)'?
As far as I understand is the first entry the USB instance, with is in both cases '0', because I only have 'USB_Config_0'.
And because I haven't set any report IDs the second value can't be 1?
I appreciate any help.
Stefan
P.S. I found this discussion '2-hids-in-one-composite-usb-code' but it doesn't lead to a conclusion.
Hi Stefan,
Your usage case has two HID instances (0 and 1) and they are both on the same Device.
So, you should use 'USBD_HID_GetReportTrigger(1, 0, buf, len)' to send data on the second HID instance.
Best regards, Milorad
Thanks, yes it worked!My fault was that I didn't increase 'Maximum Input Report Size', instead I skiped a line and increased 'Maximum Feature Report Size'!
In case I would like to handle both HID reports in one device and one instance, I would have to add report IDs.But I always had a problem designing the descriptor.
const uint8_t usbd_hid0_report_descriptor[] = { // KEYBOARD STRUCT 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) // modifier 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x81, 0x02, // INPUT (Data,Var,Abs) //reserved 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) // keycodes[6] 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0, // END_COLLECTION };
So this is my keyboard descriptor.Some consultant told me that if I want to have a second one it should be an array.
const uint8_t usbd_hid0_report_descriptor[] = // KEYBOARD STRUCT 1 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) // Length 6 0x85, 0x00, // REPORT_ID (0) // modifier 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x81, 0x02, // INPUT (Data,Var,Abs) //reserved 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) // keycodes[6] 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0, // END_COLLECTION // KEYBOARD STRUCT 2 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) // Length 6 0x85, 0x001, // REPORT_ID (1) // modifier 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x81, 0x02, // INPUT (Data,Var,Abs) //reserved 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) // keycodes[6] 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0, // END_COLLECTION };
So this would have been my solution, can you confirm, that this should work?
Thanks in advanceStefan
What will your second device do, what is a custom HID device?
The second device is just a buffer of 64 byte I use to transfer data between the device and the computer, current use it for config and debuging.
Hi Stefan.
You can configure your Report Descriptor however it suits you, I don't see any reason why a second one should be an array.But, if you use Windows PC as an USB Host you might have to provide a driver for your device because Windows by default probably handle only standard Keyboard and Mouse.For example multimedia keyboards all have custom drivers for Windows PCs.Here is an example of Report Descriptor for a Logitech keyboard:
Also, instead of hardcoded numbers you can use macros for the values in the Report Descriptor, like HID_UsagePage(x), HID_Collection(x), HID_UsageMin(x).
For reference you can take a look in USBD_User_HID_Mouse.c template.
What software generated that window Milorad?
That was taken with Total Phase Beagle USB 480 Protocol Analyzer and screenshot was taken form Total Phase's software called Total Phase Data Center.
Thank you. I actually have one of those but end up using the Ellisys all the time.
Hey guys, I have one of the Beagles too, but use it quiet rarely.But back to my last question. I think I didn't describe it properly.
I had problems by creating a compsite device, with one describtor including 2 diffrent devices. My question was aimed at how i designed the descritor.
I wrote two keyboard describtors with diffrent report IDs. The first one will be a keyboard and the second one will be either a self-defined one or a descriptor for a special device.
I had problems addressing the seperate parts of the describtor by its report IDs. It should be:'USBD_HID_GetReportTrigger(0, 1, buf, len)' for the first keyboard and 'USBD_HID_GetReportTrigger(0, 2, buf, len)' for the second.
I talked to a quy and he mentioned that I have to design the descriptor as a 2 dimensional array.Probably something like this:
const uint8_t usbd_hid0_report_descriptor[][] = { { // KEYBOARD STRUCT 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) 0x85, 0x01, // REPORT_ID (1) // modifier 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x81, 0x02, // INPUT (Data,Var,Abs) //reserved 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) // keycodes[6] 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0, // END_COLLECTION }, { // KEYBOARD STRUCT 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) 0x85, 0x02, // REPORT_ID (2) // modifier 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x81, 0x02, // INPUT (Data,Var,Abs) //reserved 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) // keycodes[6] 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0, // END_COLLECTION } };
But the most common format I saw in all documentation was:
const uint8_t usbd_hid0_report_descriptor[] = // KEYBOARD STRUCT 1 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) 0x85, 0x01, // REPORT_ID (1) // modifier 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x81, 0x02, // INPUT (Data,Var,Abs) //reserved 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) // keycodes[6] 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0, // END_COLLECTION // KEYBOARD STRUCT 2 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) 0x85, 0x02, // REPORT_ID (2) // modifier 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x81, 0x02, // INPUT (Data,Var,Abs) //reserved 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) // keycodes[6] 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0, // END_COLLECTION };
Milorad Cvjetkovic said:Also, instead of hardcoded numbers you can use macros for the values in the Report Descriptor, like HID_UsagePage(x), HID_Collection(x), HID_UsageMin(x).
I saw that in the examples, but I also try to create the same descriptor(s) for a bluetooth modul (Silabs BT121/122), so the hardcoded one is closer to the same starting point.
Has anyone ever come in to contact with one of the bluetooth modules?Kind regardsStefan
The const uint8_t usbd_hid0_report_descriptor should not be 2-dimensional array, because library expects a 1-dimensional array with the declaration of the descriptor being:
extern const uint8_t usbd_hid0_report_descriptor[];
I do not have any experience with bluetooth modules.