blob: be8313cdbac360ac3911b5d9c038dbfceebaaecb [file] [log] [blame]
Greg Kroah-Hartmane3b3d0f2017-11-06 18:11:51 +01001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 * Written for linux by Johan Myreen as a translation from
4 * the assembly version by Linus (with diacriticals added)
5 *
6 * Some additional features added by Christoph Niemann (ChN), March 1993
7 *
8 * Loadable keymaps by Risto Kankkunen, May 1993
9 *
10 * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
11 * Added decr/incr_console, dynamic keymaps, Unicode support,
12 * dynamic function/string keys, led setting, Sept 1994
13 * `Sticky' modifier keys, 951006.
14 *
15 * 11-11-96: SAK should now work in the raw mode (Martin Mares)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050016 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 * Modified to provide 'generic' keyboard support by Hamish Macdonald
18 * Merge with the m68k keyboard driver and split-off of the PC low-level
19 * parts by Geert Uytterhoeven, May 1997
20 *
21 * 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
22 * 30-07-98: Dead keys redone, aeb@cwi.nl.
23 * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
24 */
25
Dmitry Torokhov9272e9a2010-03-21 22:31:26 -070026#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27
Jan Engelhardt759448f2007-07-15 23:40:40 -070028#include <linux/consolemap.h>
Jiri Slaby877a9c62020-10-29 12:32:08 +010029#include <linux/init.h>
30#include <linux/input.h>
31#include <linux/jiffies.h>
32#include <linux/kbd_diacr.h>
33#include <linux/kbd_kern.h>
34#include <linux/leds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/mm.h>
Jiri Slaby877a9c62020-10-29 12:32:08 +010036#include <linux/module.h>
Jiri Slabyf3af1b62020-07-30 12:55:46 +020037#include <linux/nospec.h>
Jiri Slaby877a9c62020-10-29 12:32:08 +010038#include <linux/notifier.h>
39#include <linux/reboot.h>
40#include <linux/sched/debug.h>
41#include <linux/sched/signal.h>
42#include <linux/slab.h>
Jiri Slaby0df97c72020-10-29 12:32:07 +010043#include <linux/spinlock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/string.h>
Jiri Slaby877a9c62020-10-29 12:32:08 +010045#include <linux/tty_flip.h>
46#include <linux/tty.h>
Greg Kroah-Hartman6623d642012-02-27 15:18:56 -080047#include <linux/uaccess.h>
Jiri Slaby877a9c62020-10-29 12:32:08 +010048#include <linux/vt_kern.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Geert Uytterhoeven98c2b372011-09-11 13:59:29 +020050#include <asm/irq_regs.h>
51
Linus Torvalds1da177e2005-04-16 15:20:36 -070052/*
53 * Exported functions/variables
54 */
55
Andy Shevchenkoc050a972020-11-09 12:55:59 +020056#define KBD_DEFMODE (BIT(VC_REPEAT) | BIT(VC_META))
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
Joshua Covb2d0b7a2012-04-13 21:08:26 +020058#if defined(CONFIG_X86) || defined(CONFIG_PARISC)
59#include <asm/kbdleds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#else
Joshua Covb2d0b7a2012-04-13 21:08:26 +020061static inline int kbd_defleds(void)
62{
63 return 0;
64}
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#endif
66
67#define KBD_DEFLOCK 0
68
Linus Torvalds1da177e2005-04-16 15:20:36 -070069/*
70 * Handler Tables.
71 */
72
73#define K_HANDLERS\
74 k_self, k_fn, k_spec, k_pad,\
75 k_dead, k_cons, k_cur, k_shift,\
76 k_meta, k_ascii, k_lock, k_lowercase,\
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -050077 k_slock, k_dead2, k_brl, k_ignore
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050079typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
David Howells7d12e782006-10-05 14:55:46 +010080 char up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -070081static k_handler_fn K_HANDLERS;
Dmitry Torokhov97f5f0c2010-03-21 22:31:26 -070082static k_handler_fn *k_handler[16] = { K_HANDLERS };
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
84#define FN_HANDLERS\
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -050085 fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
86 fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
87 fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
88 fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
89 fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
David Howells7d12e782006-10-05 14:55:46 +010091typedef void (fn_handler_fn)(struct vc_data *vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092static fn_handler_fn FN_HANDLERS;
93static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
94
95/*
96 * Variables exported for vt_ioctl.c
97 */
98
Eric W. Biederman81af8d62006-10-02 02:17:13 -070099struct vt_spawn_console vt_spawn_con = {
Milind Arun Choudharyccc94252007-05-08 00:30:09 -0700100 .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700101 .pid = NULL,
102 .sig = 0,
103};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106/*
107 * Internal Data.
108 */
109
Alan Cox079c9532012-02-28 14:49:23 +0000110static struct kbd_struct kbd_table[MAX_NR_CONSOLES];
111static struct kbd_struct *kbd = kbd_table;
112
113/* maximum values each key_handler can handle */
Jiri Slabye27979d2020-10-29 12:32:10 +0100114static const unsigned char max_vals[] = {
115 [ KT_LATIN ] = 255,
116 [ KT_FN ] = ARRAY_SIZE(func_table) - 1,
117 [ KT_SPEC ] = ARRAY_SIZE(fn_handler) - 1,
118 [ KT_PAD ] = NR_PAD - 1,
119 [ KT_DEAD ] = NR_DEAD - 1,
120 [ KT_CONS ] = 255,
121 [ KT_CUR ] = 3,
122 [ KT_SHIFT ] = NR_SHIFT - 1,
123 [ KT_META ] = 255,
124 [ KT_ASCII ] = NR_ASCII - 1,
125 [ KT_LOCK ] = NR_LOCK - 1,
126 [ KT_LETTER ] = 255,
127 [ KT_SLOCK ] = NR_LOCK - 1,
128 [ KT_DEAD2 ] = 255,
129 [ KT_BRL ] = NR_BRL - 1,
Alan Cox079c9532012-02-28 14:49:23 +0000130};
131
132static const int NR_TYPES = ARRAY_SIZE(max_vals);
133
Emil Renner Berthing91598352021-01-27 17:42:22 +0100134static void kbd_bh(struct tasklet_struct *unused);
135static DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh);
Jiri Slabya18a9da2021-01-05 13:02:29 +0100136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137static struct input_handler kbd_handler;
Dmitry Torokhov21cea582009-11-29 23:40:58 -0800138static DEFINE_SPINLOCK(kbd_event_lock);
Alan Cox3db1ddb2012-07-17 17:06:41 +0100139static DEFINE_SPINLOCK(led_lock);
Sergei Trofimovich46ca3f72019-03-10 21:24:15 +0000140static DEFINE_SPINLOCK(func_buf_lock); /* guard 'func_buf' and friends */
Jiri Slaby29398402020-10-29 12:32:13 +0100141static DECLARE_BITMAP(key_down, KEY_CNT); /* keyboard key bitmap */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
Dmitry Torokhove0785572010-03-21 22:31:26 -0700143static bool dead_key_next;
Dmitry Torokhovb86dab02020-05-25 16:27:40 -0700144
145/* Handles a number being assembled on the number pad */
146static bool npadch_active;
147static unsigned int npadch_value;
148
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500149static unsigned int diacr;
Jiri Slabyfe45d652020-10-29 12:32:14 +0100150static bool rep; /* flag telling character repeat */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
Alan Cox079c9532012-02-28 14:49:23 +0000152static int shift_state = 0;
153
Samuel Thibaulteeb64c12015-06-06 11:44:39 -0700154static unsigned int ledstate = -1U; /* undefined */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155static unsigned char ledioctl;
lianzhi changfb09d0ac02021-12-15 20:51:25 +0800156static bool vt_switch;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158/*
Samuel Thibault41ab4392007-10-18 23:39:12 -0700159 * Notifier list for console keyboard events
160 */
161static ATOMIC_NOTIFIER_HEAD(keyboard_notifier_list);
162
163int register_keyboard_notifier(struct notifier_block *nb)
164{
165 return atomic_notifier_chain_register(&keyboard_notifier_list, nb);
166}
167EXPORT_SYMBOL_GPL(register_keyboard_notifier);
168
169int unregister_keyboard_notifier(struct notifier_block *nb)
170{
171 return atomic_notifier_chain_unregister(&keyboard_notifier_list, nb);
172}
173EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
174
175/*
Marvin Raaijmakersc8e4c772007-03-14 22:50:42 -0400176 * Translation of scancodes to keycodes. We set them on only the first
177 * keyboard in the list that accepts the scancode and keycode.
178 * Explanation for not choosing the first attached keyboard anymore:
179 * USB keyboards for example have two event devices: one for all "normal"
180 * keys and one for extra function keys (like "volume up", "make coffee",
181 * etc.). So this means that scancodes for the extra function keys won't
182 * be valid for the first event device, but will be for the second.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 */
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800184
185struct getset_keycode_data {
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700186 struct input_keymap_entry ke;
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800187 int error;
188};
189
190static int getkeycode_helper(struct input_handle *handle, void *data)
191{
192 struct getset_keycode_data *d = data;
193
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700194 d->error = input_get_keycode(handle->dev, &d->ke);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800195
196 return d->error == 0; /* stop as soon as we successfully get one */
197}
198
Alan Cox079c9532012-02-28 14:49:23 +0000199static int getkeycode(unsigned int scancode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200{
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700201 struct getset_keycode_data d = {
202 .ke = {
203 .flags = 0,
204 .len = sizeof(scancode),
205 .keycode = 0,
206 },
207 .error = -ENODEV,
208 };
209
210 memcpy(d.ke.scancode, &scancode, sizeof(scancode));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800212 input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700214 return d.error ?: d.ke.keycode;
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800215}
216
217static int setkeycode_helper(struct input_handle *handle, void *data)
218{
219 struct getset_keycode_data *d = data;
220
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700221 d->error = input_set_keycode(handle->dev, &d->ke);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800222
223 return d->error == 0; /* stop as soon as we successfully set one */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224}
225
Alan Cox079c9532012-02-28 14:49:23 +0000226static int setkeycode(unsigned int scancode, unsigned int keycode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227{
Mauro Carvalho Chehab8613e4c2010-09-09 21:54:22 -0700228 struct getset_keycode_data d = {
229 .ke = {
230 .flags = 0,
231 .len = sizeof(scancode),
232 .keycode = keycode,
233 },
234 .error = -ENODEV,
235 };
236
237 memcpy(d.ke.scancode, &scancode, sizeof(scancode));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800239 input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800241 return d.error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242}
243
244/*
Dmitry Torokhov18f7ad52009-12-15 16:26:53 -0800245 * Making beeps and bells. Note that we prefer beeps to bells, but when
246 * shutting the sound off we do both.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 */
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800248
249static int kd_sound_helper(struct input_handle *handle, void *data)
250{
251 unsigned int *hz = data;
252 struct input_dev *dev = handle->dev;
253
254 if (test_bit(EV_SND, dev->evbit)) {
Dmitry Torokhov18f7ad52009-12-15 16:26:53 -0800255 if (test_bit(SND_TONE, dev->sndbit)) {
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800256 input_inject_event(handle, EV_SND, SND_TONE, *hz);
Dmitry Torokhov18f7ad52009-12-15 16:26:53 -0800257 if (*hz)
258 return 0;
259 }
260 if (test_bit(SND_BELL, dev->sndbit))
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800261 input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0);
262 }
263
264 return 0;
265}
266
Kees Cook24ed9602017-08-28 11:28:21 -0700267static void kd_nosound(struct timer_list *unused)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268{
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800269 static unsigned int zero;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800271 input_handler_for_each_handle(&kbd_handler, &zero, kd_sound_helper);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272}
273
Kees Cook1d27e3e2017-10-04 16:27:04 -0700274static DEFINE_TIMER(kd_mksound_timer, kd_nosound);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
276void kd_mksound(unsigned int hz, unsigned int ticks)
277{
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800278 del_timer_sync(&kd_mksound_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800280 input_handler_for_each_handle(&kbd_handler, &hz, kd_sound_helper);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800282 if (hz && ticks)
283 mod_timer(&kd_mksound_timer, jiffies + ticks);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284}
Samuel Thibaultf7511d52008-04-30 00:54:51 -0700285EXPORT_SYMBOL(kd_mksound);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
287/*
288 * Setting the keyboard rate.
289 */
290
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800291static int kbd_rate_helper(struct input_handle *handle, void *data)
292{
293 struct input_dev *dev = handle->dev;
Mark Rustad9d329c12014-09-05 18:57:57 -0700294 struct kbd_repeat *rpt = data;
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800295
296 if (test_bit(EV_REP, dev->evbit)) {
297
Mark Rustad9d329c12014-09-05 18:57:57 -0700298 if (rpt[0].delay > 0)
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800299 input_inject_event(handle,
Mark Rustad9d329c12014-09-05 18:57:57 -0700300 EV_REP, REP_DELAY, rpt[0].delay);
301 if (rpt[0].period > 0)
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800302 input_inject_event(handle,
Mark Rustad9d329c12014-09-05 18:57:57 -0700303 EV_REP, REP_PERIOD, rpt[0].period);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800304
Mark Rustad9d329c12014-09-05 18:57:57 -0700305 rpt[1].delay = dev->rep[REP_DELAY];
306 rpt[1].period = dev->rep[REP_PERIOD];
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800307 }
308
309 return 0;
310}
311
Mark Rustad9d329c12014-09-05 18:57:57 -0700312int kbd_rate(struct kbd_repeat *rpt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313{
Mark Rustad9d329c12014-09-05 18:57:57 -0700314 struct kbd_repeat data[2] = { *rpt };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
Dmitry Torokhov66d2a592009-12-01 21:54:35 -0800316 input_handler_for_each_handle(&kbd_handler, data, kbd_rate_helper);
Mark Rustad9d329c12014-09-05 18:57:57 -0700317 *rpt = data[1]; /* Copy currently used settings */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 return 0;
320}
321
322/*
323 * Helper Functions.
324 */
325static void put_queue(struct vc_data *vc, int ch)
326{
Jiri Slaby92a19f92013-01-03 15:53:03 +0100327 tty_insert_flip_char(&vc->port, ch, 0);
Jiri Slaby5f6a8512021-11-22 12:16:46 +0100328 tty_flip_buffer_push(&vc->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329}
330
Jiri Slabyc35f6382020-10-29 12:32:22 +0100331static void puts_queue(struct vc_data *vc, const char *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332{
Jiri Slabyc35f6382020-10-29 12:32:22 +0100333 tty_insert_flip_string(&vc->port, cp, strlen(cp));
Jiri Slaby5f6a8512021-11-22 12:16:46 +0100334 tty_flip_buffer_push(&vc->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335}
336
337static void applkey(struct vc_data *vc, int key, char mode)
338{
339 static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
340
341 buf[1] = (mode ? 'O' : '[');
342 buf[2] = key;
343 puts_queue(vc, buf);
344}
345
346/*
347 * Many other routines do put_queue, but I think either
348 * they produce ASCII, or they produce some user-assigned
349 * string, and in both cases we might assume that it is
Jan Engelhardt759448f2007-07-15 23:40:40 -0700350 * in utf-8 already.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 */
Jan Engelhardt759448f2007-07-15 23:40:40 -0700352static void to_utf8(struct vc_data *vc, uint c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353{
354 if (c < 0x80)
355 /* 0******* */
356 put_queue(vc, c);
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500357 else if (c < 0x800) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 /* 110***** 10****** */
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500359 put_queue(vc, 0xc0 | (c >> 6));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhove0785572010-03-21 22:31:26 -0700361 } else if (c < 0x10000) {
362 if (c >= 0xD800 && c < 0xE000)
Jan Engelhardt759448f2007-07-15 23:40:40 -0700363 return;
364 if (c == 0xFFFF)
365 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 /* 1110**** 10****** 10****** */
367 put_queue(vc, 0xe0 | (c >> 12));
368 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
369 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhove0785572010-03-21 22:31:26 -0700370 } else if (c < 0x110000) {
Jan Engelhardt759448f2007-07-15 23:40:40 -0700371 /* 11110*** 10****** 10****** 10****** */
372 put_queue(vc, 0xf0 | (c >> 18));
373 put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
374 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
375 put_queue(vc, 0x80 | (c & 0x3f));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377}
378
Jiri Slaby63f24a72021-01-05 13:02:28 +0100379/* FIXME: review locking for vt.c callers */
380static void set_leds(void)
381{
382 tasklet_schedule(&keyboard_tasklet);
383}
384
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500385/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 * Called after returning from RAW mode or when changing consoles - recompute
387 * shift_down[] and shift_state from key_down[] maybe called when keymap is
Alan Cox079c9532012-02-28 14:49:23 +0000388 * undefined, so that shiftkey release is seen. The caller must hold the
389 * kbd_event_lock.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 */
Alan Cox079c9532012-02-28 14:49:23 +0000391
392static void do_compute_shiftstate(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393{
Dmitry Torokhov510cccb2016-06-27 14:12:34 -0700394 unsigned int k, sym, val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
396 shift_state = 0;
397 memset(shift_down, 0, sizeof(shift_down));
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500398
Dmitry Torokhov510cccb2016-06-27 14:12:34 -0700399 for_each_set_bit(k, key_down, min(NR_KEYS, KEY_CNT)) {
400 sym = U(key_maps[0][k]);
401 if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 continue;
403
Dmitry Torokhov510cccb2016-06-27 14:12:34 -0700404 val = KVAL(sym);
405 if (val == KVAL(K_CAPSSHIFT))
406 val = KVAL(K_SHIFT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
Dmitry Torokhov510cccb2016-06-27 14:12:34 -0700408 shift_down[val]++;
409 shift_state |= BIT(val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 }
411}
412
Alan Cox079c9532012-02-28 14:49:23 +0000413/* We still have to export this method to vt.c */
Jiri Slaby63f24a72021-01-05 13:02:28 +0100414void vt_set_leds_compute_shiftstate(void)
Alan Cox079c9532012-02-28 14:49:23 +0000415{
416 unsigned long flags;
Jiri Slaby63f24a72021-01-05 13:02:28 +0100417
lianzhi changfb09d0ac02021-12-15 20:51:25 +0800418 /*
419 * When VT is switched, the keyboard led needs to be set once.
420 * Ensure that after the switch is completed, the state of the
421 * keyboard LED is consistent with the state of the keyboard lock.
422 */
423 vt_switch = true;
Jiri Slaby63f24a72021-01-05 13:02:28 +0100424 set_leds();
425
Alan Cox079c9532012-02-28 14:49:23 +0000426 spin_lock_irqsave(&kbd_event_lock, flags);
427 do_compute_shiftstate();
428 spin_unlock_irqrestore(&kbd_event_lock, flags);
429}
430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431/*
432 * We have a combining character DIACR here, followed by the character CH.
433 * If the combination occurs in the table, return the corresponding value.
434 * Otherwise, if CH is a space or equals DIACR, return DIACR.
435 * Otherwise, conclude that DIACR was not combining after all,
436 * queue it and return CH.
437 */
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500438static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500440 unsigned int d = diacr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 unsigned int i;
442
443 diacr = 0;
444
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500445 if ((d & ~0xff) == BRL_UC_ROW) {
446 if ((ch & ~0xff) == BRL_UC_ROW)
447 return d | ch;
448 } else {
449 for (i = 0; i < accent_table_size; i++)
450 if (accent_table[i].diacr == d && accent_table[i].base == ch)
451 return accent_table[i].result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 }
453
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500454 if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 return d;
456
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500457 if (kbd->kbdmode == VC_UNICODE)
Samuel Thibault04c71972007-10-16 23:27:04 -0700458 to_utf8(vc, d);
459 else {
460 int c = conv_uni_to_8bit(d);
461 if (c != -1)
462 put_queue(vc, c);
463 }
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500464
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 return ch;
466}
467
468/*
469 * Special function handlers
470 */
David Howells7d12e782006-10-05 14:55:46 +0100471static void fn_enter(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
473 if (diacr) {
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500474 if (kbd->kbdmode == VC_UNICODE)
Samuel Thibault04c71972007-10-16 23:27:04 -0700475 to_utf8(vc, diacr);
476 else {
477 int c = conv_uni_to_8bit(diacr);
478 if (c != -1)
479 put_queue(vc, c);
480 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 diacr = 0;
482 }
Dmitry Torokhove0785572010-03-21 22:31:26 -0700483
Andy Shevchenko6d2c52a2020-11-09 12:56:00 +0200484 put_queue(vc, '\r');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 if (vc_kbd_mode(kbd, VC_CRLF))
Andy Shevchenko6d2c52a2020-11-09 12:56:00 +0200486 put_queue(vc, '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487}
488
David Howells7d12e782006-10-05 14:55:46 +0100489static void fn_caps_toggle(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
491 if (rep)
492 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700493
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 chg_vc_kbd_led(kbd, VC_CAPSLOCK);
495}
496
David Howells7d12e782006-10-05 14:55:46 +0100497static void fn_caps_on(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498{
499 if (rep)
500 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 set_vc_kbd_led(kbd, VC_CAPSLOCK);
503}
504
David Howells7d12e782006-10-05 14:55:46 +0100505static void fn_show_ptregs(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506{
David Howells7d12e782006-10-05 14:55:46 +0100507 struct pt_regs *regs = get_irq_regs();
Dmitry Torokhove0785572010-03-21 22:31:26 -0700508
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 if (regs)
510 show_regs(regs);
511}
512
David Howells7d12e782006-10-05 14:55:46 +0100513static void fn_hold(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514{
Alan Cox8ce73262010-06-01 22:52:56 +0200515 struct tty_struct *tty = vc->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
517 if (rep || !tty)
518 return;
519
520 /*
521 * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
522 * these routines are also activated by ^S/^Q.
523 * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
524 */
Jiri Slaby6e94dbc2021-05-05 11:19:05 +0200525 if (tty->flow.stopped)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 start_tty(tty);
527 else
528 stop_tty(tty);
529}
530
David Howells7d12e782006-10-05 14:55:46 +0100531static void fn_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532{
Dmitry Torokhove0785572010-03-21 22:31:26 -0700533 if (vc_kbd_mode(kbd, VC_APPLIC))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 applkey(vc, 'P', 1);
535 else
David Howells7d12e782006-10-05 14:55:46 +0100536 fn_bare_num(vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537}
538
539/*
540 * Bind this to Shift-NumLock if you work in application keypad mode
541 * but want to be able to change the NumLock flag.
542 * Bind this to NumLock if you prefer that the NumLock key always
543 * changes the NumLock flag.
544 */
David Howells7d12e782006-10-05 14:55:46 +0100545static void fn_bare_num(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546{
547 if (!rep)
548 chg_vc_kbd_led(kbd, VC_NUMLOCK);
549}
550
David Howells7d12e782006-10-05 14:55:46 +0100551static void fn_lastcons(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552{
553 /* switch to the last used console, ChN */
554 set_console(last_console);
555}
556
David Howells7d12e782006-10-05 14:55:46 +0100557static void fn_dec_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558{
559 int i, cur = fg_console;
560
561 /* Currently switching? Queue this next switch relative to that. */
562 if (want_console != -1)
563 cur = want_console;
564
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500565 for (i = cur - 1; i != cur; i--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 if (i == -1)
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500567 i = MAX_NR_CONSOLES - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 if (vc_cons_allocated(i))
569 break;
570 }
571 set_console(i);
572}
573
David Howells7d12e782006-10-05 14:55:46 +0100574static void fn_inc_console(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575{
576 int i, cur = fg_console;
577
578 /* Currently switching? Queue this next switch relative to that. */
579 if (want_console != -1)
580 cur = want_console;
581
582 for (i = cur+1; i != cur; i++) {
583 if (i == MAX_NR_CONSOLES)
584 i = 0;
585 if (vc_cons_allocated(i))
586 break;
587 }
588 set_console(i);
589}
590
David Howells7d12e782006-10-05 14:55:46 +0100591static void fn_send_intr(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592{
Jiri Slaby92a19f92013-01-03 15:53:03 +0100593 tty_insert_flip_char(&vc->port, 0, TTY_BREAK);
Jiri Slaby5f6a8512021-11-22 12:16:46 +0100594 tty_flip_buffer_push(&vc->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595}
596
David Howells7d12e782006-10-05 14:55:46 +0100597static void fn_scroll_forw(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598{
599 scrollfront(vc, 0);
600}
601
David Howells7d12e782006-10-05 14:55:46 +0100602static void fn_scroll_back(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
Jiri Slaby1b0ec882016-06-23 13:34:23 +0200604 scrollback(vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605}
606
David Howells7d12e782006-10-05 14:55:46 +0100607static void fn_show_mem(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608{
Michal Hocko9af744d2017-02-22 15:46:16 -0800609 show_mem(0, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610}
611
David Howells7d12e782006-10-05 14:55:46 +0100612static void fn_show_state(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613{
614 show_state();
615}
616
David Howells7d12e782006-10-05 14:55:46 +0100617static void fn_boot_it(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618{
619 ctrl_alt_del();
620}
621
David Howells7d12e782006-10-05 14:55:46 +0100622static void fn_compose(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
Dmitry Torokhove0785572010-03-21 22:31:26 -0700624 dead_key_next = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625}
626
David Howells7d12e782006-10-05 14:55:46 +0100627static void fn_spawn_con(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
Eric W. Biederman81af8d62006-10-02 02:17:13 -0700629 spin_lock(&vt_spawn_con.lock);
630 if (vt_spawn_con.pid)
631 if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
632 put_pid(vt_spawn_con.pid);
633 vt_spawn_con.pid = NULL;
634 }
635 spin_unlock(&vt_spawn_con.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636}
637
David Howells7d12e782006-10-05 14:55:46 +0100638static void fn_SAK(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639{
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800640 struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
Eric W. Biederman8b6312f2007-02-10 01:44:34 -0800641 schedule_work(SAK_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642}
643
David Howells7d12e782006-10-05 14:55:46 +0100644static void fn_null(struct vc_data *vc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
Alan Cox079c9532012-02-28 14:49:23 +0000646 do_compute_shiftstate();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647}
648
649/*
650 * Special key handlers
651 */
David Howells7d12e782006-10-05 14:55:46 +0100652static void k_ignore(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653{
654}
655
David Howells7d12e782006-10-05 14:55:46 +0100656static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657{
658 if (up_flag)
659 return;
660 if (value >= ARRAY_SIZE(fn_handler))
661 return;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -0500662 if ((kbd->kbdmode == VC_RAW ||
Arthur Taylor9fc3de92011-02-04 13:55:50 -0800663 kbd->kbdmode == VC_MEDIUMRAW ||
664 kbd->kbdmode == VC_OFF) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 value != KVAL(K_SAK))
666 return; /* SAK is allowed even in raw mode */
David Howells7d12e782006-10-05 14:55:46 +0100667 fn_handler[value](vc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668}
669
David Howells7d12e782006-10-05 14:55:46 +0100670static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671{
Dmitry Torokhov9272e9a2010-03-21 22:31:26 -0700672 pr_err("k_lowercase was called - impossible\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673}
674
David Howells7d12e782006-10-05 14:55:46 +0100675static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676{
677 if (up_flag)
678 return; /* no action, if this is a key release */
679
680 if (diacr)
681 value = handle_diacr(vc, value);
682
683 if (dead_key_next) {
Dmitry Torokhove0785572010-03-21 22:31:26 -0700684 dead_key_next = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 diacr = value;
686 return;
687 }
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500688 if (kbd->kbdmode == VC_UNICODE)
Samuel Thibault04c71972007-10-16 23:27:04 -0700689 to_utf8(vc, value);
690 else {
691 int c = conv_uni_to_8bit(value);
692 if (c != -1)
693 put_queue(vc, c);
694 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695}
696
697/*
698 * Handle dead key. Note that we now may have several
699 * dead keys modifying the same character. Very useful
700 * for Vietnamese.
701 */
David Howells7d12e782006-10-05 14:55:46 +0100702static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
704 if (up_flag)
705 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700706
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 diacr = (diacr ? handle_diacr(vc, value) : value);
708}
709
David Howells7d12e782006-10-05 14:55:46 +0100710static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500711{
Jiri Bohacd2187eb2008-06-12 15:21:51 -0700712 k_unicode(vc, conv_8bit_to_uni(value), up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500713}
714
David Howells7d12e782006-10-05 14:55:46 +0100715static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500716{
David Howells7d12e782006-10-05 14:55:46 +0100717 k_deadunicode(vc, value, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500718}
719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720/*
721 * Obsolete - for backwards compatibility only
722 */
David Howells7d12e782006-10-05 14:55:46 +0100723static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724{
Samuel Thibault16777ec2018-06-03 20:18:58 +0200725 static const unsigned char ret_diacr[NR_DEAD] = {
726 '`', /* dead_grave */
727 '\'', /* dead_acute */
728 '^', /* dead_circumflex */
729 '~', /* dead_tilda */
730 '"', /* dead_diaeresis */
731 ',', /* dead_cedilla */
732 '_', /* dead_macron */
733 'U', /* dead_breve */
734 '.', /* dead_abovedot */
735 '*', /* dead_abovering */
736 '=', /* dead_doubleacute */
737 'c', /* dead_caron */
738 'k', /* dead_ogonek */
739 'i', /* dead_iota */
740 '#', /* dead_voiced_sound */
741 'o', /* dead_semivoiced_sound */
742 '!', /* dead_belowdot */
743 '?', /* dead_hook */
744 '+', /* dead_horn */
745 '-', /* dead_stroke */
746 ')', /* dead_abovecomma */
747 '(', /* dead_abovereversedcomma */
748 ':', /* dead_doublegrave */
749 'n', /* dead_invertedbreve */
750 ';', /* dead_belowcomma */
751 '$', /* dead_currency */
752 '@', /* dead_greek */
753 };
Dmitry Torokhove0785572010-03-21 22:31:26 -0700754
755 k_deadunicode(vc, ret_diacr[value], up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756}
757
David Howells7d12e782006-10-05 14:55:46 +0100758static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759{
760 if (up_flag)
761 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700762
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 set_console(value);
764}
765
David Howells7d12e782006-10-05 14:55:46 +0100766static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 if (up_flag)
769 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700770
771 if ((unsigned)value < ARRAY_SIZE(func_table)) {
Jiri Slaby82e61c32020-10-19 10:55:17 +0200772 unsigned long flags;
773
774 spin_lock_irqsave(&func_buf_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 if (func_table[value])
776 puts_queue(vc, func_table[value]);
Jiri Slaby82e61c32020-10-19 10:55:17 +0200777 spin_unlock_irqrestore(&func_buf_lock, flags);
778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 } else
Dmitry Torokhov9272e9a2010-03-21 22:31:26 -0700780 pr_err("k_fn called with value=%d\n", value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781}
782
David Howells7d12e782006-10-05 14:55:46 +0100783static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784{
Brandon Philipse52b29c2006-11-04 22:09:08 -0500785 static const char cur_chars[] = "BDCA";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
787 if (up_flag)
788 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700789
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
791}
792
David Howells7d12e782006-10-05 14:55:46 +0100793static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794{
Andreas Mohr0f5e5602006-06-05 00:18:00 -0400795 static const char pad_chars[] = "0123456789+-*/\015,.?()#";
796 static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
798 if (up_flag)
799 return; /* no action, if this is a key release */
800
801 /* kludge... shift forces cursor/number keys */
802 if (vc_kbd_mode(kbd, VC_APPLIC) && !shift_down[KG_SHIFT]) {
803 applkey(vc, app_map[value], 1);
804 return;
805 }
806
Dmitry Torokhove0785572010-03-21 22:31:26 -0700807 if (!vc_kbd_led(kbd, VC_NUMLOCK)) {
808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 switch (value) {
Dmitry Torokhove0785572010-03-21 22:31:26 -0700810 case KVAL(K_PCOMMA):
811 case KVAL(K_PDOT):
812 k_fn(vc, KVAL(K_REMOVE), 0);
813 return;
814 case KVAL(K_P0):
815 k_fn(vc, KVAL(K_INSERT), 0);
816 return;
817 case KVAL(K_P1):
818 k_fn(vc, KVAL(K_SELECT), 0);
819 return;
820 case KVAL(K_P2):
821 k_cur(vc, KVAL(K_DOWN), 0);
822 return;
823 case KVAL(K_P3):
824 k_fn(vc, KVAL(K_PGDN), 0);
825 return;
826 case KVAL(K_P4):
827 k_cur(vc, KVAL(K_LEFT), 0);
828 return;
829 case KVAL(K_P6):
830 k_cur(vc, KVAL(K_RIGHT), 0);
831 return;
832 case KVAL(K_P7):
833 k_fn(vc, KVAL(K_FIND), 0);
834 return;
835 case KVAL(K_P8):
836 k_cur(vc, KVAL(K_UP), 0);
837 return;
838 case KVAL(K_P9):
839 k_fn(vc, KVAL(K_PGUP), 0);
840 return;
841 case KVAL(K_P5):
842 applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
843 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 }
Dmitry Torokhove0785572010-03-21 22:31:26 -0700845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
847 put_queue(vc, pad_chars[value]);
848 if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
Andy Shevchenko6d2c52a2020-11-09 12:56:00 +0200849 put_queue(vc, '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850}
851
David Howells7d12e782006-10-05 14:55:46 +0100852static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
854 int old_state = shift_state;
855
856 if (rep)
857 return;
858 /*
859 * Mimic typewriter:
860 * a CapsShift key acts like Shift but undoes CapsLock
861 */
862 if (value == KVAL(K_CAPSSHIFT)) {
863 value = KVAL(K_SHIFT);
864 if (!up_flag)
865 clr_vc_kbd_led(kbd, VC_CAPSLOCK);
866 }
867
868 if (up_flag) {
869 /*
870 * handle the case that two shift or control
871 * keys are depressed simultaneously
872 */
873 if (shift_down[value])
874 shift_down[value]--;
875 } else
876 shift_down[value]++;
877
878 if (shift_down[value])
Andy Shevchenkoc050a972020-11-09 12:55:59 +0200879 shift_state |= BIT(value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 else
Andy Shevchenkoc050a972020-11-09 12:55:59 +0200881 shift_state &= ~BIT(value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
883 /* kludge */
Dmitry Torokhovb86dab02020-05-25 16:27:40 -0700884 if (up_flag && shift_state != old_state && npadch_active) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 if (kbd->kbdmode == VC_UNICODE)
Dmitry Torokhovb86dab02020-05-25 16:27:40 -0700886 to_utf8(vc, npadch_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 else
Dmitry Torokhovb86dab02020-05-25 16:27:40 -0700888 put_queue(vc, npadch_value & 0xff);
889 npadch_active = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 }
891}
892
David Howells7d12e782006-10-05 14:55:46 +0100893static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894{
895 if (up_flag)
896 return;
897
898 if (vc_kbd_mode(kbd, VC_META)) {
899 put_queue(vc, '\033');
900 put_queue(vc, value);
901 } else
Andy Shevchenkoc050a972020-11-09 12:55:59 +0200902 put_queue(vc, value | BIT(7));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903}
904
David Howells7d12e782006-10-05 14:55:46 +0100905static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906{
Dmitry Torokhovb86dab02020-05-25 16:27:40 -0700907 unsigned int base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908
909 if (up_flag)
910 return;
911
912 if (value < 10) {
913 /* decimal input of code, while Alt depressed */
914 base = 10;
915 } else {
916 /* hexadecimal input of code, while AltGr depressed */
917 value -= 10;
918 base = 16;
919 }
920
Dmitry Torokhovb86dab02020-05-25 16:27:40 -0700921 if (!npadch_active) {
922 npadch_value = 0;
923 npadch_active = true;
924 }
925
926 npadch_value = npadch_value * base + value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927}
928
David Howells7d12e782006-10-05 14:55:46 +0100929static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930{
931 if (up_flag || rep)
932 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700933
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 chg_vc_kbd_lock(kbd, value);
935}
936
David Howells7d12e782006-10-05 14:55:46 +0100937static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938{
David Howells7d12e782006-10-05 14:55:46 +0100939 k_shift(vc, value, up_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 if (up_flag || rep)
941 return;
Dmitry Torokhove0785572010-03-21 22:31:26 -0700942
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 chg_vc_kbd_slock(kbd, value);
944 /* try to make Alt, oops, AltGr and such work */
945 if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
946 kbd->slockstate = 0;
947 chg_vc_kbd_slock(kbd, value);
948 }
949}
950
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500951/* by default, 300ms interval for combination release */
Samuel Thibault77426d72006-04-26 00:14:10 -0400952static unsigned brl_timeout = 300;
953MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
954module_param(brl_timeout, uint, 0644);
955
956static unsigned brl_nbchords = 1;
957MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
958module_param(brl_nbchords, uint, 0644);
959
David Howells7d12e782006-10-05 14:55:46 +0100960static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag)
Samuel Thibault77426d72006-04-26 00:14:10 -0400961{
962 static unsigned long chords;
963 static unsigned committed;
964
965 if (!brl_nbchords)
David Howells7d12e782006-10-05 14:55:46 +0100966 k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400967 else {
968 committed |= pattern;
969 chords++;
970 if (chords == brl_nbchords) {
David Howells7d12e782006-10-05 14:55:46 +0100971 k_unicode(vc, BRL_UC_ROW | committed, up_flag);
Samuel Thibault77426d72006-04-26 00:14:10 -0400972 chords = 0;
973 committed = 0;
974 }
975 }
976}
977
David Howells7d12e782006-10-05 14:55:46 +0100978static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500979{
Dmitry Torokhove0785572010-03-21 22:31:26 -0700980 static unsigned pressed, committing;
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500981 static unsigned long releasestart;
982
983 if (kbd->kbdmode != VC_UNICODE) {
984 if (!up_flag)
Joe Perchese620e542014-11-09 22:46:35 -0800985 pr_warn("keyboard mode must be unicode for braille patterns\n");
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500986 return;
987 }
988
989 if (!value) {
David Howells7d12e782006-10-05 14:55:46 +0100990 k_unicode(vc, BRL_UC_ROW, up_flag);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500991 return;
992 }
993
994 if (value > 8)
995 return;
996
Dmitry Torokhove0785572010-03-21 22:31:26 -0700997 if (!up_flag) {
Andy Shevchenkoc050a972020-11-09 12:55:59 +0200998 pressed |= BIT(value - 1);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -0500999 if (!brl_timeout)
1000 committing = pressed;
Dmitry Torokhove0785572010-03-21 22:31:26 -07001001 } else if (brl_timeout) {
1002 if (!committing ||
1003 time_after(jiffies,
1004 releasestart + msecs_to_jiffies(brl_timeout))) {
1005 committing = pressed;
1006 releasestart = jiffies;
1007 }
Andy Shevchenkoc050a972020-11-09 12:55:59 +02001008 pressed &= ~BIT(value - 1);
Dmitry Torokhove0785572010-03-21 22:31:26 -07001009 if (!pressed && committing) {
1010 k_brlcommit(vc, committing, 0);
1011 committing = 0;
1012 }
1013 } else {
1014 if (committing) {
1015 k_brlcommit(vc, committing, 0);
1016 committing = 0;
1017 }
Andy Shevchenkoc050a972020-11-09 12:55:59 +02001018 pressed &= ~BIT(value - 1);
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -05001019 }
1020}
1021
Samuel Thibault52355522015-03-16 21:19:44 -07001022#if IS_ENABLED(CONFIG_INPUT_LEDS) && IS_ENABLED(CONFIG_LEDS_TRIGGERS)
1023
1024struct kbd_led_trigger {
1025 struct led_trigger trigger;
1026 unsigned int mask;
1027};
1028
Uwe Kleine-König2282e1252018-07-02 22:05:21 +02001029static int kbd_led_trigger_activate(struct led_classdev *cdev)
Samuel Thibault52355522015-03-16 21:19:44 -07001030{
1031 struct kbd_led_trigger *trigger =
1032 container_of(cdev->trigger, struct kbd_led_trigger, trigger);
1033
1034 tasklet_disable(&keyboard_tasklet);
Samuel Thibaulteeb64c12015-06-06 11:44:39 -07001035 if (ledstate != -1U)
Samuel Thibault52355522015-03-16 21:19:44 -07001036 led_trigger_event(&trigger->trigger,
1037 ledstate & trigger->mask ?
1038 LED_FULL : LED_OFF);
1039 tasklet_enable(&keyboard_tasklet);
Uwe Kleine-König2282e1252018-07-02 22:05:21 +02001040
1041 return 0;
Samuel Thibault52355522015-03-16 21:19:44 -07001042}
1043
1044#define KBD_LED_TRIGGER(_led_bit, _name) { \
1045 .trigger = { \
1046 .name = _name, \
1047 .activate = kbd_led_trigger_activate, \
1048 }, \
1049 .mask = BIT(_led_bit), \
1050 }
1051
Samuel Thibaulteeb64c12015-06-06 11:44:39 -07001052#define KBD_LOCKSTATE_TRIGGER(_led_bit, _name) \
1053 KBD_LED_TRIGGER((_led_bit) + 8, _name)
1054
Samuel Thibault52355522015-03-16 21:19:44 -07001055static struct kbd_led_trigger kbd_led_triggers[] = {
Maciej S. Szmigiero31b59292016-11-16 00:55:57 +01001056 KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrolllock"),
Samuel Thibault52355522015-03-16 21:19:44 -07001057 KBD_LED_TRIGGER(VC_NUMLOCK, "kbd-numlock"),
1058 KBD_LED_TRIGGER(VC_CAPSLOCK, "kbd-capslock"),
1059 KBD_LED_TRIGGER(VC_KANALOCK, "kbd-kanalock"),
Samuel Thibaulteeb64c12015-06-06 11:44:39 -07001060
1061 KBD_LOCKSTATE_TRIGGER(VC_SHIFTLOCK, "kbd-shiftlock"),
1062 KBD_LOCKSTATE_TRIGGER(VC_ALTGRLOCK, "kbd-altgrlock"),
1063 KBD_LOCKSTATE_TRIGGER(VC_CTRLLOCK, "kbd-ctrllock"),
1064 KBD_LOCKSTATE_TRIGGER(VC_ALTLOCK, "kbd-altlock"),
1065 KBD_LOCKSTATE_TRIGGER(VC_SHIFTLLOCK, "kbd-shiftllock"),
1066 KBD_LOCKSTATE_TRIGGER(VC_SHIFTRLOCK, "kbd-shiftrlock"),
1067 KBD_LOCKSTATE_TRIGGER(VC_CTRLLLOCK, "kbd-ctrlllock"),
1068 KBD_LOCKSTATE_TRIGGER(VC_CTRLRLOCK, "kbd-ctrlrlock"),
Samuel Thibault52355522015-03-16 21:19:44 -07001069};
1070
1071static void kbd_propagate_led_state(unsigned int old_state,
1072 unsigned int new_state)
1073{
1074 struct kbd_led_trigger *trigger;
1075 unsigned int changed = old_state ^ new_state;
1076 int i;
1077
1078 for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) {
1079 trigger = &kbd_led_triggers[i];
1080
1081 if (changed & trigger->mask)
1082 led_trigger_event(&trigger->trigger,
1083 new_state & trigger->mask ?
1084 LED_FULL : LED_OFF);
1085 }
1086}
1087
1088static int kbd_update_leds_helper(struct input_handle *handle, void *data)
1089{
1090 unsigned int led_state = *(unsigned int *)data;
1091
1092 if (test_bit(EV_LED, handle->dev->evbit))
1093 kbd_propagate_led_state(~led_state, led_state);
1094
1095 return 0;
1096}
1097
1098static void kbd_init_leds(void)
1099{
1100 int error;
1101 int i;
1102
1103 for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) {
1104 error = led_trigger_register(&kbd_led_triggers[i].trigger);
1105 if (error)
1106 pr_err("error %d while registering trigger %s\n",
1107 error, kbd_led_triggers[i].trigger.name);
1108 }
1109}
1110
1111#else
1112
1113static int kbd_update_leds_helper(struct input_handle *handle, void *data)
1114{
1115 unsigned int leds = *(unsigned int *)data;
1116
1117 if (test_bit(EV_LED, handle->dev->evbit)) {
Andy Shevchenkoc050a972020-11-09 12:55:59 +02001118 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & BIT(0)));
1119 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & BIT(1)));
1120 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & BIT(2)));
Samuel Thibault52355522015-03-16 21:19:44 -07001121 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
1122 }
1123
1124 return 0;
1125}
1126
1127static void kbd_propagate_led_state(unsigned int old_state,
1128 unsigned int new_state)
1129{
1130 input_handler_for_each_handle(&kbd_handler, &new_state,
1131 kbd_update_leds_helper);
1132}
1133
1134static void kbd_init_leds(void)
1135{
1136}
1137
1138#endif
1139
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140/*
1141 * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
1142 * or (ii) whatever pattern of lights people want to show using KDSETLED,
1143 * or (iii) specified bits of specified words in kernel memory.
1144 */
Alan Cox3db1ddb2012-07-17 17:06:41 +01001145static unsigned char getledstate(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146{
Samuel Thibaulteeb64c12015-06-06 11:44:39 -07001147 return ledstate & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148}
1149
Mark Rustad9d329c12014-09-05 18:57:57 -07001150void setledstate(struct kbd_struct *kb, unsigned int led)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151{
Alan Cox079c9532012-02-28 14:49:23 +00001152 unsigned long flags;
Alan Cox3db1ddb2012-07-17 17:06:41 +01001153 spin_lock_irqsave(&led_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 if (!(led & ~7)) {
1155 ledioctl = led;
Mark Rustad9d329c12014-09-05 18:57:57 -07001156 kb->ledmode = LED_SHOW_IOCTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 } else
Mark Rustad9d329c12014-09-05 18:57:57 -07001158 kb->ledmode = LED_SHOW_FLAGS;
Dmitry Torokhove0785572010-03-21 22:31:26 -07001159
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 set_leds();
Alan Cox3db1ddb2012-07-17 17:06:41 +01001161 spin_unlock_irqrestore(&led_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162}
1163
1164static inline unsigned char getleds(void)
1165{
Mark Rustad9d329c12014-09-05 18:57:57 -07001166 struct kbd_struct *kb = kbd_table + fg_console;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167
Mark Rustad9d329c12014-09-05 18:57:57 -07001168 if (kb->ledmode == LED_SHOW_IOCTL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 return ledioctl;
1170
Mark Rustad9d329c12014-09-05 18:57:57 -07001171 return kb->ledflagstate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172}
1173
Alan Cox079c9532012-02-28 14:49:23 +00001174/**
1175 * vt_get_leds - helper for braille console
1176 * @console: console to read
1177 * @flag: flag we want to check
1178 *
1179 * Check the status of a keyboard led flag and report it back
1180 */
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02001181int vt_get_leds(unsigned int console, int flag)
Alan Cox079c9532012-02-28 14:49:23 +00001182{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02001183 struct kbd_struct *kb = &kbd_table[console];
Alan Cox079c9532012-02-28 14:49:23 +00001184 int ret;
Alan Cox3db1ddb2012-07-17 17:06:41 +01001185 unsigned long flags;
Alan Cox079c9532012-02-28 14:49:23 +00001186
Alan Cox3db1ddb2012-07-17 17:06:41 +01001187 spin_lock_irqsave(&led_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07001188 ret = vc_kbd_led(kb, flag);
Alan Cox3db1ddb2012-07-17 17:06:41 +01001189 spin_unlock_irqrestore(&led_lock, flags);
Alan Cox079c9532012-02-28 14:49:23 +00001190
1191 return ret;
1192}
1193EXPORT_SYMBOL_GPL(vt_get_leds);
1194
1195/**
1196 * vt_set_led_state - set LED state of a console
1197 * @console: console to set
1198 * @leds: LED bits
1199 *
1200 * Set the LEDs on a console. This is a wrapper for the VT layer
1201 * so that we can keep kbd knowledge internal
1202 */
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02001203void vt_set_led_state(unsigned int console, int leds)
Alan Cox079c9532012-02-28 14:49:23 +00001204{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02001205 struct kbd_struct *kb = &kbd_table[console];
Mark Rustad9d329c12014-09-05 18:57:57 -07001206 setledstate(kb, leds);
Alan Cox079c9532012-02-28 14:49:23 +00001207}
1208
1209/**
1210 * vt_kbd_con_start - Keyboard side of console start
1211 * @console: console
1212 *
1213 * Handle console start. This is a wrapper for the VT layer
1214 * so that we can keep kbd knowledge internal
Alan Cox84f904e2012-05-01 16:12:19 +01001215 *
1216 * FIXME: We eventually need to hold the kbd lock here to protect
1217 * the LED updating. We can't do it yet because fn_hold calls stop_tty
1218 * and start_tty under the kbd_event_lock, while normal tty paths
1219 * don't hold the lock. We probably need to split out an LED lock
1220 * but not during an -rc release!
Alan Cox079c9532012-02-28 14:49:23 +00001221 */
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02001222void vt_kbd_con_start(unsigned int console)
Alan Cox079c9532012-02-28 14:49:23 +00001223{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02001224 struct kbd_struct *kb = &kbd_table[console];
Alan Cox3db1ddb2012-07-17 17:06:41 +01001225 unsigned long flags;
1226 spin_lock_irqsave(&led_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07001227 clr_vc_kbd_led(kb, VC_SCROLLOCK);
Alan Cox079c9532012-02-28 14:49:23 +00001228 set_leds();
Alan Cox3db1ddb2012-07-17 17:06:41 +01001229 spin_unlock_irqrestore(&led_lock, flags);
Alan Cox079c9532012-02-28 14:49:23 +00001230}
1231
1232/**
1233 * vt_kbd_con_stop - Keyboard side of console stop
1234 * @console: console
1235 *
1236 * Handle console stop. This is a wrapper for the VT layer
1237 * so that we can keep kbd knowledge internal
1238 */
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02001239void vt_kbd_con_stop(unsigned int console)
Alan Cox079c9532012-02-28 14:49:23 +00001240{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02001241 struct kbd_struct *kb = &kbd_table[console];
Alan Cox3db1ddb2012-07-17 17:06:41 +01001242 unsigned long flags;
1243 spin_lock_irqsave(&led_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07001244 set_vc_kbd_led(kb, VC_SCROLLOCK);
Alan Cox079c9532012-02-28 14:49:23 +00001245 set_leds();
Alan Cox3db1ddb2012-07-17 17:06:41 +01001246 spin_unlock_irqrestore(&led_lock, flags);
Alan Cox079c9532012-02-28 14:49:23 +00001247}
1248
Dmitry Torokhov66d2a592009-12-01 21:54:35 -08001249/*
Samuel Thibault52355522015-03-16 21:19:44 -07001250 * This is the tasklet that updates LED state of LEDs using standard
1251 * keyboard triggers. The reason we use tasklet is that we need to
1252 * handle the scenario when keyboard handler is not registered yet
1253 * but we already getting updates from the VT to update led state.
Dmitry Torokhov66d2a592009-12-01 21:54:35 -08001254 */
Emil Renner Berthing91598352021-01-27 17:42:22 +01001255static void kbd_bh(struct tasklet_struct *unused)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256{
Samuel Thibaulteeb64c12015-06-06 11:44:39 -07001257 unsigned int leds;
Alan Cox3db1ddb2012-07-17 17:06:41 +01001258 unsigned long flags;
Samuel Thibault52355522015-03-16 21:19:44 -07001259
Alan Cox3db1ddb2012-07-17 17:06:41 +01001260 spin_lock_irqsave(&led_lock, flags);
1261 leds = getleds();
Samuel Thibaulteeb64c12015-06-06 11:44:39 -07001262 leds |= (unsigned int)kbd->lockstate << 8;
Alan Cox3db1ddb2012-07-17 17:06:41 +01001263 spin_unlock_irqrestore(&led_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
lianzhi changfb09d0ac02021-12-15 20:51:25 +08001265 if (vt_switch) {
1266 ledstate = ~leds;
1267 vt_switch = false;
1268 }
1269
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 if (leds != ledstate) {
Samuel Thibault52355522015-03-16 21:19:44 -07001271 kbd_propagate_led_state(ledstate, leds);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -08001272 ledstate = leds;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274}
1275
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001277 defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
1278 defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
Andy Shevchenko7b6d5392017-05-09 20:07:13 +03001279 (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
Jiri Slaby6dee84d2020-10-29 12:32:20 +01001281static inline bool kbd_is_hw_raw(const struct input_dev *dev)
1282{
1283 if (!test_bit(EV_MSC, dev->evbit) || !test_bit(MSC_RAW, dev->mscbit))
1284 return false;
1285
1286 return dev->id.bustype == BUS_I8042 &&
1287 dev->id.vendor == 0x0001 && dev->id.product == 0x0001;
1288}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
Andreas Mohr0f5e5602006-06-05 00:18:00 -04001290static const unsigned short x86_keycodes[256] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1292 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1293 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
1294 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
1295 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
1296 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
Dmitry Torokhov896cdc7b2006-07-19 01:14:25 -04001297 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
1299 360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
Hans de Goede72a42f22007-07-03 01:55:18 -04001300 103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
1301 291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
1303 377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
1304 308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
1305 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
1306
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001307#ifdef CONFIG_SPARC
Dmitry Torokhove0785572010-03-21 22:31:26 -07001308static int sparc_l1_a_state;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309extern void sun_do_break(void);
1310#endif
1311
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001312static int emulate_raw(struct vc_data *vc, unsigned int keycode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 unsigned char up_flag)
1314{
Dmitry Torokhov896cdc7b2006-07-19 01:14:25 -04001315 int code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316
1317 switch (keycode) {
Dmitry Torokhov896cdc7b2006-07-19 01:14:25 -04001318
Dmitry Torokhove0785572010-03-21 22:31:26 -07001319 case KEY_PAUSE:
1320 put_queue(vc, 0xe1);
1321 put_queue(vc, 0x1d | up_flag);
1322 put_queue(vc, 0x45 | up_flag);
1323 break;
Dmitry Torokhov896cdc7b2006-07-19 01:14:25 -04001324
Dmitry Torokhove0785572010-03-21 22:31:26 -07001325 case KEY_HANGEUL:
1326 if (!up_flag)
1327 put_queue(vc, 0xf2);
1328 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
Dmitry Torokhove0785572010-03-21 22:31:26 -07001330 case KEY_HANJA:
1331 if (!up_flag)
1332 put_queue(vc, 0xf1);
1333 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Dmitry Torokhove0785572010-03-21 22:31:26 -07001335 case KEY_SYSRQ:
1336 /*
1337 * Real AT keyboards (that's what we're trying
Askar Safin26ba68d2016-11-07 16:43:14 +03001338 * to emulate here) emit 0xe0 0x2a 0xe0 0x37 when
Dmitry Torokhove0785572010-03-21 22:31:26 -07001339 * pressing PrtSc/SysRq alone, but simply 0x54
1340 * when pressing Alt+PrtSc/SysRq.
1341 */
1342 if (test_bit(KEY_LEFTALT, key_down) ||
1343 test_bit(KEY_RIGHTALT, key_down)) {
1344 put_queue(vc, 0x54 | up_flag);
1345 } else {
1346 put_queue(vc, 0xe0);
1347 put_queue(vc, 0x2a | up_flag);
1348 put_queue(vc, 0xe0);
1349 put_queue(vc, 0x37 | up_flag);
1350 }
1351 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Dmitry Torokhove0785572010-03-21 22:31:26 -07001353 default:
1354 if (keycode > 255)
1355 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Dmitry Torokhove0785572010-03-21 22:31:26 -07001357 code = x86_keycodes[keycode];
1358 if (!code)
1359 return -1;
Dmitry Torokhov896cdc7b2006-07-19 01:14:25 -04001360
Dmitry Torokhove0785572010-03-21 22:31:26 -07001361 if (code & 0x100)
1362 put_queue(vc, 0xe0);
1363 put_queue(vc, (code & 0x7f) | up_flag);
1364
1365 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 }
1367
1368 return 0;
1369}
1370
1371#else
1372
Jiri Slaby6dee84d2020-10-29 12:32:20 +01001373static inline bool kbd_is_hw_raw(const struct input_dev *dev)
1374{
1375 return false;
1376}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
1379{
1380 if (keycode > 127)
1381 return -1;
1382
1383 put_queue(vc, keycode | up_flag);
1384 return 0;
1385}
1386#endif
1387
1388static void kbd_rawcode(unsigned char data)
1389{
1390 struct vc_data *vc = vc_cons[fg_console].d;
Dmitry Torokhove0785572010-03-21 22:31:26 -07001391
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02001392 kbd = &kbd_table[vc->vc_num];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 if (kbd->kbdmode == VC_RAW)
1394 put_queue(vc, data);
1395}
1396
Jiri Slaby6dee84d2020-10-29 12:32:20 +01001397static void kbd_keycode(unsigned int keycode, int down, bool hw_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398{
1399 struct vc_data *vc = vc_cons[fg_console].d;
1400 unsigned short keysym, *key_map;
Dmitry Torokhove0785572010-03-21 22:31:26 -07001401 unsigned char type;
1402 bool raw_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 struct tty_struct *tty;
1404 int shift_final;
Samuel Thibault41ab4392007-10-18 23:39:12 -07001405 struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
Dmitry Torokhove0785572010-03-21 22:31:26 -07001406 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
Alan Cox8ce73262010-06-01 22:52:56 +02001408 tty = vc->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409
1410 if (tty && (!tty->driver_data)) {
1411 /* No driver data? Strange. Okay we fix it then. */
1412 tty->driver_data = vc;
1413 }
1414
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02001415 kbd = &kbd_table[vc->vc_num];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001417#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 if (keycode == KEY_STOP)
1419 sparc_l1_a_state = down;
1420#endif
1421
1422 rep = (down == 2);
1423
Dmitry Torokhove0785572010-03-21 22:31:26 -07001424 raw_mode = (kbd->kbdmode == VC_RAW);
1425 if (raw_mode && !hw_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 if (emulate_raw(vc, keycode, !down << 7))
Dmitry Torokhov9e35d202007-04-12 01:30:52 -04001427 if (keycode < BTN_MISC && printk_ratelimit())
Joe Perchese620e542014-11-09 22:46:35 -08001428 pr_warn("can't emulate rawmode for keycode %d\n",
1429 keycode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Adrian Bunk0b57ee92005-12-22 21:03:47 -08001431#ifdef CONFIG_SPARC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 if (keycode == KEY_A && sparc_l1_a_state) {
Dmitry Torokhove0785572010-03-21 22:31:26 -07001433 sparc_l1_a_state = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 sun_do_break();
1435 }
1436#endif
1437
1438 if (kbd->kbdmode == VC_MEDIUMRAW) {
1439 /*
1440 * This is extended medium raw mode, with keys above 127
1441 * encoded as 0, high 7 bits, low 7 bits, with the 0 bearing
1442 * the 'up' flag if needed. 0 is reserved, so this shouldn't
1443 * interfere with anything else. The two bytes after 0 will
1444 * always have the up flag set not to interfere with older
1445 * applications. This allows for 16384 different keycodes,
1446 * which should be enough.
1447 */
1448 if (keycode < 128) {
1449 put_queue(vc, keycode | (!down << 7));
1450 } else {
1451 put_queue(vc, !down << 7);
Andy Shevchenkoc050a972020-11-09 12:55:59 +02001452 put_queue(vc, (keycode >> 7) | BIT(7));
1453 put_queue(vc, keycode | BIT(7));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 }
Dmitry Torokhove0785572010-03-21 22:31:26 -07001455 raw_mode = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 }
1457
Andy Shevchenkocb215da2020-11-09 12:56:01 +02001458 assign_bit(keycode, key_down, down);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001460 if (rep &&
1461 (!vc_kbd_mode(kbd, VC_REPEAT) ||
Alan Coxf34d7a52008-04-30 00:54:13 -07001462 (tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 /*
1464 * Don't repeat a key if the input buffers are not empty and the
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001465 * characters get aren't echoed locally. This makes key repeat
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 * usable with slow applications and under heavy loads.
1467 */
1468 return;
1469 }
1470
Samuel Thibault41ab4392007-10-18 23:39:12 -07001471 param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
Karl Dahlke0beb4f62008-04-15 01:30:32 -04001472 param.ledstate = kbd->ledflagstate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 key_map = key_maps[shift_final];
1474
Dmitry Torokhove0785572010-03-21 22:31:26 -07001475 rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1476 KBD_KEYCODE, &param);
1477 if (rc == NOTIFY_STOP || !key_map) {
1478 atomic_notifier_call_chain(&keyboard_notifier_list,
1479 KBD_UNBOUND_KEYCODE, &param);
Alan Cox079c9532012-02-28 14:49:23 +00001480 do_compute_shiftstate();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 kbd->slockstate = 0;
1482 return;
1483 }
1484
Dmitry Torokhove0785572010-03-21 22:31:26 -07001485 if (keycode < NR_KEYS)
Samuel Thibaultb9ec4e12006-04-02 00:10:28 -05001486 keysym = key_map[keycode];
Dmitry Torokhove0785572010-03-21 22:31:26 -07001487 else if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
1488 keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1));
1489 else
1490 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 type = KTYP(keysym);
1493
1494 if (type < 0xf0) {
Samuel Thibault41ab4392007-10-18 23:39:12 -07001495 param.value = keysym;
Dmitry Torokhove0785572010-03-21 22:31:26 -07001496 rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1497 KBD_UNICODE, &param);
1498 if (rc != NOTIFY_STOP)
1499 if (down && !raw_mode)
Reinis Danne89bb1e12019-04-11 14:50:54 +03001500 k_unicode(vc, keysym, !down);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 return;
1502 }
1503
1504 type -= 0xf0;
1505
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 if (type == KT_LETTER) {
1507 type = KT_LATIN;
1508 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
Andy Shevchenkoc050a972020-11-09 12:55:59 +02001509 key_map = key_maps[shift_final ^ BIT(KG_SHIFT)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 if (key_map)
1511 keysym = key_map[keycode];
1512 }
1513 }
Samuel Thibault41ab4392007-10-18 23:39:12 -07001514
Dmitry Torokhove0785572010-03-21 22:31:26 -07001515 param.value = keysym;
1516 rc = atomic_notifier_call_chain(&keyboard_notifier_list,
1517 KBD_KEYSYM, &param);
1518 if (rc == NOTIFY_STOP)
Samuel Thibault41ab4392007-10-18 23:39:12 -07001519 return;
1520
Arthur Taylor9fc3de92011-02-04 13:55:50 -08001521 if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type != KT_SHIFT)
Samuel Thibault41ab4392007-10-18 23:39:12 -07001522 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
David Howells7d12e782006-10-05 14:55:46 +01001524 (*k_handler[type])(vc, keysym & 0xff, !down);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
Karl Dahlke0beb4f62008-04-15 01:30:32 -04001526 param.ledstate = kbd->ledflagstate;
Samuel Thibault41ab4392007-10-18 23:39:12 -07001527 atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
1528
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 if (type != KT_SLOCK)
1530 kbd->slockstate = 0;
1531}
1532
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001533static void kbd_event(struct input_handle *handle, unsigned int event_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 unsigned int event_code, int value)
1535{
Dmitry Torokhov21cea582009-11-29 23:40:58 -08001536 /* We are called with interrupts disabled, just take the lock */
1537 spin_lock(&kbd_event_lock);
1538
Jiri Slaby6dee84d2020-10-29 12:32:20 +01001539 if (event_type == EV_MSC && event_code == MSC_RAW &&
1540 kbd_is_hw_raw(handle->dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 kbd_rawcode(value);
Dmitry Torokhovb2b2dd72019-11-22 12:42:20 -08001542 if (event_type == EV_KEY && event_code <= KEY_MAX)
Jiri Slaby6dee84d2020-10-29 12:32:20 +01001543 kbd_keycode(event_code, value, kbd_is_hw_raw(handle->dev));
Dmitry Torokhov21cea582009-11-29 23:40:58 -08001544
1545 spin_unlock(&kbd_event_lock);
1546
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 tasklet_schedule(&keyboard_tasklet);
1548 do_poke_blanked_console = 1;
1549 schedule_console_callback();
1550}
1551
Dmitry Torokhov0b7024ac2010-02-02 21:08:26 -08001552static bool kbd_match(struct input_handler *handler, struct input_dev *dev)
1553{
Dmitry Torokhov0b7024ac2010-02-02 21:08:26 -08001554 if (test_bit(EV_SND, dev->evbit))
1555 return true;
1556
Samuel Thibault53c1f762010-07-31 02:28:51 -07001557 if (test_bit(EV_KEY, dev->evbit)) {
Jiri Slaby2389cdc2020-10-29 12:32:21 +01001558 if (find_next_bit(dev->keybit, BTN_MISC, KEY_RESERVED) <
1559 BTN_MISC)
1560 return true;
1561 if (find_next_bit(dev->keybit, KEY_BRL_DOT10 + 1,
1562 KEY_BRL_DOT1) <= KEY_BRL_DOT10)
1563 return true;
Samuel Thibault53c1f762010-07-31 02:28:51 -07001564 }
Dmitry Torokhov0b7024ac2010-02-02 21:08:26 -08001565
1566 return false;
1567}
1568
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569/*
1570 * When a keyboard (or other input device) is found, the kbd_connect
1571 * function is called. The function then looks at the device, and if it
1572 * likes it, it can open it and get events from it. In this (kbd_connect)
1573 * function, we should decide which VT to bind that keyboard to initially.
1574 */
Dmitry Torokhov5b2a08262007-04-12 01:29:46 -04001575static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
1576 const struct input_device_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577{
1578 struct input_handle *handle;
Dmitry Torokhov5b2a08262007-04-12 01:29:46 -04001579 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
Dmitry Torokhov22479e12006-08-04 22:51:51 -04001581 handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
1582 if (!handle)
Dmitry Torokhov5b2a08262007-04-12 01:29:46 -04001583 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584
1585 handle->dev = dev;
1586 handle->handler = handler;
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001587 handle->name = "kbd";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588
Dmitry Torokhov5b2a08262007-04-12 01:29:46 -04001589 error = input_register_handle(handle);
1590 if (error)
1591 goto err_free_handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592
Dmitry Torokhov5b2a08262007-04-12 01:29:46 -04001593 error = input_open_device(handle);
1594 if (error)
1595 goto err_unregister_handle;
1596
1597 return 0;
1598
1599 err_unregister_handle:
1600 input_unregister_handle(handle);
1601 err_free_handle:
1602 kfree(handle);
1603 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604}
1605
1606static void kbd_disconnect(struct input_handle *handle)
1607{
1608 input_close_device(handle);
Dmitry Torokhov5b2a08262007-04-12 01:29:46 -04001609 input_unregister_handle(handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 kfree(handle);
1611}
1612
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001613/*
1614 * Start keyboard handler on the new keyboard by refreshing LED state to
1615 * match the rest of the system.
1616 */
1617static void kbd_start(struct input_handle *handle)
1618{
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001619 tasklet_disable(&keyboard_tasklet);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -08001620
Samuel Thibaulteeb64c12015-06-06 11:44:39 -07001621 if (ledstate != -1U)
1622 kbd_update_leds_helper(handle, &ledstate);
Dmitry Torokhov66d2a592009-12-01 21:54:35 -08001623
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001624 tasklet_enable(&keyboard_tasklet);
1625}
1626
Dmitry Torokhov66e66112006-09-14 01:31:59 -04001627static const struct input_device_id kbd_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 {
Alan Cox6aeed472012-02-24 12:47:29 +00001629 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1630 .evbit = { BIT_MASK(EV_KEY) },
1631 },
Dmitry Torokhovfe1e8602005-09-10 12:03:38 -05001632
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 {
Alan Cox6aeed472012-02-24 12:47:29 +00001634 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1635 .evbit = { BIT_MASK(EV_SND) },
1636 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637
1638 { }, /* Terminating entry */
1639};
1640
1641MODULE_DEVICE_TABLE(input, kbd_ids);
1642
1643static struct input_handler kbd_handler = {
1644 .event = kbd_event,
Dmitry Torokhov0b7024ac2010-02-02 21:08:26 -08001645 .match = kbd_match,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 .connect = kbd_connect,
1647 .disconnect = kbd_disconnect,
Dmitry Torokhovc7e8dc62006-07-06 00:21:03 -04001648 .start = kbd_start,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 .name = "kbd",
1650 .id_table = kbd_ids,
1651};
1652
1653int __init kbd_init(void)
1654{
1655 int i;
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001656 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657
Alan Cox6aeed472012-02-24 12:47:29 +00001658 for (i = 0; i < MAX_NR_CONSOLES; i++) {
Joshua Covb2d0b7a2012-04-13 21:08:26 +02001659 kbd_table[i].ledflagstate = kbd_defleds();
1660 kbd_table[i].default_ledflagstate = kbd_defleds();
Dmitry Torokhov2b192902006-07-19 01:13:26 -04001661 kbd_table[i].ledmode = LED_SHOW_FLAGS;
1662 kbd_table[i].lockstate = KBD_DEFLOCK;
1663 kbd_table[i].slockstate = 0;
1664 kbd_table[i].modeflags = KBD_DEFMODE;
Bill Nottingham2e8ecb92007-10-16 23:29:38 -07001665 kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
Dmitry Torokhov2b192902006-07-19 01:13:26 -04001666 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
Samuel Thibault52355522015-03-16 21:19:44 -07001668 kbd_init_leds();
1669
Dmitry Torokhov4263cf02006-09-14 01:32:39 -04001670 error = input_register_handler(&kbd_handler);
1671 if (error)
1672 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
1674 tasklet_enable(&keyboard_tasklet);
1675 tasklet_schedule(&keyboard_tasklet);
1676
1677 return 0;
1678}
Alan Cox247ff8e2012-02-24 12:47:11 +00001679
1680/* Ioctl support code */
1681
1682/**
1683 * vt_do_diacrit - diacritical table updates
1684 * @cmd: ioctl request
Mark Rustad9d329c12014-09-05 18:57:57 -07001685 * @udp: pointer to user data for ioctl
Alan Cox247ff8e2012-02-24 12:47:11 +00001686 * @perm: permissions check computed by caller
1687 *
1688 * Update the diacritical tables atomically and safely. Lock them
1689 * against simultaneous keypresses
1690 */
Mark Rustad9d329c12014-09-05 18:57:57 -07001691int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
Alan Cox247ff8e2012-02-24 12:47:11 +00001692{
Alan Cox247ff8e2012-02-24 12:47:11 +00001693 unsigned long flags;
1694 int asize;
1695 int ret = 0;
1696
1697 switch (cmd) {
1698 case KDGKBDIACR:
1699 {
Mark Rustad9d329c12014-09-05 18:57:57 -07001700 struct kbdiacrs __user *a = udp;
1701 struct kbdiacr *dia;
Alan Cox247ff8e2012-02-24 12:47:11 +00001702 int i;
1703
Kees Cook6da2ec52018-06-12 13:55:00 -07001704 dia = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacr),
Alan Cox247ff8e2012-02-24 12:47:11 +00001705 GFP_KERNEL);
Mark Rustad9d329c12014-09-05 18:57:57 -07001706 if (!dia)
Alan Cox247ff8e2012-02-24 12:47:11 +00001707 return -ENOMEM;
1708
1709 /* Lock the diacriticals table, make a copy and then
1710 copy it after we unlock */
1711 spin_lock_irqsave(&kbd_event_lock, flags);
1712
1713 asize = accent_table_size;
1714 for (i = 0; i < asize; i++) {
Mark Rustad9d329c12014-09-05 18:57:57 -07001715 dia[i].diacr = conv_uni_to_8bit(
Alan Cox247ff8e2012-02-24 12:47:11 +00001716 accent_table[i].diacr);
Mark Rustad9d329c12014-09-05 18:57:57 -07001717 dia[i].base = conv_uni_to_8bit(
Alan Cox247ff8e2012-02-24 12:47:11 +00001718 accent_table[i].base);
Mark Rustad9d329c12014-09-05 18:57:57 -07001719 dia[i].result = conv_uni_to_8bit(
Alan Cox247ff8e2012-02-24 12:47:11 +00001720 accent_table[i].result);
1721 }
1722 spin_unlock_irqrestore(&kbd_event_lock, flags);
1723
1724 if (put_user(asize, &a->kb_cnt))
1725 ret = -EFAULT;
Mark Rustad9d329c12014-09-05 18:57:57 -07001726 else if (copy_to_user(a->kbdiacr, dia,
Alan Cox247ff8e2012-02-24 12:47:11 +00001727 asize * sizeof(struct kbdiacr)))
1728 ret = -EFAULT;
Mark Rustad9d329c12014-09-05 18:57:57 -07001729 kfree(dia);
Alan Cox247ff8e2012-02-24 12:47:11 +00001730 return ret;
1731 }
1732 case KDGKBDIACRUC:
1733 {
Mark Rustad9d329c12014-09-05 18:57:57 -07001734 struct kbdiacrsuc __user *a = udp;
Alan Cox247ff8e2012-02-24 12:47:11 +00001735 void *buf;
1736
Kees Cook6da2ec52018-06-12 13:55:00 -07001737 buf = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacruc),
Alan Cox247ff8e2012-02-24 12:47:11 +00001738 GFP_KERNEL);
1739 if (buf == NULL)
1740 return -ENOMEM;
1741
1742 /* Lock the diacriticals table, make a copy and then
1743 copy it after we unlock */
1744 spin_lock_irqsave(&kbd_event_lock, flags);
1745
1746 asize = accent_table_size;
1747 memcpy(buf, accent_table, asize * sizeof(struct kbdiacruc));
1748
1749 spin_unlock_irqrestore(&kbd_event_lock, flags);
1750
1751 if (put_user(asize, &a->kb_cnt))
1752 ret = -EFAULT;
1753 else if (copy_to_user(a->kbdiacruc, buf,
1754 asize*sizeof(struct kbdiacruc)))
1755 ret = -EFAULT;
1756 kfree(buf);
1757 return ret;
1758 }
1759
1760 case KDSKBDIACR:
1761 {
Mark Rustad9d329c12014-09-05 18:57:57 -07001762 struct kbdiacrs __user *a = udp;
1763 struct kbdiacr *dia = NULL;
Alan Cox247ff8e2012-02-24 12:47:11 +00001764 unsigned int ct;
1765 int i;
1766
1767 if (!perm)
1768 return -EPERM;
1769 if (get_user(ct, &a->kb_cnt))
1770 return -EFAULT;
1771 if (ct >= MAX_DIACR)
1772 return -EINVAL;
1773
1774 if (ct) {
Alan Cox247ff8e2012-02-24 12:47:11 +00001775
Saurabh Sengar1051937d2015-10-28 11:56:44 +05301776 dia = memdup_user(a->kbdiacr,
1777 sizeof(struct kbdiacr) * ct);
1778 if (IS_ERR(dia))
1779 return PTR_ERR(dia);
1780
Alan Cox247ff8e2012-02-24 12:47:11 +00001781 }
1782
1783 spin_lock_irqsave(&kbd_event_lock, flags);
1784 accent_table_size = ct;
1785 for (i = 0; i < ct; i++) {
1786 accent_table[i].diacr =
Mark Rustad9d329c12014-09-05 18:57:57 -07001787 conv_8bit_to_uni(dia[i].diacr);
Alan Cox247ff8e2012-02-24 12:47:11 +00001788 accent_table[i].base =
Mark Rustad9d329c12014-09-05 18:57:57 -07001789 conv_8bit_to_uni(dia[i].base);
Alan Cox247ff8e2012-02-24 12:47:11 +00001790 accent_table[i].result =
Mark Rustad9d329c12014-09-05 18:57:57 -07001791 conv_8bit_to_uni(dia[i].result);
Alan Cox247ff8e2012-02-24 12:47:11 +00001792 }
1793 spin_unlock_irqrestore(&kbd_event_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07001794 kfree(dia);
Alan Cox247ff8e2012-02-24 12:47:11 +00001795 return 0;
1796 }
1797
1798 case KDSKBDIACRUC:
1799 {
Mark Rustad9d329c12014-09-05 18:57:57 -07001800 struct kbdiacrsuc __user *a = udp;
Alan Cox247ff8e2012-02-24 12:47:11 +00001801 unsigned int ct;
1802 void *buf = NULL;
1803
1804 if (!perm)
1805 return -EPERM;
1806
1807 if (get_user(ct, &a->kb_cnt))
1808 return -EFAULT;
1809
1810 if (ct >= MAX_DIACR)
1811 return -EINVAL;
1812
1813 if (ct) {
Muhammad Falak R Wani9b651902016-05-20 17:53:28 +05301814 buf = memdup_user(a->kbdiacruc,
1815 ct * sizeof(struct kbdiacruc));
1816 if (IS_ERR(buf))
1817 return PTR_ERR(buf);
Alan Cox247ff8e2012-02-24 12:47:11 +00001818 }
1819 spin_lock_irqsave(&kbd_event_lock, flags);
1820 if (ct)
1821 memcpy(accent_table, buf,
1822 ct * sizeof(struct kbdiacruc));
1823 accent_table_size = ct;
1824 spin_unlock_irqrestore(&kbd_event_lock, flags);
1825 kfree(buf);
1826 return 0;
1827 }
1828 }
1829 return ret;
1830}
Alan Cox079c9532012-02-28 14:49:23 +00001831
1832/**
1833 * vt_do_kdskbmode - set keyboard mode ioctl
1834 * @console: the console to use
1835 * @arg: the requested mode
1836 *
1837 * Update the keyboard mode bits while holding the correct locks.
1838 * Return 0 for success or an error code.
1839 */
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02001840int vt_do_kdskbmode(unsigned int console, unsigned int arg)
Alan Cox079c9532012-02-28 14:49:23 +00001841{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02001842 struct kbd_struct *kb = &kbd_table[console];
Alan Cox079c9532012-02-28 14:49:23 +00001843 int ret = 0;
1844 unsigned long flags;
1845
1846 spin_lock_irqsave(&kbd_event_lock, flags);
1847 switch(arg) {
1848 case K_RAW:
Mark Rustad9d329c12014-09-05 18:57:57 -07001849 kb->kbdmode = VC_RAW;
Alan Cox079c9532012-02-28 14:49:23 +00001850 break;
1851 case K_MEDIUMRAW:
Mark Rustad9d329c12014-09-05 18:57:57 -07001852 kb->kbdmode = VC_MEDIUMRAW;
Alan Cox079c9532012-02-28 14:49:23 +00001853 break;
1854 case K_XLATE:
Mark Rustad9d329c12014-09-05 18:57:57 -07001855 kb->kbdmode = VC_XLATE;
Alan Cox079c9532012-02-28 14:49:23 +00001856 do_compute_shiftstate();
1857 break;
1858 case K_UNICODE:
Mark Rustad9d329c12014-09-05 18:57:57 -07001859 kb->kbdmode = VC_UNICODE;
Alan Cox079c9532012-02-28 14:49:23 +00001860 do_compute_shiftstate();
1861 break;
1862 case K_OFF:
Mark Rustad9d329c12014-09-05 18:57:57 -07001863 kb->kbdmode = VC_OFF;
Alan Cox079c9532012-02-28 14:49:23 +00001864 break;
1865 default:
1866 ret = -EINVAL;
1867 }
1868 spin_unlock_irqrestore(&kbd_event_lock, flags);
1869 return ret;
1870}
1871
1872/**
1873 * vt_do_kdskbmeta - set keyboard meta state
1874 * @console: the console to use
1875 * @arg: the requested meta state
1876 *
1877 * Update the keyboard meta bits while holding the correct locks.
1878 * Return 0 for success or an error code.
1879 */
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02001880int vt_do_kdskbmeta(unsigned int console, unsigned int arg)
Alan Cox079c9532012-02-28 14:49:23 +00001881{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02001882 struct kbd_struct *kb = &kbd_table[console];
Alan Cox079c9532012-02-28 14:49:23 +00001883 int ret = 0;
1884 unsigned long flags;
1885
1886 spin_lock_irqsave(&kbd_event_lock, flags);
1887 switch(arg) {
1888 case K_METABIT:
Mark Rustad9d329c12014-09-05 18:57:57 -07001889 clr_vc_kbd_mode(kb, VC_META);
Alan Cox079c9532012-02-28 14:49:23 +00001890 break;
1891 case K_ESCPREFIX:
Mark Rustad9d329c12014-09-05 18:57:57 -07001892 set_vc_kbd_mode(kb, VC_META);
Alan Cox079c9532012-02-28 14:49:23 +00001893 break;
1894 default:
1895 ret = -EINVAL;
1896 }
1897 spin_unlock_irqrestore(&kbd_event_lock, flags);
1898 return ret;
1899}
1900
1901int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
1902 int perm)
1903{
1904 struct kbkeycode tmp;
1905 int kc = 0;
1906
1907 if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
1908 return -EFAULT;
1909 switch (cmd) {
1910 case KDGETKEYCODE:
1911 kc = getkeycode(tmp.scancode);
1912 if (kc >= 0)
1913 kc = put_user(kc, &user_kbkc->keycode);
1914 break;
1915 case KDSETKEYCODE:
1916 if (!perm)
1917 return -EPERM;
1918 kc = setkeycode(tmp.scancode, tmp.keycode);
1919 break;
1920 }
1921 return kc;
1922}
1923
Jiri Slabyfe6416e2020-10-29 12:32:11 +01001924static unsigned short vt_kdgkbent(unsigned char kbdmode, unsigned char idx,
1925 unsigned char map)
1926{
1927 unsigned short *key_map, val;
1928 unsigned long flags;
1929
1930 /* Ensure another thread doesn't free it under us */
1931 spin_lock_irqsave(&kbd_event_lock, flags);
1932 key_map = key_maps[map];
1933 if (key_map) {
1934 val = U(key_map[idx]);
1935 if (kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
1936 val = K_HOLE;
1937 } else
1938 val = idx ? K_HOLE : K_NOSUCHMAP;
1939 spin_unlock_irqrestore(&kbd_event_lock, flags);
1940
1941 return val;
1942}
1943
1944static int vt_kdskbent(unsigned char kbdmode, unsigned char idx,
1945 unsigned char map, unsigned short val)
1946{
1947 unsigned long flags;
1948 unsigned short *key_map, *new_map, oldval;
1949
1950 if (!idx && val == K_NOSUCHMAP) {
1951 spin_lock_irqsave(&kbd_event_lock, flags);
1952 /* deallocate map */
1953 key_map = key_maps[map];
1954 if (map && key_map) {
1955 key_maps[map] = NULL;
1956 if (key_map[0] == U(K_ALLOCATED)) {
1957 kfree(key_map);
1958 keymap_count--;
1959 }
1960 }
1961 spin_unlock_irqrestore(&kbd_event_lock, flags);
1962
1963 return 0;
1964 }
1965
1966 if (KTYP(val) < NR_TYPES) {
1967 if (KVAL(val) > max_vals[KTYP(val)])
1968 return -EINVAL;
1969 } else if (kbdmode != VC_UNICODE)
1970 return -EINVAL;
1971
1972 /* ++Geert: non-PC keyboards may generate keycode zero */
1973#if !defined(__mc68000__) && !defined(__powerpc__)
1974 /* assignment to entry 0 only tests validity of args */
1975 if (!idx)
1976 return 0;
1977#endif
1978
1979 new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
1980 if (!new_map)
1981 return -ENOMEM;
1982
1983 spin_lock_irqsave(&kbd_event_lock, flags);
1984 key_map = key_maps[map];
1985 if (key_map == NULL) {
1986 int j;
1987
1988 if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
1989 !capable(CAP_SYS_RESOURCE)) {
1990 spin_unlock_irqrestore(&kbd_event_lock, flags);
1991 kfree(new_map);
1992 return -EPERM;
1993 }
1994 key_maps[map] = new_map;
1995 key_map = new_map;
1996 key_map[0] = U(K_ALLOCATED);
1997 for (j = 1; j < NR_KEYS; j++)
1998 key_map[j] = U(K_HOLE);
1999 keymap_count++;
2000 } else
2001 kfree(new_map);
2002
2003 oldval = U(key_map[idx]);
2004 if (val == oldval)
2005 goto out;
2006
2007 /* Attention Key */
2008 if ((oldval == K_SAK || val == K_SAK) && !capable(CAP_SYS_ADMIN)) {
2009 spin_unlock_irqrestore(&kbd_event_lock, flags);
2010 return -EPERM;
2011 }
2012
2013 key_map[idx] = U(val);
2014 if (!map && (KTYP(oldval) == KT_SHIFT || KTYP(val) == KT_SHIFT))
2015 do_compute_shiftstate();
2016out:
2017 spin_unlock_irqrestore(&kbd_event_lock, flags);
2018
2019 return 0;
2020}
Alan Cox079c9532012-02-28 14:49:23 +00002021
2022int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02002023 unsigned int console)
Alan Cox079c9532012-02-28 14:49:23 +00002024{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02002025 struct kbd_struct *kb = &kbd_table[console];
Jiri Slabyfe6416e2020-10-29 12:32:11 +01002026 struct kbentry kbe;
Alan Cox079c9532012-02-28 14:49:23 +00002027
Jiri Slabyfe6416e2020-10-29 12:32:11 +01002028 if (copy_from_user(&kbe, user_kbe, sizeof(struct kbentry)))
Alan Cox079c9532012-02-28 14:49:23 +00002029 return -EFAULT;
2030
Alan Cox079c9532012-02-28 14:49:23 +00002031 switch (cmd) {
2032 case KDGKBENT:
Jiri Slabyfe6416e2020-10-29 12:32:11 +01002033 return put_user(vt_kdgkbent(kb->kbdmode, kbe.kb_index,
2034 kbe.kb_table),
2035 &user_kbe->kb_value);
Alan Cox079c9532012-02-28 14:49:23 +00002036 case KDSKBENT:
Jiri Slabyee1cf8a2020-10-29 12:32:12 +01002037 if (!perm || !capable(CAP_SYS_TTY_CONFIG))
Alan Cox079c9532012-02-28 14:49:23 +00002038 return -EPERM;
Jiri Slabyfe6416e2020-10-29 12:32:11 +01002039 return vt_kdskbent(kb->kbdmode, kbe.kb_index, kbe.kb_table,
2040 kbe.kb_value);
Alan Cox079c9532012-02-28 14:49:23 +00002041 }
2042 return 0;
2043}
Alan Cox079c9532012-02-28 14:49:23 +00002044
Jiri Slaby4e1404a2020-10-29 12:32:17 +01002045static char *vt_kdskbsent(char *kbs, unsigned char cur)
2046{
2047 static DECLARE_BITMAP(is_kmalloc, MAX_NR_FUNC);
2048 char *cur_f = func_table[cur];
2049
2050 if (cur_f && strlen(cur_f) >= strlen(kbs)) {
2051 strcpy(cur_f, kbs);
2052 return kbs;
2053 }
2054
2055 func_table[cur] = kbs;
2056
2057 return __test_and_set_bit(cur, is_kmalloc) ? cur_f : NULL;
2058}
2059
Alan Cox079c9532012-02-28 14:49:23 +00002060int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
2061{
Jiri Slaby9788c952020-10-29 12:32:15 +01002062 unsigned char kb_func;
Jiri Slaby4e1404a2020-10-29 12:32:17 +01002063 unsigned long flags;
2064 char *kbs;
2065 int ret;
Alan Cox079c9532012-02-28 14:49:23 +00002066
Jiri Slaby07edff922020-10-29 12:32:16 +01002067 if (get_user(kb_func, &user_kdgkb->kb_func))
2068 return -EFAULT;
Alan Cox079c9532012-02-28 14:49:23 +00002069
Jiri Slaby07edff922020-10-29 12:32:16 +01002070 kb_func = array_index_nospec(kb_func, MAX_NR_FUNC);
Alan Cox079c9532012-02-28 14:49:23 +00002071
2072 switch (cmd) {
Jiri Slaby6ca03f92020-10-19 10:55:16 +02002073 case KDGKBSENT: {
2074 /* size should have been a struct member */
Jiri Slaby82e61c32020-10-19 10:55:17 +02002075 ssize_t len = sizeof(user_kdgkb->kb_string);
Jiri Slaby6ca03f92020-10-19 10:55:16 +02002076
Jiri Slaby07edff922020-10-29 12:32:16 +01002077 kbs = kmalloc(len, GFP_KERNEL);
2078 if (!kbs)
2079 return -ENOMEM;
2080
Jiri Slaby82e61c32020-10-19 10:55:17 +02002081 spin_lock_irqsave(&func_buf_lock, flags);
Jiri Slaby07edff922020-10-29 12:32:16 +01002082 len = strlcpy(kbs, func_table[kb_func] ? : "", len);
Jiri Slaby82e61c32020-10-19 10:55:17 +02002083 spin_unlock_irqrestore(&func_buf_lock, flags);
2084
Jiri Slaby07edff922020-10-29 12:32:16 +01002085 ret = copy_to_user(user_kdgkb->kb_string, kbs, len + 1) ?
2086 -EFAULT : 0;
Jiri Slaby6ca03f92020-10-19 10:55:16 +02002087
Jiri Slaby4e1404a2020-10-29 12:32:17 +01002088 break;
Jiri Slaby6ca03f92020-10-19 10:55:16 +02002089 }
Alan Cox079c9532012-02-28 14:49:23 +00002090 case KDSKBSENT:
Jiri Slabycb58a502020-10-29 12:32:19 +01002091 if (!perm || !capable(CAP_SYS_TTY_CONFIG))
Jiri Slaby07edff922020-10-29 12:32:16 +01002092 return -EPERM;
2093
2094 kbs = strndup_user(user_kdgkb->kb_string,
2095 sizeof(user_kdgkb->kb_string));
2096 if (IS_ERR(kbs))
2097 return PTR_ERR(kbs);
Alan Cox079c9532012-02-28 14:49:23 +00002098
Sergei Trofimovich46ca3f72019-03-10 21:24:15 +00002099 spin_lock_irqsave(&func_buf_lock, flags);
Jiri Slaby4e1404a2020-10-29 12:32:17 +01002100 kbs = vt_kdskbsent(kbs, kb_func);
Sergei Trofimovich46ca3f72019-03-10 21:24:15 +00002101 spin_unlock_irqrestore(&func_buf_lock, flags);
Jiri Slaby4e1404a2020-10-29 12:32:17 +01002102
2103 ret = 0;
Alan Cox079c9532012-02-28 14:49:23 +00002104 break;
2105 }
Jiri Slaby4e1404a2020-10-29 12:32:17 +01002106
Alan Cox079c9532012-02-28 14:49:23 +00002107 kfree(kbs);
Jiri Slaby4e1404a2020-10-29 12:32:17 +01002108
Alan Cox079c9532012-02-28 14:49:23 +00002109 return ret;
2110}
2111
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02002112int vt_do_kdskled(unsigned int console, int cmd, unsigned long arg, int perm)
Alan Cox079c9532012-02-28 14:49:23 +00002113{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02002114 struct kbd_struct *kb = &kbd_table[console];
Alan Cox079c9532012-02-28 14:49:23 +00002115 unsigned long flags;
2116 unsigned char ucval;
2117
2118 switch(cmd) {
2119 /* the ioctls below read/set the flags usually shown in the leds */
2120 /* don't use them - they will go away without warning */
2121 case KDGKBLED:
2122 spin_lock_irqsave(&kbd_event_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07002123 ucval = kb->ledflagstate | (kb->default_ledflagstate << 4);
Alan Cox079c9532012-02-28 14:49:23 +00002124 spin_unlock_irqrestore(&kbd_event_lock, flags);
2125 return put_user(ucval, (char __user *)arg);
2126
2127 case KDSKBLED:
2128 if (!perm)
2129 return -EPERM;
2130 if (arg & ~0x77)
2131 return -EINVAL;
Alan Cox3db1ddb2012-07-17 17:06:41 +01002132 spin_lock_irqsave(&led_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07002133 kb->ledflagstate = (arg & 7);
2134 kb->default_ledflagstate = ((arg >> 4) & 7);
Alan Cox079c9532012-02-28 14:49:23 +00002135 set_leds();
Alan Cox3db1ddb2012-07-17 17:06:41 +01002136 spin_unlock_irqrestore(&led_lock, flags);
Alan Coxeea41ae2012-05-14 14:41:31 +01002137 return 0;
Alan Cox079c9532012-02-28 14:49:23 +00002138
2139 /* the ioctls below only set the lights, not the functions */
2140 /* for those, see KDGKBLED and KDSKBLED above */
2141 case KDGETLED:
2142 ucval = getledstate();
2143 return put_user(ucval, (char __user *)arg);
2144
2145 case KDSETLED:
2146 if (!perm)
2147 return -EPERM;
Mark Rustad9d329c12014-09-05 18:57:57 -07002148 setledstate(kb, arg);
Alan Cox079c9532012-02-28 14:49:23 +00002149 return 0;
2150 }
2151 return -ENOIOCTLCMD;
2152}
2153
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02002154int vt_do_kdgkbmode(unsigned int console)
Alan Cox079c9532012-02-28 14:49:23 +00002155{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02002156 struct kbd_struct *kb = &kbd_table[console];
Alan Cox079c9532012-02-28 14:49:23 +00002157 /* This is a spot read so needs no locking */
Mark Rustad9d329c12014-09-05 18:57:57 -07002158 switch (kb->kbdmode) {
Alan Cox079c9532012-02-28 14:49:23 +00002159 case VC_RAW:
2160 return K_RAW;
2161 case VC_MEDIUMRAW:
2162 return K_MEDIUMRAW;
2163 case VC_UNICODE:
2164 return K_UNICODE;
2165 case VC_OFF:
2166 return K_OFF;
2167 default:
2168 return K_XLATE;
2169 }
2170}
2171
2172/**
2173 * vt_do_kdgkbmeta - report meta status
2174 * @console: console to report
2175 *
2176 * Report the meta flag status of this console
2177 */
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02002178int vt_do_kdgkbmeta(unsigned int console)
Alan Cox079c9532012-02-28 14:49:23 +00002179{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02002180 struct kbd_struct *kb = &kbd_table[console];
Alan Cox079c9532012-02-28 14:49:23 +00002181 /* Again a spot read so no locking */
Mark Rustad9d329c12014-09-05 18:57:57 -07002182 return vc_kbd_mode(kb, VC_META) ? K_ESCPREFIX : K_METABIT;
Alan Cox079c9532012-02-28 14:49:23 +00002183}
2184
2185/**
2186 * vt_reset_unicode - reset the unicode status
2187 * @console: console being reset
2188 *
2189 * Restore the unicode console state to its default
2190 */
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02002191void vt_reset_unicode(unsigned int console)
Alan Cox079c9532012-02-28 14:49:23 +00002192{
2193 unsigned long flags;
2194
2195 spin_lock_irqsave(&kbd_event_lock, flags);
2196 kbd_table[console].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
2197 spin_unlock_irqrestore(&kbd_event_lock, flags);
2198}
2199
2200/**
Andy Shevchenkoc6a419a2021-03-03 10:32:29 +02002201 * vt_get_shift_state - shift bit state
Alan Cox079c9532012-02-28 14:49:23 +00002202 *
2203 * Report the shift bits from the keyboard state. We have to export
2204 * this to support some oddities in the vt layer.
2205 */
2206int vt_get_shift_state(void)
2207{
2208 /* Don't lock as this is a transient report */
2209 return shift_state;
2210}
2211
2212/**
2213 * vt_reset_keyboard - reset keyboard state
2214 * @console: console to reset
2215 *
2216 * Reset the keyboard bits for a console as part of a general console
2217 * reset event
2218 */
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02002219void vt_reset_keyboard(unsigned int console)
Alan Cox079c9532012-02-28 14:49:23 +00002220{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02002221 struct kbd_struct *kb = &kbd_table[console];
Alan Cox079c9532012-02-28 14:49:23 +00002222 unsigned long flags;
2223
2224 spin_lock_irqsave(&kbd_event_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07002225 set_vc_kbd_mode(kb, VC_REPEAT);
2226 clr_vc_kbd_mode(kb, VC_CKMODE);
2227 clr_vc_kbd_mode(kb, VC_APPLIC);
2228 clr_vc_kbd_mode(kb, VC_CRLF);
2229 kb->lockstate = 0;
2230 kb->slockstate = 0;
Alan Cox3db1ddb2012-07-17 17:06:41 +01002231 spin_lock(&led_lock);
Mark Rustad9d329c12014-09-05 18:57:57 -07002232 kb->ledmode = LED_SHOW_FLAGS;
2233 kb->ledflagstate = kb->default_ledflagstate;
Alan Cox3db1ddb2012-07-17 17:06:41 +01002234 spin_unlock(&led_lock);
Alan Cox079c9532012-02-28 14:49:23 +00002235 /* do not do set_leds here because this causes an endless tasklet loop
2236 when the keyboard hasn't been initialized yet */
2237 spin_unlock_irqrestore(&kbd_event_lock, flags);
2238}
2239
2240/**
2241 * vt_get_kbd_mode_bit - read keyboard status bits
2242 * @console: console to read from
2243 * @bit: mode bit to read
2244 *
2245 * Report back a vt mode bit. We do this without locking so the
2246 * caller must be sure that there are no synchronization needs
2247 */
2248
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02002249int vt_get_kbd_mode_bit(unsigned int console, int bit)
Alan Cox079c9532012-02-28 14:49:23 +00002250{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02002251 struct kbd_struct *kb = &kbd_table[console];
Mark Rustad9d329c12014-09-05 18:57:57 -07002252 return vc_kbd_mode(kb, bit);
Alan Cox079c9532012-02-28 14:49:23 +00002253}
2254
2255/**
2256 * vt_set_kbd_mode_bit - read keyboard status bits
2257 * @console: console to read from
2258 * @bit: mode bit to read
2259 *
2260 * Set a vt mode bit. We do this without locking so the
2261 * caller must be sure that there are no synchronization needs
2262 */
2263
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02002264void vt_set_kbd_mode_bit(unsigned int console, int bit)
Alan Cox079c9532012-02-28 14:49:23 +00002265{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02002266 struct kbd_struct *kb = &kbd_table[console];
Alan Cox079c9532012-02-28 14:49:23 +00002267 unsigned long flags;
2268
2269 spin_lock_irqsave(&kbd_event_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07002270 set_vc_kbd_mode(kb, bit);
Alan Cox079c9532012-02-28 14:49:23 +00002271 spin_unlock_irqrestore(&kbd_event_lock, flags);
2272}
2273
2274/**
2275 * vt_clr_kbd_mode_bit - read keyboard status bits
2276 * @console: console to read from
2277 * @bit: mode bit to read
2278 *
2279 * Report back a vt mode bit. We do this without locking so the
2280 * caller must be sure that there are no synchronization needs
2281 */
2282
Greg Kroah-Hartman3df15d62021-07-26 15:43:22 +02002283void vt_clr_kbd_mode_bit(unsigned int console, int bit)
Alan Cox079c9532012-02-28 14:49:23 +00002284{
Greg Kroah-Hartmanc92bbbf2021-07-26 15:43:21 +02002285 struct kbd_struct *kb = &kbd_table[console];
Alan Cox079c9532012-02-28 14:49:23 +00002286 unsigned long flags;
2287
2288 spin_lock_irqsave(&kbd_event_lock, flags);
Mark Rustad9d329c12014-09-05 18:57:57 -07002289 clr_vc_kbd_mode(kb, bit);
Alan Cox079c9532012-02-28 14:49:23 +00002290 spin_unlock_irqrestore(&kbd_event_lock, flags);
2291}