#include "types.h" #include "x86.h" #include "defs.h" #include "kbd.h" #include "vt.h" /* NVT -- how many terminals the chords reach */ #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]; // Alt+1..6 before the character tables, because there is no character to // look up: it is a chord that means "show me a different terminal". What it // means is decided in console.c, which is where the terminals are; this only // has to name it. See console_vt_hotkey(). // // The modifier test is an equality, not a mask. `shift & ALT` would fire on // Ctrl+Alt+1 and on AltGr+1 as well, so a chord aimed at the host -- or a // Polish keystroke -- would switch terminals behind your back. Exactly left // Alt, and nothing else held. if ((shift & (CTL | SHIFT | ALT | RALT)) == ALT && data >= SCAN_1 && data < SCAN_1 + NVT) return KEY_ALT_F1 + (data - SCAN_1); 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); }