1
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
2
index 2ce0af1..bc59c5c 100644
3
--- a/drivers/char/keyboard.c
4
+++ b/drivers/char/keyboard.c
6
#include <linux/sysrq.h>
7
#include <linux/input.h>
8
#include <linux/reboot.h>
9
+#include <linux/notifier.h>
11
extern void ctrl_alt_del(void);
13
@@ -80,7 +81,8 @@ void compute_shiftstate(void);
14
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
16
static k_handler_fn K_HANDLERS;
17
-static k_handler_fn *k_handler[16] = { K_HANDLERS };
18
+k_handler_fn *k_handler[16] = { K_HANDLERS };
19
+EXPORT_SYMBOL_GPL(k_handler);
22
fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
23
@@ -159,2 +161,19 @@ static int sysrq_alt_use;
27
+ * Notifier list for console keyboard events
29
+static ATOMIC_NOTIFIER_HEAD(keyboard_notifier_list);
31
+int register_keyboard_notifier(struct notifier_block *nb)
33
+ return atomic_notifier_chain_register(&keyboard_notifier_list, nb);
35
+EXPORT_SYMBOL_GPL(register_keyboard_notifier);
37
+int unregister_keyboard_notifier(struct notifier_block *nb)
39
+ return atomic_notifier_chain_unregister(&keyboard_notifier_list, nb);
41
+EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
43
@@ -1119,6 +1138,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
44
unsigned char type, raw_mode;
45
struct tty_struct *tty;
47
+ struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
51
@@ -1206,10 +1226,11 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
55
- shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
56
+ param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
57
key_map = key_maps[shift_final];
60
+ if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, ¶m) == NOTIFY_STOP || !key_map) {
61
+ atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNBOUND_KEYCODE, ¶m);
65
@@ -1226,6 +1247,9 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
69
+ param.value = keysym;
70
+ if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNICODE, ¶m) == NOTIFY_STOP)
72
if (down && !raw_mode)
75
@@ -1233,9 +1257,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
79
- if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
82
if (type == KT_LETTER) {
84
if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
85
@@ -1244,9 +1265,18 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
86
keysym = key_map[keycode];
89
+ param.value = keysym;
91
+ if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYSYM, ¶m) == NOTIFY_STOP)
94
+ if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
97
(*k_handler[type])(vc, keysym & 0xff, !down, regs);
99
+ atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, ¶m);
101
if (type != KT_SLOCK)
104
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
105
index edb7002..7d6beb1 100644
106
--- a/drivers/char/vt.c
107
+++ b/drivers/char/vt.c
109
#include <linux/pm.h>
110
#include <linux/font.h>
111
#include <linux/bitops.h>
112
+#include <linux/notifier.h>
115
#include <asm/system.h>
116
@@ -223,6 +224,35 @@ enum {
120
+ * Notifier list for console events.
122
+static ATOMIC_NOTIFIER_HEAD(vt_notifier_list);
124
+int register_vt_notifier(struct notifier_block *nb)
126
+ return atomic_notifier_chain_register(&vt_notifier_list, nb);
128
+EXPORT_SYMBOL_GPL(register_vt_notifier);
130
+int unregister_vt_notifier(struct notifier_block *nb)
132
+ return atomic_notifier_chain_unregister(&vt_notifier_list, nb);
134
+EXPORT_SYMBOL_GPL(unregister_vt_notifier);
136
+static void notify_write(struct vc_data *vc, unsigned int unicode)
138
+ struct vt_notifier_param param = { .vc = vc, unicode = unicode };
139
+ atomic_notifier_call_chain(&vt_notifier_list, VT_WRITE, ¶m);
142
+static void notify_update(struct vc_data *vc)
144
+ struct vt_notifier_param param = { .vc = vc };
145
+ atomic_notifier_call_chain(&vt_notifier_list, VT_UPDATE, ¶m);
149
* Low-Level Functions
152
@@ -718,6 +748,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
154
if (!vc_cons[currcons].d) {
156
+ struct vt_notifier_param param;
158
/* prevent users from taking too much memory */
159
if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
160
@@ -729,6 +760,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
161
/* due to the granularity of kmalloc, we waste some memory here */
162
/* the alloc is done in two steps, to optimize the common situation
163
of a 25x80 console (structsize=216, screenbuf_size=4000) */
165
/* although the numbers above are not valid since long ago, the
166
point is still up-to-date and the comment still has its value
167
even if only as a historical artifact. --mj, July 1998 */
168
@@ -746,6 +777,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
170
vc->vc_kmalloced = 1;
171
vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
172
+ atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m);
176
@@ -902,6 +934,8 @@ void vc_deallocate(unsigned int currcons)
178
if (vc_cons_allocated(currcons)) {
179
struct vc_data *vc = vc_cons[currcons].d;
180
+ struct vt_notifier_param param = { .vc = vc };
181
+ atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m);
182
vc->vc_sw->con_deinit(vc);
184
module_put(vc->vc_sw->owner);
185
@@ -1014,6 +1048,7 @@ static void lf(struct vc_data *vc)
186
vc->vc_pos += vc->vc_size_row;
188
vc->vc_need_wrap = 0;
189
+ notify_write(vc, '\n');
192
static void ri(struct vc_data *vc)
193
@@ -1034,6 +1069,7 @@ static inline void cr(struct vc_data *vc)
195
vc->vc_pos -= vc->vc_x << 1;
196
vc->vc_need_wrap = vc->vc_x = 0;
197
+ notify_write(vc, '\r');
200
static inline void bs(struct vc_data *vc)
201
@@ -1042,6 +1078,7 @@ static inline void bs(struct vc_data *vc)
204
vc->vc_need_wrap = 0;
205
+ notify_write(vc, '\b');
209
@@ -1588,6 +1625,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
212
vc->vc_pos += (vc->vc_x << 1);
213
+ notify_write(vc, '\t');
215
case 10: case 11: case 12:
217
@@ -2247,6 +2285,7 @@ rescan_last_byte:
221
+ notify_write(vc, c);
223
((vc->vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
224
(vc->vc_attr << 8) + tc,
225
@@ -2265,6 +2304,7 @@ rescan_last_byte:
226
do_con_trol(tty, vc, orig);
230
console_conditional_schedule();
231
release_console_sem();
233
@@ -2312,6 +2352,7 @@ static void console_callback(struct work_struct *ignored)
235
blank_timer_expired = 0;
237
+ notify_update(vc_cons[fg_console].d);
239
release_console_sem();
241
@@ -2413,6 +2454,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
244
scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
245
+ notify_write(vc, c);
247
if (myx == vc->vc_cols - 1) {
248
vc->vc_need_wrap = 1;
249
@@ -2431,6 +2473,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
256
clear_bit(0, &printing);
257
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h
258
index 7ddbc30..2c2b105 100644
259
--- a/include/linux/keyboard.h
260
+++ b/include/linux/keyboard.h
262
#define __LINUX_KEYBOARD_H
264
#include <linux/wait.h>
265
+#include <linux/notifier.h>
269
@@ -27,6 +28,16 @@ extern const int NR_TYPES;
270
extern const int max_vals[];
271
extern unsigned short *key_maps[MAX_NR_KEYMAPS];
272
extern unsigned short plain_map[NR_KEYS];
274
+struct keyboard_notifier_param {
275
+ struct vc_data *vc; /* VC on which the keyboard press was done */
276
+ int down; /* Pressure of the key? */
277
+ int shift; /* Current shift mask */
278
+ unsigned int value; /* keycode, unicode value or keysym */
281
+extern int register_keyboard_notifier(struct notifier_block *nb);
282
+extern int unregister_keyboard_notifier(struct notifier_block *nb);
285
#define MAX_NR_FUNC 256 /* max nr of strings assigned to keys */
286
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
287
index fad7ff1..fb88436 100644
288
--- a/include/linux/notifier.h
289
+++ b/include/linux/notifier.h
290
@@ -231,5 +231,20 @@ static inline int notifier_to_errno(int ret)
291
#define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */
292
#define PM_POST_SUSPEND 0x0004 /* Suspend finished */
294
+/* Console keyboard events.
295
+ * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and
297
+#define KBD_KEYCODE 0x0001 /* Keyboard keycode, called before any other */
298
+#define KBD_UNBOUND_KEYCODE 0x0002 /* Keyboard keycode which is not bound to any other */
299
+#define KBD_UNICODE 0x0003 /* Keyboard unicode */
300
+#define KBD_KEYSYM 0x0004 /* Keyboard keysym */
301
+#define KBD_POST_KEYSYM 0x0005 /* Called after keyboard keysym interpretation */
303
+/* Virtual Terminal events. */
304
+#define VT_ALLOCATE 0x0001 /* Console got allocated */
305
+#define VT_DEALLOCATE 0x0002 /* Console will be deallocated */
306
+#define VT_WRITE 0x0003 /* A char got output */
307
+#define VT_UPDATE 0x0004 /* A bigger update occurred */
309
#endif /* __KERNEL__ */
310
#endif /* _LINUX_NOTIFIER_H */
311
diff --git a/include/linux/vt.h b/include/linux/vt.h
312
index ba806e8..40216b0 100644
313
--- a/include/linux/vt.h
314
+++ b/include/linux/vt.h
320
+#include <linux/notifier.h>
322
+struct vt_notifier_param {
323
+ struct vc_data *vc; /* VC on which the update happened */
324
+ unsigned int c; /* Printed char */
327
+extern int register_vt_notifier(struct notifier_block *nb);
328
+extern int unregister_vt_notifier(struct notifier_block *nb);
332
* These constants are also useful for user-level apps (e.g., VC