// keyboard.c // Author: Josh Holtrop // Created: 04/17/03 // Modified: 05/19/05 #include "hos_defines.h" #include "char/keyboard.h" #include "sys/io.h" // inportb, outportb #include "functions.h" #include "lang/conv.h" // asciiSwitchCase() #include "display/kout.h" // kprintf() #include "display/display.h" // display_activate() u8_t kbdFlags = 0; // holds current keyboard flags - caps/num/scroll/shift/ctrl/alt u8_t lastWasE0 = 0; // was the last byte 0x0E ? u8_t rawIgnore = 0; // how many signals to blatantly ignore u8_t ackReason = 0; // used to record the reason why we would get an acknowledge byte (0xFA) //these arrays convert a keyboard scan code to an ASCII character value const u8_t SCAN2ASCII[129] = // for normal keys "\000\0331234567890-=\010\011" // null,esc,1234567890-=,bksp,tab "qwertyuiop[]\n\000as" // qwertyuiop[],enter,lctrl,as "dfghjkl;'`\000\\zxcv" // dfghjkl;'`,lshift,\zxcv "bnm,./\000*\000 \000\000\000\000\000\000" // bnm,./,rshift,*,alt,space,caps,f1,f2,f3,f4,f5 "\000\000\000\000\000\000\000\000\000\000-\000\000\000+\000" // f6,f7,f8,f9,f10,num,scrl,home,up,pgup,dash,left,center,right,plus,end "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" // down,pgdn,ins,del,?,?,?,f11,f12,?,?,winL,winR,menu,?,? "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" // ? "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; // ? const u8_t SCAN2ASCII2[129] = // for shifted or numlocked keys "\000\033!@#$%^&*()_+\010\011" // null,esc,!@#$%^&*()_+,bksp,tab "QWERTYUIOP{}\n\000AS" // QWERTYUIOP{},enter,lctrl,AS "DFGHJKL:\"~\000|ZXCV" // DFGHJKL:"~,lshift,|ZXCV "BNM<>?\000*\000 \000\000\000\000\000\000" // BNM<>?,rshift,*,alt,space,caps,f1,f2,f3,f4,f5 "\000\000\000\000\000\000\000789-456+1" // f6,f7,f8,f9,f10,num,scrl,789-456+1 "230.\000\000\000\000\000\000\000\000\000\000\000\000" // 230.,?,?,?,f11,f12,?,?,winL,winR,menu,?,? "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" // ? "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; // ? // The Keyboard Interrupt Service Routine void isr_keyboard() { u8_t kbdScan = inportb(0x60); u8_t inState = inportb(0x61); outportb(0x61, inState|0x80); outportb(0x61, inState); if (kbdScan == 0xFA) //250 // ACKnowledge { //printf("KBD_ACK 0x%x!\n", ackReason); switch (ackReason) { case 0xED: // reset LEDs outportb(0x60, (kbdFlags & 0x07)); break; } ackReason = 0; } if (rawIgnore) // ignore keycodes { rawIgnore--; return; } if (lastWasE0 && (kbdScan == 0x2A || kbdScan == 0xAA)) // ignore extended "shift" { lastWasE0 = 0; return; } if (kbdScan == 0xE0) // 0xE0 == extended key { lastWasE0 = 1; return; } if (kbdScan == 0xE1) // 0xE1 == 2nd-set-extended key { rawIgnore = 2; return; } switch (kbdScan) // handle control keys { case KBD_SCAN_LSHIFT: kbdFlags |= KBDF_SHIFT; break; case KBD_SCAN_RSHIFT: kbdFlags |= KBDF_SHIFT; break; case KBD_SCAN_CTRL: kbdFlags |= KBDF_CTRL; break; case KBD_SCAN_ALT: kbdFlags |= KBDF_ALT; break; case KBD_SCAN_LSHIFT + KBD_SCAN_RELEASED: kbdFlags &= (KBDF_SHIFT ^ 0xFF); break; case KBD_SCAN_RSHIFT + KBD_SCAN_RELEASED: kbdFlags &= (KBDF_SHIFT ^ 0xFF); break; case KBD_SCAN_CTRL + KBD_SCAN_RELEASED: kbdFlags &= (KBDF_CTRL ^ 0xFF); break; case KBD_SCAN_ALT + KBD_SCAN_RELEASED: kbdFlags &= (KBDF_ALT ^ 0xFF); break; case KBD_SCAN_CAPS+KBD_SCAN_RELEASED: kbdFlags ^= KBDF_CAPS; kbd_resetLEDs(); // update LEDs break; case KBD_SCAN_SCROLL+KBD_SCAN_RELEASED: kbdFlags ^= KBDF_SCROLL; kbd_resetLEDs(); // update LEDs break; case KBD_SCAN_NUM+KBD_SCAN_RELEASED: kbdFlags ^= KBDF_NUM; kbd_resetLEDs(); // update LEDs break; } u8_t kbdAscii; // shift or (numlock and key from numpad) if ( (kbdFlags & KBDF_SHIFT) || ((kbdFlags & KBDF_NUM) && (kbdScan >= 71) && (kbdScan <= 83)) ) kbdAscii = SCAN2ASCII2[kbdScan & 0x7F]; else // normal key kbdAscii = SCAN2ASCII[kbdScan & 0x7F]; if (kbdFlags & KBDF_CAPS) kbdAscii = asciiSwitchCase(kbdAscii); // won't affect non-letter characters //====do something with key:: // kprintf("kbdScan = \e[31;1m0x%x\e[0m\tkbdAscii = \e[1;32m0x%x\e[0m (\e[35m%c\e[0m)\tkbdFlags = \e[34m0x%x\e[0m\n", kbdScan, kbdAscii, kbdAscii, kbdFlags); if ((kbdScan == 83) && (kbdFlags & KBDF_CTRL) && (kbdFlags & KBDF_ALT)) { kprintf("Initiating reboot."); restart(); } if (kbdScan & KBD_SCAN_RELEASED) kbdAscii = 0; // send a key event to the display subsystem display_key_event((kbdFlags << 16) | (kbdScan << 8) | kbdAscii); } //Resets the keyboard LEDs to reflect the current state of the num lock, caps lock, and scroll lock bits void kbd_resetLEDs() { outportb(0x60, 0xED); ackReason = 0xED; }