aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2008-04-30 03:54:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 11:29:52 -0400
commitf7511d5f66f01fc451747b24e79f3ada7a3af9af (patch)
tree934196c15e43077641e35286078a6753700a3e3d
parent730f412c08c13858f7681bac0a2770fbc9159fed (diff)
Basic braille screen reader support
This adds a minimalistic braille screen reader support. This is meant to be used by blind people e.g. on boot failures or when / cannot be mounted etc and thus the userland screen readers can not work. [akpm@linux-foundation.org: fix exports] Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Cc: Jiri Kosina <jikos@jikos.cz> Cc: Dmitry Torokhov <dtor@mail.ru> Acked-by: Alan Cox <alan@redhat.com> Cc: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/braille-console.txt34
-rw-r--r--Documentation/kernel-parameters.txt5
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c3
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c3
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/accessibility/Kconfig23
-rw-r--r--drivers/accessibility/Makefile1
-rw-r--r--drivers/accessibility/braille/Makefile1
-rw-r--r--drivers/accessibility/braille/braille_console.c397
-rw-r--r--drivers/char/consolemap.c1
-rw-r--r--drivers/char/keyboard.c2
-rw-r--r--drivers/char/vt.c1
-rw-r--r--include/linux/console.h4
-rw-r--r--kernel/printk.c90
15 files changed, 538 insertions, 30 deletions
diff --git a/Documentation/braille-console.txt b/Documentation/braille-console.txt
new file mode 100644
index 000000000000..000b0fbdc105
--- /dev/null
+++ b/Documentation/braille-console.txt
@@ -0,0 +1,34 @@
1 Linux Braille Console
2
3To get early boot messages on a braille device (before userspace screen
4readers can start), you first need to compile the support for the usual serial
5console (see serial-console.txt), and for braille device (in Device Drivers -
6Accessibility).
7
8Then you need to specify a console=brl, option on the kernel command line, the
9format is:
10
11 console=brl,serial_options...
12
13where serial_options... are the same as described in serial-console.txt
14
15So for instance you can use console=brl,ttyS0 if the braille device is connected
16to the first serial port, and console=brl,ttyS0,115200 to override the baud rate
17to 115200, etc.
18
19By default, the braille device will just show the last kernel message (console
20mode). To review previous messages, press the Insert key to switch to the VT
21review mode. In review mode, the arrow keys permit to browse in the VT content,
22page up/down keys go at the top/bottom of the screen, and the home key goes back
23to the cursor, hence providing very basic screen reviewing facility.
24
25Sound feedback can be obtained by adding the braille_console.sound=1 kernel
26parameter.
27
28For simplicity, only one braille console can be enabled, other uses of
29console=brl,... will be discarded. Also note that it does not interfere with
30the console selection mecanism described in serial-console.txt
31
32For now, only the VisioBraille device is supported.
33
34Samuel Thibault <samuel.thibault@ens-lyon.org>
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 3ce193f86565..0ba0861b5d18 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -496,6 +496,11 @@ and is between 256 and 4096 characters. It is defined in the file
496 switching to the matching ttyS device later. The 496 switching to the matching ttyS device later. The
497 options are the same as for ttyS, above. 497 options are the same as for ttyS, above.
498 498
499 If the device connected to the port is not a TTY but a braille
500 device, prepend "brl," before the device type, for instance
501 console=brl,ttyS0
502 For now, only VisioBraille is supported.
503
499 earlycon= [KNL] Output early console device and options. 504 earlycon= [KNL] Output early console device and options.
500 uart[8250],io,<addr>[,options] 505 uart[8250],io,<addr>[,options]
501 uart[8250],mmio,<addr>[,options] 506 uart[8250],mmio,<addr>[,options]
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 09fcb50c45ae..cf6b5a7d8b3f 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -133,9 +133,6 @@ EXPORT_SYMBOL(adb_try_handler_change);
133EXPORT_SYMBOL(cuda_request); 133EXPORT_SYMBOL(cuda_request);
134EXPORT_SYMBOL(cuda_poll); 134EXPORT_SYMBOL(cuda_poll);
135#endif /* CONFIG_ADB_CUDA */ 135#endif /* CONFIG_ADB_CUDA */
136#ifdef CONFIG_VT
137EXPORT_SYMBOL(kd_mksound);
138#endif
139EXPORT_SYMBOL(to_tm); 136EXPORT_SYMBOL(to_tm);
140 137
141#ifdef CONFIG_PPC32 138#ifdef CONFIG_PPC32
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index d9036ef0b658..16ac11ca7ba0 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -183,9 +183,6 @@ EXPORT_SYMBOL(cuda_poll);
183#if defined(CONFIG_BOOTX_TEXT) 183#if defined(CONFIG_BOOTX_TEXT)
184EXPORT_SYMBOL(btext_update_display); 184EXPORT_SYMBOL(btext_update_display);
185#endif 185#endif
186#ifdef CONFIG_VT
187EXPORT_SYMBOL(kd_mksound);
188#endif
189EXPORT_SYMBOL(to_tm); 186EXPORT_SYMBOL(to_tm);
190 187
191EXPORT_SYMBOL(pm_power_off); 188EXPORT_SYMBOL(pm_power_off);
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 80f0ec91e2cf..59f33fa6af3e 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -84,6 +84,8 @@ source "drivers/memstick/Kconfig"
84 84
85source "drivers/leds/Kconfig" 85source "drivers/leds/Kconfig"
86 86
87source "drivers/accessibility/Kconfig"
88
87source "drivers/infiniband/Kconfig" 89source "drivers/infiniband/Kconfig"
88 90
89source "drivers/edac/Kconfig" 91source "drivers/edac/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index e5e394a7e6c0..f65deda72d61 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_WATCHDOG) += watchdog/
70obj-$(CONFIG_PHONE) += telephony/ 70obj-$(CONFIG_PHONE) += telephony/
71obj-$(CONFIG_MD) += md/ 71obj-$(CONFIG_MD) += md/
72obj-$(CONFIG_BT) += bluetooth/ 72obj-$(CONFIG_BT) += bluetooth/
73obj-$(CONFIG_ACCESSIBILITY) += accessibility/
73obj-$(CONFIG_ISDN) += isdn/ 74obj-$(CONFIG_ISDN) += isdn/
74obj-$(CONFIG_EDAC) += edac/ 75obj-$(CONFIG_EDAC) += edac/
75obj-$(CONFIG_MCA) += mca/ 76obj-$(CONFIG_MCA) += mca/
diff --git a/drivers/accessibility/Kconfig b/drivers/accessibility/Kconfig
new file mode 100644
index 000000000000..1264c4b98094
--- /dev/null
+++ b/drivers/accessibility/Kconfig
@@ -0,0 +1,23 @@
1menuconfig ACCESSIBILITY
2 bool "Accessibility support"
3 ---help---
4 Enable a submenu where accessibility items may be enabled.
5
6 If unsure, say N.
7
8if ACCESSIBILITY
9config A11Y_BRAILLE_CONSOLE
10 bool "Console on braille device"
11 depends on VT
12 depends on SERIAL_CORE_CONSOLE
13 ---help---
14 Enables console output on a braille device connected to a 8250
15 serial port. For now only the VisioBraille device is supported.
16
17 To actually enable it, you need to pass option
18 console=brl,ttyS0
19 to the kernel. Options are the same as for serial console.
20
21 If unsure, say N.
22
23endif # ACCESSIBILITY
diff --git a/drivers/accessibility/Makefile b/drivers/accessibility/Makefile
new file mode 100644
index 000000000000..72b01a46546f
--- /dev/null
+++ b/drivers/accessibility/Makefile
@@ -0,0 +1 @@
obj-y += braille/
diff --git a/drivers/accessibility/braille/Makefile b/drivers/accessibility/braille/Makefile
new file mode 100644
index 000000000000..2e9f16c91347
--- /dev/null
+++ b/drivers/accessibility/braille/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille_console.o
diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
new file mode 100644
index 000000000000..0a5f6b2114c5
--- /dev/null
+++ b/drivers/accessibility/braille/braille_console.c
@@ -0,0 +1,397 @@
1/*
2 * Minimalistic braille device kernel support.
3 *
4 * By default, shows console messages on the braille device.
5 * Pressing Insert switches to VC browsing.
6 *
7 * Copyright (C) Samuel Thibault <samuel.thibault@ens-lyon.org>
8 *
9 * This program is free software ; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation ; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY ; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the program ; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/autoconf.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/console.h>
29#include <linux/notifier.h>
30
31#include <linux/selection.h>
32#include <linux/vt_kern.h>
33#include <linux/consolemap.h>
34
35#include <linux/keyboard.h>
36#include <linux/kbd_kern.h>
37#include <linux/input.h>
38
39MODULE_AUTHOR("samuel.thibault@ens-lyon.org");
40MODULE_DESCRIPTION("braille device");
41MODULE_LICENSE("GPL");
42
43/*
44 * Braille device support part.
45 */
46
47/* Emit various sounds */
48static int sound;
49module_param(sound, bool, 0);
50MODULE_PARM_DESC(sound, "emit sounds");
51
52static void beep(unsigned int freq)
53{
54 if (sound)
55 kd_mksound(freq, HZ/10);
56}
57
58/* mini console */
59#define WIDTH 40
60#define BRAILLE_KEY KEY_INSERT
61static u16 console_buf[WIDTH];
62static int console_cursor;
63
64/* mini view of VC */
65static int vc_x, vc_y, lastvc_x, lastvc_y;
66
67/* show console ? (or show VC) */
68static int console_show = 1;
69/* pending newline ? */
70static int console_newline = 1;
71static int lastVC = -1;
72
73static struct console *braille_co;
74
75/* Very VisioBraille-specific */
76static void braille_write(u16 *buf)
77{
78 static u16 lastwrite[WIDTH];
79 unsigned char data[1 + 1 + 2*WIDTH + 2 + 1], csum = 0, *c;
80 u16 out;
81 int i;
82
83 if (!braille_co)
84 return;
85
86 if (!memcmp(lastwrite, buf, WIDTH * sizeof(*buf)))
87 return;
88 memcpy(lastwrite, buf, WIDTH * sizeof(*buf));
89
90#define SOH 1
91#define STX 2
92#define ETX 2
93#define EOT 4
94#define ENQ 5
95 data[0] = STX;
96 data[1] = '>';
97 csum ^= '>';
98 c = &data[2];
99 for (i = 0; i < WIDTH; i++) {
100 out = buf[i];
101 if (out >= 0x100)
102 out = '?';
103 else if (out == 0x00)
104 out = ' ';
105 csum ^= out;
106 if (out <= 0x05) {
107 *c++ = SOH;
108 out |= 0x40;
109 }
110 *c++ = out;
111 }
112
113 if (csum <= 0x05) {
114 *c++ = SOH;
115 csum |= 0x40;
116 }
117 *c++ = csum;
118 *c++ = ETX;
119
120 braille_co->write(braille_co, data, c - data);
121}
122
123/* Follow the VC cursor*/
124static void vc_follow_cursor(struct vc_data *vc)
125{
126 vc_x = vc->vc_x - (vc->vc_x % WIDTH);
127 vc_y = vc->vc_y;
128 lastvc_x = vc->vc_x;
129 lastvc_y = vc->vc_y;
130}
131
132/* Maybe the VC cursor moved, if so follow it */
133static void vc_maybe_cursor_moved(struct vc_data *vc)
134{
135 if (vc->vc_x != lastvc_x || vc->vc_y != lastvc_y)
136 vc_follow_cursor(vc);
137}
138
139/* Show portion of VC at vc_x, vc_y */
140static void vc_refresh(struct vc_data *vc)
141{
142 u16 buf[WIDTH];
143 int i;
144
145 for (i = 0; i < WIDTH; i++) {
146 u16 glyph = screen_glyph(vc,
147 2 * (vc_x + i) + vc_y * vc->vc_size_row);
148 buf[i] = inverse_translate(vc, glyph, 1);
149 }
150 braille_write(buf);
151}
152
153/*
154 * Link to keyboard
155 */
156
157static int keyboard_notifier_call(struct notifier_block *blk,
158 unsigned long code, void *_param)
159{
160 struct keyboard_notifier_param *param = _param;
161 struct vc_data *vc = param->vc;
162 int ret = NOTIFY_OK;
163
164 if (!param->down)
165 return ret;
166
167 switch (code) {
168 case KBD_KEYCODE:
169 if (console_show) {
170 if (param->value == BRAILLE_KEY) {
171 console_show = 0;
172 beep(880);
173 vc_maybe_cursor_moved(vc);
174 vc_refresh(vc);
175 ret = NOTIFY_STOP;
176 }
177 } else {
178 ret = NOTIFY_STOP;
179 switch (param->value) {
180 case KEY_INSERT:
181 beep(440);
182 console_show = 1;
183 lastVC = -1;
184 braille_write(console_buf);
185 break;
186 case KEY_LEFT:
187 if (vc_x > 0) {
188 vc_x -= WIDTH;
189 if (vc_x < 0)
190 vc_x = 0;
191 } else if (vc_y >= 1) {
192 beep(880);
193 vc_y--;
194 vc_x = vc->vc_cols-WIDTH;
195 } else
196 beep(220);
197 break;
198 case KEY_RIGHT:
199 if (vc_x + WIDTH < vc->vc_cols) {
200 vc_x += WIDTH;
201 } else if (vc_y + 1 < vc->vc_rows) {
202 beep(880);
203 vc_y++;
204 vc_x = 0;
205 } else
206 beep(220);
207 break;
208 case KEY_DOWN:
209 if (vc_y + 1 < vc->vc_rows)
210 vc_y++;
211 else
212 beep(220);
213 break;
214 case KEY_UP:
215 if (vc_y >= 1)
216 vc_y--;
217 else
218 beep(220);
219 break;
220 case KEY_HOME:
221 vc_follow_cursor(vc);
222 break;
223 case KEY_PAGEUP:
224 vc_x = 0;
225 vc_y = 0;
226 break;
227 case KEY_PAGEDOWN:
228 vc_x = 0;
229 vc_y = vc->vc_rows-1;
230 break;
231 default:
232 ret = NOTIFY_OK;
233 break;
234 }
235 if (ret == NOTIFY_STOP)
236 vc_refresh(vc);
237 }
238 break;
239 case KBD_POST_KEYSYM:
240 {
241 unsigned char type = KTYP(param->value) - 0xf0;
242 if (type == KT_SPEC) {
243 unsigned char val = KVAL(param->value);
244 int on_off = -1;
245
246 switch (val) {
247 case KVAL(K_CAPS):
248 on_off = vc_kbd_led(kbd_table + fg_console,
249 VC_CAPSLOCK);
250 break;
251 case KVAL(K_NUM):
252 on_off = vc_kbd_led(kbd_table + fg_console,
253 VC_NUMLOCK);
254 break;
255 case KVAL(K_HOLD):
256 on_off = vc_kbd_led(kbd_table + fg_console,
257 VC_SCROLLOCK);
258 break;
259 }
260 if (on_off == 1)
261 beep(880);
262 else if (on_off == 0)
263 beep(440);
264 }
265 }
266 case KBD_UNBOUND_KEYCODE:
267 case KBD_UNICODE:
268 case KBD_KEYSYM:
269 /* Unused */
270 break;
271 }
272 return ret;
273}
274
275static struct notifier_block keyboard_notifier_block = {
276 .notifier_call = keyboard_notifier_call,
277};
278
279static int vt_notifier_call(struct notifier_block *blk,
280 unsigned long code, void *_param)
281{
282 struct vt_notifier_param *param = _param;
283 struct vc_data *vc = param->vc;
284 switch (code) {
285 case VT_ALLOCATE:
286 break;
287 case VT_DEALLOCATE:
288 break;
289 case VT_WRITE:
290 {
291 unsigned char c = param->c;
292 if (vc->vc_num != fg_console)
293 break;
294 switch (c) {
295 case '\b':
296 case 127:
297 if (console_cursor > 0) {
298 console_cursor--;
299 console_buf[console_cursor] = ' ';
300 }
301 break;
302 case '\n':
303 case '\v':
304 case '\f':
305 case '\r':
306 console_newline = 1;
307 break;
308 case '\t':
309 c = ' ';
310 /* Fallthrough */
311 default:
312 if (c < 32)
313 /* Ignore other control sequences */
314 break;
315 if (console_newline) {
316 memset(console_buf, 0, sizeof(console_buf));
317 console_cursor = 0;
318 console_newline = 0;
319 }
320 if (console_cursor == WIDTH)
321 memmove(console_buf, &console_buf[1],
322 (WIDTH-1) * sizeof(*console_buf));
323 else
324 console_cursor++;
325 console_buf[console_cursor-1] = c;
326 break;
327 }
328 if (console_show)
329 braille_write(console_buf);
330 else {
331 vc_maybe_cursor_moved(vc);
332 vc_refresh(vc);
333 }
334 break;
335 }
336 case VT_UPDATE:
337 /* Maybe a VT switch, flush */
338 if (console_show) {
339 if (vc->vc_num != lastVC) {
340 lastVC = vc->vc_num;
341 memset(console_buf, 0, sizeof(console_buf));
342 console_cursor = 0;
343 braille_write(console_buf);
344 }
345 } else {
346 vc_maybe_cursor_moved(vc);
347 vc_refresh(vc);
348 }
349 break;
350 }
351 return NOTIFY_OK;
352}
353
354static struct notifier_block vt_notifier_block = {
355 .notifier_call = vt_notifier_call,
356};
357
358/*
359 * Called from printk.c when console=brl is given
360 */
361
362int braille_register_console(struct console *console, int index,
363 char *console_options, char *braille_options)
364{
365 int ret;
366 if (!console_options)
367 /* Only support VisioBraille for now */
368 console_options = "57600o8";
369 if (braille_co)
370 return -ENODEV;
371 if (console->setup) {
372 ret = console->setup(console, console_options);
373 if (ret != 0)
374 return ret;
375 }
376 console->flags |= CON_ENABLED;
377 console->index = index;
378 braille_co = console;
379 return 0;
380}
381
382int braille_unregister_console(struct console *console)
383{
384 if (braille_co != console)
385 return -EINVAL;
386 braille_co = NULL;
387 return 0;
388}
389
390static int __init braille_init(void)
391{
392 register_keyboard_notifier(&keyboard_notifier_block);
393 register_vt_notifier(&vt_notifier_block);
394 return 0;
395}
396
397console_initcall(braille_init);
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index 6b104e45a322..4246b8e36cb3 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -277,6 +277,7 @@ u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
277 return p->inverse_translations[m][glyph]; 277 return p->inverse_translations[m][glyph];
278 } 278 }
279} 279}
280EXPORT_SYMBOL_GPL(inverse_translate);
280 281
281static void update_user_maps(void) 282static void update_user_maps(void)
282{ 283{
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index d1c50b3302e5..7f7e798c1384 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -110,6 +110,7 @@ const int max_vals[] = {
110const int NR_TYPES = ARRAY_SIZE(max_vals); 110const int NR_TYPES = ARRAY_SIZE(max_vals);
111 111
112struct kbd_struct kbd_table[MAX_NR_CONSOLES]; 112struct kbd_struct kbd_table[MAX_NR_CONSOLES];
113EXPORT_SYMBOL_GPL(kbd_table);
113static struct kbd_struct *kbd = kbd_table; 114static struct kbd_struct *kbd = kbd_table;
114 115
115struct vt_spawn_console vt_spawn_con = { 116struct vt_spawn_console vt_spawn_con = {
@@ -260,6 +261,7 @@ void kd_mksound(unsigned int hz, unsigned int ticks)
260 } else 261 } else
261 kd_nosound(0); 262 kd_nosound(0);
262} 263}
264EXPORT_SYMBOL(kd_mksound);
263 265
264/* 266/*
265 * Setting the keyboard rate. 267 * Setting the keyboard rate.
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 71cf203d282d..e458b08139af 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -4004,6 +4004,7 @@ u16 screen_glyph(struct vc_data *vc, int offset)
4004 c |= 0x100; 4004 c |= 0x100;
4005 return c; 4005 return c;
4006} 4006}
4007EXPORT_SYMBOL_GPL(screen_glyph);
4007 4008
4008/* used by vcs - note the word offset */ 4009/* used by vcs - note the word offset */
4009unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed) 4010unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed)
diff --git a/include/linux/console.h b/include/linux/console.h
index a5f88a6a259d..a4f27fbdf549 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -91,6 +91,7 @@ void give_up_console(const struct consw *sw);
91#define CON_ENABLED (4) 91#define CON_ENABLED (4)
92#define CON_BOOT (8) 92#define CON_BOOT (8)
93#define CON_ANYTIME (16) /* Safe to call when cpu is offline */ 93#define CON_ANYTIME (16) /* Safe to call when cpu is offline */
94#define CON_BRL (32) /* Used for a braille device */
94 95
95struct console { 96struct console {
96 char name[16]; 97 char name[16];
@@ -121,6 +122,9 @@ extern struct tty_driver *console_device(int *);
121extern void console_stop(struct console *); 122extern void console_stop(struct console *);
122extern void console_start(struct console *); 123extern void console_start(struct console *);
123extern int is_console_locked(void); 124extern int is_console_locked(void);
125extern int braille_register_console(struct console *, int index,
126 char *console_options, char *braille_options);
127extern int braille_unregister_console(struct console *);
124 128
125extern int console_suspend_enabled; 129extern int console_suspend_enabled;
126 130
diff --git a/kernel/printk.c b/kernel/printk.c
index 0d232589a923..e61346faf6a5 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -111,6 +111,9 @@ struct console_cmdline
111 char name[8]; /* Name of the driver */ 111 char name[8]; /* Name of the driver */
112 int index; /* Minor dev. to use */ 112 int index; /* Minor dev. to use */
113 char *options; /* Options for the driver */ 113 char *options; /* Options for the driver */
114#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
115 char *brl_options; /* Options for braille driver */
116#endif
114}; 117};
115 118
116#define MAX_CMDLINECONSOLES 8 119#define MAX_CMDLINECONSOLES 8
@@ -808,15 +811,60 @@ static void call_console_drivers(unsigned start, unsigned end)
808 811
809#endif 812#endif
810 813
814static int __add_preferred_console(char *name, int idx, char *options,
815 char *brl_options)
816{
817 struct console_cmdline *c;
818 int i;
819
820 /*
821 * See if this tty is not yet registered, and
822 * if we have a slot free.
823 */
824 for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
825 if (strcmp(console_cmdline[i].name, name) == 0 &&
826 console_cmdline[i].index == idx) {
827 if (!brl_options)
828 selected_console = i;
829 return 0;
830 }
831 if (i == MAX_CMDLINECONSOLES)
832 return -E2BIG;
833 if (!brl_options)
834 selected_console = i;
835 c = &console_cmdline[i];
836 strlcpy(c->name, name, sizeof(c->name));
837 c->options = options;
838#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
839 c->brl_options = brl_options;
840#endif
841 c->index = idx;
842 return 0;
843}
811/* 844/*
812 * Set up a list of consoles. Called from init/main.c 845 * Set up a list of consoles. Called from init/main.c
813 */ 846 */
814static int __init console_setup(char *str) 847static int __init console_setup(char *str)
815{ 848{
816 char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for index */ 849 char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for index */
817 char *s, *options; 850 char *s, *options, *brl_options = NULL;
818 int idx; 851 int idx;
819 852
853#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
854 if (!memcmp(str, "brl,", 4)) {
855 brl_options = "";
856 str += 4;
857 } else if (!memcmp(str, "brl=", 4)) {
858 brl_options = str + 4;
859 str = strchr(brl_options, ',');
860 if (!str) {
861 printk(KERN_ERR "need port name after brl=\n");
862 return 1;
863 }
864 *(str++) = 0;
865 }
866#endif
867
820 /* 868 /*
821 * Decode str into name, index, options. 869 * Decode str into name, index, options.
822 */ 870 */
@@ -841,7 +889,7 @@ static int __init console_setup(char *str)
841 idx = simple_strtoul(s, NULL, 10); 889 idx = simple_strtoul(s, NULL, 10);
842 *s = 0; 890 *s = 0;
843 891
844 add_preferred_console(buf, idx, options); 892 __add_preferred_console(buf, idx, options, brl_options);
845 return 1; 893 return 1;
846} 894}
847__setup("console=", console_setup); 895__setup("console=", console_setup);
@@ -861,28 +909,7 @@ __setup("console=", console_setup);
861 */ 909 */
862int add_preferred_console(char *name, int idx, char *options) 910int add_preferred_console(char *name, int idx, char *options)
863{ 911{
864 struct console_cmdline *c; 912 return __add_preferred_console(name, idx, options, NULL);
865 int i;
866
867 /*
868 * See if this tty is not yet registered, and
869 * if we have a slot free.
870 */
871 for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
872 if (strcmp(console_cmdline[i].name, name) == 0 &&
873 console_cmdline[i].index == idx) {
874 selected_console = i;
875 return 0;
876 }
877 if (i == MAX_CMDLINECONSOLES)
878 return -E2BIG;
879 selected_console = i;
880 c = &console_cmdline[i];
881 memcpy(c->name, name, sizeof(c->name));
882 c->name[sizeof(c->name) - 1] = 0;
883 c->options = options;
884 c->index = idx;
885 return 0;
886} 913}
887 914
888int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options) 915int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
@@ -1163,6 +1190,16 @@ void register_console(struct console *console)
1163 continue; 1190 continue;
1164 if (console->index < 0) 1191 if (console->index < 0)
1165 console->index = console_cmdline[i].index; 1192 console->index = console_cmdline[i].index;
1193#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
1194 if (console_cmdline[i].brl_options) {
1195 console->flags |= CON_BRL;
1196 braille_register_console(console,
1197 console_cmdline[i].index,
1198 console_cmdline[i].options,
1199 console_cmdline[i].brl_options);
1200 return;
1201 }
1202#endif
1166 if (console->setup && 1203 if (console->setup &&
1167 console->setup(console, console_cmdline[i].options) != 0) 1204 console->setup(console, console_cmdline[i].options) != 0)
1168 break; 1205 break;
@@ -1221,6 +1258,11 @@ int unregister_console(struct console *console)
1221 struct console *a, *b; 1258 struct console *a, *b;
1222 int res = 1; 1259 int res = 1;
1223 1260
1261#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
1262 if (console->flags & CON_BRL)
1263 return braille_unregister_console(console);
1264#endif
1265
1224 acquire_console_sem(); 1266 acquire_console_sem();
1225 if (console_drivers == console) { 1267 if (console_drivers == console) {
1226 console_drivers=console->next; 1268 console_drivers=console->next;