| /* Minimal polling PC keyboard driver | |
| * - No interrupt | |
| * - No LED | |
| * - No special keys | |
| * | |
| * still Enough For Me to type a filename. | |
| * | |
| * 2003-07 by SONE Takesh | |
| * 2004-04 moved by LYH From filo to Etherboot | |
| * yhlu@tyan.com | |
| */ | |
| #include <ipxe/io.h> | |
| #include <ipxe/console.h> | |
| static char key_map[][128] = { | |
| { | |
| "\0\x1b""1234567890-=\b\t" | |
| "qwertyuiop[]\r\0as" | |
| "dfghjkl;'`\0\\zxcv" | |
| "bnm,./\0*\0 \0\0\0\0\0\0" | |
| "\0\0\0\0\0\0\0""789-456+1" | |
| "230." | |
| },{ | |
| "\0\x1b""!@#$%^&*()_+\b\t" | |
| "QWERTYUIOP{}\r\0AS" | |
| "DFGHJKL:\"~\0|ZXCV" | |
| "BNM<>?\0\0\0 \0\0\0\0\0\0" | |
| "\0\0\0\0\0\0\0""789-456+1" | |
| "230." | |
| } | |
| }; | |
| static int cur_scan; | |
| static unsigned int shift_state; | |
| #define SHIFT 1 | |
| #define CONTROL 2 | |
| #define CAPS 4 | |
| static int get_scancode(void) | |
| { | |
| int scan; | |
| if ((inb(0x64) & 1) == 0) | |
| return 0; | |
| scan = inb(0x60); | |
| switch (scan) { | |
| case 0x2a: | |
| case 0x36: | |
| shift_state |= SHIFT; | |
| break; | |
| case 0xaa: | |
| case 0xb6: | |
| shift_state &= ~SHIFT; | |
| break; | |
| case 0x1d: | |
| shift_state |= CONTROL; | |
| break; | |
| case 0x9d: | |
| shift_state &= ~CONTROL; | |
| break; | |
| case 0x3a: | |
| shift_state ^= CAPS; | |
| break; | |
| } | |
| if (scan & 0x80) | |
| return 0; /* ignore break code or 0xe0 etc! */ | |
| return scan; | |
| } | |
| static int kbd_havekey(void) | |
| { | |
| if (!cur_scan) | |
| cur_scan = get_scancode(); | |
| return cur_scan != 0; | |
| } | |
| static int kbd_ischar(void) | |
| { | |
| if (!kbd_havekey()) | |
| return 0; | |
| if (!key_map[shift_state & SHIFT][cur_scan]) { | |
| cur_scan = 0; | |
| return 0; | |
| } | |
| return 1; | |
| } | |
| static int kbd_getc(void) | |
| { | |
| int c; | |
| while (!kbd_ischar()) | |
| ; | |
| c = key_map[shift_state & SHIFT][cur_scan]; | |
| if (shift_state & (CONTROL | CAPS)) { | |
| if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { | |
| if (shift_state & CONTROL) | |
| c &= 0x1f; | |
| else if (shift_state & CAPS) | |
| c ^= ('A' ^ 'a'); | |
| } | |
| } | |
| cur_scan = 0; | |
| return c; | |
| } | |
| struct console_driver pc_kbd_console __console_driver = { | |
| .getchar = kbd_getc, | |
| }; |