diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-03-22 01:31:26 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-04-14 02:26:02 -0400 |
| commit | 97f5f0cd8cd0a05449cbb77d1e6f02e026875802 (patch) | |
| tree | e101f38dfd7bf4e759e96617f69ceedd497608e3 | |
| parent | b91c4be730668e801aa6a2ea95f467cd9a1e0983 (diff) | |
Input: implement SysRq as a separate input handler
Instead of keeping SysRq support inside of legacy keyboard driver split
it out into a separate input handler (filter). This stops most SysRq input
events from leaking into evdev clients (some events, such as first SysRq
scancode - not keycode - event, are still leaked into both legacy keyboard
and evdev).
[martinez.javier@gmail.com: fix compile error when CONFIG_MAGIC_SYSRQ is
not defined]
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
| -rw-r--r-- | drivers/char/keyboard.c | 40 | ||||
| -rw-r--r-- | drivers/char/sysrq.c | 243 | ||||
| -rw-r--r-- | include/linux/sysrq.h | 23 | ||||
| -rw-r--r-- | kernel/sysctl.c | 23 |
4 files changed, 246 insertions, 83 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index ada25bb8941e..50f6c01f44ec 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
| @@ -38,7 +38,6 @@ | |||
| 38 | #include <linux/kbd_kern.h> | 38 | #include <linux/kbd_kern.h> |
| 39 | #include <linux/kbd_diacr.h> | 39 | #include <linux/kbd_diacr.h> |
| 40 | #include <linux/vt_kern.h> | 40 | #include <linux/vt_kern.h> |
| 41 | #include <linux/sysrq.h> | ||
| 42 | #include <linux/input.h> | 41 | #include <linux/input.h> |
| 43 | #include <linux/reboot.h> | 42 | #include <linux/reboot.h> |
| 44 | #include <linux/notifier.h> | 43 | #include <linux/notifier.h> |
| @@ -82,8 +81,7 @@ void compute_shiftstate(void); | |||
| 82 | typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, | 81 | typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, |
| 83 | char up_flag); | 82 | char up_flag); |
| 84 | static k_handler_fn K_HANDLERS; | 83 | static k_handler_fn K_HANDLERS; |
| 85 | k_handler_fn *k_handler[16] = { K_HANDLERS }; | 84 | static k_handler_fn *k_handler[16] = { K_HANDLERS }; |
| 86 | EXPORT_SYMBOL_GPL(k_handler); | ||
| 87 | 85 | ||
| 88 | #define FN_HANDLERS\ | 86 | #define FN_HANDLERS\ |
| 89 | fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\ | 87 | fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\ |
| @@ -147,22 +145,6 @@ static struct ledptr { | |||
| 147 | unsigned char valid:1; | 145 | unsigned char valid:1; |
| 148 | } ledptrs[3]; | 146 | } ledptrs[3]; |
| 149 | 147 | ||
| 150 | /* Simple translation table for the SysRq keys */ | ||
| 151 | |||
| 152 | #ifdef CONFIG_MAGIC_SYSRQ | ||
| 153 | unsigned char kbd_sysrq_xlate[KEY_MAX + 1] = | ||
| 154 | "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ | ||
| 155 | "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ | ||
| 156 | "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ | ||
| 157 | "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ | ||
| 158 | "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ | ||
| 159 | "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ | ||
| 160 | "\r\000/"; /* 0x60 - 0x6f */ | ||
| 161 | static int sysrq_down; | ||
| 162 | static int sysrq_alt_use; | ||
| 163 | #endif | ||
| 164 | static int sysrq_alt; | ||
| 165 | |||
| 166 | /* | 148 | /* |
| 167 | * Notifier list for console keyboard events | 149 | * Notifier list for console keyboard events |
| 168 | */ | 150 | */ |
| @@ -1108,7 +1090,8 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, | |||
| 1108 | * pressing PrtSc/SysRq alone, but simply 0x54 | 1090 | * pressing PrtSc/SysRq alone, but simply 0x54 |
| 1109 | * when pressing Alt+PrtSc/SysRq. | 1091 | * when pressing Alt+PrtSc/SysRq. |
| 1110 | */ | 1092 | */ |
| 1111 | if (sysrq_alt) { | 1093 | if (test_bit(KEY_LEFTALT, key_down) || |
| 1094 | test_bit(KEY_RIGHTALT, key_down)) { | ||
| 1112 | put_queue(vc, 0x54 | up_flag); | 1095 | put_queue(vc, 0x54 | up_flag); |
| 1113 | } else { | 1096 | } else { |
| 1114 | put_queue(vc, 0xe0); | 1097 | put_queue(vc, 0xe0); |
| @@ -1176,8 +1159,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
| 1176 | 1159 | ||
| 1177 | kbd = kbd_table + vc->vc_num; | 1160 | kbd = kbd_table + vc->vc_num; |
| 1178 | 1161 | ||
| 1179 | if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT) | ||
| 1180 | sysrq_alt = down ? keycode : 0; | ||
| 1181 | #ifdef CONFIG_SPARC | 1162 | #ifdef CONFIG_SPARC |
| 1182 | if (keycode == KEY_STOP) | 1163 | if (keycode == KEY_STOP) |
| 1183 | sparc_l1_a_state = down; | 1164 | sparc_l1_a_state = down; |
| @@ -1190,21 +1171,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
| 1190 | if (keycode < BTN_MISC && printk_ratelimit()) | 1171 | if (keycode < BTN_MISC && printk_ratelimit()) |
| 1191 | printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); | 1172 | printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); |
| 1192 | 1173 | ||
| 1193 | #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ | ||
| 1194 | if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) { | ||
| 1195 | if (!sysrq_down) { | ||
| 1196 | sysrq_down = down; | ||
| 1197 | sysrq_alt_use = sysrq_alt; | ||
| 1198 | } | ||
| 1199 | return; | ||
| 1200 | } | ||
| 1201 | if (sysrq_down && !down && keycode == sysrq_alt_use) | ||
| 1202 | sysrq_down = 0; | ||
| 1203 | if (sysrq_down && down && !rep) { | ||
| 1204 | handle_sysrq(kbd_sysrq_xlate[keycode], tty); | ||
| 1205 | return; | ||
| 1206 | } | ||
| 1207 | #endif | ||
| 1208 | #ifdef CONFIG_SPARC | 1174 | #ifdef CONFIG_SPARC |
| 1209 | if (keycode == KEY_A && sparc_l1_a_state) { | 1175 | if (keycode == KEY_A && sparc_l1_a_state) { |
| 1210 | sparc_l1_a_state = 0; | 1176 | sparc_l1_a_state = 0; |
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 59de2525d303..193f9c214946 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
| @@ -1,7 +1,4 @@ | |||
| 1 | /* -*- linux-c -*- | 1 | /* |
| 2 | * | ||
| 3 | * $Id: sysrq.c,v 1.15 1998/08/23 14:56:41 mj Exp $ | ||
| 4 | * | ||
| 5 | * Linux Magic System Request Key Hacks | 2 | * Linux Magic System Request Key Hacks |
| 6 | * | 3 | * |
| 7 | * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> | 4 | * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> |
| @@ -10,8 +7,13 @@ | |||
| 10 | * (c) 2000 Crutcher Dunnavant <crutcher+kernel@datastacks.com> | 7 | * (c) 2000 Crutcher Dunnavant <crutcher+kernel@datastacks.com> |
| 11 | * overhauled to use key registration | 8 | * overhauled to use key registration |
| 12 | * based upon discusions in irc://irc.openprojects.net/#kernelnewbies | 9 | * based upon discusions in irc://irc.openprojects.net/#kernelnewbies |
| 10 | * | ||
| 11 | * Copyright (c) 2010 Dmitry Torokhov | ||
| 12 | * Input handler conversion | ||
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 16 | |||
| 15 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
| 16 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
| 17 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
| @@ -39,33 +41,34 @@ | |||
| 39 | #include <linux/hrtimer.h> | 41 | #include <linux/hrtimer.h> |
| 40 | #include <linux/oom.h> | 42 | #include <linux/oom.h> |
| 41 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
| 44 | #include <linux/input.h> | ||
| 42 | 45 | ||
| 43 | #include <asm/ptrace.h> | 46 | #include <asm/ptrace.h> |
| 44 | #include <asm/irq_regs.h> | 47 | #include <asm/irq_regs.h> |
| 45 | 48 | ||
| 46 | /* Whether we react on sysrq keys or just ignore them */ | 49 | /* Whether we react on sysrq keys or just ignore them */ |
| 47 | int __read_mostly __sysrq_enabled = 1; | 50 | static int __read_mostly sysrq_enabled = 1; |
| 48 | 51 | static bool __read_mostly sysrq_always_enabled; | |
| 49 | static int __read_mostly sysrq_always_enabled; | ||
| 50 | 52 | ||
| 51 | int sysrq_on(void) | 53 | static bool sysrq_on(void) |
| 52 | { | 54 | { |
| 53 | return __sysrq_enabled || sysrq_always_enabled; | 55 | return sysrq_enabled || sysrq_always_enabled; |
| 54 | } | 56 | } |
| 55 | 57 | ||
| 56 | /* | 58 | /* |
| 57 | * A value of 1 means 'all', other nonzero values are an op mask: | 59 | * A value of 1 means 'all', other nonzero values are an op mask: |
| 58 | */ | 60 | */ |
| 59 | static inline int sysrq_on_mask(int mask) | 61 | static bool sysrq_on_mask(int mask) |
| 60 | { | 62 | { |
| 61 | return sysrq_always_enabled || __sysrq_enabled == 1 || | 63 | return sysrq_always_enabled || |
| 62 | (__sysrq_enabled & mask); | 64 | sysrq_enabled == 1 || |
| 65 | (sysrq_enabled & mask); | ||
| 63 | } | 66 | } |
| 64 | 67 | ||
| 65 | static int __init sysrq_always_enabled_setup(char *str) | 68 | static int __init sysrq_always_enabled_setup(char *str) |
| 66 | { | 69 | { |
| 67 | sysrq_always_enabled = 1; | 70 | sysrq_always_enabled = true; |
| 68 | printk(KERN_INFO "debug: sysrq always enabled.\n"); | 71 | pr_info("sysrq always enabled.\n"); |
| 69 | 72 | ||
| 70 | return 1; | 73 | return 1; |
| 71 | } | 74 | } |
| @@ -76,6 +79,7 @@ __setup("sysrq_always_enabled", sysrq_always_enabled_setup); | |||
| 76 | static void sysrq_handle_loglevel(int key, struct tty_struct *tty) | 79 | static void sysrq_handle_loglevel(int key, struct tty_struct *tty) |
| 77 | { | 80 | { |
| 78 | int i; | 81 | int i; |
| 82 | |||
| 79 | i = key - '0'; | 83 | i = key - '0'; |
| 80 | console_loglevel = 7; | 84 | console_loglevel = 7; |
| 81 | printk("Loglevel set to %d\n", i); | 85 | printk("Loglevel set to %d\n", i); |
| @@ -101,7 +105,7 @@ static struct sysrq_key_op sysrq_SAK_op = { | |||
| 101 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, | 105 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, |
| 102< | |||
