add build option: NKRO_ENABLE(remove: USB_12KRO)
12 files changed, 414 insertions(+), 260 deletions(-) M Makefile.common M README A USB_NKRO.txt M hhkb/Makefile M hhkb/keymap.c M key_process.c M tmk.c M usb.c -rw-r--r-- => -rwxr-xr-x M usb_keyboard.c M usb_keyboard.h M usb_mouse.c M util.c
M Makefile.common => Makefile.common +2 -2
@@ 129,8 129,8 @@ CDEFS += -DPRODUCT=$(PRODUCT) ifdef MOUSE_DELAY_TIME CDEFS += -DMOUSE_DELAY_TIME=$(MOUSE_DELAY_TIME) endif ifdef USB_12KRO CDEFS += -DUSB_12KRO ifdef NKRO_ENABLE CDEFS += -DNKRO_ENABLE endif
M README => README +17 -92
@@ 2,42 2,23 @@ t.m.k. Keyboard Firmware ======================== http://github.com/tmk/tmk_keyboard This is keyboard firmware for PFU HHKB style keyboard and Teensy/Teensy++ 2.0. OS see this as composite device which has keyboard and mouse. This is keyboard firmware for AVR USB MCUs or Teensy/Teensy++ 2.0. The project is heavily based on PJRC USB Keyboard/Mouse Example and owes a debt to preceding keyboard firmware projects. http://www.pjrc.com/teensy Version ------- 0.1 2010/08/23 It works as normal keyboard. It is for modified Macway keyboard(TP-999KB-E). 1.0 2010/10/02 keyboard has mouse key now. keyboard with layers.(see keymap.c) FN_1(right cmd): vi style layer FN_2(next to right shift): HHKB style layer FN_3(left bottom): h j k l: mouse move a s d spc: mouse buttons m ,: mouse wheel 1.1 2010/10/08 Matrix wiring changed for casing. (and my Teensy PD3 seems to be latchuped and unusable. :<) 1.2 2010/10/13 HHKB support horizontal mouse wheel support change keymaps 2.0 2010/10/27 HHKB/Macway support merged Functions --------- Mouse key System Control Key Power Down, Sleep, Wake Up & USB Remote Wake up Media Control Key Volume Down/Up, Mute USB NKRO @@ Build 47,17 28,16 @@ Compiling sources need AVR GCC, AVR Libc and GNU make.(You can use WinAVR on Win $ cd <target> (hhkb or macway) $ make http://winavr.sourceforge.net/ Debuging -------- Debug print is on if 4 keys are pressed during booting. Use PJRC's hid_listen.exe to see debug messages. Debuging & Rescue ----------------- Use PJRC's hid_listen.exe to see debug messages. Press right Control + Shift + Alt + GUI + H to debug menu. AVR Target board ---------------- Teensy/Teensy++ http://www.pjrc.com/teensy Pressing any 3 keys when connected enables debug output. Pressing any 4 keys when connected makes bootloader comes up. @@ Projects related 83,59 63,4 @@ ps2avr http://sourceforge.net/projects/ps2avr/ TODO & ideas ------------ licensing notes(GPL) I think GPL is not infringement of PJRC license. souce code cleaning sleep&wakeup debouncing logic will be coded when bouncing occurs. bouncing doesnt occur on my ALPS switch so far. scan rate is too slow?(to be measure) Trackpoint(PS/2) receive PS/2 signal from TrackPoint send USB HID report Thinkpad keyboard support turn keyboard to USB keyboard/mouse composite device setting menu(configure without changing firmware) console for display keymap/layer setting mouse speed/acceleration matrix display PS/2 keyboard mode with USB to PS/2 dumb adapter(possible?) AT90USBKEY support and other AVR USB boards DONE: support for HHKB pro matrix signal exchange controller board with teensy 2010/10/11 keymap Matias half keyboard style 2010/10/23 souce code cleaning 2010/10/23 debug on/off debug off by default pressing keys during booting 2010/10/23 mouse horizontal wheel http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521 http://www.keil.com/forum/15671/ http://www.microsoft.com/whdc/device/input/wheel.mspx 2010/10/13 debug on/off Fn key conbination during normal operation matrix print on/off key print on/off mouse print on/off 2010/10/26 layer switching time before switching timeout when not used during specific time 2010/10/30 EOF
A USB_NKRO.txt => USB_NKRO.txt +99 -0
@@ 0,0 1,99 @@ USB NKRO MEMO ============= 2010/12/07 References ---------- USB - boot mode, NKRO, compatibility, etc... http://geekhack.org/showthread.php?t=13162 NKey Rollover - Overview, Testing Methodology, and Results http://geekhack.org/showwiki.php?title=NKey+Rollover+-+Overview+Testing+Methodology+and+Results Terminogy --------- NKRO ghost matrix mechanical with diodes membrane OS Support Status ----------------- NKRO is possible at least relatively new OS. Following OS supports both Extended and Bitmarp report. Windows7 64bit Windows2000 SP4 Ubuntu 10.4(Linux 2.6) USB NKRO methods ---------------- 1. Virtual keyboards 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. Using this method means the keyboard is a composite device. 2. Exteded report It needs large report size for this method to achive NKRO. If a keyboard has 101keys, it needs 103byte report. It seems to be inefficient. 3. Bitmap report If the keyboard has less than 128keys, 16byte report will be enough for NKRO. The 16byte report seems to be reasonable cost to get NKRO. Report Format ------------- Other report formats than followings are possible, though these format are typical one. 1. Standard 8bytes modifiers(bitmap) 1byte reserved 1byte(not used) keys(array) 1byte*6 Standard report can send 6keys plus 8modifiers simultaneously. Standard report is used by most keyboards in the marketplace. Standard report is identical to boot protocol report. Standard report is hard to suffer from compatibility problems. 2. Extended standard 16,32,64bytes modifiers(bitmap) 1byte reserved 1byte(not used) keys(array) 1byte*(14,32,62) Extended report can send N-keys by using N+2bytes. Extended report is expected to be compatible with boot protocol. 3. Bitmap 16,32,64bytes keys(bitmap) (16,32)bytes 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 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. Windows Problem --------------- 1. Windows accepts only 6keys in case of Standard report. It should be able to send 6keys plus 8modifiers. 2. Windows accepts only 10keys in case of 16bytes Extended report. It should be able to send 14keys plus 8modifiers. 3. Windows accepts only 18keys in case of 32bytes Extended report. It should be able to send 30keys plus 8modifiers. 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) http://forums.anandtech.com/showpost.php?p=30873364&postcount=17 EOF
M hhkb/Makefile => hhkb/Makefile +3 -2
@@ 39,14 39,15 @@ # To rebuild project do "make clean" then "make all". #---------------------------------------------------------------------------- # TODO: use config.h for build options? VENDOR_ID = 0xFEED PRODUCT_ID = 0xCAFE MANUFACTURER = 't.m.k.' PRODUCT = 't.m.k. HHKB pro' PRODUCT = 'HHKB Mod' DESCRIPTION = 't.m.k. firmware for HHKB pro' MOUSE_DELAY_TIME = 127 USB_12KRO = yes NKRO_ENABLE = true # Target file name (without extension). TARGET = tmk_hhkb
M hhkb/keymap.c => hhkb/keymap.c +3 -3
@@ 42,8 42,8 @@ static const uint8_t PROGMEM fn_keycode[] = { KB_NO, // FN_0 [NOT USED] KB_NO, // FN_1 layer 1 KB_SLSH, // FN_2 layer 2 KB_SCOLON, // FN_3 layer 3 KB_SPACE, // FN_4 layer 4 KB_SCLN, // FN_3 layer 3 KB_SPC, // FN_4 layer 4 KB_NO, // FN_5 [NOT USED] KB_NO, // FN_6 [NOT USED] @@ KB_NO // FN_7 layer 1 67,7 67,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KB_TAB, KB_Q, KB_W, KB_E, KB_R, KB_T, KB_Y, KB_U, KB_I, KB_O, KB_P, KB_LBRC,KB_RBRC,KB_BSPC, \ KB_LCTL,KB_A, KB_S, KB_D, KB_F, KB_G, KB_H, KB_J, KB_K, KB_L, FN_3, KB_QUOT,KB_ENT, \ KB_LSFT,KB_Z, KB_X, KB_C, KB_V, KB_B, KB_N, KB_M, KB_COMM,KB_DOT, FN_2, KB_RSFT,FN_1, \ KB_LGUI,KB_LALT,FN_4, KB_RALT,FN_7), KB_LGUI,KB_LALT,FN_4, KB_RALT,KB_RGUI), /* Layer 1: HHKB mode (HHKB Fn) * ,-----------------------------------------------------------.
M key_process.c => key_process.c +45 -26
@@ 1,5 1,6 @@ #include <stdbool.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include "print.h" @@ #include "debug.h" 68,7 69,7 @@ void proc_matrix(void) { if (code == KB_NO) { // do nothing } else if (IS_MOD(code)) { usb_keyboard_mods |= MOD_BIT(code); usb_keyboard_add_mod(code); } else if (IS_FN(code)) { fn_bits |= FN_BIT(code); @@ } else if (IS_MOUSE(code)) { 111,22 112,7 @@ void proc_matrix(void) { // normal keys else { // TODO: fix ugly code int8_t i = 0; int8_t empty = -1; for (; i < KEYBOARD_REPORT_MAX; i++) { if (usb_keyboard_keys_prev[i] == code) { usb_keyboard_keys[i] = code; break; } else if (empty == -1 && usb_keyboard_keys_prev[i] == 0 && usb_keyboard_keys[i] == 0) { empty = i; } } if (i == KEYBOARD_REPORT_MAX) { if (empty != -1) { usb_keyboard_keys[empty] = code; } } usb_keyboard_add_key(code); } } @@ } 142,20 128,24 @@ void proc_matrix(void) { layer_switching(fn_bits); // TODO: clean code // when 4 left modifier keys down // special mode for control, develop and debug if (keymap_is_special_mode(fn_bits)) { switch (usb_keyboard_keys[0]) { switch (usb_keyboard_get_key()) { case KB_H: // help print_enable = true; print("b: jump to bootloader\n"); print("d: debug print toggle\n"); print("x: matrix debug toggle\n"); print("k: keyboard debug toggle\n"); print("m: mouse debug toggle\n"); print("p: print enable toggle\n"); print("d: toggle debug enable\n"); print("x: toggle matrix debug\n"); print("k: toggle keyboard debug\n"); print("m: toggle mouse debug\n"); print("p: toggle print enable\n"); print("v: print version\n"); print("t: print timer count\n"); print("r: print registers\n"); print("s: print status\n"); print("`: toggle protcol(boot/report)\n"); #ifdef NKRO_ENABLE print("n: toggle NKRO\n"); #endif print("ESC: power down/wake up\n"); _delay_ms(500); @@ print_enable = false; 243,13 233,42 @@ void proc_matrix(void) { } _delay_ms(1000); break; case KB_R: case KB_S: usb_keyboard_clear_report(); usb_keyboard_send(); print("UDCON: "); phex(UDCON); print("\n"); print("UDIEN: "); phex(UDIEN); print("\n"); print("UDINT: "); phex(UDINT); print("\n"); print("usb_keyboard_leds:"); phex(usb_keyboard_leds); print("\n"); print("usb_keyboard_protocol:"); phex(usb_keyboard_protocol); print("\n"); print("usb_keyboard_idle_config:"); phex(usb_keyboard_idle_config); print("\n"); print("usb_keyboard_idle_count:"); phex(usb_keyboard_idle_count); print("\n"); print("mouse_protocol:"); phex(mouse_protocol); print("\n"); if (usb_keyboard_nkro) print("NKRO: enabled\n"); else print("NKRO: disabled\n"); _delay_ms(500); break; case KB_GRV: usb_keyboard_clear_report(); usb_keyboard_send(); usb_keyboard_protocol = !usb_keyboard_protocol; mouse_protocol = !mouse_protocol; print("keyboard protcol: "); if (usb_keyboard_protocol) print("report"); else print("boot"); print("\n"); print("mouse protcol: "); if (mouse_protocol) print("report"); else print("boot"); print("\n"); _delay_ms(1000); break; #ifdef NKRO_ENABLE case KB_N: usb_keyboard_clear_report(); usb_keyboard_send(); usb_keyboard_nkro = !usb_keyboard_nkro; if (usb_keyboard_nkro) print("NKRO: enabled\n"); else print("NKRO: disabled\n"); _delay_ms(1000); break; #endif case KB_ESC: usb_keyboard_clear_report(); usb_keyboard_send();
M tmk.c => tmk.c +8 -2
@@ 66,8 66,7 @@ int main(void) matrix_init(); matrix_scan(); // bootloader comes up when any 4 or more keys are pressed at startup if (matrix_key_count() >= 4) { if (matrix_key_count() >= 3) { #ifdef DEBUG_LED for (int i = 0; i < 6; i++) { @@ DEBUG_LED_CONFIG; 80,6 79,13 @@ int main(void) _delay_ms(5000); #endif print_enable = true; debug_enable = true; debug_matrix = true; debug_keyboard = true; debug_mouse = true; print("debug enabled.\n"); } if (matrix_key_count() >= 4) { print("jump to bootloader...\n"); _delay_ms(1000); jump_bootloader(); // not return
M usb.c => usb.c +78 -35
@@ 90,12 90,12 @@ bool suspend = false; // 0:control endpoint is enabled automatically by controller. static const uint8_t PROGMEM endpoint_config_table[] = { // enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation) 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, // 1 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD_SIZE) | KBD_BUFFER, // 1 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, // 2 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 #ifdef USB_12KRO 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, // 5 #ifdef NKRO_ENABLE 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD2_SIZE) | KBD2_BUFFER, // 5 #else 0, // 5 @@ #endif 158,16 158,52 @@ static uint8_t PROGMEM keyboard_hid_report_desc[] = { 0x95, 0x01, // Report Count (1), 0x75, 0x03, // Report Size (3), 0x91, 0x03, // Output (Constant), ;LED report padding 0x95, 0x06, // Report Count (6), 0x95, KBD_REPORT_KEYS, // Report Count (), 0x75, 0x08, // Report Size (8), 0x15, 0x00, // Logical Minimum (0), 0x25, 0x68, // Logical Maximum(104), 0x25, 0xFF, // Logical Maximum(255), 0x05, 0x07, // Usage Page (Key Codes), 0x19, 0x00, // Usage Minimum (0), 0x29, 0x68, // Usage Maximum (104), 0x29, 0xFF, // Usage Maximum (255), 0x81, 0x00, // Input (Data, Array), 0xc0 // End Collection }; #ifdef NKRO_ENABLE 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 }; #endif // Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension @@ // http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521 296,17 332,17 @@ static uint8_t PROGMEM extra_hid_report_desc[] = { 0xc0 // END_COLLECTION }; #define KEYBOARD_HID_DESC_OFFSET (9+(9+9+7)*0+9) #define MOUSE_HID_DESC_OFFSET (9+(9+9+7)*1+9) #define DEBUG_HID_DESC_OFFSET (9+(9+9+7)*2+9) #define EXTRA_HID_DESC_OFFSET (9+(9+9+7)*3+9) #ifdef USB_12KRO # define NUM_INTERFACES 5 # define KEYBOARD2_HID_DESC_OFFSET (9+(9+9+7)*4+9) #define KBD_HID_DESC_OFFSET (9+(9+9+7)*0+9) #define MOUSE_HID_DESC_OFFSET (9+(9+9+7)*1+9) #define DEBUG_HID_DESC_OFFSET (9+(9+9+7)*2+9) #define EXTRA_HID_DESC_OFFSET (9+(9+9+7)*3+9) #ifdef NKRO_ENABLE # define NUM_INTERFACES 5 # define KBD2_HID_DESC_OFFSET (9+(9+9+7)*4+9) #else # define NUM_INTERFACES 4 # define NUM_INTERFACES 4 #endif #define CONFIG1_DESC_SIZE (9+(9+9+7)*NUM_INTERFACES) #define CONFIG1_DESC_SIZE (9+(9+9+7)*NUM_INTERFACES) static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 @@ 9, // bLength; 322,7 358,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType KEYBOARD_INTERFACE, // bInterfaceNumber KBD_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 1, // bNumEndpoints @@ 0x03, // bInterfaceClass (0x03 = HID) 341,10 377,10 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress KBD_ENDPOINT | 0x80, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) KEYBOARD_SIZE, 0, // wMaxPacketSize 1, // bInterval KBD_SIZE, 0, // wMaxPacketSize 10, // bInterval // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 @@ 9, // bLength 353,8 389,13 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { 0, // bAlternateSetting 1, // bNumEndpoints 0x03, // bInterfaceClass (0x03 = HID) // ThinkPad T23 BIOS doesn't work with boot mouse. 0x00, // bInterfaceSubClass (0x01 = Boot) 0x00, // bInterfaceProtocol (0x02 = Mouse) /* 0x01, // bInterfaceSubClass (0x01 = Boot) 0x02, // bInterfaceProtocol (0x02 = Mouse) */ 0, // iInterface // HID descriptor, HID 1.11 spec, section 6.2.1 @@ 9, // bLength 427,11 468,11 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { EXTRA_SIZE, 0, // wMaxPacketSize 10, // bInterval #ifdef USB_12KRO #ifdef NKRO_ENABLE // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType KEYBOARD_INTERFACE2, // bInterfaceNumber KBD2_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 1, // bNumEndpoints @@ 0x03, // bInterfaceClass (0x03 = HID) 445,14 486,14 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { 0, // bCountryCode 1, // bNumDescriptors 0x22, // bDescriptorType sizeof(keyboard_hid_report_desc), // wDescriptorLength sizeof(keyboard2_hid_report_desc), // wDescriptorLength 0, // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType KEYBOARD_ENDPOINT2 | 0x80, // bEndpointAddress KBD2_ENDPOINT | 0x80, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) KEYBOARD_SIZE, 0, // wMaxPacketSize KBD2_SIZE, 0, // wMaxPacketSize 1, // bInterval #endif @@ }; 494,17 535,17 @@ static struct descriptor_list_struct { // CONFIGURATION descriptor {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, // HID/REPORT descriptors {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9}, {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, {0x2100, KBD_INTERFACE, config1_descriptor+KBD_HID_DESC_OFFSET, 9}, {0x2200, KBD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, {0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9}, {0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)}, {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9}, {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)}, {0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9}, {0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)}, #ifdef USB_12KRO {0x2100, KEYBOARD_INTERFACE2, config1_descriptor+KEYBOARD2_HID_DESC_OFFSET, 9}, {0x2200, KEYBOARD_INTERFACE2, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, #ifdef NKRO_ENABLE {0x2100, KBD2_INTERFACE, config1_descriptor+KBD2_HID_DESC_OFFSET, 9}, {0x2200, KBD2_INTERFACE, keyboard2_hid_report_desc, sizeof(keyboard2_hid_report_desc)}, #endif // STRING descriptors @@ {0x0300, 0x0000, (const uint8_t *)&string0, 4}, 603,7 644,7 @@ ISR(USB_GEN_vect) } } if (usb_keyboard_idle_config && (++div4 & 3) == 0) { UENUM = KEYBOARD_ENDPOINT; UENUM = KBD_ENDPOINT; if (UEINTX & (1<<RWAL)) { usb_keyboard_idle_count++; @@ if (usb_keyboard_idle_count == usb_keyboard_idle_config) { 728,10 769,12 @@ ISR(USB_COM_vect) for (i=1; i<=6; i++) { UENUM = i; en = pgm_read_byte(cfg++); UECONX = en; if (en) { UECFG0X = pgm_read_byte(cfg++); UECFG1X = pgm_read_byte(cfg++); if (en) { UECONX = (1<<EPEN); UECFG0X = pgm_read_byte(cfg++); UECFG1X = pgm_read_byte(cfg++); } else { UECONX = 0; } } @@ UERST = 0x7E; 788,7 831,7 @@ ISR(USB_COM_vect) return; } } if (wIndex == KEYBOARD_INTERFACE) { if (wIndex == KBD_INTERFACE) { if (bmRequestType == 0xA1) { if (bRequest == HID_GET_REPORT) { usb_wait_in_ready();
M usb_keyboard.c => usb_keyboard.c +129 -81
@@ 4,11 4,12 @@ #include "usb_keyboard.h" #include "print.h" #include "debug.h" #include "util.h" // keyboard report. static usb_keyboard_report_t _report0 = { {0}, 0 }; static usb_keyboard_report_t _report1 = { {0}, 0 }; static usb_keyboard_report_t _report0 = { {0}, 0, false }; static usb_keyboard_report_t _report1 = { {0}, 0, false }; usb_keyboard_report_t *usb_keyboard_report = &_report0; usb_keyboard_report_t *usb_keyboard_report_prev = &_report1; @@ 27,75 28,37 @@ uint8_t usb_keyboard_idle_count=0; // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana volatile uint8_t usb_keyboard_leds=0; // enable NKRO bool usb_keyboard_nkro = false; int8_t usb_keyboard_send(void) { return usb_keyboard_send_report(usb_keyboard_report); } static inline int8_t _send_report(usb_keyboard_report_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end); int8_t usb_keyboard_send_report(usb_keyboard_report_t *report) { uint8_t i, intr_state, timeout; if (!usb_configured()) return -1; intr_state = SREG; cli(); UENUM = KEYBOARD_ENDPOINT; timeout = UDFNUML + 50; while (1) { // are we ready to transmit? if (UEINTX & (1<<RWAL)) break; SREG = intr_state; // has the USB gone offline? if (!usb_configured()) return -1; // have we waited too long? if (UDFNUML == timeout) return -1; // get ready to try checking again intr_state = SREG; cli(); UENUM = KEYBOARD_ENDPOINT; } UEDATX = report->mods; UEDATX = 0; for (i = 0; i < 6; i++) { UEDATX = report->keys[i]; } UEINTX = 0x3A; SREG = intr_state; #ifdef USB_12KRO if (!usb_configured()) return -1; intr_state = SREG; cli(); UENUM = KEYBOARD_ENDPOINT2; timeout = UDFNUML + 50; while (1) { // are we ready to transmit? if (UEINTX & (1<<RWAL)) break; SREG = intr_state; // has the USB gone offline? if (!usb_configured()) return -1; // have we waited too long? if (UDFNUML == timeout) return -1; // get ready to try checking again intr_state = SREG; cli(); UENUM = KEYBOARD_ENDPOINT2; } UEDATX = report->mods; UEDATX = 0; for (i = 6; i < 12; i++) { UEDATX = report->keys[i]; } UEINTX = 0x3A; SREG = intr_state; int8_t result = 0; #ifdef NKRO_ENABLE if (usb_keyboard_nkro) result = _send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS); else #endif { if (usb_keyboard_protocol) result = _send_report(report, KBD_ENDPOINT, 0, KBD_REPORT_KEYS); else result = _send_report(report, KBD_ENDPOINT, 0, 6); } usb_keyboard_idle_count = 0; report->is_sent =true; usb_keyboard_print_report(report); return 0; if (result) return result; usb_keyboard_idle_count = 0; report->is_sent =true; usb_keyboard_print_report(report); return 0; } @@ void usb_keyboard_swap_report(void) { 111,7 74,7 @@ void usb_keyboard_clear_report(void) { } void usb_keyboard_clear_keys(void) { for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) usb_keyboard_report->keys[i] = 0; for (int i = 0; i < KEYS_MAX; i++) usb_keyboard_report->keys[i] = 0; } @@ void usb_keyboard_clear_mods(void) 119,6 82,17 @@ void usb_keyboard_clear_mods(void) usb_keyboard_report->mods = 0; } void usb_keyboard_set_keys(uint8_t *keys) { for (int i = 0; i < KEYS_MAX; i++) usb_keyboard_report->keys[i] = keys[i]; } void usb_keyboard_set_mods(uint8_t mods) { usb_keyboard_report->mods = mods; } void usb_keyboard_add_code(uint8_t code) { @@ if (IS_MOD(code)) { 128,25 102,17 @@ void usb_keyboard_add_code(uint8_t code) } } static inline void _add_key_byte(uint8_t code); static inline void _add_key_bit(uint8_t code); void usb_keyboard_add_key(uint8_t code) { for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) { if (!usb_keyboard_report->keys[i]) { usb_keyboard_report->keys[i] = code; return; } #ifdef NKRO_ENABLE if (usb_keyboard_nkro) { _add_key_bit(code); return; } } void usb_keyboard_set_keys(uint8_t *keys) { for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) usb_keyboard_report->keys[i] = keys[i]; } void usb_keyboard_set_mods(uint8_t mods) { usb_keyboard_report->mods = mods; #endif _add_key_byte(code); } @@ void usb_keyboard_add_mod(uint8_t code) 165,12 131,18 @@ void usb_keyboard_del_code(uint8_t code) void usb_keyboard_del_key(uint8_t code) { for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) { #ifdef NKRO_ENABLE if ((code>>3) < KEYS_MAX) { usb_keyboard_keys[code>>3] &= ~(1<<(code&7)); } #else for (int i = 0; i < KEYS_MAX; i++) { if (usb_keyboard_report->keys[i] == code) { usb_keyboard_report->keys[i] = KB_NO; return; } } #endif } @@ void usb_keyboard_del_mod(uint8_t code) 186,7 158,7 @@ bool usb_keyboard_is_sent(void) bool usb_keyboard_has_key(void) { uint8_t keys = 0; for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) keys |= usb_keyboard_report->keys[i]; for (int i = 0; i < KEYS_MAX; i++) keys |= usb_keyboard_report->keys[i]; return keys ? true : false; } @@ 195,10 167,86 @@ bool usb_keyboard_has_mod(void) return usb_keyboard_report->mods ? true : false; } uint8_t usb_keyboard_get_key(void) { #ifdef NKRO_ENABLE if (usb_keyboard_nkro) { uint8_t i = 0; for (; i < KEYS_MAX && !usb_keyboard_keys[i]; i++); return i<<3 | biton(usb_keyboard_keys[i]); } #endif return usb_keyboard_keys[0]; } void usb_keyboard_print_report(usb_keyboard_report_t *report) { if (!debug_keyboard) return; print("keys: "); for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) { phex(report->keys[i]); print(" "); } for (int i = 0; i < KEYS_MAX; i++) { phex(report->keys[i]); print(" "); } print(" mods: "); phex(report->mods); print("\n"); } static inline int8_t _send_report(usb_keyboard_report_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end) { uint8_t intr_state, timeout; if (!usb_configured()) return -1; intr_state = SREG; cli(); UENUM = endpoint; timeout = UDFNUML + 50; while (1) { // are we ready to transmit? if (UEINTX & (1<<RWAL)) break; SREG = intr_state; // has the USB gone offline? if (!usb_configured()) return -1; // have we waited too long? if (UDFNUML == timeout) return -1; // get ready to try checking again intr_state = SREG; cli(); UENUM = endpoint; } UEDATX = report->mods; UEDATX = 0; for (uint8_t i = keys_start; i < keys_end; i++) { UEDATX = report->keys[i]; } UEINTX = 0x3A; SREG = intr_state; return 0; } static inline void _add_key_byte(uint8_t code) { // TODO: fix ugly code int8_t i = 0; int8_t empty = -1; for (; i < KEYS_MAX; i++) { if (usb_keyboard_keys_prev[i] == code) { usb_keyboard_keys[i] = code; break; } if (empty == -1 && usb_keyboard_keys_prev[i] == 0 && usb_keyboard_keys[i] == 0) { empty = i; } } if (i == KEYS_MAX) { if (empty != -1) { usb_keyboard_keys[empty] = code; } } } static inline void _add_key_bit(uint8_t code) { if ((code>>3) < KEYS_MAX) { usb_keyboard_keys[code>>3] |= 1<<(code&7); } }
M usb_keyboard.h => usb_keyboard.h +24 -15
@@ 6,14 6,26 @@ #include "usb.h" #define KEYBOARD_INTERFACE 0 #define KEYBOARD_ENDPOINT 1 #ifdef USB_12KRO #define KEYBOARD_INTERFACE2 4 #define KEYBOARD_ENDPOINT2 5 #define KBD_INTERFACE 0 #define KBD_ENDPOINT 1 #define KBD_SIZE 8 #define KBD_BUFFER EP_DOUBLE_BUFFER #define KBD_REPORT_KEYS (KBD_SIZE - 2) // secondary keyboard #ifdef NKRO_ENABLE #define KBD2_INTERFACE 4 #define KBD2_ENDPOINT 5 #define KBD2_SIZE 16 #define KBD2_BUFFER EP_DOUBLE_BUFFER #define KBD2_REPORT_KEYS (KBD2_SIZE - 2) #endif #if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS #define KEYS_MAX KBD2_REPORT_KEYS #else #define KEYS_MAX KBD_REPORT_KEYS #endif #define KEYBOARD_SIZE 8 #define KEYBOARD_BUFFER EP_DOUBLE_BUFFER #define BIT_LCTRL (1<<0) @@ #define BIT_LSHIFT (1<<1) 28,13 40,8 @@ #define BIT_LSFT BIT_LSHIFT #define BIT_RSFT BIT_RSHIFT #ifdef USB_12KRO # define KEYBOARD_REPORT_MAX 12 #else # define KEYBOARD_REPORT_MAX 6 #endif typedef struct report { uint8_t keys[KEYBOARD_REPORT_MAX]; uint8_t keys[KEYS_MAX]; uint8_t mods; bool is_sent; @@ } usb_keyboard_report_t; 52,9 59,9 @@ extern uint8_t usb_keyboard_protocol; extern uint8_t usb_keyboard_idle_config; extern uint8_t usb_keyboard_idle_count; extern volatile uint8_t usb_keyboard_leds; extern bool usb_keyboard_nkro; int8_t usb_keyboard_press(uint8_t key, uint8_t modifier); int8_t usb_keyboard_send(void); int8_t usb_keyboard_send_report(usb_keyboard_report_t *report); @@ 64,7 71,7 @@ void usb_keyboard_clear_report(void); void usb_keyboard_clear_keys(void); void usb_keyboard_clear_mods(void); void usb_keyboard_set_keys(uint8_t keys[6]); void usb_keyboard_set_keys(uint8_t *keys); void usb_keyboard_set_mods(uint8_t mods); @@ void usb_keyboard_add_code(uint8_t code); 79,6 86,8 @@ bool usb_keyboard_is_sent(void); bool usb_keyboard_has_key(void); bool usb_keyboard_has_mod(void); uint8_t usb_keyboard_get_key(void); void usb_keyboard_print_report(usb_keyboard_report_t *report); #endif
M usb_mouse.c => usb_mouse.c +4 -2
@@ 59,8 59,10 @@ int8_t usb_mouse_move(int8_t x, int8_t y, int8_t wheel, int8_t hwheel) UEDATX = mouse_buttons; UEDATX = x; UEDATX = y; UEDATX = wheel; UEDATX = hwheel; if (mouse_protocol) { UEDATX = wheel; UEDATX = hwheel; } UEINTX = 0x3A; SREG = intr_state;
M util.c => util.c +2 -0