📄 ps2kbdmou_ecos.c
字号:
{ 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 + -