1 /* Minimal polling PC keyboard driver 2 * - No interrupt 3 * - No LED 4 * - No special keys 5 * 6 * still Enough For Me to type a filename. 7 * 8 * 2003-07 by SONE Takesh 9 * 2004-04 moved by LYH From filo to Etherboot 10 * yhlu (at) tyan.com 11 */ 12 13 #include <gpxe/io.h> 14 #include "console.h" 15 16 static char key_map[][128] = { 17 { 18 "\0\x1b""1234567890-=\b\t" 19 "qwertyuiop[]\r\0as" 20 "dfghjkl;'`\0\\zxcv" 21 "bnm,./\0*\0 \0\0\0\0\0\0" 22 "\0\0\0\0\0\0\0""789-456+1" 23 "230." 24 },{ 25 "\0\x1b""!@#$%^&*()_+\b\t" 26 "QWERTYUIOP{}\r\0AS" 27 "DFGHJKL:\"~\0|ZXCV" 28 "BNM<>?\0\0\0 \0\0\0\0\0\0" 29 "\0\0\0\0\0\0\0""789-456+1" 30 "230." 31 } 32 }; 33 34 static int cur_scan; 35 static unsigned int shift_state; 36 #define SHIFT 1 37 #define CONTROL 2 38 #define CAPS 4 39 40 static int get_scancode(void) 41 { 42 int scan; 43 44 if ((inb(0x64) & 1) == 0) 45 return 0; 46 scan = inb(0x60); 47 48 switch (scan) { 49 case 0x2a: 50 case 0x36: 51 shift_state |= SHIFT; 52 break; 53 case 0xaa: 54 case 0xb6: 55 shift_state &= ~SHIFT; 56 break; 57 case 0x1d: 58 shift_state |= CONTROL; 59 break; 60 case 0x9d: 61 shift_state &= ~CONTROL; 62 break; 63 case 0x3a: 64 shift_state ^= CAPS; 65 break; 66 } 67 68 if (scan & 0x80) 69 return 0; /* ignore break code or 0xe0 etc! */ 70 return scan; 71 } 72 73 static int kbd_havekey(void) 74 { 75 if (!cur_scan) 76 cur_scan = get_scancode(); 77 return cur_scan != 0; 78 } 79 80 static int kbd_ischar(void) 81 { 82 if (!kbd_havekey()) 83 return 0; 84 if (!key_map[shift_state & SHIFT][cur_scan]) { 85 cur_scan = 0; 86 return 0; 87 } 88 return 1; 89 } 90 91 static int kbd_getc(void) 92 { 93 int c; 94 95 while (!kbd_ischar()) 96 ; 97 c = key_map[shift_state & SHIFT][cur_scan]; 98 if (shift_state & (CONTROL | CAPS)) { 99 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { 100 if (shift_state & CONTROL) 101 c &= 0x1f; 102 else if (shift_state & CAPS) 103 c ^= ('A' ^ 'a'); 104 } 105 } 106 cur_scan = 0; 107 return c; 108 } 109 110 struct console_driver pc_kbd_console __console_driver = { 111 .getchar = kbd_getc, 112 }; 113