USB Combodevice (Keyboard & Joystick) - problems with report
Posted: Sat Sep 13, 2014 7:52 pm
Hi all,
this is more or less a followup question to my previous thread http://forums.obdev.at/viewtopic.php?f=8&t=9311.
How does a combo-device that registers itself as keyboard (REPORT_ID = 1) and joystick (REPORT_ID = 2) have to send the usb reports in order to be working properly?
A bit of background: My goal is to develop a custom control panel (for flight simulators and the like) that is recognized by the OS as keyboard and as joystick.
The hardware part for the "keyboard" consists of 32 hardware-debounced buttons read into the microcontroller (ATMega328p) through four shift registers (74HC165N). I have the C code for a USB-keyboard working.
The hardware part for the "joystick" consists of 6 analog axis (ADC0-ADC5 on the ATMega), plus four hardware-debounced buttons (PB0, PD7, PD6, PD5). I have the C code for a USB-joystick working as well.
Now, combining these two software parts (the hardware is a single circuit anyway) I do get a device that is recognized by Windows correctly and the keyboard part works correctly. However sending the joystick report (URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) yields an URB_FUNCTION_ABORT_PIPE from the OS to the device. Naturally, Windows fails to recognize the inputs from the joystick report.
Inside main() my report-sending routine looks like this:
My USB sniffer tells me that the joystick report (REPORT_ID=2) is indeed send correctly but as said above, Windows doesn't recognize it properly.
I tried to always send both reports when any one of them required sending like this:
But doing so yields an incorrectly recognized device in Windows (yellow exclamation mark).
Any ideas? Thanks a ton
this is more or less a followup question to my previous thread http://forums.obdev.at/viewtopic.php?f=8&t=9311.
How does a combo-device that registers itself as keyboard (REPORT_ID = 1) and joystick (REPORT_ID = 2) have to send the usb reports in order to be working properly?
A bit of background: My goal is to develop a custom control panel (for flight simulators and the like) that is recognized by the OS as keyboard and as joystick.
The hardware part for the "keyboard" consists of 32 hardware-debounced buttons read into the microcontroller (ATMega328p) through four shift registers (74HC165N). I have the C code for a USB-keyboard working.
The hardware part for the "joystick" consists of 6 analog axis (ADC0-ADC5 on the ATMega), plus four hardware-debounced buttons (PB0, PD7, PD6, PD5). I have the C code for a USB-joystick working as well.
Now, combining these two software parts (the hardware is a single circuit anyway) I do get a device that is recognized by Windows correctly and the keyboard part works correctly. However sending the joystick report (URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) yields an URB_FUNCTION_ABORT_PIPE from the OS to the device. Naturally, Windows fails to recognize the inputs from the joystick report.
Inside main() my report-sending routine looks like this:
Code: Select all
while (1) {
wdt_reset(); // keep the watchdog happy
usbPoll();
keyboardUpdateNeeded |= readKeys(); // keyboard key presses
joystickUpdateNeeded |= readButtons(); // joystick buttons
// joystick analogue axis are being updated via ISR(ADC_vect) below
if (keyboardUpdateNeeded && usbInterruptIsReady()) {
usbSetInterrupt((void *) &keyboardReport, 8);
while ( !usbInterruptIsReady() ) {usbPoll();}
usbSetInterrupt((void *) &keyboardReport + 8, sizeof(keyboardReport) - 8);
keyboardUpdateNeeded = 0;
}
if (joystickUpdateNeeded && usbInterruptIsReady()) {
usbSetInterrupt((void *) &joystickReport, sizeof(joystickReport));
joystickUpdateNeeded = 0;
}
}
My USB sniffer tells me that the joystick report (REPORT_ID=2) is indeed send correctly but as said above, Windows doesn't recognize it properly.
I tried to always send both reports when any one of them required sending like this:
Code: Select all
while (1) {
wdt_reset(); // keep the watchdog happy
usbPoll();
keyboardUpdateNeeded |= readKeys(); // keyboard key presses
joystickUpdateNeeded |= readButtons(); // joystick buttons
// joystick analogue axis are being updated via ISR(ADC_vect) below
if ((keyboardUpdateNeeded || joystickUpdateNeeded) && usbInterruptIsReady()) {
usbSetInterrupt((void *) &keyboardReport, 8);
while ( !usbInterruptIsReady() ) {usbPoll();}
usbSetInterrupt((void *) &keyboardReport + 8, sizeof(keyboardReport) - 8);
keyboardUpdateNeeded = 0;
while ( !usbInterruptIsReady() ) {usbPoll();}
usbSetInterrupt((void *) &joystickReport, sizeof(joystickReport));
joystickUpdateNeeded = 0;
}
}
But doing so yields an incorrectly recognized device in Windows (yellow exclamation mark).
Any ideas? Thanks a ton