xref: /OK3568_Linux_fs/kernel/drivers/tty/vt/keyboard.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Written for linux by Johan Myreen as a translation from
4*4882a593Smuzhiyun  * the assembly version by Linus (with diacriticals added)
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Some additional features added by Christoph Niemann (ChN), March 1993
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Loadable keymaps by Risto Kankkunen, May 1993
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
11*4882a593Smuzhiyun  * Added decr/incr_console, dynamic keymaps, Unicode support,
12*4882a593Smuzhiyun  * dynamic function/string keys, led setting,  Sept 1994
13*4882a593Smuzhiyun  * `Sticky' modifier keys, 951006.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * 11-11-96: SAK should now work in the raw mode (Martin Mares)
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * Modified to provide 'generic' keyboard support by Hamish Macdonald
18*4882a593Smuzhiyun  * Merge with the m68k keyboard driver and split-off of the PC low-level
19*4882a593Smuzhiyun  * parts by Geert Uytterhoeven, May 1997
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
22*4882a593Smuzhiyun  * 30-07-98: Dead keys redone, aeb@cwi.nl.
23*4882a593Smuzhiyun  * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
24*4882a593Smuzhiyun  */
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #include <linux/consolemap.h>
29*4882a593Smuzhiyun #include <linux/module.h>
30*4882a593Smuzhiyun #include <linux/sched/signal.h>
31*4882a593Smuzhiyun #include <linux/sched/debug.h>
32*4882a593Smuzhiyun #include <linux/tty.h>
33*4882a593Smuzhiyun #include <linux/tty_flip.h>
34*4882a593Smuzhiyun #include <linux/mm.h>
35*4882a593Smuzhiyun #include <linux/nospec.h>
36*4882a593Smuzhiyun #include <linux/string.h>
37*4882a593Smuzhiyun #include <linux/init.h>
38*4882a593Smuzhiyun #include <linux/slab.h>
39*4882a593Smuzhiyun #include <linux/leds.h>
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #include <linux/kbd_kern.h>
42*4882a593Smuzhiyun #include <linux/kbd_diacr.h>
43*4882a593Smuzhiyun #include <linux/vt_kern.h>
44*4882a593Smuzhiyun #include <linux/input.h>
45*4882a593Smuzhiyun #include <linux/reboot.h>
46*4882a593Smuzhiyun #include <linux/notifier.h>
47*4882a593Smuzhiyun #include <linux/jiffies.h>
48*4882a593Smuzhiyun #include <linux/uaccess.h>
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #include <asm/irq_regs.h>
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun extern void ctrl_alt_del(void);
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /*
55*4882a593Smuzhiyun  * Exported functions/variables
56*4882a593Smuzhiyun  */
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun #define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun #if defined(CONFIG_X86) || defined(CONFIG_PARISC)
61*4882a593Smuzhiyun #include <asm/kbdleds.h>
62*4882a593Smuzhiyun #else
kbd_defleds(void)63*4882a593Smuzhiyun static inline int kbd_defleds(void)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	return 0;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun #endif
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun #define KBD_DEFLOCK 0
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun /*
72*4882a593Smuzhiyun  * Handler Tables.
73*4882a593Smuzhiyun  */
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun #define K_HANDLERS\
76*4882a593Smuzhiyun 	k_self,		k_fn,		k_spec,		k_pad,\
77*4882a593Smuzhiyun 	k_dead,		k_cons,		k_cur,		k_shift,\
78*4882a593Smuzhiyun 	k_meta,		k_ascii,	k_lock,		k_lowercase,\
79*4882a593Smuzhiyun 	k_slock,	k_dead2,	k_brl,		k_ignore
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
82*4882a593Smuzhiyun 			    char up_flag);
83*4882a593Smuzhiyun static k_handler_fn K_HANDLERS;
84*4882a593Smuzhiyun static k_handler_fn *k_handler[16] = { K_HANDLERS };
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun #define FN_HANDLERS\
87*4882a593Smuzhiyun 	fn_null,	fn_enter,	fn_show_ptregs,	fn_show_mem,\
88*4882a593Smuzhiyun 	fn_show_state,	fn_send_intr,	fn_lastcons,	fn_caps_toggle,\
89*4882a593Smuzhiyun 	fn_num,		fn_hold,	fn_scroll_forw,	fn_scroll_back,\
90*4882a593Smuzhiyun 	fn_boot_it,	fn_caps_on,	fn_compose,	fn_SAK,\
91*4882a593Smuzhiyun 	fn_dec_console, fn_inc_console, fn_spawn_con,	fn_bare_num
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun typedef void (fn_handler_fn)(struct vc_data *vc);
94*4882a593Smuzhiyun static fn_handler_fn FN_HANDLERS;
95*4882a593Smuzhiyun static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun /*
98*4882a593Smuzhiyun  * Variables exported for vt_ioctl.c
99*4882a593Smuzhiyun  */
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun struct vt_spawn_console vt_spawn_con = {
102*4882a593Smuzhiyun 	.lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
103*4882a593Smuzhiyun 	.pid  = NULL,
104*4882a593Smuzhiyun 	.sig  = 0,
105*4882a593Smuzhiyun };
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun /*
109*4882a593Smuzhiyun  * Internal Data.
110*4882a593Smuzhiyun  */
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun static struct kbd_struct kbd_table[MAX_NR_CONSOLES];
113*4882a593Smuzhiyun static struct kbd_struct *kbd = kbd_table;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun /* maximum values each key_handler can handle */
116*4882a593Smuzhiyun static const int max_vals[] = {
117*4882a593Smuzhiyun 	255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
118*4882a593Smuzhiyun 	NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
119*4882a593Smuzhiyun 	255, NR_LOCK - 1, 255, NR_BRL - 1
120*4882a593Smuzhiyun };
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun static const int NR_TYPES = ARRAY_SIZE(max_vals);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun static struct input_handler kbd_handler;
125*4882a593Smuzhiyun static DEFINE_SPINLOCK(kbd_event_lock);
126*4882a593Smuzhiyun static DEFINE_SPINLOCK(led_lock);
127*4882a593Smuzhiyun static DEFINE_SPINLOCK(func_buf_lock); /* guard 'func_buf'  and friends */
128*4882a593Smuzhiyun static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];	/* keyboard key bitmap */
129*4882a593Smuzhiyun static unsigned char shift_down[NR_SHIFT];		/* shift state counters.. */
130*4882a593Smuzhiyun static bool dead_key_next;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun /* Handles a number being assembled on the number pad */
133*4882a593Smuzhiyun static bool npadch_active;
134*4882a593Smuzhiyun static unsigned int npadch_value;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun static unsigned int diacr;
137*4882a593Smuzhiyun static char rep;					/* flag telling character repeat */
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun static int shift_state = 0;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun static unsigned int ledstate = -1U;			/* undefined */
142*4882a593Smuzhiyun static unsigned char ledioctl;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun /*
145*4882a593Smuzhiyun  * Notifier list for console keyboard events
146*4882a593Smuzhiyun  */
147*4882a593Smuzhiyun static ATOMIC_NOTIFIER_HEAD(keyboard_notifier_list);
148*4882a593Smuzhiyun 
register_keyboard_notifier(struct notifier_block * nb)149*4882a593Smuzhiyun int register_keyboard_notifier(struct notifier_block *nb)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	return atomic_notifier_chain_register(&keyboard_notifier_list, nb);
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(register_keyboard_notifier);
154*4882a593Smuzhiyun 
unregister_keyboard_notifier(struct notifier_block * nb)155*4882a593Smuzhiyun int unregister_keyboard_notifier(struct notifier_block *nb)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	return atomic_notifier_chain_unregister(&keyboard_notifier_list, nb);
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun /*
162*4882a593Smuzhiyun  * Translation of scancodes to keycodes. We set them on only the first
163*4882a593Smuzhiyun  * keyboard in the list that accepts the scancode and keycode.
164*4882a593Smuzhiyun  * Explanation for not choosing the first attached keyboard anymore:
165*4882a593Smuzhiyun  *  USB keyboards for example have two event devices: one for all "normal"
166*4882a593Smuzhiyun  *  keys and one for extra function keys (like "volume up", "make coffee",
167*4882a593Smuzhiyun  *  etc.). So this means that scancodes for the extra function keys won't
168*4882a593Smuzhiyun  *  be valid for the first event device, but will be for the second.
169*4882a593Smuzhiyun  */
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun struct getset_keycode_data {
172*4882a593Smuzhiyun 	struct input_keymap_entry ke;
173*4882a593Smuzhiyun 	int error;
174*4882a593Smuzhiyun };
175*4882a593Smuzhiyun 
getkeycode_helper(struct input_handle * handle,void * data)176*4882a593Smuzhiyun static int getkeycode_helper(struct input_handle *handle, void *data)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	struct getset_keycode_data *d = data;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	d->error = input_get_keycode(handle->dev, &d->ke);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	return d->error == 0; /* stop as soon as we successfully get one */
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
getkeycode(unsigned int scancode)185*4882a593Smuzhiyun static int getkeycode(unsigned int scancode)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun 	struct getset_keycode_data d = {
188*4882a593Smuzhiyun 		.ke	= {
189*4882a593Smuzhiyun 			.flags		= 0,
190*4882a593Smuzhiyun 			.len		= sizeof(scancode),
191*4882a593Smuzhiyun 			.keycode	= 0,
192*4882a593Smuzhiyun 		},
193*4882a593Smuzhiyun 		.error	= -ENODEV,
194*4882a593Smuzhiyun 	};
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	memcpy(d.ke.scancode, &scancode, sizeof(scancode));
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	return d.error ?: d.ke.keycode;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
setkeycode_helper(struct input_handle * handle,void * data)203*4882a593Smuzhiyun static int setkeycode_helper(struct input_handle *handle, void *data)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun 	struct getset_keycode_data *d = data;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	d->error = input_set_keycode(handle->dev, &d->ke);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	return d->error == 0; /* stop as soon as we successfully set one */
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
setkeycode(unsigned int scancode,unsigned int keycode)212*4882a593Smuzhiyun static int setkeycode(unsigned int scancode, unsigned int keycode)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	struct getset_keycode_data d = {
215*4882a593Smuzhiyun 		.ke	= {
216*4882a593Smuzhiyun 			.flags		= 0,
217*4882a593Smuzhiyun 			.len		= sizeof(scancode),
218*4882a593Smuzhiyun 			.keycode	= keycode,
219*4882a593Smuzhiyun 		},
220*4882a593Smuzhiyun 		.error	= -ENODEV,
221*4882a593Smuzhiyun 	};
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	memcpy(d.ke.scancode, &scancode, sizeof(scancode));
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	return d.error;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun /*
231*4882a593Smuzhiyun  * Making beeps and bells. Note that we prefer beeps to bells, but when
232*4882a593Smuzhiyun  * shutting the sound off we do both.
233*4882a593Smuzhiyun  */
234*4882a593Smuzhiyun 
kd_sound_helper(struct input_handle * handle,void * data)235*4882a593Smuzhiyun static int kd_sound_helper(struct input_handle *handle, void *data)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	unsigned int *hz = data;
238*4882a593Smuzhiyun 	struct input_dev *dev = handle->dev;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	if (test_bit(EV_SND, dev->evbit)) {
241*4882a593Smuzhiyun 		if (test_bit(SND_TONE, dev->sndbit)) {
242*4882a593Smuzhiyun 			input_inject_event(handle, EV_SND, SND_TONE, *hz);
243*4882a593Smuzhiyun 			if (*hz)
244*4882a593Smuzhiyun 				return 0;
245*4882a593Smuzhiyun 		}
246*4882a593Smuzhiyun 		if (test_bit(SND_BELL, dev->sndbit))
247*4882a593Smuzhiyun 			input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0);
248*4882a593Smuzhiyun 	}
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	return 0;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
kd_nosound(struct timer_list * unused)253*4882a593Smuzhiyun static void kd_nosound(struct timer_list *unused)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun 	static unsigned int zero;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	input_handler_for_each_handle(&kbd_handler, &zero, kd_sound_helper);
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun static DEFINE_TIMER(kd_mksound_timer, kd_nosound);
261*4882a593Smuzhiyun 
kd_mksound(unsigned int hz,unsigned int ticks)262*4882a593Smuzhiyun void kd_mksound(unsigned int hz, unsigned int ticks)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun 	del_timer_sync(&kd_mksound_timer);
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	input_handler_for_each_handle(&kbd_handler, &hz, kd_sound_helper);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	if (hz && ticks)
269*4882a593Smuzhiyun 		mod_timer(&kd_mksound_timer, jiffies + ticks);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun EXPORT_SYMBOL(kd_mksound);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun /*
274*4882a593Smuzhiyun  * Setting the keyboard rate.
275*4882a593Smuzhiyun  */
276*4882a593Smuzhiyun 
kbd_rate_helper(struct input_handle * handle,void * data)277*4882a593Smuzhiyun static int kbd_rate_helper(struct input_handle *handle, void *data)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	struct input_dev *dev = handle->dev;
280*4882a593Smuzhiyun 	struct kbd_repeat *rpt = data;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	if (test_bit(EV_REP, dev->evbit)) {
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 		if (rpt[0].delay > 0)
285*4882a593Smuzhiyun 			input_inject_event(handle,
286*4882a593Smuzhiyun 					   EV_REP, REP_DELAY, rpt[0].delay);
287*4882a593Smuzhiyun 		if (rpt[0].period > 0)
288*4882a593Smuzhiyun 			input_inject_event(handle,
289*4882a593Smuzhiyun 					   EV_REP, REP_PERIOD, rpt[0].period);
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 		rpt[1].delay = dev->rep[REP_DELAY];
292*4882a593Smuzhiyun 		rpt[1].period = dev->rep[REP_PERIOD];
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	return 0;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun 
kbd_rate(struct kbd_repeat * rpt)298*4882a593Smuzhiyun int kbd_rate(struct kbd_repeat *rpt)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun 	struct kbd_repeat data[2] = { *rpt };
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	input_handler_for_each_handle(&kbd_handler, data, kbd_rate_helper);
303*4882a593Smuzhiyun 	*rpt = data[1];	/* Copy currently used settings */
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	return 0;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun /*
309*4882a593Smuzhiyun  * Helper Functions.
310*4882a593Smuzhiyun  */
put_queue(struct vc_data * vc,int ch)311*4882a593Smuzhiyun static void put_queue(struct vc_data *vc, int ch)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun 	tty_insert_flip_char(&vc->port, ch, 0);
314*4882a593Smuzhiyun 	tty_flip_buffer_push(&vc->port);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun 
puts_queue(struct vc_data * vc,char * cp)317*4882a593Smuzhiyun static void puts_queue(struct vc_data *vc, char *cp)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	while (*cp) {
320*4882a593Smuzhiyun 		tty_insert_flip_char(&vc->port, *cp, 0);
321*4882a593Smuzhiyun 		cp++;
322*4882a593Smuzhiyun 	}
323*4882a593Smuzhiyun 	tty_flip_buffer_push(&vc->port);
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun 
applkey(struct vc_data * vc,int key,char mode)326*4882a593Smuzhiyun static void applkey(struct vc_data *vc, int key, char mode)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun 	static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	buf[1] = (mode ? 'O' : '[');
331*4882a593Smuzhiyun 	buf[2] = key;
332*4882a593Smuzhiyun 	puts_queue(vc, buf);
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun /*
336*4882a593Smuzhiyun  * Many other routines do put_queue, but I think either
337*4882a593Smuzhiyun  * they produce ASCII, or they produce some user-assigned
338*4882a593Smuzhiyun  * string, and in both cases we might assume that it is
339*4882a593Smuzhiyun  * in utf-8 already.
340*4882a593Smuzhiyun  */
to_utf8(struct vc_data * vc,uint c)341*4882a593Smuzhiyun static void to_utf8(struct vc_data *vc, uint c)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun 	if (c < 0x80)
344*4882a593Smuzhiyun 		/*  0******* */
345*4882a593Smuzhiyun 		put_queue(vc, c);
346*4882a593Smuzhiyun 	else if (c < 0x800) {
347*4882a593Smuzhiyun 		/* 110***** 10****** */
348*4882a593Smuzhiyun 		put_queue(vc, 0xc0 | (c >> 6));
349*4882a593Smuzhiyun 		put_queue(vc, 0x80 | (c & 0x3f));
350*4882a593Smuzhiyun 	} else if (c < 0x10000) {
351*4882a593Smuzhiyun 		if (c >= 0xD800 && c < 0xE000)
352*4882a593Smuzhiyun 			return;
353*4882a593Smuzhiyun 		if (c == 0xFFFF)
354*4882a593Smuzhiyun 			return;
355*4882a593Smuzhiyun 		/* 1110**** 10****** 10****** */
356*4882a593Smuzhiyun 		put_queue(vc, 0xe0 | (c >> 12));
357*4882a593Smuzhiyun 		put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
358*4882a593Smuzhiyun 		put_queue(vc, 0x80 | (c & 0x3f));
359*4882a593Smuzhiyun 	} else if (c < 0x110000) {
360*4882a593Smuzhiyun 		/* 11110*** 10****** 10****** 10****** */
361*4882a593Smuzhiyun 		put_queue(vc, 0xf0 | (c >> 18));
362*4882a593Smuzhiyun 		put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
363*4882a593Smuzhiyun 		put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
364*4882a593Smuzhiyun 		put_queue(vc, 0x80 | (c & 0x3f));
365*4882a593Smuzhiyun 	}
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun /*
369*4882a593Smuzhiyun  * Called after returning from RAW mode or when changing consoles - recompute
370*4882a593Smuzhiyun  * shift_down[] and shift_state from key_down[] maybe called when keymap is
371*4882a593Smuzhiyun  * undefined, so that shiftkey release is seen. The caller must hold the
372*4882a593Smuzhiyun  * kbd_event_lock.
373*4882a593Smuzhiyun  */
374*4882a593Smuzhiyun 
do_compute_shiftstate(void)375*4882a593Smuzhiyun static void do_compute_shiftstate(void)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun 	unsigned int k, sym, val;
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	shift_state = 0;
380*4882a593Smuzhiyun 	memset(shift_down, 0, sizeof(shift_down));
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	for_each_set_bit(k, key_down, min(NR_KEYS, KEY_CNT)) {
383*4882a593Smuzhiyun 		sym = U(key_maps[0][k]);
384*4882a593Smuzhiyun 		if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
385*4882a593Smuzhiyun 			continue;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 		val = KVAL(sym);
388*4882a593Smuzhiyun 		if (val == KVAL(K_CAPSSHIFT))
389*4882a593Smuzhiyun 			val = KVAL(K_SHIFT);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 		shift_down[val]++;
392*4882a593Smuzhiyun 		shift_state |= BIT(val);
393*4882a593Smuzhiyun 	}
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun /* We still have to export this method to vt.c */
compute_shiftstate(void)397*4882a593Smuzhiyun void compute_shiftstate(void)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun 	unsigned long flags;
400*4882a593Smuzhiyun 	spin_lock_irqsave(&kbd_event_lock, flags);
401*4882a593Smuzhiyun 	do_compute_shiftstate();
402*4882a593Smuzhiyun 	spin_unlock_irqrestore(&kbd_event_lock, flags);
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun /*
406*4882a593Smuzhiyun  * We have a combining character DIACR here, followed by the character CH.
407*4882a593Smuzhiyun  * If the combination occurs in the table, return the corresponding value.
408*4882a593Smuzhiyun  * Otherwise, if CH is a space or equals DIACR, return DIACR.
409*4882a593Smuzhiyun  * Otherwise, conclude that DIACR was not combining after all,
410*4882a593Smuzhiyun  * queue it and return CH.
411*4882a593Smuzhiyun  */
handle_diacr(struct vc_data * vc,unsigned int ch)412*4882a593Smuzhiyun static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun 	unsigned int d = diacr;
415*4882a593Smuzhiyun 	unsigned int i;
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	diacr = 0;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	if ((d & ~0xff) == BRL_UC_ROW) {
420*4882a593Smuzhiyun 		if ((ch & ~0xff) == BRL_UC_ROW)
421*4882a593Smuzhiyun 			return d | ch;
422*4882a593Smuzhiyun 	} else {
423*4882a593Smuzhiyun 		for (i = 0; i < accent_table_size; i++)
424*4882a593Smuzhiyun 			if (accent_table[i].diacr == d && accent_table[i].base == ch)
425*4882a593Smuzhiyun 				return accent_table[i].result;
426*4882a593Smuzhiyun 	}
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
429*4882a593Smuzhiyun 		return d;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	if (kbd->kbdmode == VC_UNICODE)
432*4882a593Smuzhiyun 		to_utf8(vc, d);
433*4882a593Smuzhiyun 	else {
434*4882a593Smuzhiyun 		int c = conv_uni_to_8bit(d);
435*4882a593Smuzhiyun 		if (c != -1)
436*4882a593Smuzhiyun 			put_queue(vc, c);
437*4882a593Smuzhiyun 	}
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	return ch;
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun /*
443*4882a593Smuzhiyun  * Special function handlers
444*4882a593Smuzhiyun  */
fn_enter(struct vc_data * vc)445*4882a593Smuzhiyun static void fn_enter(struct vc_data *vc)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun 	if (diacr) {
448*4882a593Smuzhiyun 		if (kbd->kbdmode == VC_UNICODE)
449*4882a593Smuzhiyun 			to_utf8(vc, diacr);
450*4882a593Smuzhiyun 		else {
451*4882a593Smuzhiyun 			int c = conv_uni_to_8bit(diacr);
452*4882a593Smuzhiyun 			if (c != -1)
453*4882a593Smuzhiyun 				put_queue(vc, c);
454*4882a593Smuzhiyun 		}
455*4882a593Smuzhiyun 		diacr = 0;
456*4882a593Smuzhiyun 	}
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	put_queue(vc, 13);
459*4882a593Smuzhiyun 	if (vc_kbd_mode(kbd, VC_CRLF))
460*4882a593Smuzhiyun 		put_queue(vc, 10);
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun 
fn_caps_toggle(struct vc_data * vc)463*4882a593Smuzhiyun static void fn_caps_toggle(struct vc_data *vc)
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun 	if (rep)
466*4882a593Smuzhiyun 		return;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	chg_vc_kbd_led(kbd, VC_CAPSLOCK);
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
fn_caps_on(struct vc_data * vc)471*4882a593Smuzhiyun static void fn_caps_on(struct vc_data *vc)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	if (rep)
474*4882a593Smuzhiyun 		return;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	set_vc_kbd_led(kbd, VC_CAPSLOCK);
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun 
fn_show_ptregs(struct vc_data * vc)479*4882a593Smuzhiyun static void fn_show_ptregs(struct vc_data *vc)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun 	struct pt_regs *regs = get_irq_regs();
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	if (regs)
484*4882a593Smuzhiyun 		show_regs(regs);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun 
fn_hold(struct vc_data * vc)487*4882a593Smuzhiyun static void fn_hold(struct vc_data *vc)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun 	struct tty_struct *tty = vc->port.tty;
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	if (rep || !tty)
492*4882a593Smuzhiyun 		return;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	/*
495*4882a593Smuzhiyun 	 * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
496*4882a593Smuzhiyun 	 * these routines are also activated by ^S/^Q.
497*4882a593Smuzhiyun 	 * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
498*4882a593Smuzhiyun 	 */
499*4882a593Smuzhiyun 	if (tty->stopped)
500*4882a593Smuzhiyun 		start_tty(tty);
501*4882a593Smuzhiyun 	else
502*4882a593Smuzhiyun 		stop_tty(tty);
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun 
fn_num(struct vc_data * vc)505*4882a593Smuzhiyun static void fn_num(struct vc_data *vc)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun 	if (vc_kbd_mode(kbd, VC_APPLIC))
508*4882a593Smuzhiyun 		applkey(vc, 'P', 1);
509*4882a593Smuzhiyun 	else
510*4882a593Smuzhiyun 		fn_bare_num(vc);
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun /*
514*4882a593Smuzhiyun  * Bind this to Shift-NumLock if you work in application keypad mode
515*4882a593Smuzhiyun  * but want to be able to change the NumLock flag.
516*4882a593Smuzhiyun  * Bind this to NumLock if you prefer that the NumLock key always
517*4882a593Smuzhiyun  * changes the NumLock flag.
518*4882a593Smuzhiyun  */
fn_bare_num(struct vc_data * vc)519*4882a593Smuzhiyun static void fn_bare_num(struct vc_data *vc)
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun 	if (!rep)
522*4882a593Smuzhiyun 		chg_vc_kbd_led(kbd, VC_NUMLOCK);
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun 
fn_lastcons(struct vc_data * vc)525*4882a593Smuzhiyun static void fn_lastcons(struct vc_data *vc)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun 	/* switch to the last used console, ChN */
528*4882a593Smuzhiyun 	set_console(last_console);
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun 
fn_dec_console(struct vc_data * vc)531*4882a593Smuzhiyun static void fn_dec_console(struct vc_data *vc)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun 	int i, cur = fg_console;
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	/* Currently switching?  Queue this next switch relative to that. */
536*4882a593Smuzhiyun 	if (want_console != -1)
537*4882a593Smuzhiyun 		cur = want_console;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	for (i = cur - 1; i != cur; i--) {
540*4882a593Smuzhiyun 		if (i == -1)
541*4882a593Smuzhiyun 			i = MAX_NR_CONSOLES - 1;
542*4882a593Smuzhiyun 		if (vc_cons_allocated(i))
543*4882a593Smuzhiyun 			break;
544*4882a593Smuzhiyun 	}
545*4882a593Smuzhiyun 	set_console(i);
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun 
fn_inc_console(struct vc_data * vc)548*4882a593Smuzhiyun static void fn_inc_console(struct vc_data *vc)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun 	int i, cur = fg_console;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	/* Currently switching?  Queue this next switch relative to that. */
553*4882a593Smuzhiyun 	if (want_console != -1)
554*4882a593Smuzhiyun 		cur = want_console;
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 	for (i = cur+1; i != cur; i++) {
557*4882a593Smuzhiyun 		if (i == MAX_NR_CONSOLES)
558*4882a593Smuzhiyun 			i = 0;
559*4882a593Smuzhiyun 		if (vc_cons_allocated(i))
560*4882a593Smuzhiyun 			break;
561*4882a593Smuzhiyun 	}
562*4882a593Smuzhiyun 	set_console(i);
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun 
fn_send_intr(struct vc_data * vc)565*4882a593Smuzhiyun static void fn_send_intr(struct vc_data *vc)
566*4882a593Smuzhiyun {
567*4882a593Smuzhiyun 	tty_insert_flip_char(&vc->port, 0, TTY_BREAK);
568*4882a593Smuzhiyun 	tty_flip_buffer_push(&vc->port);
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun 
fn_scroll_forw(struct vc_data * vc)571*4882a593Smuzhiyun static void fn_scroll_forw(struct vc_data *vc)
572*4882a593Smuzhiyun {
573*4882a593Smuzhiyun 	scrollfront(vc, 0);
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun 
fn_scroll_back(struct vc_data * vc)576*4882a593Smuzhiyun static void fn_scroll_back(struct vc_data *vc)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun 	scrollback(vc);
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun 
fn_show_mem(struct vc_data * vc)581*4882a593Smuzhiyun static void fn_show_mem(struct vc_data *vc)
582*4882a593Smuzhiyun {
583*4882a593Smuzhiyun 	show_mem(0, NULL);
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun 
fn_show_state(struct vc_data * vc)586*4882a593Smuzhiyun static void fn_show_state(struct vc_data *vc)
587*4882a593Smuzhiyun {
588*4882a593Smuzhiyun 	show_state();
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun 
fn_boot_it(struct vc_data * vc)591*4882a593Smuzhiyun static void fn_boot_it(struct vc_data *vc)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun 	ctrl_alt_del();
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun 
fn_compose(struct vc_data * vc)596*4882a593Smuzhiyun static void fn_compose(struct vc_data *vc)
597*4882a593Smuzhiyun {
598*4882a593Smuzhiyun 	dead_key_next = true;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun 
fn_spawn_con(struct vc_data * vc)601*4882a593Smuzhiyun static void fn_spawn_con(struct vc_data *vc)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun 	spin_lock(&vt_spawn_con.lock);
604*4882a593Smuzhiyun 	if (vt_spawn_con.pid)
605*4882a593Smuzhiyun 		if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
606*4882a593Smuzhiyun 			put_pid(vt_spawn_con.pid);
607*4882a593Smuzhiyun 			vt_spawn_con.pid = NULL;
608*4882a593Smuzhiyun 		}
609*4882a593Smuzhiyun 	spin_unlock(&vt_spawn_con.lock);
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun 
fn_SAK(struct vc_data * vc)612*4882a593Smuzhiyun static void fn_SAK(struct vc_data *vc)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun 	struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
615*4882a593Smuzhiyun 	schedule_work(SAK_work);
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun 
fn_null(struct vc_data * vc)618*4882a593Smuzhiyun static void fn_null(struct vc_data *vc)
619*4882a593Smuzhiyun {
620*4882a593Smuzhiyun 	do_compute_shiftstate();
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun /*
624*4882a593Smuzhiyun  * Special key handlers
625*4882a593Smuzhiyun  */
k_ignore(struct vc_data * vc,unsigned char value,char up_flag)626*4882a593Smuzhiyun static void k_ignore(struct vc_data *vc, unsigned char value, char up_flag)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun 
k_spec(struct vc_data * vc,unsigned char value,char up_flag)630*4882a593Smuzhiyun static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
631*4882a593Smuzhiyun {
632*4882a593Smuzhiyun 	if (up_flag)
633*4882a593Smuzhiyun 		return;
634*4882a593Smuzhiyun 	if (value >= ARRAY_SIZE(fn_handler))
635*4882a593Smuzhiyun 		return;
636*4882a593Smuzhiyun 	if ((kbd->kbdmode == VC_RAW ||
637*4882a593Smuzhiyun 	     kbd->kbdmode == VC_MEDIUMRAW ||
638*4882a593Smuzhiyun 	     kbd->kbdmode == VC_OFF) &&
639*4882a593Smuzhiyun 	     value != KVAL(K_SAK))
640*4882a593Smuzhiyun 		return;		/* SAK is allowed even in raw mode */
641*4882a593Smuzhiyun 	fn_handler[value](vc);
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun 
k_lowercase(struct vc_data * vc,unsigned char value,char up_flag)644*4882a593Smuzhiyun static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
645*4882a593Smuzhiyun {
646*4882a593Smuzhiyun 	pr_err("k_lowercase was called - impossible\n");
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun 
k_unicode(struct vc_data * vc,unsigned int value,char up_flag)649*4882a593Smuzhiyun static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
650*4882a593Smuzhiyun {
651*4882a593Smuzhiyun 	if (up_flag)
652*4882a593Smuzhiyun 		return;		/* no action, if this is a key release */
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 	if (diacr)
655*4882a593Smuzhiyun 		value = handle_diacr(vc, value);
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	if (dead_key_next) {
658*4882a593Smuzhiyun 		dead_key_next = false;
659*4882a593Smuzhiyun 		diacr = value;
660*4882a593Smuzhiyun 		return;
661*4882a593Smuzhiyun 	}
662*4882a593Smuzhiyun 	if (kbd->kbdmode == VC_UNICODE)
663*4882a593Smuzhiyun 		to_utf8(vc, value);
664*4882a593Smuzhiyun 	else {
665*4882a593Smuzhiyun 		int c = conv_uni_to_8bit(value);
666*4882a593Smuzhiyun 		if (c != -1)
667*4882a593Smuzhiyun 			put_queue(vc, c);
668*4882a593Smuzhiyun 	}
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun /*
672*4882a593Smuzhiyun  * Handle dead key. Note that we now may have several
673*4882a593Smuzhiyun  * dead keys modifying the same character. Very useful
674*4882a593Smuzhiyun  * for Vietnamese.
675*4882a593Smuzhiyun  */
k_deadunicode(struct vc_data * vc,unsigned int value,char up_flag)676*4882a593Smuzhiyun static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
677*4882a593Smuzhiyun {
678*4882a593Smuzhiyun 	if (up_flag)
679*4882a593Smuzhiyun 		return;
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun 	diacr = (diacr ? handle_diacr(vc, value) : value);
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun 
k_self(struct vc_data * vc,unsigned char value,char up_flag)684*4882a593Smuzhiyun static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
685*4882a593Smuzhiyun {
686*4882a593Smuzhiyun 	k_unicode(vc, conv_8bit_to_uni(value), up_flag);
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun 
k_dead2(struct vc_data * vc,unsigned char value,char up_flag)689*4882a593Smuzhiyun static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
690*4882a593Smuzhiyun {
691*4882a593Smuzhiyun 	k_deadunicode(vc, value, up_flag);
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun /*
695*4882a593Smuzhiyun  * Obsolete - for backwards compatibility only
696*4882a593Smuzhiyun  */
k_dead(struct vc_data * vc,unsigned char value,char up_flag)697*4882a593Smuzhiyun static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
698*4882a593Smuzhiyun {
699*4882a593Smuzhiyun 	static const unsigned char ret_diacr[NR_DEAD] = {
700*4882a593Smuzhiyun 		'`',	/* dead_grave */
701*4882a593Smuzhiyun 		'\'',	/* dead_acute */
702*4882a593Smuzhiyun 		'^',	/* dead_circumflex */
703*4882a593Smuzhiyun 		'~',	/* dead_tilda */
704*4882a593Smuzhiyun 		'"',	/* dead_diaeresis */
705*4882a593Smuzhiyun 		',',	/* dead_cedilla */
706*4882a593Smuzhiyun 		'_',	/* dead_macron */
707*4882a593Smuzhiyun 		'U',	/* dead_breve */
708*4882a593Smuzhiyun 		'.',	/* dead_abovedot */
709*4882a593Smuzhiyun 		'*',	/* dead_abovering */
710*4882a593Smuzhiyun 		'=',	/* dead_doubleacute */
711*4882a593Smuzhiyun 		'c',	/* dead_caron */
712*4882a593Smuzhiyun 		'k',	/* dead_ogonek */
713*4882a593Smuzhiyun 		'i',	/* dead_iota */
714*4882a593Smuzhiyun 		'#',	/* dead_voiced_sound */
715*4882a593Smuzhiyun 		'o',	/* dead_semivoiced_sound */
716*4882a593Smuzhiyun 		'!',	/* dead_belowdot */
717*4882a593Smuzhiyun 		'?',	/* dead_hook */
718*4882a593Smuzhiyun 		'+',	/* dead_horn */
719*4882a593Smuzhiyun 		'-',	/* dead_stroke */
720*4882a593Smuzhiyun 		')',	/* dead_abovecomma */
721*4882a593Smuzhiyun 		'(',	/* dead_abovereversedcomma */
722*4882a593Smuzhiyun 		':',	/* dead_doublegrave */
723*4882a593Smuzhiyun 		'n',	/* dead_invertedbreve */
724*4882a593Smuzhiyun 		';',	/* dead_belowcomma */
725*4882a593Smuzhiyun 		'$',	/* dead_currency */
726*4882a593Smuzhiyun 		'@',	/* dead_greek */
727*4882a593Smuzhiyun 	};
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	k_deadunicode(vc, ret_diacr[value], up_flag);
730*4882a593Smuzhiyun }
731*4882a593Smuzhiyun 
k_cons(struct vc_data * vc,unsigned char value,char up_flag)732*4882a593Smuzhiyun static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
733*4882a593Smuzhiyun {
734*4882a593Smuzhiyun 	if (up_flag)
735*4882a593Smuzhiyun 		return;
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	set_console(value);
738*4882a593Smuzhiyun }
739*4882a593Smuzhiyun 
k_fn(struct vc_data * vc,unsigned char value,char up_flag)740*4882a593Smuzhiyun static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
741*4882a593Smuzhiyun {
742*4882a593Smuzhiyun 	if (up_flag)
743*4882a593Smuzhiyun 		return;
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 	if ((unsigned)value < ARRAY_SIZE(func_table)) {
746*4882a593Smuzhiyun 		unsigned long flags;
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 		spin_lock_irqsave(&func_buf_lock, flags);
749*4882a593Smuzhiyun 		if (func_table[value])
750*4882a593Smuzhiyun 			puts_queue(vc, func_table[value]);
751*4882a593Smuzhiyun 		spin_unlock_irqrestore(&func_buf_lock, flags);
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	} else
754*4882a593Smuzhiyun 		pr_err("k_fn called with value=%d\n", value);
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun 
k_cur(struct vc_data * vc,unsigned char value,char up_flag)757*4882a593Smuzhiyun static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
758*4882a593Smuzhiyun {
759*4882a593Smuzhiyun 	static const char cur_chars[] = "BDCA";
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun 	if (up_flag)
762*4882a593Smuzhiyun 		return;
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun 
k_pad(struct vc_data * vc,unsigned char value,char up_flag)767*4882a593Smuzhiyun static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
768*4882a593Smuzhiyun {
769*4882a593Smuzhiyun 	static const char pad_chars[] = "0123456789+-*/\015,.?()#";
770*4882a593Smuzhiyun 	static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	if (up_flag)
773*4882a593Smuzhiyun 		return;		/* no action, if this is a key release */
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	/* kludge... shift forces cursor/number keys */
776*4882a593Smuzhiyun 	if (vc_kbd_mode(kbd, VC_APPLIC) && !shift_down[KG_SHIFT]) {
777*4882a593Smuzhiyun 		applkey(vc, app_map[value], 1);
778*4882a593Smuzhiyun 		return;
779*4882a593Smuzhiyun 	}
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	if (!vc_kbd_led(kbd, VC_NUMLOCK)) {
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 		switch (value) {
784*4882a593Smuzhiyun 		case KVAL(K_PCOMMA):
785*4882a593Smuzhiyun 		case KVAL(K_PDOT):
786*4882a593Smuzhiyun 			k_fn(vc, KVAL(K_REMOVE), 0);
787*4882a593Smuzhiyun 			return;
788*4882a593Smuzhiyun 		case KVAL(K_P0):
789*4882a593Smuzhiyun 			k_fn(vc, KVAL(K_INSERT), 0);
790*4882a593Smuzhiyun 			return;
791*4882a593Smuzhiyun 		case KVAL(K_P1):
792*4882a593Smuzhiyun 			k_fn(vc, KVAL(K_SELECT), 0);
793*4882a593Smuzhiyun 			return;
794*4882a593Smuzhiyun 		case KVAL(K_P2):
795*4882a593Smuzhiyun 			k_cur(vc, KVAL(K_DOWN), 0);
796*4882a593Smuzhiyun 			return;
797*4882a593Smuzhiyun 		case KVAL(K_P3):
798*4882a593Smuzhiyun 			k_fn(vc, KVAL(K_PGDN), 0);
799*4882a593Smuzhiyun 			return;
800*4882a593Smuzhiyun 		case KVAL(K_P4):
801*4882a593Smuzhiyun 			k_cur(vc, KVAL(K_LEFT), 0);
802*4882a593Smuzhiyun 			return;
803*4882a593Smuzhiyun 		case KVAL(K_P6):
804*4882a593Smuzhiyun 			k_cur(vc, KVAL(K_RIGHT), 0);
805*4882a593Smuzhiyun 			return;
806*4882a593Smuzhiyun 		case KVAL(K_P7):
807*4882a593Smuzhiyun 			k_fn(vc, KVAL(K_FIND), 0);
808*4882a593Smuzhiyun 			return;
809*4882a593Smuzhiyun 		case KVAL(K_P8):
810*4882a593Smuzhiyun 			k_cur(vc, KVAL(K_UP), 0);
811*4882a593Smuzhiyun 			return;
812*4882a593Smuzhiyun 		case KVAL(K_P9):
813*4882a593Smuzhiyun 			k_fn(vc, KVAL(K_PGUP), 0);
814*4882a593Smuzhiyun 			return;
815*4882a593Smuzhiyun 		case KVAL(K_P5):
816*4882a593Smuzhiyun 			applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
817*4882a593Smuzhiyun 			return;
818*4882a593Smuzhiyun 		}
819*4882a593Smuzhiyun 	}
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun 	put_queue(vc, pad_chars[value]);
822*4882a593Smuzhiyun 	if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
823*4882a593Smuzhiyun 		put_queue(vc, 10);
824*4882a593Smuzhiyun }
825*4882a593Smuzhiyun 
k_shift(struct vc_data * vc,unsigned char value,char up_flag)826*4882a593Smuzhiyun static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
827*4882a593Smuzhiyun {
828*4882a593Smuzhiyun 	int old_state = shift_state;
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	if (rep)
831*4882a593Smuzhiyun 		return;
832*4882a593Smuzhiyun 	/*
833*4882a593Smuzhiyun 	 * Mimic typewriter:
834*4882a593Smuzhiyun 	 * a CapsShift key acts like Shift but undoes CapsLock
835*4882a593Smuzhiyun 	 */
836*4882a593Smuzhiyun 	if (value == KVAL(K_CAPSSHIFT)) {
837*4882a593Smuzhiyun 		value = KVAL(K_SHIFT);
838*4882a593Smuzhiyun 		if (!up_flag)
839*4882a593Smuzhiyun 			clr_vc_kbd_led(kbd, VC_CAPSLOCK);
840*4882a593Smuzhiyun 	}
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	if (up_flag) {
843*4882a593Smuzhiyun 		/*
844*4882a593Smuzhiyun 		 * handle the case that two shift or control
845*4882a593Smuzhiyun 		 * keys are depressed simultaneously
846*4882a593Smuzhiyun 		 */
847*4882a593Smuzhiyun 		if (shift_down[value])
848*4882a593Smuzhiyun 			shift_down[value]--;
849*4882a593Smuzhiyun 	} else
850*4882a593Smuzhiyun 		shift_down[value]++;
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 	if (shift_down[value])
853*4882a593Smuzhiyun 		shift_state |= (1 << value);
854*4882a593Smuzhiyun 	else
855*4882a593Smuzhiyun 		shift_state &= ~(1 << value);
856*4882a593Smuzhiyun 
857*4882a593Smuzhiyun 	/* kludge */
858*4882a593Smuzhiyun 	if (up_flag && shift_state != old_state && npadch_active) {
859*4882a593Smuzhiyun 		if (kbd->kbdmode == VC_UNICODE)
860*4882a593Smuzhiyun 			to_utf8(vc, npadch_value);
861*4882a593Smuzhiyun 		else
862*4882a593Smuzhiyun 			put_queue(vc, npadch_value & 0xff);
863*4882a593Smuzhiyun 		npadch_active = false;
864*4882a593Smuzhiyun 	}
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun 
k_meta(struct vc_data * vc,unsigned char value,char up_flag)867*4882a593Smuzhiyun static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
868*4882a593Smuzhiyun {
869*4882a593Smuzhiyun 	if (up_flag)
870*4882a593Smuzhiyun 		return;
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	if (vc_kbd_mode(kbd, VC_META)) {
873*4882a593Smuzhiyun 		put_queue(vc, '\033');
874*4882a593Smuzhiyun 		put_queue(vc, value);
875*4882a593Smuzhiyun 	} else
876*4882a593Smuzhiyun 		put_queue(vc, value | 0x80);
877*4882a593Smuzhiyun }
878*4882a593Smuzhiyun 
k_ascii(struct vc_data * vc,unsigned char value,char up_flag)879*4882a593Smuzhiyun static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
880*4882a593Smuzhiyun {
881*4882a593Smuzhiyun 	unsigned int base;
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun 	if (up_flag)
884*4882a593Smuzhiyun 		return;
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun 	if (value < 10) {
887*4882a593Smuzhiyun 		/* decimal input of code, while Alt depressed */
888*4882a593Smuzhiyun 		base = 10;
889*4882a593Smuzhiyun 	} else {
890*4882a593Smuzhiyun 		/* hexadecimal input of code, while AltGr depressed */
891*4882a593Smuzhiyun 		value -= 10;
892*4882a593Smuzhiyun 		base = 16;
893*4882a593Smuzhiyun 	}
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 	if (!npadch_active) {
896*4882a593Smuzhiyun 		npadch_value = 0;
897*4882a593Smuzhiyun 		npadch_active = true;
898*4882a593Smuzhiyun 	}
899*4882a593Smuzhiyun 
900*4882a593Smuzhiyun 	npadch_value = npadch_value * base + value;
901*4882a593Smuzhiyun }
902*4882a593Smuzhiyun 
k_lock(struct vc_data * vc,unsigned char value,char up_flag)903*4882a593Smuzhiyun static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
904*4882a593Smuzhiyun {
905*4882a593Smuzhiyun 	if (up_flag || rep)
906*4882a593Smuzhiyun 		return;
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun 	chg_vc_kbd_lock(kbd, value);
909*4882a593Smuzhiyun }
910*4882a593Smuzhiyun 
k_slock(struct vc_data * vc,unsigned char value,char up_flag)911*4882a593Smuzhiyun static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
912*4882a593Smuzhiyun {
913*4882a593Smuzhiyun 	k_shift(vc, value, up_flag);
914*4882a593Smuzhiyun 	if (up_flag || rep)
915*4882a593Smuzhiyun 		return;
916*4882a593Smuzhiyun 
917*4882a593Smuzhiyun 	chg_vc_kbd_slock(kbd, value);
918*4882a593Smuzhiyun 	/* try to make Alt, oops, AltGr and such work */
919*4882a593Smuzhiyun 	if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
920*4882a593Smuzhiyun 		kbd->slockstate = 0;
921*4882a593Smuzhiyun 		chg_vc_kbd_slock(kbd, value);
922*4882a593Smuzhiyun 	}
923*4882a593Smuzhiyun }
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun /* by default, 300ms interval for combination release */
926*4882a593Smuzhiyun static unsigned brl_timeout = 300;
927*4882a593Smuzhiyun MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
928*4882a593Smuzhiyun module_param(brl_timeout, uint, 0644);
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun static unsigned brl_nbchords = 1;
931*4882a593Smuzhiyun MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
932*4882a593Smuzhiyun module_param(brl_nbchords, uint, 0644);
933*4882a593Smuzhiyun 
k_brlcommit(struct vc_data * vc,unsigned int pattern,char up_flag)934*4882a593Smuzhiyun static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag)
935*4882a593Smuzhiyun {
936*4882a593Smuzhiyun 	static unsigned long chords;
937*4882a593Smuzhiyun 	static unsigned committed;
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun 	if (!brl_nbchords)
940*4882a593Smuzhiyun 		k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag);
941*4882a593Smuzhiyun 	else {
942*4882a593Smuzhiyun 		committed |= pattern;
943*4882a593Smuzhiyun 		chords++;
944*4882a593Smuzhiyun 		if (chords == brl_nbchords) {
945*4882a593Smuzhiyun 			k_unicode(vc, BRL_UC_ROW | committed, up_flag);
946*4882a593Smuzhiyun 			chords = 0;
947*4882a593Smuzhiyun 			committed = 0;
948*4882a593Smuzhiyun 		}
949*4882a593Smuzhiyun 	}
950*4882a593Smuzhiyun }
951*4882a593Smuzhiyun 
k_brl(struct vc_data * vc,unsigned char value,char up_flag)952*4882a593Smuzhiyun static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
953*4882a593Smuzhiyun {
954*4882a593Smuzhiyun 	static unsigned pressed, committing;
955*4882a593Smuzhiyun 	static unsigned long releasestart;
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun 	if (kbd->kbdmode != VC_UNICODE) {
958*4882a593Smuzhiyun 		if (!up_flag)
959*4882a593Smuzhiyun 			pr_warn("keyboard mode must be unicode for braille patterns\n");
960*4882a593Smuzhiyun 		return;
961*4882a593Smuzhiyun 	}
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	if (!value) {
964*4882a593Smuzhiyun 		k_unicode(vc, BRL_UC_ROW, up_flag);
965*4882a593Smuzhiyun 		return;
966*4882a593Smuzhiyun 	}
967*4882a593Smuzhiyun 
968*4882a593Smuzhiyun 	if (value > 8)
969*4882a593Smuzhiyun 		return;
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun 	if (!up_flag) {
972*4882a593Smuzhiyun 		pressed |= 1 << (value - 1);
973*4882a593Smuzhiyun 		if (!brl_timeout)
974*4882a593Smuzhiyun 			committing = pressed;
975*4882a593Smuzhiyun 	} else if (brl_timeout) {
976*4882a593Smuzhiyun 		if (!committing ||
977*4882a593Smuzhiyun 		    time_after(jiffies,
978*4882a593Smuzhiyun 			       releasestart + msecs_to_jiffies(brl_timeout))) {
979*4882a593Smuzhiyun 			committing = pressed;
980*4882a593Smuzhiyun 			releasestart = jiffies;
981*4882a593Smuzhiyun 		}
982*4882a593Smuzhiyun 		pressed &= ~(1 << (value - 1));
983*4882a593Smuzhiyun 		if (!pressed && committing) {
984*4882a593Smuzhiyun 			k_brlcommit(vc, committing, 0);
985*4882a593Smuzhiyun 			committing = 0;
986*4882a593Smuzhiyun 		}
987*4882a593Smuzhiyun 	} else {
988*4882a593Smuzhiyun 		if (committing) {
989*4882a593Smuzhiyun 			k_brlcommit(vc, committing, 0);
990*4882a593Smuzhiyun 			committing = 0;
991*4882a593Smuzhiyun 		}
992*4882a593Smuzhiyun 		pressed &= ~(1 << (value - 1));
993*4882a593Smuzhiyun 	}
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_INPUT_LEDS) && IS_ENABLED(CONFIG_LEDS_TRIGGERS)
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun struct kbd_led_trigger {
999*4882a593Smuzhiyun 	struct led_trigger trigger;
1000*4882a593Smuzhiyun 	unsigned int mask;
1001*4882a593Smuzhiyun };
1002*4882a593Smuzhiyun 
kbd_led_trigger_activate(struct led_classdev * cdev)1003*4882a593Smuzhiyun static int kbd_led_trigger_activate(struct led_classdev *cdev)
1004*4882a593Smuzhiyun {
1005*4882a593Smuzhiyun 	struct kbd_led_trigger *trigger =
1006*4882a593Smuzhiyun 		container_of(cdev->trigger, struct kbd_led_trigger, trigger);
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun 	tasklet_disable(&keyboard_tasklet);
1009*4882a593Smuzhiyun 	if (ledstate != -1U)
1010*4882a593Smuzhiyun 		led_trigger_event(&trigger->trigger,
1011*4882a593Smuzhiyun 				  ledstate & trigger->mask ?
1012*4882a593Smuzhiyun 					LED_FULL : LED_OFF);
1013*4882a593Smuzhiyun 	tasklet_enable(&keyboard_tasklet);
1014*4882a593Smuzhiyun 
1015*4882a593Smuzhiyun 	return 0;
1016*4882a593Smuzhiyun }
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun #define KBD_LED_TRIGGER(_led_bit, _name) {			\
1019*4882a593Smuzhiyun 		.trigger = {					\
1020*4882a593Smuzhiyun 			.name = _name,				\
1021*4882a593Smuzhiyun 			.activate = kbd_led_trigger_activate,	\
1022*4882a593Smuzhiyun 		},						\
1023*4882a593Smuzhiyun 		.mask	= BIT(_led_bit),			\
1024*4882a593Smuzhiyun 	}
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun #define KBD_LOCKSTATE_TRIGGER(_led_bit, _name)		\
1027*4882a593Smuzhiyun 	KBD_LED_TRIGGER((_led_bit) + 8, _name)
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun static struct kbd_led_trigger kbd_led_triggers[] = {
1030*4882a593Smuzhiyun 	KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrolllock"),
1031*4882a593Smuzhiyun 	KBD_LED_TRIGGER(VC_NUMLOCK,   "kbd-numlock"),
1032*4882a593Smuzhiyun 	KBD_LED_TRIGGER(VC_CAPSLOCK,  "kbd-capslock"),
1033*4882a593Smuzhiyun 	KBD_LED_TRIGGER(VC_KANALOCK,  "kbd-kanalock"),
1034*4882a593Smuzhiyun 
1035*4882a593Smuzhiyun 	KBD_LOCKSTATE_TRIGGER(VC_SHIFTLOCK,  "kbd-shiftlock"),
1036*4882a593Smuzhiyun 	KBD_LOCKSTATE_TRIGGER(VC_ALTGRLOCK,  "kbd-altgrlock"),
1037*4882a593Smuzhiyun 	KBD_LOCKSTATE_TRIGGER(VC_CTRLLOCK,   "kbd-ctrllock"),
1038*4882a593Smuzhiyun 	KBD_LOCKSTATE_TRIGGER(VC_ALTLOCK,    "kbd-altlock"),
1039*4882a593Smuzhiyun 	KBD_LOCKSTATE_TRIGGER(VC_SHIFTLLOCK, "kbd-shiftllock"),
1040*4882a593Smuzhiyun 	KBD_LOCKSTATE_TRIGGER(VC_SHIFTRLOCK, "kbd-shiftrlock"),
1041*4882a593Smuzhiyun 	KBD_LOCKSTATE_TRIGGER(VC_CTRLLLOCK,  "kbd-ctrlllock"),
1042*4882a593Smuzhiyun 	KBD_LOCKSTATE_TRIGGER(VC_CTRLRLOCK,  "kbd-ctrlrlock"),
1043*4882a593Smuzhiyun };
1044*4882a593Smuzhiyun 
kbd_propagate_led_state(unsigned int old_state,unsigned int new_state)1045*4882a593Smuzhiyun static void kbd_propagate_led_state(unsigned int old_state,
1046*4882a593Smuzhiyun 				    unsigned int new_state)
1047*4882a593Smuzhiyun {
1048*4882a593Smuzhiyun 	struct kbd_led_trigger *trigger;
1049*4882a593Smuzhiyun 	unsigned int changed = old_state ^ new_state;
1050*4882a593Smuzhiyun 	int i;
1051*4882a593Smuzhiyun 
1052*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) {
1053*4882a593Smuzhiyun 		trigger = &kbd_led_triggers[i];
1054*4882a593Smuzhiyun 
1055*4882a593Smuzhiyun 		if (changed & trigger->mask)
1056*4882a593Smuzhiyun 			led_trigger_event(&trigger->trigger,
1057*4882a593Smuzhiyun 					  new_state & trigger->mask ?
1058*4882a593Smuzhiyun 						LED_FULL : LED_OFF);
1059*4882a593Smuzhiyun 	}
1060*4882a593Smuzhiyun }
1061*4882a593Smuzhiyun 
kbd_update_leds_helper(struct input_handle * handle,void * data)1062*4882a593Smuzhiyun static int kbd_update_leds_helper(struct input_handle *handle, void *data)
1063*4882a593Smuzhiyun {
1064*4882a593Smuzhiyun 	unsigned int led_state = *(unsigned int *)data;
1065*4882a593Smuzhiyun 
1066*4882a593Smuzhiyun 	if (test_bit(EV_LED, handle->dev->evbit))
1067*4882a593Smuzhiyun 		kbd_propagate_led_state(~led_state, led_state);
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun 	return 0;
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun 
kbd_init_leds(void)1072*4882a593Smuzhiyun static void kbd_init_leds(void)
1073*4882a593Smuzhiyun {
1074*4882a593Smuzhiyun 	int error;
1075*4882a593Smuzhiyun 	int i;
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) {
1078*4882a593Smuzhiyun 		error = led_trigger_register(&kbd_led_triggers[i].trigger);
1079*4882a593Smuzhiyun 		if (error)
1080*4882a593Smuzhiyun 			pr_err("error %d while registering trigger %s\n",
1081*4882a593Smuzhiyun 			       error, kbd_led_triggers[i].trigger.name);
1082*4882a593Smuzhiyun 	}
1083*4882a593Smuzhiyun }
1084*4882a593Smuzhiyun 
1085*4882a593Smuzhiyun #else
1086*4882a593Smuzhiyun 
kbd_update_leds_helper(struct input_handle * handle,void * data)1087*4882a593Smuzhiyun static int kbd_update_leds_helper(struct input_handle *handle, void *data)
1088*4882a593Smuzhiyun {
1089*4882a593Smuzhiyun 	unsigned int leds = *(unsigned int *)data;
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun 	if (test_bit(EV_LED, handle->dev->evbit)) {
1092*4882a593Smuzhiyun 		input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
1093*4882a593Smuzhiyun 		input_inject_event(handle, EV_LED, LED_NUML,    !!(leds & 0x02));
1094*4882a593Smuzhiyun 		input_inject_event(handle, EV_LED, LED_CAPSL,   !!(leds & 0x04));
1095*4882a593Smuzhiyun 		input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
1096*4882a593Smuzhiyun 	}
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun 	return 0;
1099*4882a593Smuzhiyun }
1100*4882a593Smuzhiyun 
kbd_propagate_led_state(unsigned int old_state,unsigned int new_state)1101*4882a593Smuzhiyun static void kbd_propagate_led_state(unsigned int old_state,
1102*4882a593Smuzhiyun 				    unsigned int new_state)
1103*4882a593Smuzhiyun {
1104*4882a593Smuzhiyun 	input_handler_for_each_handle(&kbd_handler, &new_state,
1105*4882a593Smuzhiyun 				      kbd_update_leds_helper);
1106*4882a593Smuzhiyun }
1107*4882a593Smuzhiyun 
kbd_init_leds(void)1108*4882a593Smuzhiyun static void kbd_init_leds(void)
1109*4882a593Smuzhiyun {
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun 
1112*4882a593Smuzhiyun #endif
1113*4882a593Smuzhiyun 
1114*4882a593Smuzhiyun /*
1115*4882a593Smuzhiyun  * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
1116*4882a593Smuzhiyun  * or (ii) whatever pattern of lights people want to show using KDSETLED,
1117*4882a593Smuzhiyun  * or (iii) specified bits of specified words in kernel memory.
1118*4882a593Smuzhiyun  */
getledstate(void)1119*4882a593Smuzhiyun static unsigned char getledstate(void)
1120*4882a593Smuzhiyun {
1121*4882a593Smuzhiyun 	return ledstate & 0xff;
1122*4882a593Smuzhiyun }
1123*4882a593Smuzhiyun 
setledstate(struct kbd_struct * kb,unsigned int led)1124*4882a593Smuzhiyun void setledstate(struct kbd_struct *kb, unsigned int led)
1125*4882a593Smuzhiyun {
1126*4882a593Smuzhiyun         unsigned long flags;
1127*4882a593Smuzhiyun         spin_lock_irqsave(&led_lock, flags);
1128*4882a593Smuzhiyun 	if (!(led & ~7)) {
1129*4882a593Smuzhiyun 		ledioctl = led;
1130*4882a593Smuzhiyun 		kb->ledmode = LED_SHOW_IOCTL;
1131*4882a593Smuzhiyun 	} else
1132*4882a593Smuzhiyun 		kb->ledmode = LED_SHOW_FLAGS;
1133*4882a593Smuzhiyun 
1134*4882a593Smuzhiyun 	set_leds();
1135*4882a593Smuzhiyun 	spin_unlock_irqrestore(&led_lock, flags);
1136*4882a593Smuzhiyun }
1137*4882a593Smuzhiyun 
getleds(void)1138*4882a593Smuzhiyun static inline unsigned char getleds(void)
1139*4882a593Smuzhiyun {
1140*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + fg_console;
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun 	if (kb->ledmode == LED_SHOW_IOCTL)
1143*4882a593Smuzhiyun 		return ledioctl;
1144*4882a593Smuzhiyun 
1145*4882a593Smuzhiyun 	return kb->ledflagstate;
1146*4882a593Smuzhiyun }
1147*4882a593Smuzhiyun 
1148*4882a593Smuzhiyun /**
1149*4882a593Smuzhiyun  *	vt_get_leds	-	helper for braille console
1150*4882a593Smuzhiyun  *	@console: console to read
1151*4882a593Smuzhiyun  *	@flag: flag we want to check
1152*4882a593Smuzhiyun  *
1153*4882a593Smuzhiyun  *	Check the status of a keyboard led flag and report it back
1154*4882a593Smuzhiyun  */
vt_get_leds(int console,int flag)1155*4882a593Smuzhiyun int vt_get_leds(int console, int flag)
1156*4882a593Smuzhiyun {
1157*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
1158*4882a593Smuzhiyun 	int ret;
1159*4882a593Smuzhiyun 	unsigned long flags;
1160*4882a593Smuzhiyun 
1161*4882a593Smuzhiyun 	spin_lock_irqsave(&led_lock, flags);
1162*4882a593Smuzhiyun 	ret = vc_kbd_led(kb, flag);
1163*4882a593Smuzhiyun 	spin_unlock_irqrestore(&led_lock, flags);
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun 	return ret;
1166*4882a593Smuzhiyun }
1167*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(vt_get_leds);
1168*4882a593Smuzhiyun 
1169*4882a593Smuzhiyun /**
1170*4882a593Smuzhiyun  *	vt_set_led_state	-	set LED state of a console
1171*4882a593Smuzhiyun  *	@console: console to set
1172*4882a593Smuzhiyun  *	@leds: LED bits
1173*4882a593Smuzhiyun  *
1174*4882a593Smuzhiyun  *	Set the LEDs on a console. This is a wrapper for the VT layer
1175*4882a593Smuzhiyun  *	so that we can keep kbd knowledge internal
1176*4882a593Smuzhiyun  */
vt_set_led_state(int console,int leds)1177*4882a593Smuzhiyun void vt_set_led_state(int console, int leds)
1178*4882a593Smuzhiyun {
1179*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
1180*4882a593Smuzhiyun 	setledstate(kb, leds);
1181*4882a593Smuzhiyun }
1182*4882a593Smuzhiyun 
1183*4882a593Smuzhiyun /**
1184*4882a593Smuzhiyun  *	vt_kbd_con_start	-	Keyboard side of console start
1185*4882a593Smuzhiyun  *	@console: console
1186*4882a593Smuzhiyun  *
1187*4882a593Smuzhiyun  *	Handle console start. This is a wrapper for the VT layer
1188*4882a593Smuzhiyun  *	so that we can keep kbd knowledge internal
1189*4882a593Smuzhiyun  *
1190*4882a593Smuzhiyun  *	FIXME: We eventually need to hold the kbd lock here to protect
1191*4882a593Smuzhiyun  *	the LED updating. We can't do it yet because fn_hold calls stop_tty
1192*4882a593Smuzhiyun  *	and start_tty under the kbd_event_lock, while normal tty paths
1193*4882a593Smuzhiyun  *	don't hold the lock. We probably need to split out an LED lock
1194*4882a593Smuzhiyun  *	but not during an -rc release!
1195*4882a593Smuzhiyun  */
vt_kbd_con_start(int console)1196*4882a593Smuzhiyun void vt_kbd_con_start(int console)
1197*4882a593Smuzhiyun {
1198*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
1199*4882a593Smuzhiyun 	unsigned long flags;
1200*4882a593Smuzhiyun 	spin_lock_irqsave(&led_lock, flags);
1201*4882a593Smuzhiyun 	clr_vc_kbd_led(kb, VC_SCROLLOCK);
1202*4882a593Smuzhiyun 	set_leds();
1203*4882a593Smuzhiyun 	spin_unlock_irqrestore(&led_lock, flags);
1204*4882a593Smuzhiyun }
1205*4882a593Smuzhiyun 
1206*4882a593Smuzhiyun /**
1207*4882a593Smuzhiyun  *	vt_kbd_con_stop		-	Keyboard side of console stop
1208*4882a593Smuzhiyun  *	@console: console
1209*4882a593Smuzhiyun  *
1210*4882a593Smuzhiyun  *	Handle console stop. This is a wrapper for the VT layer
1211*4882a593Smuzhiyun  *	so that we can keep kbd knowledge internal
1212*4882a593Smuzhiyun  */
vt_kbd_con_stop(int console)1213*4882a593Smuzhiyun void vt_kbd_con_stop(int console)
1214*4882a593Smuzhiyun {
1215*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
1216*4882a593Smuzhiyun 	unsigned long flags;
1217*4882a593Smuzhiyun 	spin_lock_irqsave(&led_lock, flags);
1218*4882a593Smuzhiyun 	set_vc_kbd_led(kb, VC_SCROLLOCK);
1219*4882a593Smuzhiyun 	set_leds();
1220*4882a593Smuzhiyun 	spin_unlock_irqrestore(&led_lock, flags);
1221*4882a593Smuzhiyun }
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun /*
1224*4882a593Smuzhiyun  * This is the tasklet that updates LED state of LEDs using standard
1225*4882a593Smuzhiyun  * keyboard triggers. The reason we use tasklet is that we need to
1226*4882a593Smuzhiyun  * handle the scenario when keyboard handler is not registered yet
1227*4882a593Smuzhiyun  * but we already getting updates from the VT to update led state.
1228*4882a593Smuzhiyun  */
kbd_bh(unsigned long dummy)1229*4882a593Smuzhiyun static void kbd_bh(unsigned long dummy)
1230*4882a593Smuzhiyun {
1231*4882a593Smuzhiyun 	unsigned int leds;
1232*4882a593Smuzhiyun 	unsigned long flags;
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun 	spin_lock_irqsave(&led_lock, flags);
1235*4882a593Smuzhiyun 	leds = getleds();
1236*4882a593Smuzhiyun 	leds |= (unsigned int)kbd->lockstate << 8;
1237*4882a593Smuzhiyun 	spin_unlock_irqrestore(&led_lock, flags);
1238*4882a593Smuzhiyun 
1239*4882a593Smuzhiyun 	if (leds != ledstate) {
1240*4882a593Smuzhiyun 		kbd_propagate_led_state(ledstate, leds);
1241*4882a593Smuzhiyun 		ledstate = leds;
1242*4882a593Smuzhiyun 	}
1243*4882a593Smuzhiyun }
1244*4882a593Smuzhiyun 
1245*4882a593Smuzhiyun DECLARE_TASKLET_DISABLED_OLD(keyboard_tasklet, kbd_bh);
1246*4882a593Smuzhiyun 
1247*4882a593Smuzhiyun #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
1248*4882a593Smuzhiyun     defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
1249*4882a593Smuzhiyun     defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
1250*4882a593Smuzhiyun     (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
1251*4882a593Smuzhiyun 
1252*4882a593Smuzhiyun #define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
1253*4882a593Smuzhiyun 			((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
1254*4882a593Smuzhiyun 
1255*4882a593Smuzhiyun static const unsigned short x86_keycodes[256] =
1256*4882a593Smuzhiyun 	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
1257*4882a593Smuzhiyun 	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1258*4882a593Smuzhiyun 	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
1259*4882a593Smuzhiyun 	 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
1260*4882a593Smuzhiyun 	 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
1261*4882a593Smuzhiyun 	 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
1262*4882a593Smuzhiyun 	284,285,309,  0,312, 91,327,328,329,331,333,335,336,337,338,339,
1263*4882a593Smuzhiyun 	367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
1264*4882a593Smuzhiyun 	360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
1265*4882a593Smuzhiyun 	103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
1266*4882a593Smuzhiyun 	291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
1267*4882a593Smuzhiyun 	264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
1268*4882a593Smuzhiyun 	377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
1269*4882a593Smuzhiyun 	308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
1270*4882a593Smuzhiyun 	332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
1271*4882a593Smuzhiyun 
1272*4882a593Smuzhiyun #ifdef CONFIG_SPARC
1273*4882a593Smuzhiyun static int sparc_l1_a_state;
1274*4882a593Smuzhiyun extern void sun_do_break(void);
1275*4882a593Smuzhiyun #endif
1276*4882a593Smuzhiyun 
emulate_raw(struct vc_data * vc,unsigned int keycode,unsigned char up_flag)1277*4882a593Smuzhiyun static int emulate_raw(struct vc_data *vc, unsigned int keycode,
1278*4882a593Smuzhiyun 		       unsigned char up_flag)
1279*4882a593Smuzhiyun {
1280*4882a593Smuzhiyun 	int code;
1281*4882a593Smuzhiyun 
1282*4882a593Smuzhiyun 	switch (keycode) {
1283*4882a593Smuzhiyun 
1284*4882a593Smuzhiyun 	case KEY_PAUSE:
1285*4882a593Smuzhiyun 		put_queue(vc, 0xe1);
1286*4882a593Smuzhiyun 		put_queue(vc, 0x1d | up_flag);
1287*4882a593Smuzhiyun 		put_queue(vc, 0x45 | up_flag);
1288*4882a593Smuzhiyun 		break;
1289*4882a593Smuzhiyun 
1290*4882a593Smuzhiyun 	case KEY_HANGEUL:
1291*4882a593Smuzhiyun 		if (!up_flag)
1292*4882a593Smuzhiyun 			put_queue(vc, 0xf2);
1293*4882a593Smuzhiyun 		break;
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun 	case KEY_HANJA:
1296*4882a593Smuzhiyun 		if (!up_flag)
1297*4882a593Smuzhiyun 			put_queue(vc, 0xf1);
1298*4882a593Smuzhiyun 		break;
1299*4882a593Smuzhiyun 
1300*4882a593Smuzhiyun 	case KEY_SYSRQ:
1301*4882a593Smuzhiyun 		/*
1302*4882a593Smuzhiyun 		 * Real AT keyboards (that's what we're trying
1303*4882a593Smuzhiyun 		 * to emulate here) emit 0xe0 0x2a 0xe0 0x37 when
1304*4882a593Smuzhiyun 		 * pressing PrtSc/SysRq alone, but simply 0x54
1305*4882a593Smuzhiyun 		 * when pressing Alt+PrtSc/SysRq.
1306*4882a593Smuzhiyun 		 */
1307*4882a593Smuzhiyun 		if (test_bit(KEY_LEFTALT, key_down) ||
1308*4882a593Smuzhiyun 		    test_bit(KEY_RIGHTALT, key_down)) {
1309*4882a593Smuzhiyun 			put_queue(vc, 0x54 | up_flag);
1310*4882a593Smuzhiyun 		} else {
1311*4882a593Smuzhiyun 			put_queue(vc, 0xe0);
1312*4882a593Smuzhiyun 			put_queue(vc, 0x2a | up_flag);
1313*4882a593Smuzhiyun 			put_queue(vc, 0xe0);
1314*4882a593Smuzhiyun 			put_queue(vc, 0x37 | up_flag);
1315*4882a593Smuzhiyun 		}
1316*4882a593Smuzhiyun 		break;
1317*4882a593Smuzhiyun 
1318*4882a593Smuzhiyun 	default:
1319*4882a593Smuzhiyun 		if (keycode > 255)
1320*4882a593Smuzhiyun 			return -1;
1321*4882a593Smuzhiyun 
1322*4882a593Smuzhiyun 		code = x86_keycodes[keycode];
1323*4882a593Smuzhiyun 		if (!code)
1324*4882a593Smuzhiyun 			return -1;
1325*4882a593Smuzhiyun 
1326*4882a593Smuzhiyun 		if (code & 0x100)
1327*4882a593Smuzhiyun 			put_queue(vc, 0xe0);
1328*4882a593Smuzhiyun 		put_queue(vc, (code & 0x7f) | up_flag);
1329*4882a593Smuzhiyun 
1330*4882a593Smuzhiyun 		break;
1331*4882a593Smuzhiyun 	}
1332*4882a593Smuzhiyun 
1333*4882a593Smuzhiyun 	return 0;
1334*4882a593Smuzhiyun }
1335*4882a593Smuzhiyun 
1336*4882a593Smuzhiyun #else
1337*4882a593Smuzhiyun 
1338*4882a593Smuzhiyun #define HW_RAW(dev)	0
1339*4882a593Smuzhiyun 
emulate_raw(struct vc_data * vc,unsigned int keycode,unsigned char up_flag)1340*4882a593Smuzhiyun static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
1341*4882a593Smuzhiyun {
1342*4882a593Smuzhiyun 	if (keycode > 127)
1343*4882a593Smuzhiyun 		return -1;
1344*4882a593Smuzhiyun 
1345*4882a593Smuzhiyun 	put_queue(vc, keycode | up_flag);
1346*4882a593Smuzhiyun 	return 0;
1347*4882a593Smuzhiyun }
1348*4882a593Smuzhiyun #endif
1349*4882a593Smuzhiyun 
kbd_rawcode(unsigned char data)1350*4882a593Smuzhiyun static void kbd_rawcode(unsigned char data)
1351*4882a593Smuzhiyun {
1352*4882a593Smuzhiyun 	struct vc_data *vc = vc_cons[fg_console].d;
1353*4882a593Smuzhiyun 
1354*4882a593Smuzhiyun 	kbd = kbd_table + vc->vc_num;
1355*4882a593Smuzhiyun 	if (kbd->kbdmode == VC_RAW)
1356*4882a593Smuzhiyun 		put_queue(vc, data);
1357*4882a593Smuzhiyun }
1358*4882a593Smuzhiyun 
kbd_keycode(unsigned int keycode,int down,int hw_raw)1359*4882a593Smuzhiyun static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
1360*4882a593Smuzhiyun {
1361*4882a593Smuzhiyun 	struct vc_data *vc = vc_cons[fg_console].d;
1362*4882a593Smuzhiyun 	unsigned short keysym, *key_map;
1363*4882a593Smuzhiyun 	unsigned char type;
1364*4882a593Smuzhiyun 	bool raw_mode;
1365*4882a593Smuzhiyun 	struct tty_struct *tty;
1366*4882a593Smuzhiyun 	int shift_final;
1367*4882a593Smuzhiyun 	struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
1368*4882a593Smuzhiyun 	int rc;
1369*4882a593Smuzhiyun 
1370*4882a593Smuzhiyun 	tty = vc->port.tty;
1371*4882a593Smuzhiyun 
1372*4882a593Smuzhiyun 	if (tty && (!tty->driver_data)) {
1373*4882a593Smuzhiyun 		/* No driver data? Strange. Okay we fix it then. */
1374*4882a593Smuzhiyun 		tty->driver_data = vc;
1375*4882a593Smuzhiyun 	}
1376*4882a593Smuzhiyun 
1377*4882a593Smuzhiyun 	kbd = kbd_table + vc->vc_num;
1378*4882a593Smuzhiyun 
1379*4882a593Smuzhiyun #ifdef CONFIG_SPARC
1380*4882a593Smuzhiyun 	if (keycode == KEY_STOP)
1381*4882a593Smuzhiyun 		sparc_l1_a_state = down;
1382*4882a593Smuzhiyun #endif
1383*4882a593Smuzhiyun 
1384*4882a593Smuzhiyun 	rep = (down == 2);
1385*4882a593Smuzhiyun 
1386*4882a593Smuzhiyun 	raw_mode = (kbd->kbdmode == VC_RAW);
1387*4882a593Smuzhiyun 	if (raw_mode && !hw_raw)
1388*4882a593Smuzhiyun 		if (emulate_raw(vc, keycode, !down << 7))
1389*4882a593Smuzhiyun 			if (keycode < BTN_MISC && printk_ratelimit())
1390*4882a593Smuzhiyun 				pr_warn("can't emulate rawmode for keycode %d\n",
1391*4882a593Smuzhiyun 					keycode);
1392*4882a593Smuzhiyun 
1393*4882a593Smuzhiyun #ifdef CONFIG_SPARC
1394*4882a593Smuzhiyun 	if (keycode == KEY_A && sparc_l1_a_state) {
1395*4882a593Smuzhiyun 		sparc_l1_a_state = false;
1396*4882a593Smuzhiyun 		sun_do_break();
1397*4882a593Smuzhiyun 	}
1398*4882a593Smuzhiyun #endif
1399*4882a593Smuzhiyun 
1400*4882a593Smuzhiyun 	if (kbd->kbdmode == VC_MEDIUMRAW) {
1401*4882a593Smuzhiyun 		/*
1402*4882a593Smuzhiyun 		 * This is extended medium raw mode, with keys above 127
1403*4882a593Smuzhiyun 		 * encoded as 0, high 7 bits, low 7 bits, with the 0 bearing
1404*4882a593Smuzhiyun 		 * the 'up' flag if needed. 0 is reserved, so this shouldn't
1405*4882a593Smuzhiyun 		 * interfere with anything else. The two bytes after 0 will
1406*4882a593Smuzhiyun 		 * always have the up flag set not to interfere with older
1407*4882a593Smuzhiyun 		 * applications. This allows for 16384 different keycodes,
1408*4882a593Smuzhiyun 		 * which should be enough.
1409*4882a593Smuzhiyun 		 */
1410*4882a593Smuzhiyun 		if (keycode < 128) {
1411*4882a593Smuzhiyun 			put_queue(vc, keycode | (!down << 7));
1412*4882a593Smuzhiyun 		} else {
1413*4882a593Smuzhiyun 			put_queue(vc, !down << 7);
1414*4882a593Smuzhiyun 			put_queue(vc, (keycode >> 7) | 0x80);
1415*4882a593Smuzhiyun 			put_queue(vc, keycode | 0x80);
1416*4882a593Smuzhiyun 		}
1417*4882a593Smuzhiyun 		raw_mode = true;
1418*4882a593Smuzhiyun 	}
1419*4882a593Smuzhiyun 
1420*4882a593Smuzhiyun 	if (down)
1421*4882a593Smuzhiyun 		set_bit(keycode, key_down);
1422*4882a593Smuzhiyun 	else
1423*4882a593Smuzhiyun 		clear_bit(keycode, key_down);
1424*4882a593Smuzhiyun 
1425*4882a593Smuzhiyun 	if (rep &&
1426*4882a593Smuzhiyun 	    (!vc_kbd_mode(kbd, VC_REPEAT) ||
1427*4882a593Smuzhiyun 	     (tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) {
1428*4882a593Smuzhiyun 		/*
1429*4882a593Smuzhiyun 		 * Don't repeat a key if the input buffers are not empty and the
1430*4882a593Smuzhiyun 		 * characters get aren't echoed locally. This makes key repeat
1431*4882a593Smuzhiyun 		 * usable with slow applications and under heavy loads.
1432*4882a593Smuzhiyun 		 */
1433*4882a593Smuzhiyun 		return;
1434*4882a593Smuzhiyun 	}
1435*4882a593Smuzhiyun 
1436*4882a593Smuzhiyun 	param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
1437*4882a593Smuzhiyun 	param.ledstate = kbd->ledflagstate;
1438*4882a593Smuzhiyun 	key_map = key_maps[shift_final];
1439*4882a593Smuzhiyun 
1440*4882a593Smuzhiyun 	rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1441*4882a593Smuzhiyun 					KBD_KEYCODE, &param);
1442*4882a593Smuzhiyun 	if (rc == NOTIFY_STOP || !key_map) {
1443*4882a593Smuzhiyun 		atomic_notifier_call_chain(&keyboard_notifier_list,
1444*4882a593Smuzhiyun 					   KBD_UNBOUND_KEYCODE, &param);
1445*4882a593Smuzhiyun 		do_compute_shiftstate();
1446*4882a593Smuzhiyun 		kbd->slockstate = 0;
1447*4882a593Smuzhiyun 		return;
1448*4882a593Smuzhiyun 	}
1449*4882a593Smuzhiyun 
1450*4882a593Smuzhiyun 	if (keycode < NR_KEYS)
1451*4882a593Smuzhiyun 		keysym = key_map[keycode];
1452*4882a593Smuzhiyun 	else if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
1453*4882a593Smuzhiyun 		keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1));
1454*4882a593Smuzhiyun 	else
1455*4882a593Smuzhiyun 		return;
1456*4882a593Smuzhiyun 
1457*4882a593Smuzhiyun 	type = KTYP(keysym);
1458*4882a593Smuzhiyun 
1459*4882a593Smuzhiyun 	if (type < 0xf0) {
1460*4882a593Smuzhiyun 		param.value = keysym;
1461*4882a593Smuzhiyun 		rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1462*4882a593Smuzhiyun 						KBD_UNICODE, &param);
1463*4882a593Smuzhiyun 		if (rc != NOTIFY_STOP)
1464*4882a593Smuzhiyun 			if (down && !raw_mode)
1465*4882a593Smuzhiyun 				k_unicode(vc, keysym, !down);
1466*4882a593Smuzhiyun 		return;
1467*4882a593Smuzhiyun 	}
1468*4882a593Smuzhiyun 
1469*4882a593Smuzhiyun 	type -= 0xf0;
1470*4882a593Smuzhiyun 
1471*4882a593Smuzhiyun 	if (type == KT_LETTER) {
1472*4882a593Smuzhiyun 		type = KT_LATIN;
1473*4882a593Smuzhiyun 		if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
1474*4882a593Smuzhiyun 			key_map = key_maps[shift_final ^ (1 << KG_SHIFT)];
1475*4882a593Smuzhiyun 			if (key_map)
1476*4882a593Smuzhiyun 				keysym = key_map[keycode];
1477*4882a593Smuzhiyun 		}
1478*4882a593Smuzhiyun 	}
1479*4882a593Smuzhiyun 
1480*4882a593Smuzhiyun 	param.value = keysym;
1481*4882a593Smuzhiyun 	rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1482*4882a593Smuzhiyun 					KBD_KEYSYM, &param);
1483*4882a593Smuzhiyun 	if (rc == NOTIFY_STOP)
1484*4882a593Smuzhiyun 		return;
1485*4882a593Smuzhiyun 
1486*4882a593Smuzhiyun 	if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type != KT_SHIFT)
1487*4882a593Smuzhiyun 		return;
1488*4882a593Smuzhiyun 
1489*4882a593Smuzhiyun 	(*k_handler[type])(vc, keysym & 0xff, !down);
1490*4882a593Smuzhiyun 
1491*4882a593Smuzhiyun 	param.ledstate = kbd->ledflagstate;
1492*4882a593Smuzhiyun 	atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
1493*4882a593Smuzhiyun 
1494*4882a593Smuzhiyun 	if (type != KT_SLOCK)
1495*4882a593Smuzhiyun 		kbd->slockstate = 0;
1496*4882a593Smuzhiyun }
1497*4882a593Smuzhiyun 
kbd_event(struct input_handle * handle,unsigned int event_type,unsigned int event_code,int value)1498*4882a593Smuzhiyun static void kbd_event(struct input_handle *handle, unsigned int event_type,
1499*4882a593Smuzhiyun 		      unsigned int event_code, int value)
1500*4882a593Smuzhiyun {
1501*4882a593Smuzhiyun 	/* We are called with interrupts disabled, just take the lock */
1502*4882a593Smuzhiyun 	spin_lock(&kbd_event_lock);
1503*4882a593Smuzhiyun 
1504*4882a593Smuzhiyun 	if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
1505*4882a593Smuzhiyun 		kbd_rawcode(value);
1506*4882a593Smuzhiyun 	if (event_type == EV_KEY && event_code <= KEY_MAX)
1507*4882a593Smuzhiyun 		kbd_keycode(event_code, value, HW_RAW(handle->dev));
1508*4882a593Smuzhiyun 
1509*4882a593Smuzhiyun 	spin_unlock(&kbd_event_lock);
1510*4882a593Smuzhiyun 
1511*4882a593Smuzhiyun 	tasklet_schedule(&keyboard_tasklet);
1512*4882a593Smuzhiyun 	do_poke_blanked_console = 1;
1513*4882a593Smuzhiyun 	schedule_console_callback();
1514*4882a593Smuzhiyun }
1515*4882a593Smuzhiyun 
kbd_match(struct input_handler * handler,struct input_dev * dev)1516*4882a593Smuzhiyun static bool kbd_match(struct input_handler *handler, struct input_dev *dev)
1517*4882a593Smuzhiyun {
1518*4882a593Smuzhiyun 	int i;
1519*4882a593Smuzhiyun 
1520*4882a593Smuzhiyun 	if (test_bit(EV_SND, dev->evbit))
1521*4882a593Smuzhiyun 		return true;
1522*4882a593Smuzhiyun 
1523*4882a593Smuzhiyun 	if (test_bit(EV_KEY, dev->evbit)) {
1524*4882a593Smuzhiyun 		for (i = KEY_RESERVED; i < BTN_MISC; i++)
1525*4882a593Smuzhiyun 			if (test_bit(i, dev->keybit))
1526*4882a593Smuzhiyun 				return true;
1527*4882a593Smuzhiyun 		for (i = KEY_BRL_DOT1; i <= KEY_BRL_DOT10; i++)
1528*4882a593Smuzhiyun 			if (test_bit(i, dev->keybit))
1529*4882a593Smuzhiyun 				return true;
1530*4882a593Smuzhiyun 	}
1531*4882a593Smuzhiyun 
1532*4882a593Smuzhiyun 	return false;
1533*4882a593Smuzhiyun }
1534*4882a593Smuzhiyun 
1535*4882a593Smuzhiyun /*
1536*4882a593Smuzhiyun  * When a keyboard (or other input device) is found, the kbd_connect
1537*4882a593Smuzhiyun  * function is called. The function then looks at the device, and if it
1538*4882a593Smuzhiyun  * likes it, it can open it and get events from it. In this (kbd_connect)
1539*4882a593Smuzhiyun  * function, we should decide which VT to bind that keyboard to initially.
1540*4882a593Smuzhiyun  */
kbd_connect(struct input_handler * handler,struct input_dev * dev,const struct input_device_id * id)1541*4882a593Smuzhiyun static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
1542*4882a593Smuzhiyun 			const struct input_device_id *id)
1543*4882a593Smuzhiyun {
1544*4882a593Smuzhiyun 	struct input_handle *handle;
1545*4882a593Smuzhiyun 	int error;
1546*4882a593Smuzhiyun 
1547*4882a593Smuzhiyun 	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
1548*4882a593Smuzhiyun 	if (!handle)
1549*4882a593Smuzhiyun 		return -ENOMEM;
1550*4882a593Smuzhiyun 
1551*4882a593Smuzhiyun 	handle->dev = dev;
1552*4882a593Smuzhiyun 	handle->handler = handler;
1553*4882a593Smuzhiyun 	handle->name = "kbd";
1554*4882a593Smuzhiyun 
1555*4882a593Smuzhiyun 	error = input_register_handle(handle);
1556*4882a593Smuzhiyun 	if (error)
1557*4882a593Smuzhiyun 		goto err_free_handle;
1558*4882a593Smuzhiyun 
1559*4882a593Smuzhiyun 	error = input_open_device(handle);
1560*4882a593Smuzhiyun 	if (error)
1561*4882a593Smuzhiyun 		goto err_unregister_handle;
1562*4882a593Smuzhiyun 
1563*4882a593Smuzhiyun 	return 0;
1564*4882a593Smuzhiyun 
1565*4882a593Smuzhiyun  err_unregister_handle:
1566*4882a593Smuzhiyun 	input_unregister_handle(handle);
1567*4882a593Smuzhiyun  err_free_handle:
1568*4882a593Smuzhiyun 	kfree(handle);
1569*4882a593Smuzhiyun 	return error;
1570*4882a593Smuzhiyun }
1571*4882a593Smuzhiyun 
kbd_disconnect(struct input_handle * handle)1572*4882a593Smuzhiyun static void kbd_disconnect(struct input_handle *handle)
1573*4882a593Smuzhiyun {
1574*4882a593Smuzhiyun 	input_close_device(handle);
1575*4882a593Smuzhiyun 	input_unregister_handle(handle);
1576*4882a593Smuzhiyun 	kfree(handle);
1577*4882a593Smuzhiyun }
1578*4882a593Smuzhiyun 
1579*4882a593Smuzhiyun /*
1580*4882a593Smuzhiyun  * Start keyboard handler on the new keyboard by refreshing LED state to
1581*4882a593Smuzhiyun  * match the rest of the system.
1582*4882a593Smuzhiyun  */
kbd_start(struct input_handle * handle)1583*4882a593Smuzhiyun static void kbd_start(struct input_handle *handle)
1584*4882a593Smuzhiyun {
1585*4882a593Smuzhiyun 	tasklet_disable(&keyboard_tasklet);
1586*4882a593Smuzhiyun 
1587*4882a593Smuzhiyun 	if (ledstate != -1U)
1588*4882a593Smuzhiyun 		kbd_update_leds_helper(handle, &ledstate);
1589*4882a593Smuzhiyun 
1590*4882a593Smuzhiyun 	tasklet_enable(&keyboard_tasklet);
1591*4882a593Smuzhiyun }
1592*4882a593Smuzhiyun 
1593*4882a593Smuzhiyun static const struct input_device_id kbd_ids[] = {
1594*4882a593Smuzhiyun 	{
1595*4882a593Smuzhiyun 		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1596*4882a593Smuzhiyun 		.evbit = { BIT_MASK(EV_KEY) },
1597*4882a593Smuzhiyun 	},
1598*4882a593Smuzhiyun 
1599*4882a593Smuzhiyun 	{
1600*4882a593Smuzhiyun 		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1601*4882a593Smuzhiyun 		.evbit = { BIT_MASK(EV_SND) },
1602*4882a593Smuzhiyun 	},
1603*4882a593Smuzhiyun 
1604*4882a593Smuzhiyun 	{ },    /* Terminating entry */
1605*4882a593Smuzhiyun };
1606*4882a593Smuzhiyun 
1607*4882a593Smuzhiyun MODULE_DEVICE_TABLE(input, kbd_ids);
1608*4882a593Smuzhiyun 
1609*4882a593Smuzhiyun static struct input_handler kbd_handler = {
1610*4882a593Smuzhiyun 	.event		= kbd_event,
1611*4882a593Smuzhiyun 	.match		= kbd_match,
1612*4882a593Smuzhiyun 	.connect	= kbd_connect,
1613*4882a593Smuzhiyun 	.disconnect	= kbd_disconnect,
1614*4882a593Smuzhiyun 	.start		= kbd_start,
1615*4882a593Smuzhiyun 	.name		= "kbd",
1616*4882a593Smuzhiyun 	.id_table	= kbd_ids,
1617*4882a593Smuzhiyun };
1618*4882a593Smuzhiyun 
kbd_init(void)1619*4882a593Smuzhiyun int __init kbd_init(void)
1620*4882a593Smuzhiyun {
1621*4882a593Smuzhiyun 	int i;
1622*4882a593Smuzhiyun 	int error;
1623*4882a593Smuzhiyun 
1624*4882a593Smuzhiyun 	for (i = 0; i < MAX_NR_CONSOLES; i++) {
1625*4882a593Smuzhiyun 		kbd_table[i].ledflagstate = kbd_defleds();
1626*4882a593Smuzhiyun 		kbd_table[i].default_ledflagstate = kbd_defleds();
1627*4882a593Smuzhiyun 		kbd_table[i].ledmode = LED_SHOW_FLAGS;
1628*4882a593Smuzhiyun 		kbd_table[i].lockstate = KBD_DEFLOCK;
1629*4882a593Smuzhiyun 		kbd_table[i].slockstate = 0;
1630*4882a593Smuzhiyun 		kbd_table[i].modeflags = KBD_DEFMODE;
1631*4882a593Smuzhiyun 		kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
1632*4882a593Smuzhiyun 	}
1633*4882a593Smuzhiyun 
1634*4882a593Smuzhiyun 	kbd_init_leds();
1635*4882a593Smuzhiyun 
1636*4882a593Smuzhiyun 	error = input_register_handler(&kbd_handler);
1637*4882a593Smuzhiyun 	if (error)
1638*4882a593Smuzhiyun 		return error;
1639*4882a593Smuzhiyun 
1640*4882a593Smuzhiyun 	tasklet_enable(&keyboard_tasklet);
1641*4882a593Smuzhiyun 	tasklet_schedule(&keyboard_tasklet);
1642*4882a593Smuzhiyun 
1643*4882a593Smuzhiyun 	return 0;
1644*4882a593Smuzhiyun }
1645*4882a593Smuzhiyun 
1646*4882a593Smuzhiyun /* Ioctl support code */
1647*4882a593Smuzhiyun 
1648*4882a593Smuzhiyun /**
1649*4882a593Smuzhiyun  *	vt_do_diacrit		-	diacritical table updates
1650*4882a593Smuzhiyun  *	@cmd: ioctl request
1651*4882a593Smuzhiyun  *	@udp: pointer to user data for ioctl
1652*4882a593Smuzhiyun  *	@perm: permissions check computed by caller
1653*4882a593Smuzhiyun  *
1654*4882a593Smuzhiyun  *	Update the diacritical tables atomically and safely. Lock them
1655*4882a593Smuzhiyun  *	against simultaneous keypresses
1656*4882a593Smuzhiyun  */
vt_do_diacrit(unsigned int cmd,void __user * udp,int perm)1657*4882a593Smuzhiyun int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
1658*4882a593Smuzhiyun {
1659*4882a593Smuzhiyun 	unsigned long flags;
1660*4882a593Smuzhiyun 	int asize;
1661*4882a593Smuzhiyun 	int ret = 0;
1662*4882a593Smuzhiyun 
1663*4882a593Smuzhiyun 	switch (cmd) {
1664*4882a593Smuzhiyun 	case KDGKBDIACR:
1665*4882a593Smuzhiyun 	{
1666*4882a593Smuzhiyun 		struct kbdiacrs __user *a = udp;
1667*4882a593Smuzhiyun 		struct kbdiacr *dia;
1668*4882a593Smuzhiyun 		int i;
1669*4882a593Smuzhiyun 
1670*4882a593Smuzhiyun 		dia = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacr),
1671*4882a593Smuzhiyun 								GFP_KERNEL);
1672*4882a593Smuzhiyun 		if (!dia)
1673*4882a593Smuzhiyun 			return -ENOMEM;
1674*4882a593Smuzhiyun 
1675*4882a593Smuzhiyun 		/* Lock the diacriticals table, make a copy and then
1676*4882a593Smuzhiyun 		   copy it after we unlock */
1677*4882a593Smuzhiyun 		spin_lock_irqsave(&kbd_event_lock, flags);
1678*4882a593Smuzhiyun 
1679*4882a593Smuzhiyun 		asize = accent_table_size;
1680*4882a593Smuzhiyun 		for (i = 0; i < asize; i++) {
1681*4882a593Smuzhiyun 			dia[i].diacr = conv_uni_to_8bit(
1682*4882a593Smuzhiyun 						accent_table[i].diacr);
1683*4882a593Smuzhiyun 			dia[i].base = conv_uni_to_8bit(
1684*4882a593Smuzhiyun 						accent_table[i].base);
1685*4882a593Smuzhiyun 			dia[i].result = conv_uni_to_8bit(
1686*4882a593Smuzhiyun 						accent_table[i].result);
1687*4882a593Smuzhiyun 		}
1688*4882a593Smuzhiyun 		spin_unlock_irqrestore(&kbd_event_lock, flags);
1689*4882a593Smuzhiyun 
1690*4882a593Smuzhiyun 		if (put_user(asize, &a->kb_cnt))
1691*4882a593Smuzhiyun 			ret = -EFAULT;
1692*4882a593Smuzhiyun 		else  if (copy_to_user(a->kbdiacr, dia,
1693*4882a593Smuzhiyun 				asize * sizeof(struct kbdiacr)))
1694*4882a593Smuzhiyun 			ret = -EFAULT;
1695*4882a593Smuzhiyun 		kfree(dia);
1696*4882a593Smuzhiyun 		return ret;
1697*4882a593Smuzhiyun 	}
1698*4882a593Smuzhiyun 	case KDGKBDIACRUC:
1699*4882a593Smuzhiyun 	{
1700*4882a593Smuzhiyun 		struct kbdiacrsuc __user *a = udp;
1701*4882a593Smuzhiyun 		void *buf;
1702*4882a593Smuzhiyun 
1703*4882a593Smuzhiyun 		buf = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacruc),
1704*4882a593Smuzhiyun 								GFP_KERNEL);
1705*4882a593Smuzhiyun 		if (buf == NULL)
1706*4882a593Smuzhiyun 			return -ENOMEM;
1707*4882a593Smuzhiyun 
1708*4882a593Smuzhiyun 		/* Lock the diacriticals table, make a copy and then
1709*4882a593Smuzhiyun 		   copy it after we unlock */
1710*4882a593Smuzhiyun 		spin_lock_irqsave(&kbd_event_lock, flags);
1711*4882a593Smuzhiyun 
1712*4882a593Smuzhiyun 		asize = accent_table_size;
1713*4882a593Smuzhiyun 		memcpy(buf, accent_table, asize * sizeof(struct kbdiacruc));
1714*4882a593Smuzhiyun 
1715*4882a593Smuzhiyun 		spin_unlock_irqrestore(&kbd_event_lock, flags);
1716*4882a593Smuzhiyun 
1717*4882a593Smuzhiyun 		if (put_user(asize, &a->kb_cnt))
1718*4882a593Smuzhiyun 			ret = -EFAULT;
1719*4882a593Smuzhiyun 		else if (copy_to_user(a->kbdiacruc, buf,
1720*4882a593Smuzhiyun 				asize*sizeof(struct kbdiacruc)))
1721*4882a593Smuzhiyun 			ret = -EFAULT;
1722*4882a593Smuzhiyun 		kfree(buf);
1723*4882a593Smuzhiyun 		return ret;
1724*4882a593Smuzhiyun 	}
1725*4882a593Smuzhiyun 
1726*4882a593Smuzhiyun 	case KDSKBDIACR:
1727*4882a593Smuzhiyun 	{
1728*4882a593Smuzhiyun 		struct kbdiacrs __user *a = udp;
1729*4882a593Smuzhiyun 		struct kbdiacr *dia = NULL;
1730*4882a593Smuzhiyun 		unsigned int ct;
1731*4882a593Smuzhiyun 		int i;
1732*4882a593Smuzhiyun 
1733*4882a593Smuzhiyun 		if (!perm)
1734*4882a593Smuzhiyun 			return -EPERM;
1735*4882a593Smuzhiyun 		if (get_user(ct, &a->kb_cnt))
1736*4882a593Smuzhiyun 			return -EFAULT;
1737*4882a593Smuzhiyun 		if (ct >= MAX_DIACR)
1738*4882a593Smuzhiyun 			return -EINVAL;
1739*4882a593Smuzhiyun 
1740*4882a593Smuzhiyun 		if (ct) {
1741*4882a593Smuzhiyun 
1742*4882a593Smuzhiyun 			dia = memdup_user(a->kbdiacr,
1743*4882a593Smuzhiyun 					sizeof(struct kbdiacr) * ct);
1744*4882a593Smuzhiyun 			if (IS_ERR(dia))
1745*4882a593Smuzhiyun 				return PTR_ERR(dia);
1746*4882a593Smuzhiyun 
1747*4882a593Smuzhiyun 		}
1748*4882a593Smuzhiyun 
1749*4882a593Smuzhiyun 		spin_lock_irqsave(&kbd_event_lock, flags);
1750*4882a593Smuzhiyun 		accent_table_size = ct;
1751*4882a593Smuzhiyun 		for (i = 0; i < ct; i++) {
1752*4882a593Smuzhiyun 			accent_table[i].diacr =
1753*4882a593Smuzhiyun 					conv_8bit_to_uni(dia[i].diacr);
1754*4882a593Smuzhiyun 			accent_table[i].base =
1755*4882a593Smuzhiyun 					conv_8bit_to_uni(dia[i].base);
1756*4882a593Smuzhiyun 			accent_table[i].result =
1757*4882a593Smuzhiyun 					conv_8bit_to_uni(dia[i].result);
1758*4882a593Smuzhiyun 		}
1759*4882a593Smuzhiyun 		spin_unlock_irqrestore(&kbd_event_lock, flags);
1760*4882a593Smuzhiyun 		kfree(dia);
1761*4882a593Smuzhiyun 		return 0;
1762*4882a593Smuzhiyun 	}
1763*4882a593Smuzhiyun 
1764*4882a593Smuzhiyun 	case KDSKBDIACRUC:
1765*4882a593Smuzhiyun 	{
1766*4882a593Smuzhiyun 		struct kbdiacrsuc __user *a = udp;
1767*4882a593Smuzhiyun 		unsigned int ct;
1768*4882a593Smuzhiyun 		void *buf = NULL;
1769*4882a593Smuzhiyun 
1770*4882a593Smuzhiyun 		if (!perm)
1771*4882a593Smuzhiyun 			return -EPERM;
1772*4882a593Smuzhiyun 
1773*4882a593Smuzhiyun 		if (get_user(ct, &a->kb_cnt))
1774*4882a593Smuzhiyun 			return -EFAULT;
1775*4882a593Smuzhiyun 
1776*4882a593Smuzhiyun 		if (ct >= MAX_DIACR)
1777*4882a593Smuzhiyun 			return -EINVAL;
1778*4882a593Smuzhiyun 
1779*4882a593Smuzhiyun 		if (ct) {
1780*4882a593Smuzhiyun 			buf = memdup_user(a->kbdiacruc,
1781*4882a593Smuzhiyun 					  ct * sizeof(struct kbdiacruc));
1782*4882a593Smuzhiyun 			if (IS_ERR(buf))
1783*4882a593Smuzhiyun 				return PTR_ERR(buf);
1784*4882a593Smuzhiyun 		}
1785*4882a593Smuzhiyun 		spin_lock_irqsave(&kbd_event_lock, flags);
1786*4882a593Smuzhiyun 		if (ct)
1787*4882a593Smuzhiyun 			memcpy(accent_table, buf,
1788*4882a593Smuzhiyun 					ct * sizeof(struct kbdiacruc));
1789*4882a593Smuzhiyun 		accent_table_size = ct;
1790*4882a593Smuzhiyun 		spin_unlock_irqrestore(&kbd_event_lock, flags);
1791*4882a593Smuzhiyun 		kfree(buf);
1792*4882a593Smuzhiyun 		return 0;
1793*4882a593Smuzhiyun 	}
1794*4882a593Smuzhiyun 	}
1795*4882a593Smuzhiyun 	return ret;
1796*4882a593Smuzhiyun }
1797*4882a593Smuzhiyun 
1798*4882a593Smuzhiyun /**
1799*4882a593Smuzhiyun  *	vt_do_kdskbmode		-	set keyboard mode ioctl
1800*4882a593Smuzhiyun  *	@console: the console to use
1801*4882a593Smuzhiyun  *	@arg: the requested mode
1802*4882a593Smuzhiyun  *
1803*4882a593Smuzhiyun  *	Update the keyboard mode bits while holding the correct locks.
1804*4882a593Smuzhiyun  *	Return 0 for success or an error code.
1805*4882a593Smuzhiyun  */
vt_do_kdskbmode(int console,unsigned int arg)1806*4882a593Smuzhiyun int vt_do_kdskbmode(int console, unsigned int arg)
1807*4882a593Smuzhiyun {
1808*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
1809*4882a593Smuzhiyun 	int ret = 0;
1810*4882a593Smuzhiyun 	unsigned long flags;
1811*4882a593Smuzhiyun 
1812*4882a593Smuzhiyun 	spin_lock_irqsave(&kbd_event_lock, flags);
1813*4882a593Smuzhiyun 	switch(arg) {
1814*4882a593Smuzhiyun 	case K_RAW:
1815*4882a593Smuzhiyun 		kb->kbdmode = VC_RAW;
1816*4882a593Smuzhiyun 		break;
1817*4882a593Smuzhiyun 	case K_MEDIUMRAW:
1818*4882a593Smuzhiyun 		kb->kbdmode = VC_MEDIUMRAW;
1819*4882a593Smuzhiyun 		break;
1820*4882a593Smuzhiyun 	case K_XLATE:
1821*4882a593Smuzhiyun 		kb->kbdmode = VC_XLATE;
1822*4882a593Smuzhiyun 		do_compute_shiftstate();
1823*4882a593Smuzhiyun 		break;
1824*4882a593Smuzhiyun 	case K_UNICODE:
1825*4882a593Smuzhiyun 		kb->kbdmode = VC_UNICODE;
1826*4882a593Smuzhiyun 		do_compute_shiftstate();
1827*4882a593Smuzhiyun 		break;
1828*4882a593Smuzhiyun 	case K_OFF:
1829*4882a593Smuzhiyun 		kb->kbdmode = VC_OFF;
1830*4882a593Smuzhiyun 		break;
1831*4882a593Smuzhiyun 	default:
1832*4882a593Smuzhiyun 		ret = -EINVAL;
1833*4882a593Smuzhiyun 	}
1834*4882a593Smuzhiyun 	spin_unlock_irqrestore(&kbd_event_lock, flags);
1835*4882a593Smuzhiyun 	return ret;
1836*4882a593Smuzhiyun }
1837*4882a593Smuzhiyun 
1838*4882a593Smuzhiyun /**
1839*4882a593Smuzhiyun  *	vt_do_kdskbmeta		-	set keyboard meta state
1840*4882a593Smuzhiyun  *	@console: the console to use
1841*4882a593Smuzhiyun  *	@arg: the requested meta state
1842*4882a593Smuzhiyun  *
1843*4882a593Smuzhiyun  *	Update the keyboard meta bits while holding the correct locks.
1844*4882a593Smuzhiyun  *	Return 0 for success or an error code.
1845*4882a593Smuzhiyun  */
vt_do_kdskbmeta(int console,unsigned int arg)1846*4882a593Smuzhiyun int vt_do_kdskbmeta(int console, unsigned int arg)
1847*4882a593Smuzhiyun {
1848*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
1849*4882a593Smuzhiyun 	int ret = 0;
1850*4882a593Smuzhiyun 	unsigned long flags;
1851*4882a593Smuzhiyun 
1852*4882a593Smuzhiyun 	spin_lock_irqsave(&kbd_event_lock, flags);
1853*4882a593Smuzhiyun 	switch(arg) {
1854*4882a593Smuzhiyun 	case K_METABIT:
1855*4882a593Smuzhiyun 		clr_vc_kbd_mode(kb, VC_META);
1856*4882a593Smuzhiyun 		break;
1857*4882a593Smuzhiyun 	case K_ESCPREFIX:
1858*4882a593Smuzhiyun 		set_vc_kbd_mode(kb, VC_META);
1859*4882a593Smuzhiyun 		break;
1860*4882a593Smuzhiyun 	default:
1861*4882a593Smuzhiyun 		ret = -EINVAL;
1862*4882a593Smuzhiyun 	}
1863*4882a593Smuzhiyun 	spin_unlock_irqrestore(&kbd_event_lock, flags);
1864*4882a593Smuzhiyun 	return ret;
1865*4882a593Smuzhiyun }
1866*4882a593Smuzhiyun 
vt_do_kbkeycode_ioctl(int cmd,struct kbkeycode __user * user_kbkc,int perm)1867*4882a593Smuzhiyun int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
1868*4882a593Smuzhiyun 								int perm)
1869*4882a593Smuzhiyun {
1870*4882a593Smuzhiyun 	struct kbkeycode tmp;
1871*4882a593Smuzhiyun 	int kc = 0;
1872*4882a593Smuzhiyun 
1873*4882a593Smuzhiyun 	if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
1874*4882a593Smuzhiyun 		return -EFAULT;
1875*4882a593Smuzhiyun 	switch (cmd) {
1876*4882a593Smuzhiyun 	case KDGETKEYCODE:
1877*4882a593Smuzhiyun 		kc = getkeycode(tmp.scancode);
1878*4882a593Smuzhiyun 		if (kc >= 0)
1879*4882a593Smuzhiyun 			kc = put_user(kc, &user_kbkc->keycode);
1880*4882a593Smuzhiyun 		break;
1881*4882a593Smuzhiyun 	case KDSETKEYCODE:
1882*4882a593Smuzhiyun 		if (!perm)
1883*4882a593Smuzhiyun 			return -EPERM;
1884*4882a593Smuzhiyun 		kc = setkeycode(tmp.scancode, tmp.keycode);
1885*4882a593Smuzhiyun 		break;
1886*4882a593Smuzhiyun 	}
1887*4882a593Smuzhiyun 	return kc;
1888*4882a593Smuzhiyun }
1889*4882a593Smuzhiyun 
1890*4882a593Smuzhiyun #define i (tmp.kb_index)
1891*4882a593Smuzhiyun #define s (tmp.kb_table)
1892*4882a593Smuzhiyun #define v (tmp.kb_value)
1893*4882a593Smuzhiyun 
vt_do_kdsk_ioctl(int cmd,struct kbentry __user * user_kbe,int perm,int console)1894*4882a593Smuzhiyun int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
1895*4882a593Smuzhiyun 						int console)
1896*4882a593Smuzhiyun {
1897*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
1898*4882a593Smuzhiyun 	struct kbentry tmp;
1899*4882a593Smuzhiyun 	ushort *key_map, *new_map, val, ov;
1900*4882a593Smuzhiyun 	unsigned long flags;
1901*4882a593Smuzhiyun 
1902*4882a593Smuzhiyun 	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
1903*4882a593Smuzhiyun 		return -EFAULT;
1904*4882a593Smuzhiyun 
1905*4882a593Smuzhiyun 	if (!capable(CAP_SYS_TTY_CONFIG))
1906*4882a593Smuzhiyun 		perm = 0;
1907*4882a593Smuzhiyun 
1908*4882a593Smuzhiyun 	switch (cmd) {
1909*4882a593Smuzhiyun 	case KDGKBENT:
1910*4882a593Smuzhiyun 		/* Ensure another thread doesn't free it under us */
1911*4882a593Smuzhiyun 		spin_lock_irqsave(&kbd_event_lock, flags);
1912*4882a593Smuzhiyun 		key_map = key_maps[s];
1913*4882a593Smuzhiyun 		if (key_map) {
1914*4882a593Smuzhiyun 		    val = U(key_map[i]);
1915*4882a593Smuzhiyun 		    if (kb->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
1916*4882a593Smuzhiyun 			val = K_HOLE;
1917*4882a593Smuzhiyun 		} else
1918*4882a593Smuzhiyun 		    val = (i ? K_HOLE : K_NOSUCHMAP);
1919*4882a593Smuzhiyun 		spin_unlock_irqrestore(&kbd_event_lock, flags);
1920*4882a593Smuzhiyun 		return put_user(val, &user_kbe->kb_value);
1921*4882a593Smuzhiyun 	case KDSKBENT:
1922*4882a593Smuzhiyun 		if (!perm)
1923*4882a593Smuzhiyun 			return -EPERM;
1924*4882a593Smuzhiyun 		if (!i && v == K_NOSUCHMAP) {
1925*4882a593Smuzhiyun 			spin_lock_irqsave(&kbd_event_lock, flags);
1926*4882a593Smuzhiyun 			/* deallocate map */
1927*4882a593Smuzhiyun 			key_map = key_maps[s];
1928*4882a593Smuzhiyun 			if (s && key_map) {
1929*4882a593Smuzhiyun 			    key_maps[s] = NULL;
1930*4882a593Smuzhiyun 			    if (key_map[0] == U(K_ALLOCATED)) {
1931*4882a593Smuzhiyun 					kfree(key_map);
1932*4882a593Smuzhiyun 					keymap_count--;
1933*4882a593Smuzhiyun 			    }
1934*4882a593Smuzhiyun 			}
1935*4882a593Smuzhiyun 			spin_unlock_irqrestore(&kbd_event_lock, flags);
1936*4882a593Smuzhiyun 			break;
1937*4882a593Smuzhiyun 		}
1938*4882a593Smuzhiyun 
1939*4882a593Smuzhiyun 		if (KTYP(v) < NR_TYPES) {
1940*4882a593Smuzhiyun 		    if (KVAL(v) > max_vals[KTYP(v)])
1941*4882a593Smuzhiyun 				return -EINVAL;
1942*4882a593Smuzhiyun 		} else
1943*4882a593Smuzhiyun 		    if (kb->kbdmode != VC_UNICODE)
1944*4882a593Smuzhiyun 				return -EINVAL;
1945*4882a593Smuzhiyun 
1946*4882a593Smuzhiyun 		/* ++Geert: non-PC keyboards may generate keycode zero */
1947*4882a593Smuzhiyun #if !defined(__mc68000__) && !defined(__powerpc__)
1948*4882a593Smuzhiyun 		/* assignment to entry 0 only tests validity of args */
1949*4882a593Smuzhiyun 		if (!i)
1950*4882a593Smuzhiyun 			break;
1951*4882a593Smuzhiyun #endif
1952*4882a593Smuzhiyun 
1953*4882a593Smuzhiyun 		new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
1954*4882a593Smuzhiyun 		if (!new_map)
1955*4882a593Smuzhiyun 			return -ENOMEM;
1956*4882a593Smuzhiyun 		spin_lock_irqsave(&kbd_event_lock, flags);
1957*4882a593Smuzhiyun 		key_map = key_maps[s];
1958*4882a593Smuzhiyun 		if (key_map == NULL) {
1959*4882a593Smuzhiyun 			int j;
1960*4882a593Smuzhiyun 
1961*4882a593Smuzhiyun 			if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
1962*4882a593Smuzhiyun 			    !capable(CAP_SYS_RESOURCE)) {
1963*4882a593Smuzhiyun 				spin_unlock_irqrestore(&kbd_event_lock, flags);
1964*4882a593Smuzhiyun 				kfree(new_map);
1965*4882a593Smuzhiyun 				return -EPERM;
1966*4882a593Smuzhiyun 			}
1967*4882a593Smuzhiyun 			key_maps[s] = new_map;
1968*4882a593Smuzhiyun 			key_map = new_map;
1969*4882a593Smuzhiyun 			key_map[0] = U(K_ALLOCATED);
1970*4882a593Smuzhiyun 			for (j = 1; j < NR_KEYS; j++)
1971*4882a593Smuzhiyun 				key_map[j] = U(K_HOLE);
1972*4882a593Smuzhiyun 			keymap_count++;
1973*4882a593Smuzhiyun 		} else
1974*4882a593Smuzhiyun 			kfree(new_map);
1975*4882a593Smuzhiyun 
1976*4882a593Smuzhiyun 		ov = U(key_map[i]);
1977*4882a593Smuzhiyun 		if (v == ov)
1978*4882a593Smuzhiyun 			goto out;
1979*4882a593Smuzhiyun 		/*
1980*4882a593Smuzhiyun 		 * Attention Key.
1981*4882a593Smuzhiyun 		 */
1982*4882a593Smuzhiyun 		if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) {
1983*4882a593Smuzhiyun 			spin_unlock_irqrestore(&kbd_event_lock, flags);
1984*4882a593Smuzhiyun 			return -EPERM;
1985*4882a593Smuzhiyun 		}
1986*4882a593Smuzhiyun 		key_map[i] = U(v);
1987*4882a593Smuzhiyun 		if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
1988*4882a593Smuzhiyun 			do_compute_shiftstate();
1989*4882a593Smuzhiyun out:
1990*4882a593Smuzhiyun 		spin_unlock_irqrestore(&kbd_event_lock, flags);
1991*4882a593Smuzhiyun 		break;
1992*4882a593Smuzhiyun 	}
1993*4882a593Smuzhiyun 	return 0;
1994*4882a593Smuzhiyun }
1995*4882a593Smuzhiyun #undef i
1996*4882a593Smuzhiyun #undef s
1997*4882a593Smuzhiyun #undef v
1998*4882a593Smuzhiyun 
1999*4882a593Smuzhiyun /* FIXME: This one needs untangling */
vt_do_kdgkb_ioctl(int cmd,struct kbsentry __user * user_kdgkb,int perm)2000*4882a593Smuzhiyun int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
2001*4882a593Smuzhiyun {
2002*4882a593Smuzhiyun 	struct kbsentry *kbs;
2003*4882a593Smuzhiyun 	u_char *q;
2004*4882a593Smuzhiyun 	int sz, fnw_sz;
2005*4882a593Smuzhiyun 	int delta;
2006*4882a593Smuzhiyun 	char *first_free, *fj, *fnw;
2007*4882a593Smuzhiyun 	int i, j, k;
2008*4882a593Smuzhiyun 	int ret;
2009*4882a593Smuzhiyun 	unsigned long flags;
2010*4882a593Smuzhiyun 
2011*4882a593Smuzhiyun 	if (!capable(CAP_SYS_TTY_CONFIG))
2012*4882a593Smuzhiyun 		perm = 0;
2013*4882a593Smuzhiyun 
2014*4882a593Smuzhiyun 	kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
2015*4882a593Smuzhiyun 	if (!kbs) {
2016*4882a593Smuzhiyun 		ret = -ENOMEM;
2017*4882a593Smuzhiyun 		goto reterr;
2018*4882a593Smuzhiyun 	}
2019*4882a593Smuzhiyun 
2020*4882a593Smuzhiyun 	/* we mostly copy too much here (512bytes), but who cares ;) */
2021*4882a593Smuzhiyun 	if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
2022*4882a593Smuzhiyun 		ret = -EFAULT;
2023*4882a593Smuzhiyun 		goto reterr;
2024*4882a593Smuzhiyun 	}
2025*4882a593Smuzhiyun 	kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
2026*4882a593Smuzhiyun 	i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC);
2027*4882a593Smuzhiyun 
2028*4882a593Smuzhiyun 	switch (cmd) {
2029*4882a593Smuzhiyun 	case KDGKBSENT: {
2030*4882a593Smuzhiyun 		/* size should have been a struct member */
2031*4882a593Smuzhiyun 		ssize_t len = sizeof(user_kdgkb->kb_string);
2032*4882a593Smuzhiyun 
2033*4882a593Smuzhiyun 		spin_lock_irqsave(&func_buf_lock, flags);
2034*4882a593Smuzhiyun 		len = strlcpy(kbs->kb_string, func_table[i] ? : "", len);
2035*4882a593Smuzhiyun 		spin_unlock_irqrestore(&func_buf_lock, flags);
2036*4882a593Smuzhiyun 
2037*4882a593Smuzhiyun 		ret = copy_to_user(user_kdgkb->kb_string, kbs->kb_string,
2038*4882a593Smuzhiyun 				len + 1) ? -EFAULT : 0;
2039*4882a593Smuzhiyun 
2040*4882a593Smuzhiyun 		goto reterr;
2041*4882a593Smuzhiyun 	}
2042*4882a593Smuzhiyun 	case KDSKBSENT:
2043*4882a593Smuzhiyun 		if (!perm) {
2044*4882a593Smuzhiyun 			ret = -EPERM;
2045*4882a593Smuzhiyun 			goto reterr;
2046*4882a593Smuzhiyun 		}
2047*4882a593Smuzhiyun 
2048*4882a593Smuzhiyun 		fnw = NULL;
2049*4882a593Smuzhiyun 		fnw_sz = 0;
2050*4882a593Smuzhiyun 		/* race aginst other writers */
2051*4882a593Smuzhiyun 		again:
2052*4882a593Smuzhiyun 		spin_lock_irqsave(&func_buf_lock, flags);
2053*4882a593Smuzhiyun 		q = func_table[i];
2054*4882a593Smuzhiyun 
2055*4882a593Smuzhiyun 		/* fj pointer to next entry after 'q' */
2056*4882a593Smuzhiyun 		first_free = funcbufptr + (funcbufsize - funcbufleft);
2057*4882a593Smuzhiyun 		for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
2058*4882a593Smuzhiyun 			;
2059*4882a593Smuzhiyun 		if (j < MAX_NR_FUNC)
2060*4882a593Smuzhiyun 			fj = func_table[j];
2061*4882a593Smuzhiyun 		else
2062*4882a593Smuzhiyun 			fj = first_free;
2063*4882a593Smuzhiyun 		/* buffer usage increase by new entry */
2064*4882a593Smuzhiyun 		delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string);
2065*4882a593Smuzhiyun 
2066*4882a593Smuzhiyun 		if (delta <= funcbufleft) { 	/* it fits in current buf */
2067*4882a593Smuzhiyun 		    if (j < MAX_NR_FUNC) {
2068*4882a593Smuzhiyun 			/* make enough space for new entry at 'fj' */
2069*4882a593Smuzhiyun 			memmove(fj + delta, fj, first_free - fj);
2070*4882a593Smuzhiyun 			for (k = j; k < MAX_NR_FUNC; k++)
2071*4882a593Smuzhiyun 			    if (func_table[k])
2072*4882a593Smuzhiyun 				func_table[k] += delta;
2073*4882a593Smuzhiyun 		    }
2074*4882a593Smuzhiyun 		    if (!q)
2075*4882a593Smuzhiyun 		      func_table[i] = fj;
2076*4882a593Smuzhiyun 		    funcbufleft -= delta;
2077*4882a593Smuzhiyun 		} else {			/* allocate a larger buffer */
2078*4882a593Smuzhiyun 		    sz = 256;
2079*4882a593Smuzhiyun 		    while (sz < funcbufsize - funcbufleft + delta)
2080*4882a593Smuzhiyun 		      sz <<= 1;
2081*4882a593Smuzhiyun 		    if (fnw_sz != sz) {
2082*4882a593Smuzhiyun 		      spin_unlock_irqrestore(&func_buf_lock, flags);
2083*4882a593Smuzhiyun 		      kfree(fnw);
2084*4882a593Smuzhiyun 		      fnw = kmalloc(sz, GFP_KERNEL);
2085*4882a593Smuzhiyun 		      fnw_sz = sz;
2086*4882a593Smuzhiyun 		      if (!fnw) {
2087*4882a593Smuzhiyun 			ret = -ENOMEM;
2088*4882a593Smuzhiyun 			goto reterr;
2089*4882a593Smuzhiyun 		      }
2090*4882a593Smuzhiyun 		      goto again;
2091*4882a593Smuzhiyun 		    }
2092*4882a593Smuzhiyun 
2093*4882a593Smuzhiyun 		    if (!q)
2094*4882a593Smuzhiyun 		      func_table[i] = fj;
2095*4882a593Smuzhiyun 		    /* copy data before insertion point to new location */
2096*4882a593Smuzhiyun 		    if (fj > funcbufptr)
2097*4882a593Smuzhiyun 			memmove(fnw, funcbufptr, fj - funcbufptr);
2098*4882a593Smuzhiyun 		    for (k = 0; k < j; k++)
2099*4882a593Smuzhiyun 		      if (func_table[k])
2100*4882a593Smuzhiyun 			func_table[k] = fnw + (func_table[k] - funcbufptr);
2101*4882a593Smuzhiyun 
2102*4882a593Smuzhiyun 		    /* copy data after insertion point to new location */
2103*4882a593Smuzhiyun 		    if (first_free > fj) {
2104*4882a593Smuzhiyun 			memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
2105*4882a593Smuzhiyun 			for (k = j; k < MAX_NR_FUNC; k++)
2106*4882a593Smuzhiyun 			  if (func_table[k])
2107*4882a593Smuzhiyun 			    func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
2108*4882a593Smuzhiyun 		    }
2109*4882a593Smuzhiyun 		    if (funcbufptr != func_buf)
2110*4882a593Smuzhiyun 		      kfree(funcbufptr);
2111*4882a593Smuzhiyun 		    funcbufptr = fnw;
2112*4882a593Smuzhiyun 		    funcbufleft = funcbufleft - delta + sz - funcbufsize;
2113*4882a593Smuzhiyun 		    funcbufsize = sz;
2114*4882a593Smuzhiyun 		}
2115*4882a593Smuzhiyun 		/* finally insert item itself */
2116*4882a593Smuzhiyun 		strcpy(func_table[i], kbs->kb_string);
2117*4882a593Smuzhiyun 		spin_unlock_irqrestore(&func_buf_lock, flags);
2118*4882a593Smuzhiyun 		break;
2119*4882a593Smuzhiyun 	}
2120*4882a593Smuzhiyun 	ret = 0;
2121*4882a593Smuzhiyun reterr:
2122*4882a593Smuzhiyun 	kfree(kbs);
2123*4882a593Smuzhiyun 	return ret;
2124*4882a593Smuzhiyun }
2125*4882a593Smuzhiyun 
vt_do_kdskled(int console,int cmd,unsigned long arg,int perm)2126*4882a593Smuzhiyun int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
2127*4882a593Smuzhiyun {
2128*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
2129*4882a593Smuzhiyun         unsigned long flags;
2130*4882a593Smuzhiyun 	unsigned char ucval;
2131*4882a593Smuzhiyun 
2132*4882a593Smuzhiyun         switch(cmd) {
2133*4882a593Smuzhiyun 	/* the ioctls below read/set the flags usually shown in the leds */
2134*4882a593Smuzhiyun 	/* don't use them - they will go away without warning */
2135*4882a593Smuzhiyun 	case KDGKBLED:
2136*4882a593Smuzhiyun                 spin_lock_irqsave(&kbd_event_lock, flags);
2137*4882a593Smuzhiyun 		ucval = kb->ledflagstate | (kb->default_ledflagstate << 4);
2138*4882a593Smuzhiyun                 spin_unlock_irqrestore(&kbd_event_lock, flags);
2139*4882a593Smuzhiyun 		return put_user(ucval, (char __user *)arg);
2140*4882a593Smuzhiyun 
2141*4882a593Smuzhiyun 	case KDSKBLED:
2142*4882a593Smuzhiyun 		if (!perm)
2143*4882a593Smuzhiyun 			return -EPERM;
2144*4882a593Smuzhiyun 		if (arg & ~0x77)
2145*4882a593Smuzhiyun 			return -EINVAL;
2146*4882a593Smuzhiyun                 spin_lock_irqsave(&led_lock, flags);
2147*4882a593Smuzhiyun 		kb->ledflagstate = (arg & 7);
2148*4882a593Smuzhiyun 		kb->default_ledflagstate = ((arg >> 4) & 7);
2149*4882a593Smuzhiyun 		set_leds();
2150*4882a593Smuzhiyun                 spin_unlock_irqrestore(&led_lock, flags);
2151*4882a593Smuzhiyun 		return 0;
2152*4882a593Smuzhiyun 
2153*4882a593Smuzhiyun 	/* the ioctls below only set the lights, not the functions */
2154*4882a593Smuzhiyun 	/* for those, see KDGKBLED and KDSKBLED above */
2155*4882a593Smuzhiyun 	case KDGETLED:
2156*4882a593Smuzhiyun 		ucval = getledstate();
2157*4882a593Smuzhiyun 		return put_user(ucval, (char __user *)arg);
2158*4882a593Smuzhiyun 
2159*4882a593Smuzhiyun 	case KDSETLED:
2160*4882a593Smuzhiyun 		if (!perm)
2161*4882a593Smuzhiyun 			return -EPERM;
2162*4882a593Smuzhiyun 		setledstate(kb, arg);
2163*4882a593Smuzhiyun 		return 0;
2164*4882a593Smuzhiyun         }
2165*4882a593Smuzhiyun         return -ENOIOCTLCMD;
2166*4882a593Smuzhiyun }
2167*4882a593Smuzhiyun 
vt_do_kdgkbmode(int console)2168*4882a593Smuzhiyun int vt_do_kdgkbmode(int console)
2169*4882a593Smuzhiyun {
2170*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
2171*4882a593Smuzhiyun 	/* This is a spot read so needs no locking */
2172*4882a593Smuzhiyun 	switch (kb->kbdmode) {
2173*4882a593Smuzhiyun 	case VC_RAW:
2174*4882a593Smuzhiyun 		return K_RAW;
2175*4882a593Smuzhiyun 	case VC_MEDIUMRAW:
2176*4882a593Smuzhiyun 		return K_MEDIUMRAW;
2177*4882a593Smuzhiyun 	case VC_UNICODE:
2178*4882a593Smuzhiyun 		return K_UNICODE;
2179*4882a593Smuzhiyun 	case VC_OFF:
2180*4882a593Smuzhiyun 		return K_OFF;
2181*4882a593Smuzhiyun 	default:
2182*4882a593Smuzhiyun 		return K_XLATE;
2183*4882a593Smuzhiyun 	}
2184*4882a593Smuzhiyun }
2185*4882a593Smuzhiyun 
2186*4882a593Smuzhiyun /**
2187*4882a593Smuzhiyun  *	vt_do_kdgkbmeta		-	report meta status
2188*4882a593Smuzhiyun  *	@console: console to report
2189*4882a593Smuzhiyun  *
2190*4882a593Smuzhiyun  *	Report the meta flag status of this console
2191*4882a593Smuzhiyun  */
vt_do_kdgkbmeta(int console)2192*4882a593Smuzhiyun int vt_do_kdgkbmeta(int console)
2193*4882a593Smuzhiyun {
2194*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
2195*4882a593Smuzhiyun         /* Again a spot read so no locking */
2196*4882a593Smuzhiyun 	return vc_kbd_mode(kb, VC_META) ? K_ESCPREFIX : K_METABIT;
2197*4882a593Smuzhiyun }
2198*4882a593Smuzhiyun 
2199*4882a593Smuzhiyun /**
2200*4882a593Smuzhiyun  *	vt_reset_unicode	-	reset the unicode status
2201*4882a593Smuzhiyun  *	@console: console being reset
2202*4882a593Smuzhiyun  *
2203*4882a593Smuzhiyun  *	Restore the unicode console state to its default
2204*4882a593Smuzhiyun  */
vt_reset_unicode(int console)2205*4882a593Smuzhiyun void vt_reset_unicode(int console)
2206*4882a593Smuzhiyun {
2207*4882a593Smuzhiyun 	unsigned long flags;
2208*4882a593Smuzhiyun 
2209*4882a593Smuzhiyun 	spin_lock_irqsave(&kbd_event_lock, flags);
2210*4882a593Smuzhiyun 	kbd_table[console].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
2211*4882a593Smuzhiyun 	spin_unlock_irqrestore(&kbd_event_lock, flags);
2212*4882a593Smuzhiyun }
2213*4882a593Smuzhiyun 
2214*4882a593Smuzhiyun /**
2215*4882a593Smuzhiyun  *	vt_get_shiftstate	-	shift bit state
2216*4882a593Smuzhiyun  *
2217*4882a593Smuzhiyun  *	Report the shift bits from the keyboard state. We have to export
2218*4882a593Smuzhiyun  *	this to support some oddities in the vt layer.
2219*4882a593Smuzhiyun  */
vt_get_shift_state(void)2220*4882a593Smuzhiyun int vt_get_shift_state(void)
2221*4882a593Smuzhiyun {
2222*4882a593Smuzhiyun         /* Don't lock as this is a transient report */
2223*4882a593Smuzhiyun         return shift_state;
2224*4882a593Smuzhiyun }
2225*4882a593Smuzhiyun 
2226*4882a593Smuzhiyun /**
2227*4882a593Smuzhiyun  *	vt_reset_keyboard	-	reset keyboard state
2228*4882a593Smuzhiyun  *	@console: console to reset
2229*4882a593Smuzhiyun  *
2230*4882a593Smuzhiyun  *	Reset the keyboard bits for a console as part of a general console
2231*4882a593Smuzhiyun  *	reset event
2232*4882a593Smuzhiyun  */
vt_reset_keyboard(int console)2233*4882a593Smuzhiyun void vt_reset_keyboard(int console)
2234*4882a593Smuzhiyun {
2235*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
2236*4882a593Smuzhiyun 	unsigned long flags;
2237*4882a593Smuzhiyun 
2238*4882a593Smuzhiyun 	spin_lock_irqsave(&kbd_event_lock, flags);
2239*4882a593Smuzhiyun 	set_vc_kbd_mode(kb, VC_REPEAT);
2240*4882a593Smuzhiyun 	clr_vc_kbd_mode(kb, VC_CKMODE);
2241*4882a593Smuzhiyun 	clr_vc_kbd_mode(kb, VC_APPLIC);
2242*4882a593Smuzhiyun 	clr_vc_kbd_mode(kb, VC_CRLF);
2243*4882a593Smuzhiyun 	kb->lockstate = 0;
2244*4882a593Smuzhiyun 	kb->slockstate = 0;
2245*4882a593Smuzhiyun 	spin_lock(&led_lock);
2246*4882a593Smuzhiyun 	kb->ledmode = LED_SHOW_FLAGS;
2247*4882a593Smuzhiyun 	kb->ledflagstate = kb->default_ledflagstate;
2248*4882a593Smuzhiyun 	spin_unlock(&led_lock);
2249*4882a593Smuzhiyun 	/* do not do set_leds here because this causes an endless tasklet loop
2250*4882a593Smuzhiyun 	   when the keyboard hasn't been initialized yet */
2251*4882a593Smuzhiyun 	spin_unlock_irqrestore(&kbd_event_lock, flags);
2252*4882a593Smuzhiyun }
2253*4882a593Smuzhiyun 
2254*4882a593Smuzhiyun /**
2255*4882a593Smuzhiyun  *	vt_get_kbd_mode_bit	-	read keyboard status bits
2256*4882a593Smuzhiyun  *	@console: console to read from
2257*4882a593Smuzhiyun  *	@bit: mode bit to read
2258*4882a593Smuzhiyun  *
2259*4882a593Smuzhiyun  *	Report back a vt mode bit. We do this without locking so the
2260*4882a593Smuzhiyun  *	caller must be sure that there are no synchronization needs
2261*4882a593Smuzhiyun  */
2262*4882a593Smuzhiyun 
vt_get_kbd_mode_bit(int console,int bit)2263*4882a593Smuzhiyun int vt_get_kbd_mode_bit(int console, int bit)
2264*4882a593Smuzhiyun {
2265*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
2266*4882a593Smuzhiyun 	return vc_kbd_mode(kb, bit);
2267*4882a593Smuzhiyun }
2268*4882a593Smuzhiyun 
2269*4882a593Smuzhiyun /**
2270*4882a593Smuzhiyun  *	vt_set_kbd_mode_bit	-	read keyboard status bits
2271*4882a593Smuzhiyun  *	@console: console to read from
2272*4882a593Smuzhiyun  *	@bit: mode bit to read
2273*4882a593Smuzhiyun  *
2274*4882a593Smuzhiyun  *	Set a vt mode bit. We do this without locking so the
2275*4882a593Smuzhiyun  *	caller must be sure that there are no synchronization needs
2276*4882a593Smuzhiyun  */
2277*4882a593Smuzhiyun 
vt_set_kbd_mode_bit(int console,int bit)2278*4882a593Smuzhiyun void vt_set_kbd_mode_bit(int console, int bit)
2279*4882a593Smuzhiyun {
2280*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
2281*4882a593Smuzhiyun 	unsigned long flags;
2282*4882a593Smuzhiyun 
2283*4882a593Smuzhiyun 	spin_lock_irqsave(&kbd_event_lock, flags);
2284*4882a593Smuzhiyun 	set_vc_kbd_mode(kb, bit);
2285*4882a593Smuzhiyun 	spin_unlock_irqrestore(&kbd_event_lock, flags);
2286*4882a593Smuzhiyun }
2287*4882a593Smuzhiyun 
2288*4882a593Smuzhiyun /**
2289*4882a593Smuzhiyun  *	vt_clr_kbd_mode_bit	-	read keyboard status bits
2290*4882a593Smuzhiyun  *	@console: console to read from
2291*4882a593Smuzhiyun  *	@bit: mode bit to read
2292*4882a593Smuzhiyun  *
2293*4882a593Smuzhiyun  *	Report back a vt mode bit. We do this without locking so the
2294*4882a593Smuzhiyun  *	caller must be sure that there are no synchronization needs
2295*4882a593Smuzhiyun  */
2296*4882a593Smuzhiyun 
vt_clr_kbd_mode_bit(int console,int bit)2297*4882a593Smuzhiyun void vt_clr_kbd_mode_bit(int console, int bit)
2298*4882a593Smuzhiyun {
2299*4882a593Smuzhiyun 	struct kbd_struct *kb = kbd_table + console;
2300*4882a593Smuzhiyun 	unsigned long flags;
2301*4882a593Smuzhiyun 
2302*4882a593Smuzhiyun 	spin_lock_irqsave(&kbd_event_lock, flags);
2303*4882a593Smuzhiyun 	clr_vc_kbd_mode(kb, bit);
2304*4882a593Smuzhiyun 	spin_unlock_irqrestore(&kbd_event_lock, flags);
2305*4882a593Smuzhiyun }
2306