diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2008-04-30 03:54:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:52 -0400 |
commit | f7511d5f66f01fc451747b24e79f3ada7a3af9af (patch) | |
tree | 934196c15e43077641e35286078a6753700a3e3d | |
parent | 730f412c08c13858f7681bac0a2770fbc9159fed (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.txt | 34 | ||||
-rw-r--r-- | Documentation/kernel-parameters.txt | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/ppc_ksyms.c | 3 | ||||
-rw-r--r-- | arch/ppc/kernel/ppc_ksyms.c | 3 | ||||
-rw-r--r-- | drivers/Kconfig | 2 | ||||
-rw-r--r-- | drivers/Makefile | 1 | ||||
-rw-r--r-- | drivers/accessibility/Kconfig | 23 | ||||
-rw-r--r-- | drivers/accessibility/Makefile | 1 | ||||
-rw-r--r-- | drivers/accessibility/braille/Makefile | 1 | ||||
-rw-r--r-- | drivers/accessibility/braille/braille_console.c | 397 | ||||
-rw-r--r-- | drivers/char/consolemap.c | 1 | ||||
-rw-r--r-- | drivers/char/keyboard.c | 2 | ||||
-rw-r--r-- | drivers/char/vt.c | 1 | ||||
-rw-r--r-- | include/linux/console.h | 4 | ||||
-rw-r--r-- | kernel/printk.c | 90 |
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 | |||
3 | To get early boot messages on a braille device (before userspace screen | ||
4 | readers can start), you first need to compile the support for the usual serial | ||
5 | console (see serial-console.txt), and for braille device (in Device Drivers - | ||
6 | Accessibility). | ||
7 | |||
8 | Then you need to specify a console=brl, option on the kernel command line, the | ||
9 | format is: | ||
10 | |||
11 | console=brl,serial_options... | ||
12 | |||
13 | where serial_options... are the same as described in serial-console.txt | ||
14 | |||
15 | So for instance you can use console=brl,ttyS0 if the braille device is connected | ||
16 | to the first serial port, and console=brl,ttyS0,115200 to override the baud rate | ||
17 | to 115200, etc. | ||
18 | |||
19 | By default, the braille device will just show the last kernel message (console | ||
20 | mode). To review previous messages, press the Insert key to switch to the VT | ||
21 | review mode. In review mode, the arrow keys permit to browse in the VT content, | ||
22 | page up/down keys go at the top/bottom of the screen, and the home key goes back | ||
23 | to the cursor, hence providing very basic screen reviewing facility. | ||
24 | |||
25 | Sound feedback can be obtained by adding the braille_console.sound=1 kernel | ||
26 | parameter. | ||
27 | |||
28 | For simplicity, only one braille console can be enabled, other uses of | ||
29 | console=brl,... will be discarded. Also note that it does not interfere with | ||
30 | the console selection mecanism described in serial-console.txt | ||
31 | |||
32 | For now, only the VisioBraille device is supported. | ||
33 | |||
34 | Samuel 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); | |||
133 | EXPORT_SYMBOL(cuda_request); | 133 | EXPORT_SYMBOL(cuda_request); |
134 | EXPORT_SYMBOL(cuda_poll); | 134 | EXPORT_SYMBOL(cuda_poll); |
135 | #endif /* CONFIG_ADB_CUDA */ | 135 | #endif /* CONFIG_ADB_CUDA */ |
136 | #ifdef CONFIG_VT | ||
137 | EXPORT_SYMBOL(kd_mksound); | ||
138 | #endif | ||
139 | EXPORT_SYMBOL(to_tm); | 136 | EXPORT_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) |
184 | EXPORT_SYMBOL(btext_update_display); | 184 | EXPORT_SYMBOL(btext_update_display); |
185 | #endif | 185 | #endif |
186 | #ifdef CONFIG_VT | ||
187 | EXPORT_SYMBOL(kd_mksound); | ||
188 | #endif | ||
189 | EXPORT_SYMBOL(to_tm); | 186 | EXPORT_SYMBOL(to_tm); |
190 | 187 | ||
191 | EXPORT_SYMBOL(pm_power_off); | 188 | EXPORT_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 | ||
85 | source "drivers/leds/Kconfig" | 85 | source "drivers/leds/Kconfig" |
86 | 86 | ||
87 | source "drivers/accessibility/Kconfig" | ||
88 | |||
87 | source "drivers/infiniband/Kconfig" | 89 | source "drivers/infiniband/Kconfig" |
88 | 90 | ||
89 | source "drivers/edac/Kconfig" | 91 | source "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/ | |||
70 | obj-$(CONFIG_PHONE) += telephony/ | 70 | obj-$(CONFIG_PHONE) += telephony/ |
71 | obj-$(CONFIG_MD) += md/ | 71 | obj-$(CONFIG_MD) += md/ |
72 | obj-$(CONFIG_BT) += bluetooth/ | 72 | obj-$(CONFIG_BT) += bluetooth/ |
73 | obj-$(CONFIG_ACCESSIBILITY) += accessibility/ | ||
73 | obj-$(CONFIG_ISDN) += isdn/ | 74 | obj-$(CONFIG_ISDN) += isdn/ |
74 | obj-$(CONFIG_EDAC) += edac/ | 75 | obj-$(CONFIG_EDAC) += edac/ |
75 | obj-$(CONFIG_MCA) += mca/ | 76 | obj-$(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 @@ | |||
1 | menuconfig ACCESSIBILITY | ||
2 | bool "Accessibility support" | ||
3 | ---help--- | ||
4 | Enable a submenu where accessibility items may be enabled. | ||
5 | |||
6 | If unsure, say N. | ||
7 | |||
8 | if ACCESSIBILITY | ||
9 | config 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 | |||
23 | endif # 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 | |||
39 | MODULE_AUTHOR("samuel.thibault@ens-lyon.org"); | ||
40 | MODULE_DESCRIPTION("braille device"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | /* | ||
44 | * Braille device support part. | ||
45 | */ | ||
46 | |||
47 | /* Emit various sounds */ | ||
48 | static int sound; | ||
49 | module_param(sound, bool, 0); | ||
50 | MODULE_PARM_DESC(sound, "emit sounds"); | ||
51 | |||
52 | static 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 | ||
61 | static u16 console_buf[WIDTH]; | ||
62 | static int console_cursor; | ||
63 | |||
64 | /* mini view of VC */ | ||
65 | static int vc_x, vc_y, lastvc_x, lastvc_y; | ||
66 | |||
67 | /* show console ? (or show VC) */ | ||
68 | static int console_show = 1; | ||
69 | /* pending newline ? */ | ||
70 | static int console_newline = 1; | ||
71 | static int lastVC = -1; | ||
72 | |||
73 | static struct console *braille_co; | ||
74 | |||
75 | /* Very VisioBraille-specific */ | ||
76 | static 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*/ | ||
124 | static 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 */ | ||
133 | static 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 */ | ||
140 | static 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 | |||
157 | static 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 | |||
275 | static struct notifier_block keyboard_notifier_block = { | ||
276 | .notifier_call = keyboard_notifier_call, | ||
277 | }; | ||
278 | |||
279 | static 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 | |||
354 | static 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 | |||
362 | int 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 | |||
382 | int braille_unregister_console(struct console *console) | ||
383 | { | ||
384 | if (braille_co != console) | ||
385 | return -EINVAL; | ||
386 | braille_co = NULL; | ||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static 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 | |||
397 | console_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 | } |
280 | EXPORT_SYMBOL_GPL(inverse_translate); | ||
280 | 281 | ||
281 | static void update_user_maps(void) | 282 | static 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[] = { | |||
110 | const int NR_TYPES = ARRAY_SIZE(max_vals); | 110 | const int NR_TYPES = ARRAY_SIZE(max_vals); |
111 | 111 | ||
112 | struct kbd_struct kbd_table[MAX_NR_CONSOLES]; | 112 | struct kbd_struct kbd_table[MAX_NR_CONSOLES]; |
113 | EXPORT_SYMBOL_GPL(kbd_table); | ||
113 | static struct kbd_struct *kbd = kbd_table; | 114 | static struct kbd_struct *kbd = kbd_table; |
114 | 115 | ||
115 | struct vt_spawn_console vt_spawn_con = { | 116 | struct 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 | } |
264 | EXPORT_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 | } |
4007 | EXPORT_SYMBOL_GPL(screen_glyph); | ||
4007 | 4008 | ||
4008 | /* used by vcs - note the word offset */ | 4009 | /* used by vcs - note the word offset */ |
4009 | unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed) | 4010 | unsigned 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 | ||
95 | struct console { | 96 | struct console { |
96 | char name[16]; | 97 | char name[16]; |
@@ -121,6 +122,9 @@ extern struct tty_driver *console_device(int *); | |||
121 | extern void console_stop(struct console *); | 122 | extern void console_stop(struct console *); |
122 | extern void console_start(struct console *); | 123 | extern void console_start(struct console *); |
123 | extern int is_console_locked(void); | 124 | extern int is_console_locked(void); |
125 | extern int braille_register_console(struct console *, int index, | ||
126 | char *console_options, char *braille_options); | ||
127 | extern int braille_unregister_console(struct console *); | ||
124 | 128 | ||
125 | extern int console_suspend_enabled; | 129 | extern 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 | ||
814 | static 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 | */ |
814 | static int __init console_setup(char *str) | 847 | static 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 | */ |
862 | int add_preferred_console(char *name, int idx, char *options) | 910 | int 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 | ||
888 | int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options) | 915 | int 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; |