~ruther/qmk_firmware

23c686ad46d325d054b83734cc8e89c4fb5e2572 — tmk 14 years ago a28a2a6
Exceptional handling for PS/2 scan code set 2

changed names which does not comply to C spec.(underscore prefix names)
2 files changed, 150 insertions(+), 116 deletions(-)

M ps2_usb/keymap.c
M ps2_usb/matrix.c
M ps2_usb/keymap.c => ps2_usb/keymap.c +3 -3
@@ 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
    ),
};

M ps2_usb/matrix.c => ps2_usb/matrix.c +147 -113
@@ 29,40 29,39 @@
 *      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