Hello all.
The next step in my C64 USB keyboard implementation is trying to make a composite device that handles both the keyboard and two digital joysticks. I have made each of these work individually, that is two joysticks on one uController and the keyboard on a different one.
I tried to create a combined report (still only 8 bytes) containing both the keyboard and one joystick (the joystick report is only one byte), but aparently Windows cannot decide whether to use the keyboard or joystick driver for this device, so it ends up saying device installation failed, and nothing works.
I was thinking that I could make two different reports: one for the keyboard and one for the two joysticks. Is there any reason why this should not work?
For this, I guess I need to have a report ID in the reports. This should be no problem, except that the keyboard report can then not conform to the boot specification. Does anyone know if there would be a problem implementing a boot device (keyboard) that does not use the boot protocol when running in normal report mode, but does when the boot protocol is used? I assume this is the reason why there are SET_PROTOCOL and GET_PROTOCOL functions (which I have currently implemented, but which do nothing).
How do I make the composite device with two different reports. Does the setup request ask for which report to return, or is that something my application has to decide (e.g. switching between the two)?
Making a composite device.
Hi !
Making a device supporting different kinds (length) of reports, the easiest way is to use ReportIDs.
The report structure canges a little bit (Device Class Definition for HID V1.11, 5.6 Reports, page 17).
You must add the Report_ID statement in your HID Descriptor. My example shows a descriptor for a keyboard with embedded mouse.
You need 2 reportBuffers, the element with index 0 contains the ID
and 2 routines sending the buffers
I hope this helps.
It is very easy to add more devices (joysticks....), each device simply needs an unique Report_ID. Report_ID 0 is reserved, do not use.
Have fun!
Regards,
STB
Making a device supporting different kinds (length) of reports, the easiest way is to use ReportIDs.
The report structure canges a little bit (Device Class Definition for HID V1.11, 5.6 Reports, page 17).
You must add the Report_ID statement in your HID Descriptor. My example shows a descriptor for a keyboard with embedded mouse.
Code: Select all
char usbHidReportDescriptor[83] = { //83
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x85, MouseID, // REPORT_ID (77)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x08, // USAGE_MAXIMUM (Button 8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, KeyboardID, // REPORT_ID (75)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xE0, // USAGE_MINIMUM (Left Ctrl)
0x29, 0xE7, // USAGE_MAXIMUM (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)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x19, 0x00, // USAGE_MINIMUM (Reserved, No Event)
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Var,Abs)
0xc0 // END_COLLECTION
};
You need 2 reportBuffers, the element with index 0 contains the ID
Code: Select all
reportBufferMouse[3] = {MouseID, 0, 0};
reportBufferKBD[3] = {KeyboardID, 0, 0};
and 2 routines sending the buffers
Code: Select all
if(usbInterruptIsReady() && ((TB_pos_x != oldTB_pos_x) || (TB_pos_y != oldTB_pos_y)))
{ /* we can send another relative coordinate */
buildReportTrackball();
usbSetInterrupt(reportBufferMouse, sizeof(reportBufferMouse));
}
if(usbInterruptIsReady() && (key_state != old_key_state))
{ /* we can send another Keysequence */
buildReportKBD();
usbSetInterrupt(reportBufferKBD, sizeof(reportBufferKBD));
}
I hope this helps.
It is very easy to add more devices (joysticks....), each device simply needs an unique Report_ID. Report_ID 0 is reserved, do not use.
Have fun!
Regards,
STB
-
- Posts: 4
- Joined: Tue Apr 29, 2008 9:53 pm
- Location: Germany
- Contact:
Hello there.
I'd try to do it so, how you show above.
But I'd used a keyboard and Custom device Reports. It was not recognised as right Report Descriptor
Here it is:
It's shows as HID device, but with exclamation sight on it in Device Manager.
What did I wrong?
Thanks in advance.
Alexei
I'd try to do it so, how you show above.
But I'd used a keyboard and Custom device Reports. It was not recognised as right Report Descriptor
Here it is:
Code: Select all
char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_0, // REPORT_ID (0)
// 8
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
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)
0x81, 0x02, // INPUT (Data,Var,Abs)
// 16
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
// 12
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
// 6
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x81, 0x00, // INPUT (Data,Ary,Abs)
// 17
0xc0, // END_COLLECTION
// 1
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_1, // REPORT ID (1)
0x09, 0xe9, // USAGE (Volume Up)
0x09, 0xea, // USAGE (Volume Down)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x15, 0x01, // LOGICAL_MINIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0xe2, // USAGE (Mute)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x06, // INPUT (Data,Var,Rel)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x05, // REPORT_COUNT (5)
0x81, 0x07, // INPUT (Cnst,Var,Rel)
// 40
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x03, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
// 6
0xc0 // END_COLLECTION
// 1
};
It's shows as HID device, but with exclamation sight on it in Device Manager.
What did I wrong?
Thanks in advance.
Alexei
-
- Posts: 4
- Joined: Tue Apr 29, 2008 9:53 pm
- Location: Germany
- Contact:
Code: Select all
PROGMEM char usbHidReportDescriptor[70] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x4b, // REPORT_ID (75)
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)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x4c, // REPORT_ID (76)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x09, 0xe9, // USAGE (Volume Up)
0x09, 0xea, // USAGE (Volume Down)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0xe2, // USAGE (Mute)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x06, // INPUT (Data,Var,Rel)
0x95, 0x05, // REPORT_COUNT (5)
0x81, 0x01, // INPUT (Cnst,Ary,Abs)
0xc0 // END_COLLECTION
};
This descriptor for a composit device works fine maybe you can use it as a startpoint.
-
- Posts: 4
- Joined: Tue Apr 29, 2008 9:53 pm
- Location: Germany
- Contact: