HID keyboard/mouse combo report ID
Posted: Mon Mar 27, 2017 1:53 pm
I am trying to create a device which acts as a keyboard and mouse at the same time. After some research I've concluded that it should be possible to combine both the mouse and keyboard HID descriptors, and separate them with Report IDs. I've successfully implemented the keyboard and mouse separately, but when I try to assign a report ID to the keyboard, no output is produced.
Here is the offending keyboard descriptor:
and the code I'm testing it with
The code simply sends the letter 'b' over and over. With the report ID lines commented out in the descriptor and the code, it works fine, but when not commented the device not produce any output, but is still recognized by Windows. I also tried adding a report ID to the mouse HID descriptor and it worked without problems.
Does anyone know why this might be happening?
Here is the offending keyboard descriptor:
Code: Select all
PROGMEM const char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {
//45 without report ID
//47 with report ID
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
//0x85, (uint8_t)ID_KEYBOARD, // REPORT_ID (2)
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)
0x95, 0x08, // REPORT_COUNT (8)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x01, // INPUT (Cnst,Ary,Abs)
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
}
and the code I'm testing it with
Code: Select all
typedef struct{
//uint8_t reportID;
uint8_t modifier;
uint8_t reserved;
uint8_t keycode[6];
}keyboard_report_t;
//static keyboard_report_t keyboardReportBuffer = {(uint8_t)ID_KEYBOARD, 0, 0, {0, 0, 0, 0, 0, 0}};
static keyboard_report_t keyboardReportBuffer = {0, 0, {0, 0, 0, 0, 0, 0}};
static uchar idleRate; /* repeat rate for keyboards, never used for mice */
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
/* The following requests are never used. But since they are required by
* the specification, we implement them in this example.
*/
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
switch(rq->bRequest) {
case USBRQ_HID_GET_REPORT: // send "no keys pressed" if asked here
usbMsgPtr = (usbMsgPtr_t)(void *)&keyboardReportBuffer; // we only have this one
keyboardReportBuffer.modifier = 0;
keyboardReportBuffer.keycode[0] = 0;
return sizeof(keyboardReportBuffer);
case USBRQ_HID_SET_REPORT: // if wLength == 1, should be LED state
return (rq->wLength.word == 1) ? USB_NO_MSG : 0;
case USBRQ_HID_GET_IDLE: // send idle rate to PC as required by spec
usbMsgPtr = (usbMsgPtr_t)&idleRate;
return 1;
case USBRQ_HID_SET_IDLE: // save idle rate as required by spec
idleRate = rq->wValue.bytes[1];
return 0;
}
}
return 0;
}
usbMsgLen_t usbFunctionWrite(uint8_t * data, uchar len) {
return 1; // Data read, not expecting more
}
int __attribute__((noreturn)) main(void)
{
usbInit();
usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */
_delay_ms(255);
usbDeviceConnect();
sei();
for(;;){ /* main event loop */
usbPoll();
if(usbInterruptIsReady()){
keyboardReportBuffer.keycode[0] = 5;
usbSetInterrupt((void *)&keyboardReportBuffer, sizeof(keyboardReportBuffer));
while(!usbInterruptIsReady())usbPoll();
keyboardReportBuffer.keycode[0] = 0;
usbSetInterrupt((void *)&keyboardReportBuffer, sizeof(keyboardReportBuffer));
}
}
}
The code simply sends the letter 'b' over and over. With the report ID lines commented out in the descriptor and the code, it works fine, but when not commented the device not produce any output, but is still recognized by Windows. I also tried adding a report ID to the mouse HID descriptor and it worked without problems.
Does anyone know why this might be happening?