📄 kbd.c
字号:
/*============================================================================KEYBOARD ROUTINESEXPORTS:void keyboard_irq(void);void init_keyboard(void);============================================================================*/#include <conio.h> /* KEY_nnn */#include <x86.h> /* outportb(), inportb() */#include "_krnl.h" /* MAX_VC *//* IMPORTSfrom VIDEO.C */extern console_t _vc[];void select_vc(unsigned which_vc);void putch(unsigned c);/* from MAIN.C */void kprintf(const char *fmt, ...);/* "raw" set 1 scancodes from PC keyboard. Keyboard info here:http://www.execpc.com/~geezer/osd/kbd */#define RAW1_LEFT_CTRL 0x1D#define RAW1_RIGHT_CTRL 0x1D /* same as left */#define RAW1_LEFT_SHIFT 0x2A#define RAW1_RIGHT_SHIFT 0x36#define RAW1_LEFT_ALT 0x38#define RAW1_RIGHT_ALT 0x38 /* same as left */#define RAW1_CAPS_LOCK 0x3A#define RAW1_F1 0x3B#define RAW1_F2 0x3C#define RAW1_F3 0x3D#define RAW1_F4 0x3E#define RAW1_F5 0x3F#define RAW1_F6 0x40#define RAW1_F7 0x41#define RAW1_F8 0x42#define RAW1_F9 0x43#define RAW1_F10 0x44#define RAW1_NUM_LOCK 0x45#define RAW1_SCROLL_LOCK 0x46#define RAW1_F11 0x57#define RAW1_F12 0x58#define KBD_BUF_SIZE 64/**********************************************************************************************************************************************************/static void reboot(void){ unsigned temp; disable();/* flush the keyboard controller */ do { temp = inportb(0x64); if((temp & 0x01) != 0) { (void)inportb(0x60); continue; } } while((temp & 0x02) != 0);/* pulse the CPU reset line */ outportb(0x64, 0xFE);/* ...and if that didn't work, just halt */ while(1) /* nothing */;}/**********************************************************************************************************************************************************/static void write_kbd(unsigned adr, unsigned data){ unsigned long timeout; unsigned stat;/* Linux code didn't have a timeout here... */ for(timeout = 500000L; timeout != 0; timeout--) { stat = inportb(0x64);/* loop until 8042 input buffer empty */ if((stat & 0x02) == 0) break; } if(timeout != 0) outportb(adr, data);}/**********************************************************************************************************************************************************/static unsigned convert(unsigned key){ static const unsigned char set1_map[] = {/* 00 */0, 0x1B, '1', '2', '3', '4', '5', '6',/* 08 */'7', '8', '9', '0', '-', '=', '\b', '\t',/* 10 */'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',/* 1Dh is left Ctrl *//* 18 */'o', 'p', '[', ']', '\n', 0, 'a', 's',/* 20 */'d', 'f', 'g', 'h', 'j', 'k', 'l', ';',/* 2Ah is left Shift *//* 28 */'\'', '`', 0, '\\', 'z', 'x', 'c', 'v',/* 36h is right Shift *//* 30 */'b', 'n', 'm', ',', '.', '/', 0, 0,/* 38h is left Alt, 3Ah is Caps Lock *//* 38 */0, ' ', 0, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,/* 45h is Num Lock, 46h is Scroll Lock *//* 40 */KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,0, 0, KEY_HOME,/* 48 */KEY_UP, KEY_PGUP,'-', KEY_LFT,'5', KEY_RT, '+', KEY_END,/* 50 */KEY_DN, KEY_PGDN,KEY_INS,KEY_DEL,0, 0, 0, KEY_F11,/* 58 */KEY_F12 }; static unsigned short kbd_status, saw_break_code;/**/ unsigned short temp;/* check for break key (i.e. a key is released) */ if(key >= 0x80) { saw_break_code = 1; key &= 0x7F; }/* the only break codes we're interested in are Shift, Ctrl, Alt */ if(saw_break_code) { if(key == RAW1_LEFT_ALT || key == RAW1_RIGHT_ALT) kbd_status &= ~KBD_META_ALT; else if(key == RAW1_LEFT_CTRL || key == RAW1_RIGHT_CTRL) kbd_status &= ~KBD_META_CTRL; else if(key == RAW1_LEFT_SHIFT || key == RAW1_RIGHT_SHIFT) kbd_status &= ~KBD_META_SHIFT; saw_break_code = 0; return 0; }/* it's a make key: check the "meta" keys, as above */ if(key == RAW1_LEFT_ALT || key == RAW1_RIGHT_ALT) { kbd_status |= KBD_META_ALT; return 0; } if(key == RAW1_LEFT_CTRL || key == RAW1_RIGHT_CTRL) { kbd_status |= KBD_META_CTRL; return 0; } if(key == RAW1_LEFT_SHIFT || key == RAW1_RIGHT_SHIFT) { kbd_status |= KBD_META_SHIFT; return 0; }/* Scroll Lock, Num Lock, and Caps Lock set the LEDs. These keyshave on-off (toggle or XOR) action, instead of momentary action */ if(key == RAW1_SCROLL_LOCK) { kbd_status ^= KBD_META_SCRL; goto LEDS; } if(key == RAW1_NUM_LOCK) { kbd_status ^= KBD_META_NUM; goto LEDS; } if(key == RAW1_CAPS_LOCK) { kbd_status ^= KBD_META_CAPS;LEDS: write_kbd(0x60, 0xED); /* "set LEDs" command */ temp = 0; if(kbd_status & KBD_META_SCRL) temp |= 1; if(kbd_status & KBD_META_NUM) temp |= 2; if(kbd_status & KBD_META_CAPS) temp |= 4; write_kbd(0x60, temp); /* bottom 3 bits set LEDs */ return 0; }/* ignore invalid scan codes */ if(key >= sizeof(set1_map) / sizeof(set1_map[0])) return 0;/* convert raw scancode in key to unshifted ASCII in temp */ temp = set1_map[key];/* defective keyboard? non-US keyboard? more than 104 keys? */ if(temp == 0) return temp;/* handle the three-finger salute */ if((kbd_status & KBD_META_CTRL) && (kbd_status & KBD_META_ALT) && (temp == KEY_DEL)) { kprintf("\n""\x1B[42;37;1m""*** rebooting!"); reboot(); }/* I really don't know what to do yet with Alt, Ctrl, etc. -- punt */ return temp;}/**********************************************************************************************************************************************************/void keyboard_irq(void){ unsigned key, i;/* get scancode from port 0x60 */ key = inportb(0x60);/* if it's F1, F2 etc. switch to the appropriate virtual console */ switch(key) { case RAW1_F1: i = 0; goto SWITCH_VC; case RAW1_F2: i = 1; goto SWITCH_VC; case RAW1_F3: i = 2; goto SWITCH_VC; case RAW1_F4: i = 3; goto SWITCH_VC; case RAW1_F5: i = 4; goto SWITCH_VC; case RAW1_F6: i = 5; goto SWITCH_VC; case RAW1_F7: i = 6; goto SWITCH_VC; case RAW1_F8: i = 7; goto SWITCH_VC; case RAW1_F9: i = 8; goto SWITCH_VC; case RAW1_F10: i = 9; goto SWITCH_VC; case RAW1_F11: i = 10; goto SWITCH_VC; case RAW1_F12: i = 11;SWITCH_VC: select_vc(i); break; default: i = convert(key); if(i != 0) putch(i); break; }/* reset hardware interrupt at 8259 chip */ outportb(0x20, 0x20);}/**********************************************************************************************************************************************************/void init_keyboard(void){ static unsigned char buffers[KBD_BUF_SIZE * MAX_VC];/**/ int i; for(i = 0; i < MAX_VC; i++) { _vc[i].keystrokes.data = buffers + KBD_BUF_SIZE * i; _vc[i].keystrokes.size = KBD_BUF_SIZE; } kprintf("init_kbd: %u buffers, %u bytes each\n", MAX_VC, KBD_BUF_SIZE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -