1 #include "devices/kbd.h"
6 #include "devices/input.h"
7 #include "devices/shutdown.h"
8 #include "threads/interrupt.h"
9 #include "threads/io.h"
11 /* Keyboard data register port. */
14 /* Current state of shift keys.
15 True if depressed, false otherwise. */
16 static bool left_shift, right_shift; /* Left and right Shift keys. */
17 static bool left_alt, right_alt; /* Left and right Alt keys. */
18 static bool left_ctrl, right_ctrl; /* Left and right Ctl keys. */
20 /* Status of Caps Lock.
21 True when on, false when off. */
22 static bool caps_lock;
24 /* Number of keys pressed. */
25 static int64_t key_cnt;
27 static intr_handler_func keyboard_interrupt;
29 /* Initializes the keyboard. */
33 intr_register_ext (0x21, keyboard_interrupt, "8042 Keyboard");
36 /* Prints keyboard statistics. */
38 kbd_print_stats (void)
40 printf ("Keyboard: %lld keys pressed\n", key_cnt);
43 /* Maps a set of contiguous scancodes into characters. */
46 uint8_t first_scancode; /* First scancode. */
47 const char *chars; /* chars[0] has scancode first_scancode,
48 chars[1] has scancode first_scancode + 1,
49 and so on to the end of the string. */
52 /* Keys that produce the same characters regardless of whether
53 the Shift keys are down. Case of letters is an exception
54 that we handle elsewhere. */
55 static const struct keymap invariant_keymap[] =
57 {0x01, "\033"}, /* Escape. */
59 {0x0f, "\tQWERTYUIOP"},
65 {0x53, "\177"}, /* Delete. */
69 /* Characters for keys pressed without Shift, for those keys
71 static const struct keymap unshifted_keymap[] =
73 {0x02, "1234567890-="},
81 /* Characters for keys pressed with Shift, for those keys where
83 static const struct keymap shifted_keymap[] =
85 {0x02, "!@#$%^&*()_+"},
93 static bool map_key (const struct keymap[], unsigned scancode, uint8_t *);
96 keyboard_interrupt (struct intr_frame *args UNUSED)
98 /* Status of shift keys. */
99 bool shift = left_shift || right_shift;
100 bool alt = left_alt || right_alt;
101 bool ctrl = left_ctrl || right_ctrl;
103 /* Keyboard scancode. */
106 /* False if key pressed, true if key released. */
109 /* Character that corresponds to `code'. */
112 /* Read scancode, including second byte if prefix code. */
113 code = inb (DATA_REG);
115 code = (code << 8) | inb (DATA_REG);
117 /* Bit 0x80 distinguishes key press from key release
118 (even if there's a prefix). */
119 release = (code & 0x80) != 0;
127 caps_lock = !caps_lock;
129 else if (map_key (invariant_keymap, code, &c)
130 || (!shift && map_key (unshifted_keymap, code, &c))
131 || (shift && map_key (shifted_keymap, code, &c)))
133 /* Ordinary character. */
136 /* Reboot if Ctrl+Alt+Del pressed. */
137 if (c == 0177 && ctrl && alt)
140 /* Handle Ctrl, Shift.
141 Note that Ctrl overrides Shift. */
142 if (ctrl && c >= 0x40 && c < 0x60)
144 /* A is 0x41, Ctrl+A is 0x01, etc. */
147 else if (shift == caps_lock)
150 /* Handle Alt by setting the high bit.
151 This 0x80 is unrelated to the one used to
152 distinguish key press from key release. */
156 /* Append to keyboard buffer. */
166 /* Maps a keycode into a shift state variable. */
173 /* Table of shift keys. */
174 static const struct shift_key shift_keys[] =
176 { 0x2a, &left_shift},
177 { 0x36, &right_shift},
179 {0xe038, &right_alt},
181 {0xe01d, &right_ctrl},
185 const struct shift_key *key;
187 /* Scan the table. */
188 for (key = shift_keys; key->scancode != 0; key++)
189 if (key->scancode == code)
191 *key->state_var = !release;
197 /* Scans the array of keymaps K for SCANCODE.
198 If found, sets *C to the corresponding character and returns
200 If not found, returns false and C is ignored. */
202 map_key (const struct keymap k[], unsigned scancode, uint8_t *c)
204 for (; k->first_scancode != 0; k++)
205 if (scancode >= k->first_scancode
206 && scancode < k->first_scancode + strlen (k->chars))
208 *c = k->chars[scancode - k->first_scancode];