blob: d0369e05490a57898d63e202375475b500c3ae93 [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>
Samuel Thibault41ab4392007-10-18 23:39:12 -070044#include <linux/notifier.h>
Julia Lawallb39b0442008-04-17 09:28:25 -040045#include <linux/jiffies.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Linus Torvalds1da177e2005-04-16 15:20:36 -070047extern void ctrl_alt_del(void);
48
Joe Perches253b00f2008-05-07 11:15:23 -040049#define to_handle_h(n) container_of(n, struct input_handle, h_node)
50
Linus Torvalds1da177e2005-04-16 15:20:36 -070051/*
52 * Exported functions/variables
53 */
54
55#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
56
57/*
58 * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
59 * This seems a good reason to start with NumLock off. On HIL keyboards
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050060 * of PARISC machines however there is no NumLock key and everyone expects the keypad
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 * to be used for numbers.
62 */
63
64#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
65#define KBD_DEFLEDS (1 << VC_NUMLOCK)
66#else
67#define KBD_DEFLEDS 0
68#endif
69
70#define KBD_DEFLOCK 0
71
72void compute_shiftstate(void);
73
74/*
75 * Handler Tables.
76 */
77
78#define K_HANDLERS\
79 k_self, k_fn, k_spec, k_pad,\
80 k_dead, k_cons, k_cur, k_shift,\
81 k_meta, k_ascii, k_lock, k_lowercase,\
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -050082 k_slock, k_dead2, k_brl, k_ignore
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050084typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
David Howells7d12e782006-10-05 14:55:46 +010085 char up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086static k_handler_fn K_HANDLERS;
Samuel Thibault41ab4392007-10-18 23:39:12 -070087k_handler_fn *k_handler[16] = { K_HANDLERS };
88EXPORT_SYMBOL_GPL(k_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
90#define FN_HANDLERS\
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050091 fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
92 fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
93 fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
94 fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
95 fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
David Howells7d12e782006-10-05 14:55:46 +010097typedef void (fn_handler_fn)(struct vc_data *vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070098static fn_handler_fn FN_HANDLERS;
99static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
100
101/*
102 * Variables exported for vt_ioctl.c
103 */
104
105/* maximum values each key_handler can handle */
106const int max_vals[] = {
107 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
108 NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500109 255, NR_LOCK - 1, 255, NR_BRL - 1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110};
111
112const int NR_TYPES = ARRAY_SIZE(max_vals);
113
114struct kbd_struct kbd_table[MAX_NR_CONSOLES];
Samuel Thibaultf7511d52008-04-30 00:54:51 -0700115EXPORT_SYMBOL_GPL(kbd_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116static struct kbd_struct *kbd = kbd_table;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700118struct vt_spawn_console vt_spawn_con = {
Milind Arun Choudharyccc94252007-05-08 00:30:09 -0700119 .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700120 .pid = NULL,
121 .sig = 0,
122};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
124/*
125 * Variables exported for vt.c
126 */
127
128int shift_state = 0;
129
130/*
131 * Internal Data.
132 */
133
134static struct input_handler kbd_handler;
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700135static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
137static int dead_key_next;
138static int npadch = -1; /* -1 or number assembled on pad */
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500139static unsigned int diacr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140static char rep; /* flag telling character repeat */
141
142static unsigned char ledstate = 0xff; /* undefined */
143static unsigned char ledioctl;
144
145static struct ledptr {
146 unsigned int *addr;
147 unsigned int mask;
148 unsigned char valid:1;
149} ledptrs[3];
150
151/* Simple translation table for the SysRq keys */
152
153#ifdef CONFIG_MAGIC_SYSRQ
154unsigned char kbd_sysrq_xlate[KEY_MAX + 1] =
155 "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
156 "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
157 "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
158 "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
159 "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
160 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
161 "\r\000/"; /* 0x60 - 0x6f */
162static int sysrq_down;
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -0700163static int sysrq_alt_use;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164#endif
165static int sysrq_alt;
166
167/*
Samuel Thibault41ab4392007-10-18 23:39:12 -0700168 * Notifier list for console keyboard events
169 */
170static ATOMIC_NOTIFIER_HEAD(keyboard_notifier_list);
171
172int register_keyboard_notifier(struct notifier_block *nb)
173{
174 return atomic_notifier_chain_register(&keyboard_notifier_list, nb);
175}
176EXPORT_SYMBOL_GPL(register_keyboard_notifier);
177
178int unregister_keyboard_notifier(struct notifier_block *nb)
179{
180 return atomic_notifier_chain_unregister(&keyboard_notifier_list, nb);
181}
182EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
183
184/*
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400185 * Translation of scancodes to keycodes. We set them on only the first
186 * keyboard in the list that accepts the scancode and keycode.
187 * Explanation for not choosing the first attached keyboard anymore:
188 * USB keyboards for example have two event devices: one for all "normal"
189 * keys and one for extra function keys (like "volume up", "make coffee",
190 * etc.). So this means that scancodes for the extra function keys won't
191 * be valid for the first event device, but will be for the second.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 */
193int getkeycode(unsigned int scancode)
194{
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400195 struct input_handle *handle;
196 int keycode;
197 int error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400199 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
Dmitry Torokhovf4f37c82007-11-04 00:41:12 -0400200 error = input_get_keycode(handle->dev, scancode, &keycode);
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400201 if (!error)
202 return keycode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 }
204
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400205 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206}
207
208int setkeycode(unsigned int scancode, unsigned int keycode)
209{
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400210 struct input_handle *handle;
211 int error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400213 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
Dmitry Torokhovf4f37c82007-11-04 00:41:12 -0400214 error = input_set_keycode(handle->dev, scancode, keycode);
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400215 if (!error)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500216 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 }
218
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400219 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220}
221
222/*
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500223 * Making beeps and bells.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 */
225static void kd_nosound(unsigned long ignored)
226{
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400227 struct input_handle *handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400229 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 if (test_bit(EV_SND, handle->dev->evbit)) {
231 if (test_bit(SND_TONE, handle->dev->sndbit))
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400232 input_inject_event(handle, EV_SND, SND_TONE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 if (test_bit(SND_BELL, handle->dev->sndbit))
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400234 input_inject_event(handle, EV_SND, SND_BELL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 }
236 }
237}
238
Ingo Molnar8d06afa2005-09-09 13:10:40 -0700239static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
241void kd_mksound(unsigned int hz, unsigned int ticks)
242{
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500243 struct list_head *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
245 del_timer(&kd_mksound_timer);
246
247 if (hz) {
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500248 list_for_each_prev(node, &kbd_handler.h_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 struct input_handle *handle = to_handle_h(node);
250 if (test_bit(EV_SND, handle->dev->evbit)) {
251 if (test_bit(SND_TONE, handle->dev->sndbit)) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400252 input_inject_event(handle, EV_SND, SND_TONE, hz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 break;
254 }
255 if (test_bit(SND_BELL, handle->dev->sndbit)) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400256 input_inject_event(handle, EV_SND, SND_BELL, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 break;
258 }
259 }
260 }
261 if (ticks)
262 mod_timer(&kd_mksound_timer, jiffies + ticks);
263 } else
264 kd_nosound(0);
265}
Samuel Thibaultf7511d52008-04-30 00:54:51 -0700266EXPORT_SYMBOL(kd_mksound);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
268/*
269 * Setting the keyboard rate.
270 */
271
272int kbd_rate(struct kbd_repeat *rep)
273{
274 struct list_head *node;
275 unsigned int d = 0;
276 unsigned int p = 0;
277
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400278 list_for_each(node, &kbd_handler.h_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 struct input_handle *handle = to_handle_h(node);
280 struct input_dev *dev = handle->dev;
281
282 if (test_bit(EV_REP, dev->evbit)) {
283 if (rep->delay > 0)
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400284 input_inject_event(handle, EV_REP, REP_DELAY, rep->delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 if (rep->period > 0)
Dmitry Torokhov0e739d22006-07-06 00:22:43 -0400286 input_inject_event(handle, EV_REP, REP_PERIOD, rep->period);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 d = dev->rep[REP_DELAY];
288 p = dev->rep[REP_PERIOD];
289 }
290 }
291 rep->delay = d;
292 rep->period = p;
293 return 0;
294}
295
296/*
297 * Helper Functions.
298 */
299static void put_queue(struct vc_data *vc, int ch)
300{
301 struct tty_struct *tty = vc->vc_tty;
302
303 if (tty) {
304 tty_insert_flip_char(tty, ch, 0);
305 con_schedule_flip(tty);
306 }
307}
308
309static void puts_queue(struct vc_data *vc, char *cp)
310{
311 struct tty_struct *tty = vc->vc_tty;
312
313 if (!tty)
314 return;
315
316 while (*cp) {
317 tty_insert_flip_char(tty, *cp, 0);
318 cp++;
319 }
320 con_schedule_flip(tty);
321}
322
323static void applkey(struct vc_data *vc, int key, char mode)
324{
325 static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
326
327 buf[1] = (mode ? 'O' : '[');
328 buf[2] = key;
329 puts_queue(vc, buf);
330}
331
332/*
333 * Many other routines do put_queue, but I think either
334 * they produce ASCII, or they produce some user-assigned
335 * string, and in both cases we might assume that it is
Jan Engelhardt759448f2007-07-15 23:40:40 -0700336 * in utf-8 already.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 */
Jan Engelhardt759448f2007-07-15 23:40:40 -0700338static void to_utf8(struct vc_data *vc, uint c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339{
340 if (c < 0x80)
341 /* 0******* */
342 put_queue(vc, c);
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500343 else if (c < 0x800) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 /* 110***** 10****** */
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500345 put_queue(vc, 0xc0 | (c >> 6));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 put_queue(vc, 0x80 | (c & 0x3f));
Jan Engelhardt759448f2007-07-15 23:40:40 -0700347 } else if (c < 0x10000) {
348 if (c >= 0xD800 && c < 0xE000)
349 return;
350 if (c == 0xFFFF)
351 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 /* 1110**** 10****** 10****** */
353 put_queue(vc, 0xe0 | (c >> 12));
354 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
355 put_queue(vc, 0x80 | (c & 0x3f));
Jan Engelhardt759448f2007-07-15 23:40:40 -0700356 } else if (c < 0x110000) {
357 /* 11110*** 10****** 10****** 10****** */
358 put_queue(vc, 0xf0 | (c >> 18));
359 put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
360 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
361 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363}
364
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500365/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 * Called after returning from RAW mode or when changing consoles - recompute
367 * shift_down[] and shift_state from key_down[] maybe called when keymap is
368 * undefined, so that shiftkey release is seen
369 */
370void compute_shiftstate(void)
371{
372 unsigned int i, j, k, sym, val;
373
374 shift_state = 0;
375 memset(shift_down, 0, sizeof(shift_down));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 for (i = 0; i < ARRAY_SIZE(key_down); i++) {
378
379 if (!key_down[i])
380 continue;
381
382 k = i * BITS_PER_LONG;
383
384 for (j = 0; j < BITS_PER_LONG; j++, k++) {
385
386 if (!test_bit(k, key_down))
387 continue;
388
389 sym = U(key_maps[0][k]);
390 if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
391 continue;
392
393 val = KVAL(sym);
394 if (val == KVAL(K_CAPSSHIFT))
395 val = KVAL(K_SHIFT);
396
397 shift_down[val]++;
398 shift_state |= (1 << val);
399 }
400 }
401}
402
403/*
404 * We have a combining character DIACR here, followed by the character CH.
405 * If the combination occurs in the table, return the corresponding value.
406 * Otherwise, if CH is a space or equals DIACR, return DIACR.
407 * Otherwise, conclude that DIACR was not combining after all,
408 * queue it and return CH.
409 */
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500410static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411{
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500412 unsigned int d = diacr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 unsigned int i;
414
415 diacr = 0;
416
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500417 if ((d & ~0xff) == BRL_UC_ROW) {
418 if ((ch & ~0xff) == BRL_UC_ROW)
419 return d | ch;
420 } else {
421 for (i = 0; i < accent_table_size; i++)
422 if (accent_table[i].diacr == d && accent_table[i].base == ch)
423 return accent_table[i].result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 }
425
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500426 if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 return d;
428
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500429 if (kbd->kbdmode == VC_UNICODE)
Samuel Thibault04c71972007-10-16 23:27:04 -0700430 to_utf8(vc, d);
431 else {
432 int c = conv_uni_to_8bit(d);
433 if (c != -1)
434 put_queue(vc, c);
435 }
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500436
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 return ch;
438}
439
440/*
441 * Special function handlers
442 */
David Howells7d12e782006-10-05 14:55:46 +0100443static void fn_enter(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444{
445 if (diacr) {
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500446 if (kbd->kbdmode == VC_UNICODE)
Samuel Thibault04c71972007-10-16 23:27:04 -0700447 to_utf8(vc, diacr);
448 else {
449 int c = conv_uni_to_8bit(diacr);
450 if (c != -1)
451 put_queue(vc, c);
452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 diacr = 0;
454 }
455 put_queue(vc, 13);
456 if (vc_kbd_mode(kbd, VC_CRLF))
457 put_queue(vc, 10);
458}
459
David Howells7d12e782006-10-05 14:55:46 +0100460static void fn_caps_toggle(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461{
462 if (rep)
463 return;
464 chg_vc_kbd_led(kbd, VC_CAPSLOCK);
465}
466
David Howells7d12e782006-10-05 14:55:46 +0100467static void fn_caps_on(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468{
469 if (rep)
470 return;
471 set_vc_kbd_led(kbd, VC_CAPSLOCK);
472}
473
David Howells7d12e782006-10-05 14:55:46 +0100474static void fn_show_ptregs(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475{
David Howells7d12e782006-10-05 14:55:46 +0100476 struct pt_regs *regs = get_irq_regs();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 if (regs)
478 show_regs(regs);
479}
480
David Howells7d12e782006-10-05 14:55:46 +0100481static void fn_hold(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482{
483 struct tty_struct *tty = vc->vc_tty;
484
485 if (rep || !tty)
486 return;
487
488 /*
489 * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
490 * these routines are also activated by ^S/^Q.
491 * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
492 */
493 if (tty->stopped)
494 start_tty(tty);
495 else
496 stop_tty(tty);
497}
498
David Howells7d12e782006-10-05 14:55:46 +0100499static void fn_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500{
501 if (vc_kbd_mode(kbd,VC_APPLIC))
502 applkey(vc, 'P', 1);
503 else
David Howells7d12e782006-10-05 14:55:46 +0100504 fn_bare_num(vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505}
506
507/*
508 * Bind this to Shift-NumLock if you work in application keypad mode
509 * but want to be able to change the NumLock flag.
510 * Bind this to NumLock if you prefer that the NumLock key always
511 * changes the NumLock flag.
512 */
David Howells7d12e782006-10-05 14:55:46 +0100513static void fn_bare_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514{
515 if (!rep)
516 chg_vc_kbd_led(kbd, VC_NUMLOCK);
517}
518
David Howells7d12e782006-10-05 14:55:46 +0100519static void fn_lastcons(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520{
521 /* switch to the last used console, ChN */
522 set_console(last_console);
523}
524
David Howells7d12e782006-10-05 14:55:46 +0100525static void fn_dec_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526{
527 int i, cur = fg_console;
528
529 /* Currently switching? Queue this next switch relative to that. */
530 if (want_console != -1)
531 cur = want_console;
532
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500533 for (i = cur - 1; i != cur; i--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 if (i == -1)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500535 i = MAX_NR_CONSOLES - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 if (vc_cons_allocated(i))
537 break;
538 }
539 set_console(i);
540}
541
David Howells7d12e782006-10-05 14:55:46 +0100542static void fn_inc_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543{
544 int i, cur = fg_console;
545
546 /* Currently switching? Queue this next switch relative to that. */
547 if (want_console != -1)
548 cur = want_console;
549
550 for (i = cur+1; i != cur; i++) {
551 if (i == MAX_NR_CONSOLES)
552 i = 0;
553 if (vc_cons_allocated(i))
554 break;
555 }
556 set_console(i);
557}
558
David Howells7d12e782006-10-05 14:55:46 +0100559static void fn_send_intr(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560{
561 struct tty_struct *tty = vc->vc_tty;
562
563 if (!tty)
564 return;
565 tty_insert_flip_char(tty, 0, TTY_BREAK);
566 con_schedule_flip(tty);
567}
568
David Howells7d12e782006-10-05 14:55:46 +0100569static void fn_scroll_forw(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570{
571 scrollfront(vc, 0);
572}
573
David Howells7d12e782006-10-05 14:55:46 +0100574static void fn_scroll_back(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575{
576 scrollback(vc, 0);
577}
578
David Howells7d12e782006-10-05 14:55:46 +0100579static void fn_show_mem(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
581 show_mem();
582}
583
David Howells7d12e782006-10-05 14:55:46 +0100584static void fn_show_state(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585{
586 show_state();
587}
588
David Howells7d12e782006-10-05 14:55:46 +0100589static void fn_boot_it(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590{
591 ctrl_alt_del();
592}
593
David Howells7d12e782006-10-05 14:55:46 +0100594static void fn_compose(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595{
596 dead_key_next = 1;
597}
598
David Howells7d12e782006-10-05 14:55:46 +0100599static void fn_spawn_con(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600{
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700601 spin_lock(&vt_spawn_con.lock);
602 if (vt_spawn_con.pid)
603 if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
604 put_pid(vt_spawn_con.pid);
605 vt_spawn_con.pid = NULL;
606 }
607 spin_unlock(&vt_spawn_con.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608}
609
David Howells7d12e782006-10-05 14:55:46 +0100610static void fn_SAK(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611{
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800612 struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800613 schedule_work(SAK_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614}
615
David Howells7d12e782006-10-05 14:55:46 +0100616static void fn_null(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617{
618 compute_shiftstate();
619}
620
621/*
622 * Special key handlers
623 */
David Howells7d12e782006-10-05 14:55:46 +0100624static void k_ignore(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625{
626}
627
David Howells7d12e782006-10-05 14:55:46 +0100628static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629{
630 if (up_flag)
631 return;
632 if (value >= ARRAY_SIZE(fn_handler))
633 return;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500634 if ((kbd->kbdmode == VC_RAW ||
635 kbd->kbdmode == VC_MEDIUMRAW) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 value != KVAL(K_SAK))
637 return; /* SAK is allowed even in raw mode */
David Howells7d12e782006-10-05 14:55:46 +0100638 fn_handler[value](vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639}
640
David Howells7d12e782006-10-05 14:55:46 +0100641static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642{
643 printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
644}
645
David Howells7d12e782006-10-05 14:55:46 +0100646static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647{
648 if (up_flag)
649 return; /* no action, if this is a key release */
650
651 if (diacr)
652 value = handle_diacr(vc, value);
653
654 if (dead_key_next) {
655 dead_key_next = 0;
656 diacr = value;
657 return;
658 }
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500659 if (kbd->kbdmode == VC_UNICODE)
Samuel Thibault04c71972007-10-16 23:27:04 -0700660 to_utf8(vc, value);
661 else {
662 int c = conv_uni_to_8bit(value);
663 if (c != -1)
664 put_queue(vc, c);
665 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666}
667
668/*
669 * Handle dead key. Note that we now may have several
670 * dead keys modifying the same character. Very useful
671 * for Vietnamese.
672 */
David Howells7d12e782006-10-05 14:55:46 +0100673static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674{
675 if (up_flag)
676 return;
677 diacr = (diacr ? handle_diacr(vc, value) : value);
678}
679
David Howells7d12e782006-10-05 14:55:46 +0100680static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500681{
Samuel Thibault04c71972007-10-16 23:27:04 -0700682 unsigned int uni;
683 if (kbd->kbdmode == VC_UNICODE)
684 uni = value;
685 else
686 uni = conv_8bit_to_uni(value);
687 k_unicode(vc, uni, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500688}
689
David Howells7d12e782006-10-05 14:55:46 +0100690static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500691{
David Howells7d12e782006-10-05 14:55:46 +0100692 k_deadunicode(vc, value, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500693}
694
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695/*
696 * Obsolete - for backwards compatibility only
697 */
David Howells7d12e782006-10-05 14:55:46 +0100698static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699{
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400700 static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 value = ret_diacr[value];
David Howells7d12e782006-10-05 14:55:46 +0100702 k_deadunicode(vc, value, up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703}
704
David Howells7d12e782006-10-05 14:55:46 +0100705static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706{
707 if (up_flag)
708 return;
709 set_console(value);
710}
711
David Howells7d12e782006-10-05 14:55:46 +0100712static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713{
714 unsigned v;
715
716 if (up_flag)
717 return;
718 v = value;
719 if (v < ARRAY_SIZE(func_table)) {
720 if (func_table[value])
721 puts_queue(vc, func_table[value]);
722 } else
723 printk(KERN_ERR "k_fn called with value=%d\n", value);
724}
725
David Howells7d12e782006-10-05 14:55:46 +0100726static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727{
Brandon Philipse52b29c2006-11-04 22:09:08 -0500728 static const char cur_chars[] = "BDCA";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
730 if (up_flag)
731 return;
732 applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
733}
734
David Howells7d12e782006-10-05 14:55:46 +0100735static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736{
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400737 static const char pad_chars[] = "0123456789+-*/\015,.?()#";
738 static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
740 if (up_flag)
741 return; /* no action, if this is a key release */
742
743 /* kludge... shift forces cursor/number keys */
744 if (vc_kbd_mode(kbd, VC_APPLIC) && !shift_down[KG_SHIFT]) {
745 applkey(vc, app_map[value], 1);
746 return;
747 }
748
749 if (!vc_kbd_led(kbd, VC_NUMLOCK))
750 switch (value) {
751 case KVAL(K_PCOMMA):
752 case KVAL(K_PDOT):
David Howells7d12e782006-10-05 14:55:46 +0100753 k_fn(vc, KVAL(K_REMOVE), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 return;
755 case KVAL(K_P0):
David Howells7d12e782006-10-05 14:55:46 +0100756 k_fn(vc, KVAL(K_INSERT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 return;
758 case KVAL(K_P1):
David Howells7d12e782006-10-05 14:55:46 +0100759 k_fn(vc, KVAL(K_SELECT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 return;
761 case KVAL(K_P2):
David Howells7d12e782006-10-05 14:55:46 +0100762 k_cur(vc, KVAL(K_DOWN), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 return;
764 case KVAL(K_P3):
David Howells7d12e782006-10-05 14:55:46 +0100765 k_fn(vc, KVAL(K_PGDN), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 return;
767 case KVAL(K_P4):
David Howells7d12e782006-10-05 14:55:46 +0100768 k_cur(vc, KVAL(K_LEFT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 return;
770 case KVAL(K_P6):
David Howells7d12e782006-10-05 14:55:46 +0100771 k_cur(vc, KVAL(K_RIGHT), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 return;
773 case KVAL(K_P7):
David Howells7d12e782006-10-05 14:55:46 +0100774 k_fn(vc, KVAL(K_FIND), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 return;
776 case KVAL(K_P8):
David Howells7d12e782006-10-05 14:55:46 +0100777 k_cur(vc, KVAL(K_UP), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 return;
779 case KVAL(K_P9):
David Howells7d12e782006-10-05 14:55:46 +0100780 k_fn(vc, KVAL(K_PGUP), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 return;
782 case KVAL(K_P5):
783 applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
784 return;
785 }
786
787 put_queue(vc, pad_chars[value]);
788 if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
789 put_queue(vc, 10);
790}
791
David Howells7d12e782006-10-05 14:55:46 +0100792static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793{
794 int old_state = shift_state;
795
796 if (rep)
797 return;
798 /*
799 * Mimic typewriter:
800 * a CapsShift key acts like Shift but undoes CapsLock
801 */
802 if (value == KVAL(K_CAPSSHIFT)) {
803 value = KVAL(K_SHIFT);
804 if (!up_flag)
805 clr_vc_kbd_led(kbd, VC_CAPSLOCK);
806 }
807
808 if (up_flag) {
809 /*
810 * handle the case that two shift or control
811 * keys are depressed simultaneously
812 */
813 if (shift_down[value])
814 shift_down[value]--;
815 } else
816 shift_down[value]++;
817
818 if (shift_down[value])
819 shift_state |= (1 << value);
820 else
821 shift_state &= ~(1 << value);
822
823 /* kludge */
824 if (up_flag && shift_state != old_state && npadch != -1) {
825 if (kbd->kbdmode == VC_UNICODE)
Jan Engelhardt759448f2007-07-15 23:40:40 -0700826 to_utf8(vc, npadch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 else
828 put_queue(vc, npadch & 0xff);
829 npadch = -1;
830 }
831}
832
David Howells7d12e782006-10-05 14:55:46 +0100833static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834{
835 if (up_flag)
836 return;
837
838 if (vc_kbd_mode(kbd, VC_META)) {
839 put_queue(vc, '\033');
840 put_queue(vc, value);
841 } else
842 put_queue(vc, value | 0x80);
843}
844
David Howells7d12e782006-10-05 14:55:46 +0100845static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846{
847 int base;
848
849 if (up_flag)
850 return;
851
852 if (value < 10) {
853 /* decimal input of code, while Alt depressed */
854 base = 10;
855 } else {
856 /* hexadecimal input of code, while AltGr depressed */
857 value -= 10;
858 base = 16;
859 }
860
861 if (npadch == -1)
862 npadch = value;
863 else
864 npadch = npadch * base + value;
865}
866
David Howells7d12e782006-10-05 14:55:46 +0100867static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868{
869 if (up_flag || rep)
870 return;
871 chg_vc_kbd_lock(kbd, value);
872}
873
David Howells7d12e782006-10-05 14:55:46 +0100874static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875{
David Howells7d12e782006-10-05 14:55:46 +0100876 k_shift(vc, value, up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 if (up_flag || rep)
878 return;
879 chg_vc_kbd_slock(kbd, value);
880 /* try to make Alt, oops, AltGr and such work */
881 if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
882 kbd->slockstate = 0;
883 chg_vc_kbd_slock(kbd, value);
884 }
885}
886
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500887/* by default, 300ms interval for combination release */
Samuel Thibault77426d72006-04-26 00:14:10 -0400888static unsigned brl_timeout = 300;
889MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
890module_param(brl_timeout, uint, 0644);
891
892static unsigned brl_nbchords = 1;
893MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
894module_param(brl_nbchords, uint, 0644);
895
David Howells7d12e782006-10-05 14:55:46 +0100896static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag)
Samuel Thibault77426d72006-04-26 00:14:10 -0400897{
898 static unsigned long chords;
899 static unsigned committed;
900
901 if (!brl_nbchords)
David Howells7d12e782006-10-05 14:55:46 +0100902 k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400903 else {
904 committed |= pattern;
905 chords++;
906 if (chords == brl_nbchords) {
David Howells7d12e782006-10-05 14:55:46 +0100907 k_unicode(vc, BRL_UC_ROW | committed, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400908 chords = 0;
909 committed = 0;
910 }
911 }
912}
913
David Howells7d12e782006-10-05 14:55:46 +0100914static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500915{
916 static unsigned pressed,committing;
917 static unsigned long releasestart;
918
919 if (kbd->kbdmode != VC_UNICODE) {
920 if (!up_flag)
921 printk("keyboard mode must be unicode for braille patterns\n");
922 return;
923 }
924
925 if (!value) {
David Howells7d12e782006-10-05 14:55:46 +0100926 k_unicode(vc, BRL_UC_ROW, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500927 return;
928 }
929
930 if (value > 8)
931 return;
932
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500933 if (up_flag) {
934 if (brl_timeout) {
935 if (!committing ||
Julia Lawallb39b0442008-04-17 09:28:25 -0400936 time_after(jiffies,
937 releasestart + msecs_to_jiffies(brl_timeout))) {
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500938 committing = pressed;
939 releasestart = jiffies;
940 }
941 pressed &= ~(1 << (value - 1));
942 if (!pressed) {
943 if (committing) {
David Howells7d12e782006-10-05 14:55:46 +0100944 k_brlcommit(vc, committing, 0);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500945 committing = 0;
946 }
947 }
948 } else {
949 if (committing) {
David Howells7d12e782006-10-05 14:55:46 +0100950 k_brlcommit(vc, committing, 0);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500951 committing = 0;
952 }
953 pressed &= ~(1 << (value - 1));
954 }
955 } else {
956 pressed |= 1 << (value - 1);
957 if (!brl_timeout)
958 committing = pressed;
959 }
960}
961
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962/*
963 * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
964 * or (ii) whatever pattern of lights people want to show using KDSETLED,
965 * or (iii) specified bits of specified words in kernel memory.
966 */
967unsigned char getledstate(void)
968{
969 return ledstate;
970}
971
972void setledstate(struct kbd_struct *kbd, unsigned int led)
973{
974 if (!(led & ~7)) {
975 ledioctl = led;
976 kbd->ledmode = LED_SHOW_IOCTL;
977 } else
978 kbd->ledmode = LED_SHOW_FLAGS;
979 set_leds();
980}
981
982static inline unsigned char getleds(void)
983{
984 struct kbd_struct *kbd = kbd_table + fg_console;
985 unsigned char leds;
986 int i;
987
988 if (kbd->ledmode == LED_SHOW_IOCTL)
989 return ledioctl;
990
991 leds = kbd->ledflagstate;
992
993 if (kbd->ledmode == LED_SHOW_MEM) {
994 for (i = 0; i < 3; i++)
995 if (ledptrs[i].valid) {
996 if (*ledptrs[i].addr & ledptrs[i].mask)
997 leds |= (1 << i);
998 else
999 leds &= ~(1 << i);
1000 }
1001 }
1002 return leds;
1003}
1004
1005/*
1006 * This routine is the bottom half of the keyboard interrupt
1007 * routine, and runs with all interrupts enabled. It does
1008 * console changing, led setting and copy_to_cooked, which can
1009 * take a reasonably long time.
1010 *
1011 * Aside from timing (which isn't really that important for
1012 * keyboard interrupts as they happen often), using the software
1013 * interrupt routines for this thing allows us to easily mask
1014 * this when we don't want any of the above to happen.
1015 * This allows for easy and efficient race-condition prevention
Dmitry Torokhov0e739d22006-07-06 00:22:43 -04001016 * for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 */
1018
1019static void kbd_bh(unsigned long dummy)
1020{
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001021 struct list_head *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 unsigned char leds = getleds();
1023
1024 if (leds != ledstate) {
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001025 list_for_each(node, &kbd_handler.h_list) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -04001026 struct input_handle *handle = to_handle_h(node);
1027 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
1028 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
1029 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
1030 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 }
1032 }
1033
1034 ledstate = leds;
1035}
1036
1037DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
1038
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001040 defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
1041 defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
Hans-Christian Egtvedt3a4e8322007-12-04 13:15:41 +01001042 (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) ||\
1043 defined(CONFIG_AVR32)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
1045#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
1046 ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
1047
Andreas Mohr0f5e5602006-06-05 00:18:00 -04001048static const unsigned short x86_keycodes[256] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1050 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1051 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
1052 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
1053 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
1054 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001055 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
1057 360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
Hans de Goede72a42f22007-07-03 01:55:18 -04001058 103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
1059 291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
1061 377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
1062 308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
1063 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
1064
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001065#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066static int sparc_l1_a_state = 0;
1067extern void sun_do_break(void);
1068#endif
1069
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001070static int emulate_raw(struct vc_data *vc, unsigned int keycode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 unsigned char up_flag)
1072{
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001073 int code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
1075 switch (keycode) {
1076 case KEY_PAUSE:
1077 put_queue(vc, 0xe1);
1078 put_queue(vc, 0x1d | up_flag);
1079 put_queue(vc, 0x45 | up_flag);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001080 break;
1081
Jerome Pinotb9ab58d2006-06-26 01:51:23 -04001082 case KEY_HANGEUL:
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -04001083 if (!up_flag)
1084 put_queue(vc, 0xf2);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001085 break;
1086
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 case KEY_HANJA:
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -04001088 if (!up_flag)
1089 put_queue(vc, 0xf1);
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001090 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001092 case KEY_SYSRQ:
1093 /*
1094 * Real AT keyboards (that's what we're trying
1095 * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
1096 * pressing PrtSc/SysRq alone, but simply 0x54
1097 * when pressing Alt+PrtSc/SysRq.
1098 */
1099 if (sysrq_alt) {
1100 put_queue(vc, 0x54 | up_flag);
1101 } else {
1102 put_queue(vc, 0xe0);
1103 put_queue(vc, 0x2a | up_flag);
1104 put_queue(vc, 0xe0);
1105 put_queue(vc, 0x37 | up_flag);
1106 }
1107 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001109 default:
1110 if (keycode > 255)
1111 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001113 code = x86_keycodes[keycode];
1114 if (!code)
1115 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001117 if (code & 0x100)
1118 put_queue(vc, 0xe0);
1119 put_queue(vc, (code & 0x7f) | up_flag);
1120
1121 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 }
1123
1124 return 0;
1125}
1126
1127#else
1128
1129#define HW_RAW(dev) 0
1130
1131#warning "Cannot generate rawmode keyboard for your architecture yet."
1132
1133static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
1134{
1135 if (keycode > 127)
1136 return -1;
1137
1138 put_queue(vc, keycode | up_flag);
1139 return 0;
1140}
1141#endif
1142
1143static void kbd_rawcode(unsigned char data)
1144{
1145 struct vc_data *vc = vc_cons[fg_console].d;
1146 kbd = kbd_table + fg_console;
1147 if (kbd->kbdmode == VC_RAW)
1148 put_queue(vc, data);
1149}
1150
David Howells7d12e782006-10-05 14:55:46 +01001151static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152{
1153 struct vc_data *vc = vc_cons[fg_console].d;
1154 unsigned short keysym, *key_map;
1155 unsigned char type, raw_mode;
1156 struct tty_struct *tty;
1157 int shift_final;
Samuel Thibault41ab4392007-10-18 23:39:12 -07001158 struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159
1160 tty = vc->vc_tty;
1161
1162 if (tty && (!tty->driver_data)) {
1163 /* No driver data? Strange. Okay we fix it then. */
1164 tty->driver_data = vc;
1165 }
1166
1167 kbd = kbd_table + fg_console;
1168
1169 if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001170 sysrq_alt = down ? keycode : 0;
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001171#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 if (keycode == KEY_STOP)
1173 sparc_l1_a_state = down;
1174#endif
1175
1176 rep = (down == 2);
1177
1178#ifdef CONFIG_MAC_EMUMOUSEBTN
1179 if (mac_hid_mouse_emulate_buttons(1, keycode, down))
1180 return;
1181#endif /* CONFIG_MAC_EMUMOUSEBTN */
1182
1183 if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
1184 if (emulate_raw(vc, keycode, !down << 7))
Dmitry Torokhov9e35d202007-04-12 01:30:52 -04001185 if (keycode < BTN_MISC && printk_ratelimit())
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
1187
1188#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
1189 if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001190 if (!sysrq_down) {
1191 sysrq_down = down;
1192 sysrq_alt_use = sysrq_alt;
1193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 return;
1195 }
Fredrik Roubertd2be8ee2006-06-26 00:24:35 -07001196 if (sysrq_down && !down && keycode == sysrq_alt_use)
1197 sysrq_down = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 if (sysrq_down && down && !rep) {
David Howells7d12e782006-10-05 14:55:46 +01001199 handle_sysrq(kbd_sysrq_xlate[keycode], tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 return;
1201 }
1202#endif
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001203#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 if (keycode == KEY_A && sparc_l1_a_state) {
1205 sparc_l1_a_state = 0;
1206 sun_do_break();
1207 }
1208#endif
1209
1210 if (kbd->kbdmode == VC_MEDIUMRAW) {
1211 /*
1212 * This is extended medium raw mode, with keys above 127
1213 * encoded as 0, high 7 bits, low 7 bits, with the 0 bearing
1214 * the 'up' flag if needed. 0 is reserved, so this shouldn't
1215 * interfere with anything else. The two bytes after 0 will
1216 * always have the up flag set not to interfere with older
1217 * applications. This allows for 16384 different keycodes,
1218 * which should be enough.
1219 */
1220 if (keycode < 128) {
1221 put_queue(vc, keycode | (!down << 7));
1222 } else {
1223 put_queue(vc, !down << 7);
1224 put_queue(vc, (keycode >> 7) | 0x80);
1225 put_queue(vc, keycode | 0x80);
1226 }
1227 raw_mode = 1;
1228 }
1229
1230 if (down)
1231 set_bit(keycode, key_down);
1232 else
1233 clear_bit(keycode, key_down);
1234
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001235 if (rep &&
1236 (!vc_kbd_mode(kbd, VC_REPEAT) ||
Alan Coxf34d7a52008-04-30 00:54:13 -07001237 (tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 /*
1239 * Don't repeat a key if the input buffers are not empty and the
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001240 * characters get aren't echoed locally. This makes key repeat
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 * usable with slow applications and under heavy loads.
1242 */
1243 return;
1244 }
1245
Samuel Thibault41ab4392007-10-18 23:39:12 -07001246 param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
Karl Dahlke0beb4f62008-04-15 01:30:32 -04001247 param.ledstate = kbd->ledflagstate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 key_map = key_maps[shift_final];
1249
Samuel Thibault41ab4392007-10-18 23:39:12 -07001250 if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, &param) == NOTIFY_STOP || !key_map) {
1251 atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNBOUND_KEYCODE, &param);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 compute_shiftstate();
1253 kbd->slockstate = 0;
1254 return;
1255 }
1256
1257 if (keycode > NR_KEYS)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -05001258 if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
1259 keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
1260 else
1261 return;
1262 else
1263 keysym = key_map[keycode];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 type = KTYP(keysym);
1266
1267 if (type < 0xf0) {
Samuel Thibault41ab4392007-10-18 23:39:12 -07001268 param.value = keysym;
1269 if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNICODE, &param) == NOTIFY_STOP)
1270 return;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001271 if (down && !raw_mode)
1272 to_utf8(vc, keysym);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 return;
1274 }
1275
1276 type -= 0xf0;
1277
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 if (type == KT_LETTER) {
1279 type = KT_LATIN;
1280 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
1281 key_map = key_maps[shift_final ^ (1 << KG_SHIFT)];
1282 if (key_map)
1283 keysym = key_map[keycode];
1284 }
1285 }
Samuel Thibault41ab4392007-10-18 23:39:12 -07001286 param.value = keysym;
1287
1288 if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYSYM, &param) == NOTIFY_STOP)
1289 return;
1290
1291 if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
1292 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
David Howells7d12e782006-10-05 14:55:46 +01001294 (*k_handler[type])(vc, keysym & 0xff, !down);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
Karl Dahlke0beb4f62008-04-15 01:30:32 -04001296 param.ledstate = kbd->ledflagstate;
Samuel Thibault41ab4392007-10-18 23:39:12 -07001297 atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
1298
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 if (type != KT_SLOCK)
1300 kbd->slockstate = 0;
1301}
1302
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001303static void kbd_event(struct input_handle *handle, unsigned int event_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 unsigned int event_code, int value)
1305{
1306 if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
1307 kbd_rawcode(value);
1308 if (event_type == EV_KEY)
David Howells7d12e782006-10-05 14:55:46 +01001309 kbd_keycode(event_code, value, HW_RAW(handle->dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 tasklet_schedule(&keyboard_tasklet);
1311 do_poke_blanked_console = 1;
1312 schedule_console_callback();
1313}
1314
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315/*
1316 * When a keyboard (or other input device) is found, the kbd_connect
1317 * function is called. The function then looks at the device, and if it
1318 * likes it, it can open it and get events from it. In this (kbd_connect)
1319 * function, we should decide which VT to bind that keyboard to initially.
1320 */
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001321static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
1322 const struct input_device_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323{
1324 struct input_handle *handle;
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001325 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 int i;
1327
1328 for (i = KEY_RESERVED; i < BTN_MISC; i++)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001329 if (test_bit(i, dev->keybit))
1330 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001332 if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001333 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Dmitry Torokhov22479e12006-08-04 22:51:51 -04001335 handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
1336 if (!handle)
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001337 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
1339 handle->dev = dev;
1340 handle->handler = handler;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001341 handle->name = "kbd";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001343 error = input_register_handle(handle);
1344 if (error)
1345 goto err_free_handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001347 error = input_open_device(handle);
1348 if (error)
1349 goto err_unregister_handle;
1350
1351 return 0;
1352
1353 err_unregister_handle:
1354 input_unregister_handle(handle);
1355 err_free_handle:
1356 kfree(handle);
1357 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358}
1359
1360static void kbd_disconnect(struct input_handle *handle)
1361{
1362 input_close_device(handle);
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001363 input_unregister_handle(handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 kfree(handle);
1365}
1366
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001367/*
1368 * Start keyboard handler on the new keyboard by refreshing LED state to
1369 * match the rest of the system.
1370 */
1371static void kbd_start(struct input_handle *handle)
1372{
1373 unsigned char leds = ledstate;
1374
1375 tasklet_disable(&keyboard_tasklet);
1376 if (leds != 0xff) {
Dmitry Torokhov0e739d22006-07-06 00:22:43 -04001377 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
1378 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
1379 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
1380 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001381 }
1382 tasklet_enable(&keyboard_tasklet);
1383}
1384
Dmitry Torokhov66e66112006-09-14 01:31:59 -04001385static const struct input_device_id kbd_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 {
1387 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
Jiri Slaby7b19ada2007-10-18 23:40:32 -07001388 .evbit = { BIT_MASK(EV_KEY) },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 },
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001390
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 {
1392 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
Jiri Slaby7b19ada2007-10-18 23:40:32 -07001393 .evbit = { BIT_MASK(EV_SND) },
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001394 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
1396 { }, /* Terminating entry */
1397};
1398
1399MODULE_DEVICE_TABLE(input, kbd_ids);
1400
1401static struct input_handler kbd_handler = {
1402 .event = kbd_event,
1403 .connect = kbd_connect,
1404 .disconnect = kbd_disconnect,
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001405 .start = kbd_start,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 .name = "kbd",
1407 .id_table = kbd_ids,
1408};
1409
1410int __init kbd_init(void)
1411{
1412 int i;
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001413 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
Dmitry Torokhov2b192902006-07-19 01:13:26 -04001415 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1416 kbd_table[i].ledflagstate = KBD_DEFLEDS;
1417 kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
1418 kbd_table[i].ledmode = LED_SHOW_FLAGS;
1419 kbd_table[i].lockstate = KBD_DEFLOCK;
1420 kbd_table[i].slockstate = 0;
1421 kbd_table[i].modeflags = KBD_DEFMODE;
Bill Nottingham2e8ecb92007-10-16 23:29:38 -07001422 kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
Dmitry Torokhov2b192902006-07-19 01:13:26 -04001423 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001425 error = input_register_handler(&kbd_handler);
1426 if (error)
1427 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
1429 tasklet_enable(&keyboard_tasklet);
1430 tasklet_schedule(&keyboard_tasklet);
1431
1432 return 0;
1433}