⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps2kbdmou_ecos.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 4 页
字号:
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },            // 120
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
    { MWKEY_UNKNOWN,    '|' },                      // 125
    // In theory there could also be 126 and 127, but those are unused.
    // But putting them into the table avoids a special case test in the code,
    // for a cost of only eight bytes.
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
};

// Now for the E0 sequences. The standard ones are in the range 0x47 to 0x53
// 0xE0, 0x5B is the Left Windows key. 0x5C would normally be the right one.
// 0xE0, 0x5D is the Menu key. The 
// The Dell has some additional ones for the dvd player, ignored.
// PrintScreen generates a simple sequence 0xE0, 0x2A, 0xE0, 0x37, 0xE0, 0xB7, 0xE0, 0xAA
// Break generates 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5

#define PS2KBD_E0_MIN   0x47
static const MWKEY ps2kbd_e0_map[] = {
    MWKEY_HOME,         // 0x47
    MWKEY_UP,           // 0x48
    MWKEY_PAGEUP,       // 0x49
    MWKEY_UNKNOWN,
    MWKEY_LEFT,         // 0x4B
    MWKEY_UNKNOWN,
    MWKEY_RIGHT,        // 0x4D
    MWKEY_UNKNOWN,
    MWKEY_END,          // 0x4F
    MWKEY_DOWN,         // 0x50
    MWKEY_PAGEDOWN,     // 0x51
    MWKEY_INSERT,       // 0x52
    MWKEY_DELETE,       // 0x53
    MWKEY_UNKNOWN,
    MWKEY_UNKNOWN,
    MWKEY_UNKNOWN,
    MWKEY_UNKNOWN,
    MWKEY_UNKNOWN,
    MWKEY_UNKNOWN,
    MWKEY_UNKNOWN,
    MWKEY_LMETA,        // 0x5B
    MWKEY_RMETA,        // 0x5C
    MWKEY_MENU          // 0x5D
};
#define PS2KBD_E0_MAX   0x5D

// Modifier translations. All modifiers are supported by
// this table, even though the keyboard may not actually
// have all of them.
typedef struct ps2kbd_modifier_entry {
    MWKEY       key;
    MWKEYMOD    modifier;
    int         toggle;
} ps2kbd_modifier_entry;

static const ps2kbd_modifier_entry ps2kbd_modifier_map[] = {
    { MWKEY_LSHIFT,     MWKMOD_LSHIFT,  0 },
    { MWKEY_RSHIFT,     MWKMOD_RSHIFT,  0 },
    { MWKEY_LCTRL,      MWKMOD_LCTRL,   0 },
    { MWKEY_RCTRL,      MWKMOD_RCTRL,   0 },
    { MWKEY_LALT,       MWKMOD_LALT,    0 },
    { MWKEY_RALT,       MWKMOD_RALT,    0 },
    { MWKEY_LMETA,      MWKMOD_LMETA,   0 },
    { MWKEY_RMETA,      MWKMOD_RMETA,   0 },
    { MWKEY_NUMLOCK,    MWKMOD_NUM,     1 },
    { MWKEY_CAPSLOCK,   MWKMOD_CAPS,    1 },
    { MWKEY_ALTGR,      MWKMOD_ALTGR,   0 },
    { MWKEY_SCROLLOCK,  MWKMOD_SCR,     1 },
    { MWKEY_UNKNOWN,    MWKMOD_NONE }
};

