]> git.friedersdorff.com Git - max/tmk_keyboard.git/commitdiff
Exceptional handling for PS/2 scan code set 2
authortmk <nobody@nowhere>
Mon, 24 Jan 2011 15:53:49 +0000 (00:53 +0900)
committertmk <nobody@nowhere>
Mon, 24 Jan 2011 15:53:49 +0000 (00:53 +0900)
changed names which does not comply to C spec.(underscore prefix names)

ps2_usb/keymap.c
ps2_usb/matrix.c

index f38784d1f538347a7cc0677a8fc9d17f11ec6908..47db18bfa189f33c55e05ec8f02755f6fabfcb46 100644 (file)
@@ -17,7 +17,7 @@
 // Convert physical keyboard layout to matrix array.
 // This is a macro to define keymap easily in keyboard layout form.
 #define KEYMAP( \
-    K76,  K05,K06,K04,K0C, K03,K0B,K83,K0A, K01,K09,K78,K07, KFE,K7E,KFF,      KB7,KBF,KDE, \
+    K76,  K05,K06,K04,K0C, K03,K0B,K83,K0A, K01,K09,K78,K07, KFC,K7E,KFE,      KB7,KBF,KDE, \
     K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
     K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA,  K6C,K75,K7D,     \
     K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,    K5A,               K6B,K73,K74,K79, \
@@ -55,7 +55,7 @@
     { KB_NO,    KB_NO,    KB_NO,    KB_NO,    KB_NO,    KB_NO,    KB_NO,    KB_NO    }, \
     { KB_NO,    KB_##KE9, KB_NO,    KB_##KEB, KB_##KEC, KB_NO,    KB_NO,    KB_NO    }, \
     { KB_##KF0, KB_##KF1, KB_##KF2, KB_NO,    KB_##KF4, KB_##KF5, KB_NO,    KB_NO    }, \
-    { KB_NO,    KB_NO,    KB_##KFA, KB_NO,    KB_NO,    KB_##KFD, KB_##KFE, KB_##KFF }, \
+    { KB_NO,    KB_NO,    KB_##KFA, KB_NO,    KB_##KFC, KB_##KFD, KB_##KFE, KB_NO    }, \
 }
 
 
@@ -161,7 +161,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
     ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F8,  F10, F11, F12, BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
     TAB, NO,  NO,  NO,  NO,  NO,  HOME,PGDN,PGUP,END, NO,  NO,  NO,  BSLS,     DEL, END, PGDN,    P7,  P8,  P9,
     CAPS,NO,  NO,  NO,  NO,  NO,  LEFT,DOWN,UP,  RGHT,NO,  NO,       ENT,                         P4,  P5,  P6,  PPLS,
-    LSFT,VOLD,VOLU,MUTE,NO,  NO,  HOME,PGUP,PGDN,END, FN1,           RSFT,          UP,           P1,  P2,  P3,
+    LSFT,VOLD,VOLU,MUTE,NO,  NO,  HOME,PGDN,PGUP,END, FN1,           RSFT,          UP,           P1,  P2,  P3,
     LCTL,LGUI,LALT,          SPC,                     RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PENT
     ),
 };
index 366568d681f3f51f84eb5c1992b7b3b7d43fe9b2..aaf89719efb942bab9dff61050bc69fca8deda4a 100644 (file)
  *      8bit
  *    ---------
  *  0|         |
- *  :|   XX    | 00-7F for normal codes
+ *  :|   XX    | 00-7F for normal codes(without E0-prefix)
  *  f|_________|
  * 10|         |
  *  :|  E0 XX  | 80-FF for E0-prefix codes(use (XX|0x80) as code)
  * 1f|         |
  *    ---------
  * exceptions:
- * 0x83: F8(normal code placed beyond 0x7F)
- * 0xFE: PrintScreen
- * 0xFF: Puause/Break
+ * 83:    F8[0x83](normal codes but > 0x7F)
+ * FC:    PrintScreen[E0 7C or 84]
+ * FE:    Puause
  */
-#define _PRINT_SCREEN   (0xFE)
-#define _PAUSE_BREAK    (0xFF)
-#define _ROW(code)      (code>>3)
-#define _COL(code)      (code&0x07)
+#define F8             (0x83)
+#define PRINT_SCREEN   (0xFC)
+#define PAUSE          (0xFE)
+#define ROW(code)      (code>>3)
+#define COL(code)      (code&0x07)
 
-static bool _matrix_is_modified = false;
+static bool is_modified = false;
 
 // matrix state buffer(1:on, 0:off)
 #if (MATRIX_COLS <= 8)
-static uint8_t *matrix;
-static uint8_t _matrix0[MATRIX_ROWS];
+static uint8_t matrix[MATRIX_ROWS];
 #else
-static uint16_t *matrix;
-static uint16_t _matrix0[MATRIX_ROWS];
+static uint16_t matrix[MATRIX_ROWS];
 #endif
 
 #ifdef MATRIX_HAS_GHOST
 static bool matrix_has_ghost_in_row(uint8_t row);
 #endif
-static void _matrix_make(uint8_t code);
-static void _matrix_break(uint8_t code);
-static void _ps2_reset(void);
-static void _ps2_set_leds(uint8_t leds);
+static void matrix_make(uint8_t code);
+static void matrix_break(uint8_t code);
+static void ps2_reset(void);
+static void ps2_set_leds(uint8_t leds);
 
 
 inline
@@ -82,38 +81,96 @@ void matrix_init(void)
     print_enable = true;
     ps2_host_init();
 
-    _ps2_reset();
+    ps2_reset();
 
     // flush LEDs
-    _ps2_set_leds(1<<PS2_LED_NUM_LOCK);
+    ps2_set_leds(1<<PS2_LED_NUM_LOCK);
     _delay_ms(100);
-    _ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK);
+    ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK);
     _delay_ms(100);
