blob: 3d211e8553f775c3166ab436db9830d97a9a2b74 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/char/keyboard.c
3 *
4 * Written for linux by Johan Myreen as a translation from
5 * the assembly version by Linus (with diacriticals added)
6 *
7 * Some additional features added by Christoph Niemann (ChN), March 1993
8 *
9 * Loadable keymaps by Risto Kankkunen, May 1993
10 *
11 * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
12 * Added decr/incr_console, dynamic keymaps, Unicode support,
13 * dynamic function/string keys, led setting, Sept 1994
14 * `Sticky' modifier keys, 951006.
15 *
16 * 11-11-96: SAK should now work in the raw mode (Martin Mares)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050017 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 * Modified to provide 'generic' keyboard support by Hamish Macdonald
19 * Merge with the m68k keyboard driver and split-off of the PC low-level
20 * parts by Geert Uytterhoeven, May 1997
21 *
22 * 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
23 * 30-07-98: Dead keys redone, aeb@cwi.nl.
24 * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
25 */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
28#include <linux/sched.h>
29#include <linux/tty.h>
30#include <linux/tty_flip.h>
31#include <linux/mm.h>
32#include <linux/string.h>
33#include <linux/init.h>
34#include <linux/slab.h>
David Howells7d12e782006-10-05 14:55:46 +010035#include <linux/irq.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
37#include <linux/kbd_kern.h>
38#include <linux/kbd_diacr.h>
39#include <linux/vt_kern.h>
40#include <linux/sysrq.h>
41#include <linux/input.h>
Adrian Bunk83cc5ed2006-06-25 05:47:41 -070042#include <linux/reboot.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
44static void kbd_disconnect(struct input_handle *handle);
45extern void ctrl_alt_del(void);
46
47/*
48 * Exported functions/variables
49 */
50
51#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
52
53/*
54 * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
55 * This seems a good reason to start with NumLock off. On HIL keyboards
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050056 * of PARISC machines however there is no NumLock key and everyone expects the keypad
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 * to be used for numbers.
58 */
59
60#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
61#define KBD_DEFLEDS (1 << VC_NUMLOCK)
62#else
63#define KBD_DEFLEDS 0
64#endif
65
66#define KBD_DEFLOCK 0
67
68void compute_shiftstate(void);
69
70/*
71 * Handler Tables.
72 */
73
74#define K_HANDLERS\
75 k_self, k_fn, k_spec, k_pad,\
76 k_dead, k_cons, k_cur, k_shift,\
77 k_meta, k_ascii, k_lock, k_lowercase,\
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -050078 k_slock, k_dead2, k_brl, k_ignore
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050080typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
David Howells7d12e782006-10-05 14:55:46 +010081 char up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -070082static k_handler_fn K_HANDLERS;
83static k_handler_fn *k_handler[16] = { K_HANDLERS };
84
85#define FN_HANDLERS\
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050086 fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
87 fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
88 fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
89 fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
90 fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
David Howells7d12e782006-10-05 14:55:46 +010092typedef void (fn_handler_fn)(struct vc_data *vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070093static fn_handler_fn FN_HANDLERS;
94static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
95
96/*
97 * Variables exported for vt_ioctl.c
98 */
99
100/* maximum values each key_handler can handle */
101const int max_vals[] = {
102 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
103 NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500104 255, NR_LOCK - 1, 255, NR_BRL - 1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105};
106
107const int NR_TYPES = ARRAY_SIZE(max_vals);
108
109struct kbd_struct kbd_table[MAX_NR_CONSOLES];
110static struct kbd_struct *kbd = kbd_table;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700112struct vt_spawn_console vt_spawn_con = {
113 .lock = SPIN_LOCK_UNLOCKED,
114 .pid = NULL,
115 .sig = 0,
116};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118/*
119 * Variables exported for vt.c
120 */
121
122int shift_state = 0;
123
124/*
125 * Internal Data.
126 */
127
128static struct input_handler kbd_handler;
129static unsigned long key_down[NBITS(KEY_MAX)]; /* keyboard key bitmap */
130static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
131static int dead_key_next;
132static int npadch = -1; /* -1 or number assembled on pad */
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500133static unsigned int diacr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134static char rep; /* flag telling character repeat */
135
136static unsigned char ledstate = 0xff; /* undefined */
137static unsigned char ledioctl;
138
139static struct ledptr {
140 unsigned int *addr;
141 unsigned int mask;
142 unsigned char valid:1;
143} ledptrs[3];
144
145/* Simple translation table for the SysRq keys */
146
147#ifdef CONFIG_MAGIC_SYSRQ
148unsigned char kbd_sysrq_xlate[KEY_MAX + 1] =
149 "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
150 "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
151 "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
152 "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
153 "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
154 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
155 "\r\000/"; /* 0x60 - 0x6f */
156static int sysrq_down;
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -0700157static int sysrq_alt_use;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158#endif
159static int sysrq_alt;
160
161/*
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400162 * Translation of scancodes to keycodes. We set them on only the first
163 * keyboard in the list that accepts the scancode and keycode.
164 * Explanation for not choosing the first attached keyboard anymore:
165 * USB keyboards for example have two event devices: one for all "normal"
166 * keys and one for extra function keys (like "volume up", "make coffee",
167 * etc.). So this means that scancodes for the extra function keys won't
168 * be valid for the first event device, but will be for the second.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 */
170int getkeycode(unsigned int scancode)
171{
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400172 struct input_handle *handle;
173 int keycode;
174 int error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400176 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
177 error = handle->dev->getkeycode(handle->dev, scancode, &keycode);
178 if (!error)
179 return keycode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 }
181
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400182 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183}
184
185int setkeycode(unsigned int scancode, unsigned int keycode)
186{
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400187 struct input_handle *handle;
188 int error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400190 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
191 error = handle->dev->setkeycode(handle->dev, scancode, keycode);
192 if (!error)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500193 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 }
195
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400196 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197}
198
199/*
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500200 * Making beeps and bells.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 */
202static void kd_nosound(unsigned long ignored)
203{
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400204 struct input_handle *handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400206 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 if (test_bit(EV_SND, handle->dev->evbit)) {
208 if (test_bit(SND_TONE, handle->dev->sndbit))
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400209 input_inject_event(handle, EV_SND, SND_TONE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 if (test_bit(SND_BELL, handle->dev->sndbit))
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400211 input_inject_event(handle, EV_SND, SND_BELL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 }
213 }
214}
215
Ingo Molnar8d06afa2005-09-09 13:10:40 -0700216static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
218void kd_mksound(unsigned int hz, unsigned int ticks)
219{
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500220 struct list_head *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
222 del_timer(&kd_mksound_timer);
223
224 if (hz) {
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500225 list_for_each_prev(node, &kbd_handler.h_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 struct input_handle *handle = to_handle_h(node);
227 if (test_bit(EV_SND, handle->dev->evbit)) {
228 if (test_bit(SND_TONE, handle->dev->sndbit)) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400229 input_inject_event(handle, EV_SND, SND_TONE, hz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 break;
231 }
232 if (test_bit(SND_BELL, handle->dev->sndbit)) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400233 input_inject_event(handle, EV_SND, SND_BELL, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 break;
235 }
236 }
237 }
238 if (ticks)
239 mod_timer(&kd_mksound_timer, jiffies + ticks);
240 } else
241 kd_nosound(0);
242}
243
244/*
245 * Setting the keyboard rate.
246 */
247
248int kbd_rate(struct kbd_repeat *rep)
249{
250 struct list_head *node;
251 unsigned int d = 0;
252 unsigned int p = 0;
253
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400254 list_for_each(node, &kbd_handler.h_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 struct input_handle *handle = to_handle_h(node);
256 struct input_dev *dev = handle->dev;
257
258 if (test_bit(EV_REP, dev->evbit)) {
259 if (rep->delay > 0)
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400260 input_inject_event(handle, EV_REP, REP_DELAY, rep->delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 if (rep->period > 0)
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400262 input_inject_event(handle, EV_REP, REP_PERIOD, rep->period);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 d = dev->rep[REP_DELAY];
264 p = dev->rep[REP_PERIOD];
265 }
266 }
267 rep->delay = d;
268 rep->period = p;
269 return 0;
270}
271
272/*
273 * Helper Functions.
274 */
275static void put_queue(struct vc_data *vc, int ch)
276{
277 struct tty_struct *tty = vc->vc_tty;
278
279 if (tty) {
280 tty_insert_flip_char(tty, ch, 0);
281 con_schedule_flip(tty);
282 }
283}
284
285static void puts_queue(struct vc_data *vc, char *cp)
286{
287 struct tty_struct *tty = vc->vc_tty;
288
289 if (!tty)
290 return;
291
292 while (*cp) {
293 tty_insert_flip_char(tty, *cp, 0);
294 cp++;
295 }
296 con_schedule_flip(tty);
297}
298
299static void applkey(struct vc_data *vc, int key, char mode)
300{
301 static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
302
303 buf[1] = (mode ? 'O' : '[');
304 buf[2] = key;
305 puts_queue(vc, buf);
306}
307
308/*
309 * Many other routines do put_queue, but I think either
310 * they produce ASCII, or they produce some user-assigned
311 * string, and in both cases we might assume that it is
312 * in utf-8 already. UTF-8 is defined for words of up to 31 bits,
313 * but we need only 16 bits here
314 */
315static void to_utf8(struct vc_data *vc, ushort c)
316{
317 if (c < 0x80)
318 /* 0******* */
319 put_queue(vc, c);
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500320 else if (c < 0x800) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 /* 110***** 10****** */
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500322 put_queue(vc, 0xc0 | (c >> 6));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500324 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 /* 1110**** 10****** 10****** */
326 put_queue(vc, 0xe0 | (c >> 12));
327 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
328 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330}
331
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500332/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 * Called after returning from RAW mode or when changing consoles - recompute
334 * shift_down[] and shift_state from key_down[] maybe called when keymap is
335 * undefined, so that shiftkey release is seen
336 */
337void compute_shiftstate(void)
338{
339 unsigned int i, j, k, sym, val;
340
341 shift_state = 0;
342 memset(shift_down, 0, sizeof(shift_down));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500343
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 for (i = 0; i < ARRAY_SIZE(key_down); i++) {
345
346 if (!key_down[i])
347 continue;
348
349 k = i * BITS_PER_LONG;
350
351 for (j = 0; j < BITS_PER_LONG; j++, k++) {
352
353 if (!test_bit(k, key_down))
354 continue;
355
356 sym = U(key_maps[0][k]);
357 if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
358 continue;
359
360 val = KVAL(sym);
361 if (val == KVAL(K_CAPSSHIFT))
362 val = KVAL(K_SHIFT);
363
364 shift_down[val]++;
365 shift_state |= (1 << val);
366 }
367 }
368}
369
370/*
371 * We have a combining character DIACR here, followed by the character CH.
372 * If the combination occurs in the table, return the corresponding value.
373 * Otherwise, if CH is a space or equals DIACR, return DIACR.
374 * Otherwise, conclude that DIACR was not combining after all,
375 * queue it and return CH.
376 */
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500377static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378{
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500379 unsigned int d = diacr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 unsigned int i;
381
382 diacr = 0;
383
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500384 if ((d & ~0xff) == BRL_UC_ROW) {
385 if ((ch & ~0xff) == BRL_UC_ROW)
386 return d | ch;
387 } else {
388 for (i = 0; i < accent_table_size; i++)
389 if (accent_table[i].diacr == d && accent_table[i].base == ch)
390 return accent_table[i].result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 }
392
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500393 if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 return d;
395
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500396 if (kbd->kbdmode == VC_UNICODE)
397 to_utf8(vc, d);
398 else if (d < 0x100)
399 put_queue(vc, d);
400
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 return ch;
402}
403
404/*
405 * Special function handlers
406 */
David Howells7d12e782006-10-05 14:55:46 +0100407static void fn_enter(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408{
409 if (diacr) {
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500410 if (kbd->kbdmode == VC_UNICODE)
411 to_utf8(vc, diacr);
412 else if (diacr < 0x100)
413 put_queue(vc, diacr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 diacr = 0;
415 }
416 put_queue(vc, 13);
417 if (vc_kbd_mode(kbd, VC_CRLF))
418 put_queue(vc, 10);
419}
420
David Howells7d12e782006-10-05 14:55:46 +0100421static void fn_caps_toggle(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422{
423 if (rep)
424 return;
425 chg_vc_kbd_led(kbd, VC_CAPSLOCK);
426}
427
David Howells7d12e782006-10-05 14:55:46 +0100428static void fn_caps_on(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429{
430 if (rep)
431 return;
432 set_vc_kbd_led(kbd, VC_CAPSLOCK);
433}
434
David Howells7d12e782006-10-05 14:55:46 +0100435static void fn_show_ptregs(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436{
David Howells7d12e782006-10-05 14:55:46 +0100437 struct pt_regs *regs = get_irq_regs();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 if (regs)
439 show_regs(regs);
440}
441
David Howells7d12e782006-10-05 14:55:46 +0100442static void fn_hold(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443{
444 struct tty_struct *tty = vc->vc_tty;
445
446 if (rep || !tty)
447 return;
448
449 /*
450 * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
451 * these routines are also activated by ^S/^Q.
452 * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
453 */
454 if (tty->stopped)
455 start_tty(tty);
456 else
457 stop_tty(tty);
458}
459
David Howells7d12e782006-10-05 14:55:46 +0100460static void fn_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461{
462 if (vc_kbd_mode(kbd,VC_APPLIC))
463 applkey(vc, 'P', 1);
464 else
David Howells7d12e782006-10-05 14:55:46 +0100465 fn_bare_num(vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466}
467
468/*
469 * Bind this to Shift-NumLock if you work in application keypad mode
470 * but want to be able to change the NumLock flag.
471 * Bind this to NumLock if you prefer that the NumLock key always
472 * changes the NumLock flag.
473 */
David Howells7d12e782006-10-05 14:55:46 +0100474static void fn_bare_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475{
476 if (!rep)
477 chg_vc_kbd_led(kbd, VC_NUMLOCK);
478}
479
David Howells7d12e782006-10-05 14:55:46 +0100480static void fn_lastcons(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481{
482 /* switch to the last used console, ChN */
483 set_console(last_console);
484}
485
David Howells7d12e782006-10-05 14:55:46 +0100486static void fn_dec_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
488 int i, cur = fg_console;
489
490 /* Currently switching? Queue this next switch relative to that. */
491 if (want_console != -1)
492 cur = want_console;
493
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500494 for (i = cur - 1; i != cur; i--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 if (i == -1)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500496 i = MAX_NR_CONSOLES - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 if (vc_cons_allocated(i))
498 break;
499 }
500 set_console(i);
501}
502
David Howells7d12e782006-10-05 14:55:46 +0100503static void fn_inc_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504{
505 int i, cur = fg_console;
506
507 /* Currently switching? Queue this next switch relative to that. */
508 if (want_console != -1)
509 cur = want_console;
510
511 for (i = cur+1; i != cur; i++) {
512 if (i == MAX_NR_CONSOLES)
513 i = 0;
514 if (vc_cons_allocated(i))
515 break;
516 }
517 set_console(i);
518}
519
David Howells7d12e782006-10-05 14:55:46 +0100520static void fn_send_intr(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521{
522 struct tty_struct *tty = vc->vc_tty;
523
524 if (!tty)
525 return;
526 tty_insert_flip_char(tty, 0, TTY_BREAK);
527 con_schedule_flip(tty);
528}
529
David Howells7d12e782006-10-05 14:55:46 +0100530static void fn_scroll_forw(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531{
532 scrollfront(vc, 0);
533}
534
David Howells7d12e782006-10-05 14:55:46 +0100535static void fn_scroll_back(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536{
537 scrollback(vc, 0);
538}
539
David Howells7d12e782006-10-05 14:55:46 +0100540static void fn_show_mem(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541{
542 show_mem();
543}
544
David Howells7d12e782006-10-05 14:55:46 +0100545static void fn_show_state(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546{
547 show_state();
548}
549
David Howells7d12e782006-10-05 14:55:46 +0100550static void fn_boot_it(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551{
552 ctrl_alt_del();
553}
554
David Howells7d12e782006-10-05 14:55:46 +0100555static void fn_compose(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556{
557 dead_key_next = 1;
558}
559
David Howells7d12e782006-10-05 14:55:46 +0100560static void fn_spawn_con(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561{
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700562 spin_lock(&vt_spawn_con.lock);
563 if (vt_spawn_con.pid)
564 if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
565 put_pid(vt_spawn_con.pid);
566 vt_spawn_con.pid = NULL;
567 }
568 spin_unlock(&vt_spawn_con.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569}
570
David Howells7d12e782006-10-05 14:55:46 +0100571static void fn_SAK(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572{
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800573 struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800574 schedule_work(SAK_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575}
576
David Howells7d12e782006-10-05 14:55:46 +0100577static void fn_null(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578{
579 compute_shiftstate();
580}
581
582/*
583 * Special key handlers
584 */
David Howells7d12e782006-10-05 14:55:46 +0100585static void k_ignore(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586{
587}
588
David Howells7d12e782006-10-05 14:55:46 +0100589static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590{
591 if (up_flag)
592 return;
593 if (value >= ARRAY_SIZE(fn_handler))
594 return;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500595 if ((kbd->kbdmode == VC_RAW ||
596 kbd->kbdmode == VC_MEDIUMRAW) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 value != KVAL(K_SAK))
598 return; /* SAK is allowed even in raw mode */
David Howells7d12e782006-10-05 14:55:46 +0100599 fn_handler[value](vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600}
601
David Howells7d12e782006-10-05 14:55:46 +0100602static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
604 printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
605}
606
David Howells7d12e782006-10-05 14:55:46 +0100607static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608{
609 if (up_flag)
610 return; /* no action, if this is a key release */
611
612 if (diacr)
613 value = handle_diacr(vc, value);
614
615 if (dead_key_next) {
616 dead_key_next = 0;
617 diacr = value;
618 return;
619 }
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500620 if (kbd->kbdmode == VC_UNICODE)
621 to_utf8(vc, value);
622 else if (value < 0x100)
623 put_queue(vc, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624}
625
626/*
627 * Handle dead key. Note that we now may have several
628 * dead keys modifying the same character. Very useful
629 * for Vietnamese.
630 */
David Howells7d12e782006-10-05 14:55:46 +0100631static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632{
633 if (up_flag)
634 return;
635 diacr = (diacr ? handle_diacr(vc, value) : value);
636}
637
David Howells7d12e782006-10-05 14:55:46 +0100638static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500639{
David Howells7d12e782006-10-05 14:55:46 +0100640 k_unicode(vc, value, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500641}
642
David Howells7d12e782006-10-05 14:55:46 +0100643static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500644{
David Howells7d12e782006-10-05 14:55:46 +0100645 k_deadunicode(vc, value, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500646}
647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648/*
649 * Obsolete - for backwards compatibility only
650 */
David Howells7d12e782006-10-05 14:55:46 +0100651static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652{
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400653 static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 value = ret_diacr[value];
David Howells7d12e782006-10-05 14:55:46 +0100655 k_deadunicode(vc, value, up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656}
657
David Howells7d12e782006-10-05 14:55:46 +0100658static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659{
660 if (up_flag)
661 return;
662 set_console(value);
663}
664
David Howells7d12e782006-10-05 14:55:46 +0100665static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666{
667 unsigned v;
668
669 if (up_flag)
670 return;
671 v = value;
672 if (v < ARRAY_SIZE(func_table)) {
673 if (func_table[value])
674 puts_queue(vc, func_table[value]);
675 } else
676 printk(KERN_ERR "k_fn called with value=%d\n", value);
677}
678
David Howells7d12e782006-10-05 14:55:46 +0100679static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680{
Brandon Philipse52b29c2006-11-04 22:09:08 -0500681 static const char cur_chars[] = "BDCA";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
683 if (up_flag)
684 return;
685 applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
686}
687
David Howells7d12e782006-10-05 14:55:46 +0100688static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400690 static const char pad_chars[] = "0123456789+-*/\015,.?()#";
691 static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693 if (up_flag)
694 return; /* no action, if this is a key release */
695
696 /* kludge... shift forces cursor/number keys */
697 if (vc_kbd_mode(kbd, VC_APPLIC) && !shift_down[KG_SHIFT]) {
698 applkey(vc, app_map[value], 1);
699 return;
700 }
701
702 if (!vc_kbd_led(kbd, VC_NUMLOCK))
703 switch (value) {
704 case KVAL(K_PCOMMA):
705 case KVAL(K_PDOT):
David Howells7d12e782006-10-05 14:55:46 +0100706 k_fn(vc, KVAL(K_REMOVE), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 return;
708 case KVAL(K_P0):
David Howells7d12e782006-10-05 14:55:46 +0100709 k_fn(vc, KVAL(K_INSERT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 return;
711 case KVAL(K_P1):
David Howells7d12e782006-10-05 14:55:46 +0100712 k_fn(vc, KVAL(K_SELECT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 return;
714 case KVAL(K_P2):
David Howells7d12e782006-10-05 14:55:46 +0100715 k_cur(vc, KVAL(K_DOWN), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 return;
717 case KVAL(K_P3):
David Howells7d12e782006-10-05 14:55:46 +0100718 k_fn(vc, KVAL(K_PGDN), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 return;
720 case KVAL(K_P4):
David Howells7d12e782006-10-05 14:55:46 +0100721 k_cur(vc, KVAL(K_LEFT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 return;
723 case KVAL(K_P6):
David Howells7d12e782006-10-05 14:55:46 +0100724 k_cur(vc, KVAL(K_RIGHT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 return;
726 case KVAL(K_P7):
David Howells7d12e782006-10-05 14:55:46 +0100727 k_fn(vc, KVAL(K_FIND), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 return;
729 case KVAL(K_P8):
David Howells7d12e782006-10-05 14:55:46 +0100730 k_cur(vc, KVAL(K_UP), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 return;
732 case KVAL(K_P9):
David Howells7d12e782006-10-05 14:55:46 +0100733 k_fn(vc, KVAL(K_PGUP), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 return;
735 case KVAL(K_P5):
736 applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
737 return;
738 }
739
740 put_queue(vc, pad_chars[value]);
741 if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
742 put_queue(vc, 10);
743}
744
David Howells7d12e782006-10-05 14:55:46 +0100745static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746{
747 int old_state = shift_state;
748
749 if (rep)
750 return;
751 /*
752 * Mimic typewriter:
753 * a CapsShift key acts like Shift but undoes CapsLock
754 */
755 if (value == KVAL(K_CAPSSHIFT)) {
756 value = KVAL(K_SHIFT);
757 if (!up_flag)
758 clr_vc_kbd_led(kbd, VC_CAPSLOCK);
759 }
760
761 if (up_flag) {
762 /*
763 * handle the case that two shift or control
764 * keys are depressed simultaneously
765 */
766 if (shift_down[value])
767 shift_down[value]--;
768 } else
769 shift_down[value]++;
770
771 if (shift_down[value])
772 shift_state |= (1 << value);
773 else
774 shift_state &= ~(1 << value);
775
776 /* kludge */
777 if (up_flag && shift_state != old_state && npadch != -1) {
778 if (kbd->kbdmode == VC_UNICODE)
779 to_utf8(vc, npadch & 0xffff);
780 else
781 put_queue(vc, npadch & 0xff);
782 npadch = -1;
783 }
784}
785
David Howells7d12e782006-10-05 14:55:46 +0100786static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787{
788 if (up_flag)
789 return;
790
791 if (vc_kbd_mode(kbd, VC_META)) {
792 put_queue(vc, '\033');
793 put_queue(vc, value);
794 } else
795 put_queue(vc, value | 0x80);
796}
797
David Howells7d12e782006-10-05 14:55:46 +0100798static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799{
800 int base;
801
802 if (up_flag)
803 return;
804
805 if (value < 10) {
806 /* decimal input of code, while Alt depressed */
807 base = 10;
808 } else {
809 /* hexadecimal input of code, while AltGr depressed */
810 value -= 10;
811 base = 16;
812 }
813
814 if (npadch == -1)
815 npadch = value;
816 else
817 npadch = npadch * base + value;
818}
819
David Howells7d12e782006-10-05 14:55:46 +0100820static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821{
822 if (up_flag || rep)
823 return;
824 chg_vc_kbd_lock(kbd, value);
825}
826
David Howells7d12e782006-10-05 14:55:46 +0100827static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828{
David Howells7d12e782006-10-05 14:55:46 +0100829 k_shift(vc, value, up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 if (up_flag || rep)
831 return;
832 chg_vc_kbd_slock(kbd, value);
833 /* try to make Alt, oops, AltGr and such work */
834 if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
835 kbd->slockstate = 0;
836 chg_vc_kbd_slock(kbd, value);
837 }
838}
839
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500840/* by default, 300ms interval for combination release */
Samuel Thibault77426d72006-04-26 00:14:10 -0400841static unsigned brl_timeout = 300;
842MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
843module_param(brl_timeout, uint, 0644);
844
845static unsigned brl_nbchords = 1;
846MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
847module_param(brl_nbchords, uint, 0644);
848
David Howells7d12e782006-10-05 14:55:46 +0100849static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag)
Samuel Thibault77426d72006-04-26 00:14:10 -0400850{
851 static unsigned long chords;
852 static unsigned committed;
853
854 if (!brl_nbchords)
David Howells7d12e782006-10-05 14:55:46 +0100855 k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400856 else {
857 committed |= pattern;
858 chords++;
859 if (chords == brl_nbchords) {
David Howells7d12e782006-10-05 14:55:46 +0100860 k_unicode(vc, BRL_UC_ROW | committed, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400861 chords = 0;
862 committed = 0;
863 }
864 }
865}
866
David Howells7d12e782006-10-05 14:55:46 +0100867static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500868{
869 static unsigned pressed,committing;
870 static unsigned long releasestart;
871
872 if (kbd->kbdmode != VC_UNICODE) {
873 if (!up_flag)
874 printk("keyboard mode must be unicode for braille patterns\n");
875 return;
876 }
877
878 if (!value) {
David Howells7d12e782006-10-05 14:55:46 +0100879 k_unicode(vc, BRL_UC_ROW, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500880 return;
881 }
882
883 if (value > 8)
884 return;
885
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500886 if (up_flag) {
887 if (brl_timeout) {
888 if (!committing ||
889 jiffies - releasestart > (brl_timeout * HZ) / 1000) {
890 committing = pressed;
891 releasestart = jiffies;
892 }
893 pressed &= ~(1 << (value - 1));
894 if (!pressed) {
895 if (committing) {
David Howells7d12e782006-10-05 14:55:46 +0100896 k_brlcommit(vc, committing, 0);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500897 committing = 0;
898 }
899 }
900 } else {
901 if (committing) {
David Howells7d12e782006-10-05 14:55:46 +0100902 k_brlcommit(vc, committing, 0);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500903 committing = 0;
904 }
905 pressed &= ~(1 << (value - 1));
906 }
907 } else {
908 pressed |= 1 << (value - 1);
909 if (!brl_timeout)
910 committing = pressed;
911 }
912}
913
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914/*
915 * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
916 * or (ii) whatever pattern of lights people want to show using KDSETLED,
917 * or (iii) specified bits of specified words in kernel memory.
918 */
919unsigned char getledstate(void)
920{
921 return ledstate;
922}
923
924void setledstate(struct kbd_struct *kbd, unsigned int led)
925{
926 if (!(led & ~7)) {
927 ledioctl = led;
928 kbd->ledmode = LED_SHOW_IOCTL;
929 } else
930 kbd->ledmode = LED_SHOW_FLAGS;
931 set_leds();
932}
933
934static inline unsigned char getleds(void)
935{
936 struct kbd_struct *kbd = kbd_table + fg_console;
937 unsigned char leds;
938 int i;
939
940 if (kbd->ledmode == LED_SHOW_IOCTL)
941 return ledioctl;
942
943 leds = kbd->ledflagstate;
944
945 if (kbd->ledmode == LED_SHOW_MEM) {
946 for (i = 0; i < 3; i++)
947 if (ledptrs[i].valid) {
948 if (*ledptrs[i].addr & ledptrs[i].mask)
949 leds |= (1 << i);
950 else
951 leds &= ~(1 << i);
952 }
953 }
954 return leds;
955}
956
957/*
958 * This routine is the bottom half of the keyboard interrupt
959 * routine, and runs with all interrupts enabled. It does
960 * console changing, led setting and copy_to_cooked, which can
961 * take a reasonably long time.
962 *
963 * Aside from timing (which isn't really that important for
964 * keyboard interrupts as they happen often), using the software
965 * interrupt routines for this thing allows us to easily mask
966 * this when we don't want any of the above to happen.
967 * This allows for easy and efficient race-condition prevention
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400968 * for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 */
970
971static void kbd_bh(unsigned long dummy)
972{
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500973 struct list_head *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 unsigned char leds = getleds();
975
976 if (leds != ledstate) {
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500977 list_for_each(node, &kbd_handler.h_list) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400978 struct input_handle *handle = to_handle_h(node);
979 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
980 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
981 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
982 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 }
984 }
985
986 ledstate = leds;
987}
988
989DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
990
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
Adrian Bunk0b57ee92005-12-22 21:03:47 -0800992 defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
993 defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
995
996#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
997 ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
998
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400999static const unsigned short x86_keycodes[256] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1001 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1002 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
1003 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
1004 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
1005 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001006 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
1008 360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
1009 103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
1010 291,108,381,281,290,272,292,305,280, 99,112,257,258,359,113,114,
1011 264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
1012 377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
1013 308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
1014 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
1015
1016#ifdef CONFIG_MAC_EMUMOUSEBTN
1017extern int mac_hid_mouse_emulate_buttons(int, int, int);
1018#endif /* CONFIG_MAC_EMUMOUSEBTN */
1019
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001020#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021static int sparc_l1_a_state = 0;
1022extern void sun_do_break(void);
1023#endif
1024
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001025static int emulate_raw(struct vc_data *vc, unsigned int keycode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 unsigned char up_flag)
1027{
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001028 int code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
1030 switch (keycode) {
1031 case KEY_PAUSE:
1032 put_queue(vc, 0xe1);
1033 put_queue(vc, 0x1d | up_flag);
1034 put_queue(vc, 0x45 | up_flag);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001035 break;
1036
Jerome Pinotb9ab58d2006-06-26 01:51:23 -04001037 case KEY_HANGEUL:
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -04001038 if (!up_flag)
1039 put_queue(vc, 0xf2);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001040 break;
1041
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 case KEY_HANJA:
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -04001043 if (!up_flag)
1044 put_queue(vc, 0xf1);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001045 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001047 case KEY_SYSRQ:
1048 /*
1049 * Real AT keyboards (that's what we're trying
1050 * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
1051 * pressing PrtSc/SysRq alone, but simply 0x54
1052 * when pressing Alt+PrtSc/SysRq.
1053 */
1054 if (sysrq_alt) {
1055 put_queue(vc, 0x54 | up_flag);
1056 } else {
1057 put_queue(vc, 0xe0);
1058 put_queue(vc, 0x2a | up_flag);
1059 put_queue(vc, 0xe0);
1060 put_queue(vc, 0x37 | up_flag);
1061 }
1062 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001064 default:
1065 if (keycode > 255)
1066 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001068 code = x86_keycodes[keycode];
1069 if (!code)
1070 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001072 if (code & 0x100)
1073 put_queue(vc, 0xe0);
1074 put_queue(vc, (code & 0x7f) | up_flag);
1075
1076 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 }
1078
1079 return 0;
1080}
1081
1082#else
1083
1084#define HW_RAW(dev) 0
1085
1086#warning "Cannot generate rawmode keyboard for your architecture yet."
1087
1088static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
1089{
1090 if (keycode > 127)
1091 return -1;
1092
1093 put_queue(vc, keycode | up_flag);
1094 return 0;
1095}
1096#endif
1097
1098static void kbd_rawcode(unsigned char data)
1099{
1100 struct vc_data *vc = vc_cons[fg_console].d;
1101 kbd = kbd_table + fg_console;
1102 if (kbd->kbdmode == VC_RAW)
1103 put_queue(vc, data);
1104}
1105
David Howells7d12e782006-10-05 14:55:46 +01001106static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107{
1108 struct vc_data *vc = vc_cons[fg_console].d;
1109 unsigned short keysym, *key_map;
1110 unsigned char type, raw_mode;
1111 struct tty_struct *tty;
1112 int shift_final;
1113
1114 tty = vc->vc_tty;
1115
1116 if (tty && (!tty->driver_data)) {
1117 /* No driver data? Strange. Okay we fix it then. */
1118 tty->driver_data = vc;
1119 }
1120
1121 kbd = kbd_table + fg_console;
1122
1123 if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001124 sysrq_alt = down ? keycode : 0;
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001125#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 if (keycode == KEY_STOP)
1127 sparc_l1_a_state = down;
1128#endif
1129
1130 rep = (down == 2);
1131
1132#ifdef CONFIG_MAC_EMUMOUSEBTN
1133 if (mac_hid_mouse_emulate_buttons(1, keycode, down))
1134 return;
1135#endif /* CONFIG_MAC_EMUMOUSEBTN */
1136
1137 if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
1138 if (emulate_raw(vc, keycode, !down << 7))
1139 if (keycode < BTN_MISC)
1140 printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
1141
1142#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
1143 if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001144 if (!sysrq_down) {
1145 sysrq_down = down;
1146 sysrq_alt_use = sysrq_alt;
1147 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 return;
1149 }
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001150 if (sysrq_down && !down && keycode == sysrq_alt_use)
1151 sysrq_down = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 if (sysrq_down && down && !rep) {
David Howells7d12e782006-10-05 14:55:46 +01001153 handle_sysrq(kbd_sysrq_xlate[keycode], tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 return;
1155 }
1156#endif
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001157#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 if (keycode == KEY_A && sparc_l1_a_state) {
1159 sparc_l1_a_state = 0;
1160 sun_do_break();
1161 }
1162#endif
1163
1164 if (kbd->kbdmode == VC_MEDIUMRAW) {
1165 /*
1166 * This is extended medium raw mode, with keys above 127
1167 * encoded as 0, high 7 bits, low 7 bits, with the 0 bearing
1168 * the 'up' flag if needed. 0 is reserved, so this shouldn't
1169 * interfere with anything else. The two bytes after 0 will
1170 * always have the up flag set not to interfere with older
1171 * applications. This allows for 16384 different keycodes,
1172 * which should be enough.
1173 */
1174 if (keycode < 128) {
1175 put_queue(vc, keycode | (!down << 7));
1176 } else {
1177 put_queue(vc, !down << 7);
1178 put_queue(vc, (keycode >> 7) | 0x80);
1179 put_queue(vc, keycode | 0x80);
1180 }
1181 raw_mode = 1;
1182 }
1183
1184 if (down)
1185 set_bit(keycode, key_down);
1186 else
1187 clear_bit(keycode, key_down);
1188
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001189 if (rep &&
1190 (!vc_kbd_mode(kbd, VC_REPEAT) ||
1191 (tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 /*
1193 * Don't repeat a key if the input buffers are not empty and the
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001194 * characters get aren't echoed locally. This makes key repeat
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 * usable with slow applications and under heavy loads.
1196 */
1197 return;
1198 }
1199
1200 shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
1201 key_map = key_maps[shift_final];
1202
1203 if (!key_map) {
1204 compute_shiftstate();
1205 kbd->slockstate = 0;
1206 return;
1207 }
1208
1209 if (keycode > NR_KEYS)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -05001210 if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
1211 keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
1212 else
1213 return;
1214 else
1215 keysym = key_map[keycode];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 type = KTYP(keysym);
1218
1219 if (type < 0xf0) {
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001220 if (down && !raw_mode)
1221 to_utf8(vc, keysym);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 return;
1223 }
1224
1225 type -= 0xf0;
1226
1227 if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
1228 return;
1229
1230 if (type == KT_LETTER) {
1231 type = KT_LATIN;
1232 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
1233 key_map = key_maps[shift_final ^ (1 << KG_SHIFT)];
1234 if (key_map)
1235 keysym = key_map[keycode];
1236 }
1237 }
1238
David Howells7d12e782006-10-05 14:55:46 +01001239 (*k_handler[type])(vc, keysym & 0xff, !down);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
1241 if (type != KT_SLOCK)
1242 kbd->slockstate = 0;
1243}
1244
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001245static void kbd_event(struct input_handle *handle, unsigned int event_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 unsigned int event_code, int value)
1247{
1248 if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
1249 kbd_rawcode(value);
1250 if (event_type == EV_KEY)
David Howells7d12e782006-10-05 14:55:46 +01001251 kbd_keycode(event_code, value, HW_RAW(handle->dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 tasklet_schedule(&keyboard_tasklet);
1253 do_poke_blanked_console = 1;
1254 schedule_console_callback();
1255}
1256
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257/*
1258 * When a keyboard (or other input device) is found, the kbd_connect
1259 * function is called. The function then looks at the device, and if it
1260 * likes it, it can open it and get events from it. In this (kbd_connect)
1261 * function, we should decide which VT to bind that keyboard to initially.
1262 */
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001263static struct input_handle *kbd_connect(struct input_handler *handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 struct input_dev *dev,
Dmitry Torokhov66e66112006-09-14 01:31:59 -04001265 const struct input_device_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266{
1267 struct input_handle *handle;
1268 int i;
1269
1270 for (i = KEY_RESERVED; i < BTN_MISC; i++)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001271 if (test_bit(i, dev->keybit))
1272 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001274 if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 return NULL;
1276
Dmitry Torokhov22479e12006-08-04 22:51:51 -04001277 handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
1278 if (!handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
1281 handle->dev = dev;
1282 handle->handler = handler;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001283 handle->name = "kbd";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
1285 input_open_device(handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286
1287 return handle;
1288}
1289
1290static void kbd_disconnect(struct input_handle *handle)
1291{
1292 input_close_device(handle);
1293 kfree(handle);
1294}
1295
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001296/*
1297 * Start keyboard handler on the new keyboard by refreshing LED state to
1298 * match the rest of the system.
1299 */
1300static void kbd_start(struct input_handle *handle)
1301{
1302 unsigned char leds = ledstate;
1303
1304 tasklet_disable(&keyboard_tasklet);
1305 if (leds != 0xff) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -04001306 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
1307 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
1308 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
1309 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001310 }
1311 tasklet_enable(&keyboard_tasklet);
1312}
1313
Dmitry Torokhov66e66112006-09-14 01:31:59 -04001314static const struct input_device_id kbd_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 {
1316 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1317 .evbit = { BIT(EV_KEY) },
1318 },
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001319
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 {
1321 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1322 .evbit = { BIT(EV_SND) },
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001323 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324
1325 { }, /* Terminating entry */
1326};
1327
1328MODULE_DEVICE_TABLE(input, kbd_ids);
1329
1330static struct input_handler kbd_handler = {
1331 .event = kbd_event,
1332 .connect = kbd_connect,
1333 .disconnect = kbd_disconnect,
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001334 .start = kbd_start,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 .name = "kbd",
1336 .id_table = kbd_ids,
1337};
1338
1339int __init kbd_init(void)
1340{
1341 int i;
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001342 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343
Dmitry Torokhov2b192902006-07-19 01:13:26 -04001344 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1345 kbd_table[i].ledflagstate = KBD_DEFLEDS;
1346 kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
1347 kbd_table[i].ledmode = LED_SHOW_FLAGS;
1348 kbd_table[i].lockstate = KBD_DEFLOCK;
1349 kbd_table[i].slockstate = 0;
1350 kbd_table[i].modeflags = KBD_DEFMODE;
1351 kbd_table[i].kbdmode = VC_XLATE;
1352 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001354 error = input_register_handler(&kbd_handler);
1355 if (error)
1356 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
1358 tasklet_enable(&keyboard_tasklet);
1359 tasklet_schedule(&keyboard_tasklet);
1360
1361 return 0;
1362}