Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | #include <linux/config.h> |
| 2 | #include <linux/kd.h> |
| 3 | //#include <linux/kbd_ll.h> |
| 4 | #include <linux/kbd_kern.h> |
| 5 | |
| 6 | /* |
| 7 | * Translation of escaped scancodes to keycodes. |
| 8 | * This is now user-settable. |
| 9 | * The keycodes 1-88,96-111,119 are fairly standard, and |
| 10 | * should probably not be changed - changing might confuse X. |
| 11 | * X also interprets scancode 0x5d (KEY_Begin). |
| 12 | * |
| 13 | * For 1-88 keycode equals scancode. |
| 14 | */ |
| 15 | |
| 16 | #define E0_KPENTER 96 |
| 17 | #define E0_RCTRL 97 |
| 18 | #define E0_KPSLASH 98 |
| 19 | #define E0_PRSCR 99 |
| 20 | #define E0_RALT 100 |
| 21 | #define E0_BREAK 101 /* (control-pause) */ |
| 22 | #define E0_HOME 102 |
| 23 | #define E0_UP 103 |
| 24 | #define E0_PGUP 104 |
| 25 | #define E0_LEFT 105 |
| 26 | #define E0_RIGHT 106 |
| 27 | #define E0_END 107 |
| 28 | #define E0_DOWN 108 |
| 29 | #define E0_PGDN 109 |
| 30 | #define E0_INS 110 |
| 31 | #define E0_DEL 111 |
| 32 | |
| 33 | /* for USB 106 keyboard */ |
| 34 | #define E0_YEN 124 |
| 35 | #define E0_BACKSLASH 89 |
| 36 | |
| 37 | |
| 38 | #define E1_PAUSE 119 |
| 39 | |
| 40 | /* |
| 41 | * The keycodes below are randomly located in 89-95,112-118,120-127. |
| 42 | * They could be thrown away (and all occurrences below replaced by 0), |
| 43 | * but that would force many users to use the `setkeycodes' utility, where |
| 44 | * they needed not before. It does not matter that there are duplicates, as |
| 45 | * long as no duplication occurs for any single keyboard. |
| 46 | */ |
| 47 | #define SC_LIM 89 |
| 48 | |
| 49 | #define FOCUS_PF1 85 /* actual code! */ |
| 50 | #define FOCUS_PF2 89 |
| 51 | #define FOCUS_PF3 90 |
| 52 | #define FOCUS_PF4 91 |
| 53 | #define FOCUS_PF5 92 |
| 54 | #define FOCUS_PF6 93 |
| 55 | #define FOCUS_PF7 94 |
| 56 | #define FOCUS_PF8 95 |
| 57 | #define FOCUS_PF9 120 |
| 58 | #define FOCUS_PF10 121 |
| 59 | #define FOCUS_PF11 122 |
| 60 | #define FOCUS_PF12 123 |
| 61 | |
| 62 | #define JAP_86 124 |
| 63 | /* tfj@olivia.ping.dk: |
| 64 | * The four keys are located over the numeric keypad, and are |
| 65 | * labelled A1-A4. It's an rc930 keyboard, from |
| 66 | * Regnecentralen/RC International, Now ICL. |
| 67 | * Scancodes: 59, 5a, 5b, 5c. |
| 68 | */ |
| 69 | #define RGN1 124 |
| 70 | #define RGN2 125 |
| 71 | #define RGN3 126 |
| 72 | #define RGN4 127 |
| 73 | |
| 74 | static unsigned char high_keys[128 - SC_LIM] = { |
| 75 | RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */ |
| 76 | 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ |
| 77 | 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */ |
| 78 | 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */ |
| 79 | FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */ |
| 80 | FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */ |
| 81 | }; |
| 82 | |
| 83 | /* BTC */ |
| 84 | #define E0_MACRO 112 |
| 85 | /* LK450 */ |
| 86 | #define E0_F13 113 |
| 87 | #define E0_F14 114 |
| 88 | #define E0_HELP 115 |
| 89 | #define E0_DO 116 |
| 90 | #define E0_F17 117 |
| 91 | #define E0_KPMINPLUS 118 |
| 92 | /* |
| 93 | * My OmniKey generates e0 4c for the "OMNI" key and the |
| 94 | * right alt key does nada. [kkoller@nyx10.cs.du.edu] |
| 95 | */ |
| 96 | #define E0_OK 124 |
| 97 | /* |
| 98 | * New microsoft keyboard is rumoured to have |
| 99 | * e0 5b (left window button), e0 5c (right window button), |
| 100 | * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU] |
| 101 | * [or: Windows_L, Windows_R, TaskMan] |
| 102 | */ |
| 103 | #define E0_MSLW 125 |
| 104 | #define E0_MSRW 126 |
| 105 | #define E0_MSTM 127 |
| 106 | |
| 107 | static unsigned char e0_keys[128] = { |
| 108 | 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ |
| 109 | 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */ |
| 110 | 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ |
| 111 | 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */ |
| 112 | 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */ |
| 113 | 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */ |
| 114 | 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */ |
| 115 | E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */ |
| 116 | E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */ |
| 117 | E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END, /* 0x48-0x4f */ |
| 118 | E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */ |
| 119 | 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */ |
| 120 | 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ |
| 121 | 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */ |
| 122 | //0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ |
| 123 | 0, 0, 0, 0, 0, E0_BACKSLASH, 0, 0, /* 0x70-0x77 */ |
| 124 | 0, 0, 0, E0_YEN, 0, 0, 0, 0 /* 0x78-0x7f */ |
| 125 | }; |
| 126 | |
| 127 | static int gen_setkeycode(unsigned int scancode, unsigned int keycode) |
| 128 | { |
| 129 | if (scancode < SC_LIM || scancode > 255 || keycode > 127) |
| 130 | return -EINVAL; |
| 131 | if (scancode < 128) |
| 132 | high_keys[scancode - SC_LIM] = keycode; |
| 133 | else |
| 134 | e0_keys[scancode - 128] = keycode; |
| 135 | return 0; |
| 136 | } |
| 137 | |
| 138 | static int gen_getkeycode(unsigned int scancode) |
| 139 | { |
| 140 | return |
| 141 | (scancode < SC_LIM || scancode > 255) ? -EINVAL : |
| 142 | (scancode < |
| 143 | 128) ? high_keys[scancode - SC_LIM] : e0_keys[scancode - 128]; |
| 144 | } |
| 145 | |
| 146 | static int |
| 147 | gen_translate(unsigned char scancode, unsigned char *keycode, char raw_mode) |
| 148 | { |
| 149 | static int prev_scancode; |
| 150 | |
| 151 | /* special prefix scancodes.. */ |
| 152 | if (scancode == 0xe0 || scancode == 0xe1) { |
| 153 | prev_scancode = scancode; |
| 154 | return 0; |
| 155 | } |
| 156 | |
| 157 | /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */ |
| 158 | if (scancode == 0x00 || scancode == 0xff) { |
| 159 | prev_scancode = 0; |
| 160 | return 0; |
| 161 | } |
| 162 | |
| 163 | scancode &= 0x7f; |
| 164 | |
| 165 | if (prev_scancode) { |
| 166 | /* |
| 167 | * usually it will be 0xe0, but a Pause key generates |
| 168 | * e1 1d 45 e1 9d c5 when pressed, and nothing when released |
| 169 | */ |
| 170 | if (prev_scancode != 0xe0) { |
| 171 | if (prev_scancode == 0xe1 && scancode == 0x1d) { |
| 172 | prev_scancode = 0x100; |
| 173 | return 0; |
| 174 | } |
| 175 | else if (prev_scancode == 0x100 |
| 176 | && scancode == 0x45) { |
| 177 | *keycode = E1_PAUSE; |
| 178 | prev_scancode = 0; |
| 179 | } else { |
| 180 | #ifdef KBD_REPORT_UNKN |
| 181 | if (!raw_mode) |
| 182 | printk(KERN_INFO |
| 183 | "keyboard: unknown e1 escape sequence\n"); |
| 184 | #endif |
| 185 | prev_scancode = 0; |
| 186 | return 0; |
| 187 | } |
| 188 | } else { |
| 189 | prev_scancode = 0; |
| 190 | /* |
| 191 | * The keyboard maintains its own internal caps lock and |
| 192 | * num lock statuses. In caps lock mode E0 AA precedes make |
| 193 | * code and E0 2A follows break code. In num lock mode, |
| 194 | * E0 2A precedes make code and E0 AA follows break code. |
| 195 | * We do our own book-keeping, so we will just ignore these. |
| 196 | */ |
| 197 | /* |
| 198 | * For my keyboard there is no caps lock mode, but there are |
| 199 | * both Shift-L and Shift-R modes. The former mode generates |
| 200 | * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs. |
| 201 | * So, we should also ignore the latter. - aeb@cwi.nl |
| 202 | */ |
| 203 | if (scancode == 0x2a || scancode == 0x36) |
| 204 | return 0; |
| 205 | |
| 206 | if (e0_keys[scancode]) |
| 207 | *keycode = e0_keys[scancode]; |
| 208 | else { |
| 209 | #ifdef KBD_REPORT_UNKN |
| 210 | if (!raw_mode) |
| 211 | printk(KERN_INFO |
| 212 | "keyboard: unknown scancode e0 %02x\n", |
| 213 | scancode); |
| 214 | #endif |
| 215 | return 0; |
| 216 | } |
| 217 | } |
| 218 | } else if (scancode >= SC_LIM) { |
| 219 | /* This happens with the FOCUS 9000 keyboard |
| 220 | Its keys PF1..PF12 are reported to generate |
| 221 | 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f |
| 222 | Moreover, unless repeated, they do not generate |
| 223 | key-down events, so we have to zero up_flag below */ |
| 224 | /* Also, Japanese 86/106 keyboards are reported to |
| 225 | generate 0x73 and 0x7d for \ - and \ | respectively. */ |
| 226 | /* Also, some Brazilian keyboard is reported to produce |
| 227 | 0x73 and 0x7e for \ ? and KP-dot, respectively. */ |
| 228 | |
| 229 | *keycode = high_keys[scancode - SC_LIM]; |
| 230 | |
| 231 | if (!*keycode) { |
| 232 | if (!raw_mode) { |
| 233 | #ifdef KBD_REPORT_UNKN |
| 234 | printk(KERN_INFO |
| 235 | "keyboard: unrecognized scancode (%02x)" |
| 236 | " - ignored\n", scancode); |
| 237 | #endif |
| 238 | } |
| 239 | return 0; |
| 240 | } |
| 241 | } else |
| 242 | *keycode = scancode; |
| 243 | return 1; |
| 244 | } |
| 245 | |
| 246 | static char gen_unexpected_up(unsigned char keycode) |
| 247 | { |
| 248 | /* unexpected, but this can happen: maybe this was a key release for a |
| 249 | FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */ |
| 250 | if (keycode >= SC_LIM || keycode == 85) |
| 251 | return 0; |
| 252 | else |
| 253 | return 0200; |
| 254 | } |
| 255 | |
| 256 | /* |
| 257 | * These are the default mappings |
| 258 | */ |
| 259 | int (*k_setkeycode)(unsigned int, unsigned int) = gen_setkeycode; |
| 260 | int (*k_getkeycode)(unsigned int) = gen_getkeycode; |
| 261 | int (*k_translate)(unsigned char, unsigned char *, char) = gen_translate; |
| 262 | char (*k_unexpected_up)(unsigned char) = gen_unexpected_up; |
| 263 | void (*k_leds)(unsigned char); |
| 264 | |
| 265 | /* Simple translation table for the SysRq keys */ |
| 266 | |
| 267 | #ifdef CONFIG_MAGIC_SYSRQ |
| 268 | static unsigned char gen_sysrq_xlate[128] = |
| 269 | "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ |
| 270 | "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ |
| 271 | "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ |
| 272 | "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ |
| 273 | "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ |
| 274 | "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ |
| 275 | "\r\000/"; /* 0x60 - 0x6f */ |
| 276 | |
| 277 | unsigned char *k_sysrq_xlate = gen_sysrq_xlate; |
| 278 | int k_sysrq_key = 0x54; |
| 279 | #endif |