diff options
| author | manuel <manuel@mausz.at> | 2012-03-27 11:51:08 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2012-03-27 11:51:08 +0200 |
| commit | 4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b (patch) | |
| tree | 868c52e06f207b5ec8a3cc141f4b8b2bdfcc165c /pintos-progos/devices/kbd.c | |
| parent | eae0bd57f0a26314a94785061888d193d186944a (diff) | |
| download | progos-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.c | 213 |
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. */ | ||
| 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. */ | ||
| 19 | |||
| 20 | /* Status of Caps Lock. | ||
| 21 | True when on, false when off. */ | ||
| 22 | static bool caps_lock; | ||
| 23 | |||
| 24 | /* Number of keys pressed. */ | ||
| 25 | static int64_t key_cnt; | ||
| 26 | |||
| 27 | static intr_handler_func keyboard_interrupt; | ||
| 28 | |||
| 29 | /* Initializes the keyboard. */ | ||
| 30 | void | ||
| 31 | kbd_init (void) | ||
| 32 | { | ||
| 33 | intr_register_ext (0x21, keyboard_interrupt, "8042 Keyboard"); | ||
| 34 | } | ||
| 35 | |||
| 36 | /* Prints keyboard statistics. */ | ||
| 37 | void | ||
| 38 | kbd_print_stats (void) | ||
| 39 | { | ||
| 40 | printf ("Keyboard: %lld keys pressed\n", key_cnt); | ||
| 41 | } | ||
| 42 | |||
| 43 | /* Maps a set of contiguous scancodes into characters. */ | ||
| 44 | struct 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. */ | ||
| 55 | static 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. */ | ||
| 71 | static 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. */ | ||
| 83 | static const struct keymap shifted_keymap[] = | ||
| 84 | { | ||
| 85 | {0x02, "!@#$%^&*()_+"}, | ||
| 86 | {0x1a, "{}"}, | ||
| 87 | {0x27, ":\"~"}, | ||
| 88 | {0x2b, "|"}, | ||
| 89 | {0x33, "<>?"}, | ||
| 90 | {0, NULL}, | ||
| 91 | }; | ||
| 92 | |||
| 93 | static bool map_key (const struct keymap[], unsigned scancode, uint8_t *); | ||
| 94 | |||
| 95 | static void | ||
| 96 | keyboard_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. */ | ||
| 201 | static bool | ||
| 202 | map_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 | } | ||
