00001 // See the end of this file for license information. 00002 00003 #ifndef TORSION_KEYBOARD_H 00004 #define TORSION_KEYBOARD_H 00005 00006 #include "types.h" 00007 #include "asm.h" 00008 #include "irq.h" 00009 #include "semaphore.h" 00010 00011 class Keyboard; 00012 extern Keyboard* keyboard; 00013 00014 // borrowed from NewOS. printable keys are those less than KEY_NONE 00015 typedef enum { 00016 KEY_NONE = 0x80, 00017 KEY_ENTER, 00018 KEY_ESC, 00019 KEY_LSHIFT, 00020 KEY_RSHIFT, 00021 KEY_LCTRL, 00022 KEY_RCTRL, 00023 KEY_LALT, 00024 KEY_RALT, 00025 KEY_CAPSLOCK, 00026 KEY_LWIN, 00027 KEY_RWIN, 00028 KEY_MENU, 00029 KEY_F1, 00030 KEY_F2, 00031 KEY_F3, 00032 KEY_F4, 00033 KEY_F5, 00034 KEY_F6, 00035 KEY_F7, 00036 KEY_F8, 00037 KEY_F9, 00038 KEY_F10, 00039 KEY_F11, 00040 KEY_F12, 00041 KEY_F13, 00042 KEY_F14, 00043 KEY_F15, 00044 KEY_F16, 00045 KEY_F17, 00046 KEY_F18, 00047 KEY_F19, 00048 KEY_F20, 00049 KEY_PRTSCRN, 00050 KEY_SCRLOCK, 00051 KEY_PAUSE, 00052 KEY_TAB, 00053 KEY_BACKSPACE, 00054 KEY_INS, 00055 KEY_DEL, 00056 KEY_HOME, 00057 KEY_END, 00058 KEY_PGUP, 00059 KEY_PGDN, 00060 KEY_ARROW_UP, 00061 KEY_ARROW_DOWN, 00062 KEY_ARROW_LEFT, 00063 KEY_ARROW_RIGHT, 00064 KEY_PAD_NUMLOCK, 00065 KEY_PAD_DIVIDE, 00066 KEY_PAD_MULTIPLY, 00067 KEY_PAD_MINUS, 00068 KEY_PAD_PLUS, 00069 KEY_PAD_ENTER, 00070 KEY_PAD_PERIOD, 00071 KEY_PAD_0, 00072 KEY_PAD_1, 00073 KEY_PAD_2, 00074 KEY_PAD_3, 00075 KEY_PAD_4, 00076 KEY_PAD_5, 00077 KEY_PAD_6, 00078 KEY_PAD_7, 00079 KEY_PAD_8, 00080 KEY_PAD_9, 00081 00082 /* seen on some non-pc keyboards */ 00083 KEY_S1, 00084 KEY_S2, 00085 KEY_S3, 00086 00087 /* NeXT keyboard */ 00088 KEY_LHELP, 00089 KEY_RHELP, 00090 00091 /* SUN Type 4 */ 00092 KEY_COMPOSE, 00093 KEY_ALT_GRAPH, 00094 KEY_HELP, 00095 KEY_STOP, 00096 KEY_PROPS, 00097 KEY_FRONT, 00098 KEY_OPEN, 00099 KEY_FIND, 00100 KEY_AGAIN, 00101 KEY_UNDO, 00102 KEY_COPY, 00103 KEY_PASTE, 00104 KEY_CUT, 00105 00106 /* SUN Type 6 */ 00107 KEY_BLANK, 00108 } Key; 00109 00110 typedef enum { 00111 KEY_MODIFIER_NONE = 0, 00112 KEY_MODIFIER_PRESS = (1 << 0), 00113 KEY_MODIFIER_RELEASE = (1 << 1), 00114 KEY_MODIFIER_SHIFT = (1 << 2), 00115 KEY_MODIFIER_ALT = (1 << 3), 00116 KEY_MODIFIER_CTRL = (1 << 4), 00117 KEY_MODIFIER_WIN = (1 << 5), 00118 KEY_MODIFIER_MENU = (1 << 6) 00119 } Modifier; 00120 00122 class Key_event { 00123 public: 00124 Key key; // the key that was pressed/released 00125 int modifiers; // modifiers, bitwise-or'd together 00126 }; 00127 00129 class Keyboard { 00130 public: 00132 virtual void 00133 init() = 0; 00134 00136 virtual void 00137 deinit() = 0; 00138 00141 virtual Key_event 00142 get_key() = 0; 00143 00147 virtual Key_event 00148 try_get_key() = 0; 00149 00152 virtual Key_event 00153 get_keypress() = 0; 00154 00157 virtual Key_event 00158 try_get_keypress() = 0; 00159 00161 virtual bool 00162 handle_interrupt() = 0; 00163 }; 00164 00167 class Pc_keyboard : public Keyboard { 00168 protected: 00169 Int_handler handler; 00170 Semaphore key_grab_lock; 00171 00172 static const unsigned key_buffer_size = 100; 00173 Key_event key_buffer[key_buffer_size]; 00174 unsigned buffer_append_pos; 00175 unsigned buffer_grab_pos; 00176 bool during_extended; 00177 bool shift_pressed; 00178 bool alt_pressed; 00179 bool ctrl_pressed; 00180 bool win_pressed; 00181 bool menu_pressed; 00182 static const int RELEASE_CODE = 0x80; 00183 static const int EXTENDED_SCANCODE = 0xe0; 00184 00186 typedef enum { 00187 REGISTER_DATA = 0x60, // read/write 00188 REGISTER_STATUS = 0x64 // read 00189 } Register; 00190 00193 typedef enum { 00194 STATUS_OUTPUT_BUFFER_FULL = (1 << 0), // keyboard to host 00195 STATUS_INPUT_BUFFER_FULL = (1 << 1), // host to keyboard 00196 STATUS_SYSTEM_FLAG = (1 << 2), 00197 STATUS_IS_COMMAND = (1 << 3), 00198 STATUS_KEYBOARD_ENABLED = (1 << 4), 00199 STATUS_AUX_PENDING = (1 << 5), 00200 STATUS_COMMAND_TIMEOUT = (1 << 6), 00201 STATUS_PARITY_ERROR = (1 << 7) 00202 } Status; 00203 00206 typedef enum { 00207 RESPONSE_TOO_MANY_KEY_PRESSES = 0x00, 00208 RESPONSE_SELF_TEST_SUCCEEDED = 0x55, 00209 RESPONSE_BASIC_ASSURANCE_TEST_SUCCEEDED = 0xAA, 00210 RESPONSE_COMMAND_ECHO = 0xEE, 00211 RESPONSE_COMMAND_ACKNOWLEDGE = 0xFA, 00212 RESPONSE_BASIC_ASSURANCE_TEST_FAILED = 0xFC, 00213 RESPONSE_RESEND_REQUEST = 0xFE, 00214 RESPONSE_KEYBOARD_ERROR = 0xFF 00215 } Response; 00216 00220 typedef enum { 00221 COMMAND_SET_LEDS = 0xED, 00222 COMMAND_ECHO = 0xEE, 00223 COMMAND_SELECT_SCANCODE_SET = 0xF0, 00224 COMMAND_IDENTIFY_KEYBOARD = 0xF2, 00225 COMMAND_TYPEMATIC_RATE = 0xF3, 00226 COMMAND_ENABLE_KEYBOARD = 0xF4, 00227 COMMAND_DISABLE_SCANNING = 0xF5, 00228 COMMAND_ENABLE_SCANNING = 0xF6, 00229 COMMAND_INTERNAL_DIAGNOSTICS = 0xFF, 00230 COMMAND_READ_COMMAND_BYTE = 0x20, 00231 COMMAND_WRITE_COMMAND_BYTE = 0x60, 00232 COMMAND_ENABLE_AUX_INTERFACE = 0xA7, 00233 COMMAND_DISABLE_AUX_INTERFACE = 0xA8, 00234 COMMAND_TEST_AUX_INTERFACE = 0xA9, 00235 COMMAND_SELF_TEST = 0xAA, 00236 COMMAND_TEST_KEYBOARD_INTERFACE = 0xAB, 00237 COMMAND_DEACTIVATE_KEYBOARD = 0xAD, 00238 COMMAND_ACTIVATE_KEYBOARD = 0xAE, 00239 COMMAND_WRITE_AUX_INTERFACE = 0xD4, 00240 } Command; 00241 00244 typedef enum { 00245 COMMAND_BYTE_ENABLE_KEYBOARD_INTERRUPT = (1 << 0), 00246 COMMAND_BYTE_ENABLE_AUX_INTERRUPT = (1 << 1), 00247 COMMAND_BYTE_SYSTEM_RESERVED_FLAG = (1 << 2), 00248 COMMAND_BYTE_IGNORE_KEY_LOCK = (1 << 3), 00249 COMMAND_BYTE_KEYBOARD_DISABLED = (1 << 4), 00250 COMMAND_BYTE_AUX_DISABLED = (1 << 5), 00251 COMMAND_BYTE_XT_SCANCODES = (1 << 6) 00252 } Command_byte; 00253 00256 typedef enum { 00257 LED_NONE = 0, 00258 LED_SCROLL_LOCK = (1 << 0), 00259 LED_NUM_LOCK = (1 << 1), 00260 LED_CAPS_LOCK = (1 << 2) 00261 } Led; 00262 00266 typedef enum { 00267 RATE_MINIMUM = 0, // 30 Hz repeat 00268 RATE_MEDIUM = 15, 00269 RATE_MAXIMUM = 31 // 2 Hz repeat 00270 } Rate; 00271 00276 typedef enum { 00277 DELAY_250 = 0, // 250 milliseconds 00278 DELAY_500 = 1, // 500 milliseconds 00279 DELAY_750 = 2, // 750 milliseconds 00280 DELAY_1000 = 3 // 1000 milliseconds 00281 } Delay; 00282 00288 typedef enum { 00289 SCANCODE_SET_1 = 1, 00290 SCANCODE_SET_2 = 2, 00291 SCANCODE_SET_3 = 3 00292 } Scancode_set; 00293 00295 inline void 00296 wait_for_write() { 00297 while (inb(REGISTER_STATUS) & STATUS_INPUT_BUFFER_FULL); 00298 } 00299 00301 inline Status 00302 read_status() { 00303 return (Status)inb(REGISTER_STATUS); 00304 } 00305 00307 inline Uint8 00308 read_data() { 00309 return inb(REGISTER_DATA); 00310 } 00311 00313 inline void 00314 write_data(Uint8 data) { 00315 outb(data, REGISTER_DATA); 00316 } 00317 00320 void 00321 send_data(Uint8 data); 00322 00325 Key_event 00326 grab_key(); 00327 00328 public: 00331 void 00332 init(); 00333 00335 void 00336 deinit(); 00337 00338 Key_event 00339 get_key(); 00340 00341 Key_event 00342 try_get_key(); 00343 00344 Key_event 00345 get_keypress(); 00346 00347 Key_event 00348 try_get_keypress(); 00349 00351 bool 00352 handle_interrupt(); 00353 }; 00354 00357 inline bool 00358 keyboard_interrupt_handler(); 00359 00360 // original keymaps borrowed from NewOS 00361 const unsigned pc_keymap_size = 128; 00362 const int pc_keymap[pc_keymap_size] = { 00363 /* 0x00 */ 0, KEY_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', KEY_BACKSPACE, KEY_TAB, 00364 /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', KEY_ENTER, KEY_LCTRL, 'a', 's', 00365 /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', KEY_LSHIFT, '\\', 'z', 'x', 'c', 'v', 00366 /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT, '*', KEY_LALT, ' ', KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, 00367 /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_PAD_NUMLOCK, KEY_SCRLOCK, KEY_PAD_7, KEY_PAD_8, KEY_PAD_9, KEY_PAD_MINUS, KEY_PAD_4, KEY_PAD_5, KEY_PAD_6, KEY_PAD_PLUS, KEY_PAD_1, 00368 /* 0x50 */ KEY_PAD_2, KEY_PAD_3, KEY_PAD_0, KEY_PAD_PERIOD, 0, 0, 0, KEY_F11, KEY_F12, 0, 0, 0, 0, 0, 0, 0, 00369 }; 00370 00371 const int pc_keymap_uppercase[pc_keymap_size] = { 00372 /* 0x00 */ 0, KEY_ESC, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', KEY_BACKSPACE, KEY_TAB, 00373 /* 0x10 */ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', KEY_ENTER, KEY_LCTRL, 'A', 'S', 00374 /* 0x20 */ 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', KEY_LSHIFT, '|', 'Z', 'X', 'C', 'V', 00375 /* 0x30 */ 'B', 'N', 'M', '<', '>', '?', KEY_RSHIFT, '*', KEY_LALT, ' ', KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, 00376 /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_PAD_NUMLOCK, KEY_SCRLOCK, KEY_PAD_7, KEY_PAD_8, KEY_PAD_9, KEY_PAD_MINUS, KEY_PAD_4, KEY_PAD_5, KEY_PAD_6, KEY_PAD_PLUS, KEY_PAD_1, 00377 /* 0x50 */ KEY_PAD_2, KEY_PAD_3, KEY_PAD_0, KEY_PAD_PERIOD, 0, 0, 0, KEY_F11, KEY_F12, 0, 0, 0, 0, 0, 0, 0, 00378 }; 00379 00380 const int pc_keymap_extended[pc_keymap_size] = { 00381 /* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00382 /* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PAD_ENTER, KEY_RCTRL, 0, 0, 00383 /* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00384 /* 0x30 */ 0, 0, 0, 0, 0, KEY_PAD_DIVIDE, 0, KEY_PRTSCRN, KEY_RALT, 0, 0, 0, 0, 0, 0, 0, 00385 /* 0x40 */ 0, 0, 0, 0, 0, 0, 0, KEY_HOME, KEY_ARROW_UP, KEY_PGUP, 0, KEY_ARROW_LEFT, 0, KEY_ARROW_RIGHT, 0, KEY_END, 00386 /* 0x50 */ KEY_ARROW_DOWN, KEY_PGDN, KEY_INS, KEY_DEL, 0, 0, 0, 0, 0, 0, 0, KEY_LWIN, KEY_RWIN, KEY_MENU, 0, 0 00387 }; 00388 00389 00390 #endif 00391 00392 /* Torsion Operating System, Copyright (C) 2000-2004 Dan Helfman 00393 * 00394 * This program is free software; you can redistribute it and/or modify it 00395 * under the terms of the GNU General Public License as published by the 00396 * Free Software Foundation; either version 2 of the License, or (at your 00397 * option) any later version. 00398 * 00399 * This program is distributed in the hope that it will be useful, but 00400 * WITHOUT ANY WARRANTY; without even the implied warranty of 00401 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00402 * General Public License for more details (in the COPYING file). 00403 * 00404 * You should have received a copy of the GNU General Public License along 00405 * with this program; if not, write to the Free Software Foundation, Inc., 00406 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00407 */
Torsion Operating System, Copyright (C) 2000-2004 Dan Helfman