📄 kbd.c
字号:
// Kernel
// Default Keyboard
#include <console.h>
#include <knlcon.h>
#include <knllib.h>
#include <gates.h>
#include <devices.h>
static HDRIVER _this_driver; // driver handle
static _u32 _keyboard_status; // shift, ctrl, alt, etc.
static _u32 _status;
static KBDHANDLER _pfnKeyHandler;
// status flags
#define SF_CAPS 0x00010000
#define SF_SCROLL 0x00020000
#define SF_NUM 0x00040000
#define SF_2A 0x00100000
// key maps
static _u32 _default_keys[] =
{
VK_NULL, VK_ESC, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', VK_BKSP, VK_TAB,
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', VK_CR, VK_LCTRL, 'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
'\'', '`', VK_LSHIFT, '\\', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '/', VK_RSHIFT, VKNUMPAD('*'),
VK_LALT, VK_SP, VK_CAPS, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5,
VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_NUM, VK_SCROLL, VKNUMPAD('7'),
VKNUMPAD('8'), VKNUMPAD('9'), VKNUMPAD('-'), VKNUMPAD('4'),
VKNUMPAD('5'), VKNUMPAD('6'), VKNUMPAD('+'), VKNUMPAD('1'),
VKNUMPAD('2'), VKNUMPAD('3'), VKNUMPAD('0'), VKNUMPAD('.'),
VK_NULL, VK_NULL, VK_NULL, VK_F11, VK_F12, VK_NULL, VK_NULL, VK_NULL
};
static _u32 _shift_keys[] =
{
VK_NULL, VK_ESC, '!', '@', '#', '$', '%', '^',
'&', '*', '(', ')', '_', '+', VK_BKSP, VK_TAB,
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', '{', '}', VK_CR, VK_LCTRL, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
'"', '~', VK_LSHIFT, '|', 'Z', 'X', 'C', 'V',
'B', 'N', 'M', '<', '>', '?', VK_RSHIFT, VKNUMPAD('*'),
VK_LALT, VK_SP, VK_CAPS, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5,
VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_NUM, VK_SCROLL, VKNUMPAD(VK_HOME),
VKNUMPAD(VK_UP), VKNUMPAD(VK_PGDN), VKNUMPAD('-'), VKNUMPAD(VK_LEFT),
VKNUMPAD('5'), VKNUMPAD(VK_RIGHT), VKNUMPAD('+'), VKNUMPAD(VK_END),
VKNUMPAD(VK_DOWN), VKNUMPAD(VK_PGDN), VKNUMPAD(VK_INSERT), VKNUMPAD(VK_DELETE),
VK_NULL, VK_NULL, VK_NULL, VK_F11, VK_F12, VK_NULL, VK_NULL, VK_NULL
};
static void set_leds(void)
{
asm("jmp set_leds_set\n"
"kb_wait: pushl %%eax\n"
"1: inb $0x64,%%al\n"
"testb $0x02,%%al\n"
"jne 1b\n"
"popl %%eax\n"
"ret\n"
"set_leds_set: call kb_wait\n"
"movb $0xed,%%al\n"
"outb %%al,$0x60\n"
"call kb_wait\n"
"movb %%cl,%%al\n"
"outb %%al,$0x60\n"::"c"((_keyboard_status>>4)&7)
);
}
static inline void set_status(_u8 key)
{
_status = (_status&0xffffff00) | key;
}
static inline _u32 get_cursor_keys(_u8 key)
{
switch(key)
{
case 0x37: return VK_PRTSCR;
case 0x52: return VK_INSERT;
case 0x53: return VK_DELETE;
case 0x47: return VK_HOME;
case 0x4f: return VK_END;
case 0x49: return VK_PGUP;
case 0x51: return VK_PGDN;
case 0x4b: return VK_LEFT;
case 0x4d: return VK_RIGHT;
case 0x48: return VK_UP;
case 0x50: return VK_DOWN;
}
return VK_NULL;
}
void onKBD(_u8 key)
{
_u32 code = 0;
SysLock();
switch((_u8)_status)
{
case 0:
if(key==0xe0 || key==0xe1) set_status(key);
else // normal keys
{
int size = sizeof(_default_keys)/sizeof(_u32);
_u32 release = key&0x80 ? VKF_RELEASE : 0;
key &= 0x7f;
if(key>=(_u8)size) code = VK_NULL;
else if(_default_keys[key])
{
code = _default_keys[key];
if(code&VKF_SPECIAL)
{
switch(code)
{
case VK_LSHIFT:
if(release) _keyboard_status&=~KS_LSHIFT;
else _keyboard_status|=KS_LSHIFT;
break;
case VK_RSHIFT:
if(release) _keyboard_status&=~KS_RSHIFT;
else _keyboard_status|=KS_RSHIFT;
break;
case VK_LCTRL:
if(release) _keyboard_status&=~((_keyboard_status&KS_RCTRL?0:KS_CTRL)|KS_LCTRL);
else _keyboard_status|=KS_CTRL|KS_LCTRL;
break;
case VK_LALT:
if(release) _keyboard_status&=~((_keyboard_status&KS_RALT?0:KS_ALT)|KS_LALT);
else _keyboard_status|=KS_ALT|KS_LALT;
break;
case VK_CAPS:
if(_status&SF_CAPS && release) _status&=~SF_CAPS;
else if(!(_status&SF_CAPS) && !release)
{ _keyboard_status^=KS_CAPS; _status|=SF_CAPS; set_leds(); }
else code = VK_NULL;
break;
case VK_SCROLL:
if(_status&SF_SCROLL && release) _status&=~SF_SCROLL;
else if(!(_status&SF_SCROLL) && !release)
{ _keyboard_status^=KS_SCROLL; _status|=SF_SCROLL; set_leds(); }
else code = VK_NULL;
break;
case VK_NUM:
if(_status&SF_NUM && release) _status&=~SF_NUM;
else if(!(_status&SF_NUM) && !release)
{ _keyboard_status^=KS_NUM; _status|=SF_NUM; set_leds(); }
else code = VK_NULL;
break;
default: code = VK_NULL; // keys not supported
}
}
else
{
if((code&VKF_NUMPAD &&
((_keyboard_status&KS_SHIFT && _keyboard_status&KS_NUM) || // numpad + shift
(!(_keyboard_status&KS_SHIFT) && !(_keyboard_status&KS_NUM))) ) ||
(!(code&VKF_NUMPAD) && _keyboard_status&KS_SHIFT))
code = _shift_keys[key];
if((char)code>='a' && (char)code<='z' &&
((!(_keyboard_status&KS_CAPS) && _keyboard_status&KS_SHIFT) || // shift uncaps
(!(_keyboard_status&KS_SHIFT) && _keyboard_status&KS_CAPS)) )
code = _shift_keys[key];
else if((char)code>='A' && (char)code<='Z' && _keyboard_status&KS_CAPS)
code = _default_keys[key];
code |= key<<8; // add scan code
}
}
if(code) code|=release;
}
break;
case 0xe0:
if(key==0x2a) _status|=SF_2A;
else if(_status&SF_2A && key==0xaa) _status&=~SF_2A;
else
{
_u32 release = key&0x80 ? VKF_RELEASE : 0;
key&=0x7f;
code = get_cursor_keys(key);
if(code) code|=VKF_CURSOR;
else
{
switch(key)
{
case 0x35: // '/' in numpad
code = VKNUMPAD('/'); break;
case 0x38: // right alt
code = VK_RALT;
if(release) _keyboard_status&=~((_keyboard_status&KS_LALT?0:KS_ALT)|KS_RALT);
else _keyboard_status|=KS_ALT|KS_RALT;
break;
case 0x1c: // enter in numpad
code = VKNUMPAD(VK_CR); break;
case 0x1d: // right ctrl
code = VK_RCTRL;
if(release) _keyboard_status&=~((_keyboard_status&KS_LCTRL?0:KS_CTRL)|KS_RCTRL);
else _keyboard_status|=KS_CTRL|KS_RCTRL;
break;
case 0x5b: // left win
code = VK_LWIN;
if(release) _keyboard_status&=~KS_LWIN;
else _keyboard_status|=KS_LWIN;
break;
case 0x5c: // right win
code = VK_RWIN;
if(release) _keyboard_status&=~KS_RWIN;
else _keyboard_status|=KS_RWIN;
break;
case 0x5d: // app
code = VK_APP; break;
default: code = VK_NULL;
}
}
if(code) code|=release;
}
set_status(0);
break;
case 0xe1:
if(key==0x1d) set_status(0x1d);
else if(key==0x9d) set_status(0x9d);
else set_status(0);
break;
case 0x1d:
if(key==0x45) set_status(0x45);
else set_status(0);
break;
case 0x45:
if(key==0xe1) set_status(0xe1);
else set_status(0);
break;
case 0x9d:
if(key==0xc5) code = VK_BREAK;
set_status(0);
}
SysUnlock();
if(code && _pfnKeyHandler) (*_pfnKeyHandler)(code);
}
void irq_kbd(void);
_u32 kbdGetStatus(void)
{
return _keyboard_status;
}
void kbdSetStatus(_u32 status)
{
SysLock();
_keyboard_status = status;
set_leds();
SysUnlock();
}
KBDHANDLER kbdGetHandler(void)
{
return _pfnKeyHandler;
}
void kbdSetHandler(KBDHANDLER pHandler)
{
SysLock();
_pfnKeyHandler = pHandler;
SysUnlock();
}
void InstallKeyboard(void)
{
_keyboard_status = 0;
_status = 0;
_pfnKeyHandler = NULL;
set_leds();
SetIRQ(1, (_u32)irq_kbd);
}
static long __syscall ioctrl(HDEVICE hDevice, _u32 cmd, void* in_buf, _u32 in_len, void* out_buf, _u32 out_len, _u32* trans_len)
{
switch(cmd)
{
case DEV_IOCTRL_INITIALIZE: return 0;
case DEV_IOCTRL_READ: return 0;
case DEV_IOCTRL_WRITE: return 0;
}
return DEVICE_MAKEERR(DEVERR_BADCMD);
}
static long OnLoad(HDRIVER hDrv)
{
_this_driver = hDrv;
return 0;
}
static long OnUnload(void)
{
return 0;
}
static long OnInstallDevices(void)
{
if(!RegisterDevice(_this_driver, DEV_TYPE_CHAR, 0, 1, "console", ioctrl, 0, 0))
{
kprintf("console: device registering failed\n");
return DEVICE_MAKEERR(DEVERR_INTERNAL);
}
InstallKeyboard();
return 0;
}
long __syscall drvDefaultConsole(_u32 cmd, _u32 param1, _u32 param2)
{
switch(cmd)
{
case DRV_SVC_LOAD: return OnLoad((HDRIVER)param1);
case DRV_SVC_UNLOAD: return OnUnload();
case DRV_SVC_INSTALLDEVICES:
return OnInstallDevices();
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -