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, ¶m);
1442*4882a593Smuzhiyun if (rc == NOTIFY_STOP || !key_map) {
1443*4882a593Smuzhiyun atomic_notifier_call_chain(&keyboard_notifier_list,
1444*4882a593Smuzhiyun KBD_UNBOUND_KEYCODE, ¶m);
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, ¶m);
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, ¶m);
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, ¶m);
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