summaryrefslogtreecommitdiffstats
path: root/pintos-progos/devices/kbd.c
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2012-03-27 11:51:08 +0200
committermanuel <manuel@mausz.at>2012-03-27 11:51:08 +0200
commit4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b (patch)
tree868c52e06f207b5ec8a3cc141f4b8b2bdfcc165c /pintos-progos/devices/kbd.c
parenteae0bd57f0a26314a94785061888d193d186944a (diff)
downloadprogos-4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b.tar.gz
progos-4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b.tar.bz2
progos-4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b.zip
reorganize file structure to match the upstream requirements
Diffstat (limited to 'pintos-progos/devices/kbd.c')
-rw-r--r--pintos-progos/devices/kbd.c213
1 files changed, 0 insertions, 213 deletions
diff --git a/pintos-progos/devices/kbd.c b/pintos-progos/devices/kbd.c
deleted file mode 100644
index fcc82be..0000000
--- a/pintos-progos/devices/kbd.c
+++ /dev/null
@@ -1,213 +0,0 @@
1#include "devices/kbd.h"
2#include <ctype.h>
3#include <debug.h>
4#include <stdio.h>
5#include <string.h>
6#include "devices/input.h"
7#include "devices/shutdown.h"
8#include "threads/interrupt.h"
9#include "threads/io.h"
10
11/* Keyboard data register port. */
12#define DATA_REG 0x60
13
14/* Current state of shift keys.
15 True if depressed, false otherwise. */
16static bool left_shift, right_shift; /* Left and right Shift keys. */
17static bool left_alt, right_alt; /* Left and right Alt keys. */
18static bool left_ctrl, right_ctrl; /* Left and right Ctl keys. */
19
20/* Status of Caps Lock.
21 True when on, false when off. */
22static bool caps_lock;
23
24/* Number of keys pressed. */
25static int64_t key_cnt;
26
27static intr_handler_func keyboard_interrupt;
28
29/* Initializes the keyboard. */
30void
31kbd_init (void)
32{
33 intr_register_ext (0x21, keyboard_interrupt, "8042 Keyboard");
34}
35
36/* Prints keyboard statistics. */
37void
38kbd_print_stats (void)
39{
40 printf ("Keyboard: %lld keys pressed\n", key_cnt);
41}
42
43/* Maps a set of contiguous scancodes into characters. */
44struct keymap
45 {
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. */
50 };
51
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. */
55static const struct keymap invariant_keymap[] =
56 {
57 {0x01, "\033"}, /* Escape. */
58 {0x0e, "\b"},
59 {0x0f, "\tQWERTYUIOP"},
60 {0x1c, "\r"},
61 {0x1e, "ASDFGHJKL"},
62 {0x2c, "ZXCVBNM"},
63 {0x37, "*"},
64 {0x39, " "},
65 {0x53, "\177"}, /* Delete. */
66 {0, NULL},
67 };
68
69/* Characters for keys pressed without Shift, for those keys
70 where it matters. */
71static const struct keymap unshifted_keymap[] =
72 {
73 {0x02, "1234567890-="},
74 {0x1a, "[]"},
75 {0x27, ";'`"},
76 {0x2b, "\\"},
77 {0x33, ",./"},
78 {0, NULL},
79 };
80
81/* Characters for keys pressed with Shift, for those keys where
82 it matters. */
83static const struct keymap shifted_keymap[] =
84 {
85 {0x02, "!@#$%^&*()_+"},
86 {0x1a, "{}"},
87 {0x27, ":\"~"},
88 {0x2b, "|"},
89 {0x33, "<>?"},
90 {0, NULL},
91 };
92
93static bool map_key (const struct keymap[], unsigned scancode, uint8_t *);
94
95static void
96keyboard_interrupt (struct intr_frame *args UNUSED)
97{
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;
102
103 /* Keyboard scancode. */
104 unsigned code;
105
106 /* False if key pressed, true if key released. */
107 bool release;
108
109 /* Character that corresponds to `code'. */
110 uint8_t c;
111
112 /* Read scancode, including second byte if prefix code. */
113 code = inb (DATA_REG);
114 if (code == 0xe0)
115 code = (code << 8) | inb (DATA_REG);
116
117 /* Bit 0x80 distinguishes key press from key release
118 (even if there's a prefix). */
119 release = (code & 0x80) != 0;
120 code &= ~0x80u;
121
122 /* Interpret key. */
123 if (code == 0x3a)
124 {
125 /* Caps Lock. */
126 if (!release)
127 caps_lock = !caps_lock;
128 }
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)))
132 {
133 /* Ordinary character. */
134 if (!release)
135 {
136 /* Reboot if Ctrl+Alt+Del pressed. */
137 if (c == 0177 && ctrl && alt)
138 shutdown_reboot ();
139
140 /* Handle Ctrl, Shift.
141 Note that Ctrl overrides Shift. */
142 if (ctrl && c >= 0x40 && c < 0x60)
143 {
144 /* A is 0x41, Ctrl+A is 0x01, etc. */
145 c -= 0x40;
146 }
147 else if (shift == caps_lock)
148 c = tolower (c);
149
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. */
153 if (alt)
154 c += 0x80;
155
156 /* Append to keyboard buffer. */
157 if (!input_full ())
158 {
159 key_cnt++;
160 input_putc (c);
161 }
162 }
163 }
164 else
165 {
166 /* Maps a keycode into a shift state variable. */
167 struct shift_key
168 {
169 unsigned scancode;
170 bool *state_var;
171 };
172
173 /* Table of shift keys. */
174 static const struct shift_key shift_keys[] =
175 {
176 { 0x2a, &left_shift},
177 { 0x36, &right_shift},
178 { 0x38, &left_alt},
179 {0xe038, &right_alt},
180 { 0x1d, &left_ctrl},
181 {0xe01d, &right_ctrl},
182 {0, NULL},
183 };
184
185 const struct shift_key *key;
186
187 /* Scan the table. */
188 for (key = shift_keys; key->scancode != 0; key++)
189 if (key->scancode == code)
190 {
191 *key->state_var = !release;
192 break;
193 }
194 }
195}
196
197/* Scans the array of keymaps K for SCANCODE.
198 If found, sets *C to the corresponding character and returns
199 true.
200 If not found, returns false and C is ignored. */
201static bool
202map_key (const struct keymap k[], unsigned scancode, uint8_t *c)
203{
204 for (; k->first_scancode != 0; k++)
205 if (scancode >= k->first_scancode
206 && scancode < k->first_scancode + strlen (k->chars))
207 {
208 *c = k->chars[scancode - k->first_scancode];
209 return true;
210 }
211
212 return false;
213}