aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2007-10-19 02:39:17 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 14:53:34 -0400
commitb293d758470e971253eec42b817bc9ef1213b228 (patch)
treeaafc6011762436cf3076798fee7140145908852c /drivers/char
parentfe9d4f576324999ac521c931f3b3eee0c8e45544 (diff)
Console events and accessibility
Some external modules like Speakup need to monitor console output. This adds a VT notifier that such modules can use to get console output events: allocation, deallocation, writes, other updates (cursor position, switch, etc.) [akpm@linux-foundation.org: fix headers_check] Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Cc: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/vt.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 1764c67b585f..7a5badfb7d84 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -99,6 +99,7 @@
99#include <linux/pm.h> 99#include <linux/pm.h>
100#include <linux/font.h> 100#include <linux/font.h>
101#include <linux/bitops.h> 101#include <linux/bitops.h>
102#include <linux/notifier.h>
102 103
103#include <asm/io.h> 104#include <asm/io.h>
104#include <asm/system.h> 105#include <asm/system.h>
@@ -223,6 +224,35 @@ enum {
223}; 224};
224 225
225/* 226/*
227 * Notifier list for console events.
228 */
229static ATOMIC_NOTIFIER_HEAD(vt_notifier_list);
230
231int register_vt_notifier(struct notifier_block *nb)
232{
233 return atomic_notifier_chain_register(&vt_notifier_list, nb);
234}
235EXPORT_SYMBOL_GPL(register_vt_notifier);
236
237int unregister_vt_notifier(struct notifier_block *nb)
238{
239 return atomic_notifier_chain_unregister(&vt_notifier_list, nb);
240}
241EXPORT_SYMBOL_GPL(unregister_vt_notifier);
242
243static void notify_write(struct vc_data *vc, unsigned int unicode)
244{
245 struct vt_notifier_param param = { .vc = vc, unicode = unicode };
246 atomic_notifier_call_chain(&vt_notifier_list, VT_WRITE, &param);
247}
248
249static void notify_update(struct vc_data *vc)
250{
251 struct vt_notifier_param param = { .vc = vc };
252 atomic_notifier_call_chain(&vt_notifier_list, VT_UPDATE, &param);
253}
254
255/*
226 * Low-Level Functions 256 * Low-Level Functions
227 */ 257 */
228 258
@@ -718,6 +748,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
718 return -ENXIO; 748 return -ENXIO;
719 if (!vc_cons[currcons].d) { 749 if (!vc_cons[currcons].d) {
720 struct vc_data *vc; 750 struct vc_data *vc;
751 struct vt_notifier_param param;
721 752
722 /* prevent users from taking too much memory */ 753 /* prevent users from taking too much memory */
723 if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE)) 754 if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
@@ -729,7 +760,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
729 /* although the numbers above are not valid since long ago, the 760 /* although the numbers above are not valid since long ago, the
730 point is still up-to-date and the comment still has its value 761 point is still up-to-date and the comment still has its value
731 even if only as a historical artifact. --mj, July 1998 */ 762 even if only as a historical artifact. --mj, July 1998 */
732 vc = kzalloc(sizeof(struct vc_data), GFP_KERNEL); 763 param.vc = vc = kzalloc(sizeof(struct vc_data), GFP_KERNEL);
733 if (!vc) 764 if (!vc)
734 return -ENOMEM; 765 return -ENOMEM;
735 vc_cons[currcons].d = vc; 766 vc_cons[currcons].d = vc;
@@ -746,6 +777,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
746 } 777 }
747 vc->vc_kmalloced = 1; 778 vc->vc_kmalloced = 1;
748 vc_init(vc, vc->vc_rows, vc->vc_cols, 1); 779 vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
780 atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
749 } 781 }
750 return 0; 782 return 0;
751} 783}
@@ -907,6 +939,8 @@ void vc_deallocate(unsigned int currcons)
907 939
908 if (vc_cons_allocated(currcons)) { 940 if (vc_cons_allocated(currcons)) {
909 struct vc_data *vc = vc_cons[currcons].d; 941 struct vc_data *vc = vc_cons[currcons].d;
942 struct vt_notifier_param param = { .vc = vc };
943 atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, &param);
910 vc->vc_sw->con_deinit(vc); 944 vc->vc_sw->con_deinit(vc);
911 put_pid(vc->vt_pid); 945 put_pid(vc->vt_pid);
912 module_put(vc->vc_sw->owner); 946 module_put(vc->vc_sw->owner);
@@ -1019,6 +1053,7 @@ static void lf(struct vc_data *vc)
1019 vc->vc_pos += vc->vc_size_row; 1053 vc->vc_pos += vc->vc_size_row;
1020 } 1054 }
1021 vc->vc_need_wrap = 0; 1055 vc->vc_need_wrap = 0;
1056 notify_write(vc, '\n');
1022} 1057}
1023 1058
1024static void ri(struct vc_data *vc) 1059static void ri(struct vc_data *vc)
@@ -1039,6 +1074,7 @@ static inline void cr(struct vc_data *vc)
1039{ 1074{
1040 vc->vc_pos -= vc->vc_x << 1; 1075 vc->vc_pos -= vc->vc_x << 1;
1041 vc->vc_need_wrap = vc->vc_x = 0; 1076 vc->vc_need_wrap = vc->vc_x = 0;
1077 notify_write(vc, '\r');
1042} 1078}
1043 1079
1044static inline void bs(struct vc_data *vc) 1080static inline void bs(struct vc_data *vc)
@@ -1047,6 +1083,7 @@ static inline void bs(struct vc_data *vc)
1047 vc->vc_pos -= 2; 1083 vc->vc_pos -= 2;
1048 vc->vc_x--; 1084 vc->vc_x--;
1049 vc->vc_need_wrap = 0; 1085 vc->vc_need_wrap = 0;
1086 notify_write(vc, '\b');
1050 } 1087 }
1051} 1088}
1052 1089
@@ -1593,6 +1630,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
1593 break; 1630 break;
1594 } 1631 }
1595 vc->vc_pos += (vc->vc_x << 1); 1632 vc->vc_pos += (vc->vc_x << 1);
1633 notify_write(vc, '\t');
1596 return; 1634 return;
1597 case 10: case 11: case 12: 1635 case 10: case 11: case 12:
1598 lf(vc); 1636 lf(vc);
@@ -2252,6 +2290,7 @@ rescan_last_byte:
2252 tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */ 2290 tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */
2253 if (tc < 0) tc = ' '; 2291 if (tc < 0) tc = ' ';
2254 } 2292 }
2293 notify_write(vc, c);
2255 2294
2256 if (inverse) { 2295 if (inverse) {
2257 FLUSH 2296 FLUSH
@@ -2274,6 +2313,7 @@ rescan_last_byte:
2274 release_console_sem(); 2313 release_console_sem();
2275 2314
2276out: 2315out:
2316 notify_update(vc);
2277 return n; 2317 return n;
2278#undef FLUSH 2318#undef FLUSH
2279} 2319}
@@ -2317,6 +2357,7 @@ static void console_callback(struct work_struct *ignored)
2317 do_blank_screen(0); 2357 do_blank_screen(0);
2318 blank_timer_expired = 0; 2358 blank_timer_expired = 0;
2319 } 2359 }
2360 notify_update(vc_cons[fg_console].d);
2320 2361
2321 release_console_sem(); 2362 release_console_sem();
2322} 2363}
@@ -2418,6 +2459,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
2418 continue; 2459 continue;
2419 } 2460 }
2420 scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos); 2461 scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
2462 notify_write(vc, c);
2421 cnt++; 2463 cnt++;
2422 if (myx == vc->vc_cols - 1) { 2464 if (myx == vc->vc_cols - 1) {
2423 vc->vc_need_wrap = 1; 2465 vc->vc_need_wrap = 1;
@@ -2436,6 +2478,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
2436 } 2478 }
2437 } 2479 }
2438 set_cursor(vc); 2480 set_cursor(vc);
2481 notify_update(vc);
2439 2482
2440quit: 2483quit:
2441 clear_bit(0, &printing); 2484 clear_bit(0, &printing);