aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/keyboard.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 212276affa1f..d54f4a3ae340 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -42,6 +42,7 @@
42#include <linux/sysrq.h> 42#include <linux/sysrq.h>
43#include <linux/input.h> 43#include <linux/input.h>
44#include <linux/reboot.h> 44#include <linux/reboot.h>
45#include <linux/notifier.h>
45 46
46extern void ctrl_alt_del(void); 47extern void ctrl_alt_del(void);
47 48
@@ -81,7 +82,8 @@ void compute_shiftstate(void);
81typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, 82typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
82 char up_flag); 83 char up_flag);
83static k_handler_fn K_HANDLERS; 84static k_handler_fn K_HANDLERS;
84static k_handler_fn *k_handler[16] = { K_HANDLERS }; 85k_handler_fn *k_handler[16] = { K_HANDLERS };
86EXPORT_SYMBOL_GPL(k_handler);
85 87
86#define FN_HANDLERS\ 88#define FN_HANDLERS\
87 fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\ 89 fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
@@ -160,6 +162,23 @@ static int sysrq_alt_use;
160static int sysrq_alt; 162static int sysrq_alt;
161 163
162/* 164/*
165 * Notifier list for console keyboard events
166 */
167static ATOMIC_NOTIFIER_HEAD(keyboard_notifier_list);
168
169int register_keyboard_notifier(struct notifier_block *nb)
170{
171 return atomic_notifier_chain_register(&keyboard_notifier_list, nb);
172}
173EXPORT_SYMBOL_GPL(register_keyboard_notifier);
174
175int unregister_keyboard_notifier(struct notifier_block *nb)
176{
177 return atomic_notifier_chain_unregister(&keyboard_notifier_list, nb);
178}
179EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
180
181/*
163 * Translation of scancodes to keycodes. We set them on only the first 182 * Translation of scancodes to keycodes. We set them on only the first
164 * keyboard in the list that accepts the scancode and keycode. 183 * keyboard in the list that accepts the scancode and keycode.
165 * Explanation for not choosing the first attached keyboard anymore: 184 * Explanation for not choosing the first attached keyboard anymore:
@@ -1130,6 +1149,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
1130 unsigned char type, raw_mode; 1149 unsigned char type, raw_mode;
1131 struct tty_struct *tty; 1150 struct tty_struct *tty;
1132 int shift_final; 1151 int shift_final;
1152 struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
1133 1153
1134 tty = vc->vc_tty; 1154 tty = vc->vc_tty;
1135 1155
@@ -1217,10 +1237,11 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
1217 return; 1237 return;
1218 } 1238 }
1219 1239
1220 shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate; 1240 param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
1221 key_map = key_maps[shift_final]; 1241 key_map = key_maps[shift_final];
1222 1242
1223 if (!key_map) { 1243 if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, &param) == NOTIFY_STOP || !key_map) {
1244 atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNBOUND_KEYCODE, &param);
1224 compute_shiftstate(); 1245 compute_shiftstate();
1225 kbd->slockstate = 0; 1246 kbd->slockstate = 0;
1226 return; 1247 return;
@@ -1237,6 +1258,9 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
1237 type = KTYP(keysym); 1258 type = KTYP(keysym);
1238 1259
1239 if (type < 0xf0) { 1260 if (type < 0xf0) {
1261 param.value = keysym;
1262 if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNICODE, &param) == NOTIFY_STOP)
1263 return;
1240 if (down && !raw_mode) 1264 if (down && !raw_mode)
1241 to_utf8(vc, keysym); 1265 to_utf8(vc, keysym);
1242 return; 1266 return;
@@ -1244,9 +1268,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
1244 1268
1245 type -= 0xf0; 1269 type -= 0xf0;
1246 1270
1247 if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
1248 return;
1249
1250 if (type == KT_LETTER) { 1271 if (type == KT_LETTER) {
1251 type = KT_LATIN; 1272 type = KT_LATIN;
1252 if (vc_kbd_led(kbd, VC_CAPSLOCK)) { 1273 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
@@ -1255,9 +1276,18 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
1255 keysym = key_map[keycode]; 1276 keysym = key_map[keycode];
1256 } 1277 }
1257 } 1278 }
1279 param.value = keysym;
1280
1281 if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYSYM, &param) == NOTIFY_STOP)
1282 return;
1283
1284 if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
1285 return;
1258 1286
1259 (*k_handler[type])(vc, keysym & 0xff, !down); 1287 (*k_handler[type])(vc, keysym & 0xff, !down);
1260 1288
1289 atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
1290
1261 if (type != KT_SLOCK) 1291 if (type != KT_SLOCK)
1262 kbd->slockstate = 0; 1292 kbd->slockstate = 0;
1263} 1293}