|
@@ -42,6 +42,7 @@
|
|
|
#include <linux/sysrq.h>
|
|
|
#include <linux/input.h>
|
|
|
#include <linux/reboot.h>
|
|
|
+#include <linux/notifier.h>
|
|
|
|
|
|
extern void ctrl_alt_del(void);
|
|
|
|
|
@@ -81,7 +82,8 @@ void compute_shiftstate(void);
|
|
|
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
|
|
|
char up_flag);
|
|
|
static k_handler_fn K_HANDLERS;
|
|
|
-static k_handler_fn *k_handler[16] = { K_HANDLERS };
|
|
|
+k_handler_fn *k_handler[16] = { K_HANDLERS };
|
|
|
+EXPORT_SYMBOL_GPL(k_handler);
|
|
|
|
|
|
#define FN_HANDLERS\
|
|
|
fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
|
|
@@ -159,6 +161,23 @@ static int sysrq_alt_use;
|
|
|
#endif
|
|
|
static int sysrq_alt;
|
|
|
|
|
|
+/*
|
|
|
+ * Notifier list for console keyboard events
|
|
|
+ */
|
|
|
+static ATOMIC_NOTIFIER_HEAD(keyboard_notifier_list);
|
|
|
+
|
|
|
+int register_keyboard_notifier(struct notifier_block *nb)
|
|
|
+{
|
|
|
+ return atomic_notifier_chain_register(&keyboard_notifier_list, nb);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(register_keyboard_notifier);
|
|
|
+
|
|
|
+int unregister_keyboard_notifier(struct notifier_block *nb)
|
|
|
+{
|
|
|
+ return atomic_notifier_chain_unregister(&keyboard_notifier_list, nb);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
|
|
|
+
|
|
|
/*
|
|
|
* Translation of scancodes to keycodes. We set them on only the first
|
|
|
* keyboard in the list that accepts the scancode and keycode.
|
|
@@ -1130,6 +1149,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
|
|
|
unsigned char type, raw_mode;
|
|
|
struct tty_struct *tty;
|
|
|
int shift_final;
|
|
|
+ struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
|
|
|
|
|
|
tty = vc->vc_tty;
|
|
|
|
|
@@ -1217,10 +1237,11 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
|
|
|
+ param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
|
|
|
key_map = key_maps[shift_final];
|
|
|
|
|
|
- if (!key_map) {
|
|
|
+ if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, ¶m) == NOTIFY_STOP || !key_map) {
|
|
|
+ atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNBOUND_KEYCODE, ¶m);
|
|
|
compute_shiftstate();
|
|
|
kbd->slockstate = 0;
|
|
|
return;
|
|
@@ -1237,6 +1258,9 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
|
|
|
type = KTYP(keysym);
|
|
|
|
|
|
if (type < 0xf0) {
|
|
|
+ param.value = keysym;
|
|
|
+ if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNICODE, ¶m) == NOTIFY_STOP)
|
|
|
+ return;
|
|
|
if (down && !raw_mode)
|
|
|
to_utf8(vc, keysym);
|
|
|
return;
|
|
@@ -1244,9 +1268,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
|
|
|
|
|
|
type -= 0xf0;
|
|
|
|
|
|
- if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
|
|
|
- return;
|
|
|
-
|
|
|
if (type == KT_LETTER) {
|
|
|
type = KT_LATIN;
|
|
|
if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
|
|
@@ -1255,9 +1276,18 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
|
|
|
keysym = key_map[keycode];
|
|
|
}
|
|
|
}
|
|
|
+ param.value = keysym;
|
|
|
+
|
|
|
+ if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYSYM, ¶m) == NOTIFY_STOP)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
|
|
|
+ return;
|
|
|
|
|
|
(*k_handler[type])(vc, keysym & 0xff, !down);
|
|
|
|
|
|
+ atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, ¶m);
|
|
|
+
|
|
|
if (type != KT_SLOCK)
|
|
|
kbd->slockstate = 0;
|
|
|
}
|