📄 keyctrl.cc.svn-base
字号:
/*****************************************************************************//* Betriebssysteme I, Uni-Magdeburg, SS 98, OO-Stubs *//*---------------------------------------------------------------------------*//* *//* K E Y B O A R D _ C O N T R O L L E R *//* *//*---------------------------------------------------------------------------*//* Tastaturcontroller des PCs. *//*****************************************************************************//* INCLUDES */#include "machine/keyctrl.h"#include "device/cgastr.h"extern CGA_Stream kout;/* STATIC MEMERS */unsigned char Keyboard_Controller::normal_tab[] ={ 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 225, 39, '\b', 0, 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 129, '+', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 148, 132, '^', 0, '#', 'y', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '-', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0, 0, '+', 0, 0, 0, 0, 0, 0, 0, '<', 0, 0};unsigned char Keyboard_Controller::shift_tab[] ={ 0, 0, '!', '"', 21, '$', '%', '&', '/', '(', ')', '=', '?', 96, 0, 0, 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', 'O', 'P', 154, '*', 0, 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 153, 142, 248, 0, 39, 'Y', 'X', 'C', 'V', 'B', 'N', 'M', ';', ':', '_', 0, 0, 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '>', 0, 0};unsigned char Keyboard_Controller::alt_tab[] ={ 0, 0, 0, 253, 0, 0, 0, 0, '{', '[', ']', '}', '\\', 0, 0, 0, '@', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '|', 0, 0};unsigned char Keyboard_Controller::asc_num_tab[] ={ '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', ','};unsigned char Keyboard_Controller::scan_num_tab[] ={ 8, 9, 10, 53, 5, 6, 7, 27, 2, 3, 4, 11, 51};/* PRIVATE METHODEN */// KEY_DECODED: Interpretiert die Make und Break-Codes der Tastatur und// liefert den ASCII Code, den Scancode und Informationen// darueber, welche zusaetzlichen Tasten wie Shift und Ctrl// gedrueckt wurden. Ein Rueckgabewert true bedeutet, dass// das Zeichen komplett ist, anderenfalls fehlen noch Make// oder Breakcodes.bool Keyboard_Controller::key_decoded () { bool done = false; // Die Tasten, die bei der MF II Tastatur gegenueber der aelteren // AT Tastatur hinzugekommen sind, senden immer erst eines von zwei // moeglichen Prefix Bytes. if (code == prefix1 || code == prefix2) { prefix = code; return false; } // Das Loslassen einer Taste ist eigentlich nur bei den "Modifier" Tasten // SHIFT, CTRL und ALT von Interesse, bei den anderen kann der Break Code // ignoriert werden. if (code & break_bit) { code &= ~break_bit; // Der Break Code einer Taste ist gleich dem // Make Code mit gesetzten break_bit. switch (code) { case 42: case 54: gather.shift (false); break; case 56: if (prefix == prefix1) gather.alt_right (false); else gather.alt_left (false); break; case 29: if (prefix == prefix1) gather.ctrl_right (false); else gather.ctrl_left (false); break; } // Ein Prefix gilt immer nur fuer den unmittelbar nachfolgenden Code. // Also ist es jetzt abgehandelt. prefix = 0; // Mit einem Break-Code kann man nichts anfangen, also false liefern. return false; } // Eine Taste wurde gedrueckt. Bei den Modifier Tasten wie SHIFT, ALT, // NUM_LOCK etc. wird nur der interne Zustand geaendert. Durch den // Rueckgabewert 'false' wird angezeigt, dass die Tastatureingabe noch // nicht abgeschlossen ist. Bei den anderen Tasten werden ASCII // und Scancode eingetragen und ein 'true' fuer eine erfolgreiche // Tastaturabfrage zurueckgegeben, obwohl genaugenommen noch der Break- // code der Taste fehlt. switch (code) { case 42: case 54: gather.shift (true); break; case 56: if (prefix == prefix1) gather.alt_right (true); else gather.alt_left (true); break; case 29: if (prefix == prefix1) gather.ctrl_right (true); else gather.ctrl_left (true); break; case 58: gather.caps_lock (!gather.caps_lock ()); set_led (led::caps_lock, gather.caps_lock()); break; case 70: gather.scroll_lock (!gather.scroll_lock ()); set_led (led::scroll_lock, gather.scroll_lock()); break; case 69: // Numlock oder Pause ? if (gather.ctrl_left ()) // Pause Taste { // Auf alten Tastaturen konnte die Pause-Funktion wohl nur // ueber Ctrl+NumLock erreicht werden. Moderne MF-II Tastaturen // senden daher diese Codekombination, wenn Pause gemeint ist. // Die Pause Taste liefert zwar normalerweise keinen ASCII // Code, aber Nachgucken schadet auch nicht. In jedem Fall ist // die Taste nun komplett. get_ascii_code (); done = true; } else // NumLock { gather.num_lock (!gather.num_lock()); set_led (led::num_lock, gather.num_lock ()); } break; default: // alle anderen Tasten // ASCII Codes aus den entsprechenden Tabellen auslesen, fertig. get_ascii_code (); done = true; } // Ein Prefix gilt immer nur fuer den unmittelbar nachfolgenden Code. // Also ist es jetzt abgehandelt. prefix = 0; if (done) // Tastaturabfrage abgeschlossen return true; else return false; }// GET_ASCII_CODE: ermittelt anhand von Tabellen aus dem Scancode und// den gesetzten Modifier-Bits den ASCII Code der Taste.void Keyboard_Controller::get_ascii_code () { // Sonderfall Scancode 53: Dieser Code wird sowohl von der Minustaste // des normalen Tastaturbereichs, als auch von der Divisionstaste des // Ziffernblocks gesendet. Damit in beiden Faellen ein Code heraus- // kommt, der der Aufschrift entspricht, muss im Falle des Ziffern- // blocks eine Umsetzung auf den richtigen Code der Divisionstaste // erfolgen. if (code == 53 && prefix == prefix1) // Divisionstaste des Ziffernblocks { gather.ascii ('/'); gather.scancode (Key::scan::div); } // Anhand der Modifierbits muss die richtige Tabelle ausgewaehlt // werden. Der Einfachheit halber hat NumLock Vorrang vor Alt, // Shift und CapsLock. Fuer Ctrl gibt es keine eigene Tabelle. else if (gather.num_lock () && !prefix && code>=71 && code<=83) { // Bei eingeschaltetem NumLock und der Betaetigung einer der // Tasten des separaten Ziffernblocks (Codes 71-83), sollen // nicht die Scancodes der Cursortasten, sondern ASCII und // Scancodes der ensprechenden Zifferntasten geliefert werden. // Die Tasten des Cursorblocks (prefix == prefix1) sollen // natuerlich weiterhin zur Cursorsteuerung genutzt werden // koennen. Sie senden dann uebrigens noch ein Shift, aber das // sollte nicht weiter stoeren. gather.ascii (asc_num_tab[code-71]); gather.scancode (scan_num_tab[code-71]); } else if (gather.alt_right ()) { gather.ascii (alt_tab[code]); gather.scancode (code); } else if (gather.shift ()) { gather.ascii (shift_tab[code]); gather.scancode (code); } else if (gather.caps_lock ()) { // Die Umschaltung soll nur bei Buchstaben gelten if ((code>=16 && code<=26) || (code>=30 && code<=40) || (code>=44 && code<=50)) { gather.ascii (shift_tab[code]); gather.scancode (code); } else { gather.ascii (normal_tab[code]); gather.scancode (code); } } else { gather.ascii (normal_tab[code]); gather.scancode (code); } }/* OEFFENTLICHE METHODEN */// KEYBOARD_CONTROLLER: Initialisierung der Tastatur: alle LEDs werden// ausgeschaltet und die Wiederholungsrate auf// maximale Geschwindigkeit eingestellt.Keyboard_Controller::Keyboard_Controller () : ctrl_port (0x64), data_port (0x60) { led_status = 0; // alle LEDs ausschalten (bei vielen PCs ist NumLock nach dem Booten an) set_led (led::caps_lock, false); set_led (led::scroll_lock, false); set_led (led::num_lock, false); // maximale Geschwindigkeit, minimale Verzoegerung set_repeat_rate (0, 0); }// KEY_HIT: Dient der Tastaturabfrage nach dem Auftreten einer Tastatur-// unterbrechung. Der Rueckgabewert true zeigt an, dass ein// Scancode und vielleicht auch ein ASCII Code ermittelt werden// konnten und nun in key zur Verfuegung stehen.// Ein Rueckgabewert false zeigt an, dass die Make-/Break-Codes// noch nicht vollstaendig waren. In diesem Fall darf key nicht// interpretiert werden.Key Keyboard_Controller::key_hit () { int status = ctrl_port.inb(); if(!( status & outb ) && ! ( status & auxb ) ) return Key(); code = data_port.inb(); if(!key_decoded()) return Key(); return gather; }// REBOOT: Fuehrt einen Neustart des Rechners durch. Ja, beim PC macht// das der Tastaturcontroller.void Keyboard_Controller::reboot () { int status; // Dem BIOS mitteilen, dass das Reset beabsichtigt war // und kein Speichertest durchgefuehrt werden muss. *(unsigned short*) 0x472 = 0x1234; // Der Tastaturcontroller soll das Reset ausloesen. do { status = ctrl_port.inb (); // warten, bis das letzte Kommando } while ((status & inpb) != 0); // verarbeitet wurde. ctrl_port.outb (cpu_reset); // Reset }// SET_REPEAT_RATE: Funktion zum Einstellen der Wiederholungsrate der// Tastatur. delay bestimmt, wie lange eine Taste ge-// drueckt werden muss, bevor die Wiederholung einsetzt.// Erlaubt sind Werte zwischen 0 (minimale Wartezeit)// und 7 (maximale Wartezeit). speed bestimmt, wie// schnell die Tastencodes aufeinander folgen soll.// Erlaubt sind Werte zwischen 0 (sehr schnell) und 31// (sehr langsam).void Keyboard_Controller::set_repeat_rate (int speed, int delay) { int speed_cmd = (speed & 0xf) | ( (delay & 0x3) << 4 ); while( (ctrl_port.inb() & inpb) != 0); for(int i = 0; i < 10000; i++); data_port.outb(kbd_cmd::set_speed); for(int i = 0; i < 10000; i++); while( (data_port.inb() & kbd_reply::ack) == 0); for(int i = 0; i < 10000; i++); data_port.outb(speed_cmd); for(int i = 0; i < 10000; i++); while( (data_port.inb() & kbd_reply::ack) == 0); return; }// SET_LED: setzt oder loescht die angegebene Leuchtdiodevoid Keyboard_Controller::set_led (char led, bool on) { led &= 0x7; led_status = on ? ( led_status | led ) : ( led_status & ~led ); while( (ctrl_port.inb() & inpb) != 0); data_port.outb(kbd_cmd::set_led); while( (ctrl_port.inb() & inpb) != 0); while( (data_port.inb() & kbd_reply::ack) == 0); data_port.outb(led_status); while( (ctrl_port.inb() & inpb) != 0); while( (data_port.inb() & kbd_reply::ack) == 0); return; } bool Keyboard_Controller::get_led (char led){ return led_status & led & 0x7;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -