blob: 1b094509b1d2fdb5acaebb980a7e157c3b592b2e [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070044extern void ctrl_alt_del(void);
45
46/*
47 * Exported functions/variables
48 */
49
50#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
51
52/*
53 * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
54 * This seems a good reason to start with NumLock off. On HIL keyboards
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050055 * of PARISC machines however there is no NumLock key and everyone expects the keypad
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 * to be used for numbers.
57 */
58
59#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
60#define KBD_DEFLEDS (1 << VC_NUMLOCK)
61#else
62#define KBD_DEFLEDS 0
63#endif
64
65#define KBD_DEFLOCK 0
66
67void compute_shiftstate(void);
68
69/*
70 * Handler Tables.
71 */
72
73#define K_HANDLERS\
74 k_self, k_fn, k_spec, k_pad,\
75 k_dead, k_cons, k_cur, k_shift,\
76 k_meta, k_ascii, k_lock, k_lowercase,\
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -050077 k_slock, k_dead2, k_brl, k_ignore
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050079typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
David Howells7d12e782006-10-05 14:55:46 +010080 char up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -070081static k_handler_fn K_HANDLERS;
82static k_handler_fn *k_handler[16] = { K_HANDLERS };
83
84#define FN_HANDLERS\
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050085 fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
86 fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
87 fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
88 fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
89 fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
David Howells7d12e782006-10-05 14:55:46 +010091typedef void (fn_handler_fn)(struct vc_data *vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092static fn_handler_fn FN_HANDLERS;
93static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
94
95/*
96 * Variables exported for vt_ioctl.c
97 */
98
99/* maximum values each key_handler can handle */
100const int max_vals[] = {
101 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
102 NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500103 255, NR_LOCK - 1, 255, NR_BRL - 1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104};
105
106const int NR_TYPES = ARRAY_SIZE(max_vals);
107
108struct kbd_struct kbd_table[MAX_NR_CONSOLES];
109static struct kbd_struct *kbd = kbd_table;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700111struct vt_spawn_console vt_spawn_con = {
Milind Arun Choudharyccc94252007-05-08 00:30:09 -0700112 .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700113 .pid = NULL,
114 .sig = 0,
115};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
117/*
118 * Variables exported for vt.c
119 */
120
121int shift_state = 0;
122
123/*
124 * Internal Data.
125 */
126
127static struct input_handler kbd_handler;
128static unsigned long key_down[NBITS(KEY_MAX)]; /* keyboard key bitmap */
129static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
130static int dead_key_next;
131static int npadch = -1; /* -1 or number assembled on pad */
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500132static unsigned int diacr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133static char rep; /* flag telling character repeat */
134
135static unsigned char ledstate = 0xff; /* undefined */
136static unsigned char ledioctl;
137
138static struct ledptr {
139 unsigned int *addr;
140 unsigned int mask;
141 unsigned char valid:1;
142} ledptrs[3];
143
144/* Simple translation table for the SysRq keys */
145
146#ifdef CONFIG_MAGIC_SYSRQ
147unsigned char kbd_sysrq_xlate[KEY_MAX + 1] =
148 "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
149 "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
150 "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
151 "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
152 "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
153 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
154 "\r\000/"; /* 0x60 - 0x6f */
155static int sysrq_down;
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -0700156static int sysrq_alt_use;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157#endif
158static int sysrq_alt;
159
160/*
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400161 * Translation of scancodes to keycodes. We set them on only the first
162 * keyboard in the list that accepts the scancode and keycode.
163 * Explanation for not choosing the first attached keyboard anymore:
164 * USB keyboards for example have two event devices: one for all "normal"
165 * keys and one for extra function keys (like "volume up", "make coffee",
166 * etc.). So this means that scancodes for the extra function keys won't
167 * be valid for the first event device, but will be for the second.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 */
169int getkeycode(unsigned int scancode)
170{
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400171 struct input_handle *handle;
172 int keycode;
173 int error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400175 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
176 error = handle->dev->getkeycode(handle->dev, scancode, &keycode);
177 if (!error)
178 return keycode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 }
180
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400181 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182}
183
184int setkeycode(unsigned int scancode, unsigned int keycode)
185{
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400186 struct input_handle *handle;
187 int error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400189 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
190 error = handle->dev->setkeycode(handle->dev, scancode, keycode);
191 if (!error)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500192 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 }
194
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400195 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196}
197
198/*
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500199 * Making beeps and bells.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 */
201static void kd_nosound(unsigned long ignored)
202{
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400203 struct input_handle *handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400205 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 if (test_bit(EV_SND, handle->dev->evbit)) {
207 if (test_bit(SND_TONE, handle->dev->sndbit))
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400208 input_inject_event(handle, EV_SND, SND_TONE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 if (test_bit(SND_BELL, handle->dev->sndbit))
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400210 input_inject_event(handle, EV_SND, SND_BELL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 }
212 }
213}
214
Ingo Molnar8d06afa2005-09-09 13:10:40 -0700215static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216
217void kd_mksound(unsigned int hz, unsigned int ticks)
218{
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500219 struct list_head *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
221 del_timer(&kd_mksound_timer);
222
223 if (hz) {
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500224 list_for_each_prev(node, &kbd_handler.h_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 struct input_handle *handle = to_handle_h(node);
226 if (test_bit(EV_SND, handle->dev->evbit)) {
227 if (test_bit(SND_TONE, handle->dev->sndbit)) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400228 input_inject_event(handle, EV_SND, SND_TONE, hz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 break;
230 }
231 if (test_bit(SND_BELL, handle->dev->sndbit)) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400232 input_inject_event(handle, EV_SND, SND_BELL, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 break;
234 }
235 }
236 }
237 if (ticks)
238 mod_timer(&kd_mksound_timer, jiffies + ticks);
239 } else
240 kd_nosound(0);
241}
242
243/*
244 * Setting the keyboard rate.
245 */
246
247int kbd_rate(struct kbd_repeat *rep)
248{
249 struct list_head *node;
250 unsigned int d = 0;
251 unsigned int p = 0;
252
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400253 list_for_each(node, &kbd_handler.h_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 struct input_handle *handle = to_handle_h(node);
255 struct input_dev *dev = handle->dev;
256
257 if (test_bit(EV_REP, dev->evbit)) {
258 if (rep->delay > 0)
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400259 input_inject_event(handle, EV_REP, REP_DELAY, rep->delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 if (rep->period > 0)
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400261 input_inject_event(handle, EV_REP, REP_PERIOD, rep->period);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 d = dev->rep[REP_DELAY];
263 p = dev->rep[REP_PERIOD];
264 }
265 }
266 rep->delay = d;
267 rep->period = p;
268 return 0;
269}
270
271/*
272 * Helper Functions.
273 */
274static void put_queue(struct vc_data *vc, int ch)
275{
276 struct tty_struct *tty = vc->vc_tty;
277
278 if (tty) {
279 tty_insert_flip_char(tty, ch, 0);
280 con_schedule_flip(tty);
281 }
282}
283
284static void puts_queue(struct vc_data *vc, char *cp)
285{
286 struct tty_struct *tty = vc->vc_tty;
287
288 if (!tty)
289 return;
290
291 while (*cp) {
292 tty_insert_flip_char(tty, *cp, 0);
293 cp++;
294 }
295 con_schedule_flip(tty);
296}
297
298static void applkey(struct vc_data *vc, int key, char mode)
299{
300 static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
301
302 buf[1] = (mode ? 'O' : '[');
303 buf[2] = key;
304 puts_queue(vc, buf);
305}
306
307/*
308 * Many other routines do put_queue, but I think either
309 * they produce ASCII, or they produce some user-assigned
310 * string, and in both cases we might assume that it is
311 * in utf-8 already. UTF-8 is defined for words of up to 31 bits,
312 * but we need only 16 bits here
313 */
314static void to_utf8(struct vc_data *vc, ushort c)
315{
316 if (c < 0x80)
317 /* 0******* */
318 put_queue(vc, c);
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500319 else if (c < 0x800) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 /* 110***** 10****** */
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500321 put_queue(vc, 0xc0 | (c >> 6));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500323 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 /* 1110**** 10****** 10****** */
325 put_queue(vc, 0xe0 | (c >> 12));
326 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
327 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329}
330
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500331/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 * Called after returning from RAW mode or when changing consoles - recompute
333 * shift_down[] and shift_state from key_down[] maybe called when keymap is
334 * undefined, so that shiftkey release is seen
335 */
336void compute_shiftstate(void)
337{
338 unsigned int i, j, k, sym, val;
339
340 shift_state = 0;
341 memset(shift_down, 0, sizeof(shift_down));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 for (i = 0; i < ARRAY_SIZE(key_down); i++) {
344
345 if (!key_down[i])
346 continue;
347
348 k = i * BITS_PER_LONG;
349
350 for (j = 0; j < BITS_PER_LONG; j++, k++) {
351
352 if (!test_bit(k, key_down))
353 continue;
354
355 sym = U(key_maps[0][k]);
356 if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
357 continue;
358
359 val = KVAL(sym);
360 if (val == KVAL(K_CAPSSHIFT))
361 val = KVAL(K_SHIFT);
362
363 shift_down[val]++;
364 shift_state |= (1 << val);
365 }
366 }
367}
368
369/*
370 * We have a combining character DIACR here, followed by the character CH.
371 * If the combination occurs in the table, return the corresponding value.
372 * Otherwise, if CH is a space or equals DIACR, return DIACR.
373 * Otherwise, conclude that DIACR was not combining after all,
374 * queue it and return CH.
375 */
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500376static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377{
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500378 unsigned int d = diacr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 unsigned int i;
380
381 diacr = 0;
382
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500383 if ((d & ~0xff) == BRL_UC_ROW) {
384 if ((ch & ~0xff) == BRL_UC_ROW)
385 return d | ch;
386 } else {
387 for (i = 0; i < accent_table_size; i++)
388 if (accent_table[i].diacr == d && accent_table[i].base == ch)
389 return accent_table[i].result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 }
391
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500392 if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 return d;
394
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500395 if (kbd->kbdmode == VC_UNICODE)
396 to_utf8(vc, d);
397 else if (d < 0x100)
398 put_queue(vc, d);
399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 return ch;
401}
402
403/*
404 * Special function handlers
405 */
David Howells7d12e782006-10-05 14:55:46 +0100406static void fn_enter(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407{
408 if (diacr) {
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500409 if (kbd->kbdmode == VC_UNICODE)
410 to_utf8(vc, diacr);
411 else if (diacr < 0x100)
412 put_queue(vc, diacr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 diacr = 0;
414 }
415 put_queue(vc, 13);
416 if (vc_kbd_mode(kbd, VC_CRLF))
417 put_queue(vc, 10);
418}
419
David Howells7d12e782006-10-05 14:55:46 +0100420static void fn_caps_toggle(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421{
422 if (rep)
423 return;
424 chg_vc_kbd_led(kbd, VC_CAPSLOCK);
425}
426
David Howells7d12e782006-10-05 14:55:46 +0100427static void fn_caps_on(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{
429 if (rep)
430 return;
431 set_vc_kbd_led(kbd, VC_CAPSLOCK);
432}
433
David Howells7d12e782006-10-05 14:55:46 +0100434static void fn_show_ptregs(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435{
David Howells7d12e782006-10-05 14:55:46 +0100436 struct pt_regs *regs = get_irq_regs();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 if (regs)
438 show_regs(regs);
439}
440
David Howells7d12e782006-10-05 14:55:46 +0100441static void fn_hold(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442{
443 struct tty_struct *tty = vc->vc_tty;
444
445 if (rep || !tty)
446 return;
447
448 /*
449 * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
450 * these routines are also activated by ^S/^Q.
451 * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
452 */
453 if (tty->stopped)
454 start_tty(tty);
455 else
456 stop_tty(tty);
457}
458
David Howells7d12e782006-10-05 14:55:46 +0100459static void fn_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460{
461 if (vc_kbd_mode(kbd,VC_APPLIC))
462 applkey(vc, 'P', 1);
463 else
David Howells7d12e782006-10-05 14:55:46 +0100464 fn_bare_num(vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465}
466
467/*
468 * Bind this to Shift-NumLock if you work in application keypad mode
469 * but want to be able to change the NumLock flag.
470 * Bind this to NumLock if you prefer that the NumLock key always
471 * changes the NumLock flag.
472 */
David Howells7d12e782006-10-05 14:55:46 +0100473static void fn_bare_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
475 if (!rep)
476 chg_vc_kbd_led(kbd, VC_NUMLOCK);
477}
478
David Howells7d12e782006-10-05 14:55:46 +0100479static void fn_lastcons(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480{
481 /* switch to the last used console, ChN */
482 set_console(last_console);
483}
484
David Howells7d12e782006-10-05 14:55:46 +0100485static void fn_dec_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486{
487 int i, cur = fg_console;
488
489 /* Currently switching? Queue this next switch relative to that. */
490 if (want_console != -1)
491 cur = want_console;
492
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500493 for (i = cur - 1; i != cur; i--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 if (i == -1)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500495 i = MAX_NR_CONSOLES - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 if (vc_cons_allocated(i))
497 break;
498 }
499 set_console(i);
500}
501
David Howells7d12e782006-10-05 14:55:46 +0100502static void fn_inc_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503{
504 int i, cur = fg_console;
505
506 /* Currently switching? Queue this next switch relative to that. */
507 if (want_console != -1)
508 cur = want_console;
509
510 for (i = cur+1; i != cur; i++) {
511 if (i == MAX_NR_CONSOLES)
512 i = 0;
513 if (vc_cons_allocated(i))
514 break;
515 }
516 set_console(i);
517}
518
David Howells7d12e782006-10-05 14:55:46 +0100519static void fn_send_intr(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520{
521 struct tty_struct *tty = vc->vc_tty;
522
523 if (!tty)
524 return;
525 tty_insert_flip_char(tty, 0, TTY_BREAK);
526 con_schedule_flip(tty);
527}
528
David Howells7d12e782006-10-05 14:55:46 +0100529static void fn_scroll_forw(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530{
531 scrollfront(vc, 0);
532}
533
David Howells7d12e782006-10-05 14:55:46 +0100534static void fn_scroll_back(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535{
536 scrollback(vc, 0);
537}
538
David Howells7d12e782006-10-05 14:55:46 +0100539static void fn_show_mem(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540{
541 show_mem();
542}
543
David Howells7d12e782006-10-05 14:55:46 +0100544static void fn_show_state(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545{
546 show_state();
547}
548
David Howells7d12e782006-10-05 14:55:46 +0100549static void fn_boot_it(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550{
551 ctrl_alt_del();
552}
553
David Howells7d12e782006-10-05 14:55:46 +0100554static void fn_compose(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555{
556 dead_key_next = 1;
557}
558
David Howells7d12e782006-10-05 14:55:46 +0100559static void fn_spawn_con(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560{
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700561 spin_lock(&vt_spawn_con.lock);
562 if (vt_spawn_con.pid)
563 if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
564 put_pid(vt_spawn_con.pid);
565 vt_spawn_con.pid = NULL;
566 }
567 spin_unlock(&vt_spawn_con.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568}
569
David Howells7d12e782006-10-05 14:55:46 +0100570static void fn_SAK(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571{
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800572 struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800573 schedule_work(SAK_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574}
575
David Howells7d12e782006-10-05 14:55:46 +0100576static void fn_null(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577{
578 compute_shiftstate();
579}
580
581/*
582 * Special key handlers
583 */
David Howells7d12e782006-10-05 14:55:46 +0100584static void k_ignore(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585{
586}
587
David Howells7d12e782006-10-05 14:55:46 +0100588static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589{
590 if (up_flag)
591 return;
592 if (value >= ARRAY_SIZE(fn_handler))
593 return;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500594 if ((kbd->kbdmode == VC_RAW ||
595 kbd->kbdmode == VC_MEDIUMRAW) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 value != KVAL(K_SAK))
597 return; /* SAK is allowed even in raw mode */
David Howells7d12e782006-10-05 14:55:46 +0100598 fn_handler[value](vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599}
600
David Howells7d12e782006-10-05 14:55:46 +0100601static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602{
603 printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
604}
605
David Howells7d12e782006-10-05 14:55:46 +0100606static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607{
608 if (up_flag)
609 return; /* no action, if this is a key release */
610
611 if (diacr)
612 value = handle_diacr(vc, value);
613
614 if (dead_key_next) {
615 dead_key_next = 0;
616 diacr = value;
617 return;
618 }
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500619 if (kbd->kbdmode == VC_UNICODE)
620 to_utf8(vc, value);
621 else if (value < 0x100)
622 put_queue(vc, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623}
624
625/*
626 * Handle dead key. Note that we now may have several
627 * dead keys modifying the same character. Very useful
628 * for Vietnamese.
629 */
David Howells7d12e782006-10-05 14:55:46 +0100630static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631{
632 if (up_flag)
633 return;
634 diacr = (diacr ? handle_diacr(vc, value) : value);
635}
636
David Howells7d12e782006-10-05 14:55:46 +0100637static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500638{
David Howells7d12e782006-10-05 14:55:46 +0100639 k_unicode(vc, value, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500640}
641
David Howells7d12e782006-10-05 14:55:46 +0100642static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500643{
David Howells7d12e782006-10-05 14:55:46 +0100644 k_deadunicode(vc, value, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500645}
646
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647/*
648 * Obsolete - for backwards compatibility only
649 */
David Howells7d12e782006-10-05 14:55:46 +0100650static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651{
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400652 static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 value = ret_diacr[value];
David Howells7d12e782006-10-05 14:55:46 +0100654 k_deadunicode(vc, value, up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655}
656
David Howells7d12e782006-10-05 14:55:46 +0100657static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658{
659 if (up_flag)
660 return;
661 set_console(value);
662}
663
David Howells7d12e782006-10-05 14:55:46 +0100664static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665{
666 unsigned v;
667
668 if (up_flag)
669 return;
670 v = value;
671 if (v < ARRAY_SIZE(func_table)) {
672 if (func_table[value])
673 puts_queue(vc, func_table[value]);
674 } else
675 printk(KERN_ERR "k_fn called with value=%d\n", value);
676}
677
David Howells7d12e782006-10-05 14:55:46 +0100678static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679{
Brandon Philipse52b29c2006-11-04 22:09:08 -0500680 static const char cur_chars[] = "BDCA";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
682 if (up_flag)
683 return;
684 applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
685}
686
David Howells7d12e782006-10-05 14:55:46 +0100687static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400689 static const char pad_chars[] = "0123456789+-*/\015,.?()#";
690 static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
692 if (up_flag)
693 return; /* no action, if this is a key release */
694
695 /* kludge... shift forces cursor/number keys */
696 if (vc_kbd_mode(kbd, VC_APPLIC) && !shift_down[KG_SHIFT]) {
697 applkey(vc, app_map[value], 1);
698 return;
699 }
700
701 if (!vc_kbd_led(kbd, VC_NUMLOCK))
702 switch (value) {
703 case KVAL(K_PCOMMA):
704 case KVAL(K_PDOT):
David Howells7d12e782006-10-05 14:55:46 +0100705 k_fn(vc, KVAL(K_REMOVE), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 return;
707 case KVAL(K_P0):
David Howells7d12e782006-10-05 14:55:46 +0100708 k_fn(vc, KVAL(K_INSERT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 return;
710 case KVAL(K_P1):
David Howells7d12e782006-10-05 14:55:46 +0100711 k_fn(vc, KVAL(K_SELECT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 return;
713 case KVAL(K_P2):
David Howells7d12e782006-10-05 14:55:46 +0100714 k_cur(vc, KVAL(K_DOWN), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 return;
716 case KVAL(K_P3):
David Howells7d12e782006-10-05 14:55:46 +0100717 k_fn(vc, KVAL(K_PGDN), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 return;
719 case KVAL(K_P4):
David Howells7d12e782006-10-05 14:55:46 +0100720 k_cur(vc, KVAL(K_LEFT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 return;
722 case KVAL(K_P6):
David Howells7d12e782006-10-05 14:55:46 +0100723 k_cur(vc, KVAL(K_RIGHT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 return;
725 case KVAL(K_P7):
David Howells7d12e782006-10-05 14:55:46 +0100726 k_fn(vc, KVAL(K_FIND), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 return;
728 case KVAL(K_P8):
David Howells7d12e782006-10-05 14:55:46 +0100729 k_cur(vc, KVAL(K_UP), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 return;
731 case KVAL(K_P9):
David Howells7d12e782006-10-05 14:55:46 +0100732 k_fn(vc, KVAL(K_PGUP), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 return;
734 case KVAL(K_P5):
735 applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
736 return;
737 }
738
739 put_queue(vc, pad_chars[value]);
740 if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
741 put_queue(vc, 10);
742}
743
David Howells7d12e782006-10-05 14:55:46 +0100744static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745{
746 int old_state = shift_state;
747
748 if (rep)
749 return;
750 /*
751 * Mimic typewriter:
752 * a CapsShift key acts like Shift but undoes CapsLock
753 */
754 if (value == KVAL(K_CAPSSHIFT)) {
755 value = KVAL(K_SHIFT);
756 if (!up_flag)
757 clr_vc_kbd_led(kbd, VC_CAPSLOCK);
758 }
759
760 if (up_flag) {
761 /*
762 * handle the case that two shift or control
763 * keys are depressed simultaneously
764 */
765 if (shift_down[value])
766 shift_down[value]--;
767 } else
768 shift_down[value]++;
769
770 if (shift_down[value])
771 shift_state |= (1 << value);
772 else
773 shift_state &= ~(1 << value);
774
775 /* kludge */
776 if (up_flag && shift_state != old_state && npadch != -1) {
777 if (kbd->kbdmode == VC_UNICODE)
778 to_utf8(vc, npadch & 0xffff);
779 else
780 put_queue(vc, npadch & 0xff);
781 npadch = -1;
782 }
783}
784
David Howells7d12e782006-10-05 14:55:46 +0100785static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
787 if (up_flag)
788 return;
789
790 if (vc_kbd_mode(kbd, VC_META)) {
791 put_queue(vc, '\033');
792 put_queue(vc, value);
793 } else
794 put_queue(vc, value | 0x80);
795}
796
David Howells7d12e782006-10-05 14:55:46 +0100797static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798{
799 int base;
800
801 if (up_flag)
802 return;
803
804 if (value < 10) {
805 /* decimal input of code, while Alt depressed */
806 base = 10;
807 } else {
808 /* hexadecimal input of code, while AltGr depressed */
809 value -= 10;
810 base = 16;
811 }
812
813 if (npadch == -1)
814 npadch = value;
815 else
816 npadch = npadch * base + value;
817}
818
David Howells7d12e782006-10-05 14:55:46 +0100819static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820{
821 if (up_flag || rep)
822 return;
823 chg_vc_kbd_lock(kbd, value);
824}
825
David Howells7d12e782006-10-05 14:55:46 +0100826static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827{
David Howells7d12e782006-10-05 14:55:46 +0100828 k_shift(vc, value, up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 if (up_flag || rep)
830 return;
831 chg_vc_kbd_slock(kbd, value);
832 /* try to make Alt, oops, AltGr and such work */
833 if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
834 kbd->slockstate = 0;
835 chg_vc_kbd_slock(kbd, value);
836 }
837}
838
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500839/* by default, 300ms interval for combination release */
Samuel Thibault77426d72006-04-26 00:14:10 -0400840static unsigned brl_timeout = 300;
841MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
842module_param(brl_timeout, uint, 0644);
843
844static unsigned brl_nbchords = 1;
845MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
846module_param(brl_nbchords, uint, 0644);
847
David Howells7d12e782006-10-05 14:55:46 +0100848static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag)
Samuel Thibault77426d72006-04-26 00:14:10 -0400849{
850 static unsigned long chords;
851 static unsigned committed;
852
853 if (!brl_nbchords)
David Howells7d12e782006-10-05 14:55:46 +0100854 k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400855 else {
856 committed |= pattern;
857 chords++;
858 if (chords == brl_nbchords) {
David Howells7d12e782006-10-05 14:55:46 +0100859 k_unicode(vc, BRL_UC_ROW | committed, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400860 chords = 0;
861 committed = 0;
862 }
863 }
864}
865
David Howells7d12e782006-10-05 14:55:46 +0100866static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500867{
868 static unsigned pressed,committing;
869 static unsigned long releasestart;
870
871 if (kbd->kbdmode != VC_UNICODE) {
872 if (!up_flag)
873 printk("keyboard mode must be unicode for braille patterns\n");
874 return;
875 }
876
877 if (!value) {
David Howells7d12e782006-10-05 14:55:46 +0100878 k_unicode(vc, BRL_UC_ROW, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500879 return;
880 }
881
882 if (value > 8)
883 return;
884
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500885 if (up_flag) {
886 if (brl_timeout) {
887 if (!committing ||
888 jiffies - releasestart > (brl_timeout * HZ) / 1000) {
889 committing = pressed;
890 releasestart = jiffies;
891 }
892 pressed &= ~(1 << (value - 1));
893 if (!pressed) {
894 if (committing) {
David Howells7d12e782006-10-05 14:55:46 +0100895 k_brlcommit(vc, committing, 0);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500896 committing = 0;
897 }
898 }
899 } else {
900 if (committing) {
David Howells7d12e782006-10-05 14:55:46 +0100901 k_brlcommit(vc, committing, 0);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500902 committing = 0;
903 }
904 pressed &= ~(1 << (value - 1));
905 }
906 } else {
907 pressed |= 1 << (value - 1);
908 if (!brl_timeout)
909 committing = pressed;
910 }
911}
912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913/*
914 * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
915 * or (ii) whatever pattern of lights people want to show using KDSETLED,
916 * or (iii) specified bits of specified words in kernel memory.
917 */
918unsigned char getledstate(void)
919{
920 return ledstate;
921}
922
923void setledstate(struct kbd_struct *kbd, unsigned int led)
924{
925 if (!(led & ~7)) {
926 ledioctl = led;
927 kbd->ledmode = LED_SHOW_IOCTL;
928 } else
929 kbd->ledmode = LED_SHOW_FLAGS;
930 set_leds();
931}
932
933static inline unsigned char getleds(void)
934{
935 struct kbd_struct *kbd = kbd_table + fg_console;
936 unsigned char leds;
937 int i;
938
939 if (kbd->ledmode == LED_SHOW_IOCTL)
940 return ledioctl;
941
942 leds = kbd->ledflagstate;
943
944 if (kbd->ledmode == LED_SHOW_MEM) {
945 for (i = 0; i < 3; i++)
946 if (ledptrs[i].valid) {
947 if (*ledptrs[i].addr & ledptrs[i].mask)
948 leds |= (1 << i);
949 else
950 leds &= ~(1 << i);
951 }
952 }
953 return leds;
954}
955
956/*
957 * This routine is the bottom half of the keyboard interrupt
958 * routine, and runs with all interrupts enabled. It does
959 * console changing, led setting and copy_to_cooked, which can
960 * take a reasonably long time.
961 *
962 * Aside from timing (which isn't really that important for
963 * keyboard interrupts as they happen often), using the software
964 * interrupt routines for this thing allows us to easily mask
965 * this when we don't want any of the above to happen.
966 * This allows for easy and efficient race-condition prevention
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400967 * for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 */
969
970static void kbd_bh(unsigned long dummy)
971{
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500972 struct list_head *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 unsigned char leds = getleds();
974
975 if (leds != ledstate) {
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500976 list_for_each(node, &kbd_handler.h_list) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400977 struct input_handle *handle = to_handle_h(node);
978 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
979 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
980 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
981 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 }
983 }
984
985 ledstate = leds;
986}
987
988DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
989
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
Adrian Bunk0b57ee92005-12-22 21:03:47 -0800991 defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
992 defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
994
995#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
996 ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
997
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400998static const unsigned short x86_keycodes[256] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1000 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1001 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
1002 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
1003 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
1004 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001005 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
1007 360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
1008 103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
1009 291,108,381,281,290,272,292,305,280, 99,112,257,258,359,113,114,
1010 264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
1011 377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
1012 308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
1013 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
1014
1015#ifdef CONFIG_MAC_EMUMOUSEBTN
1016extern int mac_hid_mouse_emulate_buttons(int, int, int);
1017#endif /* CONFIG_MAC_EMUMOUSEBTN */
1018
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001019#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020static int sparc_l1_a_state = 0;
1021extern void sun_do_break(void);
1022#endif
1023
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001024static int emulate_raw(struct vc_data *vc, unsigned int keycode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 unsigned char up_flag)
1026{
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001027 int code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
1029 switch (keycode) {
1030 case KEY_PAUSE:
1031 put_queue(vc, 0xe1);
1032 put_queue(vc, 0x1d | up_flag);
1033 put_queue(vc, 0x45 | up_flag);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001034 break;
1035
Jerome Pinotb9ab58d2006-06-26 01:51:23 -04001036 case KEY_HANGEUL:
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -04001037 if (!up_flag)
1038 put_queue(vc, 0xf2);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001039 break;
1040
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 case KEY_HANJA:
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -04001042 if (!up_flag)
1043 put_queue(vc, 0xf1);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001044 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001046 case KEY_SYSRQ:
1047 /*
1048 * Real AT keyboards (that's what we're trying
1049 * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
1050 * pressing PrtSc/SysRq alone, but simply 0x54
1051 * when pressing Alt+PrtSc/SysRq.
1052 */
1053 if (sysrq_alt) {
1054 put_queue(vc, 0x54 | up_flag);
1055 } else {
1056 put_queue(vc, 0xe0);
1057 put_queue(vc, 0x2a | up_flag);
1058 put_queue(vc, 0xe0);
1059 put_queue(vc, 0x37 | up_flag);
1060 }
1061 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001063 default:
1064 if (keycode > 255)
1065 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001067 code = x86_keycodes[keycode];
1068 if (!code)
1069 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001071 if (code & 0x100)
1072 put_queue(vc, 0xe0);
1073 put_queue(vc, (code & 0x7f) | up_flag);
1074
1075 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 }
1077
1078 return 0;
1079}
1080
1081#else
1082
1083#define HW_RAW(dev) 0
1084
1085#warning "Cannot generate rawmode keyboard for your architecture yet."
1086
1087static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
1088{
1089 if (keycode > 127)
1090 return -1;
1091
1092 put_queue(vc, keycode | up_flag);
1093 return 0;
1094}
1095#endif
1096
1097static void kbd_rawcode(unsigned char data)
1098{
1099 struct vc_data *vc = vc_cons[fg_console].d;
1100 kbd = kbd_table + fg_console;
1101 if (kbd->kbdmode == VC_RAW)
1102 put_queue(vc, data);
1103}
1104
David Howells7d12e782006-10-05 14:55:46 +01001105static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106{
1107 struct vc_data *vc = vc_cons[fg_console].d;
1108 unsigned short keysym, *key_map;
1109 unsigned char type, raw_mode;
1110 struct tty_struct *tty;
1111 int shift_final;
1112
1113 tty = vc->vc_tty;
1114
1115 if (tty && (!tty->driver_data)) {
1116 /* No driver data? Strange. Okay we fix it then. */
1117 tty->driver_data = vc;
1118 }
1119
1120 kbd = kbd_table + fg_console;
1121
1122 if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001123 sysrq_alt = down ? keycode : 0;
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001124#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 if (keycode == KEY_STOP)
1126 sparc_l1_a_state = down;
1127#endif
1128
1129 rep = (down == 2);
1130
1131#ifdef CONFIG_MAC_EMUMOUSEBTN
1132 if (mac_hid_mouse_emulate_buttons(1, keycode, down))
1133 return;
1134#endif /* CONFIG_MAC_EMUMOUSEBTN */
1135
1136 if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
1137 if (emulate_raw(vc, keycode, !down << 7))
Dmitry Torokhov9e35d202007-04-12 01:30:52 -04001138 if (keycode < BTN_MISC && printk_ratelimit())
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
1140
1141#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
1142 if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001143 if (!sysrq_down) {
1144 sysrq_down = down;
1145 sysrq_alt_use = sysrq_alt;
1146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 return;
1148 }
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001149 if (sysrq_down && !down && keycode == sysrq_alt_use)
1150 sysrq_down = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 if (sysrq_down && down && !rep) {
David Howells7d12e782006-10-05 14:55:46 +01001152 handle_sysrq(kbd_sysrq_xlate[keycode], tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 return;
1154 }
1155#endif
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001156#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 if (keycode == KEY_A && sparc_l1_a_state) {
1158 sparc_l1_a_state = 0;
1159 sun_do_break();
1160 }
1161#endif
1162
1163 if (kbd->kbdmode == VC_MEDIUMRAW) {
1164 /*
1165 * This is extended medium raw mode, with keys above 127
1166 * encoded as 0, high 7 bits, low 7 bits, with the 0 bearing
1167 * the 'up' flag if needed. 0 is reserved, so this shouldn't
1168 * interfere with anything else. The two bytes after 0 will
1169 * always have the up flag set not to interfere with older
1170 * applications. This allows for 16384 different keycodes,
1171 * which should be enough.
1172 */
1173 if (keycode < 128) {
1174 put_queue(vc, keycode | (!down << 7));
1175 } else {
1176 put_queue(vc, !down << 7);
1177 put_queue(vc, (keycode >> 7) | 0x80);
1178 put_queue(vc, keycode | 0x80);
1179 }
1180 raw_mode = 1;
1181 }
1182
1183 if (down)
1184 set_bit(keycode, key_down);
1185 else
1186 clear_bit(keycode, key_down);
1187
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001188 if (rep &&
1189 (!vc_kbd_mode(kbd, VC_REPEAT) ||
1190 (tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 /*
1192 * Don't repeat a key if the input buffers are not empty and the
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001193 * characters get aren't echoed locally. This makes key repeat
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 * usable with slow applications and under heavy loads.
1195 */
1196 return;
1197 }
1198
1199 shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
1200 key_map = key_maps[shift_final];
1201
1202 if (!key_map) {
1203 compute_shiftstate();
1204 kbd->slockstate = 0;
1205 return;
1206 }
1207
1208 if (keycode > NR_KEYS)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -05001209 if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
1210 keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
1211 else
1212 return;
1213 else
1214 keysym = key_map[keycode];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 type = KTYP(keysym);
1217
1218 if (type < 0xf0) {
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001219 if (down && !raw_mode)
1220 to_utf8(vc, keysym);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 return;
1222 }
1223
1224 type -= 0xf0;
1225
1226 if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
1227 return;
1228
1229 if (type == KT_LETTER) {
1230 type = KT_LATIN;
1231 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
1232 key_map = key_maps[shift_final ^ (1 << KG_SHIFT)];
1233 if (key_map)
1234 keysym = key_map[keycode];
1235 }
1236 }
1237
David Howells7d12e782006-10-05 14:55:46 +01001238 (*k_handler[type])(vc, keysym & 0xff, !down);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
1240 if (type != KT_SLOCK)
1241 kbd->slockstate = 0;
1242}
1243
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001244static void kbd_event(struct input_handle *handle, unsigned int event_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 unsigned int event_code, int value)
1246{
1247 if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
1248 kbd_rawcode(value);
1249 if (event_type == EV_KEY)
David Howells7d12e782006-10-05 14:55:46 +01001250 kbd_keycode(event_code, value, HW_RAW(handle->dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 tasklet_schedule(&keyboard_tasklet);
1252 do_poke_blanked_console = 1;
1253 schedule_console_callback();
1254}
1255
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256/*
1257 * When a keyboard (or other input device) is found, the kbd_connect
1258 * function is called. The function then looks at the device, and if it
1259 * likes it, it can open it and get events from it. In this (kbd_connect)
1260 * function, we should decide which VT to bind that keyboard to initially.
1261 */
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001262static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
1263 const struct input_device_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264{
1265 struct input_handle *handle;
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001266 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 int i;
1268
1269 for (i = KEY_RESERVED; i < BTN_MISC; i++)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001270 if (test_bit(i, dev->keybit))
1271 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001273 if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001274 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
Dmitry Torokhov22479e12006-08-04 22:51:51 -04001276 handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
1277 if (!handle)
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001278 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
1280 handle->dev = dev;
1281 handle->handler = handler;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001282 handle->name = "kbd";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001284 error = input_register_handle(handle);
1285 if (error)
1286 goto err_free_handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001288 error = input_open_device(handle);
1289 if (error)
1290 goto err_unregister_handle;
1291
1292 return 0;
1293
1294 err_unregister_handle:
1295 input_unregister_handle(handle);
1296 err_free_handle:
1297 kfree(handle);
1298 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299}
1300
1301static void kbd_disconnect(struct input_handle *handle)
1302{
1303 input_close_device(handle);
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001304 input_unregister_handle(handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 kfree(handle);
1306}
1307
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001308/*
1309 * Start keyboard handler on the new keyboard by refreshing LED state to
1310 * match the rest of the system.
1311 */
1312static void kbd_start(struct input_handle *handle)
1313{
1314 unsigned char leds = ledstate;
1315
1316 tasklet_disable(&keyboard_tasklet);
1317 if (leds != 0xff) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -04001318 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
1319 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
1320 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
1321 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001322 }
1323 tasklet_enable(&keyboard_tasklet);
1324}
1325
Dmitry Torokhov66e66112006-09-14 01:31:59 -04001326static const struct input_device_id kbd_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 {
1328 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1329 .evbit = { BIT(EV_KEY) },
1330 },
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001331
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 {
1333 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1334 .evbit = { BIT(EV_SND) },
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001335 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
1337 { }, /* Terminating entry */
1338};
1339
1340MODULE_DEVICE_TABLE(input, kbd_ids);
1341
1342static struct input_handler kbd_handler = {
1343 .event = kbd_event,
1344 .connect = kbd_connect,
1345 .disconnect = kbd_disconnect,
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001346 .start = kbd_start,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 .name = "kbd",
1348 .id_table = kbd_ids,
1349};
1350
1351int __init kbd_init(void)
1352{
1353 int i;
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001354 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
Dmitry Torokhov2b192902006-07-19 01:13:26 -04001356 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1357 kbd_table[i].ledflagstate = KBD_DEFLEDS;
1358 kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
1359 kbd_table[i].ledmode = LED_SHOW_FLAGS;
1360 kbd_table[i].lockstate = KBD_DEFLOCK;
1361 kbd_table[i].slockstate = 0;
1362 kbd_table[i].modeflags = KBD_DEFMODE;
1363 kbd_table[i].kbdmode = VC_XLATE;
1364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001366 error = input_register_handler(&kbd_handler);
1367 if (error)
1368 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
1370 tasklet_enable(&keyboard_tasklet);
1371 tasklet_schedule(&keyboard_tasklet);
1372
1373 return 0;
1374}