-    _ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK|1<<PS2_LED_SCROLL_LOCK);
+    ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK|1<<PS2_LED_SCROLL_LOCK);
     _delay_ms(300);
-    _ps2_set_leds(0x00);
+    ps2_set_leds(0x00);
     
     // initialize matrix state: all keys off
-    for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
-    matrix = _matrix0;
+    for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
 
     return;
 }
 
+/*
+ * PS/2 Scan Code Set 2: Exceptional Handling
+ *
+ * There are several keys to be handled exceptionally.
+ * The scan code for these keys are varied or prefix/postfix'd
+ * depending on modifier key state.
+ *
+ * References:
+ *     http://www.microsoft.com/whdc/archive/scancode.mspx
+ *     http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc
+ *
+ *
+ * Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left:
+ *     Num Lock: off
+ *     modifiers | make                      | break
+ *     ----------+---------------------------+----------------------
+ *     Ohter     |                    <make> | <break>
+ *     LShift    | E0 F0 12           <make> | <break>  E0 12
+ *     RShift    | E0 F0 59           <make> | <break>  E0 59
+ *     L+RShift  | E0 F0 12  E0 F0 59 <make> | <break>  E0 59 E0 12
+ *
+ *     Num Lock: on
+ *     modifiers | make                      | break
+ *     ----------+---------------------------+----------------------
+ *     Other     | E0 12              <make> | <break>  E0 F0 12
+ *     Shift'd   |                    <make> | <break>
+ *
+ *     Handling: ignore these prefix/postfix codes
+ *
+ *
+ * Keypad-/:
+ *     modifiers | make                      | break
+ *     ----------+---------------------------+----------------------
+ *     Ohter     |                    <make> | <break>
+ *     LShift    | E0 F0 12           <make> | <break>  E0 12
+ *     RShift    | E0 F0 59           <make> | <break>  E0 59
+ *     L+RShift  | E0 F0 12  E0 F0 59 <make> | <break>  E0 59 E0 12
+ *
+ *     Handling: ignore these prefix/postfix codes
+ *
+ *
+ * PrintScreen:
+ *     With hoding down modifiers, the scan code is sent as following:
+ *
+ *     modifiers | make         | break
+ *     ----------+--------------+-----------------------------------
+ *     Other     | E0 12  E0 7C | E0 F0 7C  E0 F0 12
+ *     Shift'd   |        E0 7C | E0 F0 7C
+ *     Control'd |        E0 7C | E0 F0 7C
+ *     Alt'd     |           84 | F0 84
+ *
+ *     Handling: ignore prefix/postfix codes and treat both scan code
+ *               E0 7C and 84 as PrintScreen.
+ *
+ * Pause:
+ *     With hoding down modifiers, the scan code is sent as following:
+ *
+ *     modifiers | make(no break code)
+ *     ----------+--------------------------------------------------
+ *     no mods   | E1 14 77 E1 F0 14 F0 77
+ *     Control'd | E0 7E E0 F0 7E
+ *
+ *     Handling: treat these two code sequence as Pause
+ *
+ */
 uint8_t matrix_scan(void)
 {
 
     static enum {
         INIT,
-        BREAK,
+        F0,
         E0,
         E0_F0,
-        // states for PrintScreen
-        E0_12,
-        E0_12_E0,
-        E0_F0_7C,
-        E0_F0_7C_E0,
-        E0_F0_7C_E0_F0,
         // states for Pause/Break
         E1,
         E1_14,
@@ -125,15 +182,16 @@ uint8_t matrix_scan(void)
     } state = INIT;
 
 
-    _matrix_is_modified = false;
+    is_modified = false;
 
     // Pause/Break off(PS/2 has no break for this key)
-    if (matrix_is_on(_ROW(_PAUSE_BREAK), _COL(_PAUSE_BREAK))) {
-        _matrix_break(_PAUSE_BREAK);
+    if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) {
+        matrix_break(PAUSE);
     }
 
     uint8_t code;
     while ((code = ps2_host_recv())) {
+debug_hex(code); debug(" ");
         switch (state) {
             case INIT:
                 switch (code) {
@@ -141,113 +199,88 @@ uint8_t matrix_scan(void)
                         state = E0;
                         break;
                     case 0xF0:  // break code
-                        state = BREAK;
+                        state = F0;
                         break;
                     case 0xE1:  // Pause/Break
                         state = E1;
                         break;
+                    case 0x83:  // F8
+                        matrix_make(F8);
+                        state = INIT;
+                        break;
+                    case 0x84:  // PrintScreen
+                        matrix_make(PRINT_SCREEN);
+                        state = INIT;
+                        break;
                     default:    // normal key make
                         if (code < 0x80) {
-                            _matrix_make(code);
+                            matrix_make(code);
                         } else {
-                            debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
+                            debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n");
                         }
                         state = INIT;
                 }
                 break;
             case E0:
                 switch (code) {
-                    case 0x12:  // PrintScreen(make)
-                        state = E0_12;
-                        break;
-                    case 0x7C:  // PrintScreen(typematic)
+                    case 0x12:  // postfix/postfix code for exceptional keys
+                    case 0x59:  // postfix/postfix code for exceptional keys
                         // ignore
                         state = INIT;
                         break;
+                    case 0x7E:  // former part of Control-Pause[E0 7E  E0 F0 7E]
+                        matrix_make(PAUSE);
+                        state = INIT;
+                        break;
                     case 0xF0:  // E0 break
                         state = E0_F0;
                         break;
                     default:    // E0 make
                         if (code < 0x80) {
-                            _matrix_make(code|0x80);
-                        } else {
-                            debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
-                        }
-                        state = INIT;
-                }
-                break;
-            case BREAK:
-                if (code < 0x80) {
-                    _matrix_break(code);
-                } else {
-                    debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
-                }
-                state = INIT;
-                break;
-            case E0_F0: // E0 break
-                switch (code) {
-                    case 0x7C:
-                        state = E0_F0_7C;
-                        break;
-                    default:
-                        if (code < 0x80) {
-                            _matrix_break(code|0x80);
+                            matrix_make(code|0x80);
                         } else {
-                            debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
+                            debug("unexpected scan code at E0: "); debug_hex(code); debug("\n");
                         }
                         state = INIT;
                 }
                 break;
-            /* PrintScreen(make) */
-            case E0_12:
+            case F0:
                 switch (code) {
-                    case 0xE0:
-                        state = E0_12_E0;
-                        break;
-                    default:
-                        state = INIT;
-                }
-                break;
-            case E0_12_E0:
-                switch (code) {
-                    case 0x7C:
-                        _matrix_make(_PRINT_SCREEN);
+                    case 0x83:
+                        matrix_break(F8);
                         state = INIT;
                         break;
-                    default:
+                    case 0x84:
+                        matrix_break(PRINT_SCREEN);
                         state = INIT;
-                }
-                break;
-            /* PrintScreen(break) */
-            case E0_F0_7C:
-                switch (code) {
-                    case 0xE0:
-                        state = E0_F0_7C_E0;
                         break;
                     default:
-                        state = INIT;
+                    if (code < 0x80) {
+                        matrix_break(code);
+                    } else {
+                        debug("unexpected scan code at F0: "); debug_hex(code); debug("\n");
+                    }
+                    state = INIT;
                 }
                 break;
-            case E0_F0_7C_E0:
-                switch (code) {
-                    case 0xF0:
-                        state = E0_F0_7C_E0_F0;
-                        break;
-                    default:
-                        state = INIT;
-                }
-                break;
-            case E0_F0_7C_E0_F0:
+            case E0_F0: // E0 break
                 switch (code) {
-                    case 0x12:
-                        _matrix_break(_PRINT_SCREEN);
+                    case 0x12:  // postfix/postfix code for exceptional keys
+                    case 0x59:  // postfix/postfix code for exceptional keys
+                    case 0x7E:  // latter part of Control-Pause[E0 7E  E0 F0 7E]
+                        // ignore
                         state = INIT;
                         break;
                     default:
+                        if (code < 0x80) {
+                            matrix_break(code|0x80);
+                        } else {
+                            debug("unexpected scan code at E0_F0: "); debug_hex(code); debug("\n");
+                        }
                         state = INIT;
                 }
                 break;
-            /* Pause/Break */
+            /* Pause */
             case E1:
                 switch (code) {
                     case 0x14:
@@ -305,7 +338,7 @@ uint8_t matrix_scan(void)
             case E1_14_77_E1_F0_14_F0:
                 switch (code) {
                     case 0x77:
-                        _matrix_make(_PAUSE_BREAK);
+                        matrix_make(PAUSE);
                         state = INIT;
                         break;
                     default:
@@ -317,6 +350,7 @@ uint8_t matrix_scan(void)
         }
     }
 
+    // handle LED indicators
     static uint8_t prev_leds = 0;
     if (prev_leds != usb_keyboard_leds) {
         uint8_t leds = 0;
@@ -327,7 +361,7 @@ uint8_t matrix_scan(void)
         if (usb_keyboard_leds&(1<<USB_LED_CAPS_LOCK))
             leds |= (1<<PS2_LED_CAPS_LOCK);
 
-        _ps2_set_leds(leds);
+        ps2_set_leds(leds);
         prev_leds = usb_keyboard_leds;
     }
 
@@ -336,7 +370,7 @@ uint8_t matrix_scan(void)
 
 bool matrix_is_modified(void)
 {
-    return _matrix_is_modified;
+    return is_modified;
 }
 
 inline
@@ -422,24 +456,24 @@ static bool matrix_has_ghost_in_row(uint8_t row)
 
 
 inline
-static void _matrix_make(uint8_t code)
+static void matrix_make(uint8_t code)
 {
-    if (!matrix_is_on(_ROW(code), _COL(code))) {
-        matrix[_ROW(code)] |= 1<<_COL(code);
-        _matrix_is_modified = true;
+    if (!matrix_is_on(ROW(code), COL(code))) {
+        matrix[ROW(code)] |= 1<<COL(code);
+        is_modified = true;
     }
 }
 
 inline
-static void _matrix_break(uint8_t code)
+static void matrix_break(uint8_t code)
 {
-    if (matrix_is_on(_ROW(code), _COL(code))) {
-        matrix[_ROW(code)] &= ~(1<<_COL(code));
-        _matrix_is_modified = true;
+    if (matrix_is_on(ROW(code), COL(code))) {
+        matrix[ROW(code)] &= ~(1<<COL(code));
+        is_modified = true;
     }
 }
 
-static void _ps2_reset(void)
+static void ps2_reset(void)
 {
     ps2_host_send(0xFF);
     ps2_host_recv(); // 0xFA
@@ -447,7 +481,7 @@ static void _ps2_reset(void)
     _delay_ms(1000);
 }
 
-static void _ps2_set_leds(uint8_t leds)
+static void ps2_set_leds(uint8_t leds)
 {
         ps2_host_send(0xED);
         ps2_host_recv();        // 0xFA