#include "types.h" #include "x86.h" #include "defs.h" #include "kbd.h" #include "input.h" int kbdgetc(void) { static uint shift; static uchar *charcode[4] = { normalmap, shiftmap, ctlmap, ctlmap }; uint st, data, c; st = inb(KBSTATP); if((st & KBS_DIB) == 0) return -1; if(st & 0x20) return -1; data = inb(KBDATAP); if(data == 0xE0){ shift |= E0ESC; return 0; } // Feed /dev/input/event0 before the byte is turned into a character. This // has to happen here rather than in a second handler because the byte can // only be read from the port once -- whoever reads it owes it to everyone // else. The console path below is untouched: both consumers see every key. input_ps2_scancode(data, (shift & E0ESC) != 0); // While something holds an exclusive grab on the keyboard, the console gets // nothing. The shift/caps state below is still tracked, so releasing the // grab does not leave the line discipline believing a modifier is held. if(input_is_grabbed(INPUT_KBD)){ if(data & 0x80){ data = (shift & E0ESC ? data : data & 0x7F); shift &= ~(shiftcode[data] | E0ESC); } else { shift |= shiftcode[data]; shift ^= togglecode[data]; } return 0; } if(data & 0x80){ data = (shift & E0ESC ? data : data & 0x7F); shift &= ~(shiftcode[data] | E0ESC); return 0; } else if(shift & E0ESC){ data |= 0x80; shift &= ~E0ESC; } shift |= shiftcode[data]; shift ^= togglecode[data]; c = charcode[shift & (CTL | SHIFT)][data]; if(shift & CAPSLOCK){ if('a' <= c && c <= 'z') c += 'A' - 'a'; else if('A' <= c && c <= 'Z') c += 'a' - 'A'; } return c; } void kbdintr(void) { consoleintr(kbdgetc); }