/[linux-patches]/genpatches-2.6/trunk/2.6.22-pre/4400_speakup-20070426.patch
Gentoo

Contents of /genpatches-2.6/trunk/2.6.22-pre/4400_speakup-20070426.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 963 - (show annotations) (download)
Sat May 19 09:58:57 2007 UTC (11 years, 5 months ago) by phreak
File size: 356474 byte(s)
Starting branch for 2.6.22.
1 speakup CVS for Linux 2.6.21
2 Generated by dsd on Thu Apr 26 11:33:45 EDT 2007
3 ---
4 Documentation/speakup/DefaultKeyAssignments | 46
5 Documentation/speakup/INSTALLATION | 108 +
6 Documentation/speakup/README | 98
7 Documentation/speakup/keymap-tutorial | 140 +
8 Documentation/speakup/spkguide.txt | 1279 ++++++++++++
9 MAINTAINERS | 7
10 arch/arm/Kconfig | 1
11 drivers/Kconfig | 2
12 drivers/char/Makefile | 1
13 drivers/char/consolemap.c | 1
14 drivers/char/keyboard.c | 44
15 drivers/char/speakup/Config.in | 26
16 drivers/char/speakup/Kconfig | 211 ++
17 drivers/char/speakup/Makefile | 61
18 drivers/char/speakup/cvsversion.h | 1
19 drivers/char/speakup/dtload.c | 553 +++++
20 drivers/char/speakup/dtload.h | 57
21 drivers/char/speakup/dtpc_reg.h | 132 +
22 drivers/char/speakup/genmap.c | 204 +
23 drivers/char/speakup/keyinfo.h | 120 +
24 drivers/char/speakup/makemapdata.c | 156 +
25 drivers/char/speakup/mod_code.c | 22
26 drivers/char/speakup/serialio.h | 18
27 drivers/char/speakup/speakup.c | 2877 ++++++++++++++++++++++++++++
28 drivers/char/speakup/speakup_acnt.h | 16
29 drivers/char/speakup/speakup_acntpc.c | 161 +
30 drivers/char/speakup/speakup_acntsa.c | 184 +
31 drivers/char/speakup/speakup_apollo.c | 196 +
32 drivers/char/speakup/speakup_audptr.c | 202 +
33 drivers/char/speakup/speakup_bns.c | 175 +
34 drivers/char/speakup/speakup_decext.c | 206 ++
35 drivers/char/speakup/speakup_decpc.c | 243 ++
36 drivers/char/speakup/speakup_dectlk.c | 280 ++
37 drivers/char/speakup/speakup_drvcommon.c | 1031 ++++++++++
38 drivers/char/speakup/speakup_dtlk.c | 233 ++
39 drivers/char/speakup/speakup_dtlk.h | 54
40 drivers/char/speakup/speakup_keyhelp.c | 288 ++
41 drivers/char/speakup/speakup_keypc.c | 190 +
42 drivers/char/speakup/speakup_ltlk.c | 229 ++
43 drivers/char/speakup/speakup_sftsyn.c | 206 ++
44 drivers/char/speakup/speakup_spkout.c | 201 +
45 drivers/char/speakup/speakup_txprt.c | 196 +
46 drivers/char/speakup/speakupconf | 51
47 drivers/char/speakup/speakupmap.h | 65
48 drivers/char/speakup/speakupmap.map | 93
49 drivers/char/speakup/spk_con_module.h | 43
50 drivers/char/speakup/spk_priv.h | 263 ++
51 drivers/char/speakup/synthlist.h | 51
52 drivers/char/vt.c | 18
53 include/linux/keyboard.h | 2
54 include/linux/miscdevice.h | 1
55 include/linux/speakup.h | 35
56 52 files changed, 11074 insertions(+), 4 deletions(-)
57
58 --- /dev/null
59 +++ b/Documentation/speakup/DefaultKeyAssignments
60 @@ -0,0 +1,46 @@
61 +This file is intended to give you an overview of the default keys used
62 +by speakup for it's review functions. You may change them to be
63 +anything you want but that will take some familiarity with key
64 +mapping.
65 +
66 +We have remapped the insert or zero key on the keypad to act as a
67 +shift key. Well, actually as an altgr key. So in the following list
68 +InsKeyPad-period means hold down the insert key like a shift key and
69 +hit the keypad period.
70 +
71 +KeyPad-8 Say current Line
72 +InsKeyPad-8 say from top of screen to reading cursor.
73 +KeyPad-7 Say Previous Line (UP one line)
74 +KeyPad-9 Say Next Line (down one line)
75 +KeyPad-5 Say Current Word
76 +InsKeyPad-5 Spell Current Word
77 +KeyPad-4 Say Previous Word (left one word)
78 +InsKeyPad-4 say from left edge of line to reading cursor.
79 +KeyPad-6 Say Next Word (right one word)
80 +InsKeyPad-6 Say from reading cursor to right edge of line.
81 +KeyPad-2 Say Current Letter
82 +InsKeyPad-2 say current letter phonetically
83 +KeyPad-1 Say Previous Character (left one letter)
84 +KeyPad-3 Say Next Character (right one letter)
85 +KeyPad-plus Say Entire Screen
86 +InsKeyPad-plus Say from reading cursor line to bottom of screen.
87 +KeyPad-Minus Park reading cursor (toggle)
88 +InsKeyPad-minus Say character hex and decimal value.
89 +KeyPad-period Say Position (current line, position and console)
90 +InsKeyPad-period say colour attributes of current position.
91 +InsKeyPad-9 Move reading cursor to top of screen (insert pgup)
92 +InsKeyPad-3 Move reading cursor to bottom of screen (insert pgdn)
93 +InsKeyPad-7 Move reading cursor to left edge of screen (insert home)
94 +InsKeyPad-1 Move reading cursor to right edge of screen (insert end)
95 +ControlKeyPad-1 Move reading cursor to last character on current line.
96 +KeyPad-Enter Shut Up (until another key is hit) and sync reading cursor
97 +InsKeyPad-Enter Shut Up (until toggled back on).
98 +InsKeyPad-star n<x|y> go to line (y) or column (x). Where 'n' is any
99 + allowed value for the row or column for your current screen.
100 +KeyPad-/ Mark and Cut screen region.
101 +InsKeyPad-/ Paste screen region into any console.
102 +
103 +Hitting any key while speakup is outputting speech will quiet the
104 +synth until it has caught up with what is being printed on the
105 +console.
106 +
107 --- /dev/null
108 +++ b/Documentation/speakup/INSTALLATION
109 @@ -0,0 +1,108 @@
110 +This document assumes you have had some experience with kernel
111 +compilation and installation. If you have not, I recommend you get
112 +the kernel source and read the README and various documents in the
113 +linux/Documentation directory. In particular the Changes file to make
114 +sure you have the appropriate utilities needed for installing a 2.2.xx
115 +or 2.4xx kernel. It isn't as difficult as you might think. The
116 +kernel README is intimidating the first time but once you get the
117 +steps down, it's really pretty easy. Getting through the "make
118 +config" is the tedious bit.
119 +
120 +The first thing to do is to place a copy of the tarball in the /usr/src
121 +directory which is the directory the linux tree is located in as well.
122 +Next untar speakup by typing:
123 +
124 +tar zxf speakup-1.00.tar.gz
125 +cd speakup-1.00
126 +./install
127 +
128 +Note the dot-slash before the install. This will copy the speakup
129 +directory to the kernel tree and apply the various patches and
130 +components to the appropriate kernel files. Depending on how
131 +experienced you are with kernel compiling and hacking will determine
132 +whether you should bother looking at any failed patches. If this
133 +happens, you should probably write to the speakup mailing list for
134 +help or myself.
135 +
136 +If all of the patch hunks apply successfully then just continue with
137 +the standard steps to compile the kernel with:
138 +
139 +make mrproper
140 +make config
141 +
142 +When you get to the section console speech output, answer 'y' to the
143 +CONFIG_SPEAKUP prompt. You will be given a submenu with the list of
144 +synthesizers which are currently supported. You can include as many
145 +synths in the kernel as you wish but remember each one takes up kernel
146 +space. You can only choose one of the synths as the default or none,
147 +so just type dtlk or whatever is the correct string for the
148 +synthesizer you have. You will also be asked if you wish to build-in
149 +a speakup key map. If you do not say 'y' to this option you will need
150 +to load a speakup map at boot time with whichever mechanism your
151 +distribution uses for loading key maps.
152 +
153 +We have placed the speakup configuration options in make config just
154 +after the vga console choice. For the DoubleTalk PC driver included
155 +by Jim Van Zandt. I recommend you say no to that option. I have not
156 +tried configuring them both in, but I wouldn't be at all surprised if
157 +it didn't work.
158 +
159 +If all goes well up to this point you can continue with the compiling
160 +process by doing:
161 +
162 +make dep >dep.file 2>&1 &
163 +make bzImage >cc.file 2>&1 &
164 +make modules >mod.file 2>&1 &
165 +
166 +I always redirect output to the files dep.file and cc.file so I can
167 +look over the compilation record to make sure there are no errors and
168 +warnings.
169 +
170 +Okay, you are ready to install the newly compiled kernel. Make sure
171 +you make an linux.old entry in your lilo.conf file so you can recover
172 +if it blows up. next as root run "make modules_install" to install
173 +whatever modules you compiled and move the bzImage from
174 +/usr/src/linux/arch/i386/boot to wherever your kernel lives. Also
175 +move the System.map from /usr/src/linux to where your System.map
176 +lives. On our systems we use debian so we create an vmlinuz-speakup
177 +and System.map-speakup in our /boot directory and set the symbolic
178 +links vmlinuz and System.map in the root (/) directory to point to the
179 +images. Now type lilo to tell lilo to build the new booter file and
180 +install it.
181 +
182 +As of version 0.07, the keymap for speakup is automatically built in
183 +at compile time. If you have other keymaps installed at boot time,
184 +you might want to consider removing them before you reboot the system.
185 +
186 +If everything has gone OK up until now, cross your fingers and type:
187 +
188 +shutdown -r now
189 +
190 +Your system should start talking to you as soon as it starts booting.
191 +It will talk and talk and ... well, you might want to hit the
192 +keypad-enter key to tell it to shut up. You should also read the
193 +DefaultKeyAssignments file to learn the various review functions
194 +available.
195 +
196 +As of v-0.10 the speakup configuration options are in the
197 +/proc/speakup subtree. The individual options should be fairly
198 +obvious by their names such as rate, volume, punc_level and so forth.
199 +You can manipulate them by cat'ing or echoing new values to them such
200 +as:
201 +
202 +echo 9 >/proc/speakup/rate
203 +
204 +You can see what the current values are by cat'ing those files to the console:
205 +
206 +cat /proc/speakup/rate
207 +
208 +I have probably managed to overlook a whole whack of things because
209 +this is the, enter version number here, draft. Don't worry we'll get
210 +it right eventually. If you like the package you really should get on
211 +the mailing list and start participating in it's development.
212 +
213 + Kirk
214 +
215 +email: kirk@braille.uwo.ca
216 +phone: (519) 679-6845 (home)
217 +
218 --- /dev/null
219 +++ b/Documentation/speakup/README
220 @@ -0,0 +1,98 @@
221 +Welcome to the speakup project for the Speakup speech package for Linux.
222 +
223 +Speakup is written by Kirk Reiser and Andy Berdan. It is licensed
224 +under the GPL. If you don't already know, the GPL stands for the GNU
225 +General Public License. Which basically states that this code is free to
226 +copy, modify and distribute to anyone interested in playing with it.
227 +The one thing you may not do is turn any part of it into proprietary
228 +or commercial code without the permission of the author. That's me.
229 +
230 +If you are interested in being involved with the development of speech
231 +output for Linux you can subscribe to the Speakup mailing list by
232 +sending a message to speakup-request@braille.uwo.ca with the line: subscribe. You can also subscribe by going to the speakup web page and following the links at http://www.linux-speakup.org.
233 +
234 +We are at a very early stage in the development of this package.
235 +Hopefully changes will happen often and many. The current files in
236 +this directory are:
237 +
238 +DefaultKeyAssignments # speakup's default review keys
239 +INSTALLATION # for installing speakup from the tar ball.
240 +README # this file
241 +keymap-tutorial # a tutorial on how to layout the keyboard
242 +
243 +Read the INSTALLATION file to learn how to apply the patches and the
244 +default.map for the keyboard. You should also read the Changes file.
245 +It really has any new things I've added since last time.
246 +
247 +There is no documentation in any of these files to instruct you what
248 +to do if something goes wrong with the patching or compilation. If
249 +you would like that information you will need to subscribe to the
250 +mailing list and ask for help, or write me kirk@braille.uwo.ca for
251 +help. I suggest the mailing list because I will probably tire quickly
252 +of answering the same questions over and over. You could always
253 +decide to dig-in and take on the task, and write documentation to help
254 +others.
255 +
256 +There also is a speakup reflector for the Speak Freely package, which
257 +many of us hang out on and discuss all sorts of topics from speakup
258 +problems to ALSA driver installation and just about anything else
259 +you'd like to talk about. The reflector is at lwl.braille.uwo.ca:4074
260 +with it's lwl page at lwl.braille.uwo.ca/speakup.html. Come and join
261 +us, it's fun!
262 +
263 +Acknowledgements:
264 +
265 +I am really very new at kernel hacking and screen review package
266 +writing, so I have depended heavily on other folks kindness to help me
267 +a long. No doubt I will continue to abuse them freely and others
268 +before this is a really good speech solution for Linux. (Oh Well!,
269 +somebody's got to do it.)
270 +
271 +Theodore Ts'o. He gave me a good discussion of unicode and UTF and
272 +the like. He doesn't even remember writing me about it.
273 +
274 +Alan Cox. He has answered many questions about scheduling and wait
275 +queues and timers along with code fragments and so on. I just wish I
276 +understood it all totally. He has also helped immensely in moving
277 +this package toward inclusion in the standard kernel tree. (Maybe next
278 +release!)
279 +
280 +Martin Mares. He pointed me in the right direction to figuring out
281 +the colour attributes and other useful tidbits.
282 +
283 +Paul McDermott. He really is the catalyst for me to actually get
284 +this all working. Besides I like seeing him bounce around and get all
285 +excited every time I have something new working.
286 +
287 +John Covici, He was the first person to actually attempt writing
288 +another synthesizer driver for speakup. It was the Speakout driver so
289 +it was also the first serial driver.
290 +
291 +Brian Borowski, he was the first person to actually write a speakup
292 +function other than Andy and I.
293 +
294 +Jim Danley, he has more or less become my main man in helping test
295 +code, add new features, bounce ideas off and generally become a good
296 +friend.
297 +
298 +Matt Campbell, he basically rewrote the drivers to be able to include
299 +all synths in the kernel at the same time. The distribution
300 +maintainers appreciate him a lot as well.
301 +
302 +Gene Collins, he was very helpful debugging the current release prior
303 +to its public showing. He has also worked hard educating others on
304 +the list and writing the ALSA mini howto.
305 +
306 +I would also like to really thank the folks that handle the
307 +distribution packages. I and many other people would not find access
308 +to speakup nearly so convenient without their efforts. They include
309 +Bill Acker, Tom Moore, Matt Campbell, Joe Norton and Joshua Lambert.
310 +
311 +There are probably many more I am forgetting right now. I guess I'll
312 +just have to add you all later.
313 +
314 +
315 +Happy Hacking!
316 +
317 + Kirk
318 +
319 --- /dev/null
320 +++ b/Documentation/speakup/keymap-tutorial
321 @@ -0,0 +1,140 @@
322 + Speakup Keymap Tutorial
323 +
324 +This is meant to be a basic tutorial on how to change the Linux keymap
325 +file to assign speakup review functions to desired keys. It is not
326 +intended to be a replacement for the loadkeys(8) or keymap(5) man
327 +pages.
328 +
329 +The basic lay-out of the keymap file is a series of lines with the
330 +following fields. The keyword keycode indicates this is the start of
331 +a new key assignment. It is then followed by a number which
332 +represents the actual key on the keyboard. That number is followed by
333 +the equals '=' operator and finally a list of keywords representing
334 +key names such as keypad5. Each line can have quite a few key
335 +functions on it. They are interpreted by loadkeys in order and
336 +assigned to key shift states depending on the order they are
337 +encountered. So for example, the first value after the equals is the
338 +keys unshifted state, while the second is the keys shifted state. If
339 +you wish to learn the order they are interpreted in read the
340 +loadkeys(8) and keymap(5) man pages.
341 +
342 +You can have subsequent lines which are indented and start with
343 +another keyword for the various shifted states. This way you can
344 +assign some of the states without having to specify them all in order
345 +up until you get to the one you want to assign.
346 +
347 +In speakup, we have assigned the insert key on the number pad to the
348 +altgr keyword. This is not required; you could choose any other
349 +shifted state keyword. We used altgr because it typically represents
350 +the right hand alt key. In Linux each shift key is separate and
351 +independent, so the left shift and the right shift keys are not
352 +necessarily the same. The altgr key is not really used for anything
353 +important, so we steel it.
354 +
355 +Here are the default key assignments for the number eight on the
356 +keypad:
357 +
358 +keycode 72 = KP_8
359 + alt keycode 72 = Ascii_8
360 +
361 +As you can see, the first line starts with keycode followed by 72
362 +which is the actual number assigned to the key when the keyboard port
363 +is read. The KP_8 after the equal sign, is the symbolic representation
364 +of the function called when that key is hit.
365 +
366 +The second line is the same format except it starts with the keyword
367 +alt which is indented. That means that the function at the end of
368 +that line Ascii_8 is applied to the alt-shifted eight key.
369 +
370 +Now here are the speakup assignments for that key:
371 +
372 +keycode 72 = 0x0d0a
373 + altgr keycode 72 = 0x0d20
374 +#keycode 72 = KP_8
375 + alt keycode 72 = Ascii_8
376 +
377 +Notice that the only thing which has changed on the first line is the
378 +function called when the key is struck. It is a hexadecimal number
379 +identifying the function called in a look up table. It is not a
380 +symbolic representation yet because that means we need to change the
381 +loadkeys program to understand our symbolic names. We will do this in
382 +the future but for now it is more expedient to just use the table
383 +indices. You will find a table at the bottom of this document
384 +listing the review functions and their corresponding hex lookups.
385 +
386 +The 0x0d0a in the first line above is speakup's say line function.
387 +The second line ends with 0x0d20 which is speakup's read from top of
388 +screen to reading cursor line.
389 +
390 +The third line is the original key assignment commented out with a
391 +number-sign '#' at the beginning. I do that so I can easily find the
392 +keys I want to affect by symbolic name. Otherwise I would need to
393 +keep a look up table for all the keycodes. I recommend you do this as
394 +well or you'll be very sorry at some point in the future.
395 +
396 +The forth line is just the standard key assignment for the left hand
397 +alt key.
398 +
399 +Now let's say we want to design a different keyboard layout. I'll use
400 +an example for the JAWS style keypad because I've specifically been
401 +asked to help with that. JAWS uses the eight on the keypad to move up
402 +a line or the speakup function to read previous line. JAWS also uses
403 +the keypad_8 key in a shifted mode to read the current line. I
404 +apologize if these are not quite right. It has been a long time since
405 +I used JAWS. So we would have the following two lines:
406 +
407 +keycode 72 = 0x0d0b
408 + altgr keycode 72 = 0x0d0a
409 +
410 +The hex value 0x0d0b in the first line is speakup's SAY_PREVIOUS_LINE
411 +function. The 0x0d0a in the second line is the same say_line function
412 +as we had earlier. So when the number eight is hit on the keypad
413 +speakup will read the previous line and when the number eight is
414 +shifted with the insert key on the keypad it will read the current
415 +line.
416 +
417 +As you can tell, it is not really very difficult to reassign the keys
418 +to different review functions.
419 +
420 +Once you have carefully edited the keymap file, called default.map in
421 +the speakup distribution, you copy it into the /etc/kbd directory.
422 +Make sure you back up the original default.map from that directory
423 +first, if there is one. Then you run loadkeys to load the new map
424 +into the kernel:
425 +
426 +loadkeys /etc/kbd/default.map
427 +
428 +If you wish to build your new keyboard lay-out into the kernel, after
429 +testing it, copy the default.map file into the drivers/char directory,
430 +with the name defkeymap.map, of your Linux source tree. Then rm the
431 +defkeymap.c file and recompile the kernel. Because there is no
432 +defkeymap.c `make' will rebuild it on the next compile.
433 +
434 +Here is a list of the available speakup review functions at this point
435 +in time.
436 +
437 +SAY_CHAR 0x0d04 /* say this character */
438 +SAY_PREV_CHAR 0x0d05 /* say character left of this char */
439 +SAY_NEXT_CHAR 0x0d06 /* say char right of this char */
440 +SAY_WORD 0x0d07 /* say this word under reading cursor */
441 +SAY_PREV_WORD 0x0d08
442 +SAY_NEXT_WORD 0x0d09
443 +SAY_LINE 0x0d0a /* say this line */
444 +SAY_PREV_LINE 0x0d0b /* say line above this line */
445 +SAY_NEXT_LINE 0x0d0c
446 +TOP_EDGE 0x0d0d /* move to top edge of screen */
447 +BOTTOM_EDGE 0x0d0e
448 +LEFT_EDGE 0x0d0f
449 +RIGHT_EDGE 0x0d10
450 +SAY_PHONETIC_CHAR 0x0d11 /* say this character phonetically */
451 +SPELL_WORD 0x0d12 /* spell this word letter by letter */
452 +SAY_SCREEN 0x0d14
453 +SAY_POSITION 0x0d1b
454 +SPEECH_OFF 0x0d1c
455 +SAY_ATTRIBUTES 0x0d1d
456 +SPEAKUP_PARKED 0x0d1e
457 +SAY_FROM_TOP 0x0d20
458 +SAY_TO_BOTTOM 0x0d21
459 +SAY_FROM_LEFT 0x0d22
460 +SAY_TO_RIGHT 0x0d23
461 +
462 --- /dev/null
463 +++ b/Documentation/speakup/spkguide.txt
464 @@ -0,0 +1,1279 @@
465 +
466 +The Speakup User's Guide
467 +For Speakup 2.0 and Later
468 +By Gene Collins
469 +Last modified on Tue Mar 29 10:54:19 2005
470 +Document version 1.0
471 +
472 +Copyright (c) 2005 Gene Collins
473 +
474 +Permission is granted to copy, distribute and/or modify this document
475 +under the terms of the GNU Free Documentation License, Version 1.2 or
476 +any later version published by the Free Software Foundation; with no
477 +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
478 +copy of the license is included in the section entitled "GNU Free
479 +Documentation License".
480 +
481 +Preface
482 +
483 +The purpose of this document is to familiarize users with the user
484 +interface to Speakup, a Linux Screen Reader. If you need instructions
485 +for installing or obtaining Speakup, visit the web site at
486 +http://linux-speakup.org/. Speakup is a set of patches to the standard
487 +Linux kernel source tree. It can be built as a series of modules, or as
488 +a part of a monolithic kernel. These details are beyond the scope of
489 +this manual, but the user may need to be aware of the module
490 +capabilities, depending on how your system administrator has installed
491 +Speakup. If Speakup is built as a part of a monolithic kernel, and the
492 +user is using a hardware synthesizer, then Speakup will be able to
493 +provide speech access from the time the kernel is loaded, until the time
494 +the system is shutdown. This means that if you have obtained Linux
495 +installation media for a distribution which includes Speakup as a part
496 +of its kernel, you will be able, as a blind person, to install Linux
497 +with speech access unaided by a sighted person. Again, these details
498 +are beyond the scope of this manual, but the user should be aware of
499 +them. See the web site mentioned above for further details.
500 +
501 +1. Starting Speakup
502 +
503 +If your system administrator has installed Speakup to work with your
504 +specific synthesizer by default, then all you need to do to use Speakup
505 +is to boot your system, and Speakup should come up talking. This
506 +assumes of course that your synthesizer is a supported hardware
507 +synthesizer, and that it is either installed in or connected to your
508 +system, and is if necessary powered on.
509 +
510 +It is possible, however, that Speakup may have been compiled into the
511 +kernel with no default synthesizer. It is even possible that your
512 +kernel has been compiled with support for some of the supported
513 +synthesizers and not others. If you find that this is the case, and
514 +your synthesizer is supported but not available, complain to the person
515 +who compiled and installed your kernel. Or better yet, go to the web
516 +site, and learn how to patch Speakup into your own kernel source, and
517 +build and install your own kernel.
518 +
519 +If your kernel has been compiled with Speakup, and has no default
520 +synthesizer set, or you would like to use a different synthesizer than
521 +the default one, then you may issue the following command at the boot
522 +prompt of your boot loader.
523 +
524 +linux speakup_synth=ltlk
525 +
526 +This command would tell Speakup to look for and use a LiteTalk or
527 +DoubleTalk LT at boot up. You may replace the ltlk synthesizer keyword
528 +with the keyword for whatever synthesizer you wish to use. The
529 +speakup_synth parameter will accept the following keywords, provided
530 +that support for the related synthesizers has been built into the
531 +kernel.
532 +
533 +acntsa -- Accent SA
534 +acntpc -- Accent PC
535 +apolo -- Apolo
536 +audptr -- Audapter
537 +bns -- Braille 'n Speak
538 +dectlk -- DecTalk Express (old and new, db9 serial only)
539 +decext -- DecTalk (old) External
540 +dtlk -- DoubleTalk PC
541 +keypc -- Keynote Gold PC
542 +ltlk -- DoubleTalk LT, LiteTalk, or external Tripletalk (db9 serial only)
543 +spkout -- Speak Out
544 +txprt -- Transport
545 +
546 +Note: Speakup does * NOT * support usb connections! Speakup also does *
547 +NOT * support the internal Tripletalk!
548 +
549 +Speakup does support two other synthesizers, but because they work in
550 +conjunction with other software, they must be loaded as modules after
551 +their related software is loaded, and so are not available at boot up.
552 +These are as follows:
553 +
554 +decpc -- DecTalk PC (not available at boot up)
555 +sftsyn -- One of several software synthesizers (not available at boot up)
556 +
557 +See the sections on loading modules and software synthesizers later in
558 +this manual for further details. It should be noted here that the
559 +speakup_synth boot parameter will have no effect if Speakup has been
560 +compiled as modules. In order for Speakup modules to be loaded during
561 +the boot process, such action must be configured by your system
562 +administrator. This will mean that you will hear some, but not all, of
563 +the bootup messages.
564 +
565 +2. Basic operation
566 +
567 +Once you have booted the system, and if necessary, have supplied the
568 +proper bootup parameter for your synthesizer, Speakup will begin
569 +talking as soon as the kernel is loaded. In fact, it will talk a lot!
570 +It will speak all the boot up messages that the kernel prints on the
571 +screen during the boot process. This is because Speakup is not a
572 +separate screen reader, but is actually built into the operating
573 +system. Since almost all console applications must print text on the
574 +screen using the kernel, and must get their keyboard input through the
575 +kernel, they are automatically handled properly by Speakup. There are a
576 +few exceptions, but we'll come to those later.
577 +
578 +Note: In this guide I will refer to the numeric keypad as the keypad.
579 +This is done because the speakupmap.map file referred to later in this
580 +manual uses the term keypad instead of numeric keypad. Also I'm lazy
581 +and would rather only type one word. So keypad it is. Got it? Good.
582 +
583 +Most of the Speakup review keys are located on the keypad at the far
584 +right of the keyboard. The numlock key should be off, in order for these
585 +to work. If you toggle the numlock on, the keypad will produce numbers,
586 +which is exactly what you want for spreadsheets and such. For the
587 +purposes of this guide, you should have the numlock turned off, which is
588 +its default state at bootup.
589 +
590 +You probably won't want to listen to all the bootup messages every time
591 +you start your system, though it's a good idea to listen to them at
592 +least once, just so you'll know what kind of information is available to
593 +you during the boot process. You can always review these messages after
594 +bootup with the command:
595 +
596 +dmesg | more
597 +
598 +In order to speed the boot process, and to silence the speaking of the
599 +bootup messages, just press the keypad enter key. This key is located
600 +in the bottom right corner of the keypad. Speakup will shut up and stay
601 +that way, until you press another key.
602 +
603 +You can check to see if the boot process has completed by pressing the 8
604 +key on the keypad, which reads the current line. This also has the
605 +effect of starting Speakup talking again, so you can press keypad enter
606 +to silence it again if the boot process has not completed.
607 +
608 +When the boot process is complete, you will arrive at a "login" prompt.
609 +At this point, you'll need to type in your user id and password, as
610 +provided by your system administrator. You will hear Speakup speak the
611 +letters of your user id as you type it, but not the password. This is
612 +because the password is not displayed on the screen for security
613 +reasons. This has nothing to do with Speakup, it's a Linux security
614 +feature.
615 +
616 +Once you've logged in, you can run any Linux command or program which is
617 +allowed by your user id. Normal users will not be able to run programs
618 +which require root privileges.
619 +
620 +When you are running a program or command, Speakup will automatically
621 +speak new text as it arrives on the screen. You can at any time silence
622 +the speech with keypad enter, or use any of the Speakup review keys.
623 +
624 +Here are some basic Speakup review keys, and a short description of what
625 +they do.
626 +
627 +keypad 1 -- read previous character
628 +keypad 2 -- read current character (pressing keypad 2 twice rapidly will speak
629 + the current character phonetically)
630 +keypad 3 -- read next character
631 +keypad 4 -- read previous word
632 +keypad 5 -- read current word (press twice rapidly to spell the current word)
633 +keypad 6 -- read next word
634 +keypad 7 -- read previous line
635 +keypad 8 -- read current line (press twice rapidly to hear how much the
636 + text on the current line is indented)
637 +keypad 9 -- read next line
638 +keypad period -- speak current cursor position and announce current
639 + virtual console
640 +
641 +It's also worth noting that the insert key on the keypad is mapped
642 +as the speakup key. Instead of pressing and releasing this key, as you
643 +do under DOS or Windows, you hold it like a shift key, and press other
644 +keys in combination with it. For example, repeatedly holding keypad
645 +insert, from now on called speakup, and keypad enter will toggle the
646 +speaking of new text on the screen on and off. This is not the same as
647 +just pressing keypad enter by itself, which just silences the speech
648 +until you hit another key. When you hit speakup plus keypad enter,
649 +Speakup will say, "You turned me off.", or "Hey, that's better." When
650 +Speakup is turned off, no new text on the screen will be spoken. You
651 +can still use the reading controls to review the screen however.
652 +
653 +3. Using the Speakup Help System
654 +
655 +Speakup has a help system, which is compiled as a module. It is loaded
656 +automatically whenever the Speakup help system is invoked for the first
657 +time, and remains loaded after that, until speakup is unloaded. Note
658 +that if speakup was compiled into a monolithic kernel on your system,
659 +you will not be able to unload Speakup from your kernel. If you try to
660 +use the help system, and find that it is unavailable, then your system
661 +administrator has not installed the Speakup help module, which is called
662 +speakup_help. Complain to your system administrator about this.
663 +
664 +In order to enter the Speakup help system, press and hold the speakup
665 +key (remember that this is the keypad insert key), and press the f1 key.
666 +You will hear the message:
667 +
668 +"Press space to leave help, cursor up or down to scroll, or a letter to
669 +go to commands in list."
670 +
671 +When you press the spacebar to leave the help system, you will hear:
672 +
673 +"Leaving help."
674 +
675 +While you are in the Speakup help system, you can scroll up or down
676 +through the list of available commands using the cursor keys. The list
677 +of commands is arranged in alphabetical order. If you wish to jump to
678 +commands in a specific part of the alphabet, you may press the letter of
679 +the alphabet you wish to jump to.
680 +
681 +You can also just explore by typing keyboard keys. Pressing keys will
682 +cause Speakup to speak the command associated with that key. For
683 +example, if you press the keypad 8 key, you will hear:
684 +
685 +"Keypad 8 is line, say current."
686 +
687 +You'll notice that some commands do not have keys assigned to them.
688 +This is because they are very infrequently used commands, and are also
689 +accessible through the proc system. We'll discuss the proc system later
690 +in this manual.
691 +
692 +You'll also notice that some commands have two keys assigned to them.
693 +This is because Speakup has a built in set of alternative key bindings
694 +for laptop users. The alternate speakup key is the caps lock key. You
695 +can press and hold the caps lock key, while pressing an alternate
696 +speakup command key to activate the command. On most laptops, the
697 +numeric keypad is defined as the keys in the j k l area of the keyboard.
698 +
699 +There is usually a function key which turns this keypad function on and
700 +off, and some other key which controls the numlock state. Toggling the
701 +keypad functionality on and off can become a royal pain. So, Speakup
702 +gives you a simple way to get at an alternative set of key mappings for
703 +your laptop. These are also available by default on desktop systems,
704 +because Speakup does not know whether it is running on a desktop or
705 +laptop. So you may choose which set of Speakup keys to use. Some
706 +system administrators may have chosen to compile Speakup for a desktop
707 +system without this set of alternate key bindings, but these details are
708 +beyond the scope of this manual. To use the caps lock for its normal
709 +purpose, hold the shift key while toggling the caps lock on and off. We
710 +should note here, that holding the caps lock key and pressing the z key
711 +will toggle the alternate j k l keypad on and off.
712 +
713 +4. Keys and Their Assigned Commands
714 +
715 +In this section, we'll go through a list of all the speakup keys and
716 +commands. You can also get a list of commands and assigned keys from
717 +the help system.
718 +
719 +The following list was taken from the speakupmap.map file. Key
720 +assignments are on the left of the equal sign, and the associated
721 +Speakup commands are on the right. The designation "spk" means to press
722 +and hold the speakup key, a.k.a. keypad insert, a.k.a. caps lock, while
723 +pressing the other specified key.
724 +
725 +spk key_f9 = punc_level_dec
726 +spk key_f10 = punc_level_inc
727 +spk key_f11 = reading_punc_dec
728 +spk key_f12 = reading_punc_inc
729 +spk key_1 = vol_dec
730 +spk key_2 = vol_inc
731 +spk key_3 = pitch_dec
732 +spk key_4 = pitch_inc
733 +spk key_5 = rate_dec
734 +spk key_6 = rate_inc
735 +key_kpasterisk = toggle_cursoring
736 +spk key_kpasterisk = speakup_goto
737 +spk key_f1 = speakup_help
738 +spk key_f2 = set_win
739 +spk key_f3 = clear_win
740 +spk key_f4 = enable_win
741 +spk key_f5 = edit_some
742 +spk key_f6 = edit_most
743 +spk key_f7 = edit_delim
744 +spk key_f8 = edit_repeat
745 +shift spk key_f9 = edit_exnum
746 + key_kp7 = say_prev_line
747 +spk key_kp7 = left_edge
748 + key_kp8 = say_line
749 +double key_kp8 = say_line_indent
750 +spk key_kp8 = say_from_top
751 + key_kp9 = say_next_line
752 +spk key_kp9 = top_edge
753 + key_kpminus = speakup_parked
754 +spk key_kpminus = say_char_num
755 + key_kp4 = say_prev_word
756 +spk key_kp4 = say_from_left
757 + key_kp5 = say_word
758 +double key_kp5 = spell_word
759 +spk key_kp5 = spell_phonetic
760 + key_kp6 = say_next_word
761 +spk key_kp6 = say_to_right
762 + key_kpplus = say_screen
763 +spk key_kpplus = say_win
764 + key_kp1 = say_prev_char
765 +spk key_kp1 = right_edge
766 + key_kp2 = say_char
767 +spk key_kp2 = say_to_bottom
768 +double key_kp2 = say_phonetic_char
769 + key_kp3 = say_next_char
770 +spk key_kp3 = bottom_edge
771 + key_kp0 = spk_key
772 + key_kpdot = say_position
773 +spk key_kpdot = say_attributes
774 +key_kpenter = speakup_quiet
775 +spk key_kpenter = speakup_off
776 +key_sysrq = speech_kill
777 + key_kpslash = speakup_cut
778 +spk key_kpslash = speakup_paste
779 +spk key_pageup = say_first_char
780 +spk key_pagedown = say_last_char
781 +key_capslock = spk_key
782 + spk key_z = spk_lock
783 +key_leftmeta = spk_key
784 +ctrl spk key_0 = speakup_goto
785 +spk key_u = say_prev_line
786 +spk key_i = say_line
787 +double spk key_i = say_line_indent
788 +spk key_o = say_next_line
789 +spk key_minus = speakup_parked
790 +shift spk key_minus = say_char_num
791 +spk key_j = say_prev_word
792 +spk key_k = say_word
793 +double spk key_k = spell_word
794 +spk key_l = say_next_word
795 +spk key_m = say_prev_char
796 +spk key_comma = say_char
797 +double spk key_comma = say_phonetic_char
798 +spk key_dot = say_next_char
799 +spk key_n = say_position
800 + ctrl spk key_m = left_edge
801 + ctrl spk key_y = top_edge
802 + ctrl spk key_dot = right_edge
803 +ctrl spk key_p = bottom_edge
804 +spk key_apostrophe = say_screen
805 +spk key_h = say_from_left
806 +spk key_y = say_from_top
807 +spk key_semicolon = say_to_right
808 +spk key_p = say_to_bottom
809 +spk key_slash = say_attributes
810 + spk key_enter = speakup_quiet
811 + ctrl spk key_enter = speakup_off
812 + spk key_9 = speakup_cut
813 +spk key_8 = speakup_paste
814 +shift spk key_m = say_first_char
815 + ctrl spk key_semicolon = say_last_char
816 +
817 +5. The Speakup Proc System
818 +
819 +The Speakup screen reader also creates a speakup subdirectory as a part
820 +of the proc system. You can see these entries by typing the command:
821 +
822 +ls -1 /proc/speakup/*
823 +
824 +If you issue the above ls command, you will get back something like
825 +this:
826 +
827 +/proc/speakup/attrib_bleep
828 +/proc/speakup/bell_pos
829 +/proc/speakup/bleep_time
830 +/proc/speakup/bleeps
831 +/proc/speakup/caps_start
832 +/proc/speakup/caps_stop
833 +/proc/speakup/characters
834 +/proc/speakup/cursor_time
835 +/proc/speakup/delay_time
836 +/proc/speakup/delimiters
837 +/proc/speakup/ex_num
838 +/proc/speakup/freq
839 +/proc/speakup/full_time
840 +/proc/speakup/jiffy_delta
841 +/proc/speakup/key_echo
842 +/proc/speakup/keymap
843 +/proc/speakup/no_interrupt
844 +/proc/speakup/pitch
845 +/proc/speakup/punc_all
846 +/proc/speakup/punc_level
847 +/proc/speakup/punc_most
848 +/proc/speakup/punc_some
849 +/proc/speakup/punct
850 +/proc/speakup/rate
851 +/proc/speakup/reading_punc
852 +/proc/speakup/repeats
853 +/proc/speakup/say_control
854 +/proc/speakup/say_word_ctl
855 +/proc/speakup/silent
856 +/proc/speakup/spell_delay
857 +/proc/speakup/synth_direct
858 +/proc/speakup/synth_name
859 +/proc/speakup/tone
860 +/proc/speakup/trigger_time
861 +/proc/speakup/version
862 +/proc/speakup/voice
863 +/proc/speakup/vol
864 +
865 +In addition to using the Speakup hot keys to change such things as
866 +volume, pitch, and rate, you can also echo values to the appropriate
867 +entry in the /proc/speakup directory. This is very useful, since it
868 +lets you control Speakup parameters from within a script. How you
869 +would write such scripts is somewhat beyond the scope of this manual,
870 +but I will include a couple of simple examples here to give you a
871 +general idea of what such scripts can do.
872 +
873 +Suppose for example, that you wanted to control both the punctuation
874 +level and the reading punctuation level at the same time. For
875 +simplicity, we'll call them punc0, punc1, punc2, and punc3. The scripts
876 +might look something like this:
877 +
878 +#!/bin/bash
879 +# punc0
880 +# set punc and reading punc levels to 0
881 +echo 0 >/proc/speakup/punc_level
882 +echo 0 >/proc/speakup/reading_punc
883 +echo Punctuation level set to 0.
884 +
885 +#!/bin/bash
886 +# punc1
887 +# set punc and reading punc levels to 1
888 +echo 1 >/proc/speakup/punc_level
889 +echo 1 >/proc/speakup/reading_punc
890 +echo Punctuation level set to 1.
891 +
892 +#!/bin/bash
893 +# punc2
894 +# set punc and reading punc levels to 2
895 +echo 2 >/proc/speakup/punc_level
896 +echo 2 >/proc/speakup/reading_punc
897 +echo Punctuation level set to 2.
898 +
899 +#!/bin/bash
900 +# punc3
901 +# set punc and reading punc levels to 3
902 +echo 3 >/proc/speakup/punc_level
903 +echo 3 >/proc/speakup/reading_punc
904 +echo Punctuation level set to 3.
905 +
906 +If you were to store these four small scripts in a directory in your
907 +path, perhaps /usr/local/bin, and set the permissions to 755 with the
908 +chmod command, then you could change the default reading punc and
909 +punctuation levels at the same time by issuing just one command. For
910 +example, if you were to execute the punc3 command at your shell prompt,
911 +then the reading punc and punc level would both get set to 3.
912 +
913 +I should note that the above scripts were written to work with bash, but
914 +regardless of which shell you use, you should be able to do something
915 +similar.
916 +
917 +The Speakup proc system also has another interesting use. You can echo
918 +Speakup parameters into the proc system in a script during system
919 +startup, and speakup will return to your preferred parameters every time
920 +the system is rebooted.
921 +
922 +Most of the Speakup proc parameters can be manipulated by a regular user
923 +on the system. However, there are a few parameters that are dangerous
924 +enough that they should only be manipulated by the root user on your
925 +system. There are even some parameters that are read only, and cannot
926 +be written to at all. For example, the version entry in the Speakup
927 +proc system is read only. This is because there is no reason for a user
928 +to tamper with the version number which is reported by Speakup. Doing
929 +an ls -l on /proc/speakup/version will return this:
930 +
931 +-r--r--r-- 1 root root 0 Mar 21 13:46 /proc/speakup/version
932 +
933 +As you can see, the version entry in the Speakup proc system is read
934 +only, is owned by root, and belongs to the root group. Doing a cat of
935 +/proc/speakup/version will display the Speakup version number, like
936 +this:
937 +
938 +cat /proc/speakup/version
939 +Speakup v-2.00 CVS: Thu Oct 21 10:38:21 EDT 2004
940 +synth dtlk version 1.1
941 +
942 +The display shows the Speakup version number, along with the version
943 +number of the driver for the current synthesizer.
944 +
945 +Looking at entries in the Speakup proc system can be useful in many
946 +ways. For example, you might wish to know what level your volume is set
947 +at. You could type:
948 +
949 +cat /proc/speakup/vol
950 +5
951 +
952 +The number five which comes back is the level at which the synthesizer
953 +volume is set at.
954 +
955 +All the entries in the Speakup proc system are readable, some are
956 +writable by root only, and some are writable by everyone. Unless you
957 +know what you are doing, you should probably leave the ones that are
958 +writable by root only alone. Most of the names are self explanatory.
959 +Vol for controlling volume, pitch for pitch, rate for controlling speaking
960 +rate, etc. If you find one you aren't sure about, you can post a query
961 +on the Speakup list.
962 +
963 +6. Changing Synthesizers
964 +
965 +It is possible to change to a different synthesizer while speakup is
966 +running. In other words, it is not necessary to reboot the system
967 +in order to use a different synthesizer. You can simply echo the
968 +synthesizer keyword to the /proc/speakup/synth_name proc entry.
969 +Depending on your situation, you may wish to echo none to the synth_name
970 +proc entry, to disable speech while one synthesizer is disconnected and
971 +a second one is connected in its place. Then echo the keyword for the
972 +new synthesizer into the synth_name proc entry in order to start speech
973 +with the newly connected synthesizer. See the list of synthesizer
974 +keywords in section 1 to find the keyword which matches your synth.
975 +
976 +7. Loading modules
977 +
978 +As mentioned earlier, Speakup can either be completely compiled into the
979 +kernel, with the exception of the help module, or it can be compiled as
980 +a series of modules. When compiled as modules, Speakup will only be
981 +able to speak some of the bootup messages if your system administrator
982 +has configured the system to load the modules at boo time. The modules
983 +can be loaded after the file systems have been checked and mounted, or
984 +from an initrd. There is a third possibility. Speakup can be compiled
985 +with some components built into the kernel, and others as modules. As
986 +we'll see in the next section, this is particularly useful when you are
987 +working with software synthesizers.
988 +
989 +If Speakup is completely compiled as modules, then you must use the
990 +modprobe command to load Speakup. You do this by loading the module for
991 +the synthesizer driver you wish to use. The driver modules are all
992 +named speakup_<keyword>, where <keyword> is the keyword for the
993 +synthesizer you want. So, in order to load the driver for the DecTalk
994 +Express, you would type the following command:
995 +
996 +modprobe speakup_dectlk
997 +
998 +Issuing this command would load the DecTalk Express driver and all other
999 +related Speakup modules necessary to get Speakup up and running.
1000 +
1001 +To completely unload Speakup, again presuming that it is entirely built
1002 +as modules, you would give the command:
1003 +
1004 +modprobe -r speakup_dectlk
1005 +
1006 +The above command assumes you were running a DecTalk Express. If you
1007 +were using a different synth, then you would substitute its keyword in
1008 +place of dectlk.
1009 +
1010 +But now, suppose we have a situation where the main Speakup component
1011 +is built into the kernel, and some or all of the drivers are built as
1012 +modules. Since the main part of Speakup is compiled into the kernel, a
1013 +partial Speakup proc system has been created which we can take advantage
1014 +of by simply echoing the synthesizer keyword into the
1015 +/proc/speakup/synth_name proc entry. This will cause the kernel to
1016 +automatically load the appropriate driver module, and start Speakup
1017 +talking. To switch to another synth, just echo a new keyword to the
1018 +synth_name proc entry. For example, to load the DoubleTalk LT driver,
1019 +you would type:
1020 +
1021 +echo ltlk >/proc/speakup/synth_name
1022 +
1023 +You can use the modprobe -r command to unload driver modules, regardless
1024 +of whether the main part of Speakup has been built into the kernel or
1025 +not.
1026 +
1027 +8. Using Software Synthesizers
1028 +
1029 +Using a software synthesizer requires that some other software be
1030 +installed and running on your system. For this reason, software
1031 +synthesizers are not available for use at bootup, or during a system
1032 +installation process.
1033 +
1034 +In order to use a software synthesizer, you must have a package called
1035 +Speech Dispatcher running on your system, and it must be configured to
1036 +work with one of its supported software synthesizers.
1037 +
1038 +Two open source synthesizers you might use are Flite and Festival. You
1039 +might also choose to purchase the Software DecTalk from Fonix Sales Inc.
1040 +If you run a google search for Fonix, you'll find their web site.
1041 +
1042 +You can obtain a copy of Speech Dispatcher from free(b)soft at
1043 +http://www.freebsoft.org/. Follow the installation instructions that
1044 +come with Speech Dispatcher in order to install and configure Speech
1045 +Dispatcher. You can check out the web site for your Linux distribution
1046 +in order to get a copy of either Flite or Festival. Your Linux
1047 +distribution may also have a precompiled Speech Dispatcher package.
1048 +
1049 +Once you've installed, configured, and tested Speech Dispatcher with your
1050 +chosen software synthesizer, you still need one more piece of software
1051 +in order to make things work. You need a package called speechd-up.
1052 +You get it from the free(b)soft web site mentioned above. After you've
1053 +compiled and installed speechd-up, you are almost ready to begin using
1054 +your software synthesizer.
1055 +
1056 +Before you can use a software synthesizer, you must have created the
1057 +/dev/softsynth device. If you have not already done so, issue the
1058 +following commands as root:
1059 +
1060 +cd /dev
1061 +mknod softsynth c 10 26
1062 +
1063 +While we are at it, we might just as well create the /dev/synth device,
1064 +which can be used to let user space programs send information to your
1065 +synthesizer. To create /dev/synth, change to the /dev directory, and
1066 +issue the following command as root:
1067 +
1068 +mknod synth c 10 25
1069 +
1070 +Now you can begin using your software synthesizer. In order to do so,
1071 +echo the sftsyn keyword to the synth_name proc entry like this:
1072 +
1073 +echo sftsyn >/proc/speakup/synth_name
1074 +
1075 +Next run the speechd_up command like this:
1076 +
1077 +speechd_up &
1078 +
1079 +Your synth should now start talking, and you should be able to adjust
1080 +the pitch, rate, etc.
1081 +
1082 +In this section, we have assumed that your copy of Speakup was compiled
1083 +with the speakup_sftsyn component either built into the kernel, or
1084 +compiled as a module.
1085 +
1086 +9. Using The DecTalk PC Card
1087 +
1088 +The DecTalk PC card is an ISA card that is inserted into one of the ISA
1089 +slots in your computer. It requires that the DecTalk PC software be
1090 +installed on your computer, and that the software be loaded onto the
1091 +Dectalk PC card before it can be used.
1092 +
1093 +You can get the dec_pc.tgz file from the linux-speakup.org site. The
1094 +dec_pc.tgz file is in the ~ftp/pub/linux/speakup directory.
1095 +
1096 +After you have downloaded the dec_pc.tgz file, untar it in your home
1097 +directory, and read the Readme file in the newly created dec_pc
1098 +directory.
1099 +
1100 +The easiest way to get the software working is to copy the entire dec_pc
1101 +directory into /user/local/lib. To do this, su to root in your home
1102 +directory, and issue the command:
1103 +
1104 +cp dec_pc /usr/local/lib
1105 +
1106 +You will need to copy the dtload command from the dec_pc directory to a
1107 +directory in your path. Either /usr/bin or /usr/local/bin is a good
1108 +choice.
1109 +
1110 +You can now run the dtload command in order to load the DecTalk PC
1111 +software onto the card. After you have done this, echo the decpc
1112 +keyword to the synth_name entry in the proc system like this:
1113 +
1114 +echo decpc >/proc/speakup/synth_name
1115 +
1116 +Your DecTalk PC should start talking, and then you can adjust the pitch,
1117 +rate, volume, voice, etc. The voice entry in the Speakup proc system
1118 +will accept a number from 0 through 7 for the DecTalk PC synthesizer,
1119 +which will give you access to some of the DecTalk voices.
1120 +
1121 +10. Using Cursor Tracking
1122 +
1123 +In Speakup version 2.0 and later, cursor tracking is turned on by
1124 +default. This means that when you are using an editor, Speakup will
1125 +automatically speak characters as you move left and right with the
1126 +cursor keys, and lines as you move up and down with the cursor keys.
1127 +
1128 +This is extremely useful, and makes editing files a snap. But there are
1129 +times when cursor tracking can get in your way. So Speakup provides a
1130 +toggle to turn cursor tracking on and off. You do this with the keypad
1131 +asterisk key. Pressing this key repeatedly will toggle the cursor
1132 +tracking on and off, and you will hear Speakup say, "cursoring off", and
1133 +"cursoring on".
1134 +
1135 +Some folks like to turn cursor tracking off while they are using the
1136 +lynx web browser. You definitely want to turn cursor tracking off when
1137 +you are using the alsamixer application. Otherwise, you won't be able
1138 +to hear your mixer settings while you are using the arrow keys.
1139 +
1140 +11. Cut and Paste
1141 +
1142 +One of Speakup's more useful features is the ability to cut and paste
1143 +text on the screen. This means that you can capture information from a
1144 +program, and paste that captured text into a different place in the
1145 +program, or into an entirely different program, which may even be
1146 +running on a different console.
1147 +
1148 +For example, in this manual, we have made references to several web
1149 +sites. It would be nice if you could cut and paste these urls into your
1150 +web browser. Speakup does this quite nicely. Suppose you wanted to
1151 +past the following url into your browser:
1152 +
1153 +http://linux-speakup.org/
1154 +
1155 +Use the speakup review keys to position the reading cursor on the first
1156 +character of the above url. When the reading cursor is in position,
1157 +press the keypad slash key once. Speakup will say, "mark". Next,
1158 +position the reading cursor on the rightmost character of the above
1159 +url. Press the keypad slash key once again to actually cut the text
1160 +from the screen. Speakup will say, "cut". Although we call this
1161 +cutting, Speakup does not actually delete the cut text from the screen.
1162 +It makes a copy of the text in a special buffer for later pasting.
1163 +
1164 +Now that you have the url cut from the screen, you can paste it into
1165 +your browser, or even paste the url on a command line as an argument to
1166 +your browser.
1167 +
1168 +Suppose you want to start lynx and go to the Speakup site.
1169 +
1170 +You can switch to a different console with the alt left and right
1171 +arrows, or you can switch to a specific console by typing alt and a
1172 +function key. These are not Speakup commands, just standard Linux
1173 +console capabilities.
1174 +
1175 +Once you've changed to an appropriate console, and are at a shell prompt,
1176 +type the word lynx, followed by a space. Now press and hold the speakup
1177 +key, while you type the keypad slash character. The url will be pasted
1178 +onto the command line, just as though you had typed it in. Press the
1179 +enter key to execute the command.
1180 +
1181 +The paste buffer will continue to hold the cut information, until a new
1182 +mark and cut operation is carried out. This means you can paste the cut
1183 +information as many times as you like before doing another cut
1184 +operation.
1185 +
1186 +You are not limited to cutting and pasting only one line on the screen.
1187 +You can also cut and paste rectangular regions of the screen. Just
1188 +position the reading cursor at the top left corner of the text to be
1189 +cut, mark it with the keypad slash key, then position the reading cursor
1190 +at the bottom right corner of the region to be cut, and cut it with the
1191 +keypad slash key.
1192 +
1193 +12. Changing the Pronunciation of Characters
1194 +
1195 +Through the /proc/speakup/chars proc entry, Speakup gives you the
1196 +ability to change how Speakup pronounces a given character. You could,
1197 +for example, change how some punctuation characters are spoken. You can
1198 +even change how Speakup will pronounce certain letters.
1199 +
1200 +You may, for example, wish to change how Speakup pronounces the z
1201 +character. The author of Speakup, Kirk Reiser, is Canadian, and thus
1202 +believes that the z should be pronounced zed. If you are an American,
1203 +you might wish to use the zee pronunciation instead of zed. You can
1204 +change the pronunciation of both the upper and lower case z with the
1205 +following two commands:
1206 +
1207 +echo 90 zee >/proc/speakup/characters
1208 +echo 122 zee >/proc/speakup/characters
1209 +
1210 +Let's examine the parts of the two previous commands. They are issued
1211 +at the shell prompt, and could be placed in a startup script.
1212 +
1213 +The word echo tells the shell that you want to have it display the
1214 +string of characters that follow the word echo. If you were to just
1215 +type:
1216 +
1217 +echo hello.
1218 +
1219 +You would get the word hello printed on your screen as soon as you
1220 +pressed the enter key. In this case, we are echoing strings that we
1221 +want to be redirected into the proc system.
1222 +
1223 +The numbers 90 and 122 in the above echo commands are the ascii numeric
1224 +values for the upper and lower case z, the characters we wish to change.
1225 +
1226 +The string zee is the pronunciation that we want Speakup to use for the
1227 +upper and lower case z.
1228 +
1229 +The > symbol redirects the output of the echo command to a file, just
1230 +like in DOS, or at the Windows command prompt.
1231 +
1232 +And finally, /proc/speakup/chars is the file entry in the proc system
1233 +where we want the output to be directed. Speakup looks at the numeric
1234 +value of the character we want to change, and inserts the pronunciation
1235 +string into an internal table.
1236 +
1237 +You can look at the whole table with the following command:
1238 +
1239 +cat /proc/speakup/chars
1240 +
1241 +Speakup will then print out the entire character pronunciation table. I
1242 +won't display it here, but leave you to look at it at your convenience.
1243 +
1244 +13. Mapping Keys
1245 +
1246 +Speakup has the capability of allowing you to assign or "map" keys to
1247 +internal Speakup commands. This section necessarily assumes you have a
1248 +Linux kernel source tree installed, and that it has been patched and
1249 +configured with Speakup. How you do this is beyond the scope of this
1250 +manual. For this information, visit the Speakup web site at
1251 +http://linux-speakup.org/. The reason you'll need the kernel source
1252 +tree patched with Speakup is that the genmap utility you'll need for
1253 +processing keymaps is in the
1254 +/usr/src/linux-<version_number>/drivers/char/speakup directory. The
1255 +<version_number> in the above directory path is the version number of
1256 +the Linux source tree you are working with.
1257 +
1258 +So ok, you've gone off and gotten your kernel source tree, and patched
1259 +and configured it. Now you can start manipulating keymaps.
1260 +
1261 +You can either use the
1262 +/usr/src/linux-<version_number>/drivers/char/speakup/speakupmap.map file
1263 +included with the Speakup source, or you can cut and paste the copy in
1264 +section 4 into a separate file. If you use the one in the Speakup
1265 +source tree, make sure you make a backup of it before you start making
1266 +changes. You have been warned!
1267 +
1268 +Suppose that you want to swap the key assignments for the Speakup
1269 +say_last_char and the Speakup say_first_char commands. The
1270 +speakupmap.map lists the key mappings for these two commands as follows:
1271 +
1272 +spk key_pageup = say_first_char
1273 +spk key_pagedown = say_last_char
1274 +
1275 +You can edit your copy of the speakupmap.map file and swap the command
1276 +names on the right side of the = (equals) sign. You did make a backup,
1277 +right? The new keymap lines would look like this:
1278 +
1279 +spk key_pageup = say_last_char
1280 +spk key_pagedown = say_first_char
1281 +
1282 +After you edit your copy of the speakupmap.map file, save it under a new
1283 +file name, perhaps newmap.map. Then exit your editor and return to the
1284 +shell prompt.
1285 +
1286 +You are now ready to load your keymap with your swapped key assignments.
1287 + Assuming that you saved your new keymap as the file newmap.map, you
1288 +would load your keymap into the proc system like this:
1289 +
1290 +/usr/src/linux-<version_number>/drivers/char/speakup/genmap newmap.map
1291 +>/proc/speakup/keymap
1292 +
1293 +Remember to substitute your kernel version number for the
1294 +<version_number> in the above command. Also note that although the
1295 +above command wrapped onto two lines in this document, you should type
1296 +it all on one line.
1297 +
1298 +Your say first and say last characters should now be swapped. Pressing
1299 +speakup pagedown should read you the first non-whitespace character on
1300 +the line your reading cursor is in, and pressing speakup pageup should
1301 +read you the last character on the line your reading cursor is in.
1302 +
1303 +You should note that these new mappings will only stay in effect until
1304 +you reboot, or until you load another keymap.
1305 +
1306 +One final warning. If you try to load a partial map, you will quickly
1307 +find that all the mappings you didn't include in your file got deleted
1308 +from the working map. Be extremely careful, and always make a backup!
1309 +You have been warned!
1310 +
1311 +14. Using Speakup's Windowing Capability
1312 +
1313 +Speakup has the capability of defining and manipulating windows on the
1314 +screen. Speakup uses the term "Window", to mean a user defined area of
1315 +the screen. The key strokes for defining and manipulating Speakup
1316 +windows are as follows:
1317 +
1318 +speakup + f2 -- Set the bounds of the window.
1319 +Speakup + f3 -- clear the current window definition.
1320 +speakup + f4 -- Toggle window silence on and off.
1321 +speakup + keypad plus -- Say the currently defined window.
1322 +
1323 +These capabilities are useful for tracking a certain part of the screen
1324 +without rereading the whole screen, or for silencing a part of the
1325 +screen that is constantly changing, such as a clock or status line.
1326 +
1327 +There is no way to save these window settings, and you can only have one
1328 +window defined for each virtual console. There is also no way to have
1329 +windows automaticly defined for specific applications.
1330 +
1331 +In order to define a window, use the review keys to move your reading
1332 +cursor to the beginning of the area you want to define. Then press
1333 +speakup + f2. Speakup will tell you that the window starts at the
1334 +indicated row and column position. Then move the reading cursor to the
1335 +end of the area to be defined as a window, and press speakup + f2 again.
1336 + If there is more than one line in the window, Speakup will tell you
1337 +that the window ends at the indicated row and column position. If there
1338 +is only one line in the window, then Speakup will tell you that the
1339 +window is the specified line on the screen. If you are only defining a
1340 +one line window, you can just press speakup + f2 twice after placing the
1341 +reading cursor on the line you want to define as a window. It is not
1342 +necessary to position the reading cursor at the end of the line in order
1343 +to define the whole line as a window.
1344 +
1345 + GNU Free Documentation License
1346 + Version 1.2, November 2002
1347 +
1348 +
1349 + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
1350 + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1351 + Everyone is permitted to copy and distribute verbatim copies
1352 + of this license document, but changing it is not allowed.
1353 +
1354 +
1355 +0. PREAMBLE
1356 +
1357 +The purpose of this License is to make a manual, textbook, or other
1358 +functional and useful document "free" in the sense of freedom: to
1359 +assure everyone the effective freedom to copy and redistribute it,
1360 +with or without modifying it, either commercially or noncommercially.
1361 +Secondarily, this License preserves for the author and publisher a way
1362 +to get credit for their work, while not being considered responsible
1363 +for modifications made by others.
1364 +
1365 +This License is a kind of "copyleft", which means that derivative
1366 +works of the document must themselves be free in the same sense. It
1367 +complements the GNU General Public License, which is a copyleft
1368 +license designed for free software.
1369 +
1370 +We have designed this License in order to use it for manuals for free
1371 +software, because free software needs free documentation: a free
1372 +program should come with manuals providing the same freedoms that the
1373 +software does. But this License is not limited to software manuals;
1374 +it can be used for any textual work, regardless of subject matter or
1375 +whether it is published as a printed book. We recommend this License
1376 +principally for works whose purpose is instruction or reference.
1377 +
1378 +
1379 +1. APPLICABILITY AND DEFINITIONS
1380 +
1381 +This License applies to any manual or other work, in any medium, that
1382 +contains a notice placed by the copyright holder saying it can be
1383 +distributed under the terms of this License. Such a notice grants a
1384 +world-wide, royalty-free license, unlimited in duration, to use that
1385 +work under the conditions stated herein. The "Document", below,
1386 +refers to any such manual or work. Any member of the public is a
1387 +licensee, and is addressed as "you". You accept the license if you
1388 +copy, modify or distribute the work in a way requiring permission
1389 +under copyright law.
1390 +
1391 +A "Modified Version" of the Document means any work containing the
1392 +Document or a portion of it, either copied verbatim, or with
1393 +modifications and/or translated into another language.
1394 +
1395 +A "Secondary Section" is a named appendix or a front-matter section of
1396 +the Document that deals exclusively with the relationship of the
1397 +publishers or authors of the Document to the Document's overall subject
1398 +(or to related matters) and contains nothing that could fall directly
1399 +within that overall subject. (Thus, if the Document is in part a
1400 +textbook of mathematics, a Secondary Section may not explain any
1401 +mathematics.) The relationship could be a matter of historical
1402 +connection with the subject or with related matters, or of legal,
1403 +commercial, philosophical, ethical or political position regarding
1404 +them.
1405 +
1406 +The "Invariant Sections" are certain Secondary Sections whose titles
1407 +are designated, as being those of Invariant Sections, in the notice
1408 +that says that the Document is released under this License. If a
1409 +section does not fit the above definition of Secondary then it is not
1410 +allowed to be designated as Invariant. The Document may contain zero
1411 +Invariant Sections. If the Document does not identify any Invariant
1412 +Sections then there are none.
1413 +
1414 +The "Cover Texts" are certain short passages of text that are listed,
1415 +as Front-Cover Texts or Back-Cover Texts, in the notice that says that
1416 +the Document is released under this License. A Front-Cover Text may
1417 +be at most 5 words, and a Back-Cover Text may be at most 25 words.
1418 +
1419 +A "Transparent" copy of the Document means a machine-readable copy,
1420 +represented in a format whose specification is available to the
1421 +general public, that is suitable for revising the document
1422 +straightforwardly with generic text editors or (for images composed of
1423 +pixels) generic paint programs or (for drawings) some widely available
1424 +drawing editor, and that is suitable for input to text formatters or
1425 +for automatic translation to a variety of formats suitable for input
1426 +to text formatters. A copy made in an otherwise Transparent file
1427 +format whose markup, or absence of markup, has been arranged to thwart
1428 +or discourage subsequent modification by readers is not Transparent.
1429 +An image format is not Transparent if used for any substantial amount
1430 +of text. A copy that is not "Transparent" is called "Opaque".
1431 +
1432 +Examples of suitable formats for Transparent copies include plain
1433 +ASCII without markup, Texinfo input format, LaTeX input format, SGML
1434 +or XML using a publicly available DTD, and standard-conforming simple
1435 +HTML, PostScript or PDF designed for human modification. Examples of
1436 +transparent image formats include PNG, XCF and JPG. Opaque formats
1437 +include proprietary formats that can be read and edited only by
1438 +proprietary word processors, SGML or XML for which the DTD and/or
1439 +processing tools are not generally available, and the
1440 +machine-generated HTML, PostScript or PDF produced by some word
1441 +processors for output purposes only.
1442 +
1443 +The "Title Page" means, for a printed book, the title page itself,
1444 +plus such following pages as are needed to hold, legibly, the material
1445 +this License requires to appear in the title page. For works in
1446 +formats which do not have any title page as such, "Title Page" means
1447 +the text near the most prominent appearance of the work's title,
1448 +preceding the beginning of the body of the text.
1449 +
1450 +A section "Entitled XYZ" means a named subunit of the Document whose
1451 +title either is precisely XYZ or contains XYZ in parentheses following
1452 +text that translates XYZ in another language. (Here XYZ stands for a
1453 +specific section name mentioned below, such as "Acknowledgements",
1454 +"Dedications", "Endorsements", or "History".) To "Preserve the Title"
1455 +of such a section when you modify the Document means that it remains a
1456 +section "Entitled XYZ" according to this definition.
1457 +
1458 +The Document may include Warranty Disclaimers next to the notice which
1459 +states that this License applies to the Document. These Warranty
1460 +Disclaimers are considered to be included by reference in this
1461 +License, but only as regards disclaiming warranties: any other
1462 +implication that these Warranty Disclaimers may have is void and has
1463 +no effect on the meaning of this License.
1464 +
1465 +
1466 +2. VERBATIM COPYING
1467 +
1468 +You may copy and distribute the Document in any medium, either
1469 +commercially or noncommercially, provided that this License, the
1470 +copyright notices, and the license notice saying this License applies
1471 +to the Document are reproduced in all copies, and that you add no other
1472 +conditions whatsoever to those of this License. You may not use
1473 +technical measures to obstruct or control the reading or further
1474 +copying of the copies you make or distribute. However, you may accept
1475 +compensation in exchange for copies. If you distribute a large enough
1476 +number of copies you must also follow the conditions in section 3.
1477 +
1478 +You may also lend copies, under the same conditions stated above, and
1479 +you may publicly display copies.
1480 +
1481 +
1482 +3. COPYING IN QUANTITY
1483 +
1484 +If you publish printed copies (or copies in media that commonly have
1485 +printed covers) of the Document, numbering more than 100, and the
1486 +Document's license notice requires Cover Texts, you must enclose the
1487 +copies in covers that carry, clearly and legibly, all these Cover
1488 +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
1489 +the back cover. Both covers must also clearly and legibly identify
1490 +you as the publisher of these copies. The front cover must present
1491 +the full title with all words of the title equally prominent and
1492 +visible. You may add other material on the covers in addition.
1493 +Copying with changes limited to the covers, as long as they preserve
1494 +the title of the Document and satisfy these conditions, can be treated
1495 +as verbatim copying in other respects.
1496 +
1497 +If the required texts for either cover are too voluminous to fit
1498 +legibly, you should put the first ones listed (as many as fit
1499 +reasonably) on the actual cover, and continue the rest onto adjacent
1500 +pages.
1501 +
1502 +If you publish or distribute Opaque copies of the Document numbering
1503 +more than 100, you must either include a machine-readable Transparent
1504 +copy along with each Opaque copy, or state in or with each Opaque copy
1505 +a computer-network location from which the general network-using
1506 +public has access to download using public-standard network protocols
1507 +a complete Transparent copy of the Document, free of added material.
1508 +If you use the latter option, you must take reasonably prudent steps,
1509 +when you begin distribution of Opaque copies in quantity, to ensure
1510 +that this Transparent copy will remain thus accessible at the stated
1511 +location until at least one year after the last time you distribute an
1512 +Opaque copy (directly or through your agents or retailers) of that
1513 +edition to the public.
1514 +
1515 +It is requested, but not required, that you contact the authors of the
1516 +Document well before redistributing any large number of copies, to give
1517 +them a chance to provide you with an updated version of the Document.
1518 +
1519 +
1520 +4. MODIFICATIONS
1521 +
1522 +You may copy and distribute a Modified Version of the Document under
1523 +the conditions of sections 2 and 3 above, provided that you release
1524 +the Modified Version under precisely this License, with the Modified
1525 +Version filling the role of the Document, thus licensing distribution
1526 +and modification of the Modified Version to whoever possesses a copy
1527 +of it. In addition, you must do these things in the Modified Version:
1528 +
1529 +A. Use in the Title Page (and on the covers, if any) a title distinct
1530 + from that of the Document, and from those of previous versions
1531 + (which should, if there were any, be listed in the History section
1532 + of the Document). You may use the same title as a previous version
1533 + if the original publisher of that version gives permission.
1534 +B. List on the Title Page, as authors, one or more persons or entities
1535 + responsible for authorship of the modifications in the Modified
1536 + Version, together with at least five of the principal authors of the
1537 + Document (all of its principal authors, if it has fewer than five),
1538 + unless they release you from this requirement.
1539 +C. State on the Title page the name of the publisher of the
1540 + Modified Version, as the publisher.
1541 +D. Preserve all the copyright notices of the Document.
1542 +E. Add an appropriate copyright notice for your modifications
1543 + adjacent to the other copyright notices.
1544 +F. Include, immediately after the copyright notices, a license notice
1545 + giving the public permission to use the Modified Version under the
1546 + terms of this License, in the form shown in the Addendum below.
1547 +G. Preserve in that license notice the full lists of Invariant Sections
1548 + and required Cover Texts given in the Document's license notice.
1549 +H. Include an unaltered copy of this License.
1550 +I. Preserve the section Entitled "History", Preserve its Title, and add
1551 + to it an item stating at least the title, year, new authors, and
1552 + publisher of the Modified Version as given on the Title Page. If
1553 + there is no section Entitled "History" in the Document, create one
1554 + stating the title, year, authors, and publisher of the Document as
1555 + given on its Title Page, then add an item describing the Modified
1556 + Version as stated in the previous sentence.
1557 +J. Preserve the network location, if any, given in the Document for
1558 + public access to a Transparent copy of the Document, and likewise
1559 + the network locations given in the Document for previous versions
1560 + it was based on. These may be placed in the "History" section.
1561 + You may omit a network location for a work that was published at
1562 + least four years before the Document itself, or if the original
1563 + publisher of the version it refers to gives permission.
1564 +K. For any section Entitled "Acknowledgements" or "Dedications",
1565 + Preserve the Title of the section, and preserve in the section all
1566 + the substance and tone of each of the contributor acknowledgements
1567 + and/or dedications given therein.
1568 +L. Preserve all the Invariant Sections of the Document,
1569 + unaltered in their text and in their titles. Section numbers
1570 + or the equivalent are not considered part of the section titles.
1571 +M. Delete any section Entitled "Endorsements". Such a section
1572 + may not be included in the Modified Version.
1573 +N. Do not retitle any existing section to be Entitled "Endorsements"
1574 + or to conflict in title with any Invariant Section.
1575 +O. Preserve any Warranty Disclaimers.
1576 +
1577 +If the Modified Version includes new front-matter sections or
1578 +appendices that qualify as Secondary Sections and contain no material
1579 +copied from the Document, you may at your option designate some or all
1580 +of these sections as invariant. To do this, add their titles to the
1581 +list of Invariant Sections in the Modified Version's license notice.
1582 +These titles must be distinct from any other section titles.
1583 +
1584 +You may add a section Entitled "Endorsements", provided it contains
1585 +nothing but endorsements of your Modified Version by various
1586 +parties--for example, statements of peer review or that the text has
1587 +been approved by an organization as the authoritative definition of a
1588 +standard.
1589 +
1590 +You may add a passage of up to five words as a Front-Cover Text, and a
1591 +passage of up to 25 words as a Back-Cover Text, to the end of the list
1592 +of Cover Texts in the Modified Version. Only one passage of
1593 +Front-Cover Text and one of Back-Cover Text may be added by (or
1594 +through arrangements made by) any one entity. If the Document already
1595 +includes a cover text for the same cover, previously added by you or
1596 +by arrangement made by the same entity you are acting on behalf of,
1597 +you may not add another; but you may replace the old one, on explicit
1598 +permission from the previous publisher that added the old one.
1599 +
1600 +The author(s) and publisher(s) of the Document do not by this License
1601 +give permission to use their names for publicity for or to assert or
1602 +imply endorsement of any Modified Version.
1603 +
1604 +
1605 +5. COMBINING DOCUMENTS
1606 +
1607 +You may combine the Document with other documents released under this
1608 +License, under the terms defined in section 4 above for modified
1609 +versions, provided that you include in the combination all of the
1610 +Invariant Sections of all of the original documents, unmodified, and
1611 +list them all as Invariant Sections of your combined work in its
1612 +license notice, and that you preserve all their Warranty Disclaimers.
1613 +
1614 +The combined work need only contain one copy of this License, and
1615 +multiple identical Invariant Sections may be replaced with a single
1616 +copy. If there are multiple Invariant Sections with the same name but
1617 +different contents, make the title of each such section unique by
1618 +adding at the end of it, in parentheses, the name of the original
1619 +author or publisher of that section if known, or else a unique number.
1620 +Make the same adjustment to the section titles in the list of
1621 +Invariant Sections in the license notice of the combined work.
1622 +
1623 +In the combination, you must combine any sections Entitled "History"
1624 +in the various original documents, forming one section Entitled
1625 +"History"; likewise combine any sections Entitled "Acknowledgements",
1626 +and any sections Entitled "Dedications". You must delete all sections
1627 +Entitled "Endorsements".
1628 +
1629 +
1630 +6. COLLECTIONS OF DOCUMENTS
1631 +
1632 +You may make a collection consisting of the Document and other documents
1633 +released under this License, and replace the individual copies of this
1634 +License in the various documents with a single copy that is included in
1635 +the collection, provided that you follow the rules of this License for
1636 +verbatim copying of each of the documents in all other respects.
1637 +
1638 +You may extract a single document from such a collection, and distribute
1639 +it individually under this License, provided you insert a copy of this
1640 +License into the extracted document, and follow this License in all
1641 +other respects regarding verbatim copying of that document.
1642 +
1643 +
1644 +7. AGGREGATION WITH INDEPENDENT WORKS
1645 +
1646 +A compilation of the Document or its derivatives with other separate
1647 +and independent documents or works, in or on a volume of a storage or
1648 +distribution medium, is called an "aggregate" if the copyright
1649 +resulting from the compilation is not used to limit the legal rights
1650 +of the compilation's users beyond what the individual works permit.
1651 +When the Document is included in an aggregate, this License does not
1652 +apply to the other works in the aggregate which are not themselves
1653 +derivative works of the Document.
1654 +
1655 +If the Cover Text requirement of section 3 is applicable to these
1656 +copies of the Document, then if the Document is less than one half of
1657 +the entire aggregate, the Document's Cover Texts may be placed on
1658 +covers that bracket the Document within the aggregate, or the
1659 +electronic equivalent of covers if the Document is in electronic form.
1660 +Otherwise they must appear on printed covers that bracket the whole
1661 +aggregate.
1662 +
1663 +
1664 +8. TRANSLATION
1665 +
1666 +Translation is considered a kind of modification, so you may
1667 +distribute translations of the Document under the terms of section 4.
1668 +Replacing Invariant Sections with translations requires special
1669 +permission from their copyright holders, but you may include
1670 +translations of some or all Invariant Sections in addition to the
1671 +original versions of these Invariant Sections. You may include a
1672 +translation of this License, and all the license notices in the
1673 +Document, and any Warranty Disclaimers, provided that you also include
1674 +the original English version of this License and the original versions
1675 +of those notices and disclaimers. In case of a disagreement between
1676 +the translation and the original version of this License or a notice
1677 +or disclaimer, the original version will prevail.
1678 +
1679 +If a section in the Document is Entitled "Acknowledgements",
1680 +"Dedications", or "History", the requirement (section 4) to Preserve
1681 +its Title (section 1) will typically require changing the actual
1682 +title.
1683 +
1684 +
1685 +9. TERMINATION
1686 +
1687 +You may not copy, modify, sublicense, or distribute the Document except
1688 +as expressly provided for under this License. Any other attempt to
1689 +copy, modify, sublicense or distribute the Document is void, and will
1690 +automatically terminate your rights under this License. However,
1691 +parties who have received copies, or rights, from you under this
1692 +License will not have their licenses terminated so long as such
1693 +parties remain in full compliance.
1694 +
1695 +
1696 +10. FUTURE REVISIONS OF THIS LICENSE
1697 +
1698 +The Free Software Foundation may publish new, revised versions
1699 +of the GNU Free Documentation License from time to time. Such new
1700 +versions will be similar in spirit to the present version, but may
1701 +differ in detail to address new problems or concerns. See
1702 +http://www.gnu.org/copyleft/.
1703 +
1704 +Each version of the License is given a distinguishing version number.
1705 +If the Document specifies that a particular numbered version of this
1706 +License "or any later version" applies to it, you have the option of
1707 +following the terms and conditions either of that specified version or
1708 +of any later version that has been published (not as a draft) by the
1709 +Free Software Foundation. If the Document does not specify a version
1710 +number of this License, you may choose any version ever published (not
1711 +as a draft) by the Free Software Foundation.
1712 +
1713 +
1714 +ADDENDUM: How to use this License for your documents
1715 +
1716 +To use this License in a document you have written, include a copy of
1717 +the License in the document and put the following copyright and
1718 +license notices just after the title page:
1719 +
1720 + Copyright (c) YEAR YOUR NAME.
1721 + Permission is granted to copy, distribute and/or modify this document
1722 + under the terms of the GNU Free Documentation License, Version 1.2
1723 + or any later version published by the Free Software Foundation;
1724 + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
1725 + A copy of the license is included in the section entitled "GNU
1726 + Free Documentation License".
1727 +
1728 +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
1729 +replace the "with...Texts." line with this:
1730 +
1731 + with the Invariant Sections being LIST THEIR TITLES, with the
1732 + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
1733 +
1734 +If you have Invariant Sections without Cover Texts, or some other
1735 +combination of the three, merge those two alternatives to suit the
1736 +situation.
1737 +
1738 +If your document contains nontrivial examples of program code, we
1739 +recommend releasing these examples in parallel under your choice of
1740 +free software license, such as the GNU General Public License,
1741 +to permit their use in free software.
1742 +
1743 +The End.
1744 --- a/MAINTAINERS
1745 +++ b/MAINTAINERS
1746 @@ -3333,6 +3333,13 @@ M: wli@holomorphy.com
1747 L: sparclinux@vger.kernel.org
1748 S: Maintained
1749
1750 +SPEAKUP Console speech output
1751 +P: Kirk Reiser
1752 +M: kirk@braille.uwo.ca
1753 +L: speakup@braille.uwo.ca
1754 +W: http://www.linux-speakup.org
1755 +S: Maintained
1756 +
1757 SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
1758 P: Roger Wolff
1759 M: R.E.Wolff@BitWizard.nl
1760 --- a/arch/arm/Kconfig
1761 +++ b/arch/arm/Kconfig
1762 @@ -1022,6 +1022,7 @@ source "drivers/leds/Kconfig"
1763 source "drivers/media/Kconfig"
1764
1765 source "drivers/video/Kconfig"
1766 +source "drivers/char/speakup/Kconfig"
1767
1768 source "sound/Kconfig"
1769
1770 --- a/drivers/Kconfig
1771 +++ b/drivers/Kconfig
1772 @@ -62,6 +62,8 @@ source "drivers/media/Kconfig"
1773
1774 source "drivers/video/Kconfig"
1775
1776 +source "drivers/char/speakup/Kconfig"
1777 +
1778 source "sound/Kconfig"
1779
1780 source "drivers/hid/Kconfig"
1781 --- a/drivers/char/Makefile
1782 +++ b/drivers/char/Makefile
1783 @@ -94,6 +94,7 @@ obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.
1784 obj-$(CONFIG_GPIO_TB0219) += tb0219.o
1785 obj-$(CONFIG_TELCLOCK) += tlclk.o
1786
1787 +obj-$(CONFIG_SPEAKUP) += speakup/
1788 obj-$(CONFIG_WATCHDOG) += watchdog/
1789 obj-$(CONFIG_MWAVE) += mwave/
1790 obj-$(CONFIG_AGP) += agp/
1791 --- a/drivers/char/consolemap.c
1792 +++ b/drivers/char/consolemap.c
1793 @@ -667,3 +667,4 @@ console_map_init(void)
1794 }
1795
1796 EXPORT_SYMBOL(con_copy_unimap);
1797 +EXPORT_SYMBOL_GPL(inverse_translate);
1798 --- a/drivers/char/keyboard.c
1799 +++ b/drivers/char/keyboard.c
1800 @@ -41,7 +41,23 @@
1801 #include <linux/input.h>
1802 #include <linux/reboot.h>
1803
1804 -extern void ctrl_alt_del(void);
1805 +
1806 +#include <linux/speakup.h>
1807 +
1808 +#if defined(CONFIG_SPEAKUP_MODULE)
1809 +
1810 +spk_key_func addr_spk_key = NULL;
1811 +#define speakup_key_call(__vc, __shift, __keycode, __key, __down) \
1812 + (addr_spk_key && (*addr_spk_key)(__vc, __shift, __keycode, __key, __down))
1813 +
1814 +#elif defined(CONFIG_SPEAKUP)
1815 +#define speakup_key_call(__vc, __shift, __keycode, __key, __down) \
1816 + speakup_key(__vc, __shift, __keycode, __key, __down)
1817 +#else
1818 +#define speakup_key_call(__vc, __shift, __keycode, __key, __down) 0
1819 +#endif
1820 +
1821 + extern void ctrl_alt_del(void);
1822
1823 /*
1824 * Exported functions/variables
1825 @@ -64,6 +80,10 @@ extern void ctrl_alt_del(void);
1826
1827 #define KBD_DEFLOCK 0
1828
1829 +/* Key types processed even in raw modes */
1830 +
1831 +#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT) | (1 << KT_SPKUP))
1832 +
1833 void compute_shiftstate(void);
1834
1835 /*
1836 @@ -79,7 +99,7 @@ void compute_shiftstate(void);
1837 typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
1838 char up_flag);
1839 static k_handler_fn K_HANDLERS;
1840 -static k_handler_fn *k_handler[16] = { K_HANDLERS };
1841 +k_handler_fn *k_handler[16] = { K_HANDLERS };
1842
1843 #define FN_HANDLERS\
1844 fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
1845 @@ -100,13 +120,16 @@ static fn_handler_fn *fn_handler[] = { F
1846 const int max_vals[] = {
1847 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
1848 NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
1849 - 255, NR_LOCK - 1, 255, NR_BRL - 1
1850 + 255, NR_LOCK - 1, 255, NR_BRL - 1, 255
1851 };
1852
1853 const int NR_TYPES = ARRAY_SIZE(max_vals);
1854
1855 struct kbd_struct kbd_table[MAX_NR_CONSOLES];
1856 -static struct kbd_struct *kbd = kbd_table;
1857 +struct kbd_struct *kbd = kbd_table;
1858 +
1859 +EXPORT_SYMBOL_GPL(kbd);
1860 +EXPORT_SYMBOL_GPL(k_handler);
1861
1862 struct vt_spawn_console vt_spawn_con = {
1863 .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
1864 @@ -240,6 +263,8 @@ void kd_mksound(unsigned int hz, unsigne
1865 kd_nosound(0);
1866 }
1867
1868 +EXPORT_SYMBOL_GPL(kd_mksound);
1869 +
1870 /*
1871 * Setting the keyboard rate.
1872 */
1873 @@ -590,6 +615,7 @@ static void k_spec(struct vc_data *vc, u
1874 if (up_flag)
1875 return;
1876 if (value >= ARRAY_SIZE(fn_handler))
1877 + if (up_flag || (value >= ARRAY_SIZE(fn_handler)))
1878 return;
1879 if ((kbd->kbdmode == VC_RAW ||
1880 kbd->kbdmode == VC_MEDIUMRAW) &&
1881 @@ -1200,6 +1226,9 @@ static void kbd_keycode(unsigned int key
1882 key_map = key_maps[shift_final];
1883
1884 if (!key_map) {
1885 + if (speakup_key_call(vc, shift_final, keycode, K(KT_SHIFT,0), !down))
1886 + return;
1887 +
1888 compute_shiftstate();
1889 kbd->slockstate = 0;
1890 return;
1891 @@ -1223,6 +1252,9 @@ static void kbd_keycode(unsigned int key
1892
1893 type -= 0xf0;
1894
1895 + if (speakup_key_call(vc, shift_final, keycode, keysym, !down))
1896 + return;
1897 +
1898 if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
1899 return;
1900
1901 @@ -1241,6 +1273,9 @@ static void kbd_keycode(unsigned int key
1902 kbd->slockstate = 0;
1903 }
1904
1905 +struct input_dev *fakekeydev=NULL;
1906 +EXPORT_SYMBOL_GPL(fakekeydev);
1907 +
1908 static void kbd_event(struct input_handle *handle, unsigned int event_type,
1909 unsigned int event_code, int value)
1910 {
1911 @@ -1278,6 +1313,7 @@ static int kbd_connect(struct input_hand
1912 return -ENOMEM;
1913
1914 handle->dev = dev;
1915 + fakekeydev = dev;
1916 handle->handler = handler;
1917 handle->name = "kbd";
1918
1919 --- /dev/null
1920 +++ b/drivers/char/speakup/Config.in
1921 @@ -0,0 +1,26 @@
1922 +tristate 'Speakup console speech' CONFIG_SPEAKUP
1923 +if [ "$CONFIG_SPEAKUP" != "n" ]; then
1924 + comment 'Type "y" for each synthesizer you want built into the kernel.'
1925 + dep_tristate "Accent SA, acntsa" CONFIG_SPEAKUP_ACNTSA $CONFIG_SPEAKUP
1926 + dep_tristate "Accent PC, acntpc" CONFIG_SPEAKUP_ACNTPC $CONFIG_SPEAKUP
1927 + dep_tristate "Apollo, apollo" CONFIG_SPEAKUP_APOLLO $CONFIG_SPEAKUP
1928 + dep_tristate "Audapter, audptr" CONFIG_SPEAKUP_AUDPTR $CONFIG_SPEAKUP
1929 + dep_tristate "Braille 'n' Speak, bns" CONFIG_SPEAKUP_BNS $CONFIG_SPEAKUP
1930 + dep_tristate "DECtalk Express, dectlk" CONFIG_SPEAKUP_DECTLK $CONFIG_SPEAKUP
1931 + dep_tristate "DECtalk External (old), decext" CONFIG_SPEAKUP_DECEXT $CONFIG_SPEAKUP
1932 + dep_tristate "DECtalk PC (big ISA card), decpc" CONFIG_SPEAKUP_DECPC $CONFIG_SPEAKUP
1933 + if [ "$CONFIG_SPEAKUP_DECPC" = "y" ] ;then
1934 + comment 'warning: decpc can only be built as a module'
1935 + fi
1936 + comment 'In order to use this you will need'
1937 + comment 'the dtload program and DECPC software files '
1938 + comment 'Read the accompanying DECPC documentation for more details'
1939 + dep_tristate "DoubleTalk PC, dtlk" CONFIG_SPEAKUP_DTLK $CONFIG_SPEAKUP
1940 + dep_tristate "Keynote Gold PC, keypc" CONFIG_SPEAKUP_KEYPC $CONFIG_SPEAKUP
1941 + dep_tristate "DoubleTalk LT or LiteTalk, ltlk" CONFIG_SPEAKUP_LTLK $CONFIG_SPEAKUP
1942 + dep_tristate "Software synthesizers /dev/sftsyn, sftsyn" CONFIG_SPEAKUP_SFTSYN $CONFIG_SPEAKUP
1943 + dep_tristate "Speak Out, spkout" CONFIG_SPEAKUP_SPKOUT $CONFIG_SPEAKUP
1944 + dep_tristate "Transport, txprt" CONFIG_SPEAKUP_TXPRT $CONFIG_SPEAKUP
1945 + comment 'Enter the three to six character synth string from above or none.'
1946 + string "Default synthesizer for Speakup" CONFIG_SPEAKUP_DEFAULT "none"
1947 +fi
1948 --- /dev/null
1949 +++ b/drivers/char/speakup/Kconfig
1950 @@ -0,0 +1,211 @@
1951 +menu "Speakup console speech"
1952 +config SPEAKUP
1953 + tristate "Build speakup console speech"
1954 + ---help---
1955 +
1956 + This is the Speakup screen reader. Think of it as a
1957 + video console for blind people. If built in to the
1958 + kernel, it can speak evrything on the text console from
1959 + boot up to shutdown. For more information on Speakup,
1960 + point your browser at http://www.linux-speakup.org/.
1961 + There is also a mailing list at the above url that you
1962 + can subscribe to.
1963 +
1964 + Supported synthesizers are accent sa, accent pc, appollo
1965 + II., Auddapter, Braille 'n Speak, Dectalk external
1966 + (old), Dectalk PC (full length isa board), Dectalk
1967 + express, Doubletalk, Doubletalk LT or Litetalk,
1968 + Keynote
1969 + Gold internal PC, software synthesizers, Speakout, and transport.
1970 +
1971 + Speakup can either be built in or compiled as a module
1972 + by answering y or m. If you answer y here, then you
1973 + must answer either y or m to at least one of the
1974 + synthesizer drivers below. If you answer m here, then
1975 + the synthesizer drivers below can only be built as
1976 + modules.
1977 +
1978 + These drivers are not standalone drivers, but must be
1979 + used in conjunction with Speakup. Think of them as
1980 + video cards for blind people.
1981 +
1982 +
1983 + The Dectalk pc driver can only be built as a module, and
1984 + requires software to be pre-loaded on to the card before
1985 + the module can be loaded. See the decpc choice below
1986 + for more details.
1987 +
1988 + If you are not a blind person, or don't have access to
1989 + one of the listed synthesizers, you should say n.
1990 +
1991 +config SPEAKUP_ACNTSA
1992 + depends on SPEAKUP
1993 + tristate "Accent SA, acntsa"
1994 + ---help---
1995 +
1996 + This is the Speakup driver for the accent sa
1997 + synthesizer. You can say y to build it into the kernel,
1998 + or m to build it as a module. See the configuration
1999 + help on the Speakup choice above for more info.
2000 +
2001 +config SPEAKUP_ACNTPC
2002 + depends on SPEAKUP
2003 + tristate "Accent PC, acntpc"
2004 + ---help---
2005 +
2006 + This is the Speakup driver for the accent pc
2007 + synthesizer. You can say y to build it into the kernel,
2008 + or m to build it as a module. See the configuration
2009 + help on the Speakup choice above for more info.
2010 +
2011 +config SPEAKUP_APOLLO
2012 + depends on SPEAKUP
2013 + tristate "Apollo, apollo"
2014 + ---help---
2015 +
2016 + This is the Speakup driver for the Apollo II
2017 + synthesizer. You can say y to build it into the kernel,
2018 + or m to build it as a module. See the configuration
2019 + help on the Speakup choice above for more info.
2020 +
2021 +config SPEAKUP_AUDPTR
2022 + depends on SPEAKUP
2023 + tristate "Audapter, audptr"
2024 + ---help---
2025 +
2026 + This is the Speakup driver for the Audapter synthesizer.
2027 + You can say y to build it into the kernel, or m to
2028 + build it as a module. See the configuration help on the
2029 + Speakup choice above for more info.
2030 +
2031 +config SPEAKUP_BNS
2032 + depends on SPEAKUP
2033 + tristate "Braille 'n' Speak, bns"
2034 + ---help---
2035 +
2036 + This is the Speakup driver for the Braille 'n' Speak
2037 + synthesizer. You can say y to build it into the kernel,
2038 + or m to build it as a module. See the configuration
2039 + help on the Speakup choice above for more info.
2040 +
2041 +config SPEAKUP_DECTLK
2042 + depends on SPEAKUP
2043 + tristate "DECtalk Express, dectlk"
2044 + ---help---
2045 +
2046 + This is the Speakup driver for the DecTalk Express
2047 + synthesizer. You can say y to build it into the kernel,
2048 + or m to build it as a module. See the configuration
2049 + help on the Speakup choice above for more info.
2050 +
2051 +config SPEAKUP_DECEXT
2052 + depends on SPEAKUP
2053 + tristate "DECtalk External (old), decext"
2054 + ---help---
2055 +
2056 + This is the Speakup driver for the DecTalk External
2057 + (old) synthesizer. You can say y to build it into the
2058 + kernel, or m to build it as a module. See the
2059 + configuration help on the Speakup choice above for more
2060 + info.
2061 +
2062 +config SPEAKUP_DECPC
2063 + depends on SPEAKUP
2064 + tristate "DECtalk PC (big ISA card), decpc"
2065 + ---help---
2066 +
2067 + This is the Speakup driver for the DecTalk PC (full
2068 + length ISA) synthesizer. You can say m to build it as
2069 + a module. See the configuration help on the Speakup
2070 + choice above for more info.
2071 +
2072 + In order to use the DecTalk PC driver, you must download
2073 + the dec_pc.tgz file from linux-speakup.org. It is in
2074 + the pub/linux/goodies directory. The dec_pc.tgz file
2075 + contains the software which must be pre-loaded on to the
2076 + DecTalk PC board in order to use it with this driver.
2077 + This driver must be built as a module, and can not be
2078 + loaded until the file system is mounted and the DecTalk
2079 + PC software has been pre-loaded on to the board.
2080 +
2081 + See the README file in the dec_pc.tgz file for more
2082 + details.
2083 +
2084 +config SPEAKUP_DTLK
2085 + depends on SPEAKUP
2086 + tristate "DoubleTalk PC, dtlk"
2087 + ---help---
2088 +
2089 + This is the Speakup driver for the internal DoubleTalk
2090 + PC synthesizer. You can say y to build it into the
2091 + kernel, or m to build it as a module. See the
2092 + configuration help on the Speakup choice above for more
2093 + info.
2094 +
2095 +config SPEAKUP_KEYPC
2096 + depends on SPEAKUP
2097 + tristate "Keynote Gold PC, keypc"
2098 + ---help---
2099 +
2100 + This is the Speakup driver for the Keynote Gold
2101 + PC synthesizer. You can say y to build it into the
2102 + kernel, or m to build it as a module. See the
2103 + configuration help on the Speakup choice above for more
2104 + info.
2105 +
2106 +config SPEAKUP_LTLK
2107 + depends on SPEAKUP
2108 + tristate "DoubleTalk LT or LiteTalk, ltlk"
2109 +---help---
2110 +
2111 + This is the Speakup driver for the LiteTalk/DoubleTalk
2112 + LT synthesizer. You can say y to build it into the
2113 + kernel, or m to build it as a module. See the
2114 + configuration help on the Speakup choice above for more
2115 + info.
2116 +
2117 +config SPEAKUP_SFTSYN
2118 + depends on SPEAKUP
2119 + tristate "Software synthesizers, sftsyn"
2120 +---help---
2121 +
2122 + This is the software synthesizer device node. It will
2123 + register a device /dev/sftsyn which midware programs
2124 + and speech
2125 + daemons may open and read to provide kernel output to
2126 + software synths
2127 + such as festival, flite, tuxtalk and so forth. You
2128 + can select 'y' or
2129 + 'm' to have it built-in to the kernel or loaded as a module.
2130 +
2131 +config SPEAKUP_SPKOUT
2132 + depends on SPEAKUP
2133 + tristate "Speak Out, spkout"
2134 + ---help---
2135 +
2136 + This is the Speakup driver for the Speakout synthesizer.
2137 + You can say y to build it into the kernel, or m to
2138 + build it as a module. See the configuration help on the
2139 + Speakup choice above for more info.
2140 +
2141 +config SPEAKUP_TXPRT
2142 + depends on SPEAKUP
2143 + tristate "Transport, txprt"
2144 + ---help---
2145 +
2146 + This is the Speakup driver for the Transport
2147 + synthesizer. You can say y to build it into the kernel,
2148 + or m to build it as a module. See the configuration
2149 + help on the Speakup choice above for more info.
2150 +
2151 +if SPEAKUP != n
2152 +comment 'Enter the 3 to 6 character keyword from the list above, or none for no default synthesizer on boot up.'
2153 + depends on SPEAKUP
2154 +endif
2155 +
2156 +config SPEAKUP_DEFAULT
2157 + string "Choose Default synthesizer for Speakup"
2158 + depends on SPEAKUP
2159 + default "none"
2160 +
2161 +endmenu
2162 --- /dev/null
2163 +++ b/drivers/char/speakup/Makefile
2164 @@ -0,0 +1,61 @@
2165 +#
2166 +# Makefile for the speakup speech output system.
2167 +#
2168 +
2169 +V := $(shell awk '/UTS_RELEASE/ {print substr($$3,2,3)}' $(TOPDIR)/include/linux/version.h)
2170 +ifeq ($V,2.4)
2171 +# Note! Dependencies are done automagically by 'make dep', which also
2172 +# removes any old dependencies. DON'T put your own dependencies here
2173 +# unless it's something special (ie not a .c file).
2174 +#
2175 +# Note 2! The CFLAGS definitions are now inherited from the
2176 +# parent makes..
2177 +#
2178 +O_TARGET := spk.o
2179 +export-objs := speakup_drvcommon.o speakup.o
2180 +endif
2181 +obj-m = speakup_keyhelp.o
2182 +speakupmain-objs := speakup.o speakup_drvcommon.o
2183 +obj-$(CONFIG_SPEAKUP) += speakupmain.o
2184 +obj-$(CONFIG_SPEAKUP_ACNTPC) += speakup_acntpc.o
2185 +obj-$(CONFIG_SPEAKUP_ACNTSA) += speakup_acntsa.o
2186 +obj-$(CONFIG_SPEAKUP_APOLLO) += speakup_apollo.o
2187 +obj-$(CONFIG_SPEAKUP_AUDPTR) += speakup_audptr.o
2188 +obj-$(CONFIG_SPEAKUP_BNS) += speakup_bns.o
2189 +obj-$(CONFIG_SPEAKUP_DECEXT) += speakup_decext.o
2190 +obj-$(CONFIG_SPEAKUP_DECPC) += speakup_decpc.o
2191 +obj-$(CONFIG_SPEAKUP_DECTLK) += speakup_dectlk.o
2192 +obj-$(CONFIG_SPEAKUP_DTLK) += speakup_dtlk.o
2193 +obj-$(CONFIG_SPEAKUP_KEYPC) += speakup_keypc.o
2194 +obj-$(CONFIG_SPEAKUP_LTLK) += speakup_ltlk.o
2195 +obj-$(CONFIG_SPEAKUP_SFTSYN) += speakup_sftsyn.o
2196 +obj-$(CONFIG_SPEAKUP_SPKOUT) += speakup_spkout.o
2197 +obj-$(CONFIG_SPEAKUP_TXPRT) += speakup_txprt.o
2198 +
2199 +ifeq ($V,2.4)
2200 + include $(TOPDIR)/Rules.make
2201 +
2202 +speakupmap.h: speakupmap.map genmap
2203 + ./genmap speakupmap.map >$@
2204 +
2205 +genmap: genmap.c mapdata.h
2206 + cc -o genmap genmap.c
2207 +
2208 +mapdata.h: makemapdata.c keyinfo.h
2209 + cc -o makemapdata makemapdata.c
2210 + ./makemapdata >mapdata.h
2211 +
2212 +endif
2213 +speakupmain.o:speakup.o speakup_drvcommon.o
2214 + ld -r -o speakupmain.o speakup.o speakup_drvcommon.o
2215 +
2216 +$(obj)/speakupmap.h: $(src)/speakupmap.map $(src)/genmap
2217 + $(src)/genmap $(src)/speakupmap.map >$@
2218 +
2219 +$(obj)/mapdata.h: $(src)/keyinfo.h $(src)/makemapdata
2220 + $(src)/makemapdata >$@
2221 +
2222 +$(obj)/genmap: $(obj)/mapdata.h
2223 +
2224 +HOSTCFLAGS := -Iinclude -I/usr/include
2225 +hostprogs-y := makemapdata genmap
2226 --- /dev/null
2227 +++ b/drivers/char/speakup/cvsversion.h
2228 @@ -0,0 +1 @@
2229 +#define CVSVERSION " CVS: Fri Apr 13 13:49:34 EDT 2007 "
2230 --- /dev/null
2231 +++ b/drivers/char/speakup/dtload.c
2232 @@ -0,0 +1,553 @@
2233 +/*
2234 + * This is the DECtalk PC firmware loader for the Linux kernel, version 1.0
2235 + *
2236 + * Original 386BSD source:
2237 + * Copyright ( c ) 1996 Brian Buhrow <buhrow@lothlorien.nfbcal.org>
2238 + *
2239 + * Adapted for Linux:
2240 + * Copyright ( c ) 1997 Nicolas Pitre <nico@cam.org>
2241 + *
2242 + * Adapted for speakup:
2243 + * Copyright ( c ) 2003 David Borowski <david575@golden.net>
2244 + *
2245 + * All rights reserved.
2246 + *
2247 + * This program is free software; you can redistribute it and/or modify
2248 + * it under the terms of the GNU General Public License as published by
2249 + * the Free Software Foundation; either version 2 of the License, or
2250 + * ( at your option ) any later version.
2251 + *
2252 + * This program is distributed in the hope that it will be useful,
2253 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2254 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2255 + * GNU General Public License for more details.
2256 + *
2257 + * You should have received a copy of the GNU General Public License
2258 + * along with this program; if not, write to the Free Software
2259 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2260 + *
2261 + */
2262 +
2263 +#include <stdio.h>
2264 +#include <stdlib.h>
2265 +#include <unistd.h>
2266 +#include <string.h>
2267 +#include <sys/types.h>
2268 +#include <sys/stat.h>
2269 +#include <fcntl.h>
2270 +#include <malloc.h>
2271 +#include <sys/errno.h>
2272 +#include <asm/io.h>
2273 +#include "dtload.h"
2274 +#include "dtpc_reg.h"
2275 +
2276 +static int verbose = 0, intest = 0,infd = -1;
2277 +static int image_len, total_paras;
2278 +static int dt_stat, dma_state = 0, has_kernel = 0;
2279 +static struct dos_reloc fixups[512];
2280 +static char *read_buff = NULL;
2281 +static struct dos_exe_header header;
2282 +static u_short iobase = 0x350;
2283 +
2284 +static int dt_getstatus( )
2285 +{
2286 + dt_stat = inb_p( iobase )|(inb_p( iobase+1 )<<8);
2287 + return dt_stat;
2288 +}
2289 +
2290 +static void dt_sendcmd( u_int cmd )
2291 +{
2292 + outb_p( cmd & 0xFF, iobase );
2293 + outb_p( (cmd>>8) & 0xFF, iobase+1 );
2294 +}
2295 +
2296 +static int dt_waitbit( int bit )
2297 +{
2298 + int timeout = 100;
2299 + while ( --timeout > 0 ) {
2300 + if( (dt_getstatus( ) & bit ) == bit ) return 1;
2301 + usleep( 1000 );
2302 + }
2303 + return 0;
2304 +}
2305 +
2306 +static int dt_sendcmd_wait( u_int cmd, int bit )
2307 +{
2308 + int timeout = 1000;
2309 + outb_p( cmd & 0xFF, iobase );
2310 + outb_p( (cmd>>8) & 0xFF, iobase+1 );
2311 + while ( --timeout > 0 ) {
2312 + if( (dt_getstatus( ) & bit ) == bit ) return 1;
2313 + usleep( 1000 );
2314 + }
2315 + return 0;
2316 +}
2317 +
2318 +static int dt_waitmode( int pattern )
2319 +{
2320 + int timeout = 1000;
2321 + while ( --timeout > 0 ) {
2322 + if( dt_getstatus( ) == pattern ) return 1;
2323 + usleep( 1000 );
2324 + }
2325 + fprintf( stderr, "waitmode p=%x s = %x\n", pattern, dt_stat );
2326 + return 0;
2327 +}
2328 +
2329 +static int dt_wait_dma( )
2330 +{
2331 + int timeout = 1000, state = dma_state;
2332 + if( !has_kernel ){
2333 + usleep( 500 );
2334 + return( dt_waitbit( STAT_dma_ready ) );
2335 + }
2336 + if( ! dt_waitbit( STAT_dma_ready ) ) return 0;
2337 + while ( --timeout > 0 ) {
2338 + if( (dt_getstatus()&STAT_dma_state) == state ) return 1;
2339 + usleep( 1000 );
2340 + }
2341 + dma_state = dt_getstatus( ) & STAT_dma_state;
2342 + return 1;
2343 +}
2344 +
2345 +dt_ctrl( u_int cmd )
2346 +{
2347 + while ( ! dt_waitbit( STAT_cmd_ready ) ) usleep( 100 );
2348 + outb_p( 0, iobase+2 );
2349 + outb_p( 0, iobase+3 );
2350 + dt_getstatus( );
2351 + dt_sendcmd( CMD_control|cmd );
2352 + outb_p( 0, iobase+6 );
2353 + usleep( 100 );
2354 + dt_sendcmd( CMD_null );
2355 + while ( ! dt_waitbit( STAT_cmd_ready ) ) usleep( 100 );
2356 +}
2357 +
2358 +int dt_flush( void )
2359 +{
2360 + dt_ctrl( CTRL_flush );
2361 + dt_waitbit( STAT_dma_ready );
2362 + outb_p( DMA_sync, iobase+4 );
2363 + outb_p( 0, iobase+4 );
2364 + dma_state ^= STAT_dma_state;
2365 + while( dt_getstatus( ) & STAT_flushing ) usleep( 100 );
2366 + return 0;
2367 +}
2368 +
2369 +static int dt_sendbuff( char *src, int len )
2370 +{
2371 + while( len-- ){
2372 + if( ! dt_wait_dma( ) ) return -1;
2373 + if( ! (dt_getstatus( ) & STAT_rr_char) ) break;
2374 + outb_p( DMA_single_in, iobase+4 );
2375 + outb_p( *src++, iobase+4 );
2376 + dma_state ^= STAT_dma_state;
2377 + }
2378 + return 0;
2379 +}
2380 +
2381 +unsigned long dt_allocmem( unsigned long paras )
2382 +{
2383 + unsigned long addr;
2384 + if( ! dt_wait_dma( ) ) return 0;
2385 + outb_p( DMA_control, iobase+4 );
2386 + outb_p( DT_MEM_ALLOC, iobase+4 );
2387 + dma_state ^= STAT_dma_state;
2388 + if( ! dt_wait_dma( ) ) return 0;
2389 + outb_p( paras & 0xFF, iobase+4 );
2390 + outb_p( (paras>>8) & 0xFF, iobase+4 );
2391 + dma_state ^= STAT_dma_state;
2392 + if( ! dt_wait_dma( ) ) return 0;
2393 + addr = inb_p( iobase+4 );
2394 + addr |= (inb_p( iobase+4 )<<8);
2395 + addr += (inb_p( iobase+4 )<<4);
2396 + addr += (inb_p( iobase+4 )<<12);
2397 + dma_state ^= STAT_dma_state;
2398 + return addr;
2399 +}
2400 +
2401 +static int testkernel( void )
2402 +{
2403 + dt_sendcmd( CMD_sync );
2404 + if( ! dt_waitbit( STAT_cmd_ready ) ) return -10;
2405 + has_kernel = ( dt_stat&0x8000 ) ? 1 : 0;
2406 + if ( verbose ) printf( "testkernel got %x\n", dt_stat );
2407 + if ( has_kernel ) return 0;
2408 + usleep( 100 );
2409 + return 1;
2410 +}
2411 +
2412 +static int dt_loadmem( int addr, int len, char *src )
2413 +{
2414 + char c;
2415 + int l;
2416 + if ( verbose ) printf( "dt_loadmem: addr = %08X size = %d\n", addr, len );
2417 + do {
2418 + l = len;
2419 + if ( l >= 0xc000 ) l = 0xc000;
2420 + len -= l;
2421 + if( ! dt_wait_dma( ) ) return -1;
2422 + outb_p( DMA_control, iobase+4 );
2423 + outb_p( DT_LOAD_MEM, iobase+4 );
2424 + dma_state ^= STAT_dma_state;
2425 + if( ! dt_wait_dma( ) ) return -2;
2426 + outb_p( addr & 0xFF, iobase+4 );
2427 + outb_p( (addr>>8) & 0xFF, iobase+4 );
2428 + outb_p( (addr>>16) & 0xFF, iobase+4 );
2429 + outb_p( (addr>>24) & 0xFF, iobase+4 );
2430 + outb_p( l & 0xFF, iobase+4 );
2431 + outb_p( (l>>8) & 0xFF, iobase+4 );
2432 + dma_state ^= STAT_dma_state;
2433 + if( ! dt_wait_dma( ) ) return -3;
2434 + addr += l;
2435 + while( l-- ){
2436 + c = *src++;
2437 + outb_p( c, iobase+4 );
2438 + }
2439 + dma_state ^= STAT_dma_state;
2440 + } while ( len > 0 );
2441 + return 0;
2442 +}
2443 +
2444 +unsigned int loadfile ( char *filename )
2445 +{
2446 + int i, header_size;
2447 + unsigned int total_paras;
2448 + long fix;
2449 + infd = open ( filename, O_RDONLY );
2450 + if ( infd == -1 ) {
2451 + perror ( "Opening file: " );
2452 + return 0;
2453 + }
2454 + read ( infd, &header, sizeof ( struct dos_exe_header ) );
2455 + if ( header.id != 0x5a4d ) {
2456 + fprintf ( stderr, "Invalid header file format\n" );
2457 + fprintf ( stderr, "Want 0x5a4d, got 0x%x\n", header.id );
2458 + return 0;
2459 + }
2460 + if ( header.relen > MAX_FIXUPS ) {
2461 + fprintf ( stderr, "Too many fixups\n" );
2462 + return 0;
2463 + }
2464 + lseek ( infd, ( long ) header.reloc, SEEK_SET );
2465 + read ( infd, fixups, sizeof ( struct dos_reloc ) * header.relen );
2466 + header_size = header.hsize * 16;
2467 + lseek ( infd, ( long )header_size, SEEK_SET );
2468 + image_len = ( ( header.pages-1 )*512 ) + ( header.rem- header_size );
2469 + total_paras = ( image_len >> 4 ) + header.hmin + 16;
2470 + read ( infd, read_buff, image_len );
2471 + close( infd );
2472 + return total_paras;
2473 +}
2474 +
2475 +static int loadkernel( char *filename )
2476 +{
2477 + int segfix = 0x40, fix, i;
2478 + int ipval, csval;
2479 + if ( has_kernel ) return 0;
2480 + if ( !loadfile( filename ) ) return -1;
2481 + header.csval += segfix;
2482 + header.ssval += segfix;
2483 + if ( verbose ) {
2484 + printf ( "Loading kernel of %ld bytes ( %d relocs )\n",
2485 + image_len, header.relen );
2486 + printf ( " cs:ip == %04x:%04x ss:sp == %04x:%04x\n",
2487 + header.csval, header.ipval, header.ssval, header.spval );
2488 + }
2489 + for ( i = 0; i < header.relen; i++ ) {
2490 + fix = ( fixups[i].segment << 4 ) + fixups[i].offset;
2491 + ( *( unsigned int * ) &read_buff[fix] ) += segfix;
2492 + }
2493 + csval = header.csval;
2494 + ipval = header.ipval;
2495 + dt_sendcmd_wait( MODULE_reset, MODULE_init );
2496 + dt_sendcmd( CMD_reset );
2497 + if( dt_getstatus( ) == MODULE_self_test ){
2498 + if( ! dt_waitmode( MODULE_init ) ) return -1;
2499 + }
2500 + if ( !dt_sendcmd_wait( CMD_reset, MODE_status ) ) return -2;
2501 + if ( !dt_sendcmd_wait( CMD_sync, MODE_error ) ) return -3;
2502 + if ( !dt_sendcmd_wait( CMD_reset, MODE_status ) ) return -4;
2503 + if ( verbose ) printf( "card is ready\n" );
2504 + dt_sendcmd( CMD_dma );
2505 + if( ! dt_waitbit( STAT_dma_ready ) ) return -5;
2506 + if( ( i = dt_loadmem( 0x00000400, image_len, read_buff ) ) ) {
2507 + fprintf( stderr, "kernel load failed, status %d\n", i );
2508 + return -6;
2509 + }
2510 + usleep(100);
2511 + /* the kernel is loaded, start it */
2512 + if ( !dt_sendcmd_wait( CMD_reset, MODE_status ) ) return -7;
2513 + dt_sendcmd( CMD_dma+1 ); /**xxx**/
2514 + usleep(100);
2515 + if( ! dt_waitbit( STAT_dma_ready ) ) return-8;
2516 + outb_p( DMA_control, iobase+4 );
2517 + outb_p( DT_START_TASK, iobase+4 );
2518 + usleep(100);
2519 + outb_p( ipval & 0xFF, iobase+4 );
2520 + outb_p( (ipval>>8) & 0xFF, iobase+4 );
2521 + outb_p( csval & 0xFF, iobase+4 );
2522 + outb_p( (csval>>8) & 0xFF, iobase+4 );
2523 + if( ! dt_waitmode( 0xc001 ) ) return -9;
2524 + if ( verbose ) {
2525 + printf( "done loading kernel\n" );
2526 + }
2527 + return testkernel( );
2528 +}
2529 +
2530 +int loaddict ( char *filename, char *name, int type )
2531 +{
2532 + int i, read_index, read_size, act_size;
2533 + unsigned short *index_fix, seg_fix;
2534 + unsigned long entries, index, dic_bytes, dic_addr;
2535 + unsigned int total_paras;
2536 + unsigned long param, l;
2537 + infd = open ( filename, O_RDONLY );
2538 + if ( infd == -1 ) {
2539 + perror ( filename );
2540 + return -1;
2541 + }
2542 +/* read in the entry count and the actual entry size excluding the
2543 + * index table ( which is entries * 4 ) ... */
2544 + read ( infd, &entries, 4 );
2545 + read ( infd, &dic_bytes, 4 );
2546 + if ( verbose )
2547 + printf ( "Loading %s dictionary of %lu entries, %lu bytes.\n",
2548 + name, entries, dic_bytes );
2549 + total_paras = ( ( ( entries * 4 ) + dic_bytes ) >> 4 ) + 2;
2550 + if ( verbose )
2551 + printf ( "Allocating %d paragraphs of free ram ...\n", total_paras );
2552 + l = dt_allocmem( total_paras );
2553 + if ( l == 0 ) {
2554 + perror ( "Error requesting memory from speech device" );
2555 + return -1;
2556 + }
2557 + seg_fix = ( l >> 4 ) & 0xffff;
2558 + dic_addr = l;
2559 + index = entries;
2560 + index_fix = ( unsigned short * ) &read_buff[0];
2561 + if ( verbose )
2562 + printf ( "Index table starts at %lx\n", l );
2563 + read_index = index*4;
2564 + act_size = read ( infd, read_buff, read_index );
2565 + if ( act_size != read_index ) {
2566 + fprintf ( stderr, "\nError reading indexes\n" );
2567 + fprintf ( stderr, " exp : %d act : %d\n", read_index * 4, act_size );
2568 + return -1;
2569 + }
2570 + for ( i = 1; i < index * 2; i += 2 )
2571 + index_fix[i] += seg_fix;
2572 + if( ( i = dt_loadmem( l, read_index, read_buff ) ) ) {
2573 + fprintf ( stderr, "\nError loading indexes at 0x%lX: i %d\n",
2574 + l, i );
2575 + return -1;
2576 + }
2577 + l += read_index;
2578 +/* now, load up the dictionary bytes ... */
2579 + if ( verbose )
2580 + printf ( "Dictionary text starts at %lx\n", l );
2581 + read_size = dic_bytes;
2582 + if ( ( act_size = read ( infd, read_buff, read_size ) ) != read_size ) {
2583 + fprintf ( stderr, "\nError reading dictionary text!\n" );
2584 + fprintf ( stderr, "asked : %d actual : %d\n", act_size, read_size );
2585 + return -1;
2586 + }
2587 + if( ( i = dt_loadmem( l, read_size, read_buff ) ) ) {
2588 + fprintf ( stderr, "\nError loading dictionary at 0x%lX: status %d\n",
2589 + l, i );
2590 + return -1;
2591 + }
2592 + if( ! dt_wait_dma( ) ) return -1;
2593 + outb_p( DMA_control, iobase+4 );
2594 + outb_p( DT_SET_DIC, iobase+4 );
2595 + dma_state ^= STAT_dma_state;
2596 + if( ! dt_wait_dma( ) ) return -1;
2597 + l = dic_addr;
2598 + l = ((l << 12) & 0xFFFF0000) + (l & 0x0000000F);
2599 + outb_p( l & 0xFF, iobase+4 );
2600 + outb_p( (l>>8) & 0xFF, iobase+4 );
2601 + outb_p( (l>>16) & 0xFF, iobase+4 );
2602 + outb_p( (l>>24) & 0xFF, iobase+4 );
2603 + l = entries;
2604 + outb_p( l & 0xFF, iobase+4 );
2605 + outb_p( (l>>8) & 0xFF, iobase+4 );
2606 + outb_p( (l>>16) & 0xFF, iobase+4 );
2607 + outb_p( (l>>24) & 0xFF, iobase+4 );
2608 + l = type;
2609 + outb_p( l & 0xFF, iobase+4 );
2610 + outb_p( (l>>8) & 0xFF, iobase+4 );
2611 + dma_state ^= STAT_dma_state;
2612 + close ( infd );
2613 + if ( verbose ) printf( "dictionary load complete\n" );
2614 + return 0;
2615 +}
2616 +
2617 +int loadexe ( char *filename )
2618 +{
2619 + unsigned int load_addr = 0, seg_fix;
2620 + int i, read_size;
2621 + int ipval, csval;
2622 + long fix;
2623 + unsigned long total_paras;
2624 + total_paras = loadfile ( filename );
2625 + if ( total_paras == 0 ) return -1;
2626 + load_addr = dt_allocmem( total_paras );
2627 + if ( load_addr == 0 ) {
2628 + fprintf ( stderr, "Error allocating memory on card: " );
2629 + return -1;
2630 + }
2631 + seg_fix = ( load_addr >> 4 ) & 0xffff;
2632 + if ( verbose ) {
2633 + printf ( "Loading %s %ld bytes ( %d relocs )\n",
2634 + filename, image_len, header.relen );
2635 + printf ( "Allocating %ld bytes of free ram at %05x\n",
2636 + ( long ) header.hmin * 16, load_addr );
2637 + printf ( "Total memory taken is %ld bytes\n", ( long ) total_paras * 16 );
2638 + printf ( " cs:ip == %04x:%04x ss:sp == %04x:%04x\n",
2639 + header.csval + seg_fix, header.ipval, header.ssval + seg_fix, header.spval );
2640 + }
2641 + for ( i = 0; i < header.relen; i++ ) {
2642 + fix = ( ( long ) fixups[i].segment << 4 ) + ( long ) fixups[i].offset;
2643 + ( *( unsigned int * ) &read_buff[fix] ) += seg_fix;
2644 + }
2645 + if( ( i = dt_loadmem( load_addr, image_len, read_buff ) ) ) {
2646 + fprintf ( stderr, "Error loading speech device at 0x%lX: status %d\n",
2647 + load_addr, i );
2648 + return -1;
2649 + }
2650 + csval = header.csval + seg_fix;
2651 + ipval = header.ipval;
2652 + if( ! dt_wait_dma( ) ) return -1;
2653 + outb_p( DMA_control, iobase+4 );
2654 + outb_p( DT_START_TASK, iobase+4 );
2655 + dma_state ^= STAT_dma_state;
2656 + if( ! dt_wait_dma( ) ) return -1;
2657 + outb_p( ipval & 0xFF, iobase+4 );
2658 + outb_p( (ipval>>8) & 0xFF, iobase+4 );
2659 + outb_p( csval & 0xFF, iobase+4 );
2660 + outb_p( (csval>>8) & 0xFF, iobase+4 );
2661 + dma_state ^= STAT_dma_state;
2662 + return 0;
2663 +}
2664 +
2665 +void release_io( void )
2666 +{
2667 + ioperm( (long)iobase, 8, 0 );
2668 + ioperm( (long)0x0080, 1, 0 );
2669 + if ( read_buff ) free( read_buff );
2670 +}
2671 +
2672 +parseparm( char *parm, char *value )
2673 +{
2674 + char *cp = parm+strlen( parm );
2675 + while ( --cp > parm ) if ( *cp > ' ' ) break;
2676 + cp[1] = '\0';
2677 + if ( !strcmp( parm, "io" ) ) {
2678 + long io = strtol( value, 0, 0 );
2679 + if ( io >= 0x100 && io <= 0x350 ) {
2680 + iobase = (u_short)io;
2681 + return;
2682 + }
2683 + fprintf( stderr, "invalid io value %s\n", value );
2684 + exit( 1 );
2685 + } else if ( !strcmp( parm,"verbose" ) ) {
2686 + verbose = atoi( value );
2687 + }
2688 +}
2689 +
2690 +do_test( void )
2691 +{
2692 + char buffer[512];
2693 + int len;
2694 + dma_state = dt_getstatus( ) & STAT_dma_state;
2695 + while ( fgets( buffer, 510, stdin ) ) {
2696 + len = strlen( buffer );
2697 + if ( len == 1 ) dt_flush( );
2698 + else {
2699 + if ( buffer[len-1] == '\n' ) buffer[len-1] = '\013';
2700 + dt_sendbuff( buffer, len );
2701 + }
2702 + }
2703 + *buffer = '\013';
2704 + dt_sendbuff( buffer, 1 );
2705 +}
2706 +
2707 +int main ( int argc, char **argv )
2708 +{
2709 + char name[80], *cp;
2710 + char *dirname = 0, *confname = "dec_pc.conf";
2711 + char *init_msg = "[:ra 360] dec pc initialized\011";
2712 + FILE *confile;
2713 + struct stat statbuf;
2714 + int maxsize = 0, status = 0;
2715 + while ( --argc > 0 ) {
2716 + argv++;
2717 + if ( !strcmp( *argv, "-v" ) ) verbose = 1;
2718 + else if ( !strcmp( *argv, "-t" ) ) intest = 1;
2719 + else dirname = *argv;
2720 + }
2721 + if ( !dirname ) dirname = "/usr/local/lib/dec_pc";
2722 + if ( chdir( dirname ) != 0 ) {
2723 + fprintf( stderr, "cannot chdir to %s\n", dirname );
2724 + exit( 1 );
2725 + }
2726 + if ( !( confile = fopen( confname, "r" ) ) ) {
2727 + fprintf( stderr, "could not open %s", confname );
2728 + exit( 1 );
2729 + }
2730 + while ( fgets( name, 80, confile ) ) {
2731 + cp = strchr( name, '\n' );
2732 + if ( cp ) *cp = '\0';
2733 + if ( ( cp = strchr( name, '=' ) ) ) {
2734 + *cp++ = '\0';
2735 + parseparm( name, cp );
2736 + continue;
2737 + }
2738 + if ( stat( name, &statbuf ) != 0 ) {
2739 + fprintf( stderr, "cannot stat %s\n", name );
2740 + exit( 1 );
2741 + }
2742 + if ( statbuf.st_size > maxsize ) maxsize = statbuf.st_size;
2743 + }
2744 + rewind( confile );
2745 + if ( ioperm( (long)0x0080, 1, 1 ) || ioperm( (long)iobase, 8, 1 ) ) {
2746 + fprintf( stderr, "could not get ioperm\n" );
2747 + exit( 1 );
2748 + }
2749 + atexit( release_io );
2750 + if ( testkernel( ) == 0 ) {
2751 + if ( intest ) do_test( );
2752 + else fprintf( stderr, "kernel already loaded\n" );
2753 + exit( 0 );
2754 + }
2755 + read_buff = malloc( maxsize );
2756 + if ( !read_buff ) {
2757 + fprintf( stderr, "cannot malloc %d bytes\n", maxsize );
2758 + exit( 1 );
2759 + }
2760 + while ( fgets( name, 80, confile ) && !status ) {
2761 + cp = strchr( name, '\n' );
2762 + if ( cp ) *cp = '\0';
2763 + if ( strchr( name, '=' ) ) continue; /* a parameter */
2764 + if ( !( cp = strchr( name, '.' ) ) ) continue;
2765 + cp++;
2766 + if ( !strcmp ( cp, "dic" ) ) {
2767 + status = loaddict ( name, "primary", PRIMARY_DIC );
2768 + } else if ( !strcmp ( cp, "dtu" ) ) {
2769 + status = loaddict ( name, "user", USER_DIC );
2770 + } else if ( !strcmp ( cp, "dta" ) ) {
2771 + status = loaddict ( name, "abbreviation file", ABBREV_DIC );
2772 + } else if ( !strcmp ( cp, "exe" ) ) {
2773 + status = loadexe ( name );
2774 + } else if ( !strcmp ( cp, "sys" ) ) {
2775 + status = loadkernel ( name );
2776 + }
2777 + }
2778 + if ( status ) fprintf( stderr, "status %d\n", status );
2779 + fclose( confile );
2780 + if ( status ) exit( status );
2781 + dt_sendbuff( init_msg, strlen( init_msg ) );
2782 + sleep( 1 );
2783 + if ( intest ) do_test( );
2784 + exit( 0 );
2785 +}
2786 --- /dev/null
2787 +++ b/drivers/char/speakup/dtload.h
2788 @@ -0,0 +1,57 @@
2789 +/*
2790 + * This is the DECtalk PC firmware loader for the Linux kernel, version 1.0
2791 + *
2792 + * Original 386BSD source:
2793 + * Copyright (c) 1996 Brian Buhrow <buhrow@lothlorien.nfbcal.org>
2794 + *
2795 + * Adapted for Linux:
2796 + * Copyright (c) 1997 Nicolas Pitre <nico@cam.org>
2797 + *
2798 + * Adapted for speakup:
2799 + * Copyright (c) 2003 David Borowski <david575@golden.net>
2800 + *
2801 + * All rights reserved.
2802 + *
2803 + * This program is free software; you can redistribute it and/or modify
2804 + * it under the terms of the GNU General Public License as published by
2805 + * the Free Software Foundation; either version 2 of the License, or
2806 + * (at your option) any later version.
2807 + *
2808 + * This program is distributed in the hope that it will be useful,
2809 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2810 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2811 + * GNU General Public License for more details.
2812 + *
2813 + * You should have received a copy of the GNU General Public License
2814 + * along with this program; if not, write to the Free Software
2815 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2816 + *
2817 + */
2818 +
2819 +#define MAX_FIXUPS 512 /* maximum fixups per exe */
2820 +/*
2821 + * msdos .exe files will look like ...
2822 + */
2823 +
2824 +struct dos_exe_header {
2825 + unsigned short id; /* Linker's signature, must be 0x5a4d */
2826 + unsigned short rem; /* length of image mod 512 */
2827 + unsigned short pages; /* length of image in pages of 512 bytes */
2828 + unsigned short relen; /* number of relocation items */
2829 + unsigned short hsize; /* header size in paragraphs of 16 bytes */
2830 + unsigned short hmin; /* min # of paragraphs above prog end */
2831 + unsigned short hmax;
2832 + unsigned short ssval;
2833 + unsigned short spval; /* to be loaded in sp */
2834 + unsigned short checksum;
2835 + unsigned short ipval; /* to be loaded in ip */
2836 + unsigned short csval; /* segment offset to code */
2837 + unsigned short reloc; /* location of relocation items */
2838 + unsigned short ovrlay; /* overlay number */
2839 +};
2840 +
2841 +/* a dos relocation element looks like */
2842 +
2843 +struct dos_reloc {
2844 + short int offset, segment;
2845 +};
2846 --- /dev/null
2847 +++ b/drivers/char/speakup/dtpc_reg.h
2848 @@ -0,0 +1,132 @@
2849 +/*
2850 + * This is the DECtalk PC register constants (from DEC's DOS driver)
2851 + *
2852 + * Original code:
2853 + * Copyright (c) by Digital Equipment Corp.
2854 + *
2855 + * 386BSD DECtalk PC driver:
2856 + * Copyright (c) 1996 Brian Buhrow <buhrow@lothlorien.nfbcal.org>
2857 + *
2858 + * Linux DECtalk PC driver:
2859 + * Copyright (c) 1997 Nicolas Pitre <nico@cam.org>
2860 + *
2861 + * speakup DECtalk PC driver:
2862 + * Copyright (c) 2003 David Borowski <david575@golden.net>
2863 + *
2864 + * All rights reserved.
2865 + *
2866 + * This program is free software; you can redistribute it and/or modify
2867 + * it under the terms of the GNU General Public License as published by
2868 + * the Free Software Foundation; either version 2 of the License, or
2869 + * (at your option) any later version.
2870 + *
2871 + * This program is distributed in the hope that it will be useful,
2872 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2873 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2874 + * GNU General Public License for more details.
2875 + *
2876 + * You should have received a copy of the GNU General Public License
2877 + * along with this program; if not, write to the Free Software
2878 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2879 + *
2880 + */
2881 +
2882 +/*
2883 + * port interface defs ... used by dtpc.c
2884 + */
2885 +
2886 +#define MODULE_init 0x0dec /* module in boot code */
2887 +#define MODULE_self_test 0x8800 /* module in self-test */
2888 +#define MODULE_reset 0xffff /* reinit the whole module */
2889 +
2890 +#define MODE_mask 0xf000 /* mode bits in high nibble */
2891 +#define MODE_null 0x0000
2892 +#define MODE_test 0x2000 /* in testing mode */
2893 +#define MODE_status 0x8000
2894 +#define STAT_int 0x0001 /* running in interrupt mode */
2895 +#define STAT_tr_char 0x0002 /* character data to transmit */
2896 +#define STAT_rr_char 0x0004 /* ready to receive char data */
2897 +#define STAT_cmd_ready 0x0008 /* ready to accept commands */
2898 +#define STAT_dma_ready 0x0010 /* dma command ready */
2899 +#define STAT_digitized 0x0020 /* spc in digitized mode */
2900 +#define STAT_new_index 0x0040 /* new last index ready */
2901 +#define STAT_new_status 0x0080 /* new status posted */
2902 +#define STAT_dma_state 0x0100 /* dma state toggle */
2903 +#define STAT_index_valid 0x0200 /* indexs are valid */
2904 +#define STAT_flushing 0x0400 /* flush in progress */
2905 +#define STAT_self_test 0x0800 /* module in self test */
2906 +#define MODE_ready 0xc000 /* module ready for next phase */
2907 +#define READY_boot 0x0000
2908 +#define READY_kernel 0x0001
2909 +#define MODE_error 0xf000
2910 +
2911 +#define CMD_mask 0xf000 /* mask for command nibble */
2912 +#define CMD_null 0x0000 /* post status */
2913 +#define CMD_control 0x1000 /* hard control command */
2914 +#define CTRL_mask 0x0F00 /* mask off control nibble */
2915 +#define CTRL_data 0x00FF /* madk to get data byte */
2916 +#define CTRL_null 0x0000 /* null control */
2917 +#define CTRL_vol_up 0x0100 /* increase volume */
2918 +#define CTRL_vol_down 0x0200 /* decrease volume */
2919 +#define CTRL_vol_set 0x0300 /* set volume */
2920 +#define CTRL_pause 0x0400 /* pause spc */
2921 +#define CTRL_resume 0x0500 /* resume spc clock */
2922 +#define CTRL_resume_spc 0x0001 /* resume spc soft pause */
2923 +#define CTRL_flush 0x0600 /* flush all buffers */
2924 +#define CTRL_int_enable 0x0700 /* enable status change ints */
2925 +#define CTRL_buff_free 0x0800 /* buffer remain count */
2926 +#define CTRL_buff_used 0x0900 /* buffer in use */
2927 +#define CTRL_speech 0x0a00 /* immediate speech change */
2928 +#define CTRL_SP_voice 0x0001 /* voice change */
2929 +#define CTRL_SP_rate 0x0002 /* rate change */
2930 +#define CTRL_SP_comma 0x0003 /* comma pause change */
2931 +#define CTRL_SP_period 0x0004 /* period pause change */
2932 +#define CTRL_SP_rate_delta 0x0005 /* delta rate change */
2933 +#define CTRL_SP_get_param 0x0006 /* return the desired parameter */
2934 +#define CTRL_last_index 0x0b00 /* get last index spoken */
2935 +#define CTRL_io_priority 0x0c00 /* change i/o priority */
2936 +#define CTRL_free_mem 0x0d00 /* get free paragraphs on module */
2937 +#define CTRL_get_lang 0x0e00 /* return bit mask of loaded languages */
2938 +#define CMD_test 0x2000 /* self-test request */
2939 +#define TEST_mask 0x0F00 /* isolate test field */
2940 +#define TEST_null 0x0000 /* no test requested */
2941 +#define TEST_isa_int 0x0100 /* assert isa irq */
2942 +#define TEST_echo 0x0200 /* make data in == data out */
2943 +#define TEST_seg 0x0300 /* set peek/poke segment */
2944 +#define TEST_off 0x0400 /* set peek/poke offset */
2945 +#define TEST_peek 0x0500 /* data out == *peek */
2946 +#define TEST_poke 0x0600 /* *peek == data in */
2947 +#define TEST_sub_code 0x00FF /* user defined test sub codes */
2948 +#define CMD_id 0x3000 /* return software id */
2949 +#define ID_null 0x0000 /* null id */
2950 +#define ID_kernel 0x0100 /* kernel code executing */
2951 +#define ID_boot 0x0200 /* boot code executing */
2952 +#define CMD_dma 0x4000 /* force a dma start */
2953 +#define CMD_reset 0x5000 /* reset module status */
2954 +#define CMD_sync 0x6000 /* kernel sync command */
2955 +#define CMD_char_in 0x7000 /* single character send */
2956 +#define CMD_char_out 0x8000 /* single character get */
2957 +#define CHAR_count_1 0x0100 /* one char in cmd_low */
2958 +#define CHAR_count_2 0x0200 /* the second in data_low */
2959 +#define CHAR_count_3 0x0300 /* the third in data_high */
2960 +#define CMD_spc_mode 0x9000 /* change spc mode */
2961 +#define CMD_spc_to_text 0x0100 /* set to text mode */
2962 +#define CMD_spc_to_digit 0x0200 /* set to digital mode */
2963 +#define CMD_spc_rate 0x0400 /* change spc data rate */
2964 +#define CMD_error 0xf000 /* severe error */
2965 +
2966 +enum { PRIMARY_DIC = 0, USER_DIC, COMMAND_DIC, ABBREV_DIC };
2967 +
2968 +#define DMA_single_in 0x01
2969 +#define DMA_single_out 0x02
2970 +#define DMA_buff_in 0x03
2971 +#define DMA_buff_out 0x04
2972 +#define DMA_control 0x05
2973 +#define DT_MEM_ALLOC 0x03
2974 +#define DT_SET_DIC 0x04
2975 +#define DT_START_TASK 0x05
2976 +#define DT_LOAD_MEM 0x06
2977 +#define DT_READ_MEM 0x07
2978 +#define DT_DIGITAL_IN 0x08
2979 +#define DMA_sync 0x06
2980 +#define DMA_sync_char 0x07
2981 --- /dev/null
2982 +++ b/drivers/char/speakup/genmap.c
2983 @@ -0,0 +1,204 @@
2984 +#include <stdlib.h>
2985 +#include <stdio.h>
2986 +#include <libgen.h>
2987 +#include <string.h>
2988 +#include <linux/version.h>
2989 +#include <ctype.h>
2990 +
2991 +int get_define(void);
2992 +
2993 +#define MAXKEYS 512
2994 +#define MAXKEYVAL 160
2995 +#define HASHSIZE 101
2996 +#define is_shift -3
2997 +#define is_spk -2
2998 +#define is_input -1
2999 +typedef struct st_key_init t_key_init;
3000 +struct st_key_init {
3001 + char *name;
3002 + int value, shift;
3003 +};
3004 +typedef struct st_key t_key;
3005 +struct st_key {
3006 + char *name;
3007 + t_key *next;
3008 + int value, shift;
3009 +};
3010 +unsigned char key_data[MAXKEYVAL][16], *kp;
3011 +
3012 +#include "mapdata.h"
3013 +t_key key_table[MAXKEYS];
3014 +t_key *extra_keys = key_table+HASHSIZE;
3015 +char buffer[256], filename[256];
3016 +FILE *infile;
3017 +char delims[] = "\t\n ";
3018 +char *def_name, *def_val, *cp;
3019 +int map_ver = 119; /* an arbitrary number so speakup can check */
3020 +int lc, shift_table[17];
3021 +int max_states = 1, flags = 0;
3022 +/* flags reserved for later, maybe for individual console maps */
3023 +
3024 +void open_input( char *name )
3025 +{
3026 + strcpy( filename, name );
3027 + if ( ( infile = fopen( filename, "r" ) ) == 0 ) {
3028 + fprintf( stderr, "can't open %s, version %d\n", filename, LINUX_VERSION_CODE );
3029 + exit( 1 );
3030 + }
3031 + lc = 0;
3032 +}
3033 +
3034 +int
3035 +oops( char *msg, char *info )
3036 +{
3037 + if ( info == NULL ) info = " ";
3038 + fprintf( stderr, "error: file %s line %d\n", filename, lc );
3039 + fprintf( stderr, "%s %s\n", msg, info );
3040 + exit( 1 );
3041 +}
3042 +
3043 +t_key *hash_name( char *name )
3044 +{
3045 + u_char *pn = (u_char *)name;
3046 + int hash = 0;
3047 + while ( *pn ) {
3048 + hash = ( hash * 17 ) & 0xfffffff;
3049 + if ( isupper( *pn ) ) *pn = tolower( *pn );
3050 + hash += ( int )*pn;
3051 + pn++;
3052 + }
3053 + hash %= HASHSIZE;
3054 + return &key_table[hash];
3055 +}
3056 +
3057 +t_key *find_key( char *name )
3058 +{
3059 + t_key *this = hash_name( name );
3060 + while ( this ) {
3061 + if ( !strcmp( name, this->name ) ) return this;
3062 + this = this->next;
3063 + }
3064 + return this;
3065 +}
3066 +
3067 +t_key *add_key( char *name, int value, int shift )
3068 +{
3069 + t_key *this = hash_name( name );
3070 + if ( extra_keys-key_table >= MAXKEYS )
3071 + oops( "out of key table space, enlarge MAXKEYS", NULL );
3072 + if ( this->name != NULL ) {
3073 + while ( this->next ) {
3074 + if ( !strcmp( name, this->name ) )
3075 + oops( "attempt to add duplicate key", name );
3076 + this = this->next;
3077 + }
3078 + this->next = extra_keys++;
3079 + this = this->next;
3080 + }
3081 + this->name = strdup( name );
3082 + this->value = value;
3083 + this->shift = shift;
3084 + return this;
3085 +}
3086 +
3087 +int get_shift_value( int state )
3088 +{
3089 + int i;
3090 + for ( i = 0; shift_table[i] != state; i++ ) {
3091 + if ( shift_table[i] == -1 ) {
3092 + if ( i >= 16 )
3093 + oops( "too many shift states", NULL );
3094 + shift_table[i] = state;
3095 + max_states = i+1;
3096 + break;
3097 + }
3098 + }
3099 + return i;
3100 +}
3101 +
3102 +int
3103 +main( int argc, char *argv[] )
3104 +{
3105 + int value, shift_state, i, spk_val = 0, lock_val = 0;
3106 + int max_key_used = 0, num_keys_used = 0;
3107 + t_key *this;
3108 + t_key_init *p_init;
3109 +char *argpath, *argname, *argcopy;
3110 +
3111 + bzero( key_table, sizeof( key_table ) );
3112 + bzero( key_data, sizeof( key_data ) );
3113 + shift_table[0] = 0;
3114 + for ( i = 1; i <= 16; i++ ) shift_table[i] = -1;
3115 + if ( argc < 2 ) {
3116 + fputs( "usage: genmap filename\n", stderr );
3117 + exit( 1 );
3118 + }
3119 + for ( p_init = init_key_data; p_init->name[0] != '.'; p_init++ )
3120 + add_key( p_init->name, p_init->value, p_init->shift );
3121 + open_input( argv[1] );
3122 + while ( fgets( buffer, 250, infile ) ) {
3123 + lc++;
3124 + value = shift_state = 0;
3125 + cp = strtok( buffer, delims );
3126 + if ( *cp == '#' ) continue;
3127 + while ( cp ) {
3128 + if ( *cp == '=' ) break;
3129 + this = find_key( cp );
3130 + if ( this == NULL )
3131 + oops( "unknown key/modifier", cp );
3132 + if ( this->shift == is_shift ) {
3133 + if ( value )
3134 + oops( "modifiers must come first", cp );
3135 + shift_state += this->value;
3136 + } else if ( this->shift == is_input )
3137 + value = this->value;
3138 + else oops( "bad modifier or key", cp );
3139 + cp = strtok( 0, delims );
3140 + }
3141 + if ( !cp ) oops( "no = found", NULL );
3142 + cp = strtok( 0, delims );
3143 + if ( !cp ) oops( "no speakup function after =", NULL );
3144 + this = find_key( cp );
3145 + if ( this == NULL || this->shift != is_spk )
3146 + oops( "invalid speakup function", cp );
3147 + i = get_shift_value( shift_state );
3148 + if ( key_data[value][i] ) {
3149 + while ( --cp > buffer )
3150 + if ( !*cp ) *cp = ' ';
3151 + oops( "two functions on same key combination", cp );
3152 + }
3153 + key_data[value][i] = (char)this->value;
3154 + if ( value > max_key_used ) max_key_used = value;
3155 + }
3156 + fclose( infile );
3157 + this = find_key( "spk_key" );
3158 + if ( this ) spk_val = this->value;
3159 + this = find_key( "spk_lock" );
3160 + if ( this ) lock_val = this->value;
3161 + for ( lc = 1; lc <= max_key_used; lc++ ) {
3162 + kp = key_data[lc];
3163 + if ( !memcmp( key_data[0], kp, 16 ) ) continue;
3164 + num_keys_used++;
3165 + for ( i = 0; i < max_states; i++ ) {
3166 + if ( kp[i] != spk_val&& kp[i] != lock_val ) continue;
3167 + shift_state = shift_table[i];
3168 + if ( ( shift_state&16 ) ) continue;
3169 + shift_state = get_shift_value( shift_state+16 );
3170 + kp[shift_state] = kp[i];
3171 +/* fill in so we can process the key up, as spk bit will be set */
3172 + }
3173 + }
3174 + printf( "\t%d, %d, %d,\n\t", map_ver, num_keys_used, max_states );
3175 + for ( i = 0; i < max_states; i++ )
3176 + printf( "%d, ", shift_table[i] );
3177 + printf( "%d,", flags );
3178 + for ( lc = 1; lc <= max_key_used; lc++ ) {
3179 + kp = key_data[lc];
3180 + if ( !memcmp( key_data[0], kp, 16 ) ) continue;
3181 + printf( "\n\t%d,", lc );
3182 + for ( i = 0; i < max_states; i++ )
3183 + printf( " %d,", (unsigned int)kp[i] );
3184 + }
3185 + printf( "\n\t0, %d\n", map_ver );
3186 + exit( 0 );
3187 +}
3188 --- /dev/null
3189 +++ b/drivers/char/speakup/keyinfo.h
3190 @@ -0,0 +1,120 @@
3191 +/* spk_priv.h
3192 + review functions for the speakup screen review package.
3193 + originally written by: Kirk Reiser and Andy Berdan.
3194 +
3195 + extensively modified by David Borowski.
3196 +
3197 + Copyright (C ) 1998 Kirk Reiser.
3198 + Copyright (C ) 2003 David Borowski.
3199 +
3200 + This program is free software; you can redistribute it and/or modify
3201 + it under the terms of the GNU General Public License as published by
3202 + the Free Software Foundation; either version 2 of the License, or
3203 + (at your option ) any later version.
3204 +
3205 + This program is distributed in the hope that it will be useful,
3206 + but WITHOUT ANY WARRANTY; without even the implied warranty of
3207 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3208 + GNU General Public License for more details.
3209 +
3210 + You should have received a copy of the GNU General Public License
3211 + along with this program; if not, write to the Free Software
3212 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3213 +*/
3214 +
3215 +enum { /* var_ids */
3216 + VERSION = 0, SYNTH, SILENT, SYNTH_DIRECT,
3217 + KEYMAP, CHARS,
3218 + PUNC_SOME, PUNC_MOST, PUNC_ALL,
3219 + DELIM, REPEATS, EXNUMBER,
3220 + DELAY, TRIGGER, JIFFY, FULL, /* all timers must be together */
3221 + BLEEP_TIME, CURSOR_TIME, BELL_POS,
3222 +SAY_CONTROL, SAY_WORD_CTL, NO_INTERRUPT, KEY_ECHO,
3223 + SPELL_DELAY, PUNC_LEVEL, READING_PUNC,
3224 + ATTRIB_BLEEP, BLEEPS,
3225 + RATE, PITCH, VOL, TONE, PUNCT, VOICE, FREQ, LANG,
3226 + CAPS_START, CAPS_STOP, CHARTAB,
3227 + MAXVARS
3228 +};
3229 +
3230 +#define FIRST_SYNTH_VAR RATE
3231 +/* 0 is reserved for no remap */
3232 +#define SPEAKUP_GOTO 0x01
3233 +#define SPEECH_KILL 0x02
3234 +#define SPEAKUP_QUIET 0x03
3235 +#define SPEAKUP_CUT 0x04
3236 +#define SPEAKUP_PASTE 0x05
3237 +#define SAY_FIRST_CHAR 0x06
3238 +#define SAY_LAST_CHAR 0x07
3239 +#define SAY_CHAR 0x08
3240 +#define SAY_PREV_CHAR 0x09
3241 +#define SAY_NEXT_CHAR 0x0a
3242 +#define SAY_WORD 0x0b
3243 +#define SAY_PREV_WORD 0x0c
3244 +#define SAY_NEXT_WORD 0x0d
3245 +#define SAY_LINE 0x0e
3246 +#define SAY_PREV_LINE 0x0f
3247 +#define SAY_NEXT_LINE 0x10
3248 +#define TOP_EDGE 0x11
3249 +#define BOTTOM_EDGE 0x12
3250 +#define LEFT_EDGE 0x13
3251 +#define RIGHT_EDGE 0x14
3252 +#define SPELL_PHONETIC 0x15
3253 +#define SPELL_WORD 0x16
3254 +#define SAY_SCREEN 0x17
3255 +#define SAY_POSITION 0x18
3256 +#define SAY_ATTRIBUTES 0x19
3257 +#define SPEAKUP_OFF 0x1a
3258 +#define SPEAKUP_PARKED 0x1b
3259 +#define SAY_LINE_INDENT 0x1c
3260 +#define SAY_FROM_TOP 0x1d
3261 +#define SAY_TO_BOTTOM 0x1e
3262 +#define SAY_FROM_LEFT 0x1f
3263 +#define SAY_TO_RIGHT 0x20
3264 +#define SAY_CHAR_NUM 0x21
3265 +#define EDIT_SOME 0x22
3266 +#define EDIT_MOST 0x23
3267 +#define SAY_PHONETIC_CHAR 0x24
3268 +#define EDIT_DELIM 0x25
3269 +#define EDIT_REPEAT 0x26
3270 +#define EDIT_EXNUM 0x27
3271 +#define SET_WIN 0x28
3272 +#define CLEAR_WIN 0x29
3273 +#define ENABLE_WIN 0x2a
3274 +#define SAY_WIN 0x2b
3275 +#define SPK_LOCK 0x2c
3276 +#define SPEAKUP_HELP 0x2d
3277 +#define TOGGLE_CURSORING 0x2e
3278 +#define READ_ALL_DOC 0x2f
3279 +#define SPKUP_MAX_FUNC 0x30 /* one greater than the last func handler */
3280 +
3281 +#define SPK_KEY 0x80
3282 +#define FIRST_EDIT_BITS 0x22
3283 +
3284 +#define FIRST_SET_VAR SPELL_DELAY
3285 +#define VAR_START 0x40 /* increase if adding more than 0x3f functions */
3286 +
3287 +/* keys for setting variables, must be ordered same as the enum for var_ids */
3288 +/* with dec being even and inc being 1 greater */
3289 +#define SPELL_DELAY_DEC VAR_START+0
3290 +#define SPELL_DELAY_INC SPELL_DELAY_DEC+1
3291 +#define PUNC_LEVEL_DEC SPELL_DELAY_DEC+2
3292 +#define PUNC_LEVEL_INC PUNC_LEVEL_DEC+1
3293 +#define READING_PUNC_DEC PUNC_LEVEL_DEC+2
3294 +#define READING_PUNC_INC READING_PUNC_DEC+1
3295 +#define ATTRIB_BLEEP_DEC READING_PUNC_DEC+2
3296 +#define ATTRIB_BLEEP_INC ATTRIB_BLEEP_DEC+1
3297 +#define BLEEPS_DEC ATTRIB_BLEEP_DEC+2
3298 +#define BLEEPS_INC BLEEPS_DEC+1
3299 +#define RATE_DEC BLEEPS_DEC+2
3300 +#define RATE_INC RATE_DEC+1
3301 +#define PITCH_DEC RATE_DEC+2
3302 +#define PITCH_INC PITCH_DEC+1
3303 +#define VOL_DEC PITCH_DEC+2
3304 +#define VOL_INC VOL_DEC+1
3305 +#define TONE_DEC VOL_DEC+2
3306 +#define TONE_INC TONE_DEC+1
3307 +#define PUNCT_DEC TONE_DEC+2
3308 +#define PUNCT_INC PUNCT_DEC+1
3309 +#define VOICE_DEC PUNCT_DEC+2
3310 +#define VOICE_INC VOICE_DEC+1
3311 --- /dev/null
3312 +++ b/drivers/char/speakup/makemapdata.c
3313 @@ -0,0 +1,156 @@
3314 +#include <stdlib.h>
3315 +#include <stdio.h>
3316 +#include <libgen.h>
3317 +#include <string.h>
3318 +#include <linux/version.h>
3319 +#include <ctype.h>
3320 +
3321 +int get_define(void);
3322 +
3323 +#define MAXKEYS 512
3324 +#define MAXKEYVAL 160
3325 +#define HASHSIZE 101
3326 +#define is_shift -3
3327 +#define is_spk -2
3328 +#define is_input -1
3329 +typedef struct st_key t_key;
3330 +struct st_key {
3331 + char *name;
3332 + t_key *next;
3333 + int value, shift;
3334 +};
3335 +
3336 +t_key key_table[MAXKEYS];
3337 +t_key *extra_keys = key_table+HASHSIZE;
3338 +char buffer[256], filename[256];
3339 +FILE *infile;
3340 +char delims[] = "\t\n ";
3341 +char *dir_name, *def_name, *def_val, *cp;
3342 +int lc;
3343 +
3344 +void open_input( char *name )
3345 +{
3346 + sprintf( filename, "%s/%s", dir_name, name );
3347 + if ( ( infile = fopen( filename, "r" ) ) == 0 ) {
3348 + fprintf( stderr, "can't open %s\n", filename );
3349 + exit( 1 );
3350 + }
3351 + lc = 0;
3352 +}
3353 +
3354 +int
3355 +oops( char *msg, char *info )
3356 +{
3357 + if ( info == NULL ) info = " ";
3358 + fprintf( stderr, "error: file %s line %d\n", filename, lc );
3359 + fprintf( stderr, "%s %s\n", msg, info );
3360 + exit( 1 );
3361 +}
3362 +
3363 +int get_define( )
3364 +{
3365 + while ( fgets( buffer, 250, infile ) ) {
3366 + lc++;
3367 + if ( strncmp( buffer, "#define", 7 ) ) continue;
3368 + strtok( buffer, delims );
3369 + def_name = strtok( 0, delims );
3370 + def_val = strtok( 0, delims );
3371 + if ( def_val != NULL ) return 1;
3372 + }
3373 + fclose( infile );
3374 + infile = 0;
3375 + return 0;
3376 +}
3377 +
3378 +t_key *hash_name( char *name )
3379 +{
3380 + u_char *pn = (u_char *)name;
3381 + int hash = 0;
3382 + while ( *pn ) {
3383 + hash = ( hash * 17 ) & 0xfffffff;
3384 + if ( isupper( *pn ) ) *pn = tolower( *pn );
3385 + hash += ( int )*pn;
3386 + pn++;
3387 + }
3388 + hash %= HASHSIZE;
3389 + return &key_table[hash];
3390 +}
3391 +
3392 +t_key *find_key( char *name )
3393 +{
3394 + t_key *this = hash_name( name );
3395 + while ( this ) {
3396 + if ( !strcmp( name, this->name ) ) return this;
3397 + this = this->next;
3398 + }
3399 + return this;
3400 +}
3401 +
3402 +t_key *add_key( char *name, int value, int shift )
3403 +{
3404 + t_key *this = hash_name( name );
3405 + if ( extra_keys-key_table >= MAXKEYS )
3406 + oops( "out of key table space, enlarge MAXKEYS", NULL );
3407 + if ( this->name != NULL ) {
3408 + while ( this->next ) {
3409 + if ( !strcmp( name, this->name ) )
3410 + oops( "attempt to add duplicate key", name );
3411 + this = this->next;
3412 + }
3413 + this->next = extra_keys++;
3414 + this = this->next;
3415 + }
3416 + this->name = strdup( name );
3417 + this->value = value;
3418 + this->shift = shift;
3419 + return this;
3420 +}
3421 +
3422 +int
3423 +main( int argc, char *argv[] )
3424 +{
3425 + int value, i;
3426 + t_key *this;
3427 + dir_name = getenv( "TOPDIR" );
3428 + if ( !dir_name ) dir_name = "/usr/src/linux";
3429 + bzero( key_table, sizeof( key_table ) );
3430 + add_key( "shift", 1, is_shift );
3431 + add_key( "altgr", 2, is_shift );
3432 + add_key( "ctrl", 4, is_shift );
3433 + add_key( "alt", 8, is_shift );
3434 + add_key( "spk", 16, is_shift );
3435 + add_key( "double", 32, is_shift );
3436 + open_input( "include/linux/input.h" );
3437 + while ( get_define( ) ) {
3438 + if ( strncmp( def_name, "KEY_", 4 ) ) continue;
3439 + value = atoi( def_val );
3440 + if ( value > 0 && value < MAXKEYVAL )
3441 + add_key( def_name, value, is_input );
3442 + }
3443 + open_input( "drivers/char/speakup/keyinfo.h" );
3444 + while ( get_define( ) ) {
3445 + if ( strlen( def_val ) > 5 ) {
3446 + if ( !( cp = strchr( def_val, '+' ) ) ) continue;
3447 + *cp++ = '\0';
3448 + this = find_key( def_val );
3449 + if ( !this || *cp < '0' || *cp > '9' ) continue;
3450 + value = this->value+atoi( cp );
3451 + } else if ( !strncmp( def_val, "0x", 2 ) )
3452 + sscanf( def_val+2, "%x", &value );
3453 + else if ( *def_val >= '0' && *def_val <= '9' )
3454 + value = atoi( def_val );
3455 + else continue;
3456 + add_key( def_name, value, is_spk );
3457 + }
3458 + printf( "t_key_init init_key_data[] = {\n" );
3459 + for ( i = 0; i < HASHSIZE; i++ ) {
3460 + this = &key_table[i];
3461 + if ( !this->name ) continue;
3462 + do {
3463 + printf( "\t\"%s\", %d, %d,\n", this->name, this->value, this->shift );
3464 + this = this->next;
3465 + } while ( this );
3466 + }
3467 + printf( "\t\".\", 0, 0\n};\n" );
3468 + exit( 0 );
3469 +}
3470 --- /dev/null
3471 +++ b/drivers/char/speakup/mod_code.c
3472 @@ -0,0 +1,22 @@
3473 +/* this code is to modularize a synth specific file, included at the end */
3474 +
3475 +static void __exit mod_synth_exit( void )
3476 +{
3477 + if ( synth == &MY_SYNTH )
3478 + synth_release( );
3479 + synth_remove( &MY_SYNTH );
3480 +}
3481 +
3482 +static int __init mod_synth_init( void )
3483 +{
3484 + int status = do_synth_init( &MY_SYNTH );
3485 + if ( status != 0 ) return status;
3486 + synth_add( &MY_SYNTH );
3487 + return 0;
3488 +}
3489 +
3490 +module_init( mod_synth_init );
3491 +module_exit( mod_synth_exit );
3492 +MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
3493 +MODULE_DESCRIPTION("Synthesizer driver module for speakup for the synth->long_name");
3494 +MODULE_LICENSE( "GPL" );
3495 --- /dev/null
3496 +++ b/drivers/char/speakup/serialio.h
3497 @@ -0,0 +1,18 @@
3498 +#ifndef SSPK_SERIAL
3499 +#define SSPK_SERIAL
3500 +
3501 +#include <linux/serial.h> /* for rs_table, serial constants &
3502 + serial_uart_config */
3503 +#include <linux/serial_reg.h> /* for more serial constants */
3504 +#include <linux/serialP.h> /* for struct serial_state */
3505 +#include <asm/serial.h>
3506 +
3507 +#define SPK_SERIAL_TIMEOUT 1000000 /* countdown values for serial timeouts */
3508 +#define SPK_XMITR_TIMEOUT 1000000 /* countdown values transmitter/dsr timeouts */
3509 +#define SPK_LO_TTY 0 /* check ttyS0 ... ttyS3 */
3510 +#define SPK_HI_TTY 3
3511 +#define NUM_DISABLE_TIMEOUTS 3 /* # of timeouts permitted before disable */
3512 +#define SPK_TIMEOUT 100 /* buffer timeout in ms */
3513 +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
3514 +
3515 +#endif
3516 --- /dev/null
3517 +++ b/drivers/char/speakup/speakup.c
3518 @@ -0,0 +1,2877 @@
3519 +/* speakup.c
3520 + review functions for the speakup screen review package.
3521 + originally written by: Kirk Reiser and Andy Berdan.
3522 +
3523 + extensively modified by David Borowski.
3524 +
3525 + Copyright (C ) 1998 Kirk Reiser.
3526 + Copyright (C ) 2003 David Borowski.
3527 +
3528 + This program is free software; you can redistribute it and/or modify
3529 + it under the terms of the GNU General Public License as published by
3530 + the Free Software Foundation; either version 2 of the License, or
3531 + (at your option ) any later version.
3532 +
3533 + This program is distributed in the hope that it will be useful,
3534 + but WITHOUT ANY WARRANTY; without even the implied warranty of
3535 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3536 + GNU General Public License for more details.
3537 +
3538 + You should have received a copy of the GNU General Public License
3539 + along with this program; if not, write to the Free Software
3540 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3541 +*/
3542 +
3543 +#include <linux/kernel.h>
3544 +#include <linux/version.h>
3545 +#include <linux/vt.h>
3546 +#include <linux/tty.h>
3547 +#include <linux/mm.h> /* __get_free_page( ) and friends */
3548 +#include <linux/vt_kern.h>
3549 +#include <linux/ctype.h>
3550 +#include <linux/selection.h>
3551 +#include <asm/uaccess.h> /* copy_from|to|user( ) and others */
3552 +#include <linux/unistd.h>
3553 +
3554 +#include <linux/keyboard.h> /* for KT_SHIFT */
3555 +#include <linux/kbd_kern.h> /* for vc_kbd_* and friends */
3556 +#include <linux/vt_kern.h>
3557 +#include <linux/input.h>
3558 +#include <linux/kmod.h>
3559 +#include <linux/speakup.h>
3560 +
3561 +#include "cvsversion.h"
3562 +#include "spk_priv.h"
3563 +#include <linux/bootmem.h> /* for alloc_bootmem */
3564 +
3565 +/* speakup_*_selection */
3566 +#include <linux/module.h>
3567 +#include <linux/sched.h>
3568 +#include <linux/slab.h>
3569 +#include <linux/types.h>
3570 +#include <asm/uaccess.h>
3571 +#include <linux/consolemap.h>
3572 +
3573 +#define SPEAKUP_VERSION "Speakup v-2.00" CVSVERSION
3574 +#define MAX_DELAY ( (500 * HZ ) / 1000 )
3575 +#define KEY_MAP_VER 119
3576 +#define MINECHOCHAR SPACE
3577 +
3578 +/* these are globals from the kernel code */
3579 +extern struct kbd_struct * kbd;
3580 +extern int fg_console;
3581 +extern short punc_masks[];
3582 +
3583 +static special_func special_handler = NULL;
3584 +special_func help_handler = NULL;
3585 +
3586 +short pitch_shift = 0, synth_flags = 0;
3587 +static char buf[256];
3588 +short attrib_bleep = 0, bleeps = 0, bleep_time = 1;
3589 +short no_intr = 0, spell_delay = 0;
3590 +short key_echo = 0, cursor_timeout = 120, say_word_ctl = 0;
3591 +short say_ctrl = 0, bell_pos = 0;
3592 +short punc_mask = 0, punc_level = 0, reading_punc = 0;
3593 +char str_caps_start[MAXVARLEN+1] = "\0", str_caps_stop[MAXVARLEN+1] = "\0";
3594 +static const struct st_bits_data punc_info[] = {
3595 + { "none", "", 0 },
3596 + { "some", "/$%&@", SOME },
3597 + { "most", "$%&#()=+*/@^<>|\\", MOST },
3598 + { "all", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", PUNC },
3599 + { "delimiters", "", B_WDLM },
3600 + { "repeats", "()", CH_RPT },
3601 + { "extended numeric", "", B_EXNUM },
3602 + { "symbols", "", B_SYM },
3603 + { 0, 0 }
3604 +};
3605 +static char mark_cut_flag = 0;
3606 +char synth_name[10] = CONFIG_SPEAKUP_DEFAULT;
3607 +#define MAX_KEY 160
3608 +u_char *our_keys[MAX_KEY], *shift_table;
3609 +static u_char key_buf[600];
3610 +static const u_char key_defaults[] = {
3611 +#include "speakupmap.h"
3612 +};
3613 +
3614 +/* Speakup Cursor Track Variables */
3615 +static int cursor_track = 1, prev_cursor_track = 1;
3616 +
3617 +/* cursor track modes, must be ordered same as cursor_msgs */
3618 +enum {
3619 + CT_Off = 0,
3620 + CT_On,
3621 + CT_Highlight,
3622 + CT_Window,
3623 + CT_Max
3624 +};
3625 +#define read_all_mode CT_Max
3626 +
3627 +struct tty_struct *tty;
3628 +#define key_handler k_handler
3629 +typedef void (*k_handler_fn)(struct vc_data *vc, unsigned char value,
3630 + char up_flag);
3631 +extern k_handler_fn key_handler[16];
3632 +static k_handler_fn do_shift, do_spec, do_latin, do_cursor;
3633 +EXPORT_SYMBOL_GPL(help_handler);
3634 +EXPORT_SYMBOL_GPL(special_handler);
3635 +EXPORT_SYMBOL_GPL(our_keys);
3636 +EXPORT_SYMBOL_GPL(synth_name);
3637 +
3638 +static void spkup_write(const char *in_buf, int count);
3639 +static int set_mask_bits(const char *input, const int which, const int how);
3640 +
3641 +static const char str_ctl[] = "control-";
3642 +static const char *colors[] = {
3643 + "black", "blue", "green", "cyan", "red", "magenta", "yellow", "white",
3644 + "grey"
3645 +};
3646 +
3647 +static char *phonetic[] = {
3648 + "alpha", "beta", "charley", "delta", "echo", "fox", "gamma", "hotel",
3649 + "india", "juleiet", "keelo", "leema", "mike", "november", "oscar",
3650 + "papa",
3651 + "quebec", "romeo", "seeara", "tango", "uniform", "victer", "wiskey",
3652 + "x ray", "yankee", "zooloo"
3653 +};
3654 +
3655 +// array of 256 char pointers (one for each character description )
3656 +// initialized to default_chars and user selectable via /proc/speakup/characters
3657 +static char *characters[256];
3658 +
3659 +static char *default_chars[256] = {
3660 + "null", "^a", "^b", "^c", "^d", "^e", "^f", "^g",
3661 + "^h", "^i", "^j", "^k", "^l", "^m", "^n", "^o",
3662 + "^p", "^q", "^r", "^s", "^t", "^u", "^v", "^w",
3663 + "^x", "^y", "^z", NULL, NULL, NULL, NULL, NULL,
3664 + "space", "bang!", "quote", "number", "dollar", "percent", "and",
3665 + "tick",
3666 + "left paren", "right paren", "star", "plus", "comma", "dash", "dot",
3667 + "slash",
3668 + "zero", "one", "two", "three", "four", "five", "six", "seven",
3669 + "eight", "nine",
3670 + "colon", "semmy", "less", "equals", "greater", "question", "at",
3671 + "eigh", "b", "c", "d", "e", "f", "g",
3672 + "h", "i", "j", "k", "l", "m", "n", "o",
3673 + "p", "q", "r", "s", "t", "u", "v", "w", "x",
3674 + "y", "zehd", "left bracket", "backslash", "right bracket", "caret",
3675 + "line",
3676 + "accent", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3677 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3678 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3679 + NULL, NULL, NULL, "left brace", "bar", "right brace", "tihlduh",
3680 + "delta", "see cedilla", "u oomlout", "e acute", /* 128 */
3681 + "eigh circumflex", "eigh oomlout", "eigh grave", "eigh ring", /* 132 */
3682 + "see cedilla", "e circumflex", "e oomlout", "e grave", /* 136 */
3683 + "i oomlout", "i circumflex", "i grave", "eigh oomlout", /* 140 */
3684 + "eigh ring", "e acute", "eigh e dipthong", "eigh e dipthong", /* 144 */
3685 + "o circumflex", "o oomlout", "o grave", "u circumflex", /* 148 */
3686 + "u grave", "y oomlout", "o oomlout", "u oomlout", /* 152 */
3687 + "cents", "pounds", "yen", "peseta", /* 156 */
3688 + "florin", "eigh acute", "i acute", "o acute", /* 160 */
3689 + "u acute", "n tilde", "n tilde", "feminine ordinal", /* 164 */
3690 + "masculin ordinal", "inverted question", "reversed not", "not", /* 168 */
3691 + "half", "quarter", "inverted bang", "much less than", /* 172 */
3692 + "much greater than", "dark shading", "medium shading", /* 176 */
3693 + "light shading", "verticle line", "left tee", /* 179 */
3694 + "double left tee", "left double tee", "double top right", /* 182 */
3695 + "top double right", "double left double tee", /* 185 */
3696 + "double vertical line", "double top double right", /* 187 */
3697 + "double bottom double right", "double bottom right", /* 189 */
3698 + "bottom double right", "top right", "left bottom", /* 191 */
3699 + "up tee", "tee down", "tee right", "horizontal line", /* 194 */
3700 + "cross bars", "tee double right", "double tee right", /* 198 */
3701 + "double left double bottom", "double left double top", /* 201 */
3702 + "double up double tee", "double tee double down", /* 203 */
3703 + "double tee double right", "double horizontal line", /* 205 */
3704 + "double cross bars", "up double tee", "double up tee", /* 207 */
3705 + "double tee down", "tee double down", /* 210 */
3706 + "double left bottom", "left double bottom", /* 212 */
3707 + "double left top", "left double top", /* 214 */
3708 + "double vertical cross", "double horizontal cross", /* 216 */
3709 + "bottom right", "left top", "solid square", /* 218 */
3710 + "solid lower half", "solid left half", "solid right half", /* 221 */
3711 + "solid upper half", "alpha", "beta", "gamma", /* 224 */
3712 + "pie", "sigma", "sigma", "mu", /* 228 */
3713 + "tou", "phigh", "thayta", "ohmega", /* 232 */
3714 + "delta", "infinity", "phigh", "epsilaun", /* 236 */
3715 +"intersection", "identical to", "plus or minus", "equal grater than", /* 240 */
3716 + "less than equal", "upper integral", "lower integral", /* 244 */
3717 + "divided by", "almost equal", "degrees", /* 247 */
3718 + "centre dot", "bullet", "square root", /* 250 */
3719 + "power", "squared", "black square", "white space" /* 252 */
3720 +};
3721 +
3722 +// array of 256 u_short (one for each character)
3723 +// initialized to default_chartab and user selectable via /proc/speakup/chartab
3724 +static u_short spk_chartab[256];
3725 +
3726 +static u_short default_chartab[256] = {
3727 + B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 0-7 */
3728 + B_CTL, B_CTL, A_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 8-15 */
3729 + B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /*16-23 */
3730 + B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 24-31 */
3731 +WDLM, A_PUNC, PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC, /* !"#$%&' */
3732 +PUNC, PUNC, PUNC, PUNC, A_PUNC, A_PUNC, A_PUNC, PUNC, /* ( )*+, -./ */
3733 +NUM, NUM, NUM, NUM, NUM, NUM, NUM, NUM, /* 01234567 */
3734 +NUM, NUM, A_PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC, /* 89:;<=>? */
3735 +PUNC, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* @ABCDEFG */
3736 +A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* HIJKLMNO */
3737 +A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* PQRSTUVW */
3738 +A_CAP, A_CAP, A_CAP, PUNC, PUNC, PUNC, PUNC, PUNC, /* XYZ[\]^_ */
3739 +PUNC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* `abcdefg */
3740 +ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* hijklmno */
3741 +ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* pqrstuvw */
3742 +ALPHA, ALPHA, ALPHA, PUNC, PUNC, PUNC, PUNC, 0, /* xyz{|}~ */
3743 +B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 128-135 */
3744 +B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_CAPSYM, /* 136-143 */
3745 +B_CAPSYM, B_CAPSYM, B_SYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 144-151 */
3746 +B_SYM, B_SYM, B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 152-159 */
3747 +B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_CAPSYM, B_SYM, /* 160-167 */
3748 +B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 168-175 */
3749 +B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 176-183 */
3750 +B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 184-191 */
3751 +B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 192-199 */
3752 +B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 200-207 */
3753 +B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 208-215 */
3754 +B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 216-223 */
3755 +B_SYM, B_SYM, B_SYM, B_CAPSYM, B_SYM, B_CAPSYM, B_SYM, B_SYM, /* 224-231 */
3756 +B_SYM, B_CAPSYM, B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 232-239 */
3757 +B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 240-247 */
3758 +B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM /* 248-255 */
3759 +};
3760 +
3761 +static int spk_keydown = 0;
3762 +static u_char spk_lastkey = 0, spk_close_press = 0, keymap_flags = 0;
3763 +static u_char last_keycode = 0, this_speakup_key = 0;
3764 +static u_long last_spk_jiffy = 0;
3765 +
3766 +struct st_spk_t *speakup_console[MAX_NR_CONSOLES];
3767 +
3768 +static int spk_setup(char *str)
3769 +{
3770 + int ints[4];
3771 + str = get_options(str, ARRAY_SIZE (ints), ints);
3772 + if (ints[0] > 0 && ints[1] >= 0)
3773 + synth_port_forced = ints[1];
3774 + return 1;
3775 +}
3776 +
3777 +static int spk_ser_setup(char *str)
3778 +{
3779 + const int lookup[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
3780 + int ints[4];
3781 + str = get_options(str, ARRAY_SIZE (ints), ints);
3782 + if (ints[0] > 0 && ints[1] >= 0)
3783 + synth_port_forced = lookup[ints[1]];
3784 + return 1;
3785 +}
3786 +
3787 +static int spk_synth_setup(char *str)
3788 +{
3789 + size_t len = min_t(size_t, strlen(str), 9);
3790 + memcpy (synth_name, str, len);
3791 + synth_name[len] = '\0';
3792 + return 1;
3793 +}
3794 +
3795 +static int spk_quiet_setup(char *str)
3796 +{
3797 + if (strchr("1yt", *str) != NULL)
3798 + quiet_boot = 1;
3799 + return 1;
3800 +}
3801 +
3802 +__setup("speakup_port=", spk_setup);
3803 +__setup("speakup_ser=", spk_ser_setup);
3804 +__setup("speakup_synth=", spk_synth_setup);
3805 +__setup("speakup_quiet=", spk_quiet_setup);
3806 +
3807 +static unsigned char get_attributes(u16 *pos)
3808 +{
3809 + return (u_char)(scr_readw(pos) >> 8);
3810 +}
3811 +
3812 +static void speakup_date(struct vc_data *vc)
3813 +{
3814 + spk_x = spk_cx = vc->vc_x;
3815 + spk_y = spk_cy = vc->vc_y;
3816 + spk_pos = spk_cp = vc->vc_pos;
3817 + spk_old_attr = spk_attr;
3818 + spk_attr = get_attributes((u_short *) spk_pos);
3819 +}
3820 +
3821 +char *strlwr(char *s)
3822 +{
3823 + char *p;
3824 + for (p = s; *p; p++)
3825 + if (*p >= CAP_A && *p <= CAP_Z)
3826 + *p |= 32;
3827 + return s;
3828 +}
3829 +
3830 +static void bleep(u_short val)
3831 +{
3832 + static const short vals[] = {
3833 + 350, 370, 392, 414, 440, 466, 491, 523, 554, 587, 619, 659
3834 + };
3835 + short freq;
3836 + int time = bleep_time;
3837 + freq = vals[val%12];
3838 + if (val > 11)
3839 + freq *= (1 << (val/12));
3840 + kd_mksound(freq, time);
3841 +}
3842 +
3843 +static void speakup_shut_up(struct vc_data *vc)
3844 +{
3845 + if (spk_killed)
3846 + return;
3847 + spk_shut_up |= 0x01;
3848 + spk_parked &= 0xfe;
3849 + speakup_date(vc);
3850 + if (synth != NULL)
3851 + do_flush();
3852 +}
3853 +
3854 +static void speech_kill(struct vc_data *vc)
3855 +{
3856 + char val = synth->is_alive();
3857 + if (val == 0)
3858 + return;
3859 +
3860 + /* re-enables synth, if disabled */
3861 + if (val == 2 || spk_killed) { /* dead */
3862 + spk_shut_up &= ~0x40;
3863 + synth_write_msg("Eyem a Lighve!");
3864 + } else {
3865 + synth_write_msg("You killed speak up!");
3866 + spk_shut_up |= 0x40;
3867 + }
3868 +}
3869 +
3870 +static void speakup_off(struct vc_data *vc)
3871 +{
3872 + if (spk_shut_up & 0x80) {
3873 + spk_shut_up &= 0x7f;
3874 + synth_write_msg("hey. That's better!" );
3875 + } else {
3876 + spk_shut_up |= 0x80;
3877 + synth_write_msg("You turned me off!" );
3878 + }
3879 + speakup_date(vc);
3880 +}
3881 +
3882 +static void speakup_parked(struct vc_data *vc)
3883 +{
3884 + if (spk_parked & 0x80) {
3885 + spk_parked = 0;
3886 + synth_write_msg ("unparked!");
3887 + } else {
3888 + spk_parked |= 0x80;
3889 + synth_write_msg ("parked!");
3890 + }
3891 +}
3892 +
3893 +/* ------ cut and paste ----- */
3894 +/* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
3895 +#undef isspace
3896 +#define isspace(c) ((c) == ' ')
3897 +/* Variables for selection control. */
3898 +static struct vc_data *spk_sel_cons; /* defined in selection.c must not be disallocated */
3899 +static volatile int sel_start = -1; /* cleared by clear_selection */
3900 +static int sel_end;
3901 +static int sel_buffer_lth;
3902 +static char *sel_buffer;
3903 +
3904 +static unsigned char sel_pos(int n)
3905 +{
3906 + return inverse_translate(spk_sel_cons, screen_glyph(spk_sel_cons, n));
3907 +}
3908 +
3909 +static u16 get_char(struct vc_data *vc, u16 *pos)
3910 +{
3911 + u16 ch = ' ';
3912 + if (vc && pos) {
3913 + u16 w = scr_readw(pos);
3914 + u16 c = w & 0xff;
3915 +
3916 + if (w & vc->vc_hi_font_mask)
3917 + c |= 0x100;
3918 +
3919 + ch = w & 0xff00;
3920 + ch |= inverse_translate(vc, c);
3921 + }
3922 + return ch;
3923 +}
3924 +
3925 +static void speakup_clear_selection(void)
3926 +{
3927 + sel_start = -1;
3928 +}
3929 +
3930 +/* does screen address p correspond to character at LH/RH edge of screen? */
3931 +static int atedge(const int p, int size_row)
3932 +{
3933 + return (!(p % size_row) || !((p + 2) % size_row));
3934 +}
3935 +
3936 +/* constrain v such that v <= u */
3937 +static unsigned short limit(const unsigned short v, const unsigned short u)
3938 +{
3939 + return (v > u) ? u : v;
3940 +}
3941 +
3942 +static unsigned short xs, ys, xe, ye; /* our region points */
3943 +
3944 +static int speakup_set_selection(struct tty_struct *tty)
3945 +{
3946 + int new_sel_start, new_sel_end;
3947 + char *bp, *obp;
3948 + int i, ps, pe;
3949 + struct vc_data *vc = vc_cons[fg_console].d;
3950 +
3951 + xs = limit(xs, vc->vc_cols - 1);
3952 + ys = limit(ys, vc->vc_rows - 1);
3953 + xe = limit(xe, vc->vc_cols - 1);
3954 + ye = limit(ye, vc->vc_rows - 1);
3955 + ps = ys * vc->vc_size_row + (xs << 1);
3956 + pe = ye * vc->vc_size_row + (xe << 1);
3957 +
3958 + if (ps > pe) { /* make sel_start <= sel_end */
3959 + int tmp = ps;
3960 + ps = pe;
3961 + pe = tmp;
3962 + }
3963 +
3964 + if (spk_sel_cons != vc_cons[fg_console].d) {
3965 + speakup_clear_selection();
3966 + spk_sel_cons = vc_cons[fg_console].d;
3967 + printk(KERN_WARNING "Selection: mark console not the same as cut\n");
3968 + return -EINVAL;
3969 + }
3970 +
3971 + new_sel_start = ps;
3972 + new_sel_end = pe;
3973 +
3974 + /* select to end of line if on trailing space */
3975 + if (new_sel_end > new_sel_start &&
3976 + !atedge(new_sel_end, vc->vc_size_row) &&
3977 + isspace(sel_pos(new_sel_end))) {
3978 + for (pe = new_sel_end + 2; ; pe += 2)
3979 + if (!isspace(sel_pos(pe)) ||
3980 + atedge(pe, vc->vc_size_row))
3981 + break;
3982 + if (isspace(sel_pos(pe)))
3983 + new_sel_end = pe;
3984 + }
3985 + if ((new_sel_start == sel_start) && (new_sel_end == sel_end))
3986 + return 0; /* no action required */
3987 +
3988 + sel_start = new_sel_start;
3989 + sel_end = new_sel_end;
3990 + /* Allocate a new buffer before freeing the old one ... */
3991 + bp = kmalloc((sel_end-sel_start)/2+1, GFP_ATOMIC);
3992 + if (!bp) {
3993 + printk(KERN_WARNING "selection: kmalloc() failed\n");
3994 + speakup_clear_selection();
3995 + return -ENOMEM;
3996 + }
3997 + if (sel_buffer)
3998 + kfree(sel_buffer);
3999 + sel_buffer = bp;
4000 +
4001 + obp = bp;
4002 + for (i = sel_start; i <= sel_end; i += 2) {
4003 + *bp = sel_pos(i);
4004 + if (!isspace(*bp++))
4005 + obp = bp;
4006 + if (! ((i + 2) % vc->vc_size_row)) {
4007 + /* strip trailing blanks from line and add newline,
4008 + unless non-space at end of line. */
4009 + if (obp != bp) {
4010 + bp = obp;
4011 + *bp++ = '\r';
4012 + }
4013 + obp = bp;
4014 + }
4015 + }
4016 + sel_buffer_lth = bp - sel_buffer;
4017 + return 0;
4018 +}
4019 +
4020 +static int speakup_paste_selection(struct tty_struct *tty)
4021 +{
4022 + struct vc_data *vc = (struct vc_data *) tty->driver_data;
4023 + int pasted = 0, count;
4024 + DECLARE_WAITQUEUE(wait, current);
4025 + add_wait_queue(&vc->paste_wait, &wait);
4026 + while (sel_buffer && sel_buffer_lth > pasted) {
4027 + set_current_state(TASK_INTERRUPTIBLE);
4028 + if (test_bit(TTY_THROTTLED, &tty->flags)) {
4029 + schedule();
4030 + continue;
4031 + }
4032 + count = sel_buffer_lth - pasted;
4033 + count = min_t(int, count, tty->receive_room);
4034 + tty->ldisc.receive_buf(tty, sel_buffer + pasted, 0, count);
4035 + pasted += count;
4036 + }
4037 + remove_wait_queue(&vc->paste_wait, &wait);
4038 + current->state = TASK_RUNNING;
4039 + return 0;
4040 +}
4041 +
4042 +static void speakup_cut(struct vc_data *vc)
4043 +{
4044 + static const char err_buf[] = "set selection failed";
4045 + int ret;
4046 +
4047 + if (!mark_cut_flag) {
4048 + mark_cut_flag = 1;
4049 + xs = spk_x;
4050 + ys = spk_y;
4051 + spk_sel_cons = vc;
4052 + synth_write_msg("mark");
4053 + return;
4054 + }
4055 + xe = (u_short) spk_x;
4056 + ye = (u_short) spk_y;
4057 + mark_cut_flag = 0;
4058 + synth_write_msg ("cut");
4059 +
4060 + speakup_clear_selection();
4061 + ret = speakup_set_selection(tty);
4062 +
4063 + switch (ret) {
4064 + case 0:
4065 + break; /* no error */
4066 + case -EFAULT :
4067 + pr_warn( "%sEFAULT\n", err_buf );
4068 + break;
4069 + case -EINVAL :
4070 + pr_warn( "%sEINVAL\n", err_buf );
4071 + break;
4072 + case -ENOMEM :
4073 + pr_warn( "%sENOMEM\n", err_buf );
4074 + break;
4075 + }
4076 +}
4077 +
4078 +static void speakup_paste(struct vc_data *vc)
4079 +{
4080 + if (mark_cut_flag) {
4081 + mark_cut_flag = 0;
4082 + synth_write_msg("mark, cleared");
4083 + } else {
4084 + synth_write_msg ("paste");
4085 + speakup_paste_selection(tty);
4086 + }
4087 +}
4088 +
4089 +static void say_attributes(struct vc_data *vc )
4090 +{
4091 + int fg = spk_attr & 0x0f;
4092 + int bg = spk_attr>>4;
4093 + if (fg > 8) {
4094 + synth_write_string("bright ");
4095 + fg -= 8;
4096 + }
4097 + synth_write_string(colors[fg]);
4098 + if (bg > 7) {
4099 + synth_write_string(" on blinking ");
4100 + bg -= 8;
4101 + } else
4102 + synth_write_string(" on ");
4103 + synth_write_msg(colors[bg]);
4104 +}
4105 +
4106 +static char *blank_msg = "blank";
4107 +static char *edges[] = { "top, ", "bottom, ", "left, ", "right, ", "" };
4108 +enum {
4109 + edge_top = 1,
4110 + edge_bottom,
4111 + edge_left,
4112 + edge_right,
4113 + edge_quiet
4114 +};
4115 +
4116 +static void announce_edge(struct vc_data *vc, int msg_id)
4117 +{
4118 + if (bleeps & 1)
4119 + bleep(spk_y);
4120 + if (bleeps & 2)
4121 + synth_write_msg(edges[msg_id-1]);
4122 +}
4123 +
4124 +static void speak_char( u_char ch)
4125 +{
4126 + char *cp = characters[ch];
4127 + if (cp == NULL) {
4128 + pr_info ("speak_char: cp==NULL!\n");
4129 + return;
4130 + }
4131 + synth_buffer_add(SPACE);
4132 + if (IS_CHAR(ch, B_CAP)) {
4133 + pitch_shift++;
4134 + synth_write_string(str_caps_start);
4135 + synth_write_string(cp);
4136 + synth_write_string(str_caps_stop);
4137 + } else {
4138 + if (*cp == '^') {
4139 + synth_write_string(str_ctl);
4140 + cp++;
4141 + }
4142 + synth_write_string(cp);
4143 + }
4144 + synth_buffer_add(SPACE);
4145 +}
4146 +
4147 +static void say_char(struct vc_data *vc)
4148 +{
4149 + u_short ch;
4150 + spk_old_attr = spk_attr;
4151 + ch = get_char(vc, (u_short *) spk_pos);
4152 + spk_attr = (ch >> 8);
4153 + if (spk_attr != spk_old_attr) {
4154 + if (attrib_bleep & 1)
4155 + bleep(spk_y);
4156 + if (attrib_bleep & 2)
4157 + say_attributes(vc);
4158 + }
4159 + speak_char(ch & 0xff);
4160 +}
4161 +
4162 +static void say_phonetic_char(struct vc_data *vc)
4163 +{
4164 + u_short ch;
4165 + spk_old_attr = spk_attr;
4166 + ch = get_char(vc, (u_short *) spk_pos);
4167 + spk_attr = ((ch & 0xff00) >> 8);
4168 + if (IS_CHAR(ch, B_ALPHA)) {
4169 + ch &= 0x1f;
4170 + synth_write_msg(phonetic[--ch] );
4171 + } else {
4172 + if (IS_CHAR(ch, B_NUM))
4173 + synth_write_string("number ");
4174 + speak_char(ch);
4175 + }
4176 +}
4177 +
4178 +static void say_prev_char(struct vc_data *vc)
4179 +{
4180 + spk_parked |= 0x01;
4181 + if (spk_x == 0) {
4182 + announce_edge(vc, edge_left);
4183 + return;
4184 + }
4185 + spk_x--;
4186 + spk_pos -= 2;
4187 + say_char(vc);
4188 +}
4189 +
4190 +static void say_next_char(struct vc_data *vc)
4191 +{
4192 + spk_parked |= 0x01;
4193 + if (spk_x == vc->vc_cols - 1) {
4194 + announce_edge(vc, edge_right);
4195 + return;
4196 + }
4197 + spk_x++;
4198 + spk_pos += 2;
4199 + say_char(vc);
4200 +}
4201 +
4202 +/* get_word - will first check to see if the character under the
4203 + reading cursor is a space and if say_word_ctl is true it will
4204 + return the word space. If say_word_ctl is not set it will check to
4205 + see if there is a word starting on the next position to the right
4206 + and return that word if it exists. If it does not exist it will
4207 + move left to the beginning of any previous word on the line or the
4208 + beginning off the line whichever comes first.. */
4209 +
4210 +static u_long get_word(struct vc_data *vc)
4211 +{
4212 + u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos;
4213 + char ch;
4214 + u_short attr_ch;
4215 + spk_old_attr = spk_attr;
4216 + ch = (char) get_char(vc, (u_short *) tmp_pos);
4217 +
4218 +/* decided to take out the sayword if on a space (mis-information */
4219 + if (say_word_ctl && ch == SPACE) {
4220 + *buf = '\0';
4221 + synth_write_msg("space");
4222 + return 0;
4223 + } else if ((tmpx < vc->vc_cols - 2)
4224 + && (ch == SPACE || IS_WDLM(ch ))
4225 + && ((char) get_char (vc, (u_short * ) tmp_pos+1 ) > SPACE)) {
4226 + tmp_pos += 2;
4227 + tmpx++;
4228 + } else
4229 + while (tmpx > 0 ) {
4230 + ch = (char) get_char(vc, (u_short *) tmp_pos - 1);
4231 + if ((ch == SPACE || IS_WDLM(ch))
4232 + && ((char) get_char(vc, (u_short *) tmp_pos) > SPACE))
4233 + break;
4234 + tmp_pos -= 2;
4235 + tmpx--;
4236 + }
4237 + attr_ch = get_char(vc, (u_short *) tmp_pos);
4238 + spk_attr = attr_ch >> 8;
4239 + buf[cnt++] = attr_ch & 0xff;
4240 + while (tmpx < vc->vc_cols - 1) {
4241 + tmp_pos += 2;
4242 + tmpx++;
4243 + ch = (char) get_char(vc, (u_short *) tmp_pos);
4244 + if ((ch == SPACE) || (IS_WDLM(buf[cnt-1]) && (ch > SPACE)))
4245 + break;
4246 + buf[cnt++] = ch;
4247 + }
4248 + buf[cnt] = '\0';
4249 + return cnt;
4250 +}
4251 +
4252 +static void say_word(struct vc_data *vc)
4253 +{
4254 + u_long cnt = get_word(vc );
4255 + u_short saved_punc_mask = punc_mask;
4256 + if (cnt == 0)
4257 + return;
4258 + punc_mask = PUNC;
4259 + buf[cnt++] = SPACE;
4260 + spkup_write(buf, cnt);
4261 + punc_mask = saved_punc_mask;
4262 +}
4263 +
4264 +static void say_prev_word(struct vc_data *vc)
4265 +{
4266 + char ch;
4267 + u_short edge_said = 0, last_state = 0, state = 0;
4268 + spk_parked |= 0x01;
4269 + if (spk_x == 0) {
4270 + if (spk_y == 0) {
4271 + announce_edge(vc, edge_top);
4272 + return;
4273 + }
4274 + spk_y--;
4275 + spk_x = vc->vc_cols;
4276 + edge_said = edge_quiet;
4277 + }
4278 + while (1) {
4279 + if (spk_x == 0) {
4280 + if (spk_y == 0) {
4281 + edge_said = edge_top;
4282 + break;
4283 + }
4284 + if (edge_said != edge_quiet)
4285 + edge_said = edge_left;
4286 + if (state > 0)
4287 + break;
4288 + spk_y--;
4289 + spk_x = vc->vc_cols - 1;
4290 + } else spk_x--;
4291 + spk_pos -= 2;
4292 + ch = (char) get_char(vc, (u_short *) spk_pos);
4293 + if (ch == SPACE)
4294 + state = 0;
4295 + else if (IS_WDLM(ch))
4296 + state = 1;
4297 + else state = 2;
4298 + if (state < last_state) {
4299 + spk_pos += 2;
4300 + spk_x++;
4301 + break;
4302 + }
4303 + last_state = state;
4304 + }
4305 + if (spk_x == 0 && edge_said == edge_quiet)
4306 + edge_said = edge_left;
4307 + if (edge_said > 0 && edge_said < edge_quiet)
4308 + announce_edge(vc, edge_said);
4309 + say_word(vc);
4310 +}
4311 +
4312 +static void say_next_word(struct vc_data *vc)
4313 +{
4314 + char ch;
4315 + u_short edge_said = 0, last_state = 2, state = 0;
4316 + spk_parked |= 0x01;
4317 + if (spk_x == vc->vc_cols - 1 && spk_y == vc->vc_rows - 1) {
4318 + announce_edge(vc, edge_bottom);
4319 + return;
4320 + }
4321 + while (1) {
4322 + ch = (char) get_char(vc, (u_short *) spk_pos );
4323 + if (ch == SPACE)
4324 + state = 0;
4325 + else if (IS_WDLM(ch))
4326 + state = 1;
4327 + else state = 2;
4328 + if (state > last_state) break;
4329 + if (spk_x >= vc->vc_cols - 1) {
4330 + if (spk_y == vc->vc_rows - 1) {
4331 + edge_said = edge_bottom;
4332 + break;
4333 + }
4334 + state = 0;
4335 + spk_y++;
4336 + spk_x = 0;
4337 + edge_said = edge_right;
4338 + } else spk_x++;
4339 + spk_pos += 2;
4340 + last_state = state;
4341 + }
4342 + if (edge_said > 0)
4343 + announce_edge(vc, edge_said);
4344 + say_word(vc);
4345 +}
4346 +
4347 +static void spell_word(struct vc_data *vc)
4348 +{
4349 + static char *delay_str[] = { " ", ", ", ". ", ". . ", ". . . " };
4350 + char *cp = buf, *str_cap = str_caps_stop;
4351 + char *cp1, *last_cap = str_caps_stop;
4352 + u_char ch;
4353 + if (!get_word(vc))
4354 + return;
4355 + while ((ch = (u_char) *cp)) {
4356 + if (cp != buf)
4357 + synth_write_string(delay_str[spell_delay]);
4358 + if (IS_CHAR(ch, B_CAP)) {
4359 + str_cap = str_caps_start;
4360 + if (*str_caps_stop)
4361 + pitch_shift++;
4362 + else /* synth has no pitch */
4363 + last_cap = str_caps_stop;
4364 + } else
4365 + str_cap = str_caps_stop;
4366 + if (str_cap != last_cap) {
4367 + synth_write_string(str_cap);
4368 + last_cap = str_cap;
4369 + }
4370 + if (this_speakup_key == SPELL_PHONETIC
4371 + && (IS_CHAR(ch, B_ALPHA))) {
4372 + ch &= 31;
4373 + cp1 = phonetic[--ch];
4374 + } else {
4375 + cp1 = characters[ch];
4376 + if (*cp1 == '^') {
4377 + synth_write_string(str_ctl);
4378 + cp1++;
4379 + }
4380 + }
4381 + synth_write_string(cp1);
4382 + cp++;
4383 + }
4384 + if (str_cap != str_caps_stop)
4385 + synth_write_string(str_caps_stop);
4386 +}
4387 +
4388 +static int get_line(struct vc_data *vc)
4389 +{
4390 + u_long tmp = spk_pos - (spk_x * 2);
4391 + int i = 0;
4392 + spk_old_attr = spk_attr;
4393 + spk_attr = get_attributes((u_short *) spk_pos);
4394 + for (i = 0; i < vc->vc_cols; i++) {
4395 + buf[i] = (u_char) get_char(vc, (u_short *) tmp);
4396 + tmp += 2;
4397 + }
4398 + for (--i; i >= 0; i--)
4399 + if (buf[i] != SPACE)
4400 + break;
4401 + return ++i;
4402 +}
4403 +
4404 +static void say_line(struct vc_data *vc)
4405 +{
4406 + int i = get_line(vc);
4407 + char *cp;
4408 + char num_buf[8];
4409 + u_short saved_punc_mask = punc_mask;
4410 + if (i == 0) {
4411 + synth_write_msg(blank_msg);
4412 + return;
4413 + }
4414 + buf[i++] = '\n';
4415 + if (this_speakup_key == SAY_LINE_INDENT) {
4416 + for (cp = buf; *cp == SPACE; cp++)
4417 + ;
4418 + sprintf(num_buf, "%d, ", (cp - buf) + 1);
4419 + synth_write_string(num_buf);
4420 + }
4421 + punc_mask = punc_masks[reading_punc];
4422 + spkup_write(buf, i);
4423 + punc_mask = saved_punc_mask;
4424 +}
4425 +
4426 +static void say_prev_line(struct vc_data *vc)
4427 +{
4428 + spk_parked |= 0x01;
4429 + if (spk_y == 0) {
4430 + announce_edge(vc, edge_top);
4431 + return;
4432 + }
4433 + spk_y--;
4434 + spk_pos -= vc->vc_size_row;
4435 + say_line(vc);
4436 +}
4437 +
4438 +static void say_next_line(struct vc_data *vc)
4439 +{
4440 + spk_parked |= 0x01;
4441 + if (spk_y == vc->vc_rows - 1) {
4442 + announce_edge(vc, edge_bottom);
4443 + return;
4444 + }
4445 + spk_y++;
4446 + spk_pos += vc->vc_size_row;
4447 + say_line(vc);
4448 +}
4449 +
4450 +static int say_from_to(struct vc_data *vc, u_long from, u_long to,
4451 + int read_punc)
4452 +{
4453 + int i = 0;
4454 + u_short saved_punc_mask = punc_mask;
4455 + spk_old_attr = spk_attr;
4456 + spk_attr = get_attributes((u_short *) from);
4457 + while (from < to) {
4458 + buf[i++] = (char) get_char(vc, (u_short *) from);
4459 + from += 2;
4460 + if (i >= vc->vc_size_row)
4461 + break;
4462 + }
4463 + for (--i; i >= 0; i--)
4464 + if (buf[i] != SPACE)
4465 + break;
4466 + buf[++i] = SPACE;
4467 + buf[++i] = '\0';
4468 + if (i < 1)
4469 + return i;
4470 + if (read_punc)
4471 + punc_mask = punc_info[reading_punc].mask;
4472 + spkup_write(buf, i);
4473 + if (read_punc)
4474 + punc_mask = saved_punc_mask;
4475 + return i - 1;
4476 +}
4477 +
4478 +static void say_line_from_to(struct vc_data *vc, u_long from, u_long to,
4479 + int read_punc)
4480 +{
4481 + u_long start = vc->vc_origin + (spk_y * vc->vc_size_row);
4482 + u_long end = start + (to * 2);
4483 + start += from * 2;
4484 + if (say_from_to(vc, start, end, read_punc) <= 0)
4485 + if (cursor_track != read_all_mode)
4486 + synth_write_msg(blank_msg);
4487 +}
4488 +
4489 +// Sentence Reading Commands
4490 +
4491 +void synth_insert_next_index(int);
4492 +
4493 +static int currsentence;
4494 +static int numsentences[2];
4495 +static char *sentbufend[2];
4496 +static char *sentmarks[2][10];
4497 +static int currbuf=0;
4498 +static int bn;
4499 +static char sentbuf[2][256];
4500 +
4501 +static int say_sentence_num(int num , int prev)
4502 +{
4503 + bn = currbuf;
4504 + currsentence = num + 1;
4505 + if (prev && --bn == -1)
4506 + bn = 1;
4507 +
4508 + if (num > numsentences[bn])
4509 + return 0;
4510 +
4511 + spkup_write(sentmarks[bn][num], sentbufend[bn] - sentmarks[bn][num]);
4512 + return 1;
4513 +}
4514 +
4515 +static int get_sentence_buf(struct vc_data *vc, int read_punc)
4516 +{
4517 + u_long start, end;
4518 + int i, bn;
4519 + currbuf++;
4520 + if (currbuf == 2)
4521 + currbuf = 0;
4522 + bn = currbuf;
4523 + start = vc->vc_origin + ((spk_y) *vc->vc_size_row);
4524 + end = vc->vc_origin+((spk_y) *vc->vc_size_row) + vc->vc_cols * 2;
4525 +
4526 + numsentences[bn] = 0;
4527 + sentmarks[bn][0] = &sentbuf[bn][0];
4528 + i = 0;
4529 + spk_old_attr = spk_attr;
4530 + spk_attr = get_attributes((u_short *) start);
4531 +
4532 + while (start < end) {
4533 + sentbuf[bn][i] = (char) get_char(vc, (u_short *) start);
4534 + if (i > 0) {
4535 + if (sentbuf[bn][i] == SPACE && sentbuf[bn][i-1] == '.'
4536 + && numsentences[bn] < 9) {
4537 + // Sentence Marker
4538 + numsentences[bn]++;
4539 + sentmarks[bn][numsentences[bn]] =
4540 + &sentbuf[bn][i];
4541 + }
4542 + }
4543 + i++;
4544 + start += 2;
4545 + if (i >= vc->vc_size_row)
4546 + break;
4547 + }
4548 +
4549 + for (--i; i >= 0; i--)
4550 + if (sentbuf[bn][i] != SPACE)
4551 + break;
4552 +
4553 + if (i < 1)
4554 + return -1;
4555 +
4556 + sentbuf[bn][++i] = SPACE;
4557 + sentbuf[bn][++i] = '\0';
4558 +
4559 + sentbufend[bn] = &sentbuf[bn][i];
4560 + return numsentences[bn];
4561 +}
4562 +
4563 +static void say_screen_from_to(struct vc_data *vc, u_long from, u_long to)
4564 +{
4565 + u_long start = vc->vc_origin, end;
4566 + if (from > 0)
4567 + start += from * vc->vc_size_row;
4568 + if (to > vc->vc_rows)
4569 + to = vc->vc_rows;
4570 + end = vc->vc_origin + (to * vc->vc_size_row);
4571 + for (from = start; from < end; from = to) {
4572 + to = from + vc->vc_size_row;
4573 + say_from_to(vc, from, to, 1);
4574 + }
4575 +}
4576 +
4577 +static void say_screen(struct vc_data *vc)
4578 +{
4579 + say_screen_from_to(vc, 0, vc->vc_rows);
4580 +}
4581 +
4582 +static void speakup_win_say(struct vc_data *vc)
4583 +{
4584 + u_long start, end, from, to;
4585 + if (win_start < 2) {
4586 + synth_write_msg("no window");
4587 + return;
4588 + }
4589 + start = vc->vc_origin + (win_top * vc->vc_size_row);
4590 + end = vc->vc_origin + (win_bottom * vc->vc_size_row);
4591 + while (start <= end) {
4592 + from = start + (win_left * 2);
4593 + to = start + (win_right * 2);
4594 + say_from_to(vc, from, to, 1);
4595 + start += vc->vc_size_row;
4596 + }
4597 +}
4598 +
4599 +static void top_edge (struct vc_data *vc)
4600 +{
4601 + spk_parked |= 0x01;
4602 + spk_pos = vc->vc_origin + 2 * spk_x;
4603 + spk_y = 0;
4604 + say_line(vc);
4605 +}
4606 +
4607 +static void bottom_edge(struct vc_data *vc)
4608 +{
4609 + spk_parked |= 0x01;
4610 + spk_pos += (vc->vc_rows - spk_y - 1) * vc->vc_size_row;
4611 + spk_y = vc->vc_rows - 1;
4612 + say_line(vc);
4613 +}
4614 +
4615 +static void left_edge(struct vc_data *vc)
4616 +{
4617 + spk_parked |= 0x01;
4618 + spk_pos -= spk_x * 2;
4619 + spk_x = 0;
4620 + say_char (vc );
4621 +}
4622 +
4623 +static void right_edge(struct vc_data *vc)
4624 +{
4625 + spk_parked |= 0x01;
4626 + spk_pos += (vc->vc_cols - spk_x - 1) * 2;
4627 + spk_x = vc->vc_cols - 1;
4628 + say_char(vc);
4629 +}
4630 +
4631 +static void say_first_char(struct vc_data *vc)
4632 +{
4633 + int i, len = get_line(vc);
4634 + u_char ch;
4635 + spk_parked |= 0x01;
4636 + if (len == 0) {
4637 + synth_write_msg(blank_msg);
4638 + return;
4639 + }
4640 + for (i = 0; i < len; i++)
4641 + if (buf[i] != SPACE)
4642 + break;
4643 + ch = buf[i];
4644 + spk_pos -= (spk_x - i) * 2;
4645 + spk_x = i;
4646 + sprintf(buf, "%d, ", ++i);
4647 + synth_write_string(buf);
4648 + speak_char(ch);
4649 +}
4650 +
4651 +static void say_last_char(struct vc_data *vc)
4652 +{
4653 + int len = get_line(vc);
4654 + u_char ch;
4655 + spk_parked |= 0x01;
4656 + if (len == 0) {
4657 + synth_write_msg(blank_msg);
4658 + return;
4659 + }
4660 + ch = buf[--len];
4661 + spk_pos -= (spk_x - len) * 2;
4662 + spk_x = len;
4663 + sprintf (buf, "%d, ", ++len);
4664 + synth_write_string(buf);
4665 + speak_char(ch);
4666 +}
4667 +
4668 +static void say_position(struct vc_data *vc)
4669 +{
4670 + sprintf(buf, "line %ld, col %ld, t t y %d\n", spk_y + 1, spk_x + 1,
4671 + vc->vc_num + 1);
4672 + synth_write_string(buf);
4673 +}
4674 +
4675 +// Added by brianb
4676 +static void say_char_num(struct vc_data *vc)
4677 +{
4678 + u_short ch = get_char(vc, (u_short *) spk_pos);
4679 + ch &= 0xff;
4680 + sprintf(buf, "hex %02x, decimal %d", ch, ch);
4681 + synth_write_msg(buf);
4682 +}
4683 +
4684 +/* these are stub functions to keep keyboard.c happy. */
4685 +
4686 +static void say_from_top(struct vc_data *vc)
4687 +{
4688 + say_screen_from_to(vc, 0, spk_y);
4689 +}
4690 +
4691 +static void say_to_bottom(struct vc_data *vc)
4692 +{
4693 + say_screen_from_to(vc, spk_y, vc->vc_rows);
4694 +}
4695 +
4696 +static void say_from_left(struct vc_data *vc)
4697 +{
4698 + say_line_from_to(vc, 0, spk_x, 1);
4699 +}
4700 +
4701 +static void say_to_right(struct vc_data *vc)
4702 +{
4703 + say_line_from_to(vc, spk_x, vc->vc_cols, 1);
4704 +}
4705 +
4706 +/* end of stub functions. */
4707 +
4708 +static void spkup_write(const char *in_buf, int count)
4709 +{
4710 + static int rep_count = 0;
4711 + static u_char ch = '\0', old_ch = '\0';
4712 + static u_short char_type = 0, last_type = 0;
4713 + static u_char *exn_ptr = NULL;
4714 + int in_count = count;
4715 + char rpt_buf[32];
4716 + spk_keydown = 0;
4717 + while ( count-- ) {
4718 + if ( cursor_track == read_all_mode ) {
4719 + // Insert Sentence Index
4720 + if (( in_buf == sentmarks[bn][currsentence] ) &&
4721 + ( currsentence <= numsentences[bn] ))
4722 + synth_insert_next_index(currsentence++);
4723 + }
4724 + ch = (u_char )*in_buf++;
4725 + char_type = spk_chartab[ch];
4726 + if (ch == old_ch && !(char_type&B_NUM ) ) {
4727 + if (++rep_count > 2 ) continue;
4728 + } else {
4729 + if ( (last_type&CH_RPT) && rep_count > 2 ) {
4730 + sprintf (rpt_buf, " times %d . ", ++rep_count );
4731 + synth_write_string (rpt_buf );
4732 + }
4733 + rep_count = 0;
4734 + }
4735 + if ( !( char_type&B_NUM ) )
4736 + exn_ptr = NULL;
4737 + if (ch == spk_lastkey ) {
4738 + rep_count = 0;
4739 + if ( key_echo == 1 && ch >= MINECHOCHAR )
4740 + speak_char( ch );
4741 + } else if ( ( char_type&B_ALPHA ) ) {
4742 + if ( (synth_flags&SF_DEC) && (last_type&PUNC) )
4743 + synth_buffer_add ( SPACE );
4744 + synth_write( &ch, 1 );
4745 + } else if ( ( char_type&B_NUM ) ) {
4746 + rep_count = 0;
4747 + if ( (last_type&B_EXNUM) && synth_buff_in == exn_ptr+1 ) {
4748 + synth_buff_in--;
4749 + synth_buffer_add( old_ch );
4750 + exn_ptr = NULL;
4751 + }
4752 + synth_write( &ch, 1 );
4753 + } else if ( (char_type&punc_mask) ) {
4754 + speak_char( ch );
4755 + char_type &= ~PUNC; /* for dec nospell processing */
4756 + } else if ( ( char_type&SYNTH_OK ) ) {
4757 +/* these are usually puncts like . and , which synth needs for expression.
4758 + * suppress multiple to get rid of long pausesand clear repeat count so if
4759 + *someone has repeats on you don't get nothing repeated count */
4760 + if ( ch != old_ch )
4761 + synth_write( &ch, 1 );
4762 + else rep_count = 0;
4763 + } else {
4764 + if ( ( char_type&B_EXNUM ) )
4765 + exn_ptr = (u_char *)synth_buff_in;
4766 +/* send space and record position, if next is num overwrite space */
4767 + if ( old_ch != ch ) synth_buffer_add ( SPACE );
4768 + else rep_count = 0;
4769 + }
4770 + old_ch = ch;
4771 + last_type = char_type;
4772 + }
4773 + spk_lastkey = 0;
4774 + if (in_count > 2 && rep_count > 2 ) {
4775 + if ( (last_type&CH_RPT) ) {
4776 + sprintf (rpt_buf, " repeated %d . ", ++rep_count );
4777 + synth_write_string (rpt_buf );
4778 + }
4779 + rep_count = 0;
4780 + }
4781 +}
4782 +
4783 +static char *ctl_key_ids[] = {
4784 + "shift", "altgr", "control", "ault", "l shift", "speakup",
4785 +"l control", "r control"
4786 +};
4787 +#define NUM_CTL_LABELS 8
4788 +
4789 +static void read_all_doc(struct vc_data *vc);
4790 +static void cursor_stop_timer(void);
4791 +
4792 +static void handle_shift(struct vc_data *vc, u_char value, char up_flag)
4793 +{
4794 + (*do_shift)(vc, value, up_flag);
4795 + if (synth == NULL || up_flag || spk_killed)
4796 + return;
4797 + if (cursor_track == read_all_mode) {
4798 + switch (value) {
4799 + case KVAL(K_SHIFT):
4800 + cursor_stop_timer();
4801 + spk_shut_up &= 0xfe;
4802 + do_flush();
4803 + read_all_doc(vc);
4804 + break;
4805 + case KVAL(K_CTRL):
4806 + cursor_stop_timer();
4807 + cursor_track=prev_cursor_track;
4808 + spk_shut_up &= 0xfe;
4809 + do_flush();
4810 + break;
4811 + }
4812 + } else {
4813 + spk_shut_up &= 0xfe;
4814 + do_flush();
4815 + }
4816 + if (say_ctrl && value < NUM_CTL_LABELS)
4817 + synth_write_string(ctl_key_ids[value]);
4818 +}
4819 +
4820 +static void handle_latin(struct vc_data *vc, u_char value, char up_flag)
4821 +{
4822 + (*do_latin)(vc, value, up_flag);
4823 + if (up_flag) {
4824 + spk_lastkey = spk_keydown = 0;
4825 + return;
4826 + }
4827 + if (synth == NULL || spk_killed)
4828 + return;
4829 + spk_shut_up &= 0xfe;
4830 + spk_lastkey = value;
4831 + spk_keydown++;
4832 + spk_parked &= 0xfe;
4833 + if (key_echo == 2 && value >= MINECHOCHAR)
4834 + speak_char( value );
4835 +}
4836 +
4837 +static int set_key_info(const u_char *key_info, u_char *k_buffer)
4838 +{
4839 + int i = 0, states, key_data_len;
4840 + const u_char *cp = key_info;
4841 + u_char *cp1 = k_buffer;
4842 + u_char ch, version, num_keys;
4843 + version = *cp++;
4844 + if (version != KEY_MAP_VER)
4845 + return -1;
4846 + num_keys = *cp;
4847 + states = (int) cp[1];
4848 + key_data_len = (states + 1) * (num_keys + 1);
4849 + if (key_data_len + SHIFT_TBL_SIZE + 4 >= sizeof(key_buf))
4850 + return -2;
4851 + memset(k_buffer, 0, SHIFT_TBL_SIZE);
4852 + memset(our_keys, 0, sizeof(our_keys));
4853 + shift_table = k_buffer;
4854 + our_keys[0] = shift_table;
4855 + cp1 += SHIFT_TBL_SIZE;
4856 + memcpy(cp1, cp, key_data_len + 3);
4857 + /* get num_keys, states and data*/
4858 + cp1 += 2; /* now pointing at shift states */
4859 + for (i = 1; i <= states; i++) {
4860 + ch = *cp1++;
4861 + if (ch >= SHIFT_TBL_SIZE)
4862 + return -3;
4863 + shift_table[ch] = i;
4864 + }
4865 + keymap_flags = *cp1++;
4866 + while ((ch = *cp1)) {
4867 + if (ch >= MAX_KEY)
4868 + return -4;
4869 + our_keys[ch] = cp1;
4870 + cp1 += states + 1;
4871 + }
4872 + return 0;
4873 +}
4874 +
4875 +static struct st_num_var spk_num_vars[] = { /* bell must be first to set high limit */
4876 + { BELL_POS, 0, 0, 0, 0, 0, 0, 0 },
4877 + { SPELL_DELAY, 0, 0, 0, 5, 0, 0, 0 },
4878 + { ATTRIB_BLEEP, 0, 1, 0, 3, 0, 0, 0 },
4879 + { BLEEPS, 0, 3, 0, 3, 0, 0, 0 },
4880 + { BLEEP_TIME, 0, 30, 1, 200, 0, 0, 0 },
4881 + { PUNC_LEVEL, 0, 1, 0, 4, 0, 0, 0 },
4882 + { READING_PUNC, 0, 1, 0, 4, 0, 0, 0 },
4883 + { CURSOR_TIME, 0, 120, 50, 600, 0, 0, 0 },
4884 + { SAY_CONTROL, TOGGLE_0 },
4885 + { SAY_WORD_CTL, TOGGLE_0 },
4886 + { NO_INTERRUPT, TOGGLE_0 },
4887 + { KEY_ECHO, 0, 1, 0, 2, 0, 0, 0 },
4888 + V_LAST_NUM
4889 +};
4890 +
4891 +static char *cursor_msgs[] = { "cursoring off", "cursoring on",
4892 + "highlight tracking", "read windo",
4893 +"read all" };
4894 +
4895 +static void toggle_cursoring(struct vc_data *vc)
4896 +{
4897 + if (cursor_track == read_all_mode)
4898 + cursor_track = prev_cursor_track;
4899 + if (++cursor_track >= CT_Max)
4900 + cursor_track = 0;
4901 + synth_write_msg(cursor_msgs[cursor_track]);
4902 +}
4903 +
4904 +static void reset_default_chars(void)
4905 +{
4906 + int i;
4907 + if (default_chars[(int )'a'] == NULL) /* lowers are null first time */
4908 + for (i = (int )'a'; default_chars[i] == NULL; i++)
4909 + default_chars[i] = default_chars[i - 32];
4910 + else /* free any non-default */
4911 + for (i = 0; i < 256; i++) {
4912 + if (characters[i] != default_chars[i])
4913 + kfree(characters[i]);
4914 + }
4915 + memcpy(characters, default_chars, sizeof(default_chars));
4916 +}
4917 +
4918 +static void reset_default_chartab(void)
4919 +{
4920 + memcpy(spk_chartab, default_chartab, sizeof(default_chartab));
4921 +}
4922 +
4923 +static void handle_cursor(struct vc_data *vc, u_char value, char up_flag);
4924 +static void handle_spec(struct vc_data *vc, u_char value, char up_flag);
4925 +static void cursor_done(u_long data );
4926 +
4927 +static declare_timer(cursor_timer);
4928 +
4929 +static void __init speakup_open(struct vc_data *vc,
4930 + struct st_spk_t *first_console)
4931 +{
4932 + int i;
4933 + struct st_num_var *n_var;
4934 +
4935 + reset_default_chars();
4936 + reset_default_chartab();
4937 + memset(speakup_console, 0, sizeof(speakup_console));
4938 + if (first_console == NULL)
4939 + return;
4940 + speakup_console[vc->vc_num] = first_console;
4941 + speakup_date(vc);
4942 + pr_info("%s: initialized\n", SPEAKUP_VERSION);
4943 + init_timer(&cursor_timer);
4944 + cursor_timer.entry.prev = NULL;
4945 + cursor_timer.function = cursor_done;
4946 + init_sleeper(synth_sleeping_list);
4947 + strlwr(synth_name);
4948 + spk_num_vars[0].high = vc->vc_cols;
4949 + for (n_var = spk_num_vars; n_var->var_id >= 0; n_var++)
4950 + speakup_register_var(n_var);
4951 + for (i = 1; punc_info[i].mask != 0; i++)
4952 + set_mask_bits(0, i, 2);
4953 + do_latin = key_handler[KT_LATIN];
4954 + key_handler[KT_LATIN] = handle_latin;
4955 + do_spec = key_handler[KT_SPEC];
4956 + key_handler[KT_SPEC] = handle_spec;
4957 + do_cursor = key_handler[KT_CUR];
4958 + key_handler[KT_CUR] = handle_cursor;
4959 + do_shift = key_handler[KT_SHIFT];
4960 + key_handler[KT_SHIFT] = handle_shift;
4961 + set_key_info(key_defaults, key_buf);
4962 + if (quiet_boot) spk_shut_up |= 0x01;
4963 +}
4964 +
4965 +#ifdef CONFIG_PROC_FS
4966 +
4967 +// speakup /proc interface code
4968 +
4969 +/* Usage:
4970 +cat /proc/speakup/version
4971 +
4972 +cat /proc/speakup/characters > foo
4973 +less /proc/speakup/characters
4974 +vi /proc/speakup/characters
4975 +
4976 +cat foo > /proc/speakup/characters
4977 +cat > /proc/speakup/characters
4978 +echo 39 apostrophe > /proc/speakup/characters
4979 +echo 87 w > /proc/speakup/characters
4980 +echo 119 w > /proc/speakup/characters
4981 +echo defaults > /proc/speakup/characters
4982 +echo reset > /proc/speakup/characters
4983 +
4984 +
4985 +cat /proc/speakup/chartab > foo
4986 +less /proc/speakup/chartab
4987 +vi /proc/speakup/chartab
4988 +
4989 +cat foo > /proc/speakup/chartab
4990 +cat > /proc/speakup/chartab
4991 +echo 233 ALPHA > /proc/speakup/chartab
4992 +echo 46 A_PUNC > /proc/speakup/chartab
4993 +echo defaults > /proc/speakup/chartab
4994 +echo reset > /proc/speakup/chartab
4995 +*/
4996 +
4997 +// keymap handlers
4998 +
4999 +static int keys_read_proc(char *page, char **start, off_t off, int count,
5000 + int *eof, void *data)
5001 +{
5002 + char *cp = page;
5003 + int i, n, num_keys, nstates;
5004 + u_char *cp1 = key_buf + SHIFT_TBL_SIZE, ch;
5005 + num_keys = (int)(*cp1);
5006 + nstates = (int)cp1[1];
5007 + cp += sprintf( cp, "%d, %d, %d,\n", KEY_MAP_VER, num_keys, nstates );
5008 + cp1 += 2; /* now pointing at shift states */
5009 +/* dump num_keys+1 as first row is shift states + flags,
5010 + each subsequent row is key + states */
5011 + for ( n = 0; n <= num_keys; n++ ) {
5012 + for ( i = 0; i <= nstates; i++ ) {
5013 + ch = *cp1++;
5014 + cp += sprintf( cp, "%d,", (int)ch );
5015 + *cp++ = ( i < nstates ) ? SPACE : '\n';
5016 + }
5017 + }
5018 + cp += sprintf( cp, "0, %d\n", KEY_MAP_VER );
5019 + *start = 0;
5020 + *eof = 1;
5021 + return (int)(cp-page);
5022 +}
5023 +
5024 +static char *
5025 +s2uchar ( char *start, char *dest )
5026 +{
5027 + int val = 0;
5028 + while ( *start && *start <= SPACE ) start++;
5029 + while ( *start >= '0' && *start <= '9' ) {
5030 + val *= 10;
5031 + val += ( *start ) - '0';
5032 + start++;
5033 + }
5034 + if ( *start == ',' ) start++;
5035 + *dest = (u_char)val;
5036 + return start;
5037 +}
5038 +
5039 +static int keys_write_proc(struct file *file, const char *buffer, u_long count,
5040 + void *data)
5041 +{
5042 + int i, ret = count;
5043 + char *in_buff, *cp;
5044 + u_char *cp1;
5045 + if (count < 1 || count > 1800 )
5046 + return -EINVAL;
5047 + in_buff = ( char * ) __get_free_page ( GFP_KERNEL );
5048 + if ( !in_buff ) return -ENOMEM;
5049 + if (copy_from_user (in_buff, buffer, count ) ) {
5050 + free_page ( ( unsigned long ) in_buff );
5051 + return -EFAULT;
5052 + }
5053 + if (in_buff[count - 1] == '\n' ) count--;
5054 + in_buff[count] = '\0';
5055 + if ( count == 1 && *in_buff == 'd' ) {
5056 + free_page ( ( unsigned long ) in_buff );
5057 + set_key_info( key_defaults, key_buf );
5058 + return ret;
5059 + }
5060 + cp = in_buff;
5061 + cp1 = (u_char *)in_buff;
5062 + for ( i = 0; i < 3; i++ ) {
5063 + cp = s2uchar( cp, cp1 );
5064 + cp1++;
5065 + }
5066 + i = (int)cp1[-2]+1;
5067 + i *= (int)cp1[-1]+1;
5068 + i+= 2; /* 0 and last map ver */
5069 + if ( cp1[-3] != KEY_MAP_VER || cp1[-1] > 10 ||
5070 + i+SHIFT_TBL_SIZE+4 >= sizeof(key_buf ) ) {
5071 +pr_warn( "i %d %d %d %d\n", i, (int)cp1[-3], (int)cp1[-2], (int)cp1[-1] );
5072 + free_page ( ( unsigned long ) in_buff );
5073 + return -EINVAL;
5074 + }
5075 + while ( --i >= 0 ) {
5076 + cp = s2uchar( cp, cp1 );
5077 + cp1++;
5078 + if ( !(*cp) ) break;
5079 + }
5080 + if ( i != 0 || cp1[-1] != KEY_MAP_VER || cp1[-2] != 0 ) {
5081 + ret = -EINVAL;
5082 +pr_warn( "end %d %d %d %d\n", i, (int)cp1[-3], (int)cp1[-2], (int)cp1[-1] );
5083 + } else {
5084 + if ( set_key_info( in_buff, key_buf ) ) {
5085 + set_key_info( key_defaults, key_buf );
5086 + ret = -EINVAL;
5087 +pr_warn( "set key failed\n" );
5088 + }
5089 + }
5090 + free_page ( ( unsigned long ) in_buff );
5091 + return ret;
5092 +}
5093 +
5094 +// this is the handler for /proc/speakup/version
5095 +static int version_read_proc(char *page, char **start, off_t off, int count,
5096 + int *eof, void *data)
5097 +{
5098 + int len = sprintf (page, "%s\n", SPEAKUP_VERSION );
5099 + if (synth != NULL)
5100 + len += sprintf(page+len, "synth %s version %s\n", synth->name,
5101 + synth->version);
5102 + *start = 0;
5103 + *eof = 1;
5104 + return len;
5105 +}
5106 +
5107 +// this is the read handler for /proc/speakup/characters
5108 +static int chars_read_proc(char *page, char **start, off_t off, int count,
5109 + int *eof, void *data)
5110 +{
5111 + int i, len = 0;
5112 + off_t begin = 0;
5113 + char *cp;
5114 + for (i = 0; i < 256; i++) {
5115 + cp = (characters[i]) ? characters[i] : "NULL";
5116 + len += sprintf(page + len, "%d\t%s\n", i, cp);
5117 + if (len + begin > off + count)
5118 + break;
5119 + if (len + begin < off) {
5120 + begin += len;
5121 + len = 0;
5122 + }
5123 + }
5124 + if (i >= 256)
5125 + *eof = 1;
5126 + if (off >= len + begin)
5127 + return 0;
5128 + *start = page + (off - begin);
5129 + return ((count < begin + len - off) ? count : begin + len - off);
5130 +}
5131 +
5132 +static volatile int chars_timer_active = 0; // indicates when timer is set
5133 +static declare_timer(chars_timer);
5134 +
5135 +static void chars_stop_timer(void)
5136 +{
5137 + if (chars_timer_active)
5138 + stop_timer(chars_timer);
5139 +}
5140 +
5141 +static int strings, rejects, updates;
5142 +
5143 +static void show_char_results (u_long data)
5144 +{
5145 + int len;
5146 + char buf[80];
5147 + chars_stop_timer();
5148 + len = sprintf(buf, " updated %d of %d character descriptions\n",
5149 + updates, strings);
5150 + if (rejects)
5151 + sprintf(buf + (len - 1), " with %d reject%s\n",
5152 + rejects, rejects > 1 ? "s" : "");
5153 + printk(buf);
5154 +}
5155 +
5156 +// this is the read handler for /proc/speakup/chartab
5157 +static int chartab_read_proc(char *page, char **start, off_t off, int count,
5158 + int *eof, void *data)
5159 +{
5160 + int i, len = 0;
5161 + off_t begin = 0;
5162 + char *cp;
5163 + for (i = 0; i < 256; i++) {
5164 + cp = "0";
5165 + if (IS_TYPE(i, B_CTL))
5166 + cp = "B_CTL";
5167 + else if (IS_TYPE(i, WDLM))
5168 + cp = "WDLM";
5169 + else if (IS_TYPE(i, A_PUNC))
5170 + cp = "A_PUNC";
5171 + else if (IS_TYPE(i, PUNC))
5172 + cp = "PUNC";
5173 + else if (IS_TYPE(i, NUM))
5174 + cp = "NUM";
5175 + else if (IS_TYPE(i, A_CAP))
5176 + cp = "A_CAP";
5177 + else if (IS_TYPE(i, ALPHA))
5178 + cp = "ALPHA";
5179 + else if (IS_TYPE(i, B_CAPSYM))
5180 + cp = "B_CAPSYM";
5181 + else if (IS_TYPE(i, B_SYM))
5182 + cp = "B_SYM";
5183 +
5184 + len += sprintf(page + len, "%d\t%s\n", i, cp);
5185 + if (len + begin > off + count)
5186 + break;
5187 + if (len + begin < off) {
5188 + begin += len;
5189 + len = 0;
5190 + }
5191 + }
5192 + if (i >= 256)
5193 + *eof = 1;
5194 + if (off >= len + begin)
5195 + return 0;
5196 + *start = page + (off - begin);
5197 + return ((count < begin + len - off) ? count : begin + len - off);
5198 +}
5199 +
5200 +static int chartab_get_value(char *keyword)
5201 +{
5202 + int value = 0;
5203 +
5204 + if (!strcmp(keyword, "ALPHA"))
5205 + value = ALPHA;
5206 + else if (!strcmp(keyword, "B_CTL"))
5207 + value = B_CTL;
5208 + else if (!strcmp(keyword, "WDLM"))
5209 + value = WDLM;
5210 + else if (!strcmp(keyword, "A_PUNC"))
5211 + value = A_PUNC;
5212 + else if (!strcmp(keyword, "PUNC"))
5213 + value = PUNC;
5214 + else if (!strcmp(keyword, "NUM"))
5215 + value = NUM;
5216 + else if (!strcmp(keyword, "A_CAP"))
5217 + value = A_CAP;
5218 + else if (!strcmp(keyword, "B_CAPSYM"))
5219 + value = B_CAPSYM;
5220 + else if (!strcmp(keyword, "B_SYM"))
5221 + value = B_SYM;
5222 + return value;
5223 +}
5224 +
5225 +/* this is the write handler for /proc/speakup/silent */
5226 +static int silent_write_proc(struct file *file, const char *buffer,
5227 + u_long count, void *data)
5228 +{
5229 + struct vc_data *vc = vc_cons[fg_console].d;
5230 + char ch = 0, shut;
5231 + if (count > 0 || count < 3 ) {
5232 + get_user (ch, buffer );
5233 + if ( ch == '\n' ) ch = '0';
5234 + }
5235 + if ( ch < '0' || ch > '7' ) {
5236 + pr_warn ( "silent value not in range (0,7)\n" );
5237 + return count;
5238 + }
5239 + if ( (ch&2) ) {
5240 + shut = 1;
5241 + do_flush( );
5242 + } else shut = 0;
5243 + if ( (ch&4) ) shut |= 0x40;
5244 + if ( (ch&1) )
5245 + spk_shut_up |= shut;
5246 + else spk_shut_up &= ~shut;
5247 + return count;
5248 +}
5249 +
5250 +// this is the write handler for /proc/speakup/characters
5251 +static int chars_write_proc(struct file *file, const char *buffer,
5252 + u_long count, void *data)
5253 +{
5254 +#define max_desc_len 72
5255 + static int cnt = 0, state = 0;
5256 + static char desc[max_desc_len + 1];
5257 + static u_long jiff_last = 0;
5258 + short i = 0, num;
5259 + int len;
5260 + char ch, *cp, *p_new;
5261 + // reset certain vars if enough time has elapsed since last called
5262 + if (jiffies - jiff_last > 10 ) {
5263 + cnt = state = strings = rejects = updates = 0;
5264 + }
5265 + jiff_last = jiffies;
5266 +get_more:
5267 + desc[cnt] = '\0';
5268 + state = 0;
5269 + for (; i < count && state < 2; i++ ) {
5270 + get_user (ch, buffer + i );
5271 + if ( ch == '\n' ) {
5272 + desc[cnt] = '\0';
5273 + state = 2;
5274 + } else if (cnt < max_desc_len )
5275 + desc[cnt++] = ch;
5276 + }
5277 + if (state < 2 ) return count;
5278 + cp = desc;
5279 + while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++;
5280 + if ((!cnt ) || strchr ("dDrR", *cp ) ) {
5281 + reset_default_chars ( );
5282 + pr_info( "character descriptions reset to defaults\n" );
5283 + cnt = 0;
5284 + return count;
5285 + }
5286 + cnt = 0;
5287 + if (*cp == '#' ) goto get_more;
5288 + num = -1;
5289 + cp = speakup_s2i(cp, &num );
5290 + while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++;
5291 + if (num < 0 || num > 255 ) { // not in range
5292 + rejects++;
5293 + strings++;
5294 + goto get_more;
5295 + }
5296 + if (num >= 27 && num <= 31 ) goto get_more;
5297 + if (!strcmp(cp, characters[num] ) ) {
5298 + strings++;
5299 + goto get_more;
5300 + }
5301 + len = strlen(cp );
5302 + if (characters[num] == default_chars[num] )
5303 + p_new = kmalloc(sizeof (char) * len+1, GFP_KERNEL );
5304 + else if ( strlen(characters[num] ) >= len )
5305 + p_new = characters[num];
5306 + else {
5307 + kfree(characters[num] );
5308 + characters[num] = default_chars[num];
5309 + p_new = kmalloc(sizeof (char) * len+1, GFP_KERNEL );
5310 + }
5311 + if (!p_new ) return -ENOMEM;
5312 + strcpy ( p_new, cp );
5313 + characters[num] = p_new;
5314 + updates++;
5315 + strings++;
5316 + if (i < count ) goto get_more;
5317 + chars_stop_timer ( );
5318 + init_timer (&chars_timer );
5319 + chars_timer.function = show_char_results;
5320 + chars_timer.expires = jiffies + 5;
5321 + start_timer (chars_timer );
5322 + chars_timer_active++;
5323 + return count;
5324 +}
5325 +
5326 +// this is the write handler for /proc/speakup/chartab
5327 +static int chartab_write_proc(struct file *file, const char *buffer,
5328 + u_long count, void *data)
5329 +{
5330 +#define max_desc_len 72
5331 + static int cnt = 0, state = 0;
5332 + static char desc[max_desc_len + 1];
5333 + static u_long jiff_last = 0;
5334 + short i = 0, num;
5335 + char ch, *cp;
5336 + int value=0;
5337 + // reset certain vars if enough time has elapsed since last called
5338 + if (jiffies - jiff_last > 10 ) {
5339 + cnt = state = strings = rejects = updates = 0;
5340 + }
5341 + jiff_last = jiffies;
5342 +get_more:
5343 + desc[cnt] = '\0';
5344 + state = 0;
5345 + for (; i < count && state < 2; i++ ) {
5346 + get_user (ch, buffer + i );
5347 + if ( ch == '\n' ) {
5348 + desc[cnt] = '\0';
5349 + state = 2;
5350 + } else if (cnt < max_desc_len )
5351 + desc[cnt++] = ch;
5352 + }
5353 + if (state < 2 ) return count;
5354 + cp = desc;
5355 + while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++;
5356 + if ((!cnt ) || strchr ("dDrR", *cp ) ) {
5357 + reset_default_chartab ( );
5358 + pr_info( "character descriptions reset to defaults\n" );
5359 + cnt = 0;
5360 + return count;
5361 + }
5362 + cnt = 0;
5363 + if (*cp == '#' ) goto get_more;
5364 + num = -1;
5365 + cp = speakup_s2i(cp, &num );
5366 + while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++;