1 #include "devices/kbd.h"
6 #include "devices/input.h"
7 #include "threads/interrupt.h"
8 #include "threads/io.h"
10 /* Keyboard data register port. */
13 /* Current state of shift keys.
14 True if depressed, false otherwise. */
15 static bool left_shift
, right_shift
; /* Left and right Shift keys. */
16 static bool left_alt
, right_alt
; /* Left and right Alt keys. */
17 static bool left_ctrl
, right_ctrl
; /* Left and right Ctl keys. */
19 /* Status of Caps Lock.
20 True when on, false when off. */
21 static bool caps_lock
;
23 /* Number of keys pressed. */
24 static int64_t key_cnt
;
26 static intr_handler_func keyboard_interrupt
;
28 /* Initializes the keyboard. */
32 intr_register_ext (0x21, keyboard_interrupt
, "8042 Keyboard");
35 /* Prints keyboard statistics. */
37 kbd_print_stats (void)
39 printf ("Keyboard: %lld keys pressed\n", key_cnt
);
42 /* Maps a set of contiguous scancodes into characters. */
45 uint8_t first_scancode
; /* First scancode. */
46 const char *chars
; /* chars[0] has scancode first_scancode,
47 chars[1] has scancode first_scancode + 1,
48 and so on to the end of the string. */
51 /* Keys that produce the same characters regardless of whether
52 the Shift keys are down. Case of letters is an exception
53 that we handle elsewhere. */
54 static const struct keymap invariant_keymap
[] =
58 {0x0f, "\tQWERTYUIOP"},
67 /* Characters for keys pressed without Shift, for those keys
69 static const struct keymap unshifted_keymap
[] =
71 {0x02, "1234567890-="},
79 /* Characters for keys pressed with Shift, for those keys where
81 static const struct keymap shifted_keymap
[] =
83 {0x02, "!@#$%^&*()_+"},
91 static bool map_key (const struct keymap
[], unsigned scancode
, uint8_t *);
94 keyboard_interrupt (struct intr_frame
*args UNUSED
)
96 /* Status of shift keys. */
97 bool shift
= left_shift
|| right_shift
;
98 bool alt
= left_alt
|| right_alt
;
99 bool ctrl
= left_ctrl
|| right_ctrl
;
101 /* Keyboard scancode. */
104 /* False if key pressed, true if key released. */
107 /* Character that corresponds to `code'. */
110 /* Read scancode, including second byte if prefix code. */
111 code
= inb (DATA_REG
);
113 code
= (code
<< 8) | inb (DATA_REG
);
115 /* Bit 0x80 distinguishes key press from key release
116 (even if there's a prefix). */
117 release
= (code
& 0x80) != 0;
125 caps_lock
= !caps_lock
;
127 else if (map_key (invariant_keymap
, code
, &c
)
128 || (!shift
&& map_key (unshifted_keymap
, code
, &c
))
129 || (shift
&& map_key (shifted_keymap
, code
, &c
)))
131 /* Ordinary character. */
134 /* Handle Ctrl, Shift.
135 Note that Ctrl overrides Shift. */
136 if (ctrl
&& c
>= 0x40 && c
< 0x60)
138 /* A is 0x41, Ctrl+A is 0x01, etc. */
141 else if (shift
== caps_lock
)
144 /* Handle Alt by setting the high bit.
145 This 0x80 is unrelated to the one used to
146 distinguish key press from key release. */
150 /* Append to keyboard buffer. */
160 /* Maps a keycode into a shift state variable. */
167 /* Table of shift keys. */
168 static const struct shift_key shift_keys
[] =
170 { 0x2a, &left_shift
},
171 { 0x36, &right_shift
},
173 {0xe038, &right_alt
},
175 {0xe01d, &right_ctrl
},
179 const struct shift_key
*key
;
181 /* Scan the table. */
182 for (key
= shift_keys
; key
->scancode
!= 0; key
++)
183 if (key
->scancode
== code
)
185 *key
->state_var
= !release
;
191 /* Scans the array of keymaps K for SCANCODE.
192 If found, sets *C to the corresponding character and returns
194 If not found, returns false and C is ignored. */
196 map_key (const struct keymap k
[], unsigned scancode
, uint8_t *c
)
198 for (; k
->first_scancode
!= 0; k
++)
199 if (scancode
>= k
->first_scancode
200 && scancode
< k
->first_scancode
+ strlen (k
->chars
))
202 *c
= k
->chars
[scancode
- k
->first_scancode
];