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
108884f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *
108984f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *	FIXME: We eventually need to hold the kbd lock here to protect
109084f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *	the LED updating. We can't do it yet because fn_hold calls stop_tty
109184f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *	and start_tty under the kbd_event_lock, while normal tty paths
109284f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *	don't hold the lock. We probably need to split out an LED lock
109384f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *	but not during an -rc release!
1094079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
1095079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_kbd_con_start(int console)
1096079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1097079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
109884f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox/*	unsigned long flags; */
109984f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox/*	spin_lock_irqsave(&kbd_event_lock, flags); */
1100079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	clr_vc_kbd_led(kbd, VC_SCROLLOCK);
1101079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	set_leds();
110284f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox/*	spin_unlock_irqrestore(&kbd_event_lock, flags); */
1103079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1104079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1105079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
1106079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_kbd_con_stop		-	Keyboard side of console stop
1107079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console
1108079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
1109079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Handle console stop. This is a wrapper for the VT layer
1110079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	so that we can keep kbd knowledge internal
111184f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *
111284f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *	FIXME: We eventually need to hold the kbd lock here to protect
111384f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *	the LED updating. We can't do it yet because fn_hold calls stop_tty
111484f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *	and start_tty under the kbd_event_lock, while normal tty paths
111584f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *	don't hold the lock. We probably need to split out an LED lock
111684f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox *	but not during an -rc release!
1117079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
1118079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_kbd_con_stop(int console)
1119079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1120079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
112184f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox/*	unsigned long flags; */
112284f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox/*	spin_lock_irqsave(&kbd_event_lock, flags); */
1123079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	set_vc_kbd_led(kbd, VC_SCROLLOCK);
1124079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	set_leds();
112584f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox/*	spin_unlock_irqrestore(&kbd_event_lock, flags); */
1126079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1127079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
112966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov * This is the tasklet that updates LED state on all keyboards
113066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov * attached to the box. The reason we use tasklet is that we
113166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov * need to handle the scenario when keyboard handler is not
113284f904ecd3aa2ccb5779b815b69c1cb592f07bb5Alan Cox * registered yet but we already getting updates from the VT to
113366d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov * update led state.
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void kbd_bh(unsigned long dummy)
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char leds = getleds();
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (leds != ledstate) {
114066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		input_handler_for_each_handle(&kbd_handler, &leds,
114166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov					      kbd_update_leds_helper);
114266d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		ledstate = leds;
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
11490b57ee9e55373a27e45549e82b0c43621480a71bAdrian Bunk    defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
11500b57ee9e55373a27e45549e82b0c43621480a71bAdrian Bunk    defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
11513a4e832cccc5baba98ba010e38c58266954228a7Hans-Christian Egtvedt    (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) ||\
11523a4e832cccc5baba98ba010e38c58266954228a7Hans-Christian Egtvedt    defined(CONFIG_AVR32)
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11570f5e560e4523e15f33922de5becd024ccaaff76cAndreas Mohrstatic const unsigned short x86_keycodes[256] =
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
1164896cdc7b802c972d625351eb47d4add22d1fccb6Dmitry Torokhov	284,285,309,  0,312, 91,327,328,329,331,333,335,336,337,338,339,
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
116772a42f242cad8f393bb2556f4cc5175c6cea9892Hans de Goede	103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
116872a42f242cad8f393bb2556f4cc5175c6cea9892Hans de Goede	291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11740b57ee9e55373a27e45549e82b0c43621480a71bAdrian Bunk#ifdef CONFIG_SPARC
1175e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhovstatic int sparc_l1_a_state;
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void sun_do_break(void);
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1179fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhovstatic int emulate_raw(struct vc_data *vc, unsigned int keycode,
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       unsigned char up_flag)
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1182896cdc7b802c972d625351eb47d4add22d1fccb6Dmitry Torokhov	int code;
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (keycode) {
1185896cdc7b802c972d625351eb47d4add22d1fccb6Dmitry Torokhov
1186e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	case KEY_PAUSE:
1187e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		put_queue(vc, 0xe1);
1188e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		put_queue(vc, 0x1d | up_flag);
1189e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		put_queue(vc, 0x45 | up_flag);
1190e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		break;
1191896cdc7b802c972d625351eb47d4add22d1fccb6Dmitry Torokhov
1192e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	case KEY_HANGEUL:
1193e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (!up_flag)
1194e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0xf2);
1195e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		break;
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1197e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	case KEY_HANJA:
1198e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (!up_flag)
1199e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0xf1);
1200e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		break;
1201896cdc7b802c972d625351eb47d4add22d1fccb6Dmitry Torokhov
1202e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	case KEY_SYSRQ:
1203e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		/*
1204e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		 * Real AT keyboards (that's what we're trying
1205e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		 * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
1206e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		 * pressing PrtSc/SysRq alone, but simply 0x54
1207e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		 * when pressing Alt+PrtSc/SysRq.
1208e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		 */
1209e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (test_bit(KEY_LEFTALT, key_down) ||
1210e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		    test_bit(KEY_RIGHTALT, key_down)) {
1211e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0x54 | up_flag);
1212e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		} else {
1213e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0xe0);
1214e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0x2a | up_flag);
1215e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0xe0);
1216e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0x37 | up_flag);
1217e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		}
1218e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		break;
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1220e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	default:
1221e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (keycode > 255)
1222e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return -1;
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1224e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		code = x86_keycodes[keycode];
1225e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (!code)
1226e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			return -1;
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1228e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (code & 0x100)
1229e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			put_queue(vc, 0xe0);
1230e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		put_queue(vc, (code & 0x7f) | up_flag);
1231e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
1232e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		break;
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HW_RAW(dev)	0
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (keycode > 127)
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_queue(vc, keycode | up_flag);
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void kbd_rawcode(unsigned char data)
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct vc_data *vc = vc_cons[fg_console].d;
1255e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov
12560c09b2ac35ff7c5f280e5cf8142ad0822f1c93b3Alan Jenkins	kbd = kbd_table + vc->vc_num;
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (kbd->kbdmode == VC_RAW)
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_queue(vc, data);
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12617d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void kbd_keycode(unsigned int keycode, int down, int hw_raw)
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct vc_data *vc = vc_cons[fg_console].d;
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short keysym, *key_map;
1265e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	unsigned char type;
1266e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	bool raw_mode;
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tty_struct *tty;
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int shift_final;
126941ab4396e19fba338baf28044d3e48385744b930Samuel Thibault	struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
1270e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	int rc;
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12728ce73264b75be4d5ed480440ac32dfc1f25ff678Alan Cox	tty = vc->port.tty;
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty && (!tty->driver_data)) {
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* No driver data? Strange. Okay we fix it then. */
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty->driver_data = vc;
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12790c09b2ac35ff7c5f280e5cf8142ad0822f1c93b3Alan Jenkins	kbd = kbd_table + vc->vc_num;
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12810b57ee9e55373a27e45549e82b0c43621480a71bAdrian Bunk#ifdef CONFIG_SPARC
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (keycode == KEY_STOP)
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sparc_l1_a_state = down;
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rep = (down == 2);
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1288e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	raw_mode = (kbd->kbdmode == VC_RAW);
1289e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if (raw_mode && !hw_raw)
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (emulate_raw(vc, keycode, !down << 7))
12919e35d20663344b38339ffb6127ba08285f3397a9Dmitry Torokhov			if (keycode < BTN_MISC && printk_ratelimit())
12929272e9a2f8872a0f9fb15aaa10f2a993524343e0Dmitry Torokhov				pr_warning("can't emulate rawmode for keycode %d\n",
12939272e9a2f8872a0f9fb15aaa10f2a993524343e0Dmitry Torokhov					   keycode);
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12950b57ee9e55373a27e45549e82b0c43621480a71bAdrian Bunk#ifdef CONFIG_SPARC
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (keycode == KEY_A && sparc_l1_a_state) {
1297e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		sparc_l1_a_state = false;
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sun_do_break();
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (kbd->kbdmode == VC_MEDIUMRAW) {
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * This is extended medium raw mode, with keys above 127
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * encoded as 0, high 7 bits, low 7 bits, with the 0 bearing
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the 'up' flag if needed. 0 is reserved, so this shouldn't
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * interfere with anything else. The two bytes after 0 will
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * always have the up flag set not to interfere with older
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * applications. This allows for 16384 different keycodes,
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * which should be enough.
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (keycode < 128) {
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_queue(vc, keycode | (!down << 7));
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_queue(vc, !down << 7);
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_queue(vc, (keycode >> 7) | 0x80);
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_queue(vc, keycode | 0x80);
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1319e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		raw_mode = true;
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (down)
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_bit(keycode, key_down);
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clear_bit(keycode, key_down);
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1327fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	if (rep &&
1328fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	    (!vc_kbd_mode(kbd, VC_REPEAT) ||
1329f34d7a5b7010b82fe97da95496b9971435530062Alan Cox	     (tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) {
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Don't repeat a key if the input buffers are not empty and the
1332fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov		 * characters get aren't echoed locally. This makes key repeat
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * usable with slow applications and under heavy loads.
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
133841ab4396e19fba338baf28044d3e48385744b930Samuel Thibault	param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
13390beb4f6f294b0f2dde07fa9da9c00abd4f9c8b50Karl Dahlke	param.ledstate = kbd->ledflagstate;
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	key_map = key_maps[shift_final];
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1342e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1343e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov					KBD_KEYCODE, &param);
1344e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if (rc == NOTIFY_STOP || !key_map) {
1345e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		atomic_notifier_call_chain(&keyboard_notifier_list,
1346e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov					   KBD_UNBOUND_KEYCODE, &param);
1347079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		do_compute_shiftstate();
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kbd->slockstate = 0;
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1352e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if (keycode < NR_KEYS)
1353b9ec4e109d7a342e83e1210e05797222e36555c3Samuel Thibault		keysym = key_map[keycode];
1354e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	else if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
1355e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1));
1356e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	else
1357e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		return;
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	type = KTYP(keysym);
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type < 0xf0) {
136241ab4396e19fba338baf28044d3e48385744b930Samuel Thibault		param.value = keysym;
1363e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1364e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov						KBD_UNICODE, &param);
1365e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov		if (rc != NOTIFY_STOP)
1366e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov			if (down && !raw_mode)
1367e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov				to_utf8(vc, keysym);
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	type -= 0xf0;
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type == KT_LETTER) {
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		type = KT_LATIN;
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			key_map = key_maps[shift_final ^ (1 << KG_SHIFT)];
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (key_map)
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				keysym = key_map[keycode];
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
138141ab4396e19fba338baf28044d3e48385744b930Samuel Thibault
1382e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	param.value = keysym;
1383e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1384e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov					KBD_KEYSYM, &param);
1385e0785572ce8620beb117530645e6989d2217d3b7Dmitry Torokhov	if (rc == NOTIFY_STOP)
138641ab4396e19fba338baf28044d3e48385744b930Samuel Thibault		return;
138741ab4396e19fba338baf28044d3e48385744b930Samuel Thibault
13889fc3de9c83565fcaa23df74c2fc414bb6e7efb0aArthur Taylor	if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type != KT_SHIFT)
138941ab4396e19fba338baf28044d3e48385744b930Samuel Thibault		return;
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13917d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells	(*k_handler[type])(vc, keysym & 0xff, !down);
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13930beb4f6f294b0f2dde07fa9da9c00abd4f9c8b50Karl Dahlke	param.ledstate = kbd->ledflagstate;
139441ab4396e19fba338baf28044d3e48385744b930Samuel Thibault	atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
139541ab4396e19fba338baf28044d3e48385744b930Samuel Thibault
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type != KT_SLOCK)
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kbd->slockstate = 0;
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1400fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhovstatic void kbd_event(struct input_handle *handle, unsigned int event_type,
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      unsigned int event_code, int value)
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
140321cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov	/* We are called with interrupts disabled, just take the lock */
140421cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov	spin_lock(&kbd_event_lock);
140521cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kbd_rawcode(value);
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (event_type == EV_KEY)
14097d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells		kbd_keycode(event_code, value, HW_RAW(handle->dev));
141021cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov
141121cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov	spin_unlock(&kbd_event_lock);
141221cea58e49cf59e7c77ce2a01be432458e9f99a9Dmitry Torokhov
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tasklet_schedule(&keyboard_tasklet);
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do_poke_blanked_console = 1;
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	schedule_console_callback();
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14180b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhovstatic bool kbd_match(struct input_handler *handler, struct input_dev *dev)
14190b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov{
14200b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov	int i;
14210b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov
14220b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov	if (test_bit(EV_SND, dev->evbit))
14230b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov		return true;
14240b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov
142553c1f764022337d7168b1344d6700b3d98e4acecSamuel Thibault	if (test_bit(EV_KEY, dev->evbit)) {
14260b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov		for (i = KEY_RESERVED; i < BTN_MISC; i++)
14270b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov			if (test_bit(i, dev->keybit))
14280b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov				return true;
142953c1f764022337d7168b1344d6700b3d98e4acecSamuel Thibault		for (i = KEY_BRL_DOT1; i <= KEY_BRL_DOT10; i++)
143053c1f764022337d7168b1344d6700b3d98e4acecSamuel Thibault			if (test_bit(i, dev->keybit))
143153c1f764022337d7168b1344d6700b3d98e4acecSamuel Thibault				return true;
143253c1f764022337d7168b1344d6700b3d98e4acecSamuel Thibault	}
14330b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov
14340b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov	return false;
14350b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov}
14360b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When a keyboard (or other input device) is found, the kbd_connect
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function is called. The function then looks at the device, and if it
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * likes it, it can open it and get events from it. In this (kbd_connect)
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function, we should decide which VT to bind that keyboard to initially.
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14435b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhovstatic int kbd_connect(struct input_handler *handler, struct input_dev *dev,
14445b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov			const struct input_device_id *id)
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct input_handle *handle;
14475b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	int error;
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
144922479e1c0d111c60d29a4759408394cbdc7548a5Dmitry Torokhov	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
145022479e1c0d111c60d29a4759408394cbdc7548a5Dmitry Torokhov	if (!handle)
14515b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov		return -ENOMEM;
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	handle->dev = dev;
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	handle->handler = handler;
1455fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov	handle->name = "kbd";
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14575b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	error = input_register_handle(handle);
14585b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	if (error)
14595b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov		goto err_free_handle;
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14615b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	error = input_open_device(handle);
14625b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	if (error)
14635b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov		goto err_unregister_handle;
14645b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov
14655b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	return 0;
14665b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov
14675b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov err_unregister_handle:
14685b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	input_unregister_handle(handle);
14695b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov err_free_handle:
14705b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	kfree(handle);
14715b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	return error;
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void kbd_disconnect(struct input_handle *handle)
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	input_close_device(handle);
14775b2a08262a8c952fef008154933953f083ca5766Dmitry Torokhov	input_unregister_handle(handle);
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(handle);
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1481c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov/*
1482c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov * Start keyboard handler on the new keyboard by refreshing LED state to
1483c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov * match the rest of the system.
1484c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov */
1485c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhovstatic void kbd_start(struct input_handle *handle)
1486c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov{
1487c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov	tasklet_disable(&keyboard_tasklet);
148866d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
148966d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov	if (ledstate != 0xff)
149066d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov		kbd_update_leds_helper(handle, &ledstate);
149166d2a5952eab875f1286e04f738ef029afdaf013Dmitry Torokhov
1492c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov	tasklet_enable(&keyboard_tasklet);
1493c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov}
1494c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov
149566e66118837ed95a299328437c2d9fb4b5137352Dmitry Torokhovstatic const struct input_device_id kbd_ids[] = {
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
14976aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
14986aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox		.evbit = { BIT_MASK(EV_KEY) },
14996aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox	},
1500fe1e86049813641a518d15adf7191bd711b4f611Dmitry Torokhov
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
15026aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
15036aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox		.evbit = { BIT_MASK(EV_SND) },
15046aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox	},
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ },    /* Terminating entry */
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(input, kbd_ids);
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct input_handler kbd_handler = {
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.event		= kbd_event,
15130b7024ac4df5821347141c18e680b7166bc1cb20Dmitry Torokhov	.match		= kbd_match,
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.connect	= kbd_connect,
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.disconnect	= kbd_disconnect,
1516c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2Dmitry Torokhov	.start		= kbd_start,
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "kbd",
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= kbd_ids,
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init kbd_init(void)
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
15244263cf0fac28122c8381b6f4f9441a43cd93c81fDmitry Torokhov	int error;
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15266aeed479fdef85e6874c2d41cca9f121c294c536Alan Cox	for (i = 0; i < MAX_NR_CONSOLES; i++) {
15272b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].ledflagstate = KBD_DEFLEDS;
15282b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
15292b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].ledmode = LED_SHOW_FLAGS;
15302b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].lockstate = KBD_DEFLOCK;
15312b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].slockstate = 0;
15322b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov		kbd_table[i].modeflags = KBD_DEFMODE;
15332e8ecb9db0bcc19e1cc8bb51e9252fe6a86a9863Bill Nottingham		kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
15342b192908b8e74ce0753c7dff92d244735d1eeed9Dmitry Torokhov	}
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15364263cf0fac28122c8381b6f4f9441a43cd93c81fDmitry Torokhov	error = input_register_handler(&kbd_handler);
15374263cf0fac28122c8381b6f4f9441a43cd93c81fDmitry Torokhov	if (error)
15384263cf0fac28122c8381b6f4f9441a43cd93c81fDmitry Torokhov		return error;
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tasklet_enable(&keyboard_tasklet);
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tasklet_schedule(&keyboard_tasklet);
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1545247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1546247ff8e610cb63c015de19191db9666754c2ed79Alan Cox/* Ioctl support code */
1547247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1548247ff8e610cb63c015de19191db9666754c2ed79Alan Cox/**
1549247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	vt_do_diacrit		-	diacritical table updates
1550247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	@cmd: ioctl request
1551247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	@up: pointer to user data for ioctl
1552247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	@perm: permissions check computed by caller
1553247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *
1554247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	Update the diacritical tables atomically and safely. Lock them
1555247ff8e610cb63c015de19191db9666754c2ed79Alan Cox *	against simultaneous keypresses
1556247ff8e610cb63c015de19191db9666754c2ed79Alan Cox */
1557247ff8e610cb63c015de19191db9666754c2ed79Alan Coxint vt_do_diacrit(unsigned int cmd, void __user *up, int perm)
1558247ff8e610cb63c015de19191db9666754c2ed79Alan Cox{
1559247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	struct kbdiacrs __user *a = up;
1560247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	unsigned long flags;
1561247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	int asize;
1562247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	int ret = 0;
1563247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1564247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	switch (cmd) {
1565247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	case KDGKBDIACR:
1566247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	{
1567247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		struct kbdiacr *diacr;
1568247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		int i;
1569247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1570247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		diacr = kmalloc(MAX_DIACR * sizeof(struct kbdiacr),
1571247ff8e610cb63c015de19191db9666754c2ed79Alan Cox								GFP_KERNEL);
1572247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (diacr == NULL)
1573247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -ENOMEM;
1574247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1575247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		/* Lock the diacriticals table, make a copy and then
1576247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		   copy it after we unlock */
1577247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1578247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1579247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		asize = accent_table_size;
1580247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		for (i = 0; i < asize; i++) {
1581247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			diacr[i].diacr = conv_uni_to_8bit(
1582247ff8e610cb63c015de19191db9666754c2ed79Alan Cox						accent_table[i].diacr);
1583247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			diacr[i].base = conv_uni_to_8bit(
1584247ff8e610cb63c015de19191db9666754c2ed79Alan Cox						accent_table[i].base);
1585247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			diacr[i].result = conv_uni_to_8bit(
1586247ff8e610cb63c015de19191db9666754c2ed79Alan Cox						accent_table[i].result);
1587247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		}
1588247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1589247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1590247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (put_user(asize, &a->kb_cnt))
1591247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			ret = -EFAULT;
1592247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		else  if (copy_to_user(a->kbdiacr, diacr,
1593247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				asize * sizeof(struct kbdiacr)))
1594247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			ret = -EFAULT;
1595247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		kfree(diacr);
1596247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		return ret;
1597247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	}
1598247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	case KDGKBDIACRUC:
1599247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	{
1600247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		struct kbdiacrsuc __user *a = up;
1601247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		void *buf;
1602247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1603247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		buf = kmalloc(MAX_DIACR * sizeof(struct kbdiacruc),
1604247ff8e610cb63c015de19191db9666754c2ed79Alan Cox								GFP_KERNEL);
1605247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (buf == NULL)
1606247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -ENOMEM;
1607247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1608247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		/* Lock the diacriticals table, make a copy and then
1609247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		   copy it after we unlock */
1610247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1611247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1612247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		asize = accent_table_size;
1613247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		memcpy(buf, accent_table, asize * sizeof(struct kbdiacruc));
1614247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1615247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1616247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1617247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (put_user(asize, &a->kb_cnt))
1618247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			ret = -EFAULT;
1619247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		else if (copy_to_user(a->kbdiacruc, buf,
1620247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				asize*sizeof(struct kbdiacruc)))
1621247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			ret = -EFAULT;
1622247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		kfree(buf);
1623247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		return ret;
1624247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	}
1625247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1626247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	case KDSKBDIACR:
1627247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	{
1628247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		struct kbdiacrs __user *a = up;
1629247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		struct kbdiacr *diacr = NULL;
1630247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		unsigned int ct;
1631247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		int i;
1632247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1633247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (!perm)
1634247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EPERM;
1635247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (get_user(ct, &a->kb_cnt))
1636247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EFAULT;
1637247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (ct >= MAX_DIACR)
1638247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EINVAL;
1639247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1640247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (ct) {
1641247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			diacr = kmalloc(sizeof(struct kbdiacr) * ct,
1642247ff8e610cb63c015de19191db9666754c2ed79Alan Cox								GFP_KERNEL);
1643247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			if (diacr == NULL)
1644247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				return -ENOMEM;
1645247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1646247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			if (copy_from_user(diacr, a->kbdiacr,
1647247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					sizeof(struct kbdiacr) * ct)) {
1648247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				kfree(diacr);
1649247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				return -EFAULT;
1650247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			}
1651247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		}
1652247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1653247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1654247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		accent_table_size = ct;
1655247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		for (i = 0; i < ct; i++) {
1656247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			accent_table[i].diacr =
1657247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					conv_8bit_to_uni(diacr[i].diacr);
1658247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			accent_table[i].base =
1659247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					conv_8bit_to_uni(diacr[i].base);
1660247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			accent_table[i].result =
1661247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					conv_8bit_to_uni(diacr[i].result);
1662247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		}
1663247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1664247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		kfree(diacr);
1665247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		return 0;
1666247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	}
1667247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1668247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	case KDSKBDIACRUC:
1669247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	{
1670247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		struct kbdiacrsuc __user *a = up;
1671247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		unsigned int ct;
1672247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		void *buf = NULL;
1673247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1674247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (!perm)
1675247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EPERM;
1676247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1677247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (get_user(ct, &a->kb_cnt))
1678247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EFAULT;
1679247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1680247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (ct >= MAX_DIACR)
1681247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			return -EINVAL;
1682247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1683247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (ct) {
1684247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			buf = kmalloc(ct * sizeof(struct kbdiacruc),
1685247ff8e610cb63c015de19191db9666754c2ed79Alan Cox								GFP_KERNEL);
1686247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			if (buf == NULL)
1687247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				return -ENOMEM;
1688247ff8e610cb63c015de19191db9666754c2ed79Alan Cox
1689247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			if (copy_from_user(buf, a->kbdiacruc,
1690247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					ct * sizeof(struct kbdiacruc))) {
1691247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				kfree(buf);
1692247ff8e610cb63c015de19191db9666754c2ed79Alan Cox				return -EFAULT;
1693247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			}
1694247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		}
1695247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1696247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		if (ct)
1697247ff8e610cb63c015de19191db9666754c2ed79Alan Cox			memcpy(accent_table, buf,
1698247ff8e610cb63c015de19191db9666754c2ed79Alan Cox					ct * sizeof(struct kbdiacruc));
1699247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		accent_table_size = ct;
1700247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1701247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		kfree(buf);
1702247ff8e610cb63c015de19191db9666754c2ed79Alan Cox		return 0;
1703247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	}
1704247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	}
1705247ff8e610cb63c015de19191db9666754c2ed79Alan Cox	return ret;
1706247ff8e610cb63c015de19191db9666754c2ed79Alan Cox}
1707079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1708079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
1709079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_do_kdskbmode		-	set keyboard mode ioctl
1710079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: the console to use
1711079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@arg: the requested mode
1712079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
1713079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Update the keyboard mode bits while holding the correct locks.
1714079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Return 0 for success or an error code.
1715079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
1716079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdskbmode(int console, unsigned int arg)
1717079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1718079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
1719079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int ret = 0;
1720079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
1721079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1722079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
1723079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch(arg) {
1724079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_RAW:
1725079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->kbdmode = VC_RAW;
1726079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1727079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_MEDIUMRAW:
1728079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->kbdmode = VC_MEDIUMRAW;
1729079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1730079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_XLATE:
1731079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->kbdmode = VC_XLATE;
1732079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		do_compute_shiftstate();
1733079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1734079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_UNICODE:
1735079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->kbdmode = VC_UNICODE;
1736079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		do_compute_shiftstate();
1737079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1738079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_OFF:
1739079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->kbdmode = VC_OFF;
1740079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1741079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	default:
1742079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = -EINVAL;
1743079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1744079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
1745079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return ret;
1746079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1747079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1748079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
1749079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_do_kdskbmeta		-	set keyboard meta state
1750079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: the console to use
1751079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@arg: the requested meta state
1752079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
1753079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Update the keyboard meta bits while holding the correct locks.
1754079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Return 0 for success or an error code.
1755079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
1756079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdskbmeta(int console, unsigned int arg)
1757079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1758079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
1759079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int ret = 0;
1760079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
1761079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1762079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
1763079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch(arg) {
1764079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_METABIT:
1765079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		clr_vc_kbd_mode(kbd, VC_META);
1766079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1767079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case K_ESCPREFIX:
1768079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		set_vc_kbd_mode(kbd, VC_META);
1769079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1770079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	default:
1771079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = -EINVAL;
1772079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1773079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
1774079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return ret;
1775079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1776079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1777079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
1778079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox								int perm)
1779079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1780079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbkeycode tmp;
1781079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int kc = 0;
1782079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1783079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
1784079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return -EFAULT;
1785079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch (cmd) {
1786079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDGETKEYCODE:
1787079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kc = getkeycode(tmp.scancode);
1788079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (kc >= 0)
1789079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			kc = put_user(kc, &user_kbkc->keycode);
1790079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1791079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDSETKEYCODE:
1792079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!perm)
1793079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EPERM;
1794079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kc = setkeycode(tmp.scancode, tmp.keycode);
1795079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1796079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1797079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return kc;
1798079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1799079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1800079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#define i (tmp.kb_index)
1801079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#define s (tmp.kb_table)
1802079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#define v (tmp.kb_value)
1803079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1804079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
1805079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox						int console)
1806079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1807079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
1808079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbentry tmp;
1809079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	ushort *key_map, *new_map, val, ov;
1810079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
1811079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1812079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
1813079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return -EFAULT;
1814079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1815079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (!capable(CAP_SYS_TTY_CONFIG))
1816079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		perm = 0;
1817079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1818079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch (cmd) {
1819079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDGKBENT:
1820079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		/* Ensure another thread doesn't free it under us */
1821079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1822079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		key_map = key_maps[s];
1823079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (key_map) {
1824079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    val = U(key_map[i]);
1825079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
1826079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			val = K_HOLE;
1827079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		} else
1828079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    val = (i ? K_HOLE : K_NOSUCHMAP);
1829079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1830079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return put_user(val, &user_kbe->kb_value);
1831079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDSKBENT:
1832079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!perm)
1833079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EPERM;
1834079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!i && v == K_NOSUCHMAP) {
1835079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			spin_lock_irqsave(&kbd_event_lock, flags);
1836079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			/* deallocate map */
1837079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			key_map = key_maps[s];
1838079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			if (s && key_map) {
1839079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    key_maps[s] = NULL;
1840079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    if (key_map[0] == U(K_ALLOCATED)) {
1841079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox					kfree(key_map);
1842079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox					keymap_count--;
1843079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    }
1844079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			}
1845079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			spin_unlock_irqrestore(&kbd_event_lock, flags);
1846079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			break;
1847079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		}
1848079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1849079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (KTYP(v) < NR_TYPES) {
1850079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (KVAL(v) > max_vals[KTYP(v)])
1851079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				return -EINVAL;
1852079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		} else
1853079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (kbd->kbdmode != VC_UNICODE)
1854079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				return -EINVAL;
1855079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1856079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		/* ++Geert: non-PC keyboards may generate keycode zero */
1857079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#if !defined(__mc68000__) && !defined(__powerpc__)
1858079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		/* assignment to entry 0 only tests validity of args */
1859079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!i)
1860079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			break;
1861079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#endif
1862079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1863079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
1864079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!new_map)
1865079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -ENOMEM;
1866079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		spin_lock_irqsave(&kbd_event_lock, flags);
1867079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		key_map = key_maps[s];
1868079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (key_map == NULL) {
1869079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			int j;
1870079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1871079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
1872079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    !capable(CAP_SYS_RESOURCE)) {
1873079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				spin_unlock_irqrestore(&kbd_event_lock, flags);
1874079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				kfree(new_map);
1875079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				return -EPERM;
1876079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			}
1877079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			key_maps[s] = new_map;
187882896210aa3c59eaa4f78f7ba2f5f947601dd8f8Dan Carpenter			key_map = new_map;
1879079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			key_map[0] = U(K_ALLOCATED);
1880079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			for (j = 1; j < NR_KEYS; j++)
1881079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				key_map[j] = U(K_HOLE);
1882079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			keymap_count++;
1883079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		} else
1884079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			kfree(new_map);
1885079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1886079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ov = U(key_map[i]);
1887079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (v == ov)
1888079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			goto out;
1889079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		/*
1890079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		 * Attention Key.
1891079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		 */
1892079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) {
1893079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			spin_unlock_irqrestore(&kbd_event_lock, flags);
1894079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EPERM;
1895079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		}
1896079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		key_map[i] = U(v);
1897079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
1898079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			do_compute_shiftstate();
1899079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxout:
1900079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		spin_unlock_irqrestore(&kbd_event_lock, flags);
1901079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
1902079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1903079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return 0;
1904079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
1905079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#undef i
1906079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#undef s
1907079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox#undef v
1908079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1909079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/* FIXME: This one needs untangling and locking */
1910079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
1911079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
1912079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbsentry *kbs;
1913079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	char *p;
1914079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	u_char *q;
1915079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	u_char __user *up;
1916079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int sz;
1917079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int delta;
1918079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	char *first_free, *fj, *fnw;
1919079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int i, j, k;
1920079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	int ret;
1921079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1922079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (!capable(CAP_SYS_TTY_CONFIG))
1923079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		perm = 0;
1924079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1925079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
1926079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (!kbs) {
1927079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = -ENOMEM;
1928079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		goto reterr;
1929079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1930079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1931079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* we mostly copy too much here (512bytes), but who cares ;) */
1932079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
1933079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ret = -EFAULT;
1934079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		goto reterr;
1935079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
1936079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
1937079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	i = kbs->kb_func;
1938079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1939079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch (cmd) {
1940079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDGKBSENT:
1941079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		sz = sizeof(kbs->kb_string) - 1; /* sz should have been
1942079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox						  a struct member */
1943079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		up = user_kdgkb->kb_string;
1944079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		p = func_table[i];
1945079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if(p)
1946079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			for ( ; *p && sz; p++, sz--)
1947079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				if (put_user(*p, up++)) {
1948079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox					ret = -EFAULT;
1949079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox					goto reterr;
1950079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				}
1951079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (put_user('\0', up)) {
1952079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			ret = -EFAULT;
1953079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			goto reterr;
1954079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		}
1955079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kfree(kbs);
1956079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return ((p && *p) ? -EOVERFLOW : 0);
1957079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDSKBSENT:
1958079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!perm) {
1959079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			ret = -EPERM;
1960079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			goto reterr;
1961079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		}
1962079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1963079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		q = func_table[i];
1964079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		first_free = funcbufptr + (funcbufsize - funcbufleft);
1965079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
1966079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			;
1967079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (j < MAX_NR_FUNC)
1968079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			fj = func_table[j];
1969079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		else
1970079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			fj = first_free;
1971079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1972079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string);
1973079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (delta <= funcbufleft) { 	/* it fits in current buf */
1974079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (j < MAX_NR_FUNC) {
1975079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			memmove(fj + delta, fj, first_free - fj);
1976079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			for (k = j; k < MAX_NR_FUNC; k++)
1977079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    if (func_table[k])
1978079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox				func_table[k] += delta;
1979079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    }
1980079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (!q)
1981079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      func_table[i] = fj;
1982079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    funcbufleft -= delta;
1983079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		} else {			/* allocate a larger buffer */
1984079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    sz = 256;
1985079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    while (sz < funcbufsize - funcbufleft + delta)
1986079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      sz <<= 1;
1987079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    fnw = kmalloc(sz, GFP_KERNEL);
1988079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if(!fnw) {
1989079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      ret = -ENOMEM;
1990079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      goto reterr;
1991079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    }
1992079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
1993079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (!q)
1994079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      func_table[i] = fj;
1995079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (fj > funcbufptr)
1996079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			memmove(fnw, funcbufptr, fj - funcbufptr);
1997079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    for (k = 0; k < j; k++)
1998079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      if (func_table[k])
1999079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			func_table[k] = fnw + (func_table[k] - funcbufptr);
2000079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2001079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (first_free > fj) {
2002079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
2003079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			for (k = j; k < MAX_NR_FUNC; k++)
2004079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			  if (func_table[k])
2005079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			    func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
2006079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    }
2007079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    if (funcbufptr != func_buf)
2008079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		      kfree(funcbufptr);
2009079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    funcbufptr = fnw;
2010079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    funcbufleft = funcbufleft - delta + sz - funcbufsize;
2011079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		    funcbufsize = sz;
2012079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		}
2013079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		strcpy(func_table[i], kbs->kb_string);
2014079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		break;
2015079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
2016079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	ret = 0;
2017079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxreterr:
2018079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kfree(kbs);
2019079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return ret;
2020079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2021079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2022079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
2023079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2024079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2025079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        unsigned long flags;
2026079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned char ucval;
2027079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2028079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        switch(cmd) {
2029079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* the ioctls below read/set the flags usually shown in the leds */
2030079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* don't use them - they will go away without warning */
2031079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDGKBLED:
2032079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox                spin_lock_irqsave(&kbd_event_lock, flags);
2033079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
2034079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox                spin_unlock_irqrestore(&kbd_event_lock, flags);
2035079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return put_user(ucval, (char __user *)arg);
2036079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2037079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDSKBLED:
2038079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!perm)
2039079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EPERM;
2040079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (arg & ~0x77)
2041079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EINVAL;
2042079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox                spin_lock_irqsave(&kbd_event_lock, flags);
2043079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->ledflagstate = (arg & 7);
2044079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		kbd->default_ledflagstate = ((arg >> 4) & 7);
2045079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		set_leds();
2046079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox                spin_unlock_irqrestore(&kbd_event_lock, flags);
2047eea41aee2bfad4cf5c84e1cab8aa068c66206651Alan Cox		return 0;
2048079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2049079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* the ioctls below only set the lights, not the functions */
2050079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* for those, see KDGKBLED and KDSKBLED above */
2051079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDGETLED:
2052079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		ucval = getledstate();
2053079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return put_user(ucval, (char __user *)arg);
2054079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2055079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case KDSETLED:
2056079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		if (!perm)
2057079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox			return -EPERM;
2058079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		setledstate(kbd, arg);
2059079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return 0;
2060079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        }
2061079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        return -ENOIOCTLCMD;
2062079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2063079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2064079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdgkbmode(int console)
2065079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2066079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2067079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* This is a spot read so needs no locking */
2068079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	switch (kbd->kbdmode) {
2069079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case VC_RAW:
2070079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return K_RAW;
2071079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case VC_MEDIUMRAW:
2072079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return K_MEDIUMRAW;
2073079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case VC_UNICODE:
2074079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return K_UNICODE;
2075079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	case VC_OFF:
2076079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return K_OFF;
2077079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	default:
2078079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox		return K_XLATE;
2079079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	}
2080079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2081079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2082079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2083079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_do_kdgkbmeta		-	report meta status
2084079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to report
2085079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2086079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Report the meta flag status of this console
2087079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2088079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_do_kdgkbmeta(int console)
2089079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2090079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2091079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        /* Again a spot read so no locking */
2092079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT;
2093079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2094079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2095079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2096079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_reset_unicode	-	reset the unicode status
2097079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console being reset
2098079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2099079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Restore the unicode console state to its default
2100079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2101079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_reset_unicode(int console)
2102079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2103079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
2104079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2105079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
2106079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbd_table[console].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
2107079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
2108079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2109079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2110079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2111079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_get_shiftstate	-	shift bit state
2112079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2113079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Report the shift bits from the keyboard state. We have to export
2114079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	this to support some oddities in the vt layer.
2115079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2116079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_get_shift_state(void)
2117079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2118079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        /* Don't lock as this is a transient report */
2119079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox        return shift_state;
2120079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2121079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2122079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2123079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_reset_keyboard	-	reset keyboard state
2124079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to reset
2125079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2126079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Reset the keyboard bits for a console as part of a general console
2127079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	reset event
2128079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2129079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_reset_keyboard(int console)
2130079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2131079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2132079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
2133079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2134079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
2135079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	set_vc_kbd_mode(kbd, VC_REPEAT);
2136079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	clr_vc_kbd_mode(kbd, VC_CKMODE);
2137079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	clr_vc_kbd_mode(kbd, VC_APPLIC);
2138079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	clr_vc_kbd_mode(kbd, VC_CRLF);
2139079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbd->lockstate = 0;
2140079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbd->slockstate = 0;
2141079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbd->ledmode = LED_SHOW_FLAGS;
2142079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	kbd->ledflagstate = kbd->default_ledflagstate;
2143079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	/* do not do set_leds here because this causes an endless tasklet loop
2144079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	   when the keyboard hasn't been initialized yet */
2145079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
2146079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2147079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2148079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2149079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_get_kbd_mode_bit	-	read keyboard status bits
2150079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to read from
2151079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@bit: mode bit to read
2152079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2153079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Report back a vt mode bit. We do this without locking so the
2154079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	caller must be sure that there are no synchronization needs
2155079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2156079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2157079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxint vt_get_kbd_mode_bit(int console, int bit)
2158079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2159079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2160079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	return vc_kbd_mode(kbd, bit);
2161079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2162079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2163079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2164079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_set_kbd_mode_bit	-	read keyboard status bits
2165079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to read from
2166079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@bit: mode bit to read
2167079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2168079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Set a vt mode bit. We do this without locking so the
2169079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	caller must be sure that there are no synchronization needs
2170079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2171079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2172079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_set_kbd_mode_bit(int console, int bit)
2173079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2174079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2175079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
2176079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2177079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
2178079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	set_vc_kbd_mode(kbd, bit);
2179079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
2180079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2181079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2182079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox/**
2183079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	vt_clr_kbd_mode_bit	-	read keyboard status bits
2184079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@console: console to read from
2185079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	@bit: mode bit to read
2186079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *
2187079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	Report back a vt mode bit. We do this without locking so the
2188079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox *	caller must be sure that there are no synchronization needs
2189079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox */
2190079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2191079c9534a96da9a85a2a2f9715851050fbfbf749Alan Coxvoid vt_clr_kbd_mode_bit(int console, int bit)
2192079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox{
2193079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	struct kbd_struct * kbd = kbd_table + console;
2194079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	unsigned long flags;
2195079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox
2196079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_lock_irqsave(&kbd_event_lock, flags);
2197079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	clr_vc_kbd_mode(kbd, bit);
2198079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox	spin_unlock_irqrestore(&kbd_event_lock, flags);
2199079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox}
2200