blob: b4e7a7317713b202276e36053d470a9358cea0c7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * Written for linux by Johan Myreen as a translation from
3 * the assembly version by Linus (with diacriticals added)
4 *
5 * Some additional features added by Christoph Niemann (ChN), March 1993
6 *
7 * Loadable keymaps by Risto Kankkunen, May 1993
8 *
9 * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
10 * Added decr/incr_console, dynamic keymaps, Unicode support,
11 * dynamic function/string keys, led setting, Sept 1994
12 * `Sticky' modifier keys, 951006.
13 *
14 * 11-11-96: SAK should now work in the raw mode (Martin Mares)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050015 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 * Modified to provide 'generic' keyboard support by Hamish Macdonald
17 * Merge with the m68k keyboard driver and split-off of the PC low-level
18 * parts by Geert Uytterhoeven, May 1997
19 *
20 * 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
21 * 30-07-98: Dead keys redone, aeb@cwi.nl.
22 * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
23 */
24
Dmitry Torokhov9272e9a2010-03-21 22:31:26 -070025#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
Jan Engelhardt759448f2007-07-15 23:40:40 -070027#include <linux/consolemap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
29#include <linux/sched.h>
30#include <linux/tty.h>
31#include <linux/tty_flip.h>
32#include <linux/mm.h>
33#include <linux/string.h>
34#include <linux/init.h>
35#include <linux/slab.h>
Samuel Thibault52355522015-03-16 21:19:44 -070036#include <linux/leds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
38#include <linux/kbd_kern.h>
39#include <linux/kbd_diacr.h>
40#include <linux/vt_kern.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/input.h>
Adrian Bunk83cc5ed2006-06-25 05:47:41 -070042#include <linux/reboot.h>
Samuel Thibault41ab4392007-10-18 23:39:12 -070043#include <linux/notifier.h>
Julia Lawallb39b0442008-04-17 09:28:25 -040044#include <linux/jiffies.h>
Greg Kroah-Hartman6623d642012-02-27 15:18:56 -080045#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Geert Uytterhoeven98c2b372011-09-11 13:59:29 +020047#include <asm/irq_regs.h>
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049extern void ctrl_alt_del(void);
50
51/*
52 * Exported functions/variables
53 */
54
55#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
56
Joshua Covb2d0b7a2012-04-13 21:08:26 +020057#if defined(CONFIG_X86) || defined(CONFIG_PARISC)
58#include <asm/kbdleds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#else
Joshua Covb2d0b7a2012-04-13 21:08:26 +020060static inline int kbd_defleds(void)
61{
62 return 0;
63}
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#endif
65
66#define KBD_DEFLOCK 0
67
Linus Torvalds1da177e2005-04-16 15:20:36 -070068/*
69 * Handler Tables.
70 */
71
72#define K_HANDLERS\
73 k_self, k_fn, k_spec, k_pad,\
74 k_dead, k_cons, k_cur, k_shift,\
75 k_meta, k_ascii, k_lock, k_lowercase,\
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -050076 k_slock, k_dead2, k_brl, k_ignore
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050078typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
David Howells7d12e782006-10-05 14:55:46 +010079 char up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080static k_handler_fn K_HANDLERS;
Dmitry Torokhov97f5f0c2010-03-21 22:31:26 -070081static k_handler_fn *k_handler[16] = { K_HANDLERS };
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
83#define FN_HANDLERS\
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050084 fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
85 fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
86 fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
87 fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
88 fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
David Howells7d12e782006-10-05 14:55:46 +010090typedef void (fn_handler_fn)(struct vc_data *vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091static fn_handler_fn FN_HANDLERS;
92static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
93
94/*
95 * Variables exported for vt_ioctl.c
96 */
97
Eric W. Biederman81af8d62006-10-02 02:17:13 -070098struct vt_spawn_console vt_spawn_con = {
Milind Arun Choudharyccc94252007-05-08 00:30:09 -070099 .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700100 .pid = NULL,
101 .sig = 0,
102};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
105/*
106 * Internal Data.
107 */
108
Alan Cox079c9532012-02-28 14:49:23 +0000109static struct kbd_struct kbd_table[MAX_NR_CONSOLES];
110static struct kbd_struct *kbd = kbd_table;
111
112/* maximum values each key_handler can handle */
113static const int max_vals[] = {
114 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
115 NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
116 255, NR_LOCK - 1, 255, NR_BRL - 1
117};
118
119static const int NR_TYPES = ARRAY_SIZE(max_vals);
120
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121static struct input_handler kbd_handler;
Dmitry Torokhov21cea582009-11-29 23:40:58 -0800122static DEFINE_SPINLOCK(kbd_event_lock);
Alan Cox3db1ddb2012-07-17 17:06:41 +0100123static DEFINE_SPINLOCK(led_lock);
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +0000124static DEFINE_SPINLOCK(func_buf_lock); /* guard 'func_buf' and friends */
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700125static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
Dmitry Torokhove0785572010-03-21 22:31:26 -0700127static bool dead_key_next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128static int npadch = -1; /* -1 or number assembled on pad */
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500129static unsigned int diacr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130static char rep; /* flag telling character repeat */
131
Alan Cox079c9532012-02-28 14:49:23 +0000132static int shift_state = 0;
133
Samuel Thibaulteeb64c12015-06-06 11:44:39 -0700134static unsigned int ledstate = -1U; /* undefined */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135static unsigned char ledioctl;
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137/*
Samuel Thibault41ab4392007-10-18 23:39:12 -0700138 * Notifier list for console keyboard events
139 */
140static ATOMIC_NOTIFIER_HEAD(keyboard_notifier_list);
141
142int register_keyboard_notifier(struct notifier_block *nb)
143{
144 return atomic_notifier_chain_register(&keyboard_notifier_list, nb);
145}
146EXPORT_SYMBOL_GPL(register_keyboard_notifier);
147
148int unregister_keyboard_notifier(struct notifier_block *nb)
149{
150 return atomic_notifier_chain_unregister(&keyboard_notifier_list, nb);
151}
152EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
153
154/*
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400155 * Translation of scancodes to keycodes. We set them on only the first
156 * keyboard in the list that accepts the scancode and keycode.
157 * Explanation for not choosing the first attached keyboard anymore:
158 * USB keyboards for example have two event devices: one for all "normal"
159 * keys and one for extra function keys (like "volume up", "make coffee",
160 * etc.). So this means that scancodes for the extra function keys won't
161 * be valid for the first event device, but will be for the second.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 */
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800163
164struct getset_keycode_data {
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700165 struct input_keymap_entry ke;
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800166 int error;
167};
168
169static int getkeycode_helper(struct input_handle *handle, void *data)
170{
171 struct getset_keycode_data *d = data;
172
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700173 d->error = input_get_keycode(handle->dev, &d->ke);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800174
175 return d->error == 0; /* stop as soon as we successfully get one */
176}
177
Alan Cox079c9532012-02-28 14:49:23 +0000178static int getkeycode(unsigned int scancode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179{
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700180 struct getset_keycode_data d = {
181 .ke = {
182 .flags = 0,
183 .len = sizeof(scancode),
184 .keycode = 0,
185 },
186 .error = -ENODEV,
187 };
188
189 memcpy(d.ke.scancode, &scancode, sizeof(scancode));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800191 input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700193 return d.error ?: d.ke.keycode;
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800194}
195
196static int setkeycode_helper(struct input_handle *handle, void *data)
197{
198 struct getset_keycode_data *d = data;
199
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700200 d->error = input_set_keycode(handle->dev, &d->ke);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800201
202 return d->error == 0; /* stop as soon as we successfully set one */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203}
204
Alan Cox079c9532012-02-28 14:49:23 +0000205static int setkeycode(unsigned int scancode, unsigned int keycode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206{
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700207 struct getset_keycode_data d = {
208 .ke = {
209 .flags = 0,
210 .len = sizeof(scancode),
211 .keycode = keycode,
212 },
213 .error = -ENODEV,
214 };
215
216 memcpy(d.ke.scancode, &scancode, sizeof(scancode));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800218 input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800220 return d.error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221}
222
223/*
Dmitry Torokhov18f7ad52009-12-15 16:26:53 -0800224 * Making beeps and bells. Note that we prefer beeps to bells, but when
225 * shutting the sound off we do both.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 */
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800227
228static int kd_sound_helper(struct input_handle *handle, void *data)
229{
230 unsigned int *hz = data;
231 struct input_dev *dev = handle->dev;
232
233 if (test_bit(EV_SND, dev->evbit)) {
Dmitry Torokhov18f7ad52009-12-15 16:26:53 -0800234 if (test_bit(SND_TONE, dev->sndbit)) {
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800235 input_inject_event(handle, EV_SND, SND_TONE, *hz);
Dmitry Torokhov18f7ad52009-12-15 16:26:53 -0800236 if (*hz)
237 return 0;
238 }
239 if (test_bit(SND_BELL, dev->sndbit))
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800240 input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0);
241 }
242
243 return 0;
244}
245
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246static void kd_nosound(unsigned long ignored)
247{
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800248 static unsigned int zero;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800250 input_handler_for_each_handle(&kbd_handler, &zero, kd_sound_helper);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251}
252
Ingo Molnar8d06afa2005-09-09 13:10:40 -0700253static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
255void kd_mksound(unsigned int hz, unsigned int ticks)
256{
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800257 del_timer_sync(&kd_mksound_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800259 input_handler_for_each_handle(&kbd_handler, &hz, kd_sound_helper);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800261 if (hz && ticks)
262 mod_timer(&kd_mksound_timer, jiffies + ticks);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263}
Samuel Thibaultf7511d52008-04-30 00:54:51 -0700264EXPORT_SYMBOL(kd_mksound);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
266/*
267 * Setting the keyboard rate.
268 */
269
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800270static int kbd_rate_helper(struct input_handle *handle, void *data)
271{
272 struct input_dev *dev = handle->dev;
Mark Rustad9d329c12014-09-05 18:57:57 -0700273 struct kbd_repeat *rpt = data;
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800274
275 if (test_bit(EV_REP, dev->evbit)) {
276
Mark Rustad9d329c12014-09-05 18:57:57 -0700277 if (rpt[0].delay > 0)
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800278 input_inject_event(handle,
Mark Rustad9d329c12014-09-05 18:57:57 -0700279 EV_REP, REP_DELAY, rpt[0].delay);
280 if (rpt[0].period > 0)
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800281 input_inject_event(handle,
Mark Rustad9d329c12014-09-05 18:57:57 -0700282 EV_REP, REP_PERIOD, rpt[0].period);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800283
Mark Rustad9d329c12014-09-05 18:57:57 -0700284 rpt[1].delay = dev->rep[REP_DELAY];
285 rpt[1].period = dev->rep[REP_PERIOD];
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800286 }
287
288 return 0;
289}
290
Mark Rustad9d329c12014-09-05 18:57:57 -0700291int kbd_rate(struct kbd_repeat *rpt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292{
Mark Rustad9d329c12014-09-05 18:57:57 -0700293 struct kbd_repeat data[2] = { *rpt };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800295 input_handler_for_each_handle(&kbd_handler, data, kbd_rate_helper);
Mark Rustad9d329c12014-09-05 18:57:57 -0700296 *rpt = data[1]; /* Copy currently used settings */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 return 0;
299}
300
301/*
302 * Helper Functions.
303 */
304static void put_queue(struct vc_data *vc, int ch)
305{
Jiri Slaby92a19f92013-01-03 15:53:03 +0100306 tty_insert_flip_char(&vc->port, ch, 0);
Jiri Slaby6732c8b2013-01-03 15:53:07 +0100307 tty_schedule_flip(&vc->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308}
309
310static void puts_queue(struct vc_data *vc, char *cp)
311{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 while (*cp) {
Jiri Slaby92a19f92013-01-03 15:53:03 +0100313 tty_insert_flip_char(&vc->port, *cp, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 cp++;
315 }
Jiri Slaby6732c8b2013-01-03 15:53:07 +0100316 tty_schedule_flip(&vc->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317}
318
319static void applkey(struct vc_data *vc, int key, char mode)
320{
321 static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
322
323 buf[1] = (mode ? 'O' : '[');
324 buf[2] = key;
325 puts_queue(vc, buf);
326}
327
328/*
329 * Many other routines do put_queue, but I think either
330 * they produce ASCII, or they produce some user-assigned
331 * string, and in both cases we might assume that it is
Jan Engelhardt759448f2007-07-15 23:40:40 -0700332 * in utf-8 already.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 */
Jan Engelhardt759448f2007-07-15 23:40:40 -0700334static void to_utf8(struct vc_data *vc, uint c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335{
336 if (c < 0x80)
337 /* 0******* */
338 put_queue(vc, c);
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500339 else if (c < 0x800) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 /* 110***** 10****** */
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500341 put_queue(vc, 0xc0 | (c >> 6));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhove0785572010-03-21 22:31:26 -0700343 } else if (c < 0x10000) {
344 if (c >= 0xD800 && c < 0xE000)
Jan Engelhardt759448f2007-07-15 23:40:40 -0700345 return;
346 if (c == 0xFFFF)
347 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 /* 1110**** 10****** 10****** */
349 put_queue(vc, 0xe0 | (c >> 12));
350 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
351 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhove0785572010-03-21 22:31:26 -0700352 } else if (c < 0x110000) {
Jan Engelhardt759448f2007-07-15 23:40:40 -0700353 /* 11110*** 10****** 10****** 10****** */
354 put_queue(vc, 0xf0 | (c >> 18));
355 put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
356 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
357 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500358 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359}
360
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500361/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 * Called after returning from RAW mode or when changing consoles - recompute
363 * shift_down[] and shift_state from key_down[] maybe called when keymap is
Alan Cox079c9532012-02-28 14:49:23 +0000364 * undefined, so that shiftkey release is seen. The caller must hold the
365 * kbd_event_lock.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 */
Alan Cox079c9532012-02-28 14:49:23 +0000367
368static void do_compute_shiftstate(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369{
Dmitry Torokhov510cccb2016-06-27 14:12:34 -0700370 unsigned int k, sym, val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
372 shift_state = 0;
373 memset(shift_down, 0, sizeof(shift_down));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500374
Dmitry Torokhov510cccb2016-06-27 14:12:34 -0700375 for_each_set_bit(k, key_down, min(NR_KEYS, KEY_CNT)) {
376 sym = U(key_maps[0][k]);
377 if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 continue;
379
Dmitry Torokhov510cccb2016-06-27 14:12:34 -0700380 val = KVAL(sym);
381 if (val == KVAL(K_CAPSSHIFT))
382 val = KVAL(K_SHIFT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Dmitry Torokhov510cccb2016-06-27 14:12:34 -0700384 shift_down[val]++;
385 shift_state |= BIT(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 }
387}
388
Alan Cox079c9532012-02-28 14:49:23 +0000389/* We still have to export this method to vt.c */
390void compute_shiftstate(void)
391{
392 unsigned long flags;
393 spin_lock_irqsave(&kbd_event_lock, flags);
394 do_compute_shiftstate();
395 spin_unlock_irqrestore(&kbd_event_lock, flags);
396}
397
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398/*
399 * We have a combining character DIACR here, followed by the character CH.
400 * If the combination occurs in the table, return the corresponding value.
401 * Otherwise, if CH is a space or equals DIACR, return DIACR.
402 * Otherwise, conclude that DIACR was not combining after all,
403 * queue it and return CH.
404 */
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500405static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406{
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500407 unsigned int d = diacr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 unsigned int i;
409
410 diacr = 0;
411
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500412 if ((d & ~0xff) == BRL_UC_ROW) {
413 if ((ch & ~0xff) == BRL_UC_ROW)
414 return d | ch;
415 } else {
416 for (i = 0; i < accent_table_size; i++)
417 if (accent_table[i].diacr == d && accent_table[i].base == ch)
418 return accent_table[i].result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 }
420
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500421 if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 return d;
423
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500424 if (kbd->kbdmode == VC_UNICODE)
Samuel Thibault04c71972007-10-16 23:27:04 -0700425 to_utf8(vc, d);
426 else {
427 int c = conv_uni_to_8bit(d);
428 if (c != -1)
429 put_queue(vc, c);
430 }
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500431
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 return ch;
433}
434
435/*
436 * Special function handlers
437 */
David Howells7d12e782006-10-05 14:55:46 +0100438static void fn_enter(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
440 if (diacr) {
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500441 if (kbd->kbdmode == VC_UNICODE)
Samuel Thibault04c71972007-10-16 23:27:04 -0700442 to_utf8(vc, diacr);
443 else {
444 int c = conv_uni_to_8bit(diacr);
445 if (c != -1)
446 put_queue(vc, c);
447 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 diacr = 0;
449 }
Dmitry Torokhove0785572010-03-21 22:31:26 -0700450
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 put_queue(vc, 13);
452 if (vc_kbd_mode(kbd, VC_CRLF))
453 put_queue(vc, 10);
454}
455
David Howells7d12e782006-10-05 14:55:46 +0100456static void fn_caps_toggle(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457{
458 if (rep)
459 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700460
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 chg_vc_kbd_led(kbd, VC_CAPSLOCK);
462}
463
David Howells7d12e782006-10-05 14:55:46 +0100464static void fn_caps_on(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465{
466 if (rep)
467 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700468
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 set_vc_kbd_led(kbd, VC_CAPSLOCK);
470}
471
David Howells7d12e782006-10-05 14:55:46 +0100472static void fn_show_ptregs(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473{
David Howells7d12e782006-10-05 14:55:46 +0100474 struct pt_regs *regs = get_irq_regs();
Dmitry Torokhove0785572010-03-21 22:31:26 -0700475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 if (regs)
477 show_regs(regs);
478}
479
David Howells7d12e782006-10-05 14:55:46 +0100480static void fn_hold(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481{
Alan Cox8ce73262010-06-01 22:52:56 +0200482 struct tty_struct *tty = vc->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484 if (rep || !tty)
485 return;
486
487 /*
488 * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
489 * these routines are also activated by ^S/^Q.
490 * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
491 */
492 if (tty->stopped)
493 start_tty(tty);
494 else
495 stop_tty(tty);
496}
497
David Howells7d12e782006-10-05 14:55:46 +0100498static void fn_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499{
Dmitry Torokhove0785572010-03-21 22:31:26 -0700500 if (vc_kbd_mode(kbd, VC_APPLIC))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 applkey(vc, 'P', 1);
502 else
David Howells7d12e782006-10-05 14:55:46 +0100503 fn_bare_num(vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504}
505
506/*
507 * Bind this to Shift-NumLock if you work in application keypad mode
508 * but want to be able to change the NumLock flag.
509 * Bind this to NumLock if you prefer that the NumLock key always
510 * changes the NumLock flag.
511 */
David Howells7d12e782006-10-05 14:55:46 +0100512static void fn_bare_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513{
514 if (!rep)
515 chg_vc_kbd_led(kbd, VC_NUMLOCK);
516}
517
David Howells7d12e782006-10-05 14:55:46 +0100518static void fn_lastcons(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519{
520 /* switch to the last used console, ChN */
521 set_console(last_console);
522}
523
David Howells7d12e782006-10-05 14:55:46 +0100524static void fn_dec_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525{
526 int i, cur = fg_console;
527
528 /* Currently switching? Queue this next switch relative to that. */
529 if (want_console != -1)
530 cur = want_console;
531
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500532 for (i = cur - 1; i != cur; i--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 if (i == -1)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500534 i = MAX_NR_CONSOLES - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 if (vc_cons_allocated(i))
536 break;
537 }
538 set_console(i);
539}
540
David Howells7d12e782006-10-05 14:55:46 +0100541static void fn_inc_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542{
543 int i, cur = fg_console;
544
545 /* Currently switching? Queue this next switch relative to that. */
546 if (want_console != -1)
547 cur = want_console;
548
549 for (i = cur+1; i != cur; i++) {
550 if (i == MAX_NR_CONSOLES)
551 i = 0;
552 if (vc_cons_allocated(i))
553 break;
554 }
555 set_console(i);
556}
557
David Howells7d12e782006-10-05 14:55:46 +0100558static void fn_send_intr(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559{
Jiri Slaby92a19f92013-01-03 15:53:03 +0100560 tty_insert_flip_char(&vc->port, 0, TTY_BREAK);
Jiri Slaby6732c8b2013-01-03 15:53:07 +0100561 tty_schedule_flip(&vc->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562}
563
David Howells7d12e782006-10-05 14:55:46 +0100564static void fn_scroll_forw(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565{
566 scrollfront(vc, 0);
567}
568
David Howells7d12e782006-10-05 14:55:46 +0100569static void fn_scroll_back(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570{
Jiri Slaby1b0ec882016-06-23 13:34:23 +0200571 scrollback(vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572}
573
David Howells7d12e782006-10-05 14:55:46 +0100574static void fn_show_mem(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575{
David Rientjesb2b755b2011-03-24 15:18:15 -0700576 show_mem(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577}
578
David Howells7d12e782006-10-05 14:55:46 +0100579static void fn_show_state(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
581 show_state();
582}
583
David Howells7d12e782006-10-05 14:55:46 +0100584static void fn_boot_it(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585{
586 ctrl_alt_del();
587}
588
David Howells7d12e782006-10-05 14:55:46 +0100589static void fn_compose(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590{
Dmitry Torokhove0785572010-03-21 22:31:26 -0700591 dead_key_next = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592}
593
David Howells7d12e782006-10-05 14:55:46 +0100594static void fn_spawn_con(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595{
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700596 spin_lock(&vt_spawn_con.lock);
597 if (vt_spawn_con.pid)
598 if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
599 put_pid(vt_spawn_con.pid);
600 vt_spawn_con.pid = NULL;
601 }
602 spin_unlock(&vt_spawn_con.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603}
604
David Howells7d12e782006-10-05 14:55:46 +0100605static void fn_SAK(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606{
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800607 struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800608 schedule_work(SAK_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609}
610
David Howells7d12e782006-10-05 14:55:46 +0100611static void fn_null(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612{
Alan Cox079c9532012-02-28 14:49:23 +0000613 do_compute_shiftstate();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614}
615
616/*
617 * Special key handlers
618 */
David Howells7d12e782006-10-05 14:55:46 +0100619static void k_ignore(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620{
621}
622
David Howells7d12e782006-10-05 14:55:46 +0100623static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624{
625 if (up_flag)
626 return;
627 if (value >= ARRAY_SIZE(fn_handler))
628 return;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500629 if ((kbd->kbdmode == VC_RAW ||
Arthur Taylor9fc3de92011-02-04 13:55:50 -0800630 kbd->kbdmode == VC_MEDIUMRAW ||
631 kbd->kbdmode == VC_OFF) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 value != KVAL(K_SAK))
633 return; /* SAK is allowed even in raw mode */
David Howells7d12e782006-10-05 14:55:46 +0100634 fn_handler[value](vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635}
636
David Howells7d12e782006-10-05 14:55:46 +0100637static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638{
Dmitry Torokhov9272e9a2010-03-21 22:31:26 -0700639 pr_err("k_lowercase was called - impossible\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640}
641
David Howells7d12e782006-10-05 14:55:46 +0100642static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643{
644 if (up_flag)
645 return; /* no action, if this is a key release */
646
647 if (diacr)
648 value = handle_diacr(vc, value);
649
650 if (dead_key_next) {
Dmitry Torokhove0785572010-03-21 22:31:26 -0700651 dead_key_next = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 diacr = value;
653 return;
654 }
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500655 if (kbd->kbdmode == VC_UNICODE)
Samuel Thibault04c71972007-10-16 23:27:04 -0700656 to_utf8(vc, value);
657 else {
658 int c = conv_uni_to_8bit(value);
659 if (c != -1)
660 put_queue(vc, c);
661 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662}
663
664/*
665 * Handle dead key. Note that we now may have several
666 * dead keys modifying the same character. Very useful
667 * for Vietnamese.
668 */
David Howells7d12e782006-10-05 14:55:46 +0100669static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670{
671 if (up_flag)
672 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700673
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 diacr = (diacr ? handle_diacr(vc, value) : value);
675}
676
David Howells7d12e782006-10-05 14:55:46 +0100677static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500678{
Jiri Bohacd2187eb2008-06-12 15:21:51 -0700679 k_unicode(vc, conv_8bit_to_uni(value), up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500680}
681
David Howells7d12e782006-10-05 14:55:46 +0100682static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500683{
David Howells7d12e782006-10-05 14:55:46 +0100684 k_deadunicode(vc, value, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500685}
686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687/*
688 * Obsolete - for backwards compatibility only
689 */
David Howells7d12e782006-10-05 14:55:46 +0100690static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691{
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400692 static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
Dmitry Torokhove0785572010-03-21 22:31:26 -0700693
694 k_deadunicode(vc, ret_diacr[value], up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695}
696
David Howells7d12e782006-10-05 14:55:46 +0100697static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698{
699 if (up_flag)
700 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700701
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 set_console(value);
703}
704
David Howells7d12e782006-10-05 14:55:46 +0100705static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 if (up_flag)
708 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700709
710 if ((unsigned)value < ARRAY_SIZE(func_table)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 if (func_table[value])
712 puts_queue(vc, func_table[value]);
713 } else
Dmitry Torokhov9272e9a2010-03-21 22:31:26 -0700714 pr_err("k_fn called with value=%d\n", value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715}
716
David Howells7d12e782006-10-05 14:55:46 +0100717static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718{
Brandon Philipse52b29c2006-11-04 22:09:08 -0500719 static const char cur_chars[] = "BDCA";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
721 if (up_flag)
722 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700723
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
725}
726
David Howells7d12e782006-10-05 14:55:46 +0100727static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728{
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400729 static const char pad_chars[] = "0123456789+-*/\015,.?()#";
730 static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731
732 if (up_flag)
733 return; /* no action, if this is a key release */
734
735 /* kludge... shift forces cursor/number keys */
736 if (vc_kbd_mode(kbd, VC_APPLIC) && !shift_down[KG_SHIFT]) {
737 applkey(vc, app_map[value], 1);
738 return;
739 }
740
Dmitry Torokhove0785572010-03-21 22:31:26 -0700741 if (!vc_kbd_led(kbd, VC_NUMLOCK)) {
742
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 switch (value) {
Dmitry Torokhove0785572010-03-21 22:31:26 -0700744 case KVAL(K_PCOMMA):
745 case KVAL(K_PDOT):
746 k_fn(vc, KVAL(K_REMOVE), 0);
747 return;
748 case KVAL(K_P0):
749 k_fn(vc, KVAL(K_INSERT), 0);
750 return;
751 case KVAL(K_P1):
752 k_fn(vc, KVAL(K_SELECT), 0);
753 return;
754 case KVAL(K_P2):
755 k_cur(vc, KVAL(K_DOWN), 0);
756 return;
757 case KVAL(K_P3):
758 k_fn(vc, KVAL(K_PGDN), 0);
759 return;
760 case KVAL(K_P4):
761 k_cur(vc, KVAL(K_LEFT), 0);
762 return;
763 case KVAL(K_P6):
764 k_cur(vc, KVAL(K_RIGHT), 0);
765 return;
766 case KVAL(K_P7):
767 k_fn(vc, KVAL(K_FIND), 0);
768 return;
769 case KVAL(K_P8):
770 k_cur(vc, KVAL(K_UP), 0);
771 return;
772 case KVAL(K_P9):
773 k_fn(vc, KVAL(K_PGUP), 0);
774 return;
775 case KVAL(K_P5):
776 applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
777 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 }
Dmitry Torokhove0785572010-03-21 22:31:26 -0700779 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
781 put_queue(vc, pad_chars[value]);
782 if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
783 put_queue(vc, 10);
784}
785
David Howells7d12e782006-10-05 14:55:46 +0100786static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787{
788 int old_state = shift_state;
789
790 if (rep)
791 return;
792 /*
793 * Mimic typewriter:
794 * a CapsShift key acts like Shift but undoes CapsLock
795 */
796 if (value == KVAL(K_CAPSSHIFT)) {
797 value = KVAL(K_SHIFT);
798 if (!up_flag)
799 clr_vc_kbd_led(kbd, VC_CAPSLOCK);
800 }
801
802 if (up_flag) {
803 /*
804 * handle the case that two shift or control
805 * keys are depressed simultaneously
806 */
807 if (shift_down[value])
808 shift_down[value]--;
809 } else
810 shift_down[value]++;
811
812 if (shift_down[value])
813 shift_state |= (1 << value);
814 else
815 shift_state &= ~(1 << value);
816
817 /* kludge */
818 if (up_flag && shift_state != old_state && npadch != -1) {
819 if (kbd->kbdmode == VC_UNICODE)
Jan Engelhardt759448f2007-07-15 23:40:40 -0700820 to_utf8(vc, npadch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 else
822 put_queue(vc, npadch & 0xff);
823 npadch = -1;
824 }
825}
826
David Howells7d12e782006-10-05 14:55:46 +0100827static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828{
829 if (up_flag)
830 return;
831
832 if (vc_kbd_mode(kbd, VC_META)) {
833 put_queue(vc, '\033');
834 put_queue(vc, value);
835 } else
836 put_queue(vc, value | 0x80);
837}
838
David Howells7d12e782006-10-05 14:55:46 +0100839static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840{
841 int base;
842
843 if (up_flag)
844 return;
845
846 if (value < 10) {
847 /* decimal input of code, while Alt depressed */
848 base = 10;
849 } else {
850 /* hexadecimal input of code, while AltGr depressed */
851 value -= 10;
852 base = 16;
853 }
854
855 if (npadch == -1)
856 npadch = value;
857 else
858 npadch = npadch * base + value;
859}
860
David Howells7d12e782006-10-05 14:55:46 +0100861static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862{
863 if (up_flag || rep)
864 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700865
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 chg_vc_kbd_lock(kbd, value);
867}
868
David Howells7d12e782006-10-05 14:55:46 +0100869static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870{
David Howells7d12e782006-10-05 14:55:46 +0100871 k_shift(vc, value, up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 if (up_flag || rep)
873 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700874
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 chg_vc_kbd_slock(kbd, value);
876 /* try to make Alt, oops, AltGr and such work */
877 if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
878 kbd->slockstate = 0;
879 chg_vc_kbd_slock(kbd, value);
880 }
881}
882
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500883/* by default, 300ms interval for combination release */
Samuel Thibault77426d72006-04-26 00:14:10 -0400884static unsigned brl_timeout = 300;
885MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
886module_param(brl_timeout, uint, 0644);
887
888static unsigned brl_nbchords = 1;
889MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
890module_param(brl_nbchords, uint, 0644);
891
David Howells7d12e782006-10-05 14:55:46 +0100892static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag)
Samuel Thibault77426d72006-04-26 00:14:10 -0400893{
894 static unsigned long chords;
895 static unsigned committed;
896
897 if (!brl_nbchords)
David Howells7d12e782006-10-05 14:55:46 +0100898 k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400899 else {
900 committed |= pattern;
901 chords++;
902 if (chords == brl_nbchords) {
David Howells7d12e782006-10-05 14:55:46 +0100903 k_unicode(vc, BRL_UC_ROW | committed, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400904 chords = 0;
905 committed = 0;
906 }
907 }
908}
909
David Howells7d12e782006-10-05 14:55:46 +0100910static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500911{
Dmitry Torokhove0785572010-03-21 22:31:26 -0700912 static unsigned pressed, committing;
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500913 static unsigned long releasestart;
914
915 if (kbd->kbdmode != VC_UNICODE) {
916 if (!up_flag)
Joe Perchese620e542014-11-09 22:46:35 -0800917 pr_warn("keyboard mode must be unicode for braille patterns\n");
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500918 return;
919 }
920
921 if (!value) {
David Howells7d12e782006-10-05 14:55:46 +0100922 k_unicode(vc, BRL_UC_ROW, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500923 return;
924 }
925
926 if (value > 8)
927 return;
928
Dmitry Torokhove0785572010-03-21 22:31:26 -0700929 if (!up_flag) {
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500930 pressed |= 1 << (value - 1);
931 if (!brl_timeout)
932 committing = pressed;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700933 } else if (brl_timeout) {
934 if (!committing ||
935 time_after(jiffies,
936 releasestart + msecs_to_jiffies(brl_timeout))) {
937 committing = pressed;
938 releasestart = jiffies;
939 }
940 pressed &= ~(1 << (value - 1));
941 if (!pressed && committing) {
942 k_brlcommit(vc, committing, 0);
943 committing = 0;
944 }
945 } else {
946 if (committing) {
947 k_brlcommit(vc, committing, 0);
948 committing = 0;
949 }
950 pressed &= ~(1 << (value - 1));
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500951 }
952}
953
Samuel Thibault52355522015-03-16 21:19:44 -0700954#if IS_ENABLED(CONFIG_INPUT_LEDS) && IS_ENABLED(CONFIG_LEDS_TRIGGERS)
955
956struct kbd_led_trigger {
957 struct led_trigger trigger;
958 unsigned int mask;
959};
960
961static void kbd_led_trigger_activate(struct led_classdev *cdev)
962{
963 struct kbd_led_trigger *trigger =
964 container_of(cdev->trigger, struct kbd_led_trigger, trigger);
965
966 tasklet_disable(&keyboard_tasklet);
Samuel Thibaulteeb64c12015-06-06 11:44:39 -0700967 if (ledstate != -1U)
Samuel Thibault52355522015-03-16 21:19:44 -0700968 led_trigger_event(&trigger->trigger,
969 ledstate & trigger->mask ?
970 LED_FULL : LED_OFF);
971 tasklet_enable(&keyboard_tasklet);
972}
973
974#define KBD_LED_TRIGGER(_led_bit, _name) { \
975 .trigger = { \
976 .name = _name, \
977 .activate = kbd_led_trigger_activate, \
978 }, \
979 .mask = BIT(_led_bit), \
980 }
981
Samuel Thibaulteeb64c12015-06-06 11:44:39 -0700982#define KBD_LOCKSTATE_TRIGGER(_led_bit, _name) \
983 KBD_LED_TRIGGER((_led_bit) + 8, _name)
984
Samuel Thibault52355522015-03-16 21:19:44 -0700985static struct kbd_led_trigger kbd_led_triggers[] = {
Maciej S. Szmigierofbb28e72016-11-16 00:55:57 +0100986 KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrolllock"),
Samuel Thibault52355522015-03-16 21:19:44 -0700987 KBD_LED_TRIGGER(VC_NUMLOCK, "kbd-numlock"),
988 KBD_LED_TRIGGER(VC_CAPSLOCK, "kbd-capslock"),
989 KBD_LED_TRIGGER(VC_KANALOCK, "kbd-kanalock"),
Samuel Thibaulteeb64c12015-06-06 11:44:39 -0700990
991 KBD_LOCKSTATE_TRIGGER(VC_SHIFTLOCK, "kbd-shiftlock"),
992 KBD_LOCKSTATE_TRIGGER(VC_ALTGRLOCK, "kbd-altgrlock"),
993 KBD_LOCKSTATE_TRIGGER(VC_CTRLLOCK, "kbd-ctrllock"),
994 KBD_LOCKSTATE_TRIGGER(VC_ALTLOCK, "kbd-altlock"),
995 KBD_LOCKSTATE_TRIGGER(VC_SHIFTLLOCK, "kbd-shiftllock"),
996 KBD_LOCKSTATE_TRIGGER(VC_SHIFTRLOCK, "kbd-shiftrlock"),
997 KBD_LOCKSTATE_TRIGGER(VC_CTRLLLOCK, "kbd-ctrlllock"),
998 KBD_LOCKSTATE_TRIGGER(VC_CTRLRLOCK, "kbd-ctrlrlock"),
Samuel Thibault52355522015-03-16 21:19:44 -0700999};
1000
1001static void kbd_propagate_led_state(unsigned int old_state,
1002 unsigned int new_state)
1003{
1004 struct kbd_led_trigger *trigger;
1005 unsigned int changed = old_state ^ new_state;
1006 int i;
1007
1008 for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) {
1009 trigger = &kbd_led_triggers[i];
1010
1011 if (changed & trigger->mask)
1012 led_trigger_event(&trigger->trigger,
1013 new_state & trigger->mask ?
1014 LED_FULL : LED_OFF);
1015 }
1016}
1017
1018static int kbd_update_leds_helper(struct input_handle *handle, void *data)
1019{
1020 unsigned int led_state = *(unsigned int *)data;
1021
1022 if (test_bit(EV_LED, handle->dev->evbit))
1023 kbd_propagate_led_state(~led_state, led_state);
1024
1025 return 0;
1026}
1027
1028static void kbd_init_leds(void)
1029{
1030 int error;
1031 int i;
1032
1033 for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) {
1034 error = led_trigger_register(&kbd_led_triggers[i].trigger);
1035 if (error)
1036 pr_err("error %d while registering trigger %s\n",
1037 error, kbd_led_triggers[i].trigger.name);
1038 }
1039}
1040
1041#else
1042
1043static int kbd_update_leds_helper(struct input_handle *handle, void *data)
1044{
1045 unsigned int leds = *(unsigned int *)data;
1046
1047 if (test_bit(EV_LED, handle->dev->evbit)) {
1048 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
1049 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
1050 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
1051 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
1052 }
1053
1054 return 0;
1055}
1056
1057static void kbd_propagate_led_state(unsigned int old_state,
1058 unsigned int new_state)
1059{
1060 input_handler_for_each_handle(&kbd_handler, &new_state,
1061 kbd_update_leds_helper);
1062}
1063
1064static void kbd_init_leds(void)
1065{
1066}
1067
1068#endif
1069
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070/*
1071 * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
1072 * or (ii) whatever pattern of lights people want to show using KDSETLED,
1073 * or (iii) specified bits of specified words in kernel memory.
1074 */
Alan Cox3db1ddb2012-07-17 17:06:41 +01001075static unsigned char getledstate(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076{
Samuel Thibaulteeb64c12015-06-06 11:44:39 -07001077 return ledstate & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078}
1079
Mark Rustad9d329c12014-09-05 18:57:57 -07001080void setledstate(struct kbd_struct *kb, unsigned int led)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081{
Alan Cox079c9532012-02-28 14:49:23 +00001082 unsigned long flags;
Alan Cox3db1ddb2012-07-17 17:06:41 +01001083 spin_lock_irqsave(&led_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 if (!(led & ~7)) {
1085 ledioctl = led;
Mark Rustad9d329c12014-09-05 18:57:57 -07001086 kb->ledmode = LED_SHOW_IOCTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 } else
Mark Rustad9d329c12014-09-05 18:57:57 -07001088 kb->ledmode = LED_SHOW_FLAGS;
Dmitry Torokhove0785572010-03-21 22:31:26 -07001089
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 set_leds();
Alan Cox3db1ddb2012-07-17 17:06:41 +01001091 spin_unlock_irqrestore(&led_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092}
1093
1094static inline unsigned char getleds(void)
1095{
Mark Rustad9d329c12014-09-05 18:57:57 -07001096 struct kbd_struct *kb = kbd_table + fg_console;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Mark Rustad9d329c12014-09-05 18:57:57 -07001098 if (kb->ledmode == LED_SHOW_IOCTL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 return ledioctl;
1100
Mark Rustad9d329c12014-09-05 18:57:57 -07001101 return kb->ledflagstate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102}
1103
Alan Cox079c9532012-02-28 14:49:23 +00001104/**
1105 * vt_get_leds - helper for braille console
1106 * @console: console to read
1107 * @flag: flag we want to check
1108 *
1109 * Check the status of a keyboard led flag and report it back
1110 */
1111int vt_get_leds(int console, int flag)
1112{
Mark Rustad9d329c12014-09-05 18:57:57 -07001113 struct kbd_struct *kb = kbd_table + console;
Alan Cox079c9532012-02-28 14:49:23 +00001114 int ret;
Alan Cox3db1ddb2012-07-17 17:06:41 +01001115 unsigned long flags;
Alan Cox079c9532012-02-28 14:49:23 +00001116
Alan Cox3db1ddb2012-07-17 17:06:41 +01001117 spin_lock_irqsave(&led_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07001118 ret = vc_kbd_led(kb, flag);
Alan Cox3db1ddb2012-07-17 17:06:41 +01001119 spin_unlock_irqrestore(&led_lock, flags);
Alan Cox079c9532012-02-28 14:49:23 +00001120
1121 return ret;
1122}
1123EXPORT_SYMBOL_GPL(vt_get_leds);
1124
1125/**
1126 * vt_set_led_state - set LED state of a console
1127 * @console: console to set
1128 * @leds: LED bits
1129 *
1130 * Set the LEDs on a console. This is a wrapper for the VT layer
1131 * so that we can keep kbd knowledge internal
1132 */
1133void vt_set_led_state(int console, int leds)
1134{
Mark Rustad9d329c12014-09-05 18:57:57 -07001135 struct kbd_struct *kb = kbd_table + console;
1136 setledstate(kb, leds);
Alan Cox079c9532012-02-28 14:49:23 +00001137}
1138
1139/**
1140 * vt_kbd_con_start - Keyboard side of console start
1141 * @console: console
1142 *
1143 * Handle console start. This is a wrapper for the VT layer
1144 * so that we can keep kbd knowledge internal
Alan Cox84f904e2012-05-01 16:12:19 +01001145 *
1146 * FIXME: We eventually need to hold the kbd lock here to protect
1147 * the LED updating. We can't do it yet because fn_hold calls stop_tty
1148 * and start_tty under the kbd_event_lock, while normal tty paths
1149 * don't hold the lock. We probably need to split out an LED lock
1150 * but not during an -rc release!
Alan Cox079c9532012-02-28 14:49:23 +00001151 */
1152void vt_kbd_con_start(int console)
1153{
Mark Rustad9d329c12014-09-05 18:57:57 -07001154 struct kbd_struct *kb = kbd_table + console;
Alan Cox3db1ddb2012-07-17 17:06:41 +01001155 unsigned long flags;
1156 spin_lock_irqsave(&led_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07001157 clr_vc_kbd_led(kb, VC_SCROLLOCK);
Alan Cox079c9532012-02-28 14:49:23 +00001158 set_leds();
Alan Cox3db1ddb2012-07-17 17:06:41 +01001159 spin_unlock_irqrestore(&led_lock, flags);
Alan Cox079c9532012-02-28 14:49:23 +00001160}
1161
1162/**
1163 * vt_kbd_con_stop - Keyboard side of console stop
1164 * @console: console
1165 *
1166 * Handle console stop. This is a wrapper for the VT layer
1167 * so that we can keep kbd knowledge internal
1168 */
1169void vt_kbd_con_stop(int console)
1170{
Mark Rustad9d329c12014-09-05 18:57:57 -07001171 struct kbd_struct *kb = kbd_table + console;
Alan Cox3db1ddb2012-07-17 17:06:41 +01001172 unsigned long flags;
1173 spin_lock_irqsave(&led_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07001174 set_vc_kbd_led(kb, VC_SCROLLOCK);
Alan Cox079c9532012-02-28 14:49:23 +00001175 set_leds();
Alan Cox3db1ddb2012-07-17 17:06:41 +01001176 spin_unlock_irqrestore(&led_lock, flags);
Alan Cox079c9532012-02-28 14:49:23 +00001177}
1178
Dmitry Torokhov66d2a592009-12-01 21:54:35 -08001179/*
Samuel Thibault52355522015-03-16 21:19:44 -07001180 * This is the tasklet that updates LED state of LEDs using standard
1181 * keyboard triggers. The reason we use tasklet is that we need to
1182 * handle the scenario when keyboard handler is not registered yet
1183 * but we already getting updates from the VT to update led state.
Dmitry Torokhov66d2a592009-12-01 21:54:35 -08001184 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185static void kbd_bh(unsigned long dummy)
1186{
Samuel Thibaulteeb64c12015-06-06 11:44:39 -07001187 unsigned int leds;
Alan Cox3db1ddb2012-07-17 17:06:41 +01001188 unsigned long flags;
Samuel Thibault52355522015-03-16 21:19:44 -07001189
Alan Cox3db1ddb2012-07-17 17:06:41 +01001190 spin_lock_irqsave(&led_lock, flags);
1191 leds = getleds();
Samuel Thibaulteeb64c12015-06-06 11:44:39 -07001192 leds |= (unsigned int)kbd->lockstate << 8;
Alan Cox3db1ddb2012-07-17 17:06:41 +01001193 spin_unlock_irqrestore(&led_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194
1195 if (leds != ledstate) {
Samuel Thibault52355522015-03-16 21:19:44 -07001196 kbd_propagate_led_state(ledstate, leds);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -08001197 ledstate = leds;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199}
1200
1201DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
1202
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001204 defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
1205 defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
Hans-Christian Egtvedt3a4e8322007-12-04 13:15:41 +01001206 (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) ||\
1207 defined(CONFIG_AVR32)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
1209#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
1210 ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
1211
Andreas Mohr0f5e5602006-06-05 00:18:00 -04001212static const unsigned short x86_keycodes[256] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1214 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1215 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
1216 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
1217 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
1218 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001219 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
1221 360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
Hans de Goede72a42f22007-07-03 01:55:18 -04001222 103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
1223 291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
1225 377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
1226 308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
1227 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
1228
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001229#ifdef CONFIG_SPARC
Dmitry Torokhove0785572010-03-21 22:31:26 -07001230static int sparc_l1_a_state;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231extern void sun_do_break(void);
1232#endif
1233
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001234static int emulate_raw(struct vc_data *vc, unsigned int keycode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 unsigned char up_flag)
1236{
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001237 int code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
1239 switch (keycode) {
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001240
Dmitry Torokhove0785572010-03-21 22:31:26 -07001241 case KEY_PAUSE:
1242 put_queue(vc, 0xe1);
1243 put_queue(vc, 0x1d | up_flag);
1244 put_queue(vc, 0x45 | up_flag);
1245 break;
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001246
Dmitry Torokhove0785572010-03-21 22:31:26 -07001247 case KEY_HANGEUL:
1248 if (!up_flag)
1249 put_queue(vc, 0xf2);
1250 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
Dmitry Torokhove0785572010-03-21 22:31:26 -07001252 case KEY_HANJA:
1253 if (!up_flag)
1254 put_queue(vc, 0xf1);
1255 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
Dmitry Torokhove0785572010-03-21 22:31:26 -07001257 case KEY_SYSRQ:
1258 /*
1259 * Real AT keyboards (that's what we're trying
1260 * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
1261 * pressing PrtSc/SysRq alone, but simply 0x54
1262 * when pressing Alt+PrtSc/SysRq.
1263 */
1264 if (test_bit(KEY_LEFTALT, key_down) ||
1265 test_bit(KEY_RIGHTALT, key_down)) {
1266 put_queue(vc, 0x54 | up_flag);
1267 } else {
1268 put_queue(vc, 0xe0);
1269 put_queue(vc, 0x2a | up_flag);
1270 put_queue(vc, 0xe0);
1271 put_queue(vc, 0x37 | up_flag);
1272 }
1273 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Dmitry Torokhove0785572010-03-21 22:31:26 -07001275 default:
1276 if (keycode > 255)
1277 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
Dmitry Torokhove0785572010-03-21 22:31:26 -07001279 code = x86_keycodes[keycode];
1280 if (!code)
1281 return -1;
Dmitry Torokhov896cdc72006-07-19 01:14:25 -04001282
Dmitry Torokhove0785572010-03-21 22:31:26 -07001283 if (code & 0x100)
1284 put_queue(vc, 0xe0);
1285 put_queue(vc, (code & 0x7f) | up_flag);
1286
1287 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 }
1289
1290 return 0;
1291}
1292
1293#else
1294
1295#define HW_RAW(dev) 0
1296
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
1298{
1299 if (keycode > 127)
1300 return -1;
1301
1302 put_queue(vc, keycode | up_flag);
1303 return 0;
1304}
1305#endif
1306
1307static void kbd_rawcode(unsigned char data)
1308{
1309 struct vc_data *vc = vc_cons[fg_console].d;
Dmitry Torokhove0785572010-03-21 22:31:26 -07001310
Alan Jenkins0c09b2a2009-11-18 00:40:48 -08001311 kbd = kbd_table + vc->vc_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 if (kbd->kbdmode == VC_RAW)
1313 put_queue(vc, data);
1314}
1315
David Howells7d12e782006-10-05 14:55:46 +01001316static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317{
1318 struct vc_data *vc = vc_cons[fg_console].d;
1319 unsigned short keysym, *key_map;
Dmitry Torokhove0785572010-03-21 22:31:26 -07001320 unsigned char type;
1321 bool raw_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 struct tty_struct *tty;
1323 int shift_final;
Samuel Thibault41ab4392007-10-18 23:39:12 -07001324 struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
Dmitry Torokhove0785572010-03-21 22:31:26 -07001325 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
Alan Cox8ce73262010-06-01 22:52:56 +02001327 tty = vc->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
1329 if (tty && (!tty->driver_data)) {
1330 /* No driver data? Strange. Okay we fix it then. */
1331 tty->driver_data = vc;
1332 }
1333
Alan Jenkins0c09b2a2009-11-18 00:40:48 -08001334 kbd = kbd_table + vc->vc_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001336#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 if (keycode == KEY_STOP)
1338 sparc_l1_a_state = down;
1339#endif
1340
1341 rep = (down == 2);
1342
Dmitry Torokhove0785572010-03-21 22:31:26 -07001343 raw_mode = (kbd->kbdmode == VC_RAW);
1344 if (raw_mode && !hw_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 if (emulate_raw(vc, keycode, !down << 7))
Dmitry Torokhov9e35d202007-04-12 01:30:52 -04001346 if (keycode < BTN_MISC && printk_ratelimit())
Joe Perchese620e542014-11-09 22:46:35 -08001347 pr_warn("can't emulate rawmode for keycode %d\n",
1348 keycode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001350#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 if (keycode == KEY_A && sparc_l1_a_state) {
Dmitry Torokhove0785572010-03-21 22:31:26 -07001352 sparc_l1_a_state = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 sun_do_break();
1354 }
1355#endif
1356
1357 if (kbd->kbdmode == VC_MEDIUMRAW) {
1358 /*
1359 * This is extended medium raw mode, with keys above 127
1360 * encoded as 0, high 7 bits, low 7 bits, with the 0 bearing
1361 * the 'up' flag if needed. 0 is reserved, so this shouldn't
1362 * interfere with anything else. The two bytes after 0 will
1363 * always have the up flag set not to interfere with older
1364 * applications. This allows for 16384 different keycodes,
1365 * which should be enough.
1366 */
1367 if (keycode < 128) {
1368 put_queue(vc, keycode | (!down << 7));
1369 } else {
1370 put_queue(vc, !down << 7);
1371 put_queue(vc, (keycode >> 7) | 0x80);
1372 put_queue(vc, keycode | 0x80);
1373 }
Dmitry Torokhove0785572010-03-21 22:31:26 -07001374 raw_mode = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 }
1376
1377 if (down)
1378 set_bit(keycode, key_down);
1379 else
1380 clear_bit(keycode, key_down);
1381
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001382 if (rep &&
1383 (!vc_kbd_mode(kbd, VC_REPEAT) ||
Alan Coxf34d7a52008-04-30 00:54:13 -07001384 (tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 /*
1386 * Don't repeat a key if the input buffers are not empty and the
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001387 * characters get aren't echoed locally. This makes key repeat
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 * usable with slow applications and under heavy loads.
1389 */
1390 return;
1391 }
1392
Samuel Thibault41ab4392007-10-18 23:39:12 -07001393 param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
Karl Dahlke0beb4f62008-04-15 01:30:32 -04001394 param.ledstate = kbd->ledflagstate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 key_map = key_maps[shift_final];
1396
Dmitry Torokhove0785572010-03-21 22:31:26 -07001397 rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1398 KBD_KEYCODE, &param);
1399 if (rc == NOTIFY_STOP || !key_map) {
1400 atomic_notifier_call_chain(&keyboard_notifier_list,
1401 KBD_UNBOUND_KEYCODE, &param);
Alan Cox079c9532012-02-28 14:49:23 +00001402 do_compute_shiftstate();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 kbd->slockstate = 0;
1404 return;
1405 }
1406
Dmitry Torokhove0785572010-03-21 22:31:26 -07001407 if (keycode < NR_KEYS)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -05001408 keysym = key_map[keycode];
Dmitry Torokhove0785572010-03-21 22:31:26 -07001409 else if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
1410 keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1));
1411 else
1412 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 type = KTYP(keysym);
1415
1416 if (type < 0xf0) {
Samuel Thibault41ab4392007-10-18 23:39:12 -07001417 param.value = keysym;
Dmitry Torokhove0785572010-03-21 22:31:26 -07001418 rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1419 KBD_UNICODE, &param);
1420 if (rc != NOTIFY_STOP)
1421 if (down && !raw_mode)
1422 to_utf8(vc, keysym);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 return;
1424 }
1425
1426 type -= 0xf0;
1427
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 if (type == KT_LETTER) {
1429 type = KT_LATIN;
1430 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
1431 key_map = key_maps[shift_final ^ (1 << KG_SHIFT)];
1432 if (key_map)
1433 keysym = key_map[keycode];
1434 }
1435 }
Samuel Thibault41ab4392007-10-18 23:39:12 -07001436
Dmitry Torokhove0785572010-03-21 22:31:26 -07001437 param.value = keysym;
1438 rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1439 KBD_KEYSYM, &param);
1440 if (rc == NOTIFY_STOP)
Samuel Thibault41ab4392007-10-18 23:39:12 -07001441 return;
1442
Arthur Taylor9fc3de92011-02-04 13:55:50 -08001443 if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type != KT_SHIFT)
Samuel Thibault41ab4392007-10-18 23:39:12 -07001444 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445
David Howells7d12e782006-10-05 14:55:46 +01001446 (*k_handler[type])(vc, keysym & 0xff, !down);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
Karl Dahlke0beb4f62008-04-15 01:30:32 -04001448 param.ledstate = kbd->ledflagstate;
Samuel Thibault41ab4392007-10-18 23:39:12 -07001449 atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
1450
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 if (type != KT_SLOCK)
1452 kbd->slockstate = 0;
1453}
1454
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001455static void kbd_event(struct input_handle *handle, unsigned int event_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 unsigned int event_code, int value)
1457{
Dmitry Torokhov21cea582009-11-29 23:40:58 -08001458 /* We are called with interrupts disabled, just take the lock */
1459 spin_lock(&kbd_event_lock);
1460
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
1462 kbd_rawcode(value);
Dmitry Torokhovf111d792019-11-22 12:42:20 -08001463 if (event_type == EV_KEY && event_code <= KEY_MAX)
David Howells7d12e782006-10-05 14:55:46 +01001464 kbd_keycode(event_code, value, HW_RAW(handle->dev));
Dmitry Torokhov21cea582009-11-29 23:40:58 -08001465
1466 spin_unlock(&kbd_event_lock);
1467
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 tasklet_schedule(&keyboard_tasklet);
1469 do_poke_blanked_console = 1;
1470 schedule_console_callback();
1471}
1472
Dmitry Torokhov0b7024ac2010-02-02 21:08:26 -08001473static bool kbd_match(struct input_handler *handler, struct input_dev *dev)
1474{
1475 int i;
1476
1477 if (test_bit(EV_SND, dev->evbit))
1478 return true;
1479
Samuel Thibault53c1f762010-07-31 02:28:51 -07001480 if (test_bit(EV_KEY, dev->evbit)) {
Dmitry Torokhov0b7024ac2010-02-02 21:08:26 -08001481 for (i = KEY_RESERVED; i < BTN_MISC; i++)
1482 if (test_bit(i, dev->keybit))
1483 return true;
Samuel Thibault53c1f762010-07-31 02:28:51 -07001484 for (i = KEY_BRL_DOT1; i <= KEY_BRL_DOT10; i++)
1485 if (test_bit(i, dev->keybit))
1486 return true;
1487 }
Dmitry Torokhov0b7024ac2010-02-02 21:08:26 -08001488
1489 return false;
1490}
1491
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492/*
1493 * When a keyboard (or other input device) is found, the kbd_connect
1494 * function is called. The function then looks at the device, and if it
1495 * likes it, it can open it and get events from it. In this (kbd_connect)
1496 * function, we should decide which VT to bind that keyboard to initially.
1497 */
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001498static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
1499 const struct input_device_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500{
1501 struct input_handle *handle;
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001502 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
Dmitry Torokhov22479e12006-08-04 22:51:51 -04001504 handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
1505 if (!handle)
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001506 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
1508 handle->dev = dev;
1509 handle->handler = handler;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001510 handle->name = "kbd";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001512 error = input_register_handle(handle);
1513 if (error)
1514 goto err_free_handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001516 error = input_open_device(handle);
1517 if (error)
1518 goto err_unregister_handle;
1519
1520 return 0;
1521
1522 err_unregister_handle:
1523 input_unregister_handle(handle);
1524 err_free_handle:
1525 kfree(handle);
1526 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527}
1528
1529static void kbd_disconnect(struct input_handle *handle)
1530{
1531 input_close_device(handle);
Dmitry Torokhov5b2a0822007-04-12 01:29:46 -04001532 input_unregister_handle(handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 kfree(handle);
1534}
1535
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001536/*
1537 * Start keyboard handler on the new keyboard by refreshing LED state to
1538 * match the rest of the system.
1539 */
1540static void kbd_start(struct input_handle *handle)
1541{
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001542 tasklet_disable(&keyboard_tasklet);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -08001543
Samuel Thibaulteeb64c12015-06-06 11:44:39 -07001544 if (ledstate != -1U)
1545 kbd_update_leds_helper(handle, &ledstate);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -08001546
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001547 tasklet_enable(&keyboard_tasklet);
1548}
1549
Dmitry Torokhov66e66112006-09-14 01:31:59 -04001550static const struct input_device_id kbd_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 {
Alan Cox6aeed472012-02-24 12:47:29 +00001552 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1553 .evbit = { BIT_MASK(EV_KEY) },
1554 },
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001555
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 {
Alan Cox6aeed472012-02-24 12:47:29 +00001557 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1558 .evbit = { BIT_MASK(EV_SND) },
1559 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
1561 { }, /* Terminating entry */
1562};
1563
1564MODULE_DEVICE_TABLE(input, kbd_ids);
1565
1566static struct input_handler kbd_handler = {
1567 .event = kbd_event,
Dmitry Torokhov0b7024ac2010-02-02 21:08:26 -08001568 .match = kbd_match,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 .connect = kbd_connect,
1570 .disconnect = kbd_disconnect,
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001571 .start = kbd_start,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 .name = "kbd",
1573 .id_table = kbd_ids,
1574};
1575
1576int __init kbd_init(void)
1577{
1578 int i;
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001579 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
Alan Cox6aeed472012-02-24 12:47:29 +00001581 for (i = 0; i < MAX_NR_CONSOLES; i++) {
Joshua Covb2d0b7a2012-04-13 21:08:26 +02001582 kbd_table[i].ledflagstate = kbd_defleds();
1583 kbd_table[i].default_ledflagstate = kbd_defleds();
Dmitry Torokhov2b192902006-07-19 01:13:26 -04001584 kbd_table[i].ledmode = LED_SHOW_FLAGS;
1585 kbd_table[i].lockstate = KBD_DEFLOCK;
1586 kbd_table[i].slockstate = 0;
1587 kbd_table[i].modeflags = KBD_DEFMODE;
Bill Nottingham2e8ecb92007-10-16 23:29:38 -07001588 kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
Dmitry Torokhov2b192902006-07-19 01:13:26 -04001589 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590
Samuel Thibault52355522015-03-16 21:19:44 -07001591 kbd_init_leds();
1592
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001593 error = input_register_handler(&kbd_handler);
1594 if (error)
1595 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
1597 tasklet_enable(&keyboard_tasklet);
1598 tasklet_schedule(&keyboard_tasklet);
1599
1600 return 0;
1601}
Alan Cox247ff8e2012-02-24 12:47:11 +00001602
1603/* Ioctl support code */
1604
1605/**
1606 * vt_do_diacrit - diacritical table updates
1607 * @cmd: ioctl request
Mark Rustad9d329c12014-09-05 18:57:57 -07001608 * @udp: pointer to user data for ioctl
Alan Cox247ff8e2012-02-24 12:47:11 +00001609 * @perm: permissions check computed by caller
1610 *
1611 * Update the diacritical tables atomically and safely. Lock them
1612 * against simultaneous keypresses
1613 */
Mark Rustad9d329c12014-09-05 18:57:57 -07001614int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
Alan Cox247ff8e2012-02-24 12:47:11 +00001615{
Alan Cox247ff8e2012-02-24 12:47:11 +00001616 unsigned long flags;
1617 int asize;
1618 int ret = 0;
1619
1620 switch (cmd) {
1621 case KDGKBDIACR:
1622 {
Mark Rustad9d329c12014-09-05 18:57:57 -07001623 struct kbdiacrs __user *a = udp;
1624 struct kbdiacr *dia;
Alan Cox247ff8e2012-02-24 12:47:11 +00001625 int i;
1626
Mark Rustad9d329c12014-09-05 18:57:57 -07001627 dia = kmalloc(MAX_DIACR * sizeof(struct kbdiacr),
Alan Cox247ff8e2012-02-24 12:47:11 +00001628 GFP_KERNEL);
Mark Rustad9d329c12014-09-05 18:57:57 -07001629 if (!dia)
Alan Cox247ff8e2012-02-24 12:47:11 +00001630 return -ENOMEM;
1631
1632 /* Lock the diacriticals table, make a copy and then
1633 copy it after we unlock */
1634 spin_lock_irqsave(&kbd_event_lock, flags);
1635
1636 asize = accent_table_size;
1637 for (i = 0; i < asize; i++) {
Mark Rustad9d329c12014-09-05 18:57:57 -07001638 dia[i].diacr = conv_uni_to_8bit(
Alan Cox247ff8e2012-02-24 12:47:11 +00001639 accent_table[i].diacr);
Mark Rustad9d329c12014-09-05 18:57:57 -07001640 dia[i].base = conv_uni_to_8bit(
Alan Cox247ff8e2012-02-24 12:47:11 +00001641 accent_table[i].base);
Mark Rustad9d329c12014-09-05 18:57:57 -07001642 dia[i].result = conv_uni_to_8bit(
Alan Cox247ff8e2012-02-24 12:47:11 +00001643 accent_table[i].result);
1644 }
1645 spin_unlock_irqrestore(&kbd_event_lock, flags);
1646
1647 if (put_user(asize, &a->kb_cnt))
1648 ret = -EFAULT;
Mark Rustad9d329c12014-09-05 18:57:57 -07001649 else if (copy_to_user(a->kbdiacr, dia,
Alan Cox247ff8e2012-02-24 12:47:11 +00001650 asize * sizeof(struct kbdiacr)))
1651 ret = -EFAULT;
Mark Rustad9d329c12014-09-05 18:57:57 -07001652 kfree(dia);
Alan Cox247ff8e2012-02-24 12:47:11 +00001653 return ret;
1654 }
1655 case KDGKBDIACRUC:
1656 {
Mark Rustad9d329c12014-09-05 18:57:57 -07001657 struct kbdiacrsuc __user *a = udp;
Alan Cox247ff8e2012-02-24 12:47:11 +00001658 void *buf;
1659
1660 buf = kmalloc(MAX_DIACR * sizeof(struct kbdiacruc),
1661 GFP_KERNEL);
1662 if (buf == NULL)
1663 return -ENOMEM;
1664
1665 /* Lock the diacriticals table, make a copy and then
1666 copy it after we unlock */
1667 spin_lock_irqsave(&kbd_event_lock, flags);
1668
1669 asize = accent_table_size;
1670 memcpy(buf, accent_table, asize * sizeof(struct kbdiacruc));
1671
1672 spin_unlock_irqrestore(&kbd_event_lock, flags);
1673
1674 if (put_user(asize, &a->kb_cnt))
1675 ret = -EFAULT;
1676 else if (copy_to_user(a->kbdiacruc, buf,
1677 asize*sizeof(struct kbdiacruc)))
1678 ret = -EFAULT;
1679 kfree(buf);
1680 return ret;
1681 }
1682
1683 case KDSKBDIACR:
1684 {
Mark Rustad9d329c12014-09-05 18:57:57 -07001685 struct kbdiacrs __user *a = udp;
1686 struct kbdiacr *dia = NULL;
Alan Cox247ff8e2012-02-24 12:47:11 +00001687 unsigned int ct;
1688 int i;
1689
1690 if (!perm)
1691 return -EPERM;
1692 if (get_user(ct, &a->kb_cnt))
1693 return -EFAULT;
1694 if (ct >= MAX_DIACR)
1695 return -EINVAL;
1696
1697 if (ct) {
Alan Cox247ff8e2012-02-24 12:47:11 +00001698
Saurabh Sengar10519372015-10-28 11:56:44 +05301699 dia = memdup_user(a->kbdiacr,
1700 sizeof(struct kbdiacr) * ct);
1701 if (IS_ERR(dia))
1702 return PTR_ERR(dia);
1703
Alan Cox247ff8e2012-02-24 12:47:11 +00001704 }
1705
1706 spin_lock_irqsave(&kbd_event_lock, flags);
1707 accent_table_size = ct;
1708 for (i = 0; i < ct; i++) {
1709 accent_table[i].diacr =
Mark Rustad9d329c12014-09-05 18:57:57 -07001710 conv_8bit_to_uni(dia[i].diacr);
Alan Cox247ff8e2012-02-24 12:47:11 +00001711 accent_table[i].base =
Mark Rustad9d329c12014-09-05 18:57:57 -07001712 conv_8bit_to_uni(dia[i].base);
Alan Cox247ff8e2012-02-24 12:47:11 +00001713 accent_table[i].result =
Mark Rustad9d329c12014-09-05 18:57:57 -07001714 conv_8bit_to_uni(dia[i].result);
Alan Cox247ff8e2012-02-24 12:47:11 +00001715 }
1716 spin_unlock_irqrestore(&kbd_event_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07001717 kfree(dia);
Alan Cox247ff8e2012-02-24 12:47:11 +00001718 return 0;
1719 }
1720
1721 case KDSKBDIACRUC:
1722 {
Mark Rustad9d329c12014-09-05 18:57:57 -07001723 struct kbdiacrsuc __user *a = udp;
Alan Cox247ff8e2012-02-24 12:47:11 +00001724 unsigned int ct;
1725 void *buf = NULL;
1726
1727 if (!perm)
1728 return -EPERM;
1729
1730 if (get_user(ct, &a->kb_cnt))
1731 return -EFAULT;
1732
1733 if (ct >= MAX_DIACR)
1734 return -EINVAL;
1735
1736 if (ct) {
Muhammad Falak R Wani9b651902016-05-20 17:53:28 +05301737 buf = memdup_user(a->kbdiacruc,
1738 ct * sizeof(struct kbdiacruc));
1739 if (IS_ERR(buf))
1740 return PTR_ERR(buf);
Alan Cox247ff8e2012-02-24 12:47:11 +00001741 }
1742 spin_lock_irqsave(&kbd_event_lock, flags);
1743 if (ct)
1744 memcpy(accent_table, buf,
1745 ct * sizeof(struct kbdiacruc));
1746 accent_table_size = ct;
1747 spin_unlock_irqrestore(&kbd_event_lock, flags);
1748 kfree(buf);
1749 return 0;
1750 }
1751 }
1752 return ret;
1753}
Alan Cox079c9532012-02-28 14:49:23 +00001754
1755/**
1756 * vt_do_kdskbmode - set keyboard mode ioctl
1757 * @console: the console to use
1758 * @arg: the requested mode
1759 *
1760 * Update the keyboard mode bits while holding the correct locks.
1761 * Return 0 for success or an error code.
1762 */
1763int vt_do_kdskbmode(int console, unsigned int arg)
1764{
Mark Rustad9d329c12014-09-05 18:57:57 -07001765 struct kbd_struct *kb = kbd_table + console;
Alan Cox079c9532012-02-28 14:49:23 +00001766 int ret = 0;
1767 unsigned long flags;
1768
1769 spin_lock_irqsave(&kbd_event_lock, flags);
1770 switch(arg) {
1771 case K_RAW:
Mark Rustad9d329c12014-09-05 18:57:57 -07001772 kb->kbdmode = VC_RAW;
Alan Cox079c9532012-02-28 14:49:23 +00001773 break;
1774 case K_MEDIUMRAW:
Mark Rustad9d329c12014-09-05 18:57:57 -07001775 kb->kbdmode = VC_MEDIUMRAW;
Alan Cox079c9532012-02-28 14:49:23 +00001776 break;
1777 case K_XLATE:
Mark Rustad9d329c12014-09-05 18:57:57 -07001778 kb->kbdmode = VC_XLATE;
Alan Cox079c9532012-02-28 14:49:23 +00001779 do_compute_shiftstate();
1780 break;
1781 case K_UNICODE:
Mark Rustad9d329c12014-09-05 18:57:57 -07001782 kb->kbdmode = VC_UNICODE;
Alan Cox079c9532012-02-28 14:49:23 +00001783 do_compute_shiftstate();
1784 break;
1785 case K_OFF:
Mark Rustad9d329c12014-09-05 18:57:57 -07001786 kb->kbdmode = VC_OFF;
Alan Cox079c9532012-02-28 14:49:23 +00001787 break;
1788 default:
1789 ret = -EINVAL;
1790 }
1791 spin_unlock_irqrestore(&kbd_event_lock, flags);
1792 return ret;
1793}
1794
1795/**
1796 * vt_do_kdskbmeta - set keyboard meta state
1797 * @console: the console to use
1798 * @arg: the requested meta state
1799 *
1800 * Update the keyboard meta bits while holding the correct locks.
1801 * Return 0 for success or an error code.
1802 */
1803int vt_do_kdskbmeta(int console, unsigned int arg)
1804{
Mark Rustad9d329c12014-09-05 18:57:57 -07001805 struct kbd_struct *kb = kbd_table + console;
Alan Cox079c9532012-02-28 14:49:23 +00001806 int ret = 0;
1807 unsigned long flags;
1808
1809 spin_lock_irqsave(&kbd_event_lock, flags);
1810 switch(arg) {
1811 case K_METABIT:
Mark Rustad9d329c12014-09-05 18:57:57 -07001812 clr_vc_kbd_mode(kb, VC_META);
Alan Cox079c9532012-02-28 14:49:23 +00001813 break;
1814 case K_ESCPREFIX:
Mark Rustad9d329c12014-09-05 18:57:57 -07001815 set_vc_kbd_mode(kb, VC_META);
Alan Cox079c9532012-02-28 14:49:23 +00001816 break;
1817 default:
1818 ret = -EINVAL;
1819 }
1820 spin_unlock_irqrestore(&kbd_event_lock, flags);
1821 return ret;
1822}
1823
1824int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
1825 int perm)
1826{
1827 struct kbkeycode tmp;
1828 int kc = 0;
1829
1830 if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
1831 return -EFAULT;
1832 switch (cmd) {
1833 case KDGETKEYCODE:
1834 kc = getkeycode(tmp.scancode);
1835 if (kc >= 0)
1836 kc = put_user(kc, &user_kbkc->keycode);
1837 break;
1838 case KDSETKEYCODE:
1839 if (!perm)
1840 return -EPERM;
1841 kc = setkeycode(tmp.scancode, tmp.keycode);
1842 break;
1843 }
1844 return kc;
1845}
1846
1847#define i (tmp.kb_index)
1848#define s (tmp.kb_table)
1849#define v (tmp.kb_value)
1850
1851int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
1852 int console)
1853{
Mark Rustad9d329c12014-09-05 18:57:57 -07001854 struct kbd_struct *kb = kbd_table + console;
Alan Cox079c9532012-02-28 14:49:23 +00001855 struct kbentry tmp;
1856 ushort *key_map, *new_map, val, ov;
1857 unsigned long flags;
1858
1859 if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
1860 return -EFAULT;
1861
1862 if (!capable(CAP_SYS_TTY_CONFIG))
1863 perm = 0;
1864
1865 switch (cmd) {
1866 case KDGKBENT:
1867 /* Ensure another thread doesn't free it under us */
1868 spin_lock_irqsave(&kbd_event_lock, flags);
1869 key_map = key_maps[s];
1870 if (key_map) {
1871 val = U(key_map[i]);
Mark Rustad9d329c12014-09-05 18:57:57 -07001872 if (kb->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
Alan Cox079c9532012-02-28 14:49:23 +00001873 val = K_HOLE;
1874 } else
1875 val = (i ? K_HOLE : K_NOSUCHMAP);
1876 spin_unlock_irqrestore(&kbd_event_lock, flags);
1877 return put_user(val, &user_kbe->kb_value);
1878 case KDSKBENT:
1879 if (!perm)
1880 return -EPERM;
1881 if (!i && v == K_NOSUCHMAP) {
1882 spin_lock_irqsave(&kbd_event_lock, flags);
1883 /* deallocate map */
1884 key_map = key_maps[s];
1885 if (s && key_map) {
1886 key_maps[s] = NULL;
1887 if (key_map[0] == U(K_ALLOCATED)) {
1888 kfree(key_map);
1889 keymap_count--;
1890 }
1891 }
1892 spin_unlock_irqrestore(&kbd_event_lock, flags);
1893 break;
1894 }
1895
1896 if (KTYP(v) < NR_TYPES) {
1897 if (KVAL(v) > max_vals[KTYP(v)])
1898 return -EINVAL;
1899 } else
Mark Rustad9d329c12014-09-05 18:57:57 -07001900 if (kb->kbdmode != VC_UNICODE)
Alan Cox079c9532012-02-28 14:49:23 +00001901 return -EINVAL;
1902
1903 /* ++Geert: non-PC keyboards may generate keycode zero */
1904#if !defined(__mc68000__) && !defined(__powerpc__)
1905 /* assignment to entry 0 only tests validity of args */
1906 if (!i)
1907 break;
1908#endif
1909
1910 new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
1911 if (!new_map)
1912 return -ENOMEM;
1913 spin_lock_irqsave(&kbd_event_lock, flags);
1914 key_map = key_maps[s];
1915 if (key_map == NULL) {
1916 int j;
1917
1918 if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
1919 !capable(CAP_SYS_RESOURCE)) {
1920 spin_unlock_irqrestore(&kbd_event_lock, flags);
1921 kfree(new_map);
1922 return -EPERM;
1923 }
1924 key_maps[s] = new_map;
Dan Carpenter82896212012-03-10 11:59:23 +03001925 key_map = new_map;
Alan Cox079c9532012-02-28 14:49:23 +00001926 key_map[0] = U(K_ALLOCATED);
1927 for (j = 1; j < NR_KEYS; j++)
1928 key_map[j] = U(K_HOLE);
1929 keymap_count++;
1930 } else
1931 kfree(new_map);
1932
1933 ov = U(key_map[i]);
1934 if (v == ov)
1935 goto out;
1936 /*
1937 * Attention Key.
1938 */
1939 if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) {
1940 spin_unlock_irqrestore(&kbd_event_lock, flags);
1941 return -EPERM;
1942 }
1943 key_map[i] = U(v);
1944 if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
1945 do_compute_shiftstate();
1946out:
1947 spin_unlock_irqrestore(&kbd_event_lock, flags);
1948 break;
1949 }
1950 return 0;
1951}
1952#undef i
1953#undef s
1954#undef v
1955
1956/* FIXME: This one needs untangling and locking */
1957int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
1958{
1959 struct kbsentry *kbs;
1960 char *p;
1961 u_char *q;
1962 u_char __user *up;
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00001963 int sz, fnw_sz;
Alan Cox079c9532012-02-28 14:49:23 +00001964 int delta;
1965 char *first_free, *fj, *fnw;
1966 int i, j, k;
1967 int ret;
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00001968 unsigned long flags;
Alan Cox079c9532012-02-28 14:49:23 +00001969
1970 if (!capable(CAP_SYS_TTY_CONFIG))
1971 perm = 0;
1972
1973 kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
1974 if (!kbs) {
1975 ret = -ENOMEM;
1976 goto reterr;
1977 }
1978
1979 /* we mostly copy too much here (512bytes), but who cares ;) */
1980 if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
1981 ret = -EFAULT;
1982 goto reterr;
1983 }
1984 kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
1985 i = kbs->kb_func;
1986
1987 switch (cmd) {
1988 case KDGKBSENT:
1989 sz = sizeof(kbs->kb_string) - 1; /* sz should have been
1990 a struct member */
1991 up = user_kdgkb->kb_string;
1992 p = func_table[i];
1993 if(p)
1994 for ( ; *p && sz; p++, sz--)
1995 if (put_user(*p, up++)) {
1996 ret = -EFAULT;
1997 goto reterr;
1998 }
1999 if (put_user('\0', up)) {
2000 ret = -EFAULT;
2001 goto reterr;
2002 }
2003 kfree(kbs);
2004 return ((p && *p) ? -EOVERFLOW : 0);
2005 case KDSKBSENT:
2006 if (!perm) {
2007 ret = -EPERM;
2008 goto reterr;
2009 }
2010
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00002011 fnw = NULL;
2012 fnw_sz = 0;
2013 /* race aginst other writers */
2014 again:
2015 spin_lock_irqsave(&func_buf_lock, flags);
Alan Cox079c9532012-02-28 14:49:23 +00002016 q = func_table[i];
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00002017
2018 /* fj pointer to next entry after 'q' */
Alan Cox079c9532012-02-28 14:49:23 +00002019 first_free = funcbufptr + (funcbufsize - funcbufleft);
2020 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
2021 ;
2022 if (j < MAX_NR_FUNC)
2023 fj = func_table[j];
2024 else
2025 fj = first_free;
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00002026 /* buffer usage increase by new entry */
Alan Cox079c9532012-02-28 14:49:23 +00002027 delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string);
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00002028
Alan Cox079c9532012-02-28 14:49:23 +00002029 if (delta <= funcbufleft) { /* it fits in current buf */
2030 if (j < MAX_NR_FUNC) {
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00002031 /* make enough space for new entry at 'fj' */
Alan Cox079c9532012-02-28 14:49:23 +00002032 memmove(fj + delta, fj, first_free - fj);
2033 for (k = j; k < MAX_NR_FUNC; k++)
2034 if (func_table[k])
2035 func_table[k] += delta;
2036 }
2037 if (!q)
2038 func_table[i] = fj;
2039 funcbufleft -= delta;
2040 } else { /* allocate a larger buffer */
2041 sz = 256;
2042 while (sz < funcbufsize - funcbufleft + delta)
2043 sz <<= 1;
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00002044 if (fnw_sz != sz) {
2045 spin_unlock_irqrestore(&func_buf_lock, flags);
2046 kfree(fnw);
2047 fnw = kmalloc(sz, GFP_KERNEL);
2048 fnw_sz = sz;
2049 if (!fnw) {
2050 ret = -ENOMEM;
2051 goto reterr;
2052 }
2053 goto again;
Alan Cox079c9532012-02-28 14:49:23 +00002054 }
2055
2056 if (!q)
2057 func_table[i] = fj;
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00002058 /* copy data before insertion point to new location */
Alan Cox079c9532012-02-28 14:49:23 +00002059 if (fj > funcbufptr)
2060 memmove(fnw, funcbufptr, fj - funcbufptr);
2061 for (k = 0; k < j; k++)
2062 if (func_table[k])
2063 func_table[k] = fnw + (func_table[k] - funcbufptr);
2064
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00002065 /* copy data after insertion point to new location */
Alan Cox079c9532012-02-28 14:49:23 +00002066 if (first_free > fj) {
2067 memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
2068 for (k = j; k < MAX_NR_FUNC; k++)
2069 if (func_table[k])
2070 func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
2071 }
2072 if (funcbufptr != func_buf)
2073 kfree(funcbufptr);
2074 funcbufptr = fnw;
2075 funcbufleft = funcbufleft - delta + sz - funcbufsize;
2076 funcbufsize = sz;
2077 }
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00002078 /* finally insert item itself */
Alan Cox079c9532012-02-28 14:49:23 +00002079 strcpy(func_table[i], kbs->kb_string);
Sergei Trofimovich948c9cec2019-03-10 21:24:15 +00002080 spin_unlock_irqrestore(&func_buf_lock, flags);
Alan Cox079c9532012-02-28 14:49:23 +00002081 break;
2082 }
2083 ret = 0;
2084reterr:
2085 kfree(kbs);
2086 return ret;
2087}
2088
2089int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
2090{
Mark Rustad9d329c12014-09-05 18:57:57 -07002091 struct kbd_struct *kb = kbd_table + console;
Alan Cox079c9532012-02-28 14:49:23 +00002092 unsigned long flags;
2093 unsigned char ucval;
2094
2095 switch(cmd) {
2096 /* the ioctls below read/set the flags usually shown in the leds */
2097 /* don't use them - they will go away without warning */
2098 case KDGKBLED:
2099 spin_lock_irqsave(&kbd_event_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07002100 ucval = kb->ledflagstate | (kb->default_ledflagstate << 4);
Alan Cox079c9532012-02-28 14:49:23 +00002101 spin_unlock_irqrestore(&kbd_event_lock, flags);
2102 return put_user(ucval, (char __user *)arg);
2103
2104 case KDSKBLED:
2105 if (!perm)
2106 return -EPERM;
2107 if (arg & ~0x77)
2108 return -EINVAL;
Alan Cox3db1ddb2012-07-17 17:06:41 +01002109 spin_lock_irqsave(&led_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07002110 kb->ledflagstate = (arg & 7);
2111 kb->default_ledflagstate = ((arg >> 4) & 7);
Alan Cox079c9532012-02-28 14:49:23 +00002112 set_leds();
Alan Cox3db1ddb2012-07-17 17:06:41 +01002113 spin_unlock_irqrestore(&led_lock, flags);
Alan Coxeea41ae2012-05-14 14:41:31 +01002114 return 0;
Alan Cox079c9532012-02-28 14:49:23 +00002115
2116 /* the ioctls below only set the lights, not the functions */
2117 /* for those, see KDGKBLED and KDSKBLED above */
2118 case KDGETLED:
2119 ucval = getledstate();
2120 return put_user(ucval, (char __user *)arg);
2121
2122 case KDSETLED:
2123 if (!perm)
2124 return -EPERM;
Mark Rustad9d329c12014-09-05 18:57:57 -07002125 setledstate(kb, arg);
Alan Cox079c9532012-02-28 14:49:23 +00002126 return 0;
2127 }
2128 return -ENOIOCTLCMD;
2129}
2130
2131int vt_do_kdgkbmode(int console)
2132{
Mark Rustad9d329c12014-09-05 18:57:57 -07002133 struct kbd_struct *kb = kbd_table + console;
Alan Cox079c9532012-02-28 14:49:23 +00002134 /* This is a spot read so needs no locking */
Mark Rustad9d329c12014-09-05 18:57:57 -07002135 switch (kb->kbdmode) {
Alan Cox079c9532012-02-28 14:49:23 +00002136 case VC_RAW:
2137 return K_RAW;
2138 case VC_MEDIUMRAW:
2139 return K_MEDIUMRAW;
2140 case VC_UNICODE:
2141 return K_UNICODE;
2142 case VC_OFF:
2143 return K_OFF;
2144 default:
2145 return K_XLATE;
2146 }
2147}
2148
2149/**
2150 * vt_do_kdgkbmeta - report meta status
2151 * @console: console to report
2152 *
2153 * Report the meta flag status of this console
2154 */
2155int vt_do_kdgkbmeta(int console)
2156{
Mark Rustad9d329c12014-09-05 18:57:57 -07002157 struct kbd_struct *kb = kbd_table + console;
Alan Cox079c9532012-02-28 14:49:23 +00002158 /* Again a spot read so no locking */
Mark Rustad9d329c12014-09-05 18:57:57 -07002159 return vc_kbd_mode(kb, VC_META) ? K_ESCPREFIX : K_METABIT;
Alan Cox079c9532012-02-28 14:49:23 +00002160}
2161
2162/**
2163 * vt_reset_unicode - reset the unicode status
2164 * @console: console being reset
2165 *
2166 * Restore the unicode console state to its default
2167 */
2168void vt_reset_unicode(int console)
2169{
2170 unsigned long flags;
2171
2172 spin_lock_irqsave(&kbd_event_lock, flags);
2173 kbd_table[console].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
2174 spin_unlock_irqrestore(&kbd_event_lock, flags);
2175}
2176
2177/**
2178 * vt_get_shiftstate - shift bit state
2179 *
2180 * Report the shift bits from the keyboard state. We have to export
2181 * this to support some oddities in the vt layer.
2182 */
2183int vt_get_shift_state(void)
2184{
2185 /* Don't lock as this is a transient report */
2186 return shift_state;
2187}
2188
2189/**
2190 * vt_reset_keyboard - reset keyboard state
2191 * @console: console to reset
2192 *
2193 * Reset the keyboard bits for a console as part of a general console
2194 * reset event
2195 */
2196void vt_reset_keyboard(int console)
2197{
Mark Rustad9d329c12014-09-05 18:57:57 -07002198 struct kbd_struct *kb = kbd_table + console;
Alan Cox079c9532012-02-28 14:49:23 +00002199 unsigned long flags;
2200
2201 spin_lock_irqsave(&kbd_event_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07002202 set_vc_kbd_mode(kb, VC_REPEAT);
2203 clr_vc_kbd_mode(kb, VC_CKMODE);
2204 clr_vc_kbd_mode(kb, VC_APPLIC);
2205 clr_vc_kbd_mode(kb, VC_CRLF);
2206 kb->lockstate = 0;
2207 kb->slockstate = 0;
Alan Cox3db1ddb2012-07-17 17:06:41 +01002208 spin_lock(&led_lock);
Mark Rustad9d329c12014-09-05 18:57:57 -07002209 kb->ledmode = LED_SHOW_FLAGS;
2210 kb->ledflagstate = kb->default_ledflagstate;
Alan Cox3db1ddb2012-07-17 17:06:41 +01002211 spin_unlock(&led_lock);
Alan Cox079c9532012-02-28 14:49:23 +00002212 /* do not do set_leds here because this causes an endless tasklet loop
2213 when the keyboard hasn't been initialized yet */
2214 spin_unlock_irqrestore(&kbd_event_lock, flags);
2215}
2216
2217/**
2218 * vt_get_kbd_mode_bit - read keyboard status bits
2219 * @console: console to read from
2220 * @bit: mode bit to read
2221 *
2222 * Report back a vt mode bit. We do this without locking so the
2223 * caller must be sure that there are no synchronization needs
2224 */
2225
2226int vt_get_kbd_mode_bit(int console, int bit)
2227{
Mark Rustad9d329c12014-09-05 18:57:57 -07002228 struct kbd_struct *kb = kbd_table + console;
2229 return vc_kbd_mode(kb, bit);
Alan Cox079c9532012-02-28 14:49:23 +00002230}
2231
2232/**
2233 * vt_set_kbd_mode_bit - read keyboard status bits
2234 * @console: console to read from
2235 * @bit: mode bit to read
2236 *
2237 * Set a vt mode bit. We do this without locking so the
2238 * caller must be sure that there are no synchronization needs
2239 */
2240
2241void vt_set_kbd_mode_bit(int console, int bit)
2242{
Mark Rustad9d329c12014-09-05 18:57:57 -07002243 struct kbd_struct *kb = kbd_table + console;
Alan Cox079c9532012-02-28 14:49:23 +00002244 unsigned long flags;
2245
2246 spin_lock_irqsave(&kbd_event_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07002247 set_vc_kbd_mode(kb, bit);
Alan Cox079c9532012-02-28 14:49:23 +00002248 spin_unlock_irqrestore(&kbd_event_lock, flags);
2249}
2250
2251/**
2252 * vt_clr_kbd_mode_bit - read keyboard status bits
2253 * @console: console to read from
2254 * @bit: mode bit to read
2255 *
2256 * Report back a vt mode bit. We do this without locking so the
2257 * caller must be sure that there are no synchronization needs
2258 */
2259
2260void vt_clr_kbd_mode_bit(int console, int bit)
2261{
Mark Rustad9d329c12014-09-05 18:57:57 -07002262 struct kbd_struct *kb = kbd_table + console;
Alan Cox079c9532012-02-28 14:49:23 +00002263 unsigned long flags;
2264
2265 spin_lock_irqsave(&kbd_event_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07002266 clr_vc_kbd_mode(kb, bit);
Alan Cox079c9532012-02-28 14:49:23 +00002267 spin_unlock_irqrestore(&kbd_event_lock, flags);
2268}