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?