static void
ps2kbd_process_scancodes(void)
{
    static int      e0_seen             = 0;
    static MWKEY    pending_up          = MWKEY_UNKNOWN;
    static int      pending_scancode    = 0;
    static int      discard             = 0;
    int scancode;
    int i;
    
    CYG_PRECONDITION(MWKEY_UNKNOWN == ps2kbd_current_key, "There should be no pending key");

    if (MWKEY_UNKNOWN != pending_up) {
        ps2kbd_current_key          = pending_up;
        ps2kbd_current_scancode     = pending_scancode;
        ps2kbd_current_keydown      = 0;
        pending_up                  = MWKEY_UNKNOWN;
        return;
    }
    
    while (MWKEY_UNKNOWN == ps2kbd_current_key) {
        // The ISR will manipulate the scancode buffer directly, so
        // interrupts have to be disabled temporarily.
        scancode = -1;
        cyg_drv_isr_lock();
        if (ps2kbd_scancode_buffer_head != ps2kbd_scancode_buffer_tail) {
            scancode = ps2kbd_scancode_buffer[ps2kbd_scancode_buffer_tail];
            ps2kbd_scancode_buffer_tail = (ps2kbd_scancode_buffer_tail + 1) % PS2KBD_SCANCODE_BUFSIZE;
        }
        cyg_drv_isr_unlock();

        if (scancode == -1) {
            // No more data to be processed.
            break;
        }

        // Are we in one of the special sequences, where bytes should be
        // discarded?
        if (discard > 0) {
            discard -= 1;
            continue;
        }

        // A real scancode has been extracted. Are we in an E0 sequence?
        if (e0_seen) {
            e0_seen = 0;
            ps2kbd_current_keydown = (0 == (scancode & 0x0080));
            scancode &= 0x007F;
            if ((scancode >= PS2KBD_E0_MIN) && (scancode <= PS2KBD_E0_MAX)) {
                ps2kbd_current_key = ps2kbd_e0_map[scancode - PS2KBD_E0_MIN];
                ps2kbd_current_scancode = 0x80 + scancode - PS2KBD_E0_MIN;  // Invent a key scancode
            }
            // We may or may not have a valid keycode at this time, so go
            // around the loop again to check for MWKEY_UNKNOWN
            continue;
        }

        // Is this the start of an E0 sequence?
        if (0x00E0 == scancode) {
            e0_seen = 1;
            continue;
        }

        // How about E1?
        if (0x00E1 == scancode) {
            // For now there is only one key which generates E1 sequences
            ps2kbd_current_key      = MWKEY_BREAK;
            ps2kbd_current_keydown  = 1;
            ps2kbd_current_scancode = 0x00E1;   // Invent another key scancode
            pending_up              = MWKEY_BREAK;
            pending_scancode        = 0x00E1;
            discard = 5;
            return;
        }

        // Must be an ordinary key.
        ps2kbd_current_keydown  = (0 == (scancode & 0x0080));
        scancode &= 0x007F;
        ps2kbd_current_scancode = scancode;
        ps2kbd_current_key      = ps2kbd_keymap[scancode].normal;

        // Detect the modifier keys.
        for (i = 0; MWKEY_UNKNOWN != ps2kbd_modifier_map[i].key; i++) {
            if (ps2kbd_current_key == ps2kbd_modifier_map[i].key) {
                // capslock etc. behave differently. Toggle the current
                // status on the keyup event, ignore key down (because
                // of hardware autorepeat).
                if (ps2kbd_modifier_map[i].toggle) {
                    if (!ps2kbd_current_keydown) {
                        ps2kbd_current_modifiers ^= ps2kbd_modifier_map[i].modifier;
                    }
                } else if (ps2kbd_current_keydown) {
                    ps2kbd_current_modifiers |= ps2kbd_modifier_map[i].modifier;
                } else {
                    ps2kbd_current_modifiers &= ~ps2kbd_modifier_map[i].modifier;
                }
                break;
            }
        }

        // Cope with some of the modifiers.
        if (0 != (ps2kbd_current_modifiers & (MWKMOD_LCTRL | MWKMOD_RCTRL))) {
            // Control key. a-z and A-Z go to ctrl-A - ctrl-Z, i.e. 1 to 26
            // Other characters in the range 64 to 96, e.g. [ and ], also
            // get translated. This includes the A-Z range.
            if ((64 <= ps2kbd_current_key) && (ps2kbd_current_key < 96)) {
                ps2kbd_current_key -= 64;
            } else if (('a' <= ps2kbd_current_key) && (ps2kbd_current_key <= 'z')) {
                ps2kbd_current_key -= 96;
            }
        } else if (ps2kbd_current_modifiers & (MWKMOD_LSHIFT | MWKMOD_RSHIFT)) {
            // Pick up the shift entry from the keymap
            ps2kbd_current_key = ps2kbd_keymap[scancode].shifted;
        }
        
        if (ps2kbd_current_modifiers & MWKMOD_CAPS) {
            // Capslock only affects a-z and A-z
            if ( ('a' <= ps2kbd_current_key) && (ps2kbd_current_key <= 'z')) {
                ps2kbd_current_key = (ps2kbd_current_key -'a') + 'A';
            } else if (('A' <= ps2kbd_current_key) && (ps2kbd_current_key <= 'Z')) {
                ps2kbd_current_key = (ps2kbd_current_key -'A') + 'a';
            }
        }

        // If we have found a real key, the loop will exit.
        // Otherwise try again.
    }
}

