/[linux-patches]/genpatches-2.6/tags/2.6.20-9/4400_speakup-20070204.patch
Gentoo

Contents of /genpatches-2.6/tags/2.6.20-9/4400_speakup-20070204.patch

Parent Directory Parent Directory | Revision Log Revision Log


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