Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

keyboard.h

Go to the documentation of this file.
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