Home | History | Annotate | Download | only in core
      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