blob: d95f316afb5a9d1c3328046c8d9f4f8ab7743981 [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
Jan Engelhardt759448f2007-07-15 23:40:40 -070027#include <linux/consolemap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
29#include <linux/sched.h>
30#include <linux/tty.h>
31#include <linux/tty_flip.h>
32#include <linux/mm.h>
33#include <linux/string.h>
34#include <linux/init.h>
35#include <linux/slab.h>
David Howells7d12e782006-10-05 14:55:46 +010036#include <linux/irq.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
38#include <linux/kbd_kern.h>
39#include <linux/kbd_diacr.h>
40#include <linux/vt_kern.h>
41#include <linux/sysrq.h>
42#include <linux/input.h>
Adrian Bunk83cc5ed2006-06-25 05:47:41 -070043#include <linux/reboot.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Linus Torvalds1da177e2005-04-16 15:20:36 -070045extern 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 = {
Milind Arun Choudharyccc94252007-05-08 00:30:09 -0700113 .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700114 .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
Jan Engelhardt759448f2007-07-15 23:40:40 -0700312 * in utf-8 already.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 */
Jan Engelhardt759448f2007-07-15 23:40:40 -0700314static void to_utf8(struct vc_data *vc, uint c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315{
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));
Jan Engelhardt759448f2007-07-15 23:40:40 -0700323 } else if (c < 0x10000) {
324 if (c >= 0xD800 && c < 0xE000)
325 return;
326 if (c == 0xFFFF)
327 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 /* 1110**** 10****** 10****** */
329 put_queue(vc, 0xe0 | (c >> 12));
330 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
331 put_queue(vc, 0x80 | (c & 0x3f));
Jan Engelhardt759448f2007-07-15 23:40:40 -0700332 } else if (c < 0x110000) {
333 /* 11110*** 10****** 10****** 10****** */
334 put_queue(vc, 0xf0 | (c >> 18));
335 put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
336 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
337 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500338 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339}
340
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500341/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 * Called after returning from RAW mode or when changing consoles - recompute
343 * shift_down[] and shift_state from key_down[] maybe called when keymap is
344 * undefined, so that shiftkey release is seen
345 */
346void compute_shiftstate(void)
347{
348 unsigned int i, j, k, sym, val;
349
350 shift_state = 0;
351 memset(shift_down, 0, sizeof(shift_down));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 for (i = 0; i < ARRAY_SIZE(key_down); i++) {
354
355 if (!key_down[i])
356 continue;
357
358 k = i * BITS_PER_LONG;
359
360 for (j = 0; j < BITS_PER_LONG; j++, k++) {
361
362 if (!test_bit(k, key_down))
363 continue;
364
365 sym = U(key_maps[0][k]);
366 if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
367 continue;
368
369 val = KVAL(sym);
370 if (val == KVAL(K_CAPSSHIFT))
371 val = KVAL(K_SHIFT);
372
373 shift_down[val]++;
374 shift_state |= (1 << val);
375 }
376 }
377}
378
379/*
380 * We have a combining character DIACR here, followed by the character CH.
381 * If the combination occurs in the table, return the corresponding value.
382 * Otherwise, if CH is a space or equals DIACR, return DIACR.
383 * Otherwise, conclude that DIACR was not combining after all,
384 * queue it and return CH.
385 */
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500386static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387{
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500388 unsigned int d = diacr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 unsigned int i;
390
391 diacr = 0;
392
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500393 if ((d & ~0xff) == BRL_UC_ROW) {
394 if ((ch & ~0xff) == BRL_UC_ROW)
395 return d | ch;
396 } else {
397 for (i = 0; i < accent_table_size; i++)
398 if (accent_table[i].diacr == d && accent_table[i].base == ch)
399 return accent_table[i].result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 }
401
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500402 if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 return d;
404
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500405 if (kbd->kbdmode == VC_UNICODE)
Jan Engelhardt759448f2007-07-15 23:40:40 -0700406 to_utf8(vc, conv_8bit_to_uni(d));
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500407 else if (d < 0x100)
408 put_queue(vc, d);
409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 return ch;
411}
412
413/*
414 * Special function handlers
415 */
David Howells7d12e782006-10-05 14:55:46 +0100416static void fn_enter(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417{
418 if (diacr) {
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500419 if (kbd->kbdmode == VC_UNICODE)
Jan Engelhardt759448f2007-07-15 23:40:40 -0700420 to_utf8(vc, conv_8bit_to_uni(diacr));
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500421 else if (diacr < 0x100)
422 put_queue(vc, diacr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 diacr = 0;
424 }
425 put_queue(vc, 13);
426 if (vc_kbd_mode(kbd, VC_CRLF))
427 put_queue(vc, 10);
428}
429
David Howells7d12e782006-10-05 14:55:46 +0100430static void fn_caps_toggle(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431{
432 if (rep)
433 return;
434 chg_vc_kbd_led(kbd, VC_CAPSLOCK);
435}
436
David Howells7d12e782006-10-05 14:55:46 +0100437static void fn_caps_on(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438{
439 if (rep)
440 return;
441 set_vc_kbd_led(kbd, VC_CAPSLOCK);
442}
443
David Howells7d12e782006-10-05 14:55:46 +0100444static void fn_show_ptregs(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445{
David Howells7d12e782006-10-05 14:55:46 +0100446 struct pt_regs *regs = get_irq_regs();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 if (regs)
448 show_regs(regs);
449}
450
David Howells7d12e782006-10-05 14:55:46 +0100451static void fn_hold(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452{
453 struct tty_struct *tty = vc->vc_tty;
454
455 if (rep || !tty)
456 return;
457
458 /*
459 * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
460 * these routines are also activated by ^S/^Q.
461 * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
462 */
463 if (tty->stopped)
464 start_tty(tty);
465 else
466 stop_tty(tty);
467}
468
David Howells7d12e782006-10-05 14:55:46 +0100469static void fn_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470{
471 if (vc_kbd_mode(kbd,VC_APPLIC))
472 applkey(vc, 'P', 1);
473 else
David Howells7d12e782006-10-05 14:55:46 +0100474 fn_bare_num(vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475}
476
477/*
478 * Bind this to Shift-NumLock if you work in application keypad mode
479 * but want to be able to change the NumLock flag.
480 * Bind this to NumLock if you prefer that the NumLock key always
481 * changes the NumLock flag.
482 */
David Howells7d12e782006-10-05 14:55:46 +0100483static void fn_bare_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484{
485 if (!rep)
486 chg_vc_kbd_led(kbd, VC_NUMLOCK);
487}
488
David Howells7d12e782006-10-05 14:55:46 +0100489static void fn_lastcons(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
491 /* switch to the last used console, ChN */
492 set_console(last_console);
493}
494
David Howells7d12e782006-10-05 14:55:46 +0100495static void fn_dec_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496{
497 int i, cur = fg_console;
498
499 /* Currently switching? Queue this next switch relative to that. */
500 if (want_console != -1)
501 cur = want_console;
502
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500503 for (i = cur - 1; i != cur; i--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 if (i == -1)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500505 i = MAX_NR_CONSOLES - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 if (vc_cons_allocated(i))
507 break;
508 }
509 set_console(i);
510}
511
David Howells7d12e782006-10-05 14:55:46 +0100512static void fn_inc_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513{
514 int i, cur = fg_console;
515
516 /* Currently switching? Queue this next switch relative to that. */
517 if (want_console != -1)
518 cur = want_console;
519
520 for (i = cur+1; i != cur; i++) {
521 if (i == MAX_NR_CONSOLES)
522 i = 0;
523 if (vc_cons_allocated(i))
524 break;
525 }
526 set_console(i);
527}
528
David Howells7d12e782006-10-05 14:55:46 +0100529static void fn_send_intr(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530{
531 struct tty_struct *tty = vc->vc_tty;
532
533 if (!tty)
534 return;
535 tty_insert_flip_char(tty, 0, TTY_BREAK);
536 con_schedule_flip(tty);
537}
538
David Howells7d12e782006-10-05 14:55:46 +0100539static void fn_scroll_forw(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540{
541 scrollfront(vc, 0);
542}
543
David Howells7d12e782006-10-05 14:55:46 +0100544static void fn_scroll_back(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545{
546 scrollback(vc, 0);
547}
548
David Howells7d12e782006-10-05 14:55:46 +0100549static void fn_show_mem(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550{
551 show_mem();
552}
553
David Howells7d12e782006-10-05 14:55:46 +0100554static void fn_show_state(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555{
556 show_state();
557}
558
David Howells7d12e782006-10-05 14:55:46 +0100559static void fn_boot_it(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560{
561 ctrl_alt_del();
562}
563
David Howells7d12e782006-10-05 14:55:46 +0100564static void fn_compose(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565{
566 dead_key_next = 1;
567}
568
David Howells7d12e782006-10-05 14:55:46 +0100569static void fn_spawn_con(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570{
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700571 spin_lock(&vt_spawn_con.lock);
572 if (vt_spawn_con.pid)
573 if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
574 put_pid(vt_spawn_con.pid);
575 vt_spawn_con.pid = NULL;
576 }
577 spin_unlock(&vt_spawn_con.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578}
579
David Howells7d12e782006-10-05 14:55:46 +0100580static void fn_SAK(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581{
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800582 struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800583 schedule_work(SAK_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584}
585
David Howells7d12e782006-10-05 14:55:46 +0100586static void fn_null(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587{
588 compute_shiftstate();
589}
590
591/*
592 * Special key handlers
593 */
David Howells7d12e782006-10-05 14:55:46 +0100594static void k_ignore(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595{
596}
597
David Howells7d12e782006-10-05 14:55:46 +0100598static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599{
600 if (up_flag)
601 return;
602 if (value >= ARRAY_SIZE(fn_handler))
603 return;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500604 if ((kbd->kbdmode == VC_RAW ||
605 kbd->kbdmode == VC_MEDIUMRAW) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 value != KVAL(K_SAK))
607 return; /* SAK is allowed even in raw mode */
David Howells7d12e782006-10-05 14:55:46 +0100608 fn_handler[value](vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609}
610
David Howells7d12e782006-10-05 14:55:46 +0100611static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612{
613 printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
614}
615
David Howells7d12e782006-10-05 14:55:46 +0100616static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617{
618 if (up_flag)
619 return; /* no action, if this is a key release */
620
621 if (diacr)
622 value = handle_diacr(vc, value);
623
624 if (dead_key_next) {
625 dead_key_next = 0;
626 diacr = value;
627 return;
628 }
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500629 if (kbd->kbdmode == VC_UNICODE)
Jan Engelhardt759448f2007-07-15 23:40:40 -0700630 to_utf8(vc, conv_8bit_to_uni(value));
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500631 else if (value < 0x100)
632 put_queue(vc, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633}
634
635/*
636 * Handle dead key. Note that we now may have several
637 * dead keys modifying the same character. Very useful
638 * for Vietnamese.
639 */
David Howells7d12e782006-10-05 14:55:46 +0100640static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641{
642 if (up_flag)
643 return;
644 diacr = (diacr ? handle_diacr(vc, value) : value);
645}
646
David Howells7d12e782006-10-05 14:55:46 +0100647static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500648{
David Howells7d12e782006-10-05 14:55:46 +0100649 k_unicode(vc, value, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500650}
651
David Howells7d12e782006-10-05 14:55:46 +0100652static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500653{
David Howells7d12e782006-10-05 14:55:46 +0100654 k_deadunicode(vc, value, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500655}
656
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657/*
658 * Obsolete - for backwards compatibility only
659 */
David Howells7d12e782006-10-05 14:55:46 +0100660static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661{
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400662 static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 value = ret_diacr[value];
David Howells7d12e782006-10-05 14:55:46 +0100664 k_deadunicode(vc, value, up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665}
666
David Howells7d12e782006-10-05 14:55:46 +0100667static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668{
669 if (up_flag)
670 return;
671 set_console(value);
672}
673
David Howells7d12e782006-10-05 14:55:46 +0100674static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675{
676 unsigned v;
677
678 if (up_flag)
679 return;
680 v = value;
681 if (v < ARRAY_SIZE(func_table)) {
682 if (func_table[value])
683 puts_queue(vc, func_table[value]);
684 } else
685 printk(KERN_ERR "k_fn called with value=%d\n", value);
686}
687
David Howells7d12e782006-10-05 14:55:46 +0100688static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
Brandon Philipse52b29c2006-11-04 22:09:08 -0500690 static const char cur_chars[] = "BDCA";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
692 if (up_flag)
693 return;
694 applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
695}
696
David Howells7d12e782006-10-05 14:55:46 +0100697static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698{
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400699 static const char pad_chars[] = "0123456789+-*/\015,.?()#";
700 static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
702 if (up_flag)
703 return; /* no action, if this is a key release */
704
705 /* kludge... shift forces cursor/number keys */
706 if (vc_kbd_mode(kbd, VC_APPLIC) && !shift_down[KG_SHIFT]) {
707 applkey(vc, app_map[value], 1);
708 return;
709 }
710
711 if (!vc_kbd_led(kbd, VC_NUMLOCK))
712 switch (value) {
713 case KVAL(K_PCOMMA):
714 case KVAL(K_PDOT):
David Howells7d12e782006-10-05 14:55:46 +0100715 k_fn(vc, KVAL(K_REMOVE), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 return;
717 case KVAL(K_P0):
David Howells7d12e782006-10-05 14:55:46 +0100718 k_fn(vc, KVAL(K_INSERT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 return;
720 case KVAL(K_P1):
David Howells7d12e782006-10-05 14:55:46 +0100721 k_fn(vc, KVAL(K_SELECT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 return;
723 case KVAL(K_P2):
David Howells7d12e782006-10-05 14:55:46 +0100724 k_cur(vc, KVAL(K_DOWN), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 return;
726 case KVAL(K_P3):
David Howells7d12e782006-10-05 14:55:46 +0100727 k_fn(vc, KVAL(K_PGDN), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 return;
729 case KVAL(K_P4):
David Howells7d12e782006-10-05 14:55:46 +0100730 k_cur(vc, KVAL(K_LEFT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 return;
732 case KVAL(K_P6):
David Howells7d12e782006-10-05 14:55:46 +0100733 k_cur(vc, KVAL(K_RIGHT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 return;
735 case KVAL(K_P7):
David Howells7d12e782006-10-05 14:55:46 +0100736 k_fn(vc, KVAL(K_FIND), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 return;
738 case KVAL(K_P8):
David Howells7d12e782006-10-05 14:55:46 +0100739 k_cur(vc, KVAL(K_UP), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 return;
741 case KVAL(K_P9):
David Howells7d12e782006-10-05 14:55:46 +0100742 k_fn(vc, KVAL(K_PGUP), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 return;
744 case KVAL(K_P5):
745 applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
746 return;
747 }
748
749 put_queue(vc, pad_chars[value]);
750 if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
751 put_queue(vc, 10);
752}
753
David Howells7d12e782006-10-05 14:55:46 +0100754static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755{
756 int old_state = shift_state;
757
758 if (rep)
759 return;
760 /*
761 * Mimic typewriter:
762 * a CapsShift key acts like Shift but undoes CapsLock
763 */
764 if (value == KVAL(K_CAPSSHIFT)) {
765 value = KVAL(K_SHIFT);
766 if (!up_flag)
767 clr_vc_kbd_led(kbd, VC_CAPSLOCK);
768 }
769
770 if (up_flag) {
771 /*
772 * handle the case that two shift or control
773 * keys are depressed simultaneously
774 */
775 if (shift_down[value])
776 shift_down[value]--;
777 } else
778 shift_down[value]++;
779
780 if (shift_down[value])
781 shift_state |= (1 << value);
782 else
783 shift_state &= ~(1 << value);
784
785 /* kludge */
786 if (up_flag && shift_state != old_state && npadch != -1) {
787 if (kbd->kbdmode == VC_UNICODE)
Jan Engelhardt759448f2007-07-15 23:40:40 -0700788 to_utf8(vc, npadch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 else
790 put_queue(vc, npadch & 0xff);
791 npadch = -1;
792 }
793}
794
David Howells7d12e782006-10-05 14:55:46 +0100795static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796{
797 if (up_flag)
798 return;
799
800 if (vc_kbd_mode(kbd, VC_META)) {
801 put_queue(vc, '\033');
802 put_queue(vc, value);
803 } else
804 put_queue(vc, value | 0x80);
805}
806
David Howells7d12e782006-10-05 14:55:46 +0100807static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808{
809 int base;
810
811 if (up_flag)
812 return;
813
814 if (value < 10) {
815 /* decimal input of code, while Alt depressed */
816 base = 10;
817 } else {
818 /* hexadecimal input of code, while AltGr depressed */
819 value -= 10;
820 base = 16;
821 }
822
823 if (npadch == -1)
824 npadch = value;
825 else
826 npadch = npadch * base + value;
827}
828
David Howells7d12e782006-10-05 14:55:46 +0100829static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830{
831 if (up_flag || rep)
832 return;
833 chg_vc_kbd_lock(kbd, value);
834}
835
David Howells7d12e782006-10-05 14:55:46 +0100836static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837{
David Howells7d12e782006-10-05 14:55:46 +0100838 k_shift(vc, value, up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 if (up_flag || rep)
840 return;
841 chg_vc_kbd_slock(kbd, value);
842 /* try to make Alt, oops, AltGr and such work */
843 if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
844 kbd->slockstate = 0;
845 chg_vc_kbd_slock(kbd, value);
846 }
847}
848
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500849/* by default, 300ms interval for combination release */
Samuel Thibault77426d72006-04-26 00:14:10 -0400850static unsigned brl_timeout = 300;
851MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
852module_param(brl_timeout, uint, 0644);
853
854static unsigned brl_nbchords = 1;
855MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
856module_param(brl_nbchords, uint, 0644);
857
David Howells7d12e782006-10-05 14:55:46 +0100858static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag)
Samuel Thibault77426d72006-04-26 00:14:10 -0400859{
860 static unsigned long chords;
861 static unsigned committed;
862
863 if (!brl_nbchords)
David Howells7d12e782006-10-05 14:55:46 +0100864 k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400865 else {
866 committed |= pattern;
867 chords++;
868 if (chords == brl_nbchords) {
David Howells7d12e782006-10-05 14:55:46 +0100869 k_unicode(vc, BRL_UC_ROW | committed, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400870 chords = 0;
871 committed = 0;
872 }
873 }
874}
875
David Howells7d12e782006-10-05 14:55:46 +0100876static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500877{
878 static unsigned pressed,committing;
879 static unsigned long releasestart;
880
881 if (kbd->kbdmode != VC_UNICODE) {
882 if (!up_flag)
883 printk("keyboard mode must be unicode for braille patterns\n");
884 return;
885 }
886
887 if (!value) {
David Howells7d12e782006-10-05 14:55:46 +0100888 k_unicode(vc, BRL_UC_ROW, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500889 return;
890 }
891
892 if (value > 8)
893 return;
894
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500895 if (up_flag) {
896 if (brl_timeout) {
897 if (!committing ||
898 jiffies - releasestart > (brl_timeout * HZ) / 1000) {
899 committing = pressed;
900 releasestart = jiffies;
901 }
902 pressed &= ~(1 << (value - 1));
903 if (!pressed) {
904 if (committing) {
David Howells7d12e782006-10-05 14:55:46 +0100905 k_brlcommit(vc, committing, 0);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500906 committing = 0;
907 }
908 }
909 } else {
910 if (committing) {
David Howells7d12e782006-10-05 14:55:46 +0100911 k_brlcommit(vc, committing, 0);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500912 committing = 0;
913 }
914 pressed &= ~(1 << (value - 1));
915 }
916 } else {
917 pressed |= 1 << (value - 1);
918 if (!brl_timeout)
919 committing = pressed;
920 }
921}
922
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923/*
924 * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
925 * or (ii) whatever pattern of lights people want to show using KDSETLED,
926 * or (iii) specified bits of specified words in kernel memory.
927 */
928unsigned char getledstate(void)
929{
930 return ledstate;
931}
932
933void setledstate(struct kbd_struct *kbd, unsigned int led)
934{
935 if (!(led & ~7)) {
936 ledioctl = led;
937 kbd->ledmode = LED_SHOW_IOCTL;
938 } else
939 kbd->ledmode = LED_SHOW_FLAGS;
940 set_leds();
941}
942
943static inline unsigned char getleds(void)
944{
945 struct kbd_struct *kbd = kbd_table + fg_console;
946 unsigned char leds;
947 int i;
948
949 if (kbd->ledmode == LED_SHOW_IOCTL)
950 return ledioctl;
951
952 leds = kbd->ledflagstate;
953
954 if (kbd->ledmode == LED_SHOW_MEM) {
955 for (i = 0; i < 3; i++)
956 if (ledptrs[i].valid) {
957 if (*ledptrs[i].addr & ledptrs[i].mask)
958 leds |= (1 << i);
959 else
960 leds &= ~(1 << i);
961 }
962 }
963 return leds;
964}
965
966/*
967 * This routine is the bottom half of the keyboard interrupt
968 * routine, and runs with all interrupts enabled. It does
969 * console changing, led setting and copy_to_cooked, which can
970 * take a reasonably long time.
971 *
972 * Aside from timing (which isn't really that important for
973 * keyboard interrupts as they happen often), using the software
974 * interrupt routines for this thing allows us to easily mask
975 * this when we don't want any of the above to happen.
976 * This allows for easy and efficient race-condition prevention
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400977 * for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 */
979
980static void kbd_bh(unsigned long dummy)
981{
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500982 struct list_head *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 unsigned char leds = getleds();
984
985 if (leds != ledstate) {
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500986 list_for_each(node, &kbd_handler.h_list) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400987 struct input_handle *handle = to_handle_h(node);
988 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
989 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
990 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
991 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 }
993 }
994
995 ledstate = leds;
996}
997
998DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
999
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001001 defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
1002 defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
1004
1005#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
1006 ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
1007
Andreas Mohr0f5e5602006-06-05 00:18:00 -04001008static const unsigned short x86_keycodes[256] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1010 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1011 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
1012 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
1013 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
1014 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001015 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
1017 360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
Hans de Goede72a42f22007-07-03 01:55:18 -04001018 103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
1019 291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
1021 377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
1022 308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
1023 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
1024
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001025#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026static int sparc_l1_a_state = 0;
1027extern void sun_do_break(void);
1028#endif
1029
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001030static int emulate_raw(struct vc_data *vc, unsigned int keycode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 unsigned char up_flag)
1032{
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001033 int code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
1035 switch (keycode) {
1036 case KEY_PAUSE:
1037 put_queue(vc, 0xe1);
1038 put_queue(vc, 0x1d | up_flag);
1039 put_queue(vc, 0x45 | up_flag);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001040 break;
1041
Jerome Pinotb9ab58d2006-06-26 01:51:23 -04001042 case KEY_HANGEUL:
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -04001043 if (!up_flag)
1044 put_queue(vc, 0xf2);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001045 break;
1046
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 case KEY_HANJA:
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -04001048 if (!up_flag)
1049 put_queue(vc, 0xf1);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001050 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001052 case KEY_SYSRQ:
1053 /*
1054 * Real AT keyboards (that's what we're trying
1055 * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
1056 * pressing PrtSc/SysRq alone, but simply 0x54
1057 * when pressing Alt+PrtSc/SysRq.
1058 */
1059 if (sysrq_alt) {
1060 put_queue(vc, 0x54 | up_flag);
1061 } else {
1062 put_queue(vc, 0xe0);
1063 put_queue(vc, 0x2a | up_flag);
1064 put_queue(vc, 0xe0);
1065 put_queue(vc, 0x37 | up_flag);
1066 }
1067 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001069 default:
1070 if (keycode > 255)
1071 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001073 code = x86_keycodes[keycode];
1074 if (!code)
1075 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001077 if (code & 0x100)
1078 put_queue(vc, 0xe0);
1079 put_queue(vc, (code & 0x7f) | up_flag);
1080
1081 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 }
1083
1084 return 0;
1085}
1086
1087#else
1088
1089#define HW_RAW(dev) 0
1090
1091#warning "Cannot generate rawmode keyboard for your architecture yet."
1092
1093static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
1094{
1095 if (keycode > 127)
1096 return -1;
1097
1098 put_queue(vc, keycode | up_flag);
1099 return 0;
1100}
1101#endif
1102
1103static void kbd_rawcode(unsigned char data)
1104{
1105 struct vc_data *vc = vc_cons[fg_console].d;
1106 kbd = kbd_table + fg_console;
1107 if (kbd->kbdmode == VC_RAW)
1108 put_queue(vc, data);
1109}
1110
David Howells7d12e782006-10-05 14:55:46 +01001111static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112{
1113 struct vc_data *vc = vc_cons[fg_console].d;
1114 unsigned short keysym, *key_map;
1115 unsigned char type, raw_mode;
1116 struct tty_struct *tty;
1117 int shift_final;
1118
1119 tty = vc->vc_tty;
1120
1121 if (tty && (!tty->driver_data)) {
1122 /* No driver data? Strange. Okay we fix it then. */
1123 tty->driver_data = vc;
1124 }
1125
1126 kbd = kbd_table + fg_console;
1127
1128 if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001129 sysrq_alt = down ? keycode : 0;
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001130#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 if (keycode == KEY_STOP)
1132 sparc_l1_a_state = down;
1133#endif
1134
1135 rep = (down == 2);
1136
1137#ifdef CONFIG_MAC_EMUMOUSEBTN
1138 if (mac_hid_mouse_emulate_buttons(1, keycode, down))
1139 return;
1140#endif /* CONFIG_MAC_EMUMOUSEBTN */
1141
1142 if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
1143 if (emulate_raw(vc, keycode, !down << 7))
Dmitry Torokhov9e35d202007-04-12 01:30:52 -04001144 if (keycode < BTN_MISC && printk_ratelimit())
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
1146
1147#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
1148 if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001149 if (!sysrq_down) {
1150 sysrq_down = down;
1151 sysrq_alt_use = sysrq_alt;
1152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 return;
1154 }
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001155 if (sysrq_down && !down && keycode == sysrq_alt_use)
1156 sysrq_down = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 if (sysrq_down && down && !rep) {
David Howells7d12e782006-10-05 14:55:46 +01001158 handle_sysrq(kbd_sysrq_xlate[keycode], tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 return;
1160 }
1161#endif
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001162#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 if (keycode == KEY_A && sparc_l1_a_state) {
1164 sparc_l1_a_state = 0;
1165 sun_do_break();
1166 }
1167#endif
1168
1169 if (kbd->kbdmode == VC_MEDIUMRAW) {
1170 /*
1171 * This is extended medium raw mode, with keys above 127
1172 * encoded as 0, high 7 bits, low 7 bits, with the 0 bearing
1173 * the 'up' flag if needed. 0 is reserved, so this shouldn't
1174 * interfere with anything else. The two bytes after 0 will
1175 * always have the up flag set not to interfere with older
1176 * applications. This allows for 16384 different keycodes,
1177 * which should be enough.
1178 */
1179 if (keycode < 128) {
1180 put_queue(vc, keycode | (!down << 7));
1181 } else {
1182 put_queue(vc, !down << 7);
1183 put_queue(vc, (keycode >> 7) | 0x80);
1184 put_queue(vc, keycode | 0x80);
1185 }
1186 raw_mode = 1;
1187 }
1188
1189 if (down)
1190 set_bit(keycode, key_down);
1191 else
1192 clear_bit(keycode, key_down);
1193
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001194 if (rep &&
1195 (!vc_kbd_mode(kbd, VC_REPEAT) ||
1196 (tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 /*
1198 * Don't repeat a key if the input buffers are not empty and the
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001199 * characters get aren't echoed locally. This makes key repeat
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 * usable with slow applications and under heavy loads.
1201 */
1202 return;
1203 }
1204
1205 shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
1206 key_map = key_maps[shift_final];
1207
1208 if (!key_map) {
1209 compute_shiftstate();
1210 kbd->slockstate = 0;
1211 return;
1212 }
1213
1214 if (keycode > NR_KEYS)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -05001215 if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
1216 keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
1217 else
1218 return;
1219 else
1220 keysym = key_map[keycode];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 type = KTYP(keysym);
1223
1224 if (type < 0xf0) {
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001225 if (down && !raw_mode)
1226 to_utf8(vc, keysym);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 return;
1228 }
1229
1230 type -= 0xf0;
1231
1232 if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
1233 return;
1234
1235 if (type == KT_LETTER) {
1236 type = KT_LATIN;
1237 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
1238 key_map = key_maps[shift_final ^ (1 << KG_SHIFT)];
1239 if (key_map)
1240 keysym = key_map[keycode];
1241 }
1242 }
1243
David Howells7d12e782006-10-05 14:55:46 +01001244 (*k_handler[type])(vc, keysym & 0xff, !down);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
1246 if (type != KT_SLOCK)
1247 kbd->slockstate = 0;
1248}
1249
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001250static void kbd_event(struct input_handle *handle, unsigned int event_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 unsigned int event_code, int value)
1252{
1253 if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
1254 kbd_rawcode(value);
1255 if (event_type == EV_KEY)
David Howells7d12e782006-10-05 14:55:46 +01001256 kbd_keycode(event_code, value, HW_RAW(handle->dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 tasklet_schedule(&keyboard_tasklet);
1258 do_poke_blanked_console = 1;
1259 schedule_console_callback();
1260}
1261
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262/*
1263 * When a keyboard (or other input device) is found, the kbd_connect
1264 * function is called. The function then looks at the device, and if it
1265 * likes it, it can open it and get events from it. In this (kbd_connect)
1266 * function, we should decide which VT to bind that keyboard to initially.
1267 */
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001268static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
1269 const struct input_device_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270{
1271 struct input_handle *handle;
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001272 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 int i;
1274
1275 for (i = KEY_RESERVED; i < BTN_MISC; i++)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001276 if (test_bit(i, dev->keybit))
1277 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001279 if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001280 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Dmitry Torokhov22479e12006-08-04 22:51:51 -04001282 handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
1283 if (!handle)
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001284 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285
1286 handle->dev = dev;
1287 handle->handler = handler;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001288 handle->name = "kbd";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001290 error = input_register_handle(handle);
1291 if (error)
1292 goto err_free_handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001294 error = input_open_device(handle);
1295 if (error)
1296 goto err_unregister_handle;
1297
1298 return 0;
1299
1300 err_unregister_handle:
1301 input_unregister_handle(handle);
1302 err_free_handle:
1303 kfree(handle);
1304 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305}
1306
1307static void kbd_disconnect(struct input_handle *handle)
1308{
1309 input_close_device(handle);
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001310 input_unregister_handle(handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 kfree(handle);
1312}
1313
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001314/*
1315 * Start keyboard handler on the new keyboard by refreshing LED state to
1316 * match the rest of the system.
1317 */
1318static void kbd_start(struct input_handle *handle)
1319{
1320 unsigned char leds = ledstate;
1321
1322 tasklet_disable(&keyboard_tasklet);
1323 if (leds != 0xff) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -04001324 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
1325 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
1326 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
1327 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001328 }
1329 tasklet_enable(&keyboard_tasklet);
1330}
1331
Dmitry Torokhov66e66112006-09-14 01:31:59 -04001332static const struct input_device_id kbd_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 {
1334 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1335 .evbit = { BIT(EV_KEY) },
1336 },
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001337
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 {
1339 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1340 .evbit = { BIT(EV_SND) },
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001341 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
1343 { }, /* Terminating entry */
1344};
1345
1346MODULE_DEVICE_TABLE(input, kbd_ids);
1347
1348static struct input_handler kbd_handler = {
1349 .event = kbd_event,
1350 .connect = kbd_connect,
1351 .disconnect = kbd_disconnect,
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001352 .start = kbd_start,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 .name = "kbd",
1354 .id_table = kbd_ids,
1355};
1356
1357int __init kbd_init(void)
1358{
1359 int i;
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001360 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
Dmitry Torokhov2b192902006-07-19 01:13:26 -04001362 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1363 kbd_table[i].ledflagstate = KBD_DEFLEDS;
1364 kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
1365 kbd_table[i].ledmode = LED_SHOW_FLAGS;
1366 kbd_table[i].lockstate = KBD_DEFLOCK;
1367 kbd_table[i].slockstate = 0;
1368 kbd_table[i].modeflags = KBD_DEFMODE;
1369 kbd_table[i].kbdmode = VC_XLATE;
1370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001372 error = input_register_handler(&kbd_handler);
1373 if (error)
1374 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
1376 tasklet_enable(&keyboard_tasklet);
1377 tasklet_schedule(&keyboard_tasklet);
1378
1379 return 0;
1380}