# HG changeset patch # User Jacob Alexander # Date 1415862290 28800 # Node ID d3ac199593d654d2784eccbe879191d01f4189c2 # Parent afe96322d0c5f1dd97deafc3de8ab70453f86994 Fixing NKRO on Windows 8.1 - Had to re-write descriptor to support Windows 8.1 while still working with Mac OSX - NKRO keyboard is now more bandwidth intensive as all the keys must be updated at the same time (due to 8.1 bug in the HID spec) diff -r afe96322d0c5 -r d3ac199593d6 Output/pjrcUSB/arm/usb_desc.c --- a/Output/pjrcUSB/arm/usb_desc.c Mon Nov 10 23:42:39 2014 -0800 +++ b/Output/pjrcUSB/arm/usb_desc.c Wed Nov 12 23:04:50 2014 -0800 @@ -153,20 +153,9 @@ 0x09, 0x06, // Usage (Keyboard), 0xA1, 0x01, // Collection (Application) - Keyboard, - // Modifier Byte + // LED Report 0x85, 0x01, // Report ID (1), 0x75, 0x01, // Report Size (1), - 0x95, 0x08, // Report Count (8), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x01, // Logical Maximum (1), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0xE0, // Usage Minimum (224), - 0x29, 0xE7, // Usage Maximum (231), - 0x81, 0x02, // Input (Data, Variable, Absolute), - - // LED Report - 0x85, 0x02, // Report ID (2), - 0x75, 0x01, // Report Size (1), 0x95, 0x05, // Report Count (5), 0x05, 0x08, // Usage Page (LEDs), 0x19, 0x01, // Usage Minimum (1), @@ -189,21 +178,34 @@ // 50 (ISO \ due to \ bug) and 156 (Clear due to Delete bug) must be excluded // due to a Linux bug with bitmaps (not useful anyways) // 165-175 are reserved/unused as well as 222-223 and 232-65535 - // 224-231 are used for modifiers (see above) // // Compatibility Notes: // - Using a second endpoint for a boot mode device helps with compatibility // - DO NOT use Padding in the descriptor for bitfields // (Mac OSX silently fails... Windows/Linux work correctly) + // - DO NOT use Report IDs, Windows 8.1 will not update keyboard correctly (modifiers disappear) + // (all other OSs, including OSX work fine...) + // (you can use them *iff* you only have 1 per collection) + // - Mac OSX and Windows 8.1 are extremely picky about padding // // Packing of bitmaps are as follows: - // 4-49 : 6 bytes + 1 Report ID byte (0x04-0x31) ( 46 bits + 2 padding bits for 6 bytes total) - // 51-155 : 14 bytes + 1 Report ID byte (0x33-0x9B) (105 bits + 6 padding bits for 15 bytes total) - // 157-164 : 1 byte + 1 Report ID byte (0x9D-0xA4) ( 8 bits) - // 176-221 : 6 bytes + 1 Report ID byte (0xB0-0xDD) ( 46 bits + 2 padding bits for 6 bytes total) - // + // 4-49 : 6 bytes (0x04-0x31) ( 46 bits + 2 padding bits for 6 bytes total) + // 51-155 : 14 bytes (0x33-0x9B) (105 bits + 6 padding bits for 15 bytes total) + // 157-164 : 1 byte (0x9D-0xA4) ( 8 bits) + // 176-221 : 6 bytes (0xB0-0xDD) ( 46 bits + 2 padding bits for 6 bytes total) + // 224-231 : 1 byte (0xE0-0xE7) ( 8 bits) + + // Modifier Byte + 0x75, 0x01, // Report Size (1), + 0x95, 0x08, // Report Count (8), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0xE0, // Usage Minimum (224), + 0x29, 0xE7, // Usage Maximum (231), + 0x81, 0x02, // Input (Data, Variable, Absolute), + // 4-49 (6 bytes/46 bits) - MainKeys - 0x85, 0x03, // Report ID (3), 0x75, 0x01, // Report Size (1), 0x95, 0x2E, // Report Count (46), 0x15, 0x00, // Logical Minimum (0), @@ -213,10 +215,12 @@ 0x29, 0x31, // Usage Maximum (49), 0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), - // Should pad 2 bits according to the spec, but OSX doesn't like this -HaaTa + // Padding (2 bits) + 0x75, 0x02, // Report Size (2), + 0x95, 0x01, // Report Count (1), + 0x81, 0x03, // Input (Constant), // 51-155 (14 bytes/105 bits) - SecondaryKeys - 0x85, 0x04, // Report ID (4), 0x75, 0x01, // Report Size (1), 0x95, 0x69, // Report Count (105), 0x15, 0x00, // Logical Minimum (0), @@ -226,10 +230,12 @@ 0x29, 0x9B, // Usage Maximum (155), 0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), - // Should pad 6 bits according to the spec, but OSX doesn't like this -HaaTa + // Padding (7 bits) + 0x75, 0x07, // Report Size (7), + 0x95, 0x01, // Report Count (1), + 0x81, 0x03, // Input (Constant), // 157-164 (1 byte/8 bits) - TertiaryKeys - 0x85, 0x05, // Report ID (5), 0x75, 0x01, // Report Size (1), 0x95, 0x08, // Report Count (8), 0x15, 0x00, // Logical Minimum (0), @@ -240,9 +246,8 @@ 0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), // 176-221 (6 bytes/46 bits) - QuartiaryKeys - 0x85, 0x06, // Report ID (6), 0x75, 0x01, // Report Size (1), - 0x95, 0x2D, // Report Count (45), + 0x95, 0x2E, // Report Count (46), 0x15, 0x00, // Logical Minimum (0), 0x25, 0x01, // Logical Maximum (1), 0x05, 0x07, // Usage Page (Key Codes), @@ -250,8 +255,10 @@ 0x29, 0xDD, // Usage Maximum (221), 0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), - // Should pad 2 bits according to the spec, but OSX doesn't like this -HaaTa - + // Padding (2 bits) + 0x75, 0x02, // Report Size (2), + 0x95, 0x01, // Report Count (1), + 0x81, 0x03, // Input (Constant), 0xc0, // End Collection - Keyboard // System Control Collection @@ -262,7 +269,7 @@ 0x05, 0x01, // Usage Page (Generic Desktop), 0x09, 0x80, // Usage (System Control), 0xA1, 0x01, // Collection (Application), - 0x85, 0x07, // Report ID (7), + 0x85, 0x02, // Report ID (2), 0x75, 0x08, // Report Size (8), 0x95, 0x01, // Report Count (1), 0x16, 0x81, 0x00, // Logical Minimum (129), @@ -280,7 +287,7 @@ 0x05, 0x0c, // Usage Page (Consumer), 0x09, 0x01, // Usage (Consumer Control), 0xA1, 0x01, // Collection (Application), - 0x85, 0x08, // Report ID (8), + 0x85, 0x03, // Report ID (3), 0x75, 0x10, // Report Size (16), 0x95, 0x01, // Report Count (1), 0x16, 0x20, 0x00, // Logical Minimum (32), diff -r afe96322d0c5 -r d3ac199593d6 Output/pjrcUSB/arm/usb_dev.c --- a/Output/pjrcUSB/arm/usb_dev.c Mon Nov 10 23:42:39 2014 -0800 +++ b/Output/pjrcUSB/arm/usb_dev.c Wed Nov 12 23:04:50 2014 -0800 @@ -397,7 +397,7 @@ case 0x2021: // CDC_SET_LINE_CODING // XXX Needed? //serial_print("set coding, waiting...\n"); - //endpoint0_stall(); + endpoint0_stall(); return; // Cannot stall here (causes issues) case 0x0921: // HID SET_REPORT diff -r afe96322d0c5 -r d3ac199593d6 Output/pjrcUSB/arm/usb_keyboard.c --- a/Output/pjrcUSB/arm/usb_keyboard.c Mon Nov 10 23:42:39 2014 -0800 +++ b/Output/pjrcUSB/arm/usb_keyboard.c Wed Nov 12 23:04:50 2014 -0800 @@ -133,73 +133,10 @@ // Send NKRO keyboard interrupts packet(s) case 1: - // Check modifiers - if ( USBKeys_Changed & USBKeyChangeState_Modifiers ) - { - *tx_buf++ = 0x01; // ID - *tx_buf = USBKeys_Modifiers; - tx_packet->len = 2; - - // Send USB Packet - usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet ); - USBKeys_Changed &= ~USBKeyChangeState_Modifiers; // Mark sent - } - // Check main key section - else if ( USBKeys_Changed & USBKeyChangeState_MainKeys ) - { - *tx_buf++ = 0x03; // ID - - // 4-49 (first 6 bytes) - memcpy( tx_buf, USBKeys_Keys, 6 ); - tx_packet->len = 7; - - // Send USB Packet - usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet ); - USBKeys_Changed &= ~USBKeyChangeState_MainKeys; // Mark sent - } - // Check secondary key section - else if ( USBKeys_Changed & USBKeyChangeState_SecondaryKeys ) + // Check system control keys + if ( USBKeys_Changed & USBKeyChangeState_System ) { - *tx_buf++ = 0x04; // ID - - // 51-155 (Middle 14 bytes) - memcpy( tx_buf, USBKeys_Keys + 6, 14 ); - tx_packet->len = 15; - - // Send USB Packet - usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet ); - USBKeys_Changed &= ~USBKeyChangeState_SecondaryKeys; // Mark sent - } - // Check tertiary key section - else if ( USBKeys_Changed & USBKeyChangeState_TertiaryKeys ) - { - *tx_buf++ = 0x05; // ID - - // 157-164 (Next byte) - memcpy( tx_buf, USBKeys_Keys + 20, 1 ); - tx_packet->len = 2; - - // Send USB Packet - usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet ); - USBKeys_Changed &= ~USBKeyChangeState_TertiaryKeys; // Mark sent - } - // Check quartiary key section - else if ( USBKeys_Changed & USBKeyChangeState_QuartiaryKeys ) - { - *tx_buf++ = 0x06; // ID - - // 176-221 (last 6 bytes) - memcpy( tx_buf, USBKeys_Keys + 21, 6 ); - tx_packet->len = 7; - - // Send USB Packet - usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet ); - USBKeys_Changed &= ~USBKeyChangeState_QuartiaryKeys; // Mark sent - } - // Check system control keys - else if ( USBKeys_Changed & USBKeyChangeState_System ) - { - *tx_buf++ = 0x07; // ID + *tx_buf++ = 0x02; // ID *tx_buf = USBKeys_SysCtrl; tx_packet->len = 2; @@ -207,10 +144,11 @@ usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet ); USBKeys_Changed &= ~USBKeyChangeState_System; // Mark sent } + // Check consumer control keys - else if ( USBKeys_Changed & USBKeyChangeState_Consumer ) + if ( USBKeys_Changed & USBKeyChangeState_Consumer ) { - *tx_buf++ = 0x08; // ID + *tx_buf++ = 0x03; // ID *tx_buf++ = (uint8_t)(USBKeys_ConsCtrl & 0x00FF); *tx_buf = (uint8_t)(USBKeys_ConsCtrl >> 8); tx_packet->len = 3; @@ -220,6 +158,40 @@ USBKeys_Changed &= ~USBKeyChangeState_Consumer; // Mark sent } + // Standard HID Keyboard + if ( USBKeys_Changed ) + { + tx_packet->len = 0; + + // Modifiers + *tx_buf++ = 0x01; // ID + *tx_buf++ = USBKeys_Modifiers; + tx_packet->len += 2; + + // 4-49 (first 6 bytes) + memcpy( tx_buf, USBKeys_Keys, 6 ); + tx_buf += 6; + tx_packet->len += 6; + + // 51-155 (Middle 14 bytes) + memcpy( tx_buf, USBKeys_Keys + 6, 14 ); + tx_buf += 14; + tx_packet->len += 14; + + // 157-164 (Next byte) + memcpy( tx_buf, USBKeys_Keys + 20, 1 ); + tx_buf += 1; + tx_packet->len += 1; + + // 176-221 (last 6 bytes) + memcpy( tx_buf, USBKeys_Keys + 21, 6 ); + tx_packet->len += 6; + + // Send USB Packet + usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet ); + USBKeys_Changed = USBKeyChangeState_None; // Mark sent + } + break; } diff -r afe96322d0c5 -r d3ac199593d6 Output/pjrcUSB/avr/usb_keyboard_serial.c --- a/Output/pjrcUSB/avr/usb_keyboard_serial.c Mon Nov 10 23:42:39 2014 -0800 +++ b/Output/pjrcUSB/avr/usb_keyboard_serial.c Wed Nov 12 23:04:50 2014 -0800 @@ -104,85 +104,54 @@ // Send NKRO keyboard interrupts packet(s) case 1: - // Check modifiers - if ( USBKeys_Changed & USBKeyChangeState_Modifiers ) + // Check system control keys + if ( USBKeys_Changed & USBKeyChangeState_System ) { - UEDATX = 0x01; // ID - UEDATX = USBKeys_Modifiers; + UEDATX = 0x02; // ID + UEDATX = USBKeys_SysCtrl; UEINTX = 0; // Finished with ID - USBKeys_Changed &= ~USBKeyChangeState_Modifiers; // Mark sent + USBKeys_Changed &= ~USBKeyChangeState_System; // Mark sent } - // Check main key section - if ( USBKeys_Changed & USBKeyChangeState_MainKeys ) + + // Check consumer control keys + if ( USBKeys_Changed & USBKeyChangeState_Consumer ) { UEDATX = 0x03; // ID + UEDATX = (uint8_t)(USBKeys_ConsCtrl & 0x00FF); + UEDATX = (uint8_t)(USBKeys_ConsCtrl >> 8); + UEINTX = 0; // Finished with ID + + USBKeys_Changed &= ~USBKeyChangeState_Consumer; // Mark sent + } + + // Standard HID Keyboard + if ( USBKeys_Changed ) + { + UEDATX = 0x01; // ID + + // Modifiers + UEDATX = USBKeys_Modifiers; // 4-49 (first 6 bytes) for ( uint8_t byte = 0; byte < 6; byte++ ) UEDATX = USBKeys_Keys[ byte ]; - UEINTX = 0; // Finished with ID - - USBKeys_Changed &= ~USBKeyChangeState_MainKeys; // Mark sent - } - // Check secondary key section - if ( USBKeys_Changed & USBKeyChangeState_SecondaryKeys ) - { - UEDATX = 0x04; // ID - // 51-155 (Middle 14 bytes) for ( uint8_t byte = 6; byte < 20; byte++ ) UEDATX = USBKeys_Keys[ byte ]; - UEINTX = 0; // Finished with ID - - USBKeys_Changed &= ~USBKeyChangeState_SecondaryKeys; // Mark sent - } - // Check tertiary key section - if ( USBKeys_Changed & USBKeyChangeState_TertiaryKeys ) - { - UEDATX = 0x05; // ID - // 157-164 (Next byte) for ( uint8_t byte = 20; byte < 21; byte++ ) UEDATX = USBKeys_Keys[ byte ]; - UEINTX = 0; // Finished with ID - - USBKeys_Changed &= ~USBKeyChangeState_TertiaryKeys; // Mark sent - } - // Check quartiary key section - if ( USBKeys_Changed & USBKeyChangeState_TertiaryKeys ) - { - UEDATX = 0x06; // ID - // 176-221 (last 6 bytes) for ( uint8_t byte = 21; byte < 27; byte++ ) UEDATX = USBKeys_Keys[ byte ]; UEINTX = 0; // Finished with ID - USBKeys_Changed &= ~USBKeyChangeState_QuartiaryKeys; // Mark sent - } - // Check system control keys - if ( USBKeys_Changed & USBKeyChangeState_System ) - { - UEDATX = 0x07; // ID - UEDATX = USBKeys_SysCtrl; - UEINTX = 0; // Finished with ID - - USBKeys_Changed &= ~USBKeyChangeState_System; // Mark sent - } - // Check consumer control keys - if ( USBKeys_Changed & USBKeyChangeState_Consumer ) - { - UEDATX = 0x08; // ID - UEDATX = (uint8_t)(USBKeys_ConsCtrl & 0x00FF); - UEDATX = (uint8_t)(USBKeys_ConsCtrl >> 8); - UEINTX = 0; // Finished with ID - - USBKeys_Changed &= ~USBKeyChangeState_Consumer; // Mark sent + USBKeys_Changed = USBKeyChangeState_None; // Mark sent } break; diff -r afe96322d0c5 -r d3ac199593d6 Output/pjrcUSB/avr/usb_keyboard_serial.h --- a/Output/pjrcUSB/avr/usb_keyboard_serial.h Mon Nov 10 23:42:39 2014 -0800 +++ b/Output/pjrcUSB/avr/usb_keyboard_serial.h Wed Nov 12 23:04:50 2014 -0800 @@ -337,20 +337,9 @@ 0x09, 0x06, // Usage (Keyboard), 0xA1, 0x01, // Collection (Application) - Keyboard, - // Modifier Byte + // LED Report 0x85, 0x01, // Report ID (1), 0x75, 0x01, // Report Size (1), - 0x95, 0x08, // Report Count (8), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x01, // Logical Maximum (1), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0xE0, // Usage Minimum (224), - 0x29, 0xE7, // Usage Maximum (231), - 0x81, 0x02, // Input (Data, Variable, Absolute), - - // LED Report - 0x85, 0x02, // Report ID (2), - 0x75, 0x01, // Report Size (1), 0x95, 0x05, // Report Count (5), 0x05, 0x08, // Usage Page (LEDs), 0x19, 0x01, // Usage Minimum (1), @@ -373,21 +362,34 @@ // 50 (ISO \ due to \ bug) and 156 (Clear due to Delete bug) must be excluded // due to a Linux bug with bitmaps (not useful anyways) // 165-175 are reserved/unused as well as 222-223 and 232-65535 - // 224-231 are used for modifiers (see above) // // Compatibility Notes: // - Using a second endpoint for a boot mode device helps with compatibility // - DO NOT use Padding in the descriptor for bitfields // (Mac OSX silently fails... Windows/Linux work correctly) + // - DO NOT use Report IDs, Windows 8.1 will not update keyboard correctly (modifiers disappear) + // (all other OSs, including OSX work fine...) + // (you can use them *iff* you only have 1 per collection) + // - Mac OSX and Windows 8.1 are extremely picky about padding // // Packing of bitmaps are as follows: - // 4-49 : 6 bytes + 1 Report ID byte (0x04-0x31) ( 46 bits + 2 padding bits for 6 bytes total) - // 51-155 : 14 bytes + 1 Report ID byte (0x33-0x9B) (105 bits + 6 padding bits for 15 bytes total) - // 157-164 : 1 byte + 1 Report ID byte (0x9D-0xA4) ( 8 bits) - // 176-221 : 6 bytes + 1 Report ID byte (0xB0-0xDD) ( 46 bits + 2 padding bits for 6 bytes total) - // + // 4-49 : 6 bytes (0x04-0x31) ( 46 bits + 2 padding bits for 6 bytes total) + // 51-155 : 14 bytes (0x33-0x9B) (105 bits + 6 padding bits for 15 bytes total) + // 157-164 : 1 byte (0x9D-0xA4) ( 8 bits) + // 176-221 : 6 bytes (0xB0-0xDD) ( 46 bits + 2 padding bits for 6 bytes total) + // 224-231 : 1 byte (0xE0-0xE7) ( 8 bits) + + // Modifier Byte + 0x75, 0x01, // Report Size (1), + 0x95, 0x08, // Report Count (8), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0xE0, // Usage Minimum (224), + 0x29, 0xE7, // Usage Maximum (231), + 0x81, 0x02, // Input (Data, Variable, Absolute), + // 4-49 (6 bytes/46 bits) - MainKeys - 0x85, 0x03, // Report ID (3), 0x75, 0x01, // Report Size (1), 0x95, 0x2E, // Report Count (46), 0x15, 0x00, // Logical Minimum (0), @@ -397,10 +399,12 @@ 0x29, 0x31, // Usage Maximum (49), 0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), - // Should pad 2 bits according to the spec, but OSX doesn't like this -HaaTa + // Padding (2 bits) + 0x75, 0x02, // Report Size (2), + 0x95, 0x01, // Report Count (1), + 0x81, 0x03, // Input (Constant), // 51-155 (14 bytes/105 bits) - SecondaryKeys - 0x85, 0x04, // Report ID (4), 0x75, 0x01, // Report Size (1), 0x95, 0x69, // Report Count (105), 0x15, 0x00, // Logical Minimum (0), @@ -410,10 +414,12 @@ 0x29, 0x9B, // Usage Maximum (155), 0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), - // Should pad 6 bits according to the spec, but OSX doesn't like this -HaaTa + // Padding (7 bits) + 0x75, 0x07, // Report Size (7), + 0x95, 0x01, // Report Count (1), + 0x81, 0x03, // Input (Constant), // 157-164 (1 byte/8 bits) - TertiaryKeys - 0x85, 0x05, // Report ID (5), 0x75, 0x01, // Report Size (1), 0x95, 0x08, // Report Count (8), 0x15, 0x00, // Logical Minimum (0), @@ -424,9 +430,8 @@ 0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), // 176-221 (6 bytes/46 bits) - QuartiaryKeys - 0x85, 0x06, // Report ID (6), 0x75, 0x01, // Report Size (1), - 0x95, 0x2D, // Report Count (45), + 0x95, 0x2E, // Report Count (46), 0x15, 0x00, // Logical Minimum (0), 0x25, 0x01, // Logical Maximum (1), 0x05, 0x07, // Usage Page (Key Codes), @@ -434,8 +439,10 @@ 0x29, 0xDD, // Usage Maximum (221), 0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), - // Should pad 2 bits according to the spec, but OSX doesn't like this -HaaTa - + // Padding (2 bits) + 0x75, 0x02, // Report Size (2), + 0x95, 0x01, // Report Count (1), + 0x81, 0x03, // Input (Constant), 0xc0, // End Collection - Keyboard // System Control Collection @@ -446,7 +453,7 @@ 0x05, 0x01, // Usage Page (Generic Desktop), 0x09, 0x80, // Usage (System Control), 0xA1, 0x01, // Collection (Application), - 0x85, 0x07, // Report ID (7), + 0x85, 0x02, // Report ID (2), 0x75, 0x08, // Report Size (8), 0x95, 0x01, // Report Count (1), 0x16, 0x81, 0x00, // Logical Minimum (129), @@ -464,7 +471,7 @@ 0x05, 0x0c, // Usage Page (Consumer), 0x09, 0x01, // Usage (Consumer Control), 0xA1, 0x01, // Collection (Application), - 0x85, 0x08, // Report ID (8), + 0x85, 0x03, // Report ID (3), 0x75, 0x10, // Report Size (16), 0x95, 0x01, // Report Count (1), 0x16, 0x20, 0x00, // Logical Minimum (32),