keyboard.c revision 079c9534a96da9a85a2a2f9715851050fbfbf749
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Written for linux by Johan Myreen as a translation from
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the assembly version by Linus (with diacriticals added)
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some additional features added by Christoph Niemann (ChN), March 1993
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Loadable keymaps by Risto Kankkunen, May 1993
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Added decr/incr_console, dynamic keymaps, Unicode support,
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dynamic function/string keys, led setting,  Sept 1994
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * `Sticky' modifier keys, 951006.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11-11-96: SAK should now work in the raw mode (Martin Mares)
15fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov *
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified to provide 'generic' keyboard support by Hamish Macdonald
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Merge with the m68k keyboard driver and split-off of the PC low-level
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * parts by Geert Uytterhoeven, May 1997
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 30-07-98: Dead keys redone, aeb@cwi.nl.
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
259272e9a2f8872a0f9fb15aaa10f2a993524343e0Dmitry Torokhov#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
269272e9a2f8872a0f9fb15aaa10f2a993524343e0Dmitry Torokhov
27759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardt#include <linux/consolemap.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_flip.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_kern.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_diacr.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt_kern.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/input.h>
4183cc5ed3c4c65fc4c3729a5cec2111ede1ebf85eAdrian Bunk#include <linux/reboot.h>
4241ab4396e19fba338baf28044d3e48385744b930Samuel Thibault#include <linux/notifier.h>
43b39b04403bba4f807ee6e57ae2f4407187588fcdJulia Lawall#include <linux/jiffies.h>
446623d64021469b0094bb070d3eb7d0e3f5e928afGreg Kroah-Hartman#include <linux/uaccess.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4698c2b37353cd8839f86f36e9bb9fe39f33fc9626Geert Uytterhoeven#include <asm/irq_regs.h>
4798c2b37353cd8839f86f36e9bb9fe39f33fc9626Geert Uytterhoeven
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void ctrl_alt_del(void);
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Exported functions/variables
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This seems a good reason to start with NumLock off. On HIL keyboards
596aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox * of PARISC machines however there is no NumLock key and everyone expects the
606aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox * keypad to be used for numbers.
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define KBD_DEFLEDS (1 << VC_NUMLOCK)
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define KBD_DEFLEDS 0
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define KBD_DEFLOCK 0
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handler Tables.
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define K_HANDLERS\
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	k_self,		k_fn,		k_spec,		k_pad,\
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	k_dead,		k_cons,		k_cur,		k_shift,\
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	k_meta,		k_ascii,	k_lock,		k_lowercase,\
79b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	k_slock,	k_dead2,	k_brl,		k_ignore
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhovtypedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
827d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells			    char up_flag);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic k_handler_fn K_HANDLERS;
8497f5f0cd8cd0a05449cbb77d1e6f02e026875802Dmitry Torokhovstatic k_handler_fn *k_handler[16] = { K_HANDLERS };
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FN_HANDLERS\
87fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	fn_null,	fn_enter,	fn_show_ptregs,	fn_show_mem,\
88fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	fn_show_state,	fn_send_intr,	fn_lastcons,	fn_caps_toggle,\
89fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	fn_num,		fn_hold,	fn_scroll_forw,	fn_scroll_back,\
90fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	fn_boot_it,	fn_caps_on,	fn_compose,	fn_SAK,\
91fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	fn_dec_console, fn_inc_console, fn_spawn_con,	fn_bare_num
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
937d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellstypedef void (fn_handler_fn)(struct vc_data *vc);
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic fn_handler_fn FN_HANDLERS;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic fn_handler_fn *fn_handler[] = { FN_HANDLERS };
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Variables exported for vt_ioctl.c
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10181af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biedermanstruct vt_spawn_console vt_spawn_con = {
102ccc942567e10d6a5d59c4d57f03d07b4110611eaMilind Arun Choudhary	.lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
10381af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman	.pid  = NULL,
10481af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman	.sig  = 0,
10581af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman};
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Internal Data.
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
112079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxstatic struct kbd_struct kbd_table[MAX_NR_CONSOLES];
113079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxstatic struct kbd_struct *kbd = kbd_table;
114079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
115079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/* maximum values each key_handler can handle */
116079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxstatic const int max_vals[] = {
117079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
118079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
119079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	255, NR_LOCK - 1, 255, NR_BRL - 1
120079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox};
121079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
122079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxstatic const int NR_TYPES = ARRAY_SIZE(max_vals);
123079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct input_handler kbd_handler;
12521cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhovstatic DEFINE_SPINLOCK(kbd_event_lock);
1267b19ada2ed3c1eccb9fe94d74b05e1428224663dJiri Slabystatic unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];	/* keyboard key bitmap */
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char shift_down[NR_SHIFT];		/* shift state counters.. */
128e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhovstatic bool dead_key_next;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int npadch = -1;					/* -1 or number assembled on pad */
130b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibaultstatic unsigned int diacr;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char rep;					/* flag telling character repeat */
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
133079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxstatic int shift_state = 0;
134079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char ledstate = 0xff;			/* undefined */
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char ledioctl;
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct ledptr {
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int *addr;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int mask;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char valid:1;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} ledptrs[3];
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
14541ab4396e19fba338baf28044d3e48385744b930Samuel Thibault * Notifier list for console keyboard events
14641ab4396e19fba338baf28044d3e48385744b930Samuel Thibault */
14741ab4396e19fba338baf28044d3e48385744b930Samuel Thibaultstatic ATOMIC_NOTIFIER_HEAD(keyboard_notifier_list);
14841ab4396e19fba338baf28044d3e48385744b930Samuel Thibault
14941ab4396e19fba338baf28044d3e48385744b930Samuel Thibaultint register_keyboard_notifier(struct notifier_block *nb)
15041ab4396e19fba338baf28044d3e48385744b930Samuel Thibault{
15141ab4396e19fba338baf28044d3e48385744b930Samuel Thibault	return atomic_notifier_chain_register(&keyboard_notifier_list, nb);
15241ab4396e19fba338baf28044d3e48385744b930Samuel Thibault}
15341ab4396e19fba338baf28044d3e48385744b930Samuel ThibaultEXPORT_SYMBOL_GPL(register_keyboard_notifier);
15441ab4396e19fba338baf28044d3e48385744b930Samuel Thibault
15541ab4396e19fba338baf28044d3e48385744b930Samuel Thibaultint unregister_keyboard_notifier(struct notifier_block *nb)
15641ab4396e19fba338baf28044d3e48385744b930Samuel Thibault{
15741ab4396e19fba338baf28044d3e48385744b930Samuel Thibault	return atomic_notifier_chain_unregister(&keyboard_notifier_list, nb);
15841ab4396e19fba338baf28044d3e48385744b930Samuel Thibault}
15941ab4396e19fba338baf28044d3e48385744b930Samuel ThibaultEXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
16041ab4396e19fba338baf28044d3e48385744b930Samuel Thibault
16141ab4396e19fba338baf28044d3e48385744b930Samuel Thibault/*
162c8e4c77277ca5db0c4ddbfb4bc628b8abad585b0Marvin Raaijmakers * Translation of scancodes to keycodes. We set them on only the first
163c8e4c77277ca5db0c4ddbfb4bc628b8abad585b0Marvin Raaijmakers * keyboard in the list that accepts the scancode and keycode.
164c8e4c77277ca5db0c4ddbfb4bc628b8abad585b0Marvin Raaijmakers * Explanation for not choosing the first attached keyboard anymore:
165c8e4c77277ca5db0c4ddbfb4bc628b8abad585b0Marvin Raaijmakers *  USB keyboards for example have two event devices: one for all "normal"
166c8e4c77277ca5db0c4ddbfb4bc628b8abad585b0Marvin Raaijmakers *  keys and one for extra function keys (like "volume up", "make coffee",
167c8e4c77277ca5db0c4ddbfb4bc628b8abad585b0Marvin Raaijmakers *  etc.). So this means that scancodes for the extra function keys won't
168c8e4c77277ca5db0c4ddbfb4bc628b8abad585b0Marvin Raaijmakers *  be valid for the first event device, but will be for the second.
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
17066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
17166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhovstruct getset_keycode_data {
1728613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab	struct input_keymap_entry ke;
17366d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	int error;
17466d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov};
17566d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
17666d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhovstatic int getkeycode_helper(struct input_handle *handle, void *data)
17766d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov{
17866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	struct getset_keycode_data *d = data;
17966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
1808613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab	d->error = input_get_keycode(handle->dev, &d->ke);
18166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
18266d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	return d->error == 0; /* stop as soon as we successfully get one */
18366d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov}
18466d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
185079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxstatic int getkeycode(unsigned int scancode)
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1878613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab	struct getset_keycode_data d = {
1888613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab		.ke	= {
1898613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab			.flags		= 0,
1908613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab			.len		= sizeof(scancode),
1918613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab			.keycode	= 0,
1928613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab		},
1938613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab		.error	= -ENODEV,
1948613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab	};
1958613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab
1968613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab	memcpy(d.ke.scancode, &scancode, sizeof(scancode));
197c8e4c77277ca5db0c4ddbfb4bc628b8abad585b0Marvin Raaijmakers
19866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper);
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2008613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab	return d.error ?: d.ke.keycode;
20166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov}
20266d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
20366d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhovstatic int setkeycode_helper(struct input_handle *handle, void *data)
20466d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov{
20566d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	struct getset_keycode_data *d = data;
20666d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
2078613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab	d->error = input_set_keycode(handle->dev, &d->ke);
20866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
20966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	return d->error == 0; /* stop as soon as we successfully set one */
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
212079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxstatic int setkeycode(unsigned int scancode, unsigned int keycode)
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2148613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab	struct getset_keycode_data d = {
2158613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab		.ke	= {
2168613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab			.flags		= 0,
2178613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab			.len		= sizeof(scancode),
2188613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab			.keycode	= keycode,
2198613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab		},
2208613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab		.error	= -ENODEV,
2218613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab	};
2228613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab
2238613e4c2872a87cc309a42de2c7091744dc54d0eMauro Carvalho Chehab	memcpy(d.ke.scancode, &scancode, sizeof(scancode));
224c8e4c77277ca5db0c4ddbfb4bc628b8abad585b0Marvin Raaijmakers
22566d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper);
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22766d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	return d.error;
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
23118f7ad59b0ef341fb9390cb79b2a39707c48257dDmitry Torokhov * Making beeps and bells. Note that we prefer beeps to bells, but when
23218f7ad59b0ef341fb9390cb79b2a39707c48257dDmitry Torokhov * shutting the sound off we do both.
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
23466d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
23566d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhovstatic int kd_sound_helper(struct input_handle *handle, void *data)
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
23766d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	unsigned int *hz = data;
23866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	struct input_dev *dev = handle->dev;
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	if (test_bit(EV_SND, dev->evbit)) {
24118f7ad59b0ef341fb9390cb79b2a39707c48257dDmitry Torokhov		if (test_bit(SND_TONE, dev->sndbit)) {
24266d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov			input_inject_event(handle, EV_SND, SND_TONE, *hz);
24318f7ad59b0ef341fb9390cb79b2a39707c48257dDmitry Torokhov			if (*hz)
24418f7ad59b0ef341fb9390cb79b2a39707c48257dDmitry Torokhov				return 0;
24518f7ad59b0ef341fb9390cb79b2a39707c48257dDmitry Torokhov		}
24618f7ad59b0ef341fb9390cb79b2a39707c48257dDmitry Torokhov		if (test_bit(SND_BELL, dev->sndbit))
24766d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov			input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
24966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
25066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	return 0;
25166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov}
25266d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
25366d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhovstatic void kd_nosound(unsigned long ignored)
25466d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov{
25566d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	static unsigned int zero;
25666d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
25766d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	input_handler_for_each_handle(&kbd_handler, &zero, kd_sound_helper);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2608d06afab73a75f40ae2864e6c296356bab1ab473Ingo Molnarstatic DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid kd_mksound(unsigned int hz, unsigned int ticks)
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26466d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	del_timer_sync(&kd_mksound_timer);
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26666d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	input_handler_for_each_handle(&kbd_handler, &hz, kd_sound_helper);
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	if (hz && ticks)
26966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		mod_timer(&kd_mksound_timer, jiffies + ticks);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
271f7511d5f66f01fc451747b24e79f3ada7a3af9afSamuel ThibaultEXPORT_SYMBOL(kd_mksound);
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Setting the keyboard rate.
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27766d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhovstatic int kbd_rate_helper(struct input_handle *handle, void *data)
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	struct input_dev *dev = handle->dev;
28066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	struct kbd_repeat *rep = data;
28166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
28266d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	if (test_bit(EV_REP, dev->evbit)) {
28366d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
28466d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		if (rep[0].delay > 0)
28566d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov			input_inject_event(handle,
28666d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov					   EV_REP, REP_DELAY, rep[0].delay);
28766d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		if (rep[0].period > 0)
28866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov			input_inject_event(handle,
28966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov					   EV_REP, REP_PERIOD, rep[0].period);
29066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
29166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		rep[1].delay = dev->rep[REP_DELAY];
29266d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		rep[1].period = dev->rep[REP_PERIOD];
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29466d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
29566d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	return 0;
29666d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov}
29766d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
29866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhovint kbd_rate(struct kbd_repeat *rep)
29966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov{
30066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	struct kbd_repeat data[2] = { *rep };
30166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
30266d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	input_handler_for_each_handle(&kbd_handler, data, kbd_rate_helper);
30366d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	*rep = data[1];	/* Copy currently used settings */
30466d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Helper Functions.
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void put_queue(struct vc_data *vc, int ch)
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3138ce73264b75be4d5ed480440ac32dfc1f25ff678Alan Cox	struct tty_struct *tty = vc->port.tty;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty) {
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty_insert_flip_char(tty, ch, 0);
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_schedule_flip(tty);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void puts_queue(struct vc_data *vc, char *cp)
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3238ce73264b75be4d5ed480440ac32dfc1f25ff678Alan Cox	struct tty_struct *tty = vc->port.tty;
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!tty)
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (*cp) {
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty_insert_flip_char(tty, *cp, 0);
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cp++;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_schedule_flip(tty);
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void applkey(struct vc_data *vc, int key, char mode)
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	buf[1] = (mode ? 'O' : '[');
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	buf[2] = key;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	puts_queue(vc, buf);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Many other routines do put_queue, but I think either
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * they produce ASCII, or they produce some user-assigned
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * string, and in both cases we might assume that it is
348759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardt * in utf-8 already.
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
350759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardtstatic void to_utf8(struct vc_data *vc, uint c)
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (c < 0x80)
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*  0******* */
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, c);
355fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	else if (c < 0x800) {
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* 110***** 10****** */
357fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov		put_queue(vc, 0xc0 | (c >> 6));
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, 0x80 | (c & 0x3f));
359e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	} else if (c < 0x10000) {
360e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (c >= 0xD800 && c < 0xE000)
361759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardt			return;
362759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardt		if (c == 0xFFFF)
363759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardt			return;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* 1110**** 10****** 10****** */
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, 0xe0 | (c >> 12));
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, 0x80 | (c & 0x3f));
368e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	} else if (c < 0x110000) {
369759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardt		/* 11110*** 10****** 10****** 10****** */
370759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardt		put_queue(vc, 0xf0 | (c >> 18));
371759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardt		put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
372759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardt		put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
373759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardt		put_queue(vc, 0x80 | (c & 0x3f));
374fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	}
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
377fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov/*
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called after returning from RAW mode or when changing consoles - recompute
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * shift_down[] and shift_state from key_down[] maybe called when keymap is
380079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox * undefined, so that shiftkey release is seen. The caller must hold the
381079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox * kbd_event_lock.
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
383079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
384079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxstatic void do_compute_shiftstate(void)
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int i, j, k, sym, val;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	shift_state = 0;
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(shift_down, 0, sizeof(shift_down));
390fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < ARRAY_SIZE(key_down); i++) {
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!key_down[i])
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		k = i * BITS_PER_LONG;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (j = 0; j < BITS_PER_LONG; j++, k++) {
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!test_bit(k, key_down))
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sym = U(key_maps[0][k]);
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			val = KVAL(sym);
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (val == KVAL(K_CAPSSHIFT))
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				val = KVAL(K_SHIFT);
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			shift_down[val]++;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			shift_state |= (1 << val);
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
417079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/* We still have to export this method to vt.c */
418079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid compute_shiftstate(void)
419079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
420079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
421079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
422079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	do_compute_shiftstate();
423079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
424079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
425079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We have a combining character DIACR here, followed by the character CH.
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the combination occurs in the table, return the corresponding value.
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Otherwise, if CH is a space or equals DIACR, return DIACR.
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Otherwise, conclude that DIACR was not combining after all,
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * queue it and return CH.
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
433b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibaultstatic unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
435b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	unsigned int d = diacr;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int i;
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	diacr = 0;
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
440b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	if ((d & ~0xff) == BRL_UC_ROW) {
441b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault		if ((ch & ~0xff) == BRL_UC_ROW)
442b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault			return d | ch;
443b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	} else {
444b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault		for (i = 0; i < accent_table_size; i++)
445b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault			if (accent_table[i].diacr == d && accent_table[i].base == ch)
446b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault				return accent_table[i].result;
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
449b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return d;
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
452b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	if (kbd->kbdmode == VC_UNICODE)
45304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault		to_utf8(vc, d);
45404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault	else {
45504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault		int c = conv_uni_to_8bit(d);
45604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault		if (c != -1)
45704c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault			put_queue(vc, c);
45804c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault	}
459b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ch;
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Special function handlers
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4667d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_enter(struct vc_data *vc)
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (diacr) {
469b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault		if (kbd->kbdmode == VC_UNICODE)
47004c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault			to_utf8(vc, diacr);
47104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault		else {
47204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault			int c = conv_uni_to_8bit(diacr);
47304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault			if (c != -1)
47404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault				put_queue(vc, c);
47504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault		}
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		diacr = 0;
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
478e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_queue(vc, 13);
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vc_kbd_mode(kbd, VC_CRLF))
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, 10);
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4847d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_caps_toggle(struct vc_data *vc)
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rep)
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
488e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	chg_vc_kbd_led(kbd, VC_CAPSLOCK);
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4927d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_caps_on(struct vc_data *vc)
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rep)
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
496e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_vc_kbd_led(kbd, VC_CAPSLOCK);
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5007d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_show_ptregs(struct vc_data *vc)
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5027d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells	struct pt_regs *regs = get_irq_regs();
503e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regs)
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		show_regs(regs);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5087d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_hold(struct vc_data *vc)
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5108ce73264b75be4d5ed480440ac32dfc1f25ff678Alan Cox	struct tty_struct *tty = vc->port.tty;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rep || !tty)
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * these routines are also activated by ^S/^Q.
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty->stopped)
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start_tty(tty);
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		stop_tty(tty);
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5267d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_num(struct vc_data *vc)
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
528e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if (vc_kbd_mode(kbd, VC_APPLIC))
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		applkey(vc, 'P', 1);
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5317d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells		fn_bare_num(vc);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bind this to Shift-NumLock if you work in application keypad mode
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but want to be able to change the NumLock flag.
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bind this to NumLock if you prefer that the NumLock key always
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * changes the NumLock flag.
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5407d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_bare_num(struct vc_data *vc)
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!rep)
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		chg_vc_kbd_led(kbd, VC_NUMLOCK);
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5467d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_lastcons(struct vc_data *vc)
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* switch to the last used console, ChN */
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_console(last_console);
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5527d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_dec_console(struct vc_data *vc)
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, cur = fg_console;
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Currently switching?  Queue this next switch relative to that. */
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (want_console != -1)
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cur = want_console;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
560fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	for (i = cur - 1; i != cur; i--) {
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == -1)
562fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov			i = MAX_NR_CONSOLES - 1;
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vc_cons_allocated(i))
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_console(i);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5697d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_inc_console(struct vc_data *vc)
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, cur = fg_console;
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Currently switching?  Queue this next switch relative to that. */
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (want_console != -1)
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cur = want_console;
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = cur+1; i != cur; i++) {
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == MAX_NR_CONSOLES)
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i = 0;
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vc_cons_allocated(i))
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_console(i);
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5867d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_send_intr(struct vc_data *vc)
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5888ce73264b75be4d5ed480440ac32dfc1f25ff678Alan Cox	struct tty_struct *tty = vc->port.tty;
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!tty)
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tty_insert_flip_char(tty, 0, TTY_BREAK);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_schedule_flip(tty);
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5967d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_scroll_forw(struct vc_data *vc)
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scrollfront(vc, 0);
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6017d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_scroll_back(struct vc_data *vc)
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scrollback(vc, 0);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6067d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_show_mem(struct vc_data *vc)
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
608b2b755b5f10eb32fbdc73a9907c07006b17f714bDavid Rientjes	show_mem(0);
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6117d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_show_state(struct vc_data *vc)
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_state();
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6167d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_boot_it(struct vc_data *vc)
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctrl_alt_del();
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6217d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_compose(struct vc_data *vc)
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
623e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	dead_key_next = true;
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6267d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_spawn_con(struct vc_data *vc)
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
62881af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman	spin_lock(&vt_spawn_con.lock);
62981af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman	if (vt_spawn_con.pid)
63081af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman		if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
63181af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman			put_pid(vt_spawn_con.pid);
63281af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman			vt_spawn_con.pid = NULL;
63381af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman		}
63481af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman	spin_unlock(&vt_spawn_con.lock);
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6377d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_SAK(struct vc_data *vc)
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6398b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
6408b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman	schedule_work(SAK_work);
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6437d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void fn_null(struct vc_data *vc)
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
645079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	do_compute_shiftstate();
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Special key handlers
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6517d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_ignore(struct vc_data *vc, unsigned char value, char up_flag)
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6557d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag)
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (value >= ARRAY_SIZE(fn_handler))
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
661fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	if ((kbd->kbdmode == VC_RAW ||
6629fc3de9c83565fcaa23df74c2fc414bb6e7efb0aArthur Taylor	     kbd->kbdmode == VC_MEDIUMRAW ||
6639fc3de9c83565fcaa23df74c2fc414bb6e7efb0aArthur Taylor	     kbd->kbdmode == VC_OFF) &&
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     value != KVAL(K_SAK))
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;		/* SAK is allowed even in raw mode */
6667d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells	fn_handler[value](vc);
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6697d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6719272e9a2f8872a0f9fb15aaa10f2a993524343e0Dmitry Torokhov	pr_err("k_lowercase was called - impossible\n");
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6747d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag)
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;		/* no action, if this is a key release */
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (diacr)
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = handle_diacr(vc, value);
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dead_key_next) {
683e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		dead_key_next = false;
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		diacr = value;
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
687b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	if (kbd->kbdmode == VC_UNICODE)
68804c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault		to_utf8(vc, value);
68904c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault	else {
69004c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault		int c = conv_uni_to_8bit(value);
69104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault		if (c != -1)
69204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault			put_queue(vc, c);
69304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault	}
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handle dead key. Note that we now may have several
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dead keys modifying the same character. Very useful
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for Vietnamese.
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7017d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag)
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
705e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	diacr = (diacr ? handle_diacr(vc, value) : value);
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7097d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_self(struct vc_data *vc, unsigned char value, char up_flag)
710b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault{
711d2187ebd84c7dd13ef269e9600f4daebeb02816eJiri Bohac	k_unicode(vc, conv_8bit_to_uni(value), up_flag);
712b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault}
713b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault
7147d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
715b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault{
7167d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells	k_deadunicode(vc, value, up_flag);
717b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault}
718b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Obsolete - for backwards compatibility only
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7227d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7240f5e560e4523e15f33922de5becd024ccaaff76cAndreas Mohr	static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
725e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
726e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	k_deadunicode(vc, ret_diacr[value], up_flag);
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7297d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag)
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
733e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_console(value);
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7377d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag)
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
741e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
742e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if ((unsigned)value < ARRAY_SIZE(func_table)) {
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (func_table[value])
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			puts_queue(vc, func_table[value]);
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
7469272e9a2f8872a0f9fb15aaa10f2a993524343e0Dmitry Torokhov		pr_err("k_fn called with value=%d\n", value);
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7497d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
751e52b29c2a637f6854d71a45646d7283d984a6dadBrandon Philips	static const char cur_chars[] = "BDCA";
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag)
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
755e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7597d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7610f5e560e4523e15f33922de5becd024ccaaff76cAndreas Mohr	static const char pad_chars[] = "0123456789+-*/\015,.?()#";
7620f5e560e4523e15f33922de5becd024ccaaff76cAndreas Mohr	static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag)
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;		/* no action, if this is a key release */
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* kludge... shift forces cursor/number keys */
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vc_kbd_mode(kbd, VC_APPLIC) && !shift_down[KG_SHIFT]) {
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		applkey(vc, app_map[value], 1);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
773e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if (!vc_kbd_led(kbd, VC_NUMLOCK)) {
774e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (value) {
776e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_PCOMMA):
777e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_PDOT):
778e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_fn(vc, KVAL(K_REMOVE), 0);
779e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return;
780e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_P0):
781e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_fn(vc, KVAL(K_INSERT), 0);
782e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return;
783e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_P1):
784e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_fn(vc, KVAL(K_SELECT), 0);
785e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return;
786e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_P2):
787e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_cur(vc, KVAL(K_DOWN), 0);
788e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return;
789e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_P3):
790e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_fn(vc, KVAL(K_PGDN), 0);
791e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return;
792e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_P4):
793e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_cur(vc, KVAL(K_LEFT), 0);
794e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return;
795e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_P6):
796e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_cur(vc, KVAL(K_RIGHT), 0);
797e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return;
798e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_P7):
799e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_fn(vc, KVAL(K_FIND), 0);
800e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return;
801e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_P8):
802e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_cur(vc, KVAL(K_UP), 0);
803e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return;
804e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_P9):
805e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_fn(vc, KVAL(K_PGUP), 0);
806e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return;
807e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		case KVAL(K_P5):
808e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
809e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
811e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	}
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_queue(vc, pad_chars[value]);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, 10);
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8187d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int old_state = shift_state;
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rep)
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Mimic typewriter:
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * a CapsShift key acts like Shift but undoes CapsLock
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (value == KVAL(K_CAPSSHIFT)) {
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = KVAL(K_SHIFT);
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!up_flag)
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			clr_vc_kbd_led(kbd, VC_CAPSLOCK);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag) {
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * handle the case that two shift or control
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * keys are depressed simultaneously
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (shift_down[value])
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			shift_down[value]--;
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		shift_down[value]++;
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (shift_down[value])
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		shift_state |= (1 << value);
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		shift_state &= ~(1 << value);
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* kludge */
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag && shift_state != old_state && npadch != -1) {
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (kbd->kbdmode == VC_UNICODE)
852759448f459234bfcf34b82471f0dba77a9aca498Jan Engelhardt			to_utf8(vc, npadch);
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_queue(vc, npadch & 0xff);
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		npadch = -1;
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8597d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag)
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vc_kbd_mode(kbd, VC_META)) {
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, '\033');
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, value);
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, value | 0x80);
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8717d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int base;
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag)
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (value < 10) {
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* decimal input of code, while Alt depressed */
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		base = 10;
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* hexadecimal input of code, while AltGr depressed */
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value -= 10;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		base = 16;
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (npadch == -1)
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		npadch = value;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		npadch = npadch * base + value;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8937d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag || rep)
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
897e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	chg_vc_kbd_lock(kbd, value);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9017d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9037d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells	k_shift(vc, value, up_flag);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up_flag || rep)
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
906e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	chg_vc_kbd_slock(kbd, value);
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* try to make Alt, oops, AltGr and such work */
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kbd->slockstate = 0;
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		chg_vc_kbd_slock(kbd, value);
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
915b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault/* by default, 300ms interval for combination release */
91677426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibaultstatic unsigned brl_timeout = 300;
91777426d7210430b70a7f5b21c05c4e7505528937dSamuel ThibaultMODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
91877426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibaultmodule_param(brl_timeout, uint, 0644);
91977426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault
92077426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibaultstatic unsigned brl_nbchords = 1;
92177426d7210430b70a7f5b21c05c4e7505528937dSamuel ThibaultMODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
92277426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibaultmodule_param(brl_nbchords, uint, 0644);
92377426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault
9247d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag)
92577426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault{
92677426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault	static unsigned long chords;
92777426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault	static unsigned committed;
92877426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault
92977426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault	if (!brl_nbchords)
9307d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells		k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag);
93177426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault	else {
93277426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault		committed |= pattern;
93377426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault		chords++;
93477426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault		if (chords == brl_nbchords) {
9357d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells			k_unicode(vc, BRL_UC_ROW | committed, up_flag);
93677426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault			chords = 0;
93777426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault			committed = 0;
93877426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault		}
93977426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault	}
94077426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault}
94177426d7210430b70a7f5b21c05c4e7505528937dSamuel Thibault
9427d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
943b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault{
944e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	static unsigned pressed, committing;
945b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	static unsigned long releasestart;
946b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault
947b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	if (kbd->kbdmode != VC_UNICODE) {
948b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault		if (!up_flag)
9499272e9a2f8872a0f9fb15aaa10f2a993524343e0Dmitry Torokhov			pr_warning("keyboard mode must be unicode for braille patterns\n");
950b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault		return;
951b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	}
952b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault
953b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	if (!value) {
9547d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells		k_unicode(vc, BRL_UC_ROW, up_flag);
955b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault		return;
956b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	}
957b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault
958b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	if (value > 8)
959b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault		return;
960b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault
961e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if (!up_flag) {
962b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault		pressed |= 1 << (value - 1);
963b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault		if (!brl_timeout)
964b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault			committing = pressed;
965e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	} else if (brl_timeout) {
966e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (!committing ||
967e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		    time_after(jiffies,
968e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			       releasestart + msecs_to_jiffies(brl_timeout))) {
969e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			committing = pressed;
970e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			releasestart = jiffies;
971e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		}
972e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		pressed &= ~(1 << (value - 1));
973e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (!pressed && committing) {
974e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_brlcommit(vc, committing, 0);
975e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			committing = 0;
976e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		}
977e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	} else {
978e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (committing) {
979e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			k_brlcommit(vc, committing, 0);
980e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			committing = 0;
981e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		}
982e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		pressed &= ~(1 << (value - 1));
983b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault	}
984b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault}
985b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or (ii) whatever pattern of lights people want to show using KDSETLED,
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or (iii) specified bits of specified words in kernel memory.
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned char getledstate(void)
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ledstate;
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid setledstate(struct kbd_struct *kbd, unsigned int led)
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
998079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        unsigned long flags;
999079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        spin_lock_irqsave(&kbd_event_lock, flags);
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(led & ~7)) {
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ledioctl = led;
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kbd->ledmode = LED_SHOW_IOCTL;
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kbd->ledmode = LED_SHOW_FLAGS;
1005e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_leds();
1007079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline unsigned char getleds(void)
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct kbd_struct *kbd = kbd_table + fg_console;
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char leds;
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (kbd->ledmode == LED_SHOW_IOCTL)
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ledioctl;
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	leds = kbd->ledflagstate;
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (kbd->ledmode == LED_SHOW_MEM) {
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < 3; i++)
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ledptrs[i].valid) {
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (*ledptrs[i].addr & ledptrs[i].mask)
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					leds |= (1 << i);
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					leds &= ~(1 << i);
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return leds;
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
103366d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhovstatic int kbd_update_leds_helper(struct input_handle *handle, void *data)
103466d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov{
103566d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	unsigned char leds = *(unsigned char *)data;
103666d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
103766d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	if (test_bit(EV_LED, handle->dev->evbit)) {
103866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
103966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		input_inject_event(handle, EV_LED, LED_NUML,    !!(leds & 0x02));
104066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		input_inject_event(handle, EV_LED, LED_CAPSL,   !!(leds & 0x04));
104166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
104266d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	}
104366d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
104466d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	return 0;
104566d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov}
104666d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
1047079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
1048079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_get_leds	-	helper for braille console
1049079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to read
1050079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@flag: flag we want to check
1051079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
1052079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Check the status of a keyboard led flag and report it back
1053079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
1054079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_get_leds(int console, int flag)
1055079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1056079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
1057079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
1058079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int ret;
1059079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1060079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
1061079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	ret = vc_kbd_led(kbd, flag);
1062079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
1063079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1064079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return ret;
1065079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1066079c9534a96da9a85a2a2f9715851050fbfbf749Alan CoxEXPORT_SYMBOL_GPL(vt_get_leds);
1067079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1068079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
1069079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_set_led_state	-	set LED state of a console
1070079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to set
1071079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@leds: LED bits
1072079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
1073079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Set the LEDs on a console. This is a wrapper for the VT layer
1074079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	so that we can keep kbd knowledge internal
1075079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
1076079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_set_led_state(int console, int leds)
1077079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1078079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
1079079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	setledstate(kbd, leds);
1080079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1081079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1082079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
1083079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_kbd_con_start	-	Keyboard side of console start
1084079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console
1085079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
1086079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Handle console start. This is a wrapper for the VT layer
1087079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	so that we can keep kbd knowledge internal
1088079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
1089079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_kbd_con_start(int console)
1090079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1091079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
1092079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
1093079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
1094079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	clr_vc_kbd_led(kbd, VC_SCROLLOCK);
1095079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	set_leds();
1096079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
1097079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1098079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1099079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
1100079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_kbd_con_stop		-	Keyboard side of console stop
1101079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console
1102079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
1103079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Handle console stop. This is a wrapper for the VT layer
1104079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	so that we can keep kbd knowledge internal
1105079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
1106079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_kbd_con_stop(int console)
1107079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1108079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
1109079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
1110079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
1111079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	set_vc_kbd_led(kbd, VC_SCROLLOCK);
1112079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	set_leds();
1113079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
1114079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1115079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
111766d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov * This is the tasklet that updates LED state on all keyboards
111866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov * attached to the box. The reason we use tasklet is that we
111966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov * need to handle the scenario when keyboard handler is not
112066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov * registered yet but we already getting updates form VT to
112166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov * update led state.
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void kbd_bh(unsigned long dummy)
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char leds = getleds();
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (leds != ledstate) {
112866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		input_handler_for_each_handle(&kbd_handler, &leds,
112966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov					      kbd_update_leds_helper);
113066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		ledstate = leds;
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
11370b57ee9e55373a27e45549e82b0c43621480a71bAdrian Bunk    defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
11380b57ee9e55373a27e45549e82b0c43621480a71bAdrian Bunk    defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
11393a4e832cccc5baba98ba010e38c58266954228a7Hans-Christian Egtvedt    (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) ||\
11403a4e832cccc5baba98ba010e38c58266954228a7Hans-Christian Egtvedt    defined(CONFIG_AVR32)
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11450f5e560e4523e15f33922de5becd024ccaaff76cAndreas Mohrstatic const unsigned short x86_keycodes[256] =
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
1152896cdc7b802c972d625351eb47d4add22d1fccb6Dmitry Torokhov	284,285,309,  0,312, 91,327,328,329,331,333,335,336,337,338,339,
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
115572a42f242cad8f393bb2556f4cc5175c6cea9892Hans de Goede	103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
115672a42f242cad8f393bb2556f4cc5175c6cea9892Hans de Goede	291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11620b57ee9e55373a27e45549e82b0c43621480a71bAdrian Bunk#ifdef CONFIG_SPARC
1163e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhovstatic int sparc_l1_a_state;
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void sun_do_break(void);
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1167fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhovstatic int emulate_raw(struct vc_data *vc, unsigned int keycode,
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       unsigned char up_flag)
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1170896cdc7b802c972d625351eb47d4add22d1fccb6Dmitry Torokhov	int code;
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (keycode) {
1173896cdc7b802c972d625351eb47d4add22d1fccb6Dmitry Torokhov
1174e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	case KEY_PAUSE:
1175e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		put_queue(vc, 0xe1);
1176e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		put_queue(vc, 0x1d | up_flag);
1177e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		put_queue(vc, 0x45 | up_flag);
1178e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		break;
1179896cdc7b802c972d625351eb47d4add22d1fccb6Dmitry Torokhov
1180e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	case KEY_HANGEUL:
1181e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (!up_flag)
1182e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0xf2);
1183e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		break;
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1185e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	case KEY_HANJA:
1186e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (!up_flag)
1187e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0xf1);
1188e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		break;
1189896cdc7b802c972d625351eb47d4add22d1fccb6Dmitry Torokhov
1190e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	case KEY_SYSRQ:
1191e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		/*
1192e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		 * Real AT keyboards (that's what we're trying
1193e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		 * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
1194e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		 * pressing PrtSc/SysRq alone, but simply 0x54
1195e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		 * when pressing Alt+PrtSc/SysRq.
1196e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		 */
1197e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (test_bit(KEY_LEFTALT, key_down) ||
1198e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		    test_bit(KEY_RIGHTALT, key_down)) {
1199e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0x54 | up_flag);
1200e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		} else {
1201e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0xe0);
1202e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0x2a | up_flag);
1203e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0xe0);
1204e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0x37 | up_flag);
1205e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		}
1206e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		break;
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1208e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	default:
1209e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (keycode > 255)
1210e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return -1;
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1212e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		code = x86_keycodes[keycode];
1213e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (!code)
1214e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return -1;
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1216e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (code & 0x100)
1217e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0xe0);
1218e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		put_queue(vc, (code & 0x7f) | up_flag);
1219e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
1220e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		break;
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HW_RAW(dev)	0
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (keycode > 127)
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_queue(vc, keycode | up_flag);
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void kbd_rawcode(unsigned char data)
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct vc_data *vc = vc_cons[fg_console].d;
1243e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
12440c09b2ac35ff7c5f280e5cf8142ad0822f1c93b3Alan Jenkins	kbd = kbd_table + vc->vc_num;
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (kbd->kbdmode == VC_RAW)
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, data);
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12497d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void kbd_keycode(unsigned int keycode, int down, int hw_raw)
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct vc_data *vc = vc_cons[fg_console].d;
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short keysym, *key_map;
1253e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	unsigned char type;
1254e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	bool raw_mode;
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tty_struct *tty;
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int shift_final;
125741ab4396e19fba338baf28044d3e48385744b930Samuel Thibault	struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
1258e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	int rc;
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12608ce73264b75be4d5ed480440ac32dfc1f25ff678Alan Cox	tty = vc->port.tty;
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty && (!tty->driver_data)) {
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* No driver data? Strange. Okay we fix it then. */
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty->driver_data = vc;
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12670c09b2ac35ff7c5f280e5cf8142ad0822f1c93b3Alan Jenkins	kbd = kbd_table + vc->vc_num;
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12690b57ee9e55373a27e45549e82b0c43621480a71bAdrian Bunk#ifdef CONFIG_SPARC
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (keycode == KEY_STOP)
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sparc_l1_a_state = down;
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rep = (down == 2);
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1276e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	raw_mode = (kbd->kbdmode == VC_RAW);
1277e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if (raw_mode && !hw_raw)
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (emulate_raw(vc, keycode, !down << 7))
12799e35d20663344b38339ffb6127ba08285f3397a9Dmitry Torokhov			if (keycode < BTN_MISC && printk_ratelimit())
12809272e9a2f8872a0f9fb15aaa10f2a993524343e0Dmitry Torokhov				pr_warning("can't emulate rawmode for keycode %d\n",
12819272e9a2f8872a0f9fb15aaa10f2a993524343e0Dmitry Torokhov					   keycode);
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12830b57ee9e55373a27e45549e82b0c43621480a71bAdrian Bunk#ifdef CONFIG_SPARC
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (keycode == KEY_A && sparc_l1_a_state) {
1285e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		sparc_l1_a_state = false;
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sun_do_break();
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (kbd->kbdmode == VC_MEDIUMRAW) {
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * This is extended medium raw mode, with keys above 127
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * encoded as 0, high 7 bits, low 7 bits, with the 0 bearing
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the 'up' flag if needed. 0 is reserved, so this shouldn't
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * interfere with anything else. The two bytes after 0 will
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * always have the up flag set not to interfere with older
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * applications. This allows for 16384 different keycodes,
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * which should be enough.
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (keycode < 128) {
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_queue(vc, keycode | (!down << 7));
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_queue(vc, !down << 7);
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_queue(vc, (keycode >> 7) | 0x80);
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_queue(vc, keycode | 0x80);
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1307e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		raw_mode = true;
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (down)
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_bit(keycode, key_down);
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clear_bit(keycode, key_down);
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1315fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	if (rep &&
1316fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	    (!vc_kbd_mode(kbd, VC_REPEAT) ||
1317f34d7a5b7010b82fe97da95496b9971435530062Alan Cox	     (tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) {
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Don't repeat a key if the input buffers are not empty and the
1320fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov		 * characters get aren't echoed locally. This makes key repeat
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * usable with slow applications and under heavy loads.
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
132641ab4396e19fba338baf28044d3e48385744b930Samuel Thibault	param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
13270beb4f6f294b0f2dde07fa9da9c00abd4f9c8b50Karl Dahlke	param.ledstate = kbd->ledflagstate;
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	key_map = key_maps[shift_final];
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1330e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1331e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov					KBD_KEYCODE, &param);
1332e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if (rc == NOTIFY_STOP || !key_map) {
1333e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		atomic_notifier_call_chain(&keyboard_notifier_list,
1334e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov					   KBD_UNBOUND_KEYCODE, &param);
1335079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		do_compute_shiftstate();
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kbd->slockstate = 0;
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1340e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if (keycode < NR_KEYS)
1341b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault		keysym = key_map[keycode];
1342e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	else if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
1343e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1));
1344e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	else
1345e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		return;
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	type = KTYP(keysym);
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type < 0xf0) {
135041ab4396e19fba338baf28044d3e48385744b930Samuel Thibault		param.value = keysym;
1351e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1352e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov						KBD_UNICODE, &param);
1353e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (rc != NOTIFY_STOP)
1354e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			if (down && !raw_mode)
1355e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov				to_utf8(vc, keysym);
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	type -= 0xf0;
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type == KT_LETTER) {
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		type = KT_LATIN;
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			key_map = key_maps[shift_final ^ (1 << KG_SHIFT)];
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (key_map)
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				keysym = key_map[keycode];
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
136941ab4396e19fba338baf28044d3e48385744b930Samuel Thibault
1370e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	param.value = keysym;
1371e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1372e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov					KBD_KEYSYM, &param);
1373e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if (rc == NOTIFY_STOP)
137441ab4396e19fba338baf28044d3e48385744b930Samuel Thibault		return;
137541ab4396e19fba338baf28044d3e48385744b930Samuel Thibault
13769fc3de9c83565fcaa23df74c2fc414bb6e7efb0aArthur Taylor	if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type != KT_SHIFT)
137741ab4396e19fba338baf28044d3e48385744b930Samuel Thibault		return;
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13797d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells	(*k_handler[type])(vc, keysym & 0xff, !down);
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13810beb4f6f294b0f2dde07fa9da9c00abd4f9c8b50Karl Dahlke	param.ledstate = kbd->ledflagstate;
138241ab4396e19fba338baf28044d3e48385744b930Samuel Thibault	atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
138341ab4396e19fba338baf28044d3e48385744b930Samuel Thibault
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type != KT_SLOCK)
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kbd->slockstate = 0;
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1388fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhovstatic void kbd_event(struct input_handle *handle, unsigned int event_type,
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      unsigned int event_code, int value)
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
139121cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov	/* We are called with interrupts disabled, just take the lock */
139221cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov	spin_lock(&kbd_event_lock);
139321cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kbd_rawcode(value);
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (event_type == EV_KEY)
13977d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells		kbd_keycode(event_code, value, HW_RAW(handle->dev));
139821cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov
139921cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov	spin_unlock(&kbd_event_lock);
140021cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tasklet_schedule(&keyboard_tasklet);
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do_poke_blanked_console = 1;
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	schedule_console_callback();
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14060b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhovstatic bool kbd_match(struct input_handler *handler, struct input_dev *dev)
14070b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov{
14080b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov	int i;
14090b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov
14100b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov	if (test_bit(EV_SND, dev->evbit))
14110b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov		return true;
14120b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov
141353c1f764022337d7168b1344d6700b3d98e4acecSamuel Thibault	if (test_bit(EV_KEY, dev->evbit)) {
14140b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov		for (i = KEY_RESERVED; i < BTN_MISC; i++)
14150b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov			if (test_bit(i, dev->keybit))
14160b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov				return true;
141753c1f764022337d7168b1344d6700b3d98e4acecSamuel Thibault		for (i = KEY_BRL_DOT1; i <= KEY_BRL_DOT10; i++)
141853c1f764022337d7168b1344d6700b3d98e4acecSamuel Thibault			if (test_bit(i, dev->keybit))
141953c1f764022337d7168b1344d6700b3d98e4acecSamuel Thibault				return true;
142053c1f764022337d7168b1344d6700b3d98e4acecSamuel Thibault	}
14210b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov
14220b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov	return false;
14230b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov}
14240b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When a keyboard (or other input device) is found, the kbd_connect
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function is called. The function then looks at the device, and if it
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * likes it, it can open it and get events from it. In this (kbd_connect)
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function, we should decide which VT to bind that keyboard to initially.
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14315b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhovstatic int kbd_connect(struct input_handler *handler, struct input_dev *dev,
14325b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov			const struct input_device_id *id)
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct input_handle *handle;
14355b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	int error;
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
143722479e1c0d111c60d29a4759408394cbdc7548a5Dmitry Torokhov	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
143822479e1c0d111c60d29a4759408394cbdc7548a5Dmitry Torokhov	if (!handle)
14395b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov		return -ENOMEM;
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	handle->dev = dev;
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	handle->handler = handler;
1443fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	handle->name = "kbd";
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14455b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	error = input_register_handle(handle);
14465b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	if (error)
14475b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov		goto err_free_handle;
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14495b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	error = input_open_device(handle);
14505b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	if (error)
14515b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov		goto err_unregister_handle;
14525b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov
14535b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	return 0;
14545b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov
14555b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov err_unregister_handle:
14565b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	input_unregister_handle(handle);
14575b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov err_free_handle:
14585b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	kfree(handle);
14595b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	return error;
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void kbd_disconnect(struct input_handle *handle)
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	input_close_device(handle);
14655b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	input_unregister_handle(handle);
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(handle);
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1469c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov/*
1470c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov * Start keyboard handler on the new keyboard by refreshing LED state to
1471c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov * match the rest of the system.
1472c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov */
1473c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhovstatic void kbd_start(struct input_handle *handle)
1474c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov{
1475c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov	tasklet_disable(&keyboard_tasklet);
147666d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
147766d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	if (ledstate != 0xff)
147866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		kbd_update_leds_helper(handle, &ledstate);
147966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
1480c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov	tasklet_enable(&keyboard_tasklet);
1481c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov}
1482c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov
148366e66118837ed95a299328437c2d9fb4b5137352Dmitry Torokhovstatic const struct input_device_id kbd_ids[] = {
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
14856aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
14866aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox		.evbit = { BIT_MASK(EV_KEY) },
14876aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox	},
1488fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
14906aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
14916aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox		.evbit = { BIT_MASK(EV_SND) },
14926aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox	},
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ },    /* Terminating entry */
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(input, kbd_ids);
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct input_handler kbd_handler = {
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.event		= kbd_event,
15010b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov	.match		= kbd_match,
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.connect	= kbd_connect,
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.disconnect	= kbd_disconnect,
1504c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov	.start		= kbd_start,
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "kbd",
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= kbd_ids,
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init kbd_init(void)
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
15124263cf0fac28122c8381b6f4f9441a43cd93c81fDmitry Torokhov	int error;
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15146aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox	for (i = 0; i < MAX_NR_CONSOLES; i++) {
15152b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].ledflagstate = KBD_DEFLEDS;
15162b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
15172b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].ledmode = LED_SHOW_FLAGS;
15182b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].lockstate = KBD_DEFLOCK;
15192b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].slockstate = 0;
15202b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].modeflags = KBD_DEFMODE;
15212e8ecb9db0bcc19e1cc8bb51e9252fe6a86a9863Bill Nottingham		kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
15222b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov	}
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15244263cf0fac28122c8381b6f4f9441a43cd93c81fDmitry Torokhov	error = input_register_handler(&kbd_handler);
15254263cf0fac28122c8381b6f4f9441a43cd93c81fDmitry Torokhov	if (error)
15264263cf0fac28122c8381b6f4f9441a43cd93c81fDmitry Torokhov		return error;
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tasklet_enable(&keyboard_tasklet);
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tasklet_schedule(&keyboard_tasklet);
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1533247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1534247ff8e610cb63c015de19191db9666754c2ed79Alan Cox/* Ioctl support code */
1535247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1536247ff8e610cb63c015de19191db9666754c2ed79Alan Cox/**
1537247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	vt_do_diacrit		-	diacritical table updates
1538247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	@cmd: ioctl request
1539247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	@up: pointer to user data for ioctl
1540247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	@perm: permissions check computed by caller
1541247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *
1542247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	Update the diacritical tables atomically and safely. Lock them
1543247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	against simultaneous keypresses
1544247ff8e610cb63c015de19191db9666754c2ed79Alan Cox */
1545247ff8e610cb63c015de19191db9666754c2ed79Alan Coxint vt_do_diacrit(unsigned int cmd, void __user *up, int perm)
1546247ff8e610cb63c015de19191db9666754c2ed79Alan Cox{
1547247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	struct kbdiacrs __user *a = up;
1548247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	unsigned long flags;
1549247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	int asize;
1550247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	int ret = 0;
1551247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1552247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	switch (cmd) {
1553247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	case KDGKBDIACR:
1554247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	{
1555247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		struct kbdiacr *diacr;
1556247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		int i;
1557247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1558247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		diacr = kmalloc(MAX_DIACR * sizeof(struct kbdiacr),
1559247ff8e610cb63c015de19191db9666754c2ed79Alan Cox								GFP_KERNEL);
1560247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (diacr == NULL)
1561247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -ENOMEM;
1562247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1563247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		/* Lock the diacriticals table, make a copy and then
1564247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		   copy it after we unlock */
1565247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1566247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1567247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		asize = accent_table_size;
1568247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		for (i = 0; i < asize; i++) {
1569247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			diacr[i].diacr = conv_uni_to_8bit(
1570247ff8e610cb63c015de19191db9666754c2ed79Alan Cox						accent_table[i].diacr);
1571247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			diacr[i].base = conv_uni_to_8bit(
1572247ff8e610cb63c015de19191db9666754c2ed79Alan Cox						accent_table[i].base);
1573247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			diacr[i].result = conv_uni_to_8bit(
1574247ff8e610cb63c015de19191db9666754c2ed79Alan Cox						accent_table[i].result);
1575247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		}
1576247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1577247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1578247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (put_user(asize, &a->kb_cnt))
1579247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			ret = -EFAULT;
1580247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		else  if (copy_to_user(a->kbdiacr, diacr,
1581247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				asize * sizeof(struct kbdiacr)))
1582247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			ret = -EFAULT;
1583247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		kfree(diacr);
1584247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		return ret;
1585247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	}
1586247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	case KDGKBDIACRUC:
1587247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	{
1588247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		struct kbdiacrsuc __user *a = up;
1589247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		void *buf;
1590247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1591247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		buf = kmalloc(MAX_DIACR * sizeof(struct kbdiacruc),
1592247ff8e610cb63c015de19191db9666754c2ed79Alan Cox								GFP_KERNEL);
1593247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (buf == NULL)
1594247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -ENOMEM;
1595247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1596247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		/* Lock the diacriticals table, make a copy and then
1597247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		   copy it after we unlock */
1598247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1599247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1600247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		asize = accent_table_size;
1601247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		memcpy(buf, accent_table, asize * sizeof(struct kbdiacruc));
1602247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1603247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1604247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1605247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (put_user(asize, &a->kb_cnt))
1606247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			ret = -EFAULT;
1607247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		else if (copy_to_user(a->kbdiacruc, buf,
1608247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				asize*sizeof(struct kbdiacruc)))
1609247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			ret = -EFAULT;
1610247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		kfree(buf);
1611247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		return ret;
1612247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	}
1613247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1614247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	case KDSKBDIACR:
1615247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	{
1616247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		struct kbdiacrs __user *a = up;
1617247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		struct kbdiacr *diacr = NULL;
1618247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		unsigned int ct;
1619247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		int i;
1620247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1621247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (!perm)
1622247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EPERM;
1623247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (get_user(ct, &a->kb_cnt))
1624247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EFAULT;
1625247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (ct >= MAX_DIACR)
1626247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EINVAL;
1627247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1628247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (ct) {
1629247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			diacr = kmalloc(sizeof(struct kbdiacr) * ct,
1630247ff8e610cb63c015de19191db9666754c2ed79Alan Cox								GFP_KERNEL);
1631247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			if (diacr == NULL)
1632247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				return -ENOMEM;
1633247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1634247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			if (copy_from_user(diacr, a->kbdiacr,
1635247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					sizeof(struct kbdiacr) * ct)) {
1636247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				kfree(diacr);
1637247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				return -EFAULT;
1638247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			}
1639247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		}
1640247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1641247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1642247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		accent_table_size = ct;
1643247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		for (i = 0; i < ct; i++) {
1644247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			accent_table[i].diacr =
1645247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					conv_8bit_to_uni(diacr[i].diacr);
1646247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			accent_table[i].base =
1647247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					conv_8bit_to_uni(diacr[i].base);
1648247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			accent_table[i].result =
1649247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					conv_8bit_to_uni(diacr[i].result);
1650247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		}
1651247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1652247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		kfree(diacr);
1653247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		return 0;
1654247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	}
1655247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1656247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	case KDSKBDIACRUC:
1657247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	{
1658247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		struct kbdiacrsuc __user *a = up;
1659247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		unsigned int ct;
1660247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		void *buf = NULL;
1661247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1662247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (!perm)
1663247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EPERM;
1664247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1665247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (get_user(ct, &a->kb_cnt))
1666247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EFAULT;
1667247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1668247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (ct >= MAX_DIACR)
1669247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EINVAL;
1670247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1671247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (ct) {
1672247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			buf = kmalloc(ct * sizeof(struct kbdiacruc),
1673247ff8e610cb63c015de19191db9666754c2ed79Alan Cox								GFP_KERNEL);
1674247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			if (buf == NULL)
1675247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				return -ENOMEM;
1676247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1677247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			if (copy_from_user(buf, a->kbdiacruc,
1678247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					ct * sizeof(struct kbdiacruc))) {
1679247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				kfree(buf);
1680247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				return -EFAULT;
1681247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			}
1682247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		}
1683247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1684247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (ct)
1685247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			memcpy(accent_table, buf,
1686247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					ct * sizeof(struct kbdiacruc));
1687247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		accent_table_size = ct;
1688247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1689247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		kfree(buf);
1690247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		return 0;
1691247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	}
1692247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	}
1693247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	return ret;
1694247ff8e610cb63c015de19191db9666754c2ed79Alan Cox}
1695079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1696079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
1697079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_do_kdskbmode		-	set keyboard mode ioctl
1698079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: the console to use
1699079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@arg: the requested mode
1700079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
1701079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Update the keyboard mode bits while holding the correct locks.
1702079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Return 0 for success or an error code.
1703079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
1704079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdskbmode(int console, unsigned int arg)
1705079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1706079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
1707079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int ret = 0;
1708079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
1709079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1710079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
1711079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch(arg) {
1712079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_RAW:
1713079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->kbdmode = VC_RAW;
1714079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1715079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_MEDIUMRAW:
1716079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->kbdmode = VC_MEDIUMRAW;
1717079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1718079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_XLATE:
1719079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->kbdmode = VC_XLATE;
1720079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		do_compute_shiftstate();
1721079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1722079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_UNICODE:
1723079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->kbdmode = VC_UNICODE;
1724079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		do_compute_shiftstate();
1725079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1726079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_OFF:
1727079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->kbdmode = VC_OFF;
1728079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1729079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	default:
1730079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = -EINVAL;
1731079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1732079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
1733079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return ret;
1734079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1735079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1736079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
1737079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_do_kdskbmeta		-	set keyboard meta state
1738079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: the console to use
1739079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@arg: the requested meta state
1740079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
1741079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Update the keyboard meta bits while holding the correct locks.
1742079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Return 0 for success or an error code.
1743079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
1744079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdskbmeta(int console, unsigned int arg)
1745079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1746079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
1747079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int ret = 0;
1748079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
1749079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1750079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
1751079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch(arg) {
1752079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_METABIT:
1753079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		clr_vc_kbd_mode(kbd, VC_META);
1754079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1755079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_ESCPREFIX:
1756079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		set_vc_kbd_mode(kbd, VC_META);
1757079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1758079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	default:
1759079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = -EINVAL;
1760079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1761079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
1762079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return ret;
1763079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1764079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1765079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
1766079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox								int perm)
1767079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1768079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbkeycode tmp;
1769079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int kc = 0;
1770079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1771079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
1772079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return -EFAULT;
1773079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch (cmd) {
1774079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDGETKEYCODE:
1775079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kc = getkeycode(tmp.scancode);
1776079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (kc >= 0)
1777079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			kc = put_user(kc, &user_kbkc->keycode);
1778079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1779079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDSETKEYCODE:
1780079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!perm)
1781079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EPERM;
1782079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kc = setkeycode(tmp.scancode, tmp.keycode);
1783079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1784079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1785079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return kc;
1786079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1787079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1788079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#define i (tmp.kb_index)
1789079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#define s (tmp.kb_table)
1790079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#define v (tmp.kb_value)
1791079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1792079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
1793079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox						int console)
1794079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1795079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
1796079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbentry tmp;
1797079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	ushort *key_map, *new_map, val, ov;
1798079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
1799079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1800079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
1801079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return -EFAULT;
1802079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1803079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (!capable(CAP_SYS_TTY_CONFIG))
1804079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		perm = 0;
1805079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1806079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch (cmd) {
1807079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDGKBENT:
1808079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		/* Ensure another thread doesn't free it under us */
1809079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1810079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		key_map = key_maps[s];
1811079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (key_map) {
1812079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    val = U(key_map[i]);
1813079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
1814079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			val = K_HOLE;
1815079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		} else
1816079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    val = (i ? K_HOLE : K_NOSUCHMAP);
1817079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1818079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return put_user(val, &user_kbe->kb_value);
1819079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDSKBENT:
1820079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!perm)
1821079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EPERM;
1822079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!i && v == K_NOSUCHMAP) {
1823079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			spin_lock_irqsave(&kbd_event_lock, flags);
1824079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			/* deallocate map */
1825079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			key_map = key_maps[s];
1826079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			if (s && key_map) {
1827079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    key_maps[s] = NULL;
1828079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    if (key_map[0] == U(K_ALLOCATED)) {
1829079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox					kfree(key_map);
1830079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox					keymap_count--;
1831079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    }
1832079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			}
1833079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			spin_unlock_irqrestore(&kbd_event_lock, flags);
1834079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			break;
1835079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		}
1836079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1837079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (KTYP(v) < NR_TYPES) {
1838079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (KVAL(v) > max_vals[KTYP(v)])
1839079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				return -EINVAL;
1840079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		} else
1841079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (kbd->kbdmode != VC_UNICODE)
1842079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				return -EINVAL;
1843079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1844079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		/* ++Geert: non-PC keyboards may generate keycode zero */
1845079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#if !defined(__mc68000__) && !defined(__powerpc__)
1846079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		/* assignment to entry 0 only tests validity of args */
1847079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!i)
1848079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			break;
1849079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#endif
1850079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1851079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
1852079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!new_map)
1853079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -ENOMEM;
1854079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1855079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		key_map = key_maps[s];
1856079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (key_map == NULL) {
1857079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			int j;
1858079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1859079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
1860079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    !capable(CAP_SYS_RESOURCE)) {
1861079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				spin_unlock_irqrestore(&kbd_event_lock, flags);
1862079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				kfree(new_map);
1863079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				return -EPERM;
1864079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			}
1865079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			key_maps[s] = new_map;
1866079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			key_map[0] = U(K_ALLOCATED);
1867079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			for (j = 1; j < NR_KEYS; j++)
1868079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				key_map[j] = U(K_HOLE);
1869079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			keymap_count++;
1870079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		} else
1871079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			kfree(new_map);
1872079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1873079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ov = U(key_map[i]);
1874079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (v == ov)
1875079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			goto out;
1876079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		/*
1877079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		 * Attention Key.
1878079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		 */
1879079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) {
1880079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			spin_unlock_irqrestore(&kbd_event_lock, flags);
1881079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EPERM;
1882079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		}
1883079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		key_map[i] = U(v);
1884079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
1885079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			do_compute_shiftstate();
1886079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxout:
1887079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1888079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1889079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1890079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return 0;
1891079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1892079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#undef i
1893079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#undef s
1894079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#undef v
1895079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1896079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/* FIXME: This one needs untangling and locking */
1897079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
1898079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1899079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbsentry *kbs;
1900079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	char *p;
1901079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	u_char *q;
1902079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	u_char __user *up;
1903079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int sz;
1904079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int delta;
1905079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	char *first_free, *fj, *fnw;
1906079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int i, j, k;
1907079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int ret;
1908079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1909079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (!capable(CAP_SYS_TTY_CONFIG))
1910079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		perm = 0;
1911079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1912079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
1913079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (!kbs) {
1914079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = -ENOMEM;
1915079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		goto reterr;
1916079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1917079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1918079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* we mostly copy too much here (512bytes), but who cares ;) */
1919079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
1920079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = -EFAULT;
1921079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		goto reterr;
1922079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1923079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
1924079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	i = kbs->kb_func;
1925079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1926079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch (cmd) {
1927079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDGKBSENT:
1928079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		sz = sizeof(kbs->kb_string) - 1; /* sz should have been
1929079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox						  a struct member */
1930079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		up = user_kdgkb->kb_string;
1931079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		p = func_table[i];
1932079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if(p)
1933079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			for ( ; *p && sz; p++, sz--)
1934079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				if (put_user(*p, up++)) {
1935079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox					ret = -EFAULT;
1936079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox					goto reterr;
1937079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				}
1938079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (put_user('\0', up)) {
1939079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			ret = -EFAULT;
1940079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			goto reterr;
1941079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		}
1942079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kfree(kbs);
1943079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return ((p && *p) ? -EOVERFLOW : 0);
1944079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDSKBSENT:
1945079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!perm) {
1946079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			ret = -EPERM;
1947079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			goto reterr;
1948079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		}
1949079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1950079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		q = func_table[i];
1951079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		first_free = funcbufptr + (funcbufsize - funcbufleft);
1952079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
1953079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			;
1954079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (j < MAX_NR_FUNC)
1955079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			fj = func_table[j];
1956079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		else
1957079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			fj = first_free;
1958079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1959079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string);
1960079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (delta <= funcbufleft) { 	/* it fits in current buf */
1961079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (j < MAX_NR_FUNC) {
1962079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			memmove(fj + delta, fj, first_free - fj);
1963079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			for (k = j; k < MAX_NR_FUNC; k++)
1964079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    if (func_table[k])
1965079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				func_table[k] += delta;
1966079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    }
1967079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (!q)
1968079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      func_table[i] = fj;
1969079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    funcbufleft -= delta;
1970079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		} else {			/* allocate a larger buffer */
1971079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    sz = 256;
1972079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    while (sz < funcbufsize - funcbufleft + delta)
1973079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      sz <<= 1;
1974079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    fnw = kmalloc(sz, GFP_KERNEL);
1975079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if(!fnw) {
1976079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      ret = -ENOMEM;
1977079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      goto reterr;
1978079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    }
1979079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1980079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (!q)
1981079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      func_table[i] = fj;
1982079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (fj > funcbufptr)
1983079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			memmove(fnw, funcbufptr, fj - funcbufptr);
1984079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    for (k = 0; k < j; k++)
1985079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      if (func_table[k])
1986079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			func_table[k] = fnw + (func_table[k] - funcbufptr);
1987079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1988079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (first_free > fj) {
1989079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
1990079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			for (k = j; k < MAX_NR_FUNC; k++)
1991079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			  if (func_table[k])
1992079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
1993079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    }
1994079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (funcbufptr != func_buf)
1995079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      kfree(funcbufptr);
1996079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    funcbufptr = fnw;
1997079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    funcbufleft = funcbufleft - delta + sz - funcbufsize;
1998079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    funcbufsize = sz;
1999079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		}
2000079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		strcpy(func_table[i], kbs->kb_string);
2001079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
2002079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
2003079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	ret = 0;
2004079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxreterr:
2005079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kfree(kbs);
2006079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return ret;
2007079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2008079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2009079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
2010079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2011079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2012079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        unsigned long flags;
2013079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned char ucval;
2014079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2015079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        switch(cmd) {
2016079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* the ioctls below read/set the flags usually shown in the leds */
2017079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* don't use them - they will go away without warning */
2018079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDGKBLED:
2019079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox                spin_lock_irqsave(&kbd_event_lock, flags);
2020079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
2021079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox                spin_unlock_irqrestore(&kbd_event_lock, flags);
2022079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return put_user(ucval, (char __user *)arg);
2023079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2024079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDSKBLED:
2025079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!perm)
2026079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EPERM;
2027079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (arg & ~0x77)
2028079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EINVAL;
2029079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox                spin_lock_irqsave(&kbd_event_lock, flags);
2030079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->ledflagstate = (arg & 7);
2031079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->default_ledflagstate = ((arg >> 4) & 7);
2032079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		set_leds();
2033079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox                spin_unlock_irqrestore(&kbd_event_lock, flags);
2034079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
2035079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2036079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* the ioctls below only set the lights, not the functions */
2037079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* for those, see KDGKBLED and KDSKBLED above */
2038079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDGETLED:
2039079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ucval = getledstate();
2040079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return put_user(ucval, (char __user *)arg);
2041079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2042079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDSETLED:
2043079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!perm)
2044079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EPERM;
2045079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		setledstate(kbd, arg);
2046079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return 0;
2047079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        }
2048079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        return -ENOIOCTLCMD;
2049079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2050079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2051079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdgkbmode(int console)
2052079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2053079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2054079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* This is a spot read so needs no locking */
2055079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch (kbd->kbdmode) {
2056079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case VC_RAW:
2057079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return K_RAW;
2058079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case VC_MEDIUMRAW:
2059079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return K_MEDIUMRAW;
2060079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case VC_UNICODE:
2061079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return K_UNICODE;
2062079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case VC_OFF:
2063079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return K_OFF;
2064079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	default:
2065079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return K_XLATE;
2066079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
2067079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2068079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2069079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2070079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_do_kdgkbmeta		-	report meta status
2071079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to report
2072079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2073079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Report the meta flag status of this console
2074079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2075079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdgkbmeta(int console)
2076079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2077079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2078079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        /* Again a spot read so no locking */
2079079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT;
2080079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2081079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2082079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2083079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_reset_unicode	-	reset the unicode status
2084079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console being reset
2085079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2086079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Restore the unicode console state to its default
2087079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2088079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_reset_unicode(int console)
2089079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2090079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
2091079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2092079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
2093079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbd_table[console].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
2094079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
2095079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2096079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2097079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2098079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_get_shiftstate	-	shift bit state
2099079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2100079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Report the shift bits from the keyboard state. We have to export
2101079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	this to support some oddities in the vt layer.
2102079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2103079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_get_shift_state(void)
2104079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2105079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        /* Don't lock as this is a transient report */
2106079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        return shift_state;
2107079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2108079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2109079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2110079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_reset_keyboard	-	reset keyboard state
2111079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to reset
2112079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2113079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Reset the keyboard bits for a console as part of a general console
2114079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	reset event
2115079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2116079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_reset_keyboard(int console)
2117079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2118079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2119079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
2120079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2121079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
2122079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	set_vc_kbd_mode(kbd, VC_REPEAT);
2123079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	clr_vc_kbd_mode(kbd, VC_CKMODE);
2124079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	clr_vc_kbd_mode(kbd, VC_APPLIC);
2125079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	clr_vc_kbd_mode(kbd, VC_CRLF);
2126079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbd->lockstate = 0;
2127079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbd->slockstate = 0;
2128079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbd->ledmode = LED_SHOW_FLAGS;
2129079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbd->ledflagstate = kbd->default_ledflagstate;
2130079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* do not do set_leds here because this causes an endless tasklet loop
2131079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	   when the keyboard hasn't been initialized yet */
2132079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
2133079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2134079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2135079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2136079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_get_kbd_mode_bit	-	read keyboard status bits
2137079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to read from
2138079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@bit: mode bit to read
2139079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2140079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Report back a vt mode bit. We do this without locking so the
2141079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	caller must be sure that there are no synchronization needs
2142079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2143079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2144079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_get_kbd_mode_bit(int console, int bit)
2145079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2146079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2147079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return vc_kbd_mode(kbd, bit);
2148079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2149079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2150079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2151079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_set_kbd_mode_bit	-	read keyboard status bits
2152079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to read from
2153079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@bit: mode bit to read
2154079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2155079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Set a vt mode bit. We do this without locking so the
2156079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	caller must be sure that there are no synchronization needs
2157079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2158079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2159079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_set_kbd_mode_bit(int console, int bit)
2160079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2161079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2162079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
2163079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2164079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
2165079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	set_vc_kbd_mode(kbd, bit);
2166079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
2167079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2168079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2169079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2170079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_clr_kbd_mode_bit	-	read keyboard status bits
2171079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to read from
2172079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@bit: mode bit to read
2173079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2174079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Report back a vt mode bit. We do this without locking so the
2175079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	caller must be sure that there are no synchronization needs
2176079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2177079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2178079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_clr_kbd_mode_bit(int console, int bit)
2179079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2180079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2181079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
2182079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2183079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
2184079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	clr_vc_kbd_mode(kbd, bit);
2185079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
2186079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2187