It uses 1byte for modifiers and 15bytes(120bits) for keys now.tags/v1.9
USB NKRO MEMO | USB NKRO MEMO | ||||
============= | ============= | ||||
2010/12/07 | |||||
2010/12/09 | |||||
References | References | ||||
http://geekhack.org/showthread.php?t=13162 | http://geekhack.org/showthread.php?t=13162 | ||||
NKey Rollover - Overview, Testing Methodology, and Results | NKey Rollover - Overview, Testing Methodology, and Results | ||||
http://geekhack.org/showwiki.php?title=NKey+Rollover+-+Overview+Testing+Methodology+and+Results | http://geekhack.org/showwiki.php?title=NKey+Rollover+-+Overview+Testing+Methodology+and+Results | ||||
dfj's NKRO(2010/06) | |||||
http://geekhack.org/showpost.php?p=191195&postcount=251 | |||||
http://geekhack.org/showthread.php?p=204389#post204389 | |||||
Terminogy | Terminogy | ||||
OS Support Status | OS Support Status | ||||
----------------- | ----------------- | ||||
NKRO is possible at least relatively new OS. | |||||
Following OS supports both Extended and Bitmarp report. | |||||
USB NKRO is possible *without* a custom driver. | |||||
At least following OSes supports. | |||||
Windows7 64bit | Windows7 64bit | ||||
WindowsXP | |||||
Windows2000 SP4 | Windows2000 SP4 | ||||
Ubuntu 10.4(Linux 2.6) | |||||
Ubuntu10.4(Linux 2.6) | |||||
MacOSX(To be tested) | |||||
Custom Driver for USB NKRO | |||||
-------------------------- | |||||
NOT NEEDED | |||||
at least when using fllowing report formats on Windows, Linux or MacOSX. | |||||
USB NKRO methods | USB NKRO methods | ||||
---------------- | ---------------- | ||||
1. Virtual keyboards | 1. Virtual keyboards | ||||
Keyboard can increase its KRO by using virtual keyboards with Standard or Extended report. | Keyboard can increase its KRO by using virtual keyboards with Standard or Extended report. | ||||
If the keyboard has 2 virtul keyboard with Standard report(6KRO), it gets 12KRO. | |||||
If the keyboard has 2 virtual keyboard with Standard report(6KRO), it gets 12KRO. | |||||
Using this method means the keyboard is a composite device. | Using this method means the keyboard is a composite device. | ||||
2. Exteded report | 2. Exteded report | ||||
Bitmap report can send at most 128keys by 16bytes and 256keys by 32bytes. | Bitmap report can send at most 128keys by 16bytes and 256keys by 32bytes. | ||||
Bitmap report can achieve USB NKRO efficiently in terms of report size. | Bitmap report can achieve USB NKRO efficiently in terms of report size. | ||||
Bitmap report needs a deliberation for boot protocol implementation. | Bitmap report needs a deliberation for boot protocol implementation. | ||||
Compatibility Problem | |||||
--------------------- | |||||
Some BIOS doesn't send SET_PROTCOL request, a keyboard can't switch to boot protocol mode. | |||||
This may cuase a problem on a keyboard which uses other report than Standard. | |||||
Bitmap report descriptor sample: | |||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x06, // Usage (Keyboard), | |||||
0xA1, 0x01, // Collection (Application), | |||||
// bitmap of modifiers | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xE0, // Usage Minimum (224), | |||||
0x29, 0xE7, // Usage Maximum (231), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte | |||||
// LED output report | |||||
0x95, 0x05, // Report Count (5), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x05, 0x08, // Usage Page (LEDs), | |||||
0x19, 0x01, // Usage Minimum (1), | |||||
0x29, 0x05, // Usage Maximum (5), | |||||
0x91, 0x02, // Output (Data, Variable, Absolute), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x75, 0x03, // Report Size (3), | |||||
0x91, 0x03, // Output (Constant), | |||||
// bitmap of keys | |||||
0x95, (REPORT_BYTES-1)*8, // Report Count (), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum(1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x00, // Usage Minimum (0), | |||||
0x29, (REPORT_BYTES-1)*8-1, // Usage Maximum (), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), | |||||
0xc0 // End Collection | |||||
where REPORT_BYTES is a report size in bytes. | |||||
Considerations | |||||
-------------- | |||||
Compatibility | |||||
boot protocol | |||||
minor/old system | |||||
Some BIOS doesn't send SET_PROTCOL request, a keyboard can't switch to boot protocol mode. | |||||
This may cuase a problem on a keyboard which uses other report than Standard. | |||||
Reactivity | |||||
USB polling time | |||||
OS/Driver processing time | |||||
Windows Problem | Windows Problem | ||||
--------------- | --------------- | ||||
1. Windows accepts only 6keys in case of Standard report. | 1. Windows accepts only 6keys in case of Standard report. | ||||
It should be able to send 6keys plus 8modifiers. | It should be able to send 6keys plus 8modifiers. | ||||
2. Windows accepts only 10keys in case of 16bytes Extended report. | 2. Windows accepts only 10keys in case of 16bytes Extended report. | ||||
It should be able to send 14keys plus 8modifiers. | It should be able to send 14keys plus 8modifiers. | ||||
3. Windows accepts only 18keys in case of 32bytes Extended report. | 3. Windows accepts only 18keys in case of 32bytes Extended report. | ||||
It should be able to send 30keys plus 8modifiers. | It should be able to send 30keys plus 8modifiers. | ||||
If keys are pressed in excess of the number, wrong keys are registered on Windows. | If keys are pressed in excess of the number, wrong keys are registered on Windows. | ||||
This problem will be reportedly fixed soon.(2010/12/05) | This problem will be reportedly fixed soon.(2010/12/05) | ||||
http://forums.anandtech.com/showpost.php?p=30873364&postcount=17 | http://forums.anandtech.com/showpost.php?p=30873364&postcount=17 | ||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3 | 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3 | ||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4 | 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4 | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD2_SIZE) | KBD2_BUFFER, // 5 | |||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD2_SIZE) | KBD2_BUFFER, // 5 | |||||
#else | #else | ||||
0, // 5 | 0, // 5 | ||||
#endif | #endif | ||||
}; | }; | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
static uint8_t PROGMEM keyboard2_hid_report_desc[] = { | static uint8_t PROGMEM keyboard2_hid_report_desc[] = { | ||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x06, // Usage (Keyboard), | |||||
0xA1, 0x01, // Collection (Application), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xE0, // Usage Minimum (224), | |||||
0x29, 0xE7, // Usage Maximum (231), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte | |||||
0x95, 0x01, // Report Count (1), | |||||
0x75, 0x08, // Report Size (8), | |||||
0x81, 0x03, // Input (Constant), ;Reserved byte | |||||
0x95, 0x05, // Report Count (5), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x05, 0x08, // Usage Page (LEDs), | |||||
0x19, 0x01, // Usage Minimum (1), | |||||
0x29, 0x05, // Usage Maximum (5), | |||||
0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report | |||||
0x95, 0x01, // Report Count (1), | |||||
0x75, 0x03, // Report Size (3), | |||||
0x91, 0x03, // Output (Constant), ;LED report padding | |||||
0x95, KBD2_REPORT_KEYS*8, // Report Count (), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum(1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x00, // Usage Minimum (0), | |||||
0x29, KBD2_REPORT_KEYS*8-1, // Usage Maximum (), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), | |||||
0xc0 // End Collection | |||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x06, // Usage (Keyboard), | |||||
0xA1, 0x01, // Collection (Application), | |||||
// bitmap of modifiers | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xE0, // Usage Minimum (224), | |||||
0x29, 0xE7, // Usage Maximum (231), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte | |||||
// LED output report | |||||
0x95, 0x05, // Report Count (5), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x05, 0x08, // Usage Page (LEDs), | |||||
0x19, 0x01, // Usage Minimum (1), | |||||
0x29, 0x05, // Usage Maximum (5), | |||||
0x91, 0x02, // Output (Data, Variable, Absolute), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x75, 0x03, // Report Size (3), | |||||
0x91, 0x03, // Output (Constant), | |||||
// bitmap of keys | |||||
0x95, KBD2_REPORT_KEYS*8, // Report Count (), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum(1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x00, // Usage Minimum (0), | |||||
0x29, KBD2_REPORT_KEYS*8-1, // Usage Maximum (), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), | |||||
0xc0 // End Collection | |||||
}; | }; | ||||
#endif | #endif | ||||
UENUM = endpoint; | UENUM = endpoint; | ||||
} | } | ||||
UEDATX = report->mods; | UEDATX = report->mods; | ||||
UEDATX = 0; | |||||
if (!usb_keyboard_nkro) | |||||
UEDATX = 0; | |||||
for (uint8_t i = keys_start; i < keys_end; i++) { | for (uint8_t i = keys_start; i < keys_end; i++) { | ||||
UEDATX = report->keys[i]; | UEDATX = report->keys[i]; | ||||
} | } |
#define KBD2_ENDPOINT 5 | #define KBD2_ENDPOINT 5 | ||||
#define KBD2_SIZE 16 | #define KBD2_SIZE 16 | ||||
#define KBD2_BUFFER EP_DOUBLE_BUFFER | #define KBD2_BUFFER EP_DOUBLE_BUFFER | ||||
#define KBD2_REPORT_KEYS (KBD2_SIZE - 2) | |||||
#define KBD2_REPORT_KEYS (KBD2_SIZE - 1) | |||||
#endif | #endif | ||||
#if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS | #if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS |