]> git.friedersdorff.com Git - max/tmk_keyboard.git/commitdiff
add build option: NKRO_ENABLE(remove: USB_12KRO)
authortmk <nobody@nowhere>
Tue, 7 Dec 2010 16:47:57 +0000 (01:47 +0900)
committertmk <nobody@nowhere>
Tue, 7 Dec 2010 16:57:55 +0000 (01:57 +0900)
12 files changed:
Makefile.common
README
USB_NKRO.txt [new file with mode: 0644]
hhkb/Makefile
hhkb/keymap.c
key_process.c
tmk.c
usb.c [changed mode: 0644->0755]
usb_keyboard.c
usb_keyboard.h
usb_mouse.c
util.c

index 7f3f9ae50aafb7ab0bae40617bc4b17dbd48f768..d212424360c39552c759d2fd2467cbae6dc7e11b 100644 (file)
@@ -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
 
 
diff --git a/README b/README
index 4c19ddba3b6de0eac320bed641fc29a6e6a8f5f7..57bce575c725bece2dd8ad5a865138fe0c03aac9 100644 (file)
--- a/README
+++ b/README
@@ -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
diff --git a/USB_NKRO.txt b/USB_NKRO.txt
new file mode 100644 (file)
index 0000000..9bd8f70
--- /dev/null
@@ -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
index c248a67588d0f5085211870f11ba2d6691f8a618..bf5d75ee9f786566467f7629bfd3dac82e00e148 100644 (file)
 # 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
index 42a830c527d72c8bddb598ea1ea18c07c5679726..fd9bcce8a23cb0c39b9938346d5061ad95214ea3 100644 (file)
@@ -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)
      * ,-----------------------------------------------------------.
index c23d17277bbc0510c66721aa55f461a887ee7369..bb1bca02d7521dacda17f5b72e0e128509e2ec57 100644 (file)
@@ -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();
diff --git a/tmk.c b/tmk.c
index f7042bd6fbe2754267d8d48e0c41c72f4c7be1b1..b4f76f5d4ac1d69bcc712042fea77fdfb3ad94c3 100644 (file)
--- a/tmk.c
+++ b/tmk.c
@@ -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
diff --git a/usb.c b/usb.c
old mode 100644 (file)
new mode 100755 (executable)
index e633b96..215f05d
--- a/usb.c
+++ b/usb.c
@@ -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();
index 3e13ae4e36d8967656e8cb866c46bf766dd26516..7055a653fb6d057afbe8472205573b26e4567887 100644 (file)
@@ -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);
+    }
+}
+
index 872e2afc7215cf7b5d6c93fbe22088a0012d2ffd..88a641f767511ca447634ccd3421b59ad55db46a 100644 (file)
@@ -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)
 #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
index dd5d0b0ac36bff64425b83b7b82d41d64a0b59d6..98292bdd849b556f7aab509176f02cc4b97467ca 100644 (file)
@@ -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;
diff --git a/util.c b/util.c
index b02d077cc3644277288cbe2033dcb966f28f0366..efc7c14818e6b75c7f9ef9e61bd17978a9ef2d66 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,5 +1,6 @@
 #include "util.h"
 
+// bit population
 int bitpop(uint8_t bits)
 {
     int c;
@@ -8,6 +9,7 @@ int bitpop(uint8_t bits)
     return c;
 }
 
+// most significant on-bit
 int biton(uint8_t bits)
 {
     int n = 0;