diff options
-rw-r--r-- | drivers/char/keyboard.c | 42 | ||||
-rw-r--r-- | include/linux/keyboard.h | 11 | ||||
-rw-r--r-- | include/linux/notifier.h | 9 |
3 files changed, 56 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 | ||
46 | extern void ctrl_alt_del(void); | 47 | extern void ctrl_alt_del(void); |
47 | 48 | ||
@@ -81,7 +82,8 @@ void compute_shiftstate(void); | |||
81 | typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, | 82 | typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, |
82 | char up_flag); | 83 | char up_flag); |
83 | static k_handler_fn K_HANDLERS; | 84 | static k_handler_fn K_HANDLERS; |
84 | static k_handler_fn *k_handler[16] = { K_HANDLERS }; | 85 | k_handler_fn *k_handler[16] = { K_HANDLERS }; |
86 | EXPORT_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; | |||
160 | static int sysrq_alt; | 162 | static int sysrq_alt; |
161 | 163 | ||
162 | /* | 164 | /* |
165 | * Notifier list for console keyboard events | ||
166 | */ | ||
167 | static ATOMIC_NOTIFIER_HEAD(keyboard_notifier_list); | ||
168 | |||
169 | int register_keyboard_notifier(struct notifier_block *nb) | ||
170 | { | ||
171 | return atomic_notifier_chain_register(&keyboard_notifier_list, nb); | ||
172 | } | ||
173 | EXPORT_SYMBOL_GPL(register_keyboard_notifier); | ||
174 | |||
175 | int unregister_keyboard_notifier(struct notifier_block *nb) | ||
176 | { | ||
177 | return atomic_notifier_chain_unregister(&keyboard_notifier_list, nb); | ||
178 | } | ||
179 | EXPORT_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, ¶m) == NOTIFY_STOP || !key_map) { |
1244 | atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNBOUND_KEYCODE, ¶m); | ||
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, ¶m) == 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, ¶m) == 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, ¶m); | ||
1290 | |||
1261 | if (type != KT_SLOCK) | 1291 | if (type != KT_SLOCK) |
1262 | kbd->slockstate = 0; | 1292 | kbd->slockstate = 0; |
1263 | } | 1293 | } |
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h index 33b5c2e325b9..65c2d70853e9 100644 --- a/include/linux/keyboard.h +++ b/include/linux/keyboard.h | |||
@@ -23,10 +23,21 @@ | |||
23 | #define MAX_NR_OF_USER_KEYMAPS 256 /* should be at least 7 */ | 23 | #define MAX_NR_OF_USER_KEYMAPS 256 /* should be at least 7 */ |
24 | 24 | ||
25 | #ifdef __KERNEL__ | 25 | #ifdef __KERNEL__ |
26 | struct notifier_block; | ||
26 | extern const int NR_TYPES; | 27 | extern const int NR_TYPES; |
27 | extern const int max_vals[]; | 28 | extern const int max_vals[]; |
28 | extern unsigned short *key_maps[MAX_NR_KEYMAPS]; | 29 | extern unsigned short *key_maps[MAX_NR_KEYMAPS]; |
29 | extern unsigned short plain_map[NR_KEYS]; | 30 | extern unsigned short plain_map[NR_KEYS]; |
31 | |||
32 | struct keyboard_notifier_param { | ||
33 | struct vc_data *vc; /* VC on which the keyboard press was done */ | ||
34 | int down; /* Pressure of the key? */ | ||
35 | int shift; /* Current shift mask */ | ||
36 | unsigned int value; /* keycode, unicode value or keysym */ | ||
37 | }; | ||
38 | |||
39 | extern int register_keyboard_notifier(struct notifier_block *nb); | ||
40 | extern int unregister_keyboard_notifier(struct notifier_block *nb); | ||
30 | #endif | 41 | #endif |
31 | 42 | ||
32 | #define MAX_NR_FUNC 256 /* max nr of strings assigned to keys */ | 43 | #define MAX_NR_FUNC 256 /* max nr of strings assigned to keys */ |
diff --git a/include/linux/notifier.h b/include/linux/notifier.h index fad7ff17e468..bd3788084fa9 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h | |||
@@ -231,5 +231,14 @@ static inline int notifier_to_errno(int ret) | |||
231 | #define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */ | 231 | #define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */ |
232 | #define PM_POST_SUSPEND 0x0004 /* Suspend finished */ | 232 | #define PM_POST_SUSPEND 0x0004 /* Suspend finished */ |
233 | 233 | ||
234 | /* Console keyboard events. | ||
235 | * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and | ||
236 | * KBD_KEYSYM. */ | ||
237 | #define KBD_KEYCODE 0x0001 /* Keyboard keycode, called before any other */ | ||
238 | #define KBD_UNBOUND_KEYCODE 0x0002 /* Keyboard keycode which is not bound to any other */ | ||
239 | #define KBD_UNICODE 0x0003 /* Keyboard unicode */ | ||
240 | #define KBD_KEYSYM 0x0004 /* Keyboard keysym */ | ||
241 | #define KBD_POST_KEYSYM 0x0005 /* Called after keyboard keysym interpretation */ | ||
242 | |||
234 | #endif /* __KERNEL__ */ | 243 | #endif /* __KERNEL__ */ |
235 | #endif /* _LINUX_NOTIFIER_H */ | 244 | #endif /* _LINUX_NOTIFIER_H */ |