static int
PS2Kbd_Open(KBDDEVICE* pkbd)
{
    unsigned char buf[1];
    ps2_initialize();
    buf[0] = KC_KBDC_ENABLE;
    ps2_send_command_wait(KC_CONTROL_NULL, buf, 1, 0);
}

static void
PS2Kbd_Close(void)
{
    unsigned char buf[1];
    buf[0] = KC_KBDC_STANDARD_DISABLE;
    ps2_send_command_wait(KC_CONTROL_NULL, buf, 1, 0);
}

static void
PS2Kbd_GetModifierInfo(MWKEYMOD* modifiers, MWKEYMOD* curmodifiers)
{
    if (NULL != modifiers) {
        *modifiers = MWKMOD_LSHIFT | MWKMOD_RSHIFT | MWKMOD_LCTRL | MWKMOD_RCTRL |
            MWKMOD_LALT | MWKMOD_RALT | MWKMOD_LMETA | MWKMOD_RMETA |
            MWKMOD_NUM | MWKMOD_CAPS | MWKMOD_ALTGR | MWKMOD_SCR;
    }
    if (NULL != curmodifiers) {
        *modifiers = ps2kbd_current_modifiers;
    }
}

// Note: it is assumed that there are no concurrent calls to
// the poll and read functions.
static int
PS2Kbd_Poll(void)
{
    if (MWKEY_UNKNOWN == ps2kbd_current_key) {
        ps2kbd_process_scancodes();
    }
    return MWKEY_UNKNOWN != ps2kbd_current_key;
}

// Return -1 on error, 0 for no data, 1 for a keypress, 2 for a keyrelease.
static int
PS2Kbd_Read(MWKEY* buf, MWKEYMOD* modifiers, MWSCANCODE* scancode)
{
    if (MWKEY_UNKNOWN == ps2kbd_current_key) {
        ps2kbd_process_scancodes();
        if (MWKEY_UNKNOWN == ps2kbd_current_key) {
            return 0;
        }
    }

    if (NULL != buf) {
        *buf = ps2kbd_current_key;
    }
    if (NULL != modifiers) {
        *modifiers = ps2kbd_current_modifiers;
    }
    if (NULL != scancode) {
        *scancode = ps2kbd_current_scancode;
    }
    ps2kbd_current_key = MWKEY_UNKNOWN;
    return ps2kbd_current_keydown ? 1 : 2;
}

KBDDEVICE kbddev = {
    PS2Kbd_Open,
    PS2Kbd_Close,
    PS2Kbd_GetModifierInfo,
    PS2Kbd_Read,
    PS2Kbd_Poll
};

#if 0
// ----------------------------------------------------------------------------
// This code can be used for testing the mouse and keyboard without all
// of microwindows present (although the microwindows headers must still be
// visible).

#include <stdio.h>
#include <ctype.h>
int
main(int argc, char** argv)
{
    PS2Kbd_Open(&kbddev);
    PS2Mouse_Open(&mousedev);
    for ( ; ; ) {
        while (PS2Mouse_Poll()) {
            MWCOORD dx, dy, dz;
            int     buttons;
            PS2Mouse_Read(&dx, &dy, &dz, &buttons);
            printf("Mouse movement: dx %d, dy %d, dz %d, buttons 0x%02x\n", dx, dy, dz, buttons);
        }
        while (PS2Kbd_Poll()) {
            MWKEY       key;
            MWKEYMOD    modifiers;
            MWSCANCODE  scancode;
            int         which;
            which = PS2Kbd_Read(&key, &modifiers, &scancode);
            printf("Keyboard event: %s, key %c (%d) (0x%02x), modifiers 0x%02x, scancode %d (0x%02x)\n",
                   (1 == which) ? "press" : "release", isprint(key) ? key : '?', key, key, modifiers, scancode, scancode);
        }
    }
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -