00001 #include "devices/kbd.h"
00002
00003 #include <ctype.h>
00004 #include <debug.h>
00005 #include <stdio.h>
00006 #include <string.h>
00007 #include "devices/input.h"
00008 #include "threads/init.h"
00009 #include "threads/interrupt.h"
00010 #include "threads/io.h"
00011
00012
00013 #define DATA_REG 0x60
00014
00015
00016
00017 static bool left_shift, right_shift;
00018 static bool left_alt, right_alt;
00019 static bool left_ctrl, right_ctrl;
00020
00021
00022
00023 static bool caps_lock;
00024
00025
00026 static int64_t key_cnt;
00027
00028 static intr_handler_func keyboard_interrupt;
00029
00030
00031 void
00032 kbd_init (void)
00033 {
00034 intr_register_ext (0x21, keyboard_interrupt, "8042 Keyboard");
00035 }
00036
00037
00038 void
00039 kbd_print_stats (void)
00040 {
00041 printf ("Keyboard: %lld keys pressed\n", key_cnt);
00042 }
00043
00044
00045 struct keymap
00046 {
00047 uint8_t first_scancode;
00048 const char *chars;
00049
00050
00051 };
00052
00053
00054
00055
00056 static const struct keymap invariant_keymap[] =
00057 {
00058 {0x01, "\033"},
00059 {0x0e, "\b"},
00060 {0x0f, "\tQWERTYUIOP"},
00061 {0x1c, "\r"},
00062 {0x1e, "ASDFGHJKL"},
00063 {0x2c, "ZXCVBNM"},
00064 {0x37, "*"},
00065 {0x39, " "},
00066 {0x53, "\177"},
00067 {0, NULL},
00068 };
00069
00070
00071
00072 static const struct keymap unshifted_keymap[] =
00073 {
00074 {0x02, "1234567890-="},
00075 {0x1a, "[]"},
00076 {0x27, ";'`"},
00077 {0x2b, "\\"},
00078 {0x33, ",./"},
00079 {0, NULL},
00080 };
00081
00082
00083
00084 static const struct keymap shifted_keymap[] =
00085 {
00086 {0x02, "!@#$%^&*()_+"},
00087 {0x1a, "{}"},
00088 {0x27, ":\"~"},
00089 {0x2b, "|"},
00090 {0x33, "<>?"},
00091 {0, NULL},
00092 };
00093
00094 static bool map_key (const struct keymap[], unsigned scancode, uint8_t *);
00095
00096 static void
00097 keyboard_interrupt (struct intr_frame *args UNUSED)
00098 {
00099
00100 bool shift = left_shift || right_shift;
00101 bool alt = left_alt || right_alt;
00102 bool ctrl = left_ctrl || right_ctrl;
00103
00104
00105 unsigned code;
00106
00107
00108 bool release;
00109
00110
00111 uint8_t c;
00112
00113
00114 code = inb (DATA_REG);
00115 if (code == 0xe0)
00116 code = (code << 8) | inb (DATA_REG);
00117
00118
00119
00120 release = (code & 0x80) != 0;
00121 code &= ~0x80u;
00122
00123
00124 if (code == 0x3a)
00125 {
00126
00127 if (!release)
00128 caps_lock = !caps_lock;
00129 }
00130 else if (map_key (invariant_keymap, code, &c)
00131 || (!shift && map_key (unshifted_keymap, code, &c))
00132 || (shift && map_key (shifted_keymap, code, &c)))
00133 {
00134
00135 if (!release)
00136 {
00137
00138 if (c == 0177 && ctrl && alt)
00139 reboot ();
00140
00141
00142 if (c == 'A' && ctrl && alt)
00143 debug_backtrace_all ();
00144
00145
00146
00147 if (ctrl && c >= 0x40 && c < 0x60)
00148 {
00149
00150 c -= 0x40;
00151 }
00152 else if (shift == caps_lock)
00153 c = tolower (c);
00154
00155
00156
00157
00158 if (alt)
00159 c += 0x80;
00160
00161
00162 if (!input_full ())
00163 {
00164 key_cnt++;
00165 input_putc (c);
00166 }
00167 }
00168 }
00169 else
00170 {
00171
00172 struct shift_key
00173 {
00174 unsigned scancode;
00175 bool *state_var;
00176 };
00177
00178
00179 static const struct shift_key shift_keys[] =
00180 {
00181 { 0x2a, &left_shift},
00182 { 0x36, &right_shift},
00183 { 0x38, &left_alt},
00184 {0xe038, &right_alt},
00185 { 0x1d, &left_ctrl},
00186 {0xe01d, &right_ctrl},
00187 {0, NULL},
00188 };
00189
00190 const struct shift_key *key;
00191
00192
00193 for (key = shift_keys; key->scancode != 0; key++)
00194 if (key->scancode == code)
00195 {
00196 *key->state_var = !release;
00197 break;
00198 }
00199 }
00200 }
00201
00202
00203
00204
00205
00206 static bool
00207 map_key (const struct keymap k[], unsigned scancode, uint8_t *c)
00208 {
00209 for (; k->first_scancode != 0; k++)
00210 if (scancode >= k->first_scancode
00211 && scancode < k->first_scancode + strlen (k->chars))
00212 {
00213 *c = k->chars[scancode - k->first_scancode];
00214 return true;
00215 }
00216
00217 return false;
00218 }