Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 112063 Details for
Bug 166086
sys-kernel/gentoo-sources-2.6.20 doesn't compile
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
4400_speakup-20070204.patch
4400_speakup-20070204.patch (text/plain), 365.29 KB, created by
Pacho Ramos
on 2007-03-04 14:26:53 UTC
(
hide
)
Description:
4400_speakup-20070204.patch
Filename:
MIME Type:
Creator:
Pacho Ramos
Created:
2007-03-04 14:26:53 UTC
Size:
365.29 KB
patch
obsolete
>speakup CVS for Linux 2.6.20 >Generated by dsd on Sun Feb 4 16:09:21 EST 2007 >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/arch/arm/Kconfig linux-2.6.20-spk/arch/arm/Kconfig >--- linux-2.6.20/arch/arm/Kconfig 2007-02-04 16:08:00.000000000 -0500 >+++ linux-2.6.20-spk/arch/arm/Kconfig 2007-02-04 16:09:21.000000000 -0500 >@@ -951,6 +951,7 @@ source "drivers/leds/Kconfig" > source "drivers/media/Kconfig" > > source "drivers/video/Kconfig" >+source "drivers/char/speakup/Kconfig" > > source "sound/Kconfig" > >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/Documentation/speakup/DefaultKeyAssignments linux-2.6.20-spk/Documentation/speakup/DefaultKeyAssignments >--- linux-2.6.20/Documentation/speakup/DefaultKeyAssignments 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/Documentation/speakup/DefaultKeyAssignments 2007-02-04 16:09:21.000000000 -0500 >@@ -0,0 +1,46 @@ >+This file is intended to give you an overview of the default keys used >+by speakup for it's review functions. You may change them to be >+anything you want but that will take some familiarity with key >+mapping. >+ >+We have remapped the insert or zero key on the keypad to act as a >+shift key. Well, actually as an altgr key. So in the following list >+InsKeyPad-period means hold down the insert key like a shift key and >+hit the keypad period. >+ >+KeyPad-8 Say current Line >+InsKeyPad-8 say from top of screen to reading cursor. >+KeyPad-7 Say Previous Line (UP one line) >+KeyPad-9 Say Next Line (down one line) >+KeyPad-5 Say Current Word >+InsKeyPad-5 Spell Current Word >+KeyPad-4 Say Previous Word (left one word) >+InsKeyPad-4 say from left edge of line to reading cursor. >+KeyPad-6 Say Next Word (right one word) >+InsKeyPad-6 Say from reading cursor to right edge of line. >+KeyPad-2 Say Current Letter >+InsKeyPad-2 say current letter phonetically >+KeyPad-1 Say Previous Character (left one letter) >+KeyPad-3 Say Next Character (right one letter) >+KeyPad-plus Say Entire Screen >+InsKeyPad-plus Say from reading cursor line to bottom of screen. >+KeyPad-Minus Park reading cursor (toggle) >+InsKeyPad-minus Say character hex and decimal value. >+KeyPad-period Say Position (current line, position and console) >+InsKeyPad-period say colour attributes of current position. >+InsKeyPad-9 Move reading cursor to top of screen (insert pgup) >+InsKeyPad-3 Move reading cursor to bottom of screen (insert pgdn) >+InsKeyPad-7 Move reading cursor to left edge of screen (insert home) >+InsKeyPad-1 Move reading cursor to right edge of screen (insert end) >+ControlKeyPad-1 Move reading cursor to last character on current line. >+KeyPad-Enter Shut Up (until another key is hit) and sync reading cursor >+InsKeyPad-Enter Shut Up (until toggled back on). >+InsKeyPad-star n<x|y> go to line (y) or column (x). Where 'n' is any >+ allowed value for the row or column for your current screen. >+KeyPad-/ Mark and Cut screen region. >+InsKeyPad-/ Paste screen region into any console. >+ >+Hitting any key while speakup is outputting speech will quiet the >+synth until it has caught up with what is being printed on the >+console. >+ >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/Documentation/speakup/INSTALLATION linux-2.6.20-spk/Documentation/speakup/INSTALLATION >--- linux-2.6.20/Documentation/speakup/INSTALLATION 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/Documentation/speakup/INSTALLATION 2007-02-04 16:09:21.000000000 -0500 >@@ -0,0 +1,108 @@ >+This document assumes you have had some experience with kernel >+compilation and installation. If you have not, I recommend you get >+the kernel source and read the README and various documents in the >+linux/Documentation directory. In particular the Changes file to make >+sure you have the appropriate utilities needed for installing a 2.2.xx >+or 2.4xx kernel. It isn't as difficult as you might think. The >+kernel README is intimidating the first time but once you get the >+steps down, it's really pretty easy. Getting through the "make >+config" is the tedious bit. >+ >+The first thing to do is to place a copy of the tarball in the /usr/src >+directory which is the directory the linux tree is located in as well. >+Next untar speakup by typing: >+ >+tar zxf speakup-1.00.tar.gz >+cd speakup-1.00 >+./install >+ >+Note the dot-slash before the install. This will copy the speakup >+directory to the kernel tree and apply the various patches and >+components to the appropriate kernel files. Depending on how >+experienced you are with kernel compiling and hacking will determine >+whether you should bother looking at any failed patches. If this >+happens, you should probably write to the speakup mailing list for >+help or myself. >+ >+If all of the patch hunks apply successfully then just continue with >+the standard steps to compile the kernel with: >+ >+make mrproper >+make config >+ >+When you get to the section console speech output, answer 'y' to the >+CONFIG_SPEAKUP prompt. You will be given a submenu with the list of >+synthesizers which are currently supported. You can include as many >+synths in the kernel as you wish but remember each one takes up kernel >+space. You can only choose one of the synths as the default or none, >+so just type dtlk or whatever is the correct string for the >+synthesizer you have. You will also be asked if you wish to build-in >+a speakup key map. If you do not say 'y' to this option you will need >+to load a speakup map at boot time with whichever mechanism your >+distribution uses for loading key maps. >+ >+We have placed the speakup configuration options in make config just >+after the vga console choice. For the DoubleTalk PC driver included >+by Jim Van Zandt. I recommend you say no to that option. I have not >+tried configuring them both in, but I wouldn't be at all surprised if >+it didn't work. >+ >+If all goes well up to this point you can continue with the compiling >+process by doing: >+ >+make dep >dep.file 2>&1 & >+make bzImage >cc.file 2>&1 & >+make modules >mod.file 2>&1 & >+ >+I always redirect output to the files dep.file and cc.file so I can >+look over the compilation record to make sure there are no errors and >+warnings. >+ >+Okay, you are ready to install the newly compiled kernel. Make sure >+you make an linux.old entry in your lilo.conf file so you can recover >+if it blows up. next as root run "make modules_install" to install >+whatever modules you compiled and move the bzImage from >+/usr/src/linux/arch/i386/boot to wherever your kernel lives. Also >+move the System.map from /usr/src/linux to where your System.map >+lives. On our systems we use debian so we create an vmlinuz-speakup >+and System.map-speakup in our /boot directory and set the symbolic >+links vmlinuz and System.map in the root (/) directory to point to the >+images. Now type lilo to tell lilo to build the new booter file and >+install it. >+ >+As of version 0.07, the keymap for speakup is automatically built in >+at compile time. If you have other keymaps installed at boot time, >+you might want to consider removing them before you reboot the system. >+ >+If everything has gone OK up until now, cross your fingers and type: >+ >+shutdown -r now >+ >+Your system should start talking to you as soon as it starts booting. >+It will talk and talk and ... well, you might want to hit the >+keypad-enter key to tell it to shut up. You should also read the >+DefaultKeyAssignments file to learn the various review functions >+available. >+ >+As of v-0.10 the speakup configuration options are in the >+/proc/speakup subtree. The individual options should be fairly >+obvious by their names such as rate, volume, punc_level and so forth. >+You can manipulate them by cat'ing or echoing new values to them such >+as: >+ >+echo 9 >/proc/speakup/rate >+ >+You can see what the current values are by cat'ing those files to the console: >+ >+cat /proc/speakup/rate >+ >+I have probably managed to overlook a whole whack of things because >+this is the, enter version number here, draft. Don't worry we'll get >+it right eventually. If you like the package you really should get on >+the mailing list and start participating in it's development. >+ >+ Kirk >+ >+email: kirk@braille.uwo.ca >+phone: (519) 679-6845 (home) >+ >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/Documentation/speakup/keymap-tutorial linux-2.6.20-spk/Documentation/speakup/keymap-tutorial >--- linux-2.6.20/Documentation/speakup/keymap-tutorial 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/Documentation/speakup/keymap-tutorial 2007-02-04 16:09:21.000000000 -0500 >@@ -0,0 +1,140 @@ >+ Speakup Keymap Tutorial >+ >+This is meant to be a basic tutorial on how to change the Linux keymap >+file to assign speakup review functions to desired keys. It is not >+intended to be a replacement for the loadkeys(8) or keymap(5) man >+pages. >+ >+The basic lay-out of the keymap file is a series of lines with the >+following fields. The keyword keycode indicates this is the start of >+a new key assignment. It is then followed by a number which >+represents the actual key on the keyboard. That number is followed by >+the equals '=' operator and finally a list of keywords representing >+key names such as keypad5. Each line can have quite a few key >+functions on it. They are interpreted by loadkeys in order and >+assigned to key shift states depending on the order they are >+encountered. So for example, the first value after the equals is the >+keys unshifted state, while the second is the keys shifted state. If >+you wish to learn the order they are interpreted in read the >+loadkeys(8) and keymap(5) man pages. >+ >+You can have subsequent lines which are indented and start with >+another keyword for the various shifted states. This way you can >+assign some of the states without having to specify them all in order >+up until you get to the one you want to assign. >+ >+In speakup, we have assigned the insert key on the number pad to the >+altgr keyword. This is not required; you could choose any other >+shifted state keyword. We used altgr because it typically represents >+the right hand alt key. In Linux each shift key is separate and >+independent, so the left shift and the right shift keys are not >+necessarily the same. The altgr key is not really used for anything >+important, so we steel it. >+ >+Here are the default key assignments for the number eight on the >+keypad: >+ >+keycode 72 = KP_8 >+ alt keycode 72 = Ascii_8 >+ >+As you can see, the first line starts with keycode followed by 72 >+which is the actual number assigned to the key when the keyboard port >+is read. The KP_8 after the equal sign, is the symbolic representation >+of the function called when that key is hit. >+ >+The second line is the same format except it starts with the keyword >+alt which is indented. That means that the function at the end of >+that line Ascii_8 is applied to the alt-shifted eight key. >+ >+Now here are the speakup assignments for that key: >+ >+keycode 72 = 0x0d0a >+ altgr keycode 72 = 0x0d20 >+#keycode 72 = KP_8 >+ alt keycode 72 = Ascii_8 >+ >+Notice that the only thing which has changed on the first line is the >+function called when the key is struck. It is a hexadecimal number >+identifying the function called in a look up table. It is not a >+symbolic representation yet because that means we need to change the >+loadkeys program to understand our symbolic names. We will do this in >+the future but for now it is more expedient to just use the table >+indices. You will find a table at the bottom of this document >+listing the review functions and their corresponding hex lookups. >+ >+The 0x0d0a in the first line above is speakup's say line function. >+The second line ends with 0x0d20 which is speakup's read from top of >+screen to reading cursor line. >+ >+The third line is the original key assignment commented out with a >+number-sign '#' at the beginning. I do that so I can easily find the >+keys I want to affect by symbolic name. Otherwise I would need to >+keep a look up table for all the keycodes. I recommend you do this as >+well or you'll be very sorry at some point in the future. >+ >+The forth line is just the standard key assignment for the left hand >+alt key. >+ >+Now let's say we want to design a different keyboard layout. I'll use >+an example for the JAWS style keypad because I've specifically been >+asked to help with that. JAWS uses the eight on the keypad to move up >+a line or the speakup function to read previous line. JAWS also uses >+the keypad_8 key in a shifted mode to read the current line. I >+apologize if these are not quite right. It has been a long time since >+I used JAWS. So we would have the following two lines: >+ >+keycode 72 = 0x0d0b >+ altgr keycode 72 = 0x0d0a >+ >+The hex value 0x0d0b in the first line is speakup's SAY_PREVIOUS_LINE >+function. The 0x0d0a in the second line is the same say_line function >+as we had earlier. So when the number eight is hit on the keypad >+speakup will read the previous line and when the number eight is >+shifted with the insert key on the keypad it will read the current >+line. >+ >+As you can tell, it is not really very difficult to reassign the keys >+to different review functions. >+ >+Once you have carefully edited the keymap file, called default.map in >+the speakup distribution, you copy it into the /etc/kbd directory. >+Make sure you back up the original default.map from that directory >+first, if there is one. Then you run loadkeys to load the new map >+into the kernel: >+ >+loadkeys /etc/kbd/default.map >+ >+If you wish to build your new keyboard lay-out into the kernel, after >+testing it, copy the default.map file into the drivers/char directory, >+with the name defkeymap.map, of your Linux source tree. Then rm the >+defkeymap.c file and recompile the kernel. Because there is no >+defkeymap.c `make' will rebuild it on the next compile. >+ >+Here is a list of the available speakup review functions at this point >+in time. >+ >+SAY_CHAR 0x0d04 /* say this character */ >+SAY_PREV_CHAR 0x0d05 /* say character left of this char */ >+SAY_NEXT_CHAR 0x0d06 /* say char right of this char */ >+SAY_WORD 0x0d07 /* say this word under reading cursor */ >+SAY_PREV_WORD 0x0d08 >+SAY_NEXT_WORD 0x0d09 >+SAY_LINE 0x0d0a /* say this line */ >+SAY_PREV_LINE 0x0d0b /* say line above this line */ >+SAY_NEXT_LINE 0x0d0c >+TOP_EDGE 0x0d0d /* move to top edge of screen */ >+BOTTOM_EDGE 0x0d0e >+LEFT_EDGE 0x0d0f >+RIGHT_EDGE 0x0d10 >+SAY_PHONETIC_CHAR 0x0d11 /* say this character phonetically */ >+SPELL_WORD 0x0d12 /* spell this word letter by letter */ >+SAY_SCREEN 0x0d14 >+SAY_POSITION 0x0d1b >+SPEECH_OFF 0x0d1c >+SAY_ATTRIBUTES 0x0d1d >+SPEAKUP_PARKED 0x0d1e >+SAY_FROM_TOP 0x0d20 >+SAY_TO_BOTTOM 0x0d21 >+SAY_FROM_LEFT 0x0d22 >+SAY_TO_RIGHT 0x0d23 >+ >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/Documentation/speakup/README linux-2.6.20-spk/Documentation/speakup/README >--- linux-2.6.20/Documentation/speakup/README 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/Documentation/speakup/README 2007-02-04 16:09:21.000000000 -0500 >@@ -0,0 +1,98 @@ >+Welcome to the speakup project for the Speakup speech package for Linux. >+ >+Speakup is written by Kirk Reiser and Andy Berdan. It is licensed >+under the GPL. If you don't already know, the GPL stands for the GNU >+General Public License. Which basically states that this code is free to >+copy, modify and distribute to anyone interested in playing with it. >+The one thing you may not do is turn any part of it into proprietary >+or commercial code without the permission of the author. That's me. >+ >+If you are interested in being involved with the development of speech >+output for Linux you can subscribe to the Speakup mailing list by >+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. >+ >+We are at a very early stage in the development of this package. >+Hopefully changes will happen often and many. The current files in >+this directory are: >+ >+DefaultKeyAssignments # speakup's default review keys >+INSTALLATION # for installing speakup from the tar ball. >+README # this file >+keymap-tutorial # a tutorial on how to layout the keyboard >+ >+Read the INSTALLATION file to learn how to apply the patches and the >+default.map for the keyboard. You should also read the Changes file. >+It really has any new things I've added since last time. >+ >+There is no documentation in any of these files to instruct you what >+to do if something goes wrong with the patching or compilation. If >+you would like that information you will need to subscribe to the >+mailing list and ask for help, or write me kirk@braille.uwo.ca for >+help. I suggest the mailing list because I will probably tire quickly >+of answering the same questions over and over. You could always >+decide to dig-in and take on the task, and write documentation to help >+others. >+ >+There also is a speakup reflector for the Speak Freely package, which >+many of us hang out on and discuss all sorts of topics from speakup >+problems to ALSA driver installation and just about anything else >+you'd like to talk about. The reflector is at lwl.braille.uwo.ca:4074 >+with it's lwl page at lwl.braille.uwo.ca/speakup.html. Come and join >+us, it's fun! >+ >+Acknowledgements: >+ >+I am really very new at kernel hacking and screen review package >+writing, so I have depended heavily on other folks kindness to help me >+a long. No doubt I will continue to abuse them freely and others >+before this is a really good speech solution for Linux. (Oh Well!, >+somebody's got to do it.) >+ >+Theodore Ts'o. He gave me a good discussion of unicode and UTF and >+the like. He doesn't even remember writing me about it. >+ >+Alan Cox. He has answered many questions about scheduling and wait >+queues and timers along with code fragments and so on. I just wish I >+understood it all totally. He has also helped immensely in moving >+this package toward inclusion in the standard kernel tree. (Maybe next >+release!) >+ >+Martin Mares. He pointed me in the right direction to figuring out >+the colour attributes and other useful tidbits. >+ >+Paul McDermott. He really is the catalyst for me to actually get >+this all working. Besides I like seeing him bounce around and get all >+excited every time I have something new working. >+ >+John Covici, He was the first person to actually attempt writing >+another synthesizer driver for speakup. It was the Speakout driver so >+it was also the first serial driver. >+ >+Brian Borowski, he was the first person to actually write a speakup >+function other than Andy and I. >+ >+Jim Danley, he has more or less become my main man in helping test >+code, add new features, bounce ideas off and generally become a good >+friend. >+ >+Matt Campbell, he basically rewrote the drivers to be able to include >+all synths in the kernel at the same time. The distribution >+maintainers appreciate him a lot as well. >+ >+Gene Collins, he was very helpful debugging the current release prior >+to its public showing. He has also worked hard educating others on >+the list and writing the ALSA mini howto. >+ >+I would also like to really thank the folks that handle the >+distribution packages. I and many other people would not find access >+to speakup nearly so convenient without their efforts. They include >+Bill Acker, Tom Moore, Matt Campbell, Joe Norton and Joshua Lambert. >+ >+There are probably many more I am forgetting right now. I guess I'll >+just have to add you all later. >+ >+ >+Happy Hacking! >+ >+ Kirk >+ >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/Documentation/speakup/spkguide.txt linux-2.6.20-spk/Documentation/speakup/spkguide.txt >--- linux-2.6.20/Documentation/speakup/spkguide.txt 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/Documentation/speakup/spkguide.txt 2007-02-04 16:09:21.000000000 -0500 >@@ -0,0 +1,1279 @@ >+ >+The Speakup User's Guide >+For Speakup 2.0 and Later >+By Gene Collins >+Last modified on Tue Mar 29 10:54:19 2005 >+Document version 1.0 >+ >+Copyright (c) 2005 Gene Collins >+ >+Permission is granted to copy, distribute and/or modify this document >+under the terms of the GNU Free Documentation License, Version 1.2 or >+any later version published by the Free Software Foundation; with no >+Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A >+copy of the license is included in the section entitled "GNU Free >+Documentation License". >+ >+Preface >+ >+The purpose of this document is to familiarize users with the user >+interface to Speakup, a Linux Screen Reader. If you need instructions >+for installing or obtaining Speakup, visit the web site at >+http://linux-speakup.org/. Speakup is a set of patches to the standard >+Linux kernel source tree. It can be built as a series of modules, or as >+a part of a monolithic kernel. These details are beyond the scope of >+this manual, but the user may need to be aware of the module >+capabilities, depending on how your system administrator has installed >+Speakup. If Speakup is built as a part of a monolithic kernel, and the >+user is using a hardware synthesizer, then Speakup will be able to >+provide speech access from the time the kernel is loaded, until the time >+the system is shutdown. This means that if you have obtained Linux >+installation media for a distribution which includes Speakup as a part >+of its kernel, you will be able, as a blind person, to install Linux >+with speech access unaided by a sighted person. Again, these details >+are beyond the scope of this manual, but the user should be aware of >+them. See the web site mentioned above for further details. >+ >+1. Starting Speakup >+ >+If your system administrator has installed Speakup to work with your >+specific synthesizer by default, then all you need to do to use Speakup >+is to boot your system, and Speakup should come up talking. This >+assumes of course that your synthesizer is a supported hardware >+synthesizer, and that it is either installed in or connected to your >+system, and is if necessary powered on. >+ >+It is possible, however, that Speakup may have been compiled into the >+kernel with no default synthesizer. It is even possible that your >+kernel has been compiled with support for some of the supported >+synthesizers and not others. If you find that this is the case, and >+your synthesizer is supported but not available, complain to the person >+who compiled and installed your kernel. Or better yet, go to the web >+site, and learn how to patch Speakup into your own kernel source, and >+build and install your own kernel. >+ >+If your kernel has been compiled with Speakup, and has no default >+synthesizer set, or you would like to use a different synthesizer than >+the default one, then you may issue the following command at the boot >+prompt of your boot loader. >+ >+linux speakup_synth=ltlk >+ >+This command would tell Speakup to look for and use a LiteTalk or >+DoubleTalk LT at boot up. You may replace the ltlk synthesizer keyword >+with the keyword for whatever synthesizer you wish to use. The >+speakup_synth parameter will accept the following keywords, provided >+that support for the related synthesizers has been built into the >+kernel. >+ >+acntsa -- Accent SA >+acntpc -- Accent PC >+apolo -- Apolo >+audptr -- Audapter >+bns -- Braille 'n Speak >+dectlk -- DecTalk Express (old and new, db9 serial only) >+decext -- DecTalk (old) External >+dtlk -- DoubleTalk PC >+keypc -- Keynote Gold PC >+ltlk -- DoubleTalk LT, LiteTalk, or external Tripletalk (db9 serial only) >+spkout -- Speak Out >+txprt -- Transport >+ >+Note: Speakup does * NOT * support usb connections! Speakup also does * >+NOT * support the internal Tripletalk! >+ >+Speakup does support two other synthesizers, but because they work in >+conjunction with other software, they must be loaded as modules after >+their related software is loaded, and so are not available at boot up. >+These are as follows: >+ >+decpc -- DecTalk PC (not available at boot up) >+sftsyn -- One of several software synthesizers (not available at boot up) >+ >+See the sections on loading modules and software synthesizers later in >+this manual for further details. It should be noted here that the >+speakup_synth boot parameter will have no effect if Speakup has been >+compiled as modules. In order for Speakup modules to be loaded during >+the boot process, such action must be configured by your system >+administrator. This will mean that you will hear some, but not all, of >+the bootup messages. >+ >+2. Basic operation >+ >+Once you have booted the system, and if necessary, have supplied the >+proper bootup parameter for your synthesizer, Speakup will begin >+talking as soon as the kernel is loaded. In fact, it will talk a lot! >+It will speak all the boot up messages that the kernel prints on the >+screen during the boot process. This is because Speakup is not a >+separate screen reader, but is actually built into the operating >+system. Since almost all console applications must print text on the >+screen using the kernel, and must get their keyboard input through the >+kernel, they are automatically handled properly by Speakup. There are a >+few exceptions, but we'll come to those later. >+ >+Note: In this guide I will refer to the numeric keypad as the keypad. >+This is done because the speakupmap.map file referred to later in this >+manual uses the term keypad instead of numeric keypad. Also I'm lazy >+and would rather only type one word. So keypad it is. Got it? Good. >+ >+Most of the Speakup review keys are located on the keypad at the far >+right of the keyboard. The numlock key should be off, in order for these >+to work. If you toggle the numlock on, the keypad will produce numbers, >+which is exactly what you want for spreadsheets and such. For the >+purposes of this guide, you should have the numlock turned off, which is >+its default state at bootup. >+ >+You probably won't want to listen to all the bootup messages every time >+you start your system, though it's a good idea to listen to them at >+least once, just so you'll know what kind of information is available to >+you during the boot process. You can always review these messages after >+bootup with the command: >+ >+dmesg | more >+ >+In order to speed the boot process, and to silence the speaking of the >+bootup messages, just press the keypad enter key. This key is located >+in the bottom right corner of the keypad. Speakup will shut up and stay >+that way, until you press another key. >+ >+You can check to see if the boot process has completed by pressing the 8 >+key on the keypad, which reads the current line. This also has the >+effect of starting Speakup talking again, so you can press keypad enter >+to silence it again if the boot process has not completed. >+ >+When the boot process is complete, you will arrive at a "login" prompt. >+At this point, you'll need to type in your user id and password, as >+provided by your system administrator. You will hear Speakup speak the >+letters of your user id as you type it, but not the password. This is >+because the password is not displayed on the screen for security >+reasons. This has nothing to do with Speakup, it's a Linux security >+feature. >+ >+Once you've logged in, you can run any Linux command or program which is >+allowed by your user id. Normal users will not be able to run programs >+which require root privileges. >+ >+When you are running a program or command, Speakup will automatically >+speak new text as it arrives on the screen. You can at any time silence >+the speech with keypad enter, or use any of the Speakup review keys. >+ >+Here are some basic Speakup review keys, and a short description of what >+they do. >+ >+keypad 1 -- read previous character >+keypad 2 -- read current character (pressing keypad 2 twice rapidly will speak >+ the current character phonetically) >+keypad 3 -- read next character >+keypad 4 -- read previous word >+keypad 5 -- read current word (press twice rapidly to spell the current word) >+keypad 6 -- read next word >+keypad 7 -- read previous line >+keypad 8 -- read current line (press twice rapidly to hear how much the >+ text on the current line is indented) >+keypad 9 -- read next line >+keypad period -- speak current cursor position and announce current >+ virtual console >+ >+It's also worth noting that the insert key on the keypad is mapped >+as the speakup key. Instead of pressing and releasing this key, as you >+do under DOS or Windows, you hold it like a shift key, and press other >+keys in combination with it. For example, repeatedly holding keypad >+insert, from now on called speakup, and keypad enter will toggle the >+speaking of new text on the screen on and off. This is not the same as >+just pressing keypad enter by itself, which just silences the speech >+until you hit another key. When you hit speakup plus keypad enter, >+Speakup will say, "You turned me off.", or "Hey, that's better." When >+Speakup is turned off, no new text on the screen will be spoken. You >+can still use the reading controls to review the screen however. >+ >+3. Using the Speakup Help System >+ >+Speakup has a help system, which is compiled as a module. It is loaded >+automatically whenever the Speakup help system is invoked for the first >+time, and remains loaded after that, until speakup is unloaded. Note >+that if speakup was compiled into a monolithic kernel on your system, >+you will not be able to unload Speakup from your kernel. If you try to >+use the help system, and find that it is unavailable, then your system >+administrator has not installed the Speakup help module, which is called >+speakup_help. Complain to your system administrator about this. >+ >+In order to enter the Speakup help system, press and hold the speakup >+key (remember that this is the keypad insert key), and press the f1 key. >+You will hear the message: >+ >+"Press space to leave help, cursor up or down to scroll, or a letter to >+go to commands in list." >+ >+When you press the spacebar to leave the help system, you will hear: >+ >+"Leaving help." >+ >+While you are in the Speakup help system, you can scroll up or down >+through the list of available commands using the cursor keys. The list >+of commands is arranged in alphabetical order. If you wish to jump to >+commands in a specific part of the alphabet, you may press the letter of >+the alphabet you wish to jump to. >+ >+You can also just explore by typing keyboard keys. Pressing keys will >+cause Speakup to speak the command associated with that key. For >+example, if you press the keypad 8 key, you will hear: >+ >+"Keypad 8 is line, say current." >+ >+You'll notice that some commands do not have keys assigned to them. >+This is because they are very infrequently used commands, and are also >+accessible through the proc system. We'll discuss the proc system later >+in this manual. >+ >+You'll also notice that some commands have two keys assigned to them. >+This is because Speakup has a built in set of alternative key bindings >+for laptop users. The alternate speakup key is the caps lock key. You >+can press and hold the caps lock key, while pressing an alternate >+speakup command key to activate the command. On most laptops, the >+numeric keypad is defined as the keys in the j k l area of the keyboard. >+ >+There is usually a function key which turns this keypad function on and >+off, and some other key which controls the numlock state. Toggling the >+keypad functionality on and off can become a royal pain. So, Speakup >+gives you a simple way to get at an alternative set of key mappings for >+your laptop. These are also available by default on desktop systems, >+because Speakup does not know whether it is running on a desktop or >+laptop. So you may choose which set of Speakup keys to use. Some >+system administrators may have chosen to compile Speakup for a desktop >+system without this set of alternate key bindings, but these details are >+beyond the scope of this manual. To use the caps lock for its normal >+purpose, hold the shift key while toggling the caps lock on and off. We >+should note here, that holding the caps lock key and pressing the z key >+will toggle the alternate j k l keypad on and off. >+ >+4. Keys and Their Assigned Commands >+ >+In this section, we'll go through a list of all the speakup keys and >+commands. You can also get a list of commands and assigned keys from >+the help system. >+ >+The following list was taken from the speakupmap.map file. Key >+assignments are on the left of the equal sign, and the associated >+Speakup commands are on the right. The designation "spk" means to press >+and hold the speakup key, a.k.a. keypad insert, a.k.a. caps lock, while >+pressing the other specified key. >+ >+spk key_f9 = punc_level_dec >+spk key_f10 = punc_level_inc >+spk key_f11 = reading_punc_dec >+spk key_f12 = reading_punc_inc >+spk key_1 = vol_dec >+spk key_2 = vol_inc >+spk key_3 = pitch_dec >+spk key_4 = pitch_inc >+spk key_5 = rate_dec >+spk key_6 = rate_inc >+key_kpasterisk = toggle_cursoring >+spk key_kpasterisk = speakup_goto >+spk key_f1 = speakup_help >+spk key_f2 = set_win >+spk key_f3 = clear_win >+spk key_f4 = enable_win >+spk key_f5 = edit_some >+spk key_f6 = edit_most >+spk key_f7 = edit_delim >+spk key_f8 = edit_repeat >+shift spk key_f9 = edit_exnum >+ key_kp7 = say_prev_line >+spk key_kp7 = left_edge >+ key_kp8 = say_line >+double key_kp8 = say_line_indent >+spk key_kp8 = say_from_top >+ key_kp9 = say_next_line >+spk key_kp9 = top_edge >+ key_kpminus = speakup_parked >+spk key_kpminus = say_char_num >+ key_kp4 = say_prev_word >+spk key_kp4 = say_from_left >+ key_kp5 = say_word >+double key_kp5 = spell_word >+spk key_kp5 = spell_phonetic >+ key_kp6 = say_next_word >+spk key_kp6 = say_to_right >+ key_kpplus = say_screen >+spk key_kpplus = say_win >+ key_kp1 = say_prev_char >+spk key_kp1 = right_edge >+ key_kp2 = say_char >+spk key_kp2 = say_to_bottom >+double key_kp2 = say_phonetic_char >+ key_kp3 = say_next_char >+spk key_kp3 = bottom_edge >+ key_kp0 = spk_key >+ key_kpdot = say_position >+spk key_kpdot = say_attributes >+key_kpenter = speakup_quiet >+spk key_kpenter = speakup_off >+key_sysrq = speech_kill >+ key_kpslash = speakup_cut >+spk key_kpslash = speakup_paste >+spk key_pageup = say_first_char >+spk key_pagedown = say_last_char >+key_capslock = spk_key >+ spk key_z = spk_lock >+key_leftmeta = spk_key >+ctrl spk key_0 = speakup_goto >+spk key_u = say_prev_line >+spk key_i = say_line >+double spk key_i = say_line_indent >+spk key_o = say_next_line >+spk key_minus = speakup_parked >+shift spk key_minus = say_char_num >+spk key_j = say_prev_word >+spk key_k = say_word >+double spk key_k = spell_word >+spk key_l = say_next_word >+spk key_m = say_prev_char >+spk key_comma = say_char >+double spk key_comma = say_phonetic_char >+spk key_dot = say_next_char >+spk key_n = say_position >+ ctrl spk key_m = left_edge >+ ctrl spk key_y = top_edge >+ ctrl spk key_dot = right_edge >+ctrl spk key_p = bottom_edge >+spk key_apostrophe = say_screen >+spk key_h = say_from_left >+spk key_y = say_from_top >+spk key_semicolon = say_to_right >+spk key_p = say_to_bottom >+spk key_slash = say_attributes >+ spk key_enter = speakup_quiet >+ ctrl spk key_enter = speakup_off >+ spk key_9 = speakup_cut >+spk key_8 = speakup_paste >+shift spk key_m = say_first_char >+ ctrl spk key_semicolon = say_last_char >+ >+5. The Speakup Proc System >+ >+The Speakup screen reader also creates a speakup subdirectory as a part >+of the proc system. You can see these entries by typing the command: >+ >+ls -1 /proc/speakup/* >+ >+If you issue the above ls command, you will get back something like >+this: >+ >+/proc/speakup/attrib_bleep >+/proc/speakup/bell_pos >+/proc/speakup/bleep_time >+/proc/speakup/bleeps >+/proc/speakup/caps_start >+/proc/speakup/caps_stop >+/proc/speakup/characters >+/proc/speakup/cursor_time >+/proc/speakup/delay_time >+/proc/speakup/delimiters >+/proc/speakup/ex_num >+/proc/speakup/freq >+/proc/speakup/full_time >+/proc/speakup/jiffy_delta >+/proc/speakup/key_echo >+/proc/speakup/keymap >+/proc/speakup/no_interrupt >+/proc/speakup/pitch >+/proc/speakup/punc_all >+/proc/speakup/punc_level >+/proc/speakup/punc_most >+/proc/speakup/punc_some >+/proc/speakup/punct >+/proc/speakup/rate >+/proc/speakup/reading_punc >+/proc/speakup/repeats >+/proc/speakup/say_control >+/proc/speakup/say_word_ctl >+/proc/speakup/silent >+/proc/speakup/spell_delay >+/proc/speakup/synth_direct >+/proc/speakup/synth_name >+/proc/speakup/tone >+/proc/speakup/trigger_time >+/proc/speakup/version >+/proc/speakup/voice >+/proc/speakup/vol >+ >+In addition to using the Speakup hot keys to change such things as >+volume, pitch, and rate, you can also echo values to the appropriate >+entry in the /proc/speakup directory. This is very useful, since it >+lets you control Speakup parameters from within a script. How you >+would write such scripts is somewhat beyond the scope of this manual, >+but I will include a couple of simple examples here to give you a >+general idea of what such scripts can do. >+ >+Suppose for example, that you wanted to control both the punctuation >+level and the reading punctuation level at the same time. For >+simplicity, we'll call them punc0, punc1, punc2, and punc3. The scripts >+might look something like this: >+ >+#!/bin/bash >+# punc0 >+# set punc and reading punc levels to 0 >+echo 0 >/proc/speakup/punc_level >+echo 0 >/proc/speakup/reading_punc >+echo Punctuation level set to 0. >+ >+#!/bin/bash >+# punc1 >+# set punc and reading punc levels to 1 >+echo 1 >/proc/speakup/punc_level >+echo 1 >/proc/speakup/reading_punc >+echo Punctuation level set to 1. >+ >+#!/bin/bash >+# punc2 >+# set punc and reading punc levels to 2 >+echo 2 >/proc/speakup/punc_level >+echo 2 >/proc/speakup/reading_punc >+echo Punctuation level set to 2. >+ >+#!/bin/bash >+# punc3 >+# set punc and reading punc levels to 3 >+echo 3 >/proc/speakup/punc_level >+echo 3 >/proc/speakup/reading_punc >+echo Punctuation level set to 3. >+ >+If you were to store these four small scripts in a directory in your >+path, perhaps /usr/local/bin, and set the permissions to 755 with the >+chmod command, then you could change the default reading punc and >+punctuation levels at the same time by issuing just one command. For >+example, if you were to execute the punc3 command at your shell prompt, >+then the reading punc and punc level would both get set to 3. >+ >+I should note that the above scripts were written to work with bash, but >+regardless of which shell you use, you should be able to do something >+similar. >+ >+The Speakup proc system also has another interesting use. You can echo >+Speakup parameters into the proc system in a script during system >+startup, and speakup will return to your preferred parameters every time >+the system is rebooted. >+ >+Most of the Speakup proc parameters can be manipulated by a regular user >+on the system. However, there are a few parameters that are dangerous >+enough that they should only be manipulated by the root user on your >+system. There are even some parameters that are read only, and cannot >+be written to at all. For example, the version entry in the Speakup >+proc system is read only. This is because there is no reason for a user >+to tamper with the version number which is reported by Speakup. Doing >+an ls -l on /proc/speakup/version will return this: >+ >+-r--r--r-- 1 root root 0 Mar 21 13:46 /proc/speakup/version >+ >+As you can see, the version entry in the Speakup proc system is read >+only, is owned by root, and belongs to the root group. Doing a cat of >+/proc/speakup/version will display the Speakup version number, like >+this: >+ >+cat /proc/speakup/version >+Speakup v-2.00 CVS: Thu Oct 21 10:38:21 EDT 2004 >+synth dtlk version 1.1 >+ >+The display shows the Speakup version number, along with the version >+number of the driver for the current synthesizer. >+ >+Looking at entries in the Speakup proc system can be useful in many >+ways. For example, you might wish to know what level your volume is set >+at. You could type: >+ >+cat /proc/speakup/vol >+5 >+ >+The number five which comes back is the level at which the synthesizer >+volume is set at. >+ >+All the entries in the Speakup proc system are readable, some are >+writable by root only, and some are writable by everyone. Unless you >+know what you are doing, you should probably leave the ones that are >+writable by root only alone. Most of the names are self explanatory. >+Vol for controlling volume, pitch for pitch, rate for controlling speaking >+rate, etc. If you find one you aren't sure about, you can post a query >+on the Speakup list. >+ >+6. Changing Synthesizers >+ >+It is possible to change to a different synthesizer while speakup is >+running. In other words, it is not necessary to reboot the system >+in order to use a different synthesizer. You can simply echo the >+synthesizer keyword to the /proc/speakup/synth_name proc entry. >+Depending on your situation, you may wish to echo none to the synth_name >+proc entry, to disable speech while one synthesizer is disconnected and >+a second one is connected in its place. Then echo the keyword for the >+new synthesizer into the synth_name proc entry in order to start speech >+with the newly connected synthesizer. See the list of synthesizer >+keywords in section 1 to find the keyword which matches your synth. >+ >+7. Loading modules >+ >+As mentioned earlier, Speakup can either be completely compiled into the >+kernel, with the exception of the help module, or it can be compiled as >+a series of modules. When compiled as modules, Speakup will only be >+able to speak some of the bootup messages if your system administrator >+has configured the system to load the modules at boo time. The modules >+can be loaded after the file systems have been checked and mounted, or >+from an initrd. There is a third possibility. Speakup can be compiled >+with some components built into the kernel, and others as modules. As >+we'll see in the next section, this is particularly useful when you are >+working with software synthesizers. >+ >+If Speakup is completely compiled as modules, then you must use the >+modprobe command to load Speakup. You do this by loading the module for >+the synthesizer driver you wish to use. The driver modules are all >+named speakup_<keyword>, where <keyword> is the keyword for the >+synthesizer you want. So, in order to load the driver for the DecTalk >+Express, you would type the following command: >+ >+modprobe speakup_dectlk >+ >+Issuing this command would load the DecTalk Express driver and all other >+related Speakup modules necessary to get Speakup up and running. >+ >+To completely unload Speakup, again presuming that it is entirely built >+as modules, you would give the command: >+ >+modprobe -r speakup_dectlk >+ >+The above command assumes you were running a DecTalk Express. If you >+were using a different synth, then you would substitute its keyword in >+place of dectlk. >+ >+But now, suppose we have a situation where the main Speakup component >+is built into the kernel, and some or all of the drivers are built as >+modules. Since the main part of Speakup is compiled into the kernel, a >+partial Speakup proc system has been created which we can take advantage >+of by simply echoing the synthesizer keyword into the >+/proc/speakup/synth_name proc entry. This will cause the kernel to >+automatically load the appropriate driver module, and start Speakup >+talking. To switch to another synth, just echo a new keyword to the >+synth_name proc entry. For example, to load the DoubleTalk LT driver, >+you would type: >+ >+echo ltlk >/proc/speakup/synth_name >+ >+You can use the modprobe -r command to unload driver modules, regardless >+of whether the main part of Speakup has been built into the kernel or >+not. >+ >+8. Using Software Synthesizers >+ >+Using a software synthesizer requires that some other software be >+installed and running on your system. For this reason, software >+synthesizers are not available for use at bootup, or during a system >+installation process. >+ >+In order to use a software synthesizer, you must have a package called >+Speech Dispatcher running on your system, and it must be configured to >+work with one of its supported software synthesizers. >+ >+Two open source synthesizers you might use are Flite and Festival. You >+might also choose to purchase the Software DecTalk from Fonix Sales Inc. >+If you run a google search for Fonix, you'll find their web site. >+ >+You can obtain a copy of Speech Dispatcher from free(b)soft at >+http://www.freebsoft.org/. Follow the installation instructions that >+come with Speech Dispatcher in order to install and configure Speech >+Dispatcher. You can check out the web site for your Linux distribution >+in order to get a copy of either Flite or Festival. Your Linux >+distribution may also have a precompiled Speech Dispatcher package. >+ >+Once you've installed, configured, and tested Speech Dispatcher with your >+chosen software synthesizer, you still need one more piece of software >+in order to make things work. You need a package called speechd-up. >+You get it from the free(b)soft web site mentioned above. After you've >+compiled and installed speechd-up, you are almost ready to begin using >+your software synthesizer. >+ >+Before you can use a software synthesizer, you must have created the >+/dev/softsynth device. If you have not already done so, issue the >+following commands as root: >+ >+cd /dev >+mknod softsynth c 10 26 >+ >+While we are at it, we might just as well create the /dev/synth device, >+which can be used to let user space programs send information to your >+synthesizer. To create /dev/synth, change to the /dev directory, and >+issue the following command as root: >+ >+mknod synth c 10 25 >+ >+Now you can begin using your software synthesizer. In order to do so, >+echo the sftsyn keyword to the synth_name proc entry like this: >+ >+echo sftsyn >/proc/speakup/synth_name >+ >+Next run the speechd_up command like this: >+ >+speechd_up & >+ >+Your synth should now start talking, and you should be able to adjust >+the pitch, rate, etc. >+ >+In this section, we have assumed that your copy of Speakup was compiled >+with the speakup_sftsyn component either built into the kernel, or >+compiled as a module. >+ >+9. Using The DecTalk PC Card >+ >+The DecTalk PC card is an ISA card that is inserted into one of the ISA >+slots in your computer. It requires that the DecTalk PC software be >+installed on your computer, and that the software be loaded onto the >+Dectalk PC card before it can be used. >+ >+You can get the dec_pc.tgz file from the linux-speakup.org site. The >+dec_pc.tgz file is in the ~ftp/pub/linux/speakup directory. >+ >+After you have downloaded the dec_pc.tgz file, untar it in your home >+directory, and read the Readme file in the newly created dec_pc >+directory. >+ >+The easiest way to get the software working is to copy the entire dec_pc >+directory into /user/local/lib. To do this, su to root in your home >+directory, and issue the command: >+ >+cp dec_pc /usr/local/lib >+ >+You will need to copy the dtload command from the dec_pc directory to a >+directory in your path. Either /usr/bin or /usr/local/bin is a good >+choice. >+ >+You can now run the dtload command in order to load the DecTalk PC >+software onto the card. After you have done this, echo the decpc >+keyword to the synth_name entry in the proc system like this: >+ >+echo decpc >/proc/speakup/synth_name >+ >+Your DecTalk PC should start talking, and then you can adjust the pitch, >+rate, volume, voice, etc. The voice entry in the Speakup proc system >+will accept a number from 0 through 7 for the DecTalk PC synthesizer, >+which will give you access to some of the DecTalk voices. >+ >+10. Using Cursor Tracking >+ >+In Speakup version 2.0 and later, cursor tracking is turned on by >+default. This means that when you are using an editor, Speakup will >+automatically speak characters as you move left and right with the >+cursor keys, and lines as you move up and down with the cursor keys. >+ >+This is extremely useful, and makes editing files a snap. But there are >+times when cursor tracking can get in your way. So Speakup provides a >+toggle to turn cursor tracking on and off. You do this with the keypad >+asterisk key. Pressing this key repeatedly will toggle the cursor >+tracking on and off, and you will hear Speakup say, "cursoring off", and >+"cursoring on". >+ >+Some folks like to turn cursor tracking off while they are using the >+lynx web browser. You definitely want to turn cursor tracking off when >+you are using the alsamixer application. Otherwise, you won't be able >+to hear your mixer settings while you are using the arrow keys. >+ >+11. Cut and Paste >+ >+One of Speakup's more useful features is the ability to cut and paste >+text on the screen. This means that you can capture information from a >+program, and paste that captured text into a different place in the >+program, or into an entirely different program, which may even be >+running on a different console. >+ >+For example, in this manual, we have made references to several web >+sites. It would be nice if you could cut and paste these urls into your >+web browser. Speakup does this quite nicely. Suppose you wanted to >+past the following url into your browser: >+ >+http://linux-speakup.org/ >+ >+Use the speakup review keys to position the reading cursor on the first >+character of the above url. When the reading cursor is in position, >+press the keypad slash key once. Speakup will say, "mark". Next, >+position the reading cursor on the rightmost character of the above >+url. Press the keypad slash key once again to actually cut the text >+from the screen. Speakup will say, "cut". Although we call this >+cutting, Speakup does not actually delete the cut text from the screen. >+It makes a copy of the text in a special buffer for later pasting. >+ >+Now that you have the url cut from the screen, you can paste it into >+your browser, or even paste the url on a command line as an argument to >+your browser. >+ >+Suppose you want to start lynx and go to the Speakup site. >+ >+You can switch to a different console with the alt left and right >+arrows, or you can switch to a specific console by typing alt and a >+function key. These are not Speakup commands, just standard Linux >+console capabilities. >+ >+Once you've changed to an appropriate console, and are at a shell prompt, >+type the word lynx, followed by a space. Now press and hold the speakup >+key, while you type the keypad slash character. The url will be pasted >+onto the command line, just as though you had typed it in. Press the >+enter key to execute the command. >+ >+The paste buffer will continue to hold the cut information, until a new >+mark and cut operation is carried out. This means you can paste the cut >+information as many times as you like before doing another cut >+operation. >+ >+You are not limited to cutting and pasting only one line on the screen. >+You can also cut and paste rectangular regions of the screen. Just >+position the reading cursor at the top left corner of the text to be >+cut, mark it with the keypad slash key, then position the reading cursor >+at the bottom right corner of the region to be cut, and cut it with the >+keypad slash key. >+ >+12. Changing the Pronunciation of Characters >+ >+Through the /proc/speakup/chars proc entry, Speakup gives you the >+ability to change how Speakup pronounces a given character. You could, >+for example, change how some punctuation characters are spoken. You can >+even change how Speakup will pronounce certain letters. >+ >+You may, for example, wish to change how Speakup pronounces the z >+character. The author of Speakup, Kirk Reiser, is Canadian, and thus >+believes that the z should be pronounced zed. If you are an American, >+you might wish to use the zee pronunciation instead of zed. You can >+change the pronunciation of both the upper and lower case z with the >+following two commands: >+ >+echo 90 zee >/proc/speakup/characters >+echo 122 zee >/proc/speakup/characters >+ >+Let's examine the parts of the two previous commands. They are issued >+at the shell prompt, and could be placed in a startup script. >+ >+The word echo tells the shell that you want to have it display the >+string of characters that follow the word echo. If you were to just >+type: >+ >+echo hello. >+ >+You would get the word hello printed on your screen as soon as you >+pressed the enter key. In this case, we are echoing strings that we >+want to be redirected into the proc system. >+ >+The numbers 90 and 122 in the above echo commands are the ascii numeric >+values for the upper and lower case z, the characters we wish to change. >+ >+The string zee is the pronunciation that we want Speakup to use for the >+upper and lower case z. >+ >+The > symbol redirects the output of the echo command to a file, just >+like in DOS, or at the Windows command prompt. >+ >+And finally, /proc/speakup/chars is the file entry in the proc system >+where we want the output to be directed. Speakup looks at the numeric >+value of the character we want to change, and inserts the pronunciation >+string into an internal table. >+ >+You can look at the whole table with the following command: >+ >+cat /proc/speakup/chars >+ >+Speakup will then print out the entire character pronunciation table. I >+won't display it here, but leave you to look at it at your convenience. >+ >+13. Mapping Keys >+ >+Speakup has the capability of allowing you to assign or "map" keys to >+internal Speakup commands. This section necessarily assumes you have a >+Linux kernel source tree installed, and that it has been patched and >+configured with Speakup. How you do this is beyond the scope of this >+manual. For this information, visit the Speakup web site at >+http://linux-speakup.org/. The reason you'll need the kernel source >+tree patched with Speakup is that the genmap utility you'll need for >+processing keymaps is in the >+/usr/src/linux-<version_number>/drivers/char/speakup directory. The >+<version_number> in the above directory path is the version number of >+the Linux source tree you are working with. >+ >+So ok, you've gone off and gotten your kernel source tree, and patched >+and configured it. Now you can start manipulating keymaps. >+ >+You can either use the >+/usr/src/linux-<version_number>/drivers/char/speakup/speakupmap.map file >+included with the Speakup source, or you can cut and paste the copy in >+section 4 into a separate file. If you use the one in the Speakup >+source tree, make sure you make a backup of it before you start making >+changes. You have been warned! >+ >+Suppose that you want to swap the key assignments for the Speakup >+say_last_char and the Speakup say_first_char commands. The >+speakupmap.map lists the key mappings for these two commands as follows: >+ >+spk key_pageup = say_first_char >+spk key_pagedown = say_last_char >+ >+You can edit your copy of the speakupmap.map file and swap the command >+names on the right side of the = (equals) sign. You did make a backup, >+right? The new keymap lines would look like this: >+ >+spk key_pageup = say_last_char >+spk key_pagedown = say_first_char >+ >+After you edit your copy of the speakupmap.map file, save it under a new >+file name, perhaps newmap.map. Then exit your editor and return to the >+shell prompt. >+ >+You are now ready to load your keymap with your swapped key assignments. >+ Assuming that you saved your new keymap as the file newmap.map, you >+would load your keymap into the proc system like this: >+ >+/usr/src/linux-<version_number>/drivers/char/speakup/genmap newmap.map >+>/proc/speakup/keymap >+ >+Remember to substitute your kernel version number for the >+<version_number> in the above command. Also note that although the >+above command wrapped onto two lines in this document, you should type >+it all on one line. >+ >+Your say first and say last characters should now be swapped. Pressing >+speakup pagedown should read you the first non-whitespace character on >+the line your reading cursor is in, and pressing speakup pageup should >+read you the last character on the line your reading cursor is in. >+ >+You should note that these new mappings will only stay in effect until >+you reboot, or until you load another keymap. >+ >+One final warning. If you try to load a partial map, you will quickly >+find that all the mappings you didn't include in your file got deleted >+from the working map. Be extremely careful, and always make a backup! >+You have been warned! >+ >+14. Using Speakup's Windowing Capability >+ >+Speakup has the capability of defining and manipulating windows on the >+screen. Speakup uses the term "Window", to mean a user defined area of >+the screen. The key strokes for defining and manipulating Speakup >+windows are as follows: >+ >+speakup + f2 -- Set the bounds of the window. >+Speakup + f3 -- clear the current window definition. >+speakup + f4 -- Toggle window silence on and off. >+speakup + keypad plus -- Say the currently defined window. >+ >+These capabilities are useful for tracking a certain part of the screen >+without rereading the whole screen, or for silencing a part of the >+screen that is constantly changing, such as a clock or status line. >+ >+There is no way to save these window settings, and you can only have one >+window defined for each virtual console. There is also no way to have >+windows automaticly defined for specific applications. >+ >+In order to define a window, use the review keys to move your reading >+cursor to the beginning of the area you want to define. Then press >+speakup + f2. Speakup will tell you that the window starts at the >+indicated row and column position. Then move the reading cursor to the >+end of the area to be defined as a window, and press speakup + f2 again. >+ If there is more than one line in the window, Speakup will tell you >+that the window ends at the indicated row and column position. If there >+is only one line in the window, then Speakup will tell you that the >+window is the specified line on the screen. If you are only defining a >+one line window, you can just press speakup + f2 twice after placing the >+reading cursor on the line you want to define as a window. It is not >+necessary to position the reading cursor at the end of the line in order >+to define the whole line as a window. >+ >+ GNU Free Documentation License >+ Version 1.2, November 2002 >+ >+ >+ Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. >+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ Everyone is permitted to copy and distribute verbatim copies >+ of this license document, but changing it is not allowed. >+ >+ >+0. PREAMBLE >+ >+The purpose of this License is to make a manual, textbook, or other >+functional and useful document "free" in the sense of freedom: to >+assure everyone the effective freedom to copy and redistribute it, >+with or without modifying it, either commercially or noncommercially. >+Secondarily, this License preserves for the author and publisher a way >+to get credit for their work, while not being considered responsible >+for modifications made by others. >+ >+This License is a kind of "copyleft", which means that derivative >+works of the document must themselves be free in the same sense. It >+complements the GNU General Public License, which is a copyleft >+license designed for free software. >+ >+We have designed this License in order to use it for manuals for free >+software, because free software needs free documentation: a free >+program should come with manuals providing the same freedoms that the >+software does. But this License is not limited to software manuals; >+it can be used for any textual work, regardless of subject matter or >+whether it is published as a printed book. We recommend this License >+principally for works whose purpose is instruction or reference. >+ >+ >+1. APPLICABILITY AND DEFINITIONS >+ >+This License applies to any manual or other work, in any medium, that >+contains a notice placed by the copyright holder saying it can be >+distributed under the terms of this License. Such a notice grants a >+world-wide, royalty-free license, unlimited in duration, to use that >+work under the conditions stated herein. The "Document", below, >+refers to any such manual or work. Any member of the public is a >+licensee, and is addressed as "you". You accept the license if you >+copy, modify or distribute the work in a way requiring permission >+under copyright law. >+ >+A "Modified Version" of the Document means any work containing the >+Document or a portion of it, either copied verbatim, or with >+modifications and/or translated into another language. >+ >+A "Secondary Section" is a named appendix or a front-matter section of >+the Document that deals exclusively with the relationship of the >+publishers or authors of the Document to the Document's overall subject >+(or to related matters) and contains nothing that could fall directly >+within that overall subject. (Thus, if the Document is in part a >+textbook of mathematics, a Secondary Section may not explain any >+mathematics.) The relationship could be a matter of historical >+connection with the subject or with related matters, or of legal, >+commercial, philosophical, ethical or political position regarding >+them. >+ >+The "Invariant Sections" are certain Secondary Sections whose titles >+are designated, as being those of Invariant Sections, in the notice >+that says that the Document is released under this License. If a >+section does not fit the above definition of Secondary then it is not >+allowed to be designated as Invariant. The Document may contain zero >+Invariant Sections. If the Document does not identify any Invariant >+Sections then there are none. >+ >+The "Cover Texts" are certain short passages of text that are listed, >+as Front-Cover Texts or Back-Cover Texts, in the notice that says that >+the Document is released under this License. A Front-Cover Text may >+be at most 5 words, and a Back-Cover Text may be at most 25 words. >+ >+A "Transparent" copy of the Document means a machine-readable copy, >+represented in a format whose specification is available to the >+general public, that is suitable for revising the document >+straightforwardly with generic text editors or (for images composed of >+pixels) generic paint programs or (for drawings) some widely available >+drawing editor, and that is suitable for input to text formatters or >+for automatic translation to a variety of formats suitable for input >+to text formatters. A copy made in an otherwise Transparent file >+format whose markup, or absence of markup, has been arranged to thwart >+or discourage subsequent modification by readers is not Transparent. >+An image format is not Transparent if used for any substantial amount >+of text. A copy that is not "Transparent" is called "Opaque". >+ >+Examples of suitable formats for Transparent copies include plain >+ASCII without markup, Texinfo input format, LaTeX input format, SGML >+or XML using a publicly available DTD, and standard-conforming simple >+HTML, PostScript or PDF designed for human modification. Examples of >+transparent image formats include PNG, XCF and JPG. Opaque formats >+include proprietary formats that can be read and edited only by >+proprietary word processors, SGML or XML for which the DTD and/or >+processing tools are not generally available, and the >+machine-generated HTML, PostScript or PDF produced by some word >+processors for output purposes only. >+ >+The "Title Page" means, for a printed book, the title page itself, >+plus such following pages as are needed to hold, legibly, the material >+this License requires to appear in the title page. For works in >+formats which do not have any title page as such, "Title Page" means >+the text near the most prominent appearance of the work's title, >+preceding the beginning of the body of the text. >+ >+A section "Entitled XYZ" means a named subunit of the Document whose >+title either is precisely XYZ or contains XYZ in parentheses following >+text that translates XYZ in another language. (Here XYZ stands for a >+specific section name mentioned below, such as "Acknowledgements", >+"Dedications", "Endorsements", or "History".) To "Preserve the Title" >+of such a section when you modify the Document means that it remains a >+section "Entitled XYZ" according to this definition. >+ >+The Document may include Warranty Disclaimers next to the notice which >+states that this License applies to the Document. These Warranty >+Disclaimers are considered to be included by reference in this >+License, but only as regards disclaiming warranties: any other >+implication that these Warranty Disclaimers may have is void and has >+no effect on the meaning of this License. >+ >+ >+2. VERBATIM COPYING >+ >+You may copy and distribute the Document in any medium, either >+commercially or noncommercially, provided that this License, the >+copyright notices, and the license notice saying this License applies >+to the Document are reproduced in all copies, and that you add no other >+conditions whatsoever to those of this License. You may not use >+technical measures to obstruct or control the reading or further >+copying of the copies you make or distribute. However, you may accept >+compensation in exchange for copies. If you distribute a large enough >+number of copies you must also follow the conditions in section 3. >+ >+You may also lend copies, under the same conditions stated above, and >+you may publicly display copies. >+ >+ >+3. COPYING IN QUANTITY >+ >+If you publish printed copies (or copies in media that commonly have >+printed covers) of the Document, numbering more than 100, and the >+Document's license notice requires Cover Texts, you must enclose the >+copies in covers that carry, clearly and legibly, all these Cover >+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on >+the back cover. Both covers must also clearly and legibly identify >+you as the publisher of these copies. The front cover must present >+the full title with all words of the title equally prominent and >+visible. You may add other material on the covers in addition. >+Copying with changes limited to the covers, as long as they preserve >+the title of the Document and satisfy these conditions, can be treated >+as verbatim copying in other respects. >+ >+If the required texts for either cover are too voluminous to fit >+legibly, you should put the first ones listed (as many as fit >+reasonably) on the actual cover, and continue the rest onto adjacent >+pages. >+ >+If you publish or distribute Opaque copies of the Document numbering >+more than 100, you must either include a machine-readable Transparent >+copy along with each Opaque copy, or state in or with each Opaque copy >+a computer-network location from which the general network-using >+public has access to download using public-standard network protocols >+a complete Transparent copy of the Document, free of added material. >+If you use the latter option, you must take reasonably prudent steps, >+when you begin distribution of Opaque copies in quantity, to ensure >+that this Transparent copy will remain thus accessible at the stated >+location until at least one year after the last time you distribute an >+Opaque copy (directly or through your agents or retailers) of that >+edition to the public. >+ >+It is requested, but not required, that you contact the authors of the >+Document well before redistributing any large number of copies, to give >+them a chance to provide you with an updated version of the Document. >+ >+ >+4. MODIFICATIONS >+ >+You may copy and distribute a Modified Version of the Document under >+the conditions of sections 2 and 3 above, provided that you release >+the Modified Version under precisely this License, with the Modified >+Version filling the role of the Document, thus licensing distribution >+and modification of the Modified Version to whoever possesses a copy >+of it. In addition, you must do these things in the Modified Version: >+ >+A. Use in the Title Page (and on the covers, if any) a title distinct >+ from that of the Document, and from those of previous versions >+ (which should, if there were any, be listed in the History section >+ of the Document). You may use the same title as a previous version >+ if the original publisher of that version gives permission. >+B. List on the Title Page, as authors, one or more persons or entities >+ responsible for authorship of the modifications in the Modified >+ Version, together with at least five of the principal authors of the >+ Document (all of its principal authors, if it has fewer than five), >+ unless they release you from this requirement. >+C. State on the Title page the name of the publisher of the >+ Modified Version, as the publisher. >+D. Preserve all the copyright notices of the Document. >+E. Add an appropriate copyright notice for your modifications >+ adjacent to the other copyright notices. >+F. Include, immediately after the copyright notices, a license notice >+ giving the public permission to use the Modified Version under the >+ terms of this License, in the form shown in the Addendum below. >+G. Preserve in that license notice the full lists of Invariant Sections >+ and required Cover Texts given in the Document's license notice. >+H. Include an unaltered copy of this License. >+I. Preserve the section Entitled "History", Preserve its Title, and add >+ to it an item stating at least the title, year, new authors, and >+ publisher of the Modified Version as given on the Title Page. If >+ there is no section Entitled "History" in the Document, create one >+ stating the title, year, authors, and publisher of the Document as >+ given on its Title Page, then add an item describing the Modified >+ Version as stated in the previous sentence. >+J. Preserve the network location, if any, given in the Document for >+ public access to a Transparent copy of the Document, and likewise >+ the network locations given in the Document for previous versions >+ it was based on. These may be placed in the "History" section. >+ You may omit a network location for a work that was published at >+ least four years before the Document itself, or if the original >+ publisher of the version it refers to gives permission. >+K. For any section Entitled "Acknowledgements" or "Dedications", >+ Preserve the Title of the section, and preserve in the section all >+ the substance and tone of each of the contributor acknowledgements >+ and/or dedications given therein. >+L. Preserve all the Invariant Sections of the Document, >+ unaltered in their text and in their titles. Section numbers >+ or the equivalent are not considered part of the section titles. >+M. Delete any section Entitled "Endorsements". Such a section >+ may not be included in the Modified Version. >+N. Do not retitle any existing section to be Entitled "Endorsements" >+ or to conflict in title with any Invariant Section. >+O. Preserve any Warranty Disclaimers. >+ >+If the Modified Version includes new front-matter sections or >+appendices that qualify as Secondary Sections and contain no material >+copied from the Document, you may at your option designate some or all >+of these sections as invariant. To do this, add their titles to the >+list of Invariant Sections in the Modified Version's license notice. >+These titles must be distinct from any other section titles. >+ >+You may add a section Entitled "Endorsements", provided it contains >+nothing but endorsements of your Modified Version by various >+parties--for example, statements of peer review or that the text has >+been approved by an organization as the authoritative definition of a >+standard. >+ >+You may add a passage of up to five words as a Front-Cover Text, and a >+passage of up to 25 words as a Back-Cover Text, to the end of the list >+of Cover Texts in the Modified Version. Only one passage of >+Front-Cover Text and one of Back-Cover Text may be added by (or >+through arrangements made by) any one entity. If the Document already >+includes a cover text for the same cover, previously added by you or >+by arrangement made by the same entity you are acting on behalf of, >+you may not add another; but you may replace the old one, on explicit >+permission from the previous publisher that added the old one. >+ >+The author(s) and publisher(s) of the Document do not by this License >+give permission to use their names for publicity for or to assert or >+imply endorsement of any Modified Version. >+ >+ >+5. COMBINING DOCUMENTS >+ >+You may combine the Document with other documents released under this >+License, under the terms defined in section 4 above for modified >+versions, provided that you include in the combination all of the >+Invariant Sections of all of the original documents, unmodified, and >+list them all as Invariant Sections of your combined work in its >+license notice, and that you preserve all their Warranty Disclaimers. >+ >+The combined work need only contain one copy of this License, and >+multiple identical Invariant Sections may be replaced with a single >+copy. If there are multiple Invariant Sections with the same name but >+different contents, make the title of each such section unique by >+adding at the end of it, in parentheses, the name of the original >+author or publisher of that section if known, or else a unique number. >+Make the same adjustment to the section titles in the list of >+Invariant Sections in the license notice of the combined work. >+ >+In the combination, you must combine any sections Entitled "History" >+in the various original documents, forming one section Entitled >+"History"; likewise combine any sections Entitled "Acknowledgements", >+and any sections Entitled "Dedications". You must delete all sections >+Entitled "Endorsements". >+ >+ >+6. COLLECTIONS OF DOCUMENTS >+ >+You may make a collection consisting of the Document and other documents >+released under this License, and replace the individual copies of this >+License in the various documents with a single copy that is included in >+the collection, provided that you follow the rules of this License for >+verbatim copying of each of the documents in all other respects. >+ >+You may extract a single document from such a collection, and distribute >+it individually under this License, provided you insert a copy of this >+License into the extracted document, and follow this License in all >+other respects regarding verbatim copying of that document. >+ >+ >+7. AGGREGATION WITH INDEPENDENT WORKS >+ >+A compilation of the Document or its derivatives with other separate >+and independent documents or works, in or on a volume of a storage or >+distribution medium, is called an "aggregate" if the copyright >+resulting from the compilation is not used to limit the legal rights >+of the compilation's users beyond what the individual works permit. >+When the Document is included in an aggregate, this License does not >+apply to the other works in the aggregate which are not themselves >+derivative works of the Document. >+ >+If the Cover Text requirement of section 3 is applicable to these >+copies of the Document, then if the Document is less than one half of >+the entire aggregate, the Document's Cover Texts may be placed on >+covers that bracket the Document within the aggregate, or the >+electronic equivalent of covers if the Document is in electronic form. >+Otherwise they must appear on printed covers that bracket the whole >+aggregate. >+ >+ >+8. TRANSLATION >+ >+Translation is considered a kind of modification, so you may >+distribute translations of the Document under the terms of section 4. >+Replacing Invariant Sections with translations requires special >+permission from their copyright holders, but you may include >+translations of some or all Invariant Sections in addition to the >+original versions of these Invariant Sections. You may include a >+translation of this License, and all the license notices in the >+Document, and any Warranty Disclaimers, provided that you also include >+the original English version of this License and the original versions >+of those notices and disclaimers. In case of a disagreement between >+the translation and the original version of this License or a notice >+or disclaimer, the original version will prevail. >+ >+If a section in the Document is Entitled "Acknowledgements", >+"Dedications", or "History", the requirement (section 4) to Preserve >+its Title (section 1) will typically require changing the actual >+title. >+ >+ >+9. TERMINATION >+ >+You may not copy, modify, sublicense, or distribute the Document except >+as expressly provided for under this License. Any other attempt to >+copy, modify, sublicense or distribute the Document is void, and will >+automatically terminate your rights under this License. However, >+parties who have received copies, or rights, from you under this >+License will not have their licenses terminated so long as such >+parties remain in full compliance. >+ >+ >+10. FUTURE REVISIONS OF THIS LICENSE >+ >+The Free Software Foundation may publish new, revised versions >+of the GNU Free Documentation License from time to time. Such new >+versions will be similar in spirit to the present version, but may >+differ in detail to address new problems or concerns. See >+http://www.gnu.org/copyleft/. >+ >+Each version of the License is given a distinguishing version number. >+If the Document specifies that a particular numbered version of this >+License "or any later version" applies to it, you have the option of >+following the terms and conditions either of that specified version or >+of any later version that has been published (not as a draft) by the >+Free Software Foundation. If the Document does not specify a version >+number of this License, you may choose any version ever published (not >+as a draft) by the Free Software Foundation. >+ >+ >+ADDENDUM: How to use this License for your documents >+ >+To use this License in a document you have written, include a copy of >+the License in the document and put the following copyright and >+license notices just after the title page: >+ >+ Copyright (c) YEAR YOUR NAME. >+ Permission is granted to copy, distribute and/or modify this document >+ under the terms of the GNU Free Documentation License, Version 1.2 >+ or any later version published by the Free Software Foundation; >+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. >+ A copy of the license is included in the section entitled "GNU >+ Free Documentation License". >+ >+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, >+replace the "with...Texts." line with this: >+ >+ with the Invariant Sections being LIST THEIR TITLES, with the >+ Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. >+ >+If you have Invariant Sections without Cover Texts, or some other >+combination of the three, merge those two alternatives to suit the >+situation. >+ >+If your document contains nontrivial examples of program code, we >+recommend releasing these examples in parallel under your choice of >+free software license, such as the GNU General Public License, >+to permit their use in free software. >+ >+The End. >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/consolemap.c linux-2.6.20-spk/drivers/char/consolemap.c >--- linux-2.6.20/drivers/char/consolemap.c 2007-02-04 16:08:01.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/consolemap.c 2007-02-04 16:09:21.000000000 -0500 >@@ -667,3 +667,4 @@ console_map_init(void) > } > > EXPORT_SYMBOL(con_copy_unimap); >+EXPORT_SYMBOL_GPL(inverse_translate); >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/keyboard.c linux-2.6.20-spk/drivers/char/keyboard.c >--- linux-2.6.20/drivers/char/keyboard.c 2007-02-04 16:08:01.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/keyboard.c 2007-02-04 16:09:21.000000000 -0500 >@@ -41,6 +41,22 @@ > #include <linux/input.h> > #include <linux/reboot.h> > >+ >+#include <linux/speakup.h> >+ >+#if defined(CONFIG_SPEAKUP_MODULE) >+ >+spk_key_func addr_spk_key = NULL; >+#define speakup_key_call(__vc, __shift, __keycode, __key, __down) \ >+ (addr_spk_key && (*addr_spk_key)(__vc, __shift, __keycode, __key, __down)) >+ >+#elif defined(CONFIG_SPEAKUP) >+#define speakup_key_call(__vc, __shift, __keycode, __key, __down) \ >+ speakup_key(__vc, __shift, __keycode, __key, __down) >+#else >+#define speakup_key_call(__vc, __shift, __keycode, __key, __down) 0 >+#endif >+ > static void kbd_disconnect(struct input_handle *handle); > extern void ctrl_alt_del(void); > >@@ -65,6 +81,10 @@ extern void ctrl_alt_del(void); > > #define KBD_DEFLOCK 0 > >+/* Key types processed even in raw modes */ >+ >+#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT) | (1 << KT_SPKUP)) >+ > void compute_shiftstate(void); > > /* >@@ -80,7 +100,7 @@ void compute_shiftstate(void); > typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, > char up_flag); > static k_handler_fn K_HANDLERS; >-static k_handler_fn *k_handler[16] = { K_HANDLERS }; >+k_handler_fn *k_handler[16] = { K_HANDLERS }; > > #define FN_HANDLERS\ > fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\ >@@ -101,13 +121,16 @@ static fn_handler_fn *fn_handler[] = { F > const int max_vals[] = { > 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1, > NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, >- 255, NR_LOCK - 1, 255, NR_BRL - 1 >+ 255, NR_LOCK - 1, 255, NR_BRL - 1, 255 > }; > > const int NR_TYPES = ARRAY_SIZE(max_vals); > > struct kbd_struct kbd_table[MAX_NR_CONSOLES]; >-static struct kbd_struct *kbd = kbd_table; >+struct kbd_struct *kbd = kbd_table; >+ >+EXPORT_SYMBOL_GPL(kbd); >+EXPORT_SYMBOL_GPL(k_handler); > > struct vt_spawn_console vt_spawn_con = { > .lock = SPIN_LOCK_UNLOCKED, >@@ -266,6 +289,8 @@ void kd_mksound(unsigned int hz, unsigne > kd_nosound(0); > } > >+EXPORT_SYMBOL_GPL(kd_mksound); >+ > /* > * Setting the keyboard rate. > */ >@@ -623,6 +648,7 @@ static void k_spec(struct vc_data *vc, u > if (up_flag) > return; > if (value >= ARRAY_SIZE(fn_handler)) >+ if (up_flag || (value >= ARRAY_SIZE(fn_handler))) > return; > if ((kbd->kbdmode == VC_RAW || > kbd->kbdmode == VC_MEDIUMRAW) && >@@ -1233,6 +1259,9 @@ static void kbd_keycode(unsigned int key > key_map = key_maps[shift_final]; > > if (!key_map) { >+ if (speakup_key_call(vc, shift_final, keycode, K(KT_SHIFT,0), !down)) >+ return; >+ > compute_shiftstate(); > kbd->slockstate = 0; > return; >@@ -1256,6 +1285,9 @@ static void kbd_keycode(unsigned int key > > type -= 0xf0; > >+ if (speakup_key_call(vc, shift_final, keycode, keysym, !down)) >+ return; >+ > if (raw_mode && type != KT_SPEC && type != KT_SHIFT) > return; > >@@ -1274,6 +1306,9 @@ static void kbd_keycode(unsigned int key > kbd->slockstate = 0; > } > >+struct input_dev *fakekeydev=NULL; >+EXPORT_SYMBOL_GPL(fakekeydev); >+ > static void kbd_event(struct input_handle *handle, unsigned int event_type, > unsigned int event_code, int value) > { >@@ -1311,6 +1346,7 @@ static struct input_handle *kbd_connect( > return NULL; > > handle->dev = dev; >+ fakekeydev = dev; > handle->handler = handler; > handle->name = "kbd"; > >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/Makefile linux-2.6.20-spk/drivers/char/Makefile >--- linux-2.6.20/drivers/char/Makefile 2007-02-04 16:08:01.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/Makefile 2007-02-04 16:09:21.000000000 -0500 >@@ -91,6 +91,7 @@ obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu. > obj-$(CONFIG_TANBAC_TB0219) += tb0219.o > obj-$(CONFIG_TELCLOCK) += tlclk.o > >+obj-$(CONFIG_SPEAKUP) += speakup/ > obj-$(CONFIG_WATCHDOG) += watchdog/ > obj-$(CONFIG_MWAVE) += mwave/ > obj-$(CONFIG_AGP) += agp/ >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 >--- linux-2.6.20/drivers/char/speakup/Config.in 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/Config.in 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,26 @@ >+tristate 'Speakup console speech' CONFIG_SPEAKUP >+if [ "$CONFIG_SPEAKUP" != "n" ]; then >+ comment 'Type "y" for each synthesizer you want built into the kernel.' >+ dep_tristate "Accent SA, acntsa" CONFIG_SPEAKUP_ACNTSA $CONFIG_SPEAKUP >+ dep_tristate "Accent PC, acntpc" CONFIG_SPEAKUP_ACNTPC $CONFIG_SPEAKUP >+ dep_tristate "Apollo, apollo" CONFIG_SPEAKUP_APOLLO $CONFIG_SPEAKUP >+ dep_tristate "Audapter, audptr" CONFIG_SPEAKUP_AUDPTR $CONFIG_SPEAKUP >+ dep_tristate "Braille 'n' Speak, bns" CONFIG_SPEAKUP_BNS $CONFIG_SPEAKUP >+ dep_tristate "DECtalk Express, dectlk" CONFIG_SPEAKUP_DECTLK $CONFIG_SPEAKUP >+ dep_tristate "DECtalk External (old), decext" CONFIG_SPEAKUP_DECEXT $CONFIG_SPEAKUP >+ dep_tristate "DECtalk PC (big ISA card), decpc" CONFIG_SPEAKUP_DECPC $CONFIG_SPEAKUP >+ if [ "$CONFIG_SPEAKUP_DECPC" = "y" ] ;then >+ comment 'warning: decpc can only be built as a module' >+ fi >+ comment 'In order to use this you will need' >+ comment 'the dtload program and DECPC software files ' >+ comment 'Read the accompanying DECPC documentation for more details' >+ dep_tristate "DoubleTalk PC, dtlk" CONFIG_SPEAKUP_DTLK $CONFIG_SPEAKUP >+ dep_tristate "Keynote Gold PC, keypc" CONFIG_SPEAKUP_KEYPC $CONFIG_SPEAKUP >+ dep_tristate "DoubleTalk LT or LiteTalk, ltlk" CONFIG_SPEAKUP_LTLK $CONFIG_SPEAKUP >+ dep_tristate "Software synthesizers /dev/sftsyn, sftsyn" CONFIG_SPEAKUP_SFTSYN $CONFIG_SPEAKUP >+ dep_tristate "Speak Out, spkout" CONFIG_SPEAKUP_SPKOUT $CONFIG_SPEAKUP >+ dep_tristate "Transport, txprt" CONFIG_SPEAKUP_TXPRT $CONFIG_SPEAKUP >+ comment 'Enter the three to six character synth string from above or none.' >+ string "Default synthesizer for Speakup" CONFIG_SPEAKUP_DEFAULT "none" >+fi >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 >--- linux-2.6.20/drivers/char/speakup/cvsversion.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/cvsversion.h 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1 @@ >+#define CVSVERSION " CVS: Sat Oct 7 10:52:29 EDT 2006 " >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 >--- linux-2.6.20/drivers/char/speakup/dtload.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/dtload.c 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,553 @@ >+/* >+ * This is the DECtalk PC firmware loader for the Linux kernel, version 1.0 >+ * >+ * Original 386BSD source: >+ * Copyright ( c ) 1996 Brian Buhrow <buhrow@lothlorien.nfbcal.org> >+ * >+ * Adapted for Linux: >+ * Copyright ( c ) 1997 Nicolas Pitre <nico@cam.org> >+ * >+ * Adapted for speakup: >+ * Copyright ( c ) 2003 David Borowski <david575@golden.net> >+ * >+ * All rights reserved. >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 2 of the License, or >+ * ( at your option ) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, write to the Free Software >+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+ * >+ */ >+ >+#include <stdio.h> >+#include <stdlib.h> >+#include <unistd.h> >+#include <string.h> >+#include <sys/types.h> >+#include <sys/stat.h> >+#include <fcntl.h> >+#include <malloc.h> >+#include <sys/errno.h> >+#include <asm/io.h> >+#include "dtload.h" >+#include "dtpc_reg.h" >+ >+static int verbose = 0, intest = 0,infd = -1; >+static int image_len, total_paras; >+static int dt_stat, dma_state = 0, has_kernel = 0; >+static struct dos_reloc fixups[512]; >+static char *read_buff = NULL; >+static struct dos_exe_header header; >+static u_short iobase = 0x350; >+ >+static int dt_getstatus( ) >+{ >+ dt_stat = inb_p( iobase )|(inb_p( iobase+1 )<<8); >+ return dt_stat; >+} >+ >+static void dt_sendcmd( u_int cmd ) >+{ >+ outb_p( cmd & 0xFF, iobase ); >+ outb_p( (cmd>>8) & 0xFF, iobase+1 ); >+} >+ >+static int dt_waitbit( int bit ) >+{ >+ int timeout = 100; >+ while ( --timeout > 0 ) { >+ if( (dt_getstatus( ) & bit ) == bit ) return 1; >+ usleep( 1000 ); >+ } >+ return 0; >+} >+ >+static int dt_sendcmd_wait( u_int cmd, int bit ) >+{ >+ int timeout = 1000; >+ outb_p( cmd & 0xFF, iobase ); >+ outb_p( (cmd>>8) & 0xFF, iobase+1 ); >+ while ( --timeout > 0 ) { >+ if( (dt_getstatus( ) & bit ) == bit ) return 1; >+ usleep( 1000 ); >+ } >+ return 0; >+} >+ >+static int dt_waitmode( int pattern ) >+{ >+ int timeout = 1000; >+ while ( --timeout > 0 ) { >+ if( dt_getstatus( ) == pattern ) return 1; >+ usleep( 1000 ); >+ } >+ fprintf( stderr, "waitmode p=%x s = %x\n", pattern, dt_stat ); >+ return 0; >+} >+ >+static int dt_wait_dma( ) >+{ >+ int timeout = 1000, state = dma_state; >+ if( !has_kernel ){ >+ usleep( 500 ); >+ return( dt_waitbit( STAT_dma_ready ) ); >+ } >+ if( ! dt_waitbit( STAT_dma_ready ) ) return 0; >+ while ( --timeout > 0 ) { >+ if( (dt_getstatus()&STAT_dma_state) == state ) return 1; >+ usleep( 1000 ); >+ } >+ dma_state = dt_getstatus( ) & STAT_dma_state; >+ return 1; >+} >+ >+dt_ctrl( u_int cmd ) >+{ >+ while ( ! dt_waitbit( STAT_cmd_ready ) ) usleep( 100 ); >+ outb_p( 0, iobase+2 ); >+ outb_p( 0, iobase+3 ); >+ dt_getstatus( ); >+ dt_sendcmd( CMD_control|cmd ); >+ outb_p( 0, iobase+6 ); >+ usleep( 100 ); >+ dt_sendcmd( CMD_null ); >+ while ( ! dt_waitbit( STAT_cmd_ready ) ) usleep( 100 ); >+} >+ >+int dt_flush( void ) >+{ >+ dt_ctrl( CTRL_flush ); >+ dt_waitbit( STAT_dma_ready ); >+ outb_p( DMA_sync, iobase+4 ); >+ outb_p( 0, iobase+4 ); >+ dma_state ^= STAT_dma_state; >+ while( dt_getstatus( ) & STAT_flushing ) usleep( 100 ); >+ return 0; >+} >+ >+static int dt_sendbuff( char *src, int len ) >+{ >+ while( len-- ){ >+ if( ! dt_wait_dma( ) ) return -1; >+ if( ! (dt_getstatus( ) & STAT_rr_char) ) break; >+ outb_p( DMA_single_in, iobase+4 ); >+ outb_p( *src++, iobase+4 ); >+ dma_state ^= STAT_dma_state; >+ } >+ return 0; >+} >+ >+unsigned long dt_allocmem( unsigned long paras ) >+{ >+ unsigned long addr; >+ if( ! dt_wait_dma( ) ) return 0; >+ outb_p( DMA_control, iobase+4 ); >+ outb_p( DT_MEM_ALLOC, iobase+4 ); >+ dma_state ^= STAT_dma_state; >+ if( ! dt_wait_dma( ) ) return 0; >+ outb_p( paras & 0xFF, iobase+4 ); >+ outb_p( (paras>>8) & 0xFF, iobase+4 ); >+ dma_state ^= STAT_dma_state; >+ if( ! dt_wait_dma( ) ) return 0; >+ addr = inb_p( iobase+4 ); >+ addr |= (inb_p( iobase+4 )<<8); >+ addr += (inb_p( iobase+4 )<<4); >+ addr += (inb_p( iobase+4 )<<12); >+ dma_state ^= STAT_dma_state; >+ return addr; >+} >+ >+static int testkernel( void ) >+{ >+ dt_sendcmd( CMD_sync ); >+ if( ! dt_waitbit( STAT_cmd_ready ) ) return -10; >+ has_kernel = ( dt_stat&0x8000 ) ? 1 : 0; >+ if ( verbose ) printf( "testkernel got %x\n", dt_stat ); >+ if ( has_kernel ) return 0; >+ usleep( 100 ); >+ return 1; >+} >+ >+static int dt_loadmem( int addr, int len, char *src ) >+{ >+ char c; >+ int l; >+ if ( verbose ) printf( "dt_loadmem: addr = %08X size = %d\n", addr, len ); >+ do { >+ l = len; >+ if ( l >= 0xc000 ) l = 0xc000; >+ len -= l; >+ if( ! dt_wait_dma( ) ) return -1; >+ outb_p( DMA_control, iobase+4 ); >+ outb_p( DT_LOAD_MEM, iobase+4 ); >+ dma_state ^= STAT_dma_state; >+ if( ! dt_wait_dma( ) ) return -2; >+ outb_p( addr & 0xFF, iobase+4 ); >+ outb_p( (addr>>8) & 0xFF, iobase+4 ); >+ outb_p( (addr>>16) & 0xFF, iobase+4 ); >+ outb_p( (addr>>24) & 0xFF, iobase+4 ); >+ outb_p( l & 0xFF, iobase+4 ); >+ outb_p( (l>>8) & 0xFF, iobase+4 ); >+ dma_state ^= STAT_dma_state; >+ if( ! dt_wait_dma( ) ) return -3; >+ addr += l; >+ while( l-- ){ >+ c = *src++; >+ outb_p( c, iobase+4 ); >+ } >+ dma_state ^= STAT_dma_state; >+ } while ( len > 0 ); >+ return 0; >+} >+ >+unsigned int loadfile ( char *filename ) >+{ >+ int i, header_size; >+ unsigned int total_paras; >+ long fix; >+ infd = open ( filename, O_RDONLY ); >+ if ( infd == -1 ) { >+ perror ( "Opening file: " ); >+ return 0; >+ } >+ read ( infd, &header, sizeof ( struct dos_exe_header ) ); >+ if ( header.id != 0x5a4d ) { >+ fprintf ( stderr, "Invalid header file format\n" ); >+ fprintf ( stderr, "Want 0x5a4d, got 0x%x\n", header.id ); >+ return 0; >+ } >+ if ( header.relen > MAX_FIXUPS ) { >+ fprintf ( stderr, "Too many fixups\n" ); >+ return 0; >+ } >+ lseek ( infd, ( long ) header.reloc, SEEK_SET ); >+ read ( infd, fixups, sizeof ( struct dos_reloc ) * header.relen ); >+ header_size = header.hsize * 16; >+ lseek ( infd, ( long )header_size, SEEK_SET ); >+ image_len = ( ( header.pages-1 )*512 ) + ( header.rem- header_size ); >+ total_paras = ( image_len >> 4 ) + header.hmin + 16; >+ read ( infd, read_buff, image_len ); >+ close( infd ); >+ return total_paras; >+} >+ >+static int loadkernel( char *filename ) >+{ >+ int segfix = 0x40, fix, i; >+ int ipval, csval; >+ if ( has_kernel ) return 0; >+ if ( !loadfile( filename ) ) return -1; >+ header.csval += segfix; >+ header.ssval += segfix; >+ if ( verbose ) { >+ printf ( "Loading kernel of %ld bytes ( %d relocs )\n", >+ image_len, header.relen ); >+ printf ( " cs:ip == %04x:%04x ss:sp == %04x:%04x\n", >+ header.csval, header.ipval, header.ssval, header.spval ); >+ } >+ for ( i = 0; i < header.relen; i++ ) { >+ fix = ( fixups[i].segment << 4 ) + fixups[i].offset; >+ ( *( unsigned int * ) &read_buff[fix] ) += segfix; >+ } >+ csval = header.csval; >+ ipval = header.ipval; >+ dt_sendcmd_wait( MODULE_reset, MODULE_init ); >+ dt_sendcmd( CMD_reset ); >+ if( dt_getstatus( ) == MODULE_self_test ){ >+ if( ! dt_waitmode( MODULE_init ) ) return -1; >+ } >+ if ( !dt_sendcmd_wait( CMD_reset, MODE_status ) ) return -2; >+ if ( !dt_sendcmd_wait( CMD_sync, MODE_error ) ) return -3; >+ if ( !dt_sendcmd_wait( CMD_reset, MODE_status ) ) return -4; >+ if ( verbose ) printf( "card is ready\n" ); >+ dt_sendcmd( CMD_dma ); >+ if( ! dt_waitbit( STAT_dma_ready ) ) return -5; >+ if( ( i = dt_loadmem( 0x00000400, image_len, read_buff ) ) ) { >+ fprintf( stderr, "kernel load failed, status %d\n", i ); >+ return -6; >+ } >+ usleep(100); >+ /* the kernel is loaded, start it */ >+ if ( !dt_sendcmd_wait( CMD_reset, MODE_status ) ) return -7; >+ dt_sendcmd( CMD_dma+1 ); /**xxx**/ >+ usleep(100); >+ if( ! dt_waitbit( STAT_dma_ready ) ) return-8; >+ outb_p( DMA_control, iobase+4 ); >+ outb_p( DT_START_TASK, iobase+4 ); >+ usleep(100); >+ outb_p( ipval & 0xFF, iobase+4 ); >+ outb_p( (ipval>>8) & 0xFF, iobase+4 ); >+ outb_p( csval & 0xFF, iobase+4 ); >+ outb_p( (csval>>8) & 0xFF, iobase+4 ); >+ if( ! dt_waitmode( 0xc001 ) ) return -9; >+ if ( verbose ) { >+ printf( "done loading kernel\n" ); >+ } >+ return testkernel( ); >+} >+ >+int loaddict ( char *filename, char *name, int type ) >+{ >+ int i, read_index, read_size, act_size; >+ unsigned short *index_fix, seg_fix; >+ unsigned long entries, index, dic_bytes, dic_addr; >+ unsigned int total_paras; >+ unsigned long param, l; >+ infd = open ( filename, O_RDONLY ); >+ if ( infd == -1 ) { >+ perror ( filename ); >+ return -1; >+ } >+/* read in the entry count and the actual entry size excluding the >+ * index table ( which is entries * 4 ) ... */ >+ read ( infd, &entries, 4 ); >+ read ( infd, &dic_bytes, 4 ); >+ if ( verbose ) >+ printf ( "Loading %s dictionary of %lu entries, %lu bytes.\n", >+ name, entries, dic_bytes ); >+ total_paras = ( ( ( entries * 4 ) + dic_bytes ) >> 4 ) + 2; >+ if ( verbose ) >+ printf ( "Allocating %d paragraphs of free ram ...\n", total_paras ); >+ l = dt_allocmem( total_paras ); >+ if ( l == 0 ) { >+ perror ( "Error requesting memory from speech device" ); >+ return -1; >+ } >+ seg_fix = ( l >> 4 ) & 0xffff; >+ dic_addr = l; >+ index = entries; >+ index_fix = ( unsigned short * ) &read_buff[0]; >+ if ( verbose ) >+ printf ( "Index table starts at %lx\n", l ); >+ read_index = index*4; >+ act_size = read ( infd, read_buff, read_index ); >+ if ( act_size != read_index ) { >+ fprintf ( stderr, "\nError reading indexes\n" ); >+ fprintf ( stderr, " exp : %d act : %d\n", read_index * 4, act_size ); >+ return -1; >+ } >+ for ( i = 1; i < index * 2; i += 2 ) >+ index_fix[i] += seg_fix; >+ if( ( i = dt_loadmem( l, read_index, read_buff ) ) ) { >+ fprintf ( stderr, "\nError loading indexes at 0x%lX: i %d\n", >+ l, i ); >+ return -1; >+ } >+ l += read_index; >+/* now, load up the dictionary bytes ... */ >+ if ( verbose ) >+ printf ( "Dictionary text starts at %lx\n", l ); >+ read_size = dic_bytes; >+ if ( ( act_size = read ( infd, read_buff, read_size ) ) != read_size ) { >+ fprintf ( stderr, "\nError reading dictionary text!\n" ); >+ fprintf ( stderr, "asked : %d actual : %d\n", act_size, read_size ); >+ return -1; >+ } >+ if( ( i = dt_loadmem( l, read_size, read_buff ) ) ) { >+ fprintf ( stderr, "\nError loading dictionary at 0x%lX: status %d\n", >+ l, i ); >+ return -1; >+ } >+ if( ! dt_wait_dma( ) ) return -1; >+ outb_p( DMA_control, iobase+4 ); >+ outb_p( DT_SET_DIC, iobase+4 ); >+ dma_state ^= STAT_dma_state; >+ if( ! dt_wait_dma( ) ) return -1; >+ l = dic_addr; >+ l = ((l << 12) & 0xFFFF0000) + (l & 0x0000000F); >+ outb_p( l & 0xFF, iobase+4 ); >+ outb_p( (l>>8) & 0xFF, iobase+4 ); >+ outb_p( (l>>16) & 0xFF, iobase+4 ); >+ outb_p( (l>>24) & 0xFF, iobase+4 ); >+ l = entries; >+ outb_p( l & 0xFF, iobase+4 ); >+ outb_p( (l>>8) & 0xFF, iobase+4 ); >+ outb_p( (l>>16) & 0xFF, iobase+4 ); >+ outb_p( (l>>24) & 0xFF, iobase+4 ); >+ l = type; >+ outb_p( l & 0xFF, iobase+4 ); >+ outb_p( (l>>8) & 0xFF, iobase+4 ); >+ dma_state ^= STAT_dma_state; >+ close ( infd ); >+ if ( verbose ) printf( "dictionary load complete\n" ); >+ return 0; >+} >+ >+int loadexe ( char *filename ) >+{ >+ unsigned int load_addr = 0, seg_fix; >+ int i, read_size; >+ int ipval, csval; >+ long fix; >+ unsigned long total_paras; >+ total_paras = loadfile ( filename ); >+ if ( total_paras == 0 ) return -1; >+ load_addr = dt_allocmem( total_paras ); >+ if ( load_addr == 0 ) { >+ fprintf ( stderr, "Error allocating memory on card: " ); >+ return -1; >+ } >+ seg_fix = ( load_addr >> 4 ) & 0xffff; >+ if ( verbose ) { >+ printf ( "Loading %s %ld bytes ( %d relocs )\n", >+ filename, image_len, header.relen ); >+ printf ( "Allocating %ld bytes of free ram at %05x\n", >+ ( long ) header.hmin * 16, load_addr ); >+ printf ( "Total memory taken is %ld bytes\n", ( long ) total_paras * 16 ); >+ printf ( " cs:ip == %04x:%04x ss:sp == %04x:%04x\n", >+ header.csval + seg_fix, header.ipval, header.ssval + seg_fix, header.spval ); >+ } >+ for ( i = 0; i < header.relen; i++ ) { >+ fix = ( ( long ) fixups[i].segment << 4 ) + ( long ) fixups[i].offset; >+ ( *( unsigned int * ) &read_buff[fix] ) += seg_fix; >+ } >+ if( ( i = dt_loadmem( load_addr, image_len, read_buff ) ) ) { >+ fprintf ( stderr, "Error loading speech device at 0x%lX: status %d\n", >+ load_addr, i ); >+ return -1; >+ } >+ csval = header.csval + seg_fix; >+ ipval = header.ipval; >+ if( ! dt_wait_dma( ) ) return -1; >+ outb_p( DMA_control, iobase+4 ); >+ outb_p( DT_START_TASK, iobase+4 ); >+ dma_state ^= STAT_dma_state; >+ if( ! dt_wait_dma( ) ) return -1; >+ outb_p( ipval & 0xFF, iobase+4 ); >+ outb_p( (ipval>>8) & 0xFF, iobase+4 ); >+ outb_p( csval & 0xFF, iobase+4 ); >+ outb_p( (csval>>8) & 0xFF, iobase+4 ); >+ dma_state ^= STAT_dma_state; >+ return 0; >+} >+ >+void release_io( void ) >+{ >+ ioperm( (long)iobase, 8, 0 ); >+ ioperm( (long)0x0080, 1, 0 ); >+ if ( read_buff ) free( read_buff ); >+} >+ >+parseparm( char *parm, char *value ) >+{ >+ char *cp = parm+strlen( parm ); >+ while ( --cp > parm ) if ( *cp > ' ' ) break; >+ cp[1] = '\0'; >+ if ( !strcmp( parm, "io" ) ) { >+ long io = strtol( value, 0, 0 ); >+ if ( io >= 0x100 && io <= 0x350 ) { >+ iobase = (u_short)io; >+ return; >+ } >+ fprintf( stderr, "invalid io value %s\n", value ); >+ exit( 1 ); >+ } else if ( !strcmp( parm,"verbose" ) ) { >+ verbose = atoi( value ); >+ } >+} >+ >+do_test( void ) >+{ >+ char buffer[512]; >+ int len; >+ dma_state = dt_getstatus( ) & STAT_dma_state; >+ while ( fgets( buffer, 510, stdin ) ) { >+ len = strlen( buffer ); >+ if ( len == 1 ) dt_flush( ); >+ else { >+ if ( buffer[len-1] == '\n' ) buffer[len-1] = '\013'; >+ dt_sendbuff( buffer, len ); >+ } >+ } >+ *buffer = '\013'; >+ dt_sendbuff( buffer, 1 ); >+} >+ >+int main ( int argc, char **argv ) >+{ >+ char name[80], *cp; >+ char *dirname = 0, *confname = "dec_pc.conf"; >+ char *init_msg = "[:ra 360] dec pc initialized\011"; >+ FILE *confile; >+ struct stat statbuf; >+ int maxsize = 0, status = 0; >+ while ( --argc > 0 ) { >+ argv++; >+ if ( !strcmp( *argv, "-v" ) ) verbose = 1; >+ else if ( !strcmp( *argv, "-t" ) ) intest = 1; >+ else dirname = *argv; >+ } >+ if ( !dirname ) dirname = "/usr/local/lib/dec_pc"; >+ if ( chdir( dirname ) != 0 ) { >+ fprintf( stderr, "cannot chdir to %s\n", dirname ); >+ exit( 1 ); >+ } >+ if ( !( confile = fopen( confname, "r" ) ) ) { >+ fprintf( stderr, "could not open %s", confname ); >+ exit( 1 ); >+ } >+ while ( fgets( name, 80, confile ) ) { >+ cp = strchr( name, '\n' ); >+ if ( cp ) *cp = '\0'; >+ if ( ( cp = strchr( name, '=' ) ) ) { >+ *cp++ = '\0'; >+ parseparm( name, cp ); >+ continue; >+ } >+ if ( stat( name, &statbuf ) != 0 ) { >+ fprintf( stderr, "cannot stat %s\n", name ); >+ exit( 1 ); >+ } >+ if ( statbuf.st_size > maxsize ) maxsize = statbuf.st_size; >+ } >+ rewind( confile ); >+ if ( ioperm( (long)0x0080, 1, 1 ) || ioperm( (long)iobase, 8, 1 ) ) { >+ fprintf( stderr, "could not get ioperm\n" ); >+ exit( 1 ); >+ } >+ atexit( release_io ); >+ if ( testkernel( ) == 0 ) { >+ if ( intest ) do_test( ); >+ else fprintf( stderr, "kernel already loaded\n" ); >+ exit( 0 ); >+ } >+ read_buff = malloc( maxsize ); >+ if ( !read_buff ) { >+ fprintf( stderr, "cannot malloc %d bytes\n", maxsize ); >+ exit( 1 ); >+ } >+ while ( fgets( name, 80, confile ) && !status ) { >+ cp = strchr( name, '\n' ); >+ if ( cp ) *cp = '\0'; >+ if ( strchr( name, '=' ) ) continue; /* a parameter */ >+ if ( !( cp = strchr( name, '.' ) ) ) continue; >+ cp++; >+ if ( !strcmp ( cp, "dic" ) ) { >+ status = loaddict ( name, "primary", PRIMARY_DIC ); >+ } else if ( !strcmp ( cp, "dtu" ) ) { >+ status = loaddict ( name, "user", USER_DIC ); >+ } else if ( !strcmp ( cp, "dta" ) ) { >+ status = loaddict ( name, "abbreviation file", ABBREV_DIC ); >+ } else if ( !strcmp ( cp, "exe" ) ) { >+ status = loadexe ( name ); >+ } else if ( !strcmp ( cp, "sys" ) ) { >+ status = loadkernel ( name ); >+ } >+ } >+ if ( status ) fprintf( stderr, "status %d\n", status ); >+ fclose( confile ); >+ if ( status ) exit( status ); >+ dt_sendbuff( init_msg, strlen( init_msg ) ); >+ sleep( 1 ); >+ if ( intest ) do_test( ); >+ exit( 0 ); >+} >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 >--- linux-2.6.20/drivers/char/speakup/dtload.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/dtload.h 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,57 @@ >+/* >+ * This is the DECtalk PC firmware loader for the Linux kernel, version 1.0 >+ * >+ * Original 386BSD source: >+ * Copyright (c) 1996 Brian Buhrow <buhrow@lothlorien.nfbcal.org> >+ * >+ * Adapted for Linux: >+ * Copyright (c) 1997 Nicolas Pitre <nico@cam.org> >+ * >+ * Adapted for speakup: >+ * Copyright (c) 2003 David Borowski <david575@golden.net> >+ * >+ * All rights reserved. >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 2 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, write to the Free Software >+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+ * >+ */ >+ >+#define MAX_FIXUPS 512 /* maximum fixups per exe */ >+/* >+ * msdos .exe files will look like ... >+ */ >+ >+struct dos_exe_header { >+ unsigned short id; /* Linker's signature, must be 0x5a4d */ >+ unsigned short rem; /* length of image mod 512 */ >+ unsigned short pages; /* length of image in pages of 512 bytes */ >+ unsigned short relen; /* number of relocation items */ >+ unsigned short hsize; /* header size in paragraphs of 16 bytes */ >+ unsigned short hmin; /* min # of paragraphs above prog end */ >+ unsigned short hmax; >+ unsigned short ssval; >+ unsigned short spval; /* to be loaded in sp */ >+ unsigned short checksum; >+ unsigned short ipval; /* to be loaded in ip */ >+ unsigned short csval; /* segment offset to code */ >+ unsigned short reloc; /* location of relocation items */ >+ unsigned short ovrlay; /* overlay number */ >+}; >+ >+/* a dos relocation element looks like */ >+ >+struct dos_reloc { >+ short int offset, segment; >+}; >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 >--- linux-2.6.20/drivers/char/speakup/dtpc_reg.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/dtpc_reg.h 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,132 @@ >+/* >+ * This is the DECtalk PC register constants (from DEC's DOS driver) >+ * >+ * Original code: >+ * Copyright (c) by Digital Equipment Corp. >+ * >+ * 386BSD DECtalk PC driver: >+ * Copyright (c) 1996 Brian Buhrow <buhrow@lothlorien.nfbcal.org> >+ * >+ * Linux DECtalk PC driver: >+ * Copyright (c) 1997 Nicolas Pitre <nico@cam.org> >+ * >+ * speakup DECtalk PC driver: >+ * Copyright (c) 2003 David Borowski <david575@golden.net> >+ * >+ * All rights reserved. >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 2 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, write to the Free Software >+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+ * >+ */ >+ >+/* >+ * port interface defs ... used by dtpc.c >+ */ >+ >+#define MODULE_init 0x0dec /* module in boot code */ >+#define MODULE_self_test 0x8800 /* module in self-test */ >+#define MODULE_reset 0xffff /* reinit the whole module */ >+ >+#define MODE_mask 0xf000 /* mode bits in high nibble */ >+#define MODE_null 0x0000 >+#define MODE_test 0x2000 /* in testing mode */ >+#define MODE_status 0x8000 >+#define STAT_int 0x0001 /* running in interrupt mode */ >+#define STAT_tr_char 0x0002 /* character data to transmit */ >+#define STAT_rr_char 0x0004 /* ready to receive char data */ >+#define STAT_cmd_ready 0x0008 /* ready to accept commands */ >+#define STAT_dma_ready 0x0010 /* dma command ready */ >+#define STAT_digitized 0x0020 /* spc in digitized mode */ >+#define STAT_new_index 0x0040 /* new last index ready */ >+#define STAT_new_status 0x0080 /* new status posted */ >+#define STAT_dma_state 0x0100 /* dma state toggle */ >+#define STAT_index_valid 0x0200 /* indexs are valid */ >+#define STAT_flushing 0x0400 /* flush in progress */ >+#define STAT_self_test 0x0800 /* module in self test */ >+#define MODE_ready 0xc000 /* module ready for next phase */ >+#define READY_boot 0x0000 >+#define READY_kernel 0x0001 >+#define MODE_error 0xf000 >+ >+#define CMD_mask 0xf000 /* mask for command nibble */ >+#define CMD_null 0x0000 /* post status */ >+#define CMD_control 0x1000 /* hard control command */ >+#define CTRL_mask 0x0F00 /* mask off control nibble */ >+#define CTRL_data 0x00FF /* madk to get data byte */ >+#define CTRL_null 0x0000 /* null control */ >+#define CTRL_vol_up 0x0100 /* increase volume */ >+#define CTRL_vol_down 0x0200 /* decrease volume */ >+#define CTRL_vol_set 0x0300 /* set volume */ >+#define CTRL_pause 0x0400 /* pause spc */ >+#define CTRL_resume 0x0500 /* resume spc clock */ >+#define CTRL_resume_spc 0x0001 /* resume spc soft pause */ >+#define CTRL_flush 0x0600 /* flush all buffers */ >+#define CTRL_int_enable 0x0700 /* enable status change ints */ >+#define CTRL_buff_free 0x0800 /* buffer remain count */ >+#define CTRL_buff_used 0x0900 /* buffer in use */ >+#define CTRL_speech 0x0a00 /* immediate speech change */ >+#define CTRL_SP_voice 0x0001 /* voice change */ >+#define CTRL_SP_rate 0x0002 /* rate change */ >+#define CTRL_SP_comma 0x0003 /* comma pause change */ >+#define CTRL_SP_period 0x0004 /* period pause change */ >+#define CTRL_SP_rate_delta 0x0005 /* delta rate change */ >+#define CTRL_SP_get_param 0x0006 /* return the desired parameter */ >+#define CTRL_last_index 0x0b00 /* get last index spoken */ >+#define CTRL_io_priority 0x0c00 /* change i/o priority */ >+#define CTRL_free_mem 0x0d00 /* get free paragraphs on module */ >+#define CTRL_get_lang 0x0e00 /* return bit mask of loaded languages */ >+#define CMD_test 0x2000 /* self-test request */ >+#define TEST_mask 0x0F00 /* isolate test field */ >+#define TEST_null 0x0000 /* no test requested */ >+#define TEST_isa_int 0x0100 /* assert isa irq */ >+#define TEST_echo 0x0200 /* make data in == data out */ >+#define TEST_seg 0x0300 /* set peek/poke segment */ >+#define TEST_off 0x0400 /* set peek/poke offset */ >+#define TEST_peek 0x0500 /* data out == *peek */ >+#define TEST_poke 0x0600 /* *peek == data in */ >+#define TEST_sub_code 0x00FF /* user defined test sub codes */ >+#define CMD_id 0x3000 /* return software id */ >+#define ID_null 0x0000 /* null id */ >+#define ID_kernel 0x0100 /* kernel code executing */ >+#define ID_boot 0x0200 /* boot code executing */ >+#define CMD_dma 0x4000 /* force a dma start */ >+#define CMD_reset 0x5000 /* reset module status */ >+#define CMD_sync 0x6000 /* kernel sync command */ >+#define CMD_char_in 0x7000 /* single character send */ >+#define CMD_char_out 0x8000 /* single character get */ >+#define CHAR_count_1 0x0100 /* one char in cmd_low */ >+#define CHAR_count_2 0x0200 /* the second in data_low */ >+#define CHAR_count_3 0x0300 /* the third in data_high */ >+#define CMD_spc_mode 0x9000 /* change spc mode */ >+#define CMD_spc_to_text 0x0100 /* set to text mode */ >+#define CMD_spc_to_digit 0x0200 /* set to digital mode */ >+#define CMD_spc_rate 0x0400 /* change spc data rate */ >+#define CMD_error 0xf000 /* severe error */ >+ >+enum { PRIMARY_DIC = 0, USER_DIC, COMMAND_DIC, ABBREV_DIC }; >+ >+#define DMA_single_in 0x01 >+#define DMA_single_out 0x02 >+#define DMA_buff_in 0x03 >+#define DMA_buff_out 0x04 >+#define DMA_control 0x05 >+#define DT_MEM_ALLOC 0x03 >+#define DT_SET_DIC 0x04 >+#define DT_START_TASK 0x05 >+#define DT_LOAD_MEM 0x06 >+#define DT_READ_MEM 0x07 >+#define DT_DIGITAL_IN 0x08 >+#define DMA_sync 0x06 >+#define DMA_sync_char 0x07 >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 >--- linux-2.6.20/drivers/char/speakup/genmap.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/genmap.c 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,204 @@ >+#include <stdlib.h> >+#include <stdio.h> >+#include <libgen.h> >+#include <string.h> >+#include <linux/version.h> >+#include <ctype.h> >+ >+int get_define(void); >+ >+#define MAXKEYS 512 >+#define MAXKEYVAL 160 >+#define HASHSIZE 101 >+#define is_shift -3 >+#define is_spk -2 >+#define is_input -1 >+typedef struct st_key_init t_key_init; >+struct st_key_init { >+ char *name; >+ int value, shift; >+}; >+typedef struct st_key t_key; >+struct st_key { >+ char *name; >+ t_key *next; >+ int value, shift; >+}; >+unsigned char key_data[MAXKEYVAL][16], *kp; >+ >+#include "mapdata.h" >+t_key key_table[MAXKEYS]; >+t_key *extra_keys = key_table+HASHSIZE; >+char buffer[256], filename[256]; >+FILE *infile; >+char delims[] = "\t\n "; >+char *def_name, *def_val, *cp; >+int map_ver = 119; /* an arbitrary number so speakup can check */ >+int lc, shift_table[17]; >+int max_states = 1, flags = 0; >+/* flags reserved for later, maybe for individual console maps */ >+ >+void open_input( char *name ) >+{ >+ strcpy( filename, name ); >+ if ( ( infile = fopen( filename, "r" ) ) == 0 ) { >+ fprintf( stderr, "can't open %s, version %d\n", filename, LINUX_VERSION_CODE ); >+ exit( 1 ); >+ } >+ lc = 0; >+} >+ >+int >+oops( char *msg, char *info ) >+{ >+ if ( info == NULL ) info = " "; >+ fprintf( stderr, "error: file %s line %d\n", filename, lc ); >+ fprintf( stderr, "%s %s\n", msg, info ); >+ exit( 1 ); >+} >+ >+t_key *hash_name( char *name ) >+{ >+ u_char *pn = (u_char *)name; >+ int hash = 0; >+ while ( *pn ) { >+ hash = ( hash * 17 ) & 0xfffffff; >+ if ( isupper( *pn ) ) *pn = tolower( *pn ); >+ hash += ( int )*pn; >+ pn++; >+ } >+ hash %= HASHSIZE; >+ return &key_table[hash]; >+} >+ >+t_key *find_key( char *name ) >+{ >+ t_key *this = hash_name( name ); >+ while ( this ) { >+ if ( !strcmp( name, this->name ) ) return this; >+ this = this->next; >+ } >+ return this; >+} >+ >+t_key *add_key( char *name, int value, int shift ) >+{ >+ t_key *this = hash_name( name ); >+ if ( extra_keys-key_table >= MAXKEYS ) >+ oops( "out of key table space, enlarge MAXKEYS", NULL ); >+ if ( this->name != NULL ) { >+ while ( this->next ) { >+ if ( !strcmp( name, this->name ) ) >+ oops( "attempt to add duplicate key", name ); >+ this = this->next; >+ } >+ this->next = extra_keys++; >+ this = this->next; >+ } >+ this->name = strdup( name ); >+ this->value = value; >+ this->shift = shift; >+ return this; >+} >+ >+int get_shift_value( int state ) >+{ >+ int i; >+ for ( i = 0; shift_table[i] != state; i++ ) { >+ if ( shift_table[i] == -1 ) { >+ if ( i >= 16 ) >+ oops( "too many shift states", NULL ); >+ shift_table[i] = state; >+ max_states = i+1; >+ break; >+ } >+ } >+ return i; >+} >+ >+int >+main( int argc, char *argv[] ) >+{ >+ int value, shift_state, i, spk_val = 0, lock_val = 0; >+ int max_key_used = 0, num_keys_used = 0; >+ t_key *this; >+ t_key_init *p_init; >+char *argpath, *argname, *argcopy; >+ >+ bzero( key_table, sizeof( key_table ) ); >+ bzero( key_data, sizeof( key_data ) ); >+ shift_table[0] = 0; >+ for ( i = 1; i <= 16; i++ ) shift_table[i] = -1; >+ if ( argc < 2 ) { >+ fputs( "usage: genmap filename\n", stderr ); >+ exit( 1 ); >+ } >+ for ( p_init = init_key_data; p_init->name[0] != '.'; p_init++ ) >+ add_key( p_init->name, p_init->value, p_init->shift ); >+ open_input( argv[1] ); >+ while ( fgets( buffer, 250, infile ) ) { >+ lc++; >+ value = shift_state = 0; >+ cp = strtok( buffer, delims ); >+ if ( *cp == '#' ) continue; >+ while ( cp ) { >+ if ( *cp == '=' ) break; >+ this = find_key( cp ); >+ if ( this == NULL ) >+ oops( "unknown key/modifier", cp ); >+ if ( this->shift == is_shift ) { >+ if ( value ) >+ oops( "modifiers must come first", cp ); >+ shift_state += this->value; >+ } else if ( this->shift == is_input ) >+ value = this->value; >+ else oops( "bad modifier or key", cp ); >+ cp = strtok( 0, delims ); >+ } >+ if ( !cp ) oops( "no = found", NULL ); >+ cp = strtok( 0, delims ); >+ if ( !cp ) oops( "no speakup function after =", NULL ); >+ this = find_key( cp ); >+ if ( this == NULL || this->shift != is_spk ) >+ oops( "invalid speakup function", cp ); >+ i = get_shift_value( shift_state ); >+ if ( key_data[value][i] ) { >+ while ( --cp > buffer ) >+ if ( !*cp ) *cp = ' '; >+ oops( "two functions on same key combination", cp ); >+ } >+ key_data[value][i] = (char)this->value; >+ if ( value > max_key_used ) max_key_used = value; >+ } >+ fclose( infile ); >+ this = find_key( "spk_key" ); >+ if ( this ) spk_val = this->value; >+ this = find_key( "spk_lock" ); >+ if ( this ) lock_val = this->value; >+ for ( lc = 1; lc <= max_key_used; lc++ ) { >+ kp = key_data[lc]; >+ if ( !memcmp( key_data[0], kp, 16 ) ) continue; >+ num_keys_used++; >+ for ( i = 0; i < max_states; i++ ) { >+ if ( kp[i] != spk_val&& kp[i] != lock_val ) continue; >+ shift_state = shift_table[i]; >+ if ( ( shift_state&16 ) ) continue; >+ shift_state = get_shift_value( shift_state+16 ); >+ kp[shift_state] = kp[i]; >+/* fill in so we can process the key up, as spk bit will be set */ >+ } >+ } >+ printf( "\t%d, %d, %d,\n\t", map_ver, num_keys_used, max_states ); >+ for ( i = 0; i < max_states; i++ ) >+ printf( "%d, ", shift_table[i] ); >+ printf( "%d,", flags ); >+ for ( lc = 1; lc <= max_key_used; lc++ ) { >+ kp = key_data[lc]; >+ if ( !memcmp( key_data[0], kp, 16 ) ) continue; >+ printf( "\n\t%d,", lc ); >+ for ( i = 0; i < max_states; i++ ) >+ printf( " %d,", (unsigned int)kp[i] ); >+ } >+ printf( "\n\t0, %d\n", map_ver ); >+ exit( 0 ); >+} >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/Kconfig linux-2.6.20-spk/drivers/char/speakup/Kconfig >--- linux-2.6.20/drivers/char/speakup/Kconfig 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/Kconfig 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,211 @@ >+menu "Speakup console speech" >+config SPEAKUP >+ tristate "Build speakup console speech" >+ ---help--- >+ >+ This is the Speakup screen reader. Think of it as a >+ video console for blind people. If built in to the >+ kernel, it can speak evrything on the text console from >+ boot up to shutdown. For more information on Speakup, >+ point your browser at http://www.linux-speakup.org/. >+ There is also a mailing list at the above url that you >+ can subscribe to. >+ >+ Supported synthesizers are accent sa, accent pc, appollo >+ II., Auddapter, Braille 'n Speak, Dectalk external >+ (old), Dectalk PC (full length isa board), Dectalk >+ express, Doubletalk, Doubletalk LT or Litetalk, >+ Keynote >+ Gold internal PC, software synthesizers, Speakout, and transport. >+ >+ Speakup can either be built in or compiled as a module >+ by answering y or m. If you answer y here, then you >+ must answer either y or m to at least one of the >+ synthesizer drivers below. If you answer m here, then >+ the synthesizer drivers below can only be built as >+ modules. >+ >+ These drivers are not standalone drivers, but must be >+ used in conjunction with Speakup. Think of them as >+ video cards for blind people. >+ >+ >+ The Dectalk pc driver can only be built as a module, and >+ requires software to be pre-loaded on to the card before >+ the module can be loaded. See the decpc choice below >+ for more details. >+ >+ If you are not a blind person, or don't have access to >+ one of the listed synthesizers, you should say n. >+ >+config SPEAKUP_ACNTSA >+ depends on SPEAKUP >+ tristate "Accent SA, acntsa" >+ ---help--- >+ >+ This is the Speakup driver for the accent sa >+ synthesizer. You can say y to build it into the kernel, >+ or m to build it as a module. See the configuration >+ help on the Speakup choice above for more info. >+ >+config SPEAKUP_ACNTPC >+ depends on SPEAKUP >+ tristate "Accent PC, acntpc" >+ ---help--- >+ >+ This is the Speakup driver for the accent pc >+ synthesizer. You can say y to build it into the kernel, >+ or m to build it as a module. See the configuration >+ help on the Speakup choice above for more info. >+ >+config SPEAKUP_APOLLO >+ depends on SPEAKUP >+ tristate "Apollo, apollo" >+ ---help--- >+ >+ This is the Speakup driver for the Apollo II >+ synthesizer. You can say y to build it into the kernel, >+ or m to build it as a module. See the configuration >+ help on the Speakup choice above for more info. >+ >+config SPEAKUP_AUDPTR >+ depends on SPEAKUP >+ tristate "Audapter, audptr" >+ ---help--- >+ >+ This is the Speakup driver for the Audapter synthesizer. >+ You can say y to build it into the kernel, or m to >+ build it as a module. See the configuration help on the >+ Speakup choice above for more info. >+ >+config SPEAKUP_BNS >+ depends on SPEAKUP >+ tristate "Braille 'n' Speak, bns" >+ ---help--- >+ >+ This is the Speakup driver for the Braille 'n' Speak >+ synthesizer. You can say y to build it into the kernel, >+ or m to build it as a module. See the configuration >+ help on the Speakup choice above for more info. >+ >+config SPEAKUP_DECTLK >+ depends on SPEAKUP >+ tristate "DECtalk Express, dectlk" >+ ---help--- >+ >+ This is the Speakup driver for the DecTalk Express >+ synthesizer. You can say y to build it into the kernel, >+ or m to build it as a module. See the configuration >+ help on the Speakup choice above for more info. >+ >+config SPEAKUP_DECEXT >+ depends on SPEAKUP >+ tristate "DECtalk External (old), decext" >+ ---help--- >+ >+ This is the Speakup driver for the DecTalk External >+ (old) synthesizer. You can say y to build it into the >+ kernel, or m to build it as a module. See the >+ configuration help on the Speakup choice above for more >+ info. >+ >+config SPEAKUP_DECPC >+ depends on SPEAKUP >+ tristate "DECtalk PC (big ISA card), decpc" >+ ---help--- >+ >+ This is the Speakup driver for the DecTalk PC (full >+ length ISA) synthesizer. You can say m to build it as >+ a module. See the configuration help on the Speakup >+ choice above for more info. >+ >+ In order to use the DecTalk PC driver, you must download >+ the dec_pc.tgz file from linux-speakup.org. It is in >+ the pub/linux/goodies directory. The dec_pc.tgz file >+ contains the software which must be pre-loaded on to the >+ DecTalk PC board in order to use it with this driver. >+ This driver must be built as a module, and can not be >+ loaded until the file system is mounted and the DecTalk >+ PC software has been pre-loaded on to the board. >+ >+ See the README file in the dec_pc.tgz file for more >+ details. >+ >+config SPEAKUP_DTLK >+ depends on SPEAKUP >+ tristate "DoubleTalk PC, dtlk" >+ ---help--- >+ >+ This is the Speakup driver for the internal DoubleTalk >+ PC synthesizer. You can say y to build it into the >+ kernel, or m to build it as a module. See the >+ configuration help on the Speakup choice above for more >+ info. >+ >+config SPEAKUP_KEYPC >+ depends on SPEAKUP >+ tristate "Keynote Gold PC, keypc" >+ ---help--- >+ >+ This is the Speakup driver for the Keynote Gold >+ PC synthesizer. You can say y to build it into the >+ kernel, or m to build it as a module. See the >+ configuration help on the Speakup choice above for more >+ info. >+ >+config SPEAKUP_LTLK >+ depends on SPEAKUP >+ tristate "DoubleTalk LT or LiteTalk, ltlk" >+---help--- >+ >+ This is the Speakup driver for the LiteTalk/DoubleTalk >+ LT synthesizer. You can say y to build it into the >+ kernel, or m to build it as a module. See the >+ configuration help on the Speakup choice above for more >+ info. >+ >+config SPEAKUP_SFTSYN >+ depends on SPEAKUP >+ tristate "Software synthesizers, sftsyn" >+---help--- >+ >+ This is the software synthesizer device node. It will >+ register a device /dev/sftsyn which midware programs >+ and speech >+ daemons may open and read to provide kernel output to >+ software synths >+ such as festival, flite, tuxtalk and so forth. You >+ can select 'y' or >+ 'm' to have it built-in to the kernel or loaded as a module. >+ >+config SPEAKUP_SPKOUT >+ depends on SPEAKUP >+ tristate "Speak Out, spkout" >+ ---help--- >+ >+ This is the Speakup driver for the Speakout synthesizer. >+ You can say y to build it into the kernel, or m to >+ build it as a module. See the configuration help on the >+ Speakup choice above for more info. >+ >+config SPEAKUP_TXPRT >+ depends on SPEAKUP >+ tristate "Transport, txprt" >+ ---help--- >+ >+ This is the Speakup driver for the Transport >+ synthesizer. You can say y to build it into the kernel, >+ or m to build it as a module. See the configuration >+ help on the Speakup choice above for more info. >+ >+if SPEAKUP != n >+comment 'Enter the 3 to 6 character keyword from the list above, or none for no default synthesizer on boot up.' >+ depends on SPEAKUP >+endif >+ >+config SPEAKUP_DEFAULT >+ string "Choose Default synthesizer for Speakup" >+ depends on SPEAKUP >+ default "none" >+ >+endmenu >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 >--- linux-2.6.20/drivers/char/speakup/keyinfo.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/keyinfo.h 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,120 @@ >+/* spk_priv.h >+ review functions for the speakup screen review package. >+ originally written by: Kirk Reiser and Andy Berdan. >+ >+ extensively modified by David Borowski. >+ >+ Copyright (C ) 1998 Kirk Reiser. >+ Copyright (C ) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option ) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+*/ >+ >+enum { /* var_ids */ >+ VERSION = 0, SYNTH, SILENT, SYNTH_DIRECT, >+ KEYMAP, CHARS, >+ PUNC_SOME, PUNC_MOST, PUNC_ALL, >+ DELIM, REPEATS, EXNUMBER, >+ DELAY, TRIGGER, JIFFY, FULL, /* all timers must be together */ >+ BLEEP_TIME, CURSOR_TIME, BELL_POS, >+SAY_CONTROL, SAY_WORD_CTL, NO_INTERRUPT, KEY_ECHO, >+ SPELL_DELAY, PUNC_LEVEL, READING_PUNC, >+ ATTRIB_BLEEP, BLEEPS, >+ RATE, PITCH, VOL, TONE, PUNCT, VOICE, FREQ, LANG, >+ CAPS_START, CAPS_STOP, CHARTAB, >+ MAXVARS >+}; >+ >+#define FIRST_SYNTH_VAR RATE >+/* 0 is reserved for no remap */ >+#define SPEAKUP_GOTO 0x01 >+#define SPEECH_KILL 0x02 >+#define SPEAKUP_QUIET 0x03 >+#define SPEAKUP_CUT 0x04 >+#define SPEAKUP_PASTE 0x05 >+#define SAY_FIRST_CHAR 0x06 >+#define SAY_LAST_CHAR 0x07 >+#define SAY_CHAR 0x08 >+#define SAY_PREV_CHAR 0x09 >+#define SAY_NEXT_CHAR 0x0a >+#define SAY_WORD 0x0b >+#define SAY_PREV_WORD 0x0c >+#define SAY_NEXT_WORD 0x0d >+#define SAY_LINE 0x0e >+#define SAY_PREV_LINE 0x0f >+#define SAY_NEXT_LINE 0x10 >+#define TOP_EDGE 0x11 >+#define BOTTOM_EDGE 0x12 >+#define LEFT_EDGE 0x13 >+#define RIGHT_EDGE 0x14 >+#define SPELL_PHONETIC 0x15 >+#define SPELL_WORD 0x16 >+#define SAY_SCREEN 0x17 >+#define SAY_POSITION 0x18 >+#define SAY_ATTRIBUTES 0x19 >+#define SPEAKUP_OFF 0x1a >+#define SPEAKUP_PARKED 0x1b >+#define SAY_LINE_INDENT 0x1c >+#define SAY_FROM_TOP 0x1d >+#define SAY_TO_BOTTOM 0x1e >+#define SAY_FROM_LEFT 0x1f >+#define SAY_TO_RIGHT 0x20 >+#define SAY_CHAR_NUM 0x21 >+#define EDIT_SOME 0x22 >+#define EDIT_MOST 0x23 >+#define SAY_PHONETIC_CHAR 0x24 >+#define EDIT_DELIM 0x25 >+#define EDIT_REPEAT 0x26 >+#define EDIT_EXNUM 0x27 >+#define SET_WIN 0x28 >+#define CLEAR_WIN 0x29 >+#define ENABLE_WIN 0x2a >+#define SAY_WIN 0x2b >+#define SPK_LOCK 0x2c >+#define SPEAKUP_HELP 0x2d >+#define TOGGLE_CURSORING 0x2e >+#define READ_ALL_DOC 0x2f >+#define SPKUP_MAX_FUNC 0x30 /* one greater than the last func handler */ >+ >+#define SPK_KEY 0x80 >+#define FIRST_EDIT_BITS 0x22 >+ >+#define FIRST_SET_VAR SPELL_DELAY >+#define VAR_START 0x40 /* increase if adding more than 0x3f functions */ >+ >+/* keys for setting variables, must be ordered same as the enum for var_ids */ >+/* with dec being even and inc being 1 greater */ >+#define SPELL_DELAY_DEC VAR_START+0 >+#define SPELL_DELAY_INC SPELL_DELAY_DEC+1 >+#define PUNC_LEVEL_DEC SPELL_DELAY_DEC+2 >+#define PUNC_LEVEL_INC PUNC_LEVEL_DEC+1 >+#define READING_PUNC_DEC PUNC_LEVEL_DEC+2 >+#define READING_PUNC_INC READING_PUNC_DEC+1 >+#define ATTRIB_BLEEP_DEC READING_PUNC_DEC+2 >+#define ATTRIB_BLEEP_INC ATTRIB_BLEEP_DEC+1 >+#define BLEEPS_DEC ATTRIB_BLEEP_DEC+2 >+#define BLEEPS_INC BLEEPS_DEC+1 >+#define RATE_DEC BLEEPS_DEC+2 >+#define RATE_INC RATE_DEC+1 >+#define PITCH_DEC RATE_DEC+2 >+#define PITCH_INC PITCH_DEC+1 >+#define VOL_DEC PITCH_DEC+2 >+#define VOL_INC VOL_DEC+1 >+#define TONE_DEC VOL_DEC+2 >+#define TONE_INC TONE_DEC+1 >+#define PUNCT_DEC TONE_DEC+2 >+#define PUNCT_INC PUNCT_DEC+1 >+#define VOICE_DEC PUNCT_DEC+2 >+#define VOICE_INC VOICE_DEC+1 >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/Makefile linux-2.6.20-spk/drivers/char/speakup/Makefile >--- linux-2.6.20/drivers/char/speakup/Makefile 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/Makefile 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,61 @@ >+# >+# Makefile for the speakup speech output system. >+# >+ >+V := $(shell awk '/UTS_RELEASE/ {print substr($$3,2,3)}' $(TOPDIR)/include/linux/version.h) >+ifeq ($V,2.4) >+# Note! Dependencies are done automagically by 'make dep', which also >+# removes any old dependencies. DON'T put your own dependencies here >+# unless it's something special (ie not a .c file). >+# >+# Note 2! The CFLAGS definitions are now inherited from the >+# parent makes.. >+# >+O_TARGET := spk.o >+export-objs := speakup_drvcommon.o speakup.o >+endif >+obj-m = speakup_keyhelp.o >+speakupmain-objs := speakup.o speakup_drvcommon.o >+obj-$(CONFIG_SPEAKUP) += speakupmain.o >+obj-$(CONFIG_SPEAKUP_ACNTPC) += speakup_acntpc.o >+obj-$(CONFIG_SPEAKUP_ACNTSA) += speakup_acntsa.o >+obj-$(CONFIG_SPEAKUP_APOLLO) += speakup_apollo.o >+obj-$(CONFIG_SPEAKUP_AUDPTR) += speakup_audptr.o >+obj-$(CONFIG_SPEAKUP_BNS) += speakup_bns.o >+obj-$(CONFIG_SPEAKUP_DECEXT) += speakup_decext.o >+obj-$(CONFIG_SPEAKUP_DECPC) += speakup_decpc.o >+obj-$(CONFIG_SPEAKUP_DECTLK) += speakup_dectlk.o >+obj-$(CONFIG_SPEAKUP_DTLK) += speakup_dtlk.o >+obj-$(CONFIG_SPEAKUP_KEYPC) += speakup_keypc.o >+obj-$(CONFIG_SPEAKUP_LTLK) += speakup_ltlk.o >+obj-$(CONFIG_SPEAKUP_SFTSYN) += speakup_sftsyn.o >+obj-$(CONFIG_SPEAKUP_SPKOUT) += speakup_spkout.o >+obj-$(CONFIG_SPEAKUP_TXPRT) += speakup_txprt.o >+ >+ifeq ($V,2.4) >+ include $(TOPDIR)/Rules.make >+ >+speakupmap.h: speakupmap.map genmap >+ ./genmap speakupmap.map >$@ >+ >+genmap: genmap.c mapdata.h >+ cc -o genmap genmap.c >+ >+mapdata.h: makemapdata.c keyinfo.h >+ cc -o makemapdata makemapdata.c >+ ./makemapdata >mapdata.h >+ >+endif >+speakupmain.o:speakup.o speakup_drvcommon.o >+ ld -r -o speakupmain.o speakup.o speakup_drvcommon.o >+ >+$(obj)/speakupmap.h: $(src)/speakupmap.map $(src)/genmap >+ $(src)/genmap $(src)/speakupmap.map >$@ >+ >+$(obj)/mapdata.h: $(src)/keyinfo.h $(src)/makemapdata >+ $(src)/makemapdata >$@ >+ >+$(obj)/genmap: $(obj)/mapdata.h >+ >+HOSTCFLAGS := -Iinclude -I/usr/include >+hostprogs-y := makemapdata genmap >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 >--- linux-2.6.20/drivers/char/speakup/makemapdata.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/makemapdata.c 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,156 @@ >+#include <stdlib.h> >+#include <stdio.h> >+#include <libgen.h> >+#include <string.h> >+#include <linux/version.h> >+#include <ctype.h> >+ >+int get_define(void); >+ >+#define MAXKEYS 512 >+#define MAXKEYVAL 160 >+#define HASHSIZE 101 >+#define is_shift -3 >+#define is_spk -2 >+#define is_input -1 >+typedef struct st_key t_key; >+struct st_key { >+ char *name; >+ t_key *next; >+ int value, shift; >+}; >+ >+t_key key_table[MAXKEYS]; >+t_key *extra_keys = key_table+HASHSIZE; >+char buffer[256], filename[256]; >+FILE *infile; >+char delims[] = "\t\n "; >+char *dir_name, *def_name, *def_val, *cp; >+int lc; >+ >+void open_input( char *name ) >+{ >+ sprintf( filename, "%s/%s", dir_name, name ); >+ if ( ( infile = fopen( filename, "r" ) ) == 0 ) { >+ fprintf( stderr, "can't open %s\n", filename ); >+ exit( 1 ); >+ } >+ lc = 0; >+} >+ >+int >+oops( char *msg, char *info ) >+{ >+ if ( info == NULL ) info = " "; >+ fprintf( stderr, "error: file %s line %d\n", filename, lc ); >+ fprintf( stderr, "%s %s\n", msg, info ); >+ exit( 1 ); >+} >+ >+int get_define( ) >+{ >+ while ( fgets( buffer, 250, infile ) ) { >+ lc++; >+ if ( strncmp( buffer, "#define", 7 ) ) continue; >+ strtok( buffer, delims ); >+ def_name = strtok( 0, delims ); >+ def_val = strtok( 0, delims ); >+ if ( def_val != NULL ) return 1; >+ } >+ fclose( infile ); >+ infile = 0; >+ return 0; >+} >+ >+t_key *hash_name( char *name ) >+{ >+ u_char *pn = (u_char *)name; >+ int hash = 0; >+ while ( *pn ) { >+ hash = ( hash * 17 ) & 0xfffffff; >+ if ( isupper( *pn ) ) *pn = tolower( *pn ); >+ hash += ( int )*pn; >+ pn++; >+ } >+ hash %= HASHSIZE; >+ return &key_table[hash]; >+} >+ >+t_key *find_key( char *name ) >+{ >+ t_key *this = hash_name( name ); >+ while ( this ) { >+ if ( !strcmp( name, this->name ) ) return this; >+ this = this->next; >+ } >+ return this; >+} >+ >+t_key *add_key( char *name, int value, int shift ) >+{ >+ t_key *this = hash_name( name ); >+ if ( extra_keys-key_table >= MAXKEYS ) >+ oops( "out of key table space, enlarge MAXKEYS", NULL ); >+ if ( this->name != NULL ) { >+ while ( this->next ) { >+ if ( !strcmp( name, this->name ) ) >+ oops( "attempt to add duplicate key", name ); >+ this = this->next; >+ } >+ this->next = extra_keys++; >+ this = this->next; >+ } >+ this->name = strdup( name ); >+ this->value = value; >+ this->shift = shift; >+ return this; >+} >+ >+int >+main( int argc, char *argv[] ) >+{ >+ int value, i; >+ t_key *this; >+ dir_name = getenv( "TOPDIR" ); >+ if ( !dir_name ) dir_name = "/usr/src/linux"; >+ bzero( key_table, sizeof( key_table ) ); >+ add_key( "shift", 1, is_shift ); >+ add_key( "altgr", 2, is_shift ); >+ add_key( "ctrl", 4, is_shift ); >+ add_key( "alt", 8, is_shift ); >+ add_key( "spk", 16, is_shift ); >+ add_key( "double", 32, is_shift ); >+ open_input( "include/linux/input.h" ); >+ while ( get_define( ) ) { >+ if ( strncmp( def_name, "KEY_", 4 ) ) continue; >+ value = atoi( def_val ); >+ if ( value > 0 && value < MAXKEYVAL ) >+ add_key( def_name, value, is_input ); >+ } >+ open_input( "drivers/char/speakup/keyinfo.h" ); >+ while ( get_define( ) ) { >+ if ( strlen( def_val ) > 5 ) { >+ if ( !( cp = strchr( def_val, '+' ) ) ) continue; >+ *cp++ = '\0'; >+ this = find_key( def_val ); >+ if ( !this || *cp < '0' || *cp > '9' ) continue; >+ value = this->value+atoi( cp ); >+ } else if ( !strncmp( def_val, "0x", 2 ) ) >+ sscanf( def_val+2, "%x", &value ); >+ else if ( *def_val >= '0' && *def_val <= '9' ) >+ value = atoi( def_val ); >+ else continue; >+ add_key( def_name, value, is_spk ); >+ } >+ printf( "t_key_init init_key_data[] = {\n" ); >+ for ( i = 0; i < HASHSIZE; i++ ) { >+ this = &key_table[i]; >+ if ( !this->name ) continue; >+ do { >+ printf( "\t\"%s\", %d, %d,\n", this->name, this->value, this->shift ); >+ this = this->next; >+ } while ( this ); >+ } >+ printf( "\t\".\", 0, 0\n};\n" ); >+ exit( 0 ); >+} >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 >--- linux-2.6.20/drivers/char/speakup/mapdata.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/mapdata.h 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,239 @@ >+t_key_init init_key_data[] = { >+ "key_s", 31, -1, >+ "top_edge", 17, -2, >+ "key_t", 20, -1, >+ "say_first_char", 6, -2, >+ "attrib_bleep_inc", 71, -2, >+ "key_u", 22, -1, >+ "key_grave", 41, -1, >+ "key_v", 47, -1, >+ "key_w", 17, -1, >+ "key_kpasterisk", 55, -1, >+ "key_minus", 12, -1, >+ "key_x", 45, -1, >+ "key_down", 108, -1, >+ "key_y", 21, -1, >+ "key_kpdot", 83, -1, >+ "key_leftmeta", 125, -1, >+ "key_z", 44, -1, >+ "key_volumedown", 114, -1, >+ "say_next_word", 13, -2, >+ "clear_win", 41, -2, >+ "key_rightbrace", 27, -1, >+ "right_edge", 20, -2, >+ "key_scrolllock", 70, -1, >+ "key_comma", 51, -1, >+ "altgr", 2, -3, >+ "say_screen", 23, -2, >+ "key_cut", 137, -1, >+ "say_to_bottom", 30, -2, >+ "edit_most", 35, -2, >+ "key_sleep", 142, -1, >+ "say_phonetic_char", 36, -2, >+ "speakup_quiet", 3, -2, >+ "read_all_doc", 47, -2, >+ "key_hanja", 123, -1, >+ "say_next_line", 16, -2, >+ "vol_dec", 78, -2, >+ "key_help", 138, -1, >+ "key_xfer", 147, -1, >+ "speakup_goto", 1, -2, >+ "punct_inc", 83, -2, >+ "key_rightctrl", 97, -1, >+ "attrib_bleep_dec", 70, -2, >+ "key_rightshift", 54, -1, >+ "key_linefeed", 101, -1, >+ "key_wakeup", 143, -1, >+ "key_enter", 28, -1, >+ "key_hangeul", 122, -1, >+ "key_again", 129, -1, >+ "key_file", 144, -1, >+ "key_tab", 15, -1, >+ "speakup_off", 26, -2, >+ "set_win", 40, -2, >+ "key_insert", 110, -1, >+ "key_setup", 141, -1, >+ "key_equal", 13, -1, >+ "tone_inc", 81, -2, >+ "key_hiragana", 91, -1, >+ "key_kpjpcomma", 95, -1, >+ "key_pause", 119, -1, >+ "key_volumeup", 115, -1, >+ "key_f1", 59, -1, >+ "double", 32, -3, >+ "key_f2", 60, -1, >+ "key_computer", 157, -1, >+ "key_back", 158, -1, >+ "key_leftctrl", 29, -1, >+ "key_f3", 61, -1, >+ "key_f4", 62, -1, >+ "key_0", 11, -1, >+ "key_f5", 63, -1, >+ "key_yen", 124, -1, >+ "key_copy", 133, -1, >+ "speakup_paste", 5, -2, >+ "key_1", 2, -1, >+ "key_f6", 64, -1, >+ "toggle_cursoring", 46, -2, >+ "key_esc", 1, -1, >+ "key_2", 3, -1, >+ "key_f7", 65, -1, >+ "speakup_parked", 27, -2, >+ "punct_dec", 82, -2, >+ "key_3", 4, -1, >+ "key_f8", 66, -1, >+ "key_4", 5, -1, >+ "key_f9", 67, -1, >+ "key_5", 6, -1, >+ "key_calc", 140, -1, >+ "spell_phonetic", 21, -2, >+ "key_6", 7, -1, >+ "key_7", 8, -1, >+ "key_coffee", 152, -1, >+ "key_mail", 155, -1, >+ "say_attributes", 25, -2, >+ "say_to_right", 32, -2, >+ "key_8", 9, -1, >+ "key_mute", 113, -1, >+ "key_9", 10, -1, >+ "key_katakana", 90, -1, >+ "key_zenkakuhankaku", 85, -1, >+ "key_forward", 159, -1, >+ "key_up", 103, -1, >+ "tone_dec", 80, -2, >+ "key_leftalt", 56, -1, >+ "say_next_char", 10, -2, >+ "reading_punc_inc", 69, -2, >+ "rate_inc", 75, -2, >+ "key_backspace", 14, -1, >+ "bottom_edge", 18, -2, >+ "key_kp0", 82, -1, >+ "key_delete", 111, -1, >+ "key_prog1", 148, -1, >+ "say_char_num", 33, -2, >+ "key_kp1", 79, -1, >+ "key_end", 107, -1, >+ "key_prog2", 149, -1, >+ "key_kp2", 80, -1, >+ "say_prev_word", 12, -2, >+ "left_edge", 19, -2, >+ "key_kp3", 81, -1, >+ "key_katakanahiragana", 93, -1, >+ "key_right", 106, -1, >+ "key_kp4", 75, -1, >+ "key_find", 136, -1, >+ "key_kp5", 76, -1, >+ "speakup_cut", 4, -2, >+ "key_kp6", 77, -1, >+ "key_kp7", 71, -1, >+ "spkup_max_func", 48, -2, >+ "key_kp8", 72, -1, >+ "key_deletefile", 146, -1, >+ "key_f10", 68, -1, >+ "key_kp9", 73, -1, >+ "key_f11", 87, -1, >+ "key_sendfile", 145, -1, >+ "say_word", 11, -2, >+ "edit_repeat", 38, -2, >+ "key_leftbrace", 26, -1, >+ "key_f12", 88, -1, >+ "say_prev_line", 15, -2, >+ "say_from_top", 29, -2, >+ "var_start", 64, -2, >+ "reading_punc_dec", 68, -2, >+ "rate_dec", 74, -2, >+ "key_backslash", 43, -1, >+ "edit_exnum", 39, -2, >+ "key_kpslash", 98, -1, >+ "key_pagedown", 109, -1, >+ "key_kpplusminus", 118, -1, >+ "key_stop", 128, -1, >+ "key_props", 130, -1, >+ "pitch_inc", 77, -2, >+ "key_semicolon", 39, -1, >+ "key_rightalt", 100, -1, >+ "key_pageup", 104, -1, >+ "key_kpplus", 78, -1, >+ "say_line", 14, -2, >+ "bleeps_inc", 73, -2, >+ "key_leftshift", 42, -1, >+ "key_kpminus", 74, -1, >+ "key_paste", 135, -1, >+ "spell_delay_inc", 65, -2, >+ "punc_level_inc", 67, -2, >+ "key_www", 150, -1, >+ "edit_delim", 37, -2, >+ "key_capslock", 58, -1, >+ "key_muhenkan", 94, -1, >+ "key_compose", 127, -1, >+ "spk_key", 128, -2, >+ "key_sysrq", 99, -1, >+ "key_apostrophe", 40, -1, >+ "key_left", 105, -1, >+ "key_power", 116, -1, >+ "key_menu", 139, -1, >+ "voice_inc", 85, -2, >+ "key_kpcomma", 121, -1, >+ "spell_word", 22, -2, >+ "enable_win", 42, -2, >+ "key_a", 30, -1, >+ "key_henkan", 92, -1, >+ "key_bookmarks", 156, -1, >+ "say_line_indent", 28, -2, >+ "key_b", 48, -1, >+ "key_space", 57, -1, >+ "key_c", 46, -1, >+ "edit_some", 34, -2, >+ "key_d", 32, -1, >+ "key_numlock", 69, -1, >+ "key_home", 102, -1, >+ "shift", 1, -3, >+ "key_e", 18, -1, >+ "key_msdos", 151, -1, >+ "say_position", 24, -2, >+ "pitch_dec", 76, -2, >+ "key_f", 33, -1, >+ "key_cyclewindows", 154, -1, >+ "speakup_help", 45, -2, >+ "first_edit_bits", 34, -2, >+ "alt", 8, -3, >+ "key_g", 34, -1, >+ "key_kpenter", 96, -1, >+ "key_macro", 112, -1, >+ "bleeps_dec", 72, -2, >+ "ctrl", 4, -3, >+ "key_h", 35, -1, >+ "key_direction", 153, -1, >+ "key_i", 23, -1, >+ "spk_lock", 44, -2, >+ "spell_delay_dec", 64, -2, >+ "punc_level_dec", 66, -2, >+ "key_j", 36, -1, >+ "say_prev_char", 9, -2, >+ "key_k", 37, -1, >+ "key_102nd", 86, -1, >+ "key_l", 38, -1, >+ "key_ro", 89, -1, >+ "key_rightmeta", 126, -1, >+ "key_m", 50, -1, >+ "key_kpequal", 117, -1, >+ "key_undo", 131, -1, >+ "speech_kill", 2, -2, >+ "key_n", 49, -1, >+ "key_front", 132, -1, >+ "key_o", 24, -1, >+ "key_open", 134, -1, >+ "voice_dec", 84, -2, >+ "spk", 16, -3, >+ "key_p", 25, -1, >+ "say_last_char", 7, -2, >+ "say_from_left", 31, -2, >+ "key_q", 16, -1, >+ "key_slash", 53, -1, >+ "say_win", 43, -2, >+ "key_r", 19, -1, >+ "key_dot", 52, -1, >+ "say_char", 8, -2, >+ "vol_inc", 79, -2, >+ ".", 0, 0 >+}; >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 >--- linux-2.6.20/drivers/char/speakup/mod_code.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/mod_code.c 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,22 @@ >+/* this code is to modularize a synth specific file, included at the end */ >+ >+static void __exit mod_synth_exit( void ) >+{ >+ if ( synth == &MY_SYNTH ) >+ synth_release( ); >+ synth_remove( &MY_SYNTH ); >+} >+ >+static int __init mod_synth_init( void ) >+{ >+ int status = do_synth_init( &MY_SYNTH ); >+ if ( status != 0 ) return status; >+ synth_add( &MY_SYNTH ); >+ return 0; >+} >+ >+module_init( mod_synth_init ); >+module_exit( mod_synth_exit ); >+MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>"); >+MODULE_DESCRIPTION("Synthesizer driver module for speakup for the synth->long_name"); >+MODULE_LICENSE( "GPL" ); >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 >--- linux-2.6.20/drivers/char/speakup/serialio.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/serialio.h 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,18 @@ >+#ifndef SSPK_SERIAL >+#define SSPK_SERIAL >+ >+#include <linux/serial.h> /* for rs_table, serial constants & >+ serial_uart_config */ >+#include <linux/serial_reg.h> /* for more serial constants */ >+#include <linux/serialP.h> /* for struct serial_state */ >+#include <asm/serial.h> >+ >+#define SPK_SERIAL_TIMEOUT 1000000 /* countdown values for serial timeouts */ >+#define SPK_XMITR_TIMEOUT 1000000 /* countdown values transmitter/dsr timeouts */ >+#define SPK_LO_TTY 0 /* check ttyS0 ... ttyS3 */ >+#define SPK_HI_TTY 3 >+#define NUM_DISABLE_TIMEOUTS 3 /* # of timeouts permitted before disable */ >+#define SPK_TIMEOUT 100 /* buffer timeout in ms */ >+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) >+ >+#endif >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 >--- linux-2.6.20/drivers/char/speakup/speakup_acnt.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_acnt.h 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,16 @@ >+/* speakup_acntpc.h - header file for speakups Accent-PC driver. */ >+ >+#define SYNTH_IO_EXTENT 0x02 >+ >+#define SYNTH_CLEAR 0x18 /* stops speech */ >+ >+ /* Port Status Flags */ >+#define SYNTH_READABLE 0x01 /* mask for bit which is nonzero if a >+ byte can be read from the data port */ >+#define SYNTH_WRITABLE 0x02 /* mask for RDY bit, which when set to >+ 1, indicates the data port is ready >+ to accept a byte of data. */ >+#define SYNTH_QUIET 'S' /* synth is not speaking */ >+#define SYNTH_FULL 'F' /* synth is full. */ >+#define SYNTH_ALMOST_EMPTY 'M' /* synth has les than 2 seconds of text left */ >+#define SYNTH_SPEAKING 's' /* synth is speaking and has a fare way to go */ >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 >--- linux-2.6.20/drivers/char/speakup/speakup_acntpc.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_acntpc.c 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,161 @@ >+/* >+ * originially written by: Kirk Reiser <kirk@braille.uwo.ca> >+* this version considerably modified by David Borowski, david575@rogers.com >+ >+ Copyright (C) 1998-99 Kirk Reiser. >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "speakup_acnt.h" /* local header file for Accent values */ >+ >+#define MY_SYNTH synth_acntpc >+#define synth_readable( ) ( inb_p( synth_port_control ) & SYNTH_READABLE ) >+#define synth_writable( ) ( inb_p( synth_port_control ) & SYNTH_WRITABLE ) >+#define synth_full( ) ( inb_p( synth_port_tts ) == 'F' ) >+#define PROCSPEECH '\r' >+ >+ >+static int synth_port_control; >+static unsigned int synth_portlist[] = >+ { 0x2a8, 0 }; >+ >+static const char *synth_immediate ( const char *buf ) >+{ >+ u_char ch; >+ while ( ( ch = *buf ) ) { >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( synth_full( ) ) >+ return buf; >+ while ( synth_writable( ) ); >+ outb_p( ch, synth_port_tts ); >+ buf++; >+ } >+ return 0; >+} >+ >+static void do_catch_up( unsigned long data ) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+ synth_stop_timer( ); >+ while ( synth_buff_out < synth_buff_in ) { >+ if ( synth_full( ) ) { >+ synth_delay( synth_full_time ); >+ return; >+ } >+ while ( synth_writable( ) ); >+ ch = *synth_buff_out++; >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ outb_p( ch, synth_port_tts ); >+ if ( jiffies >= jiff_max && ch == SPACE ) { >+ while ( synth_writable( ) ); >+ outb_p( PROCSPEECH, synth_port_tts ); >+ synth_delay( synth_delay_time ); >+ return; >+ } >+ } >+ while ( synth_writable( ) ); >+ outb_p( PROCSPEECH, synth_port_tts ); >+ synth_done( ); >+} >+ >+static void synth_flush( void ) >+{ >+ outb_p( SYNTH_CLEAR, synth_port_tts ); >+} >+ >+static int synth_probe( void ) >+{ >+ unsigned int port_val = 0; >+ int i = 0; >+ pr_info( "Probing for %s.\n", synth->long_name ); >+ if ( synth_port_forced ) { >+ synth_port_tts = synth_port_forced; >+ pr_info( "probe forced to %x by kernel command line\n", synth_port_tts ); >+ if ( synth_request_region( synth_port_tts-1, SYNTH_IO_EXTENT ) ) { >+ pr_warn( "sorry, port already reserved\n" ); >+ return -EBUSY; >+ } >+ port_val = inw( synth_port_tts-1 ); >+ synth_port_control = synth_port_tts-1; >+ } else { >+ for( i=0; synth_portlist[i]; i++ ) { >+ if ( synth_request_region( synth_portlist[i], SYNTH_IO_EXTENT ) ) { >+ pr_warn( "request_region: failed with 0x%x, %d\n", >+ synth_portlist[i], SYNTH_IO_EXTENT ); >+ continue; >+ } >+ port_val = inw( synth_portlist[i] ); >+ if ( ( port_val &= 0xfffc ) == 0x53fc ) { /* 'S' and out&input bits */ >+ synth_port_control = synth_portlist[i]; >+ synth_port_tts = synth_port_control+1; >+ break; >+ } >+ } >+ } >+ if ( ( port_val &= 0xfffc ) != 0x53fc ) { /* 'S' and out&input bits */ >+ pr_info( "%s: not found\n", synth->long_name ); >+ synth_release_region( synth_portlist[i], SYNTH_IO_EXTENT ); >+ synth_port_control = 0; >+ return -ENODEV; >+ } >+ pr_info( "%s: %03x-%03x, driver version %s,\n", synth->long_name, >+ synth_port_control, synth_port_control+SYNTH_IO_EXTENT-1, >+ synth->version ); >+ return 0; >+} >+ >+static void accent_release( void ) >+{ >+ if ( synth_port_tts ) >+ synth_release_region( synth_port_tts-1, SYNTH_IO_EXTENT ); >+ synth_port_tts = 0; >+} >+ >+static int synth_is_alive( void ) >+{ >+ synth_alive = 1; >+ return 1; >+} >+ >+static const char init_string[] = "\033=X \033Oi\033T2\033=M\033N1\n"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "\033P8" }, >+ { CAPS_STOP, "\033P5" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "\033R%c", 9, 0, 17, 0, 0, "0123456789abcdefgh" }, >+ { PITCH, "\033P%d", 5, 0, 9, 0, 0, 0 }, >+ { VOL, "\033A%d", 5, 0, 9, 0, 0, 0 }, >+ { TONE, "\033V%d", 5, 0, 9, 0, 0, 0 }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_acntpc = {"acntpc", "1.1", "Accent PC", >+ init_string, 500, 50, 50, 1000, 0, 0, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, accent_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL, >+ {NULL,0,0,0} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >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 >--- linux-2.6.20/drivers/char/speakup/speakup_acntsa.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_acntsa.c 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,184 @@ >+/* >+ * originially written by: Kirk Reiser <kirk@braille.uwo.ca> >+* this version considerably modified by David Borowski, david575@rogers.com >+ >+ Copyright (C) 1998-99 Kirk Reiser. >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "serialio.h" >+#include "speakup_acnt.h" /* local header file for Accent values */ >+ >+#define MY_SYNTH synth_acntsa >+#define synth_full( ) ( inb_p( synth_port_tts ) == 'F' ) >+#define PROCSPEECH '\r' >+ >+static int timeouts = 0; /* sequential number of timeouts */ >+ >+static int >+wait_for_xmitr ( void ) >+{ >+ int check, tmout = SPK_XMITR_TIMEOUT; >+ if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) { >+ synth_alive = 0; >+ return 0; >+ } >+ do { /* holding register empty? */ >+ check = inb_p ( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) { >+ pr_warn ( "%s: timed out\n", synth->long_name ); >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY ); >+ tmout = SPK_XMITR_TIMEOUT; >+ do { /* CTS */ >+ check = inb_p ( synth_port_tts + UART_MSR ); >+ if ( --tmout == 0 ) { >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS ); >+ timeouts = 0; >+ return 1; >+} >+ >+static int spk_serial_out(const char ch) >+{ >+ if (synth_alive && wait_for_xmitr()) { >+ outb_p(ch, synth_port_tts); >+ return 1; >+ } >+ return 0; >+} >+ >+static void >+do_catch_up ( unsigned long data ) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+ synth_stop_timer ( ); >+ while ( synth_buff_out < synth_buff_in ) { >+ ch = *synth_buff_out; >+ if ( ch == 0x0a ) ch = 0x0D; >+ if ( !spk_serial_out ( ch ) ) { >+ synth_delay ( synth_full_time ); >+ return; >+ } >+ synth_buff_out++; >+ if ( jiffies >= jiff_max && ch == ' ' ) { >+ spk_serial_out ( PROCSPEECH ); >+ synth_delay ( synth_delay_time ); >+ return; >+ } >+ } >+ spk_serial_out ( PROCSPEECH ); >+ synth_done( ); >+} >+ >+static const char *synth_immediate ( const char *buff ) >+{ >+ u_char ch; >+ while ( ( ch = *buff ) ) { >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( wait_for_xmitr( ) ) >+ outb( ch, synth_port_tts ); >+ else return buff; >+ buff++; >+ } >+ return 0; >+} >+ >+static void synth_flush ( void ) >+{ >+ spk_serial_out ( SYNTH_CLEAR ); >+} >+ >+static int serprobe ( int index ) >+{ >+ struct serial_state *ser = spk_serial_init( index ); >+ if ( ser == NULL ) return -1; >+ outb ( 0x0d, ser->port ); >+ // mdelay ( 1 ); >+ /* ignore any error results, if port was forced */ >+ if ( synth_port_forced ) return 0; >+ /* check for accent s.a now... */ >+ if ( !synth_immediate( "\x18" ) ) >+ return 0; >+ spk_serial_release( ); >+ timeouts = synth_alive = 0; /* not ignoring */ >+ return -1; >+} >+ >+static int synth_probe ( void ) >+{ >+ int i = 0, failed=0; >+ pr_info ( "Probing for %s.\n", synth->long_name ); >+ for ( i = SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) { >+ if (( failed = serprobe( i )) == 0 ) break; /* found it */ >+ } >+ if ( failed ) { >+ pr_info ( "%s: not found\n", synth->long_name ); >+ return -ENODEV; >+ } >+ pr_info ( "%s: %03x-%03x, Driver Version %s,\n", synth->long_name, >+ synth_port_tts, synth_port_tts + 7, synth->version ); >+ synth_immediate( "\033=R\r" ); >+ mdelay( 100 ); >+ return 0; >+} >+ >+static int >+synth_is_alive ( void ) >+{ >+ if ( synth_alive ) return 1; >+ if ( !synth_alive && wait_for_xmitr ( ) > 0 ) { /* restart */ >+ synth_alive = 1; >+ synth_write_string ( synth->init ); >+ return 2; >+ } >+ pr_warn ( "%s: can't restart synth\n", synth->long_name ); >+ return 0; >+} >+ >+static const char init_string[] = "\033T2\033=M\033Oi\033N1\n"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "\033P8" }, >+ { CAPS_STOP, "\033P5" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "\033R%c", 9, 0, 17, 0, 0, "0123456789abcdefgh" }, >+ { PITCH, "\033P%d", 5, 0, 9, 0, 0, 0 }, >+ { VOL, "\033A%d", 9, 0, 9, 0, 0, 0 }, >+ { TONE, "\033V%d", 5, 0, 9, 0, 0, 0 }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_acntsa = { "acntsa", "1.1", "Accent-SA", >+ init_string, 400, 5, 30, 1000, 0, 0, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, spk_serial_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL, >+ {NULL,0,0,0} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >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 >--- linux-2.6.20/drivers/char/speakup/speakup_apollo.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_apollo.c 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,196 @@ >+/* >+ * originially written by: Kirk Reiser <kirk@braille.uwo.ca> >+* this version considerably modified by David Borowski, david575@rogers.com >+ >+ Copyright (C) 1998-99 Kirk Reiser. >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "serialio.h" >+ >+#define MY_SYNTH synth_apollo >+#define SYNTH_CLEAR 0x18 >+#define PROCSPEECH '\r' >+ >+static int timeouts = 0; /* sequential number of timeouts */ >+ >+static int wait_for_xmitr( void ) >+{ >+ int check, tmout = SPK_XMITR_TIMEOUT; >+ if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) { >+ synth_alive = 0; >+ timeouts = 0; >+ return 0; >+ } >+ do { >+ check = inb( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) { >+ pr_warn( "APOLLO: timed out\n" ); >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY ); >+ tmout = SPK_XMITR_TIMEOUT; >+ do { >+ check = inb( synth_port_tts + UART_MSR ); >+ if ( --tmout == 0 ) { >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS ); >+ timeouts = 0; >+ return 1; >+} >+ >+static int spk_serial_out(const char ch) >+{ >+ // int timer = 9000000; >+ if ( synth_alive && wait_for_xmitr( ) ) { >+ outb( ch, synth_port_tts ); >+ /*while ( inb( synth_port_tts+UART_MSR ) & UART_MSR_CTS ) if ( --timer == 0 ) break;*/ >+ /* outb( UART_MCR_DTR, synth_port_tts + UART_MCR );*/ >+ return 1; >+ } >+ return 0; >+} >+ >+/* >+static unsigned char spk_serial_in( void ) >+{ >+ int c, lsr, tmout = SPK_SERIAL_TIMEOUT; >+ do { >+ lsr = inb( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) return 0xff; >+ } while ( !( lsr & UART_LSR_DR ) ); >+ c = inb( synth_port_tts + UART_RX ); >+ return ( unsigned char ) c; >+} >+*/ >+ >+static void do_catch_up( unsigned long data ) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+synth_stop_timer( ); >+ while ( synth_buff_out < synth_buff_in ) { >+ ch = *synth_buff_out; >+ if ( !spk_serial_out( ch ) ) { >+ outb( UART_MCR_DTR, synth_port_tts + UART_MCR ); >+ outb( UART_MCR_DTR | UART_MCR_RTS, synth_port_tts + UART_MCR ); >+ synth_delay( synth_full_time ); >+ return; >+ } >+ synth_buff_out++; >+ if ( jiffies >= jiff_max && synth_buff_out-synth_buffer > 10 ) { >+ spk_serial_out( PROCSPEECH ); >+ synth_delay( synth_delay_time ); >+ return; >+ } >+ } >+ spk_serial_out( PROCSPEECH ); >+ synth_done( ); >+} >+ >+static const char *synth_immediate ( const char *buf ) >+{ >+ u_char ch; >+ while ( ( ch = *buf ) ) { >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( wait_for_xmitr( ) ) >+ outb( ch, synth_port_tts ); >+ else return buf; >+ buf++; >+ } >+ return 0; >+} >+ >+static void synth_flush ( void ) >+{ >+ spk_serial_out ( SYNTH_CLEAR ); >+} >+ >+static int serprobe( int index ) >+{ >+ struct serial_state *ser = spk_serial_init( index ); >+ if ( ser == NULL ) return -1; >+ outb( 0x0d, ser->port ); /* wake it up if older BIOS */ >+ mdelay( 1 ); >+ synth_port_tts = ser->port; >+ if ( synth_port_forced ) return 0; >+ /* check for apollo now... */ >+ if ( !synth_immediate( "\x18" ) ) return 0; >+ pr_warn( "port %x failed\n", synth_port_tts ); >+ spk_serial_release( ); >+ timeouts = synth_alive = synth_port_tts = 0; >+ return -1; >+} >+ >+static int synth_probe( void ) >+{ >+ int i, failed=0; >+ pr_info( "Probing for %s.\n", synth->long_name ); >+ for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) { >+ if (( failed = serprobe( i )) == 0 ) break; /* found it */ >+ } >+ if ( failed ) { >+ pr_info( "%s: not found\n", synth->long_name ); >+ return -ENODEV; >+ } >+ pr_info( "%s: %03x-%03x, Driver version %s,\n", synth->long_name, >+ synth_port_tts, synth_port_tts + 7, synth->version ); >+ return 0; >+} >+ >+static int synth_is_alive( void ) >+{ >+ if ( synth_alive ) return 1; >+ if ( !synth_alive && wait_for_xmitr( ) > 0 ) { /* restart */ >+ synth_alive = 1; >+ synth_write_string( synth->init ); >+ return 2; /* reenabled */ >+ } else pr_warn( "%s: can't restart synth\n", synth->long_name ); >+ return 0; >+} >+ >+static const char init_string[] = "@R3@D0@K1\r"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "cap, " }, >+ { CAPS_STOP, "" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "@W%d", 6, 1, 9, 0, 0, 0 }, >+ { PITCH, "@F%x", 10, 0, 15, 0, 0, 0 }, >+ { VOL, "@A%x", 10, 0, 15, 0, 0, 0 }, >+ { VOICE, "@V%d", 1, 1, 6, 0, 0, 0 }, >+ { LANG, "@=%d,", 1, 1, 4, 0, 0, 0 }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_apollo = {"apollo", "1.2", "Apollo", >+ init_string, 500, 50, 50, 5000, 0, 0, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, spk_serial_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL, >+ {NULL,0,0,0} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >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 >--- linux-2.6.20/drivers/char/speakup/speakup_audptr.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_audptr.c 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,202 @@ >+/* >+ * originially written by: Kirk Reiser <kirk@braille.uwo.ca> >+* this version considerably modified by David Borowski, david575@rogers.com >+ >+ Copyright (C) 1998-99 Kirk Reiser. >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "serialio.h" >+ >+#define MY_SYNTH synth_audptr >+#define SYNTH_CLEAR 0x18 /* flush synth buffer */ >+#define PROCSPEECH '\r' /* start synth processing speech char */ >+ >+static int timeouts = 0; /* sequential number of timeouts */ >+ >+static int wait_for_xmitr( void ) >+{ >+ int check, tmout = SPK_XMITR_TIMEOUT; >+ if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) { >+ synth_alive = 0; >+ timeouts = 0; >+ return 0; >+ } >+ do { /* holding register empty? */ >+ check = inb( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) { >+ pr_warn( "%s: timed out\n", synth->long_name ); >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY ); >+ tmout = SPK_XMITR_TIMEOUT; >+ do { /* CTS */ >+ check = inb( synth_port_tts + UART_MSR ); >+ if ( --tmout == 0 ) { >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS ); >+ timeouts = 0; >+ return 1; >+} >+ >+static int spk_serial_out(const char ch) >+{ >+ if ( synth_alive && wait_for_xmitr( ) ) { >+ outb( ch, synth_port_tts ); >+ return 1; >+ } >+ return 0; >+} >+ >+static unsigned char spk_serial_in( void ) >+{ >+ int c, lsr, tmout = SPK_SERIAL_TIMEOUT; >+ do { >+ lsr = inb( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) return 0xff; >+ } while ( !( lsr & UART_LSR_DR ) ); >+ c = inb( synth_port_tts + UART_RX ); >+ return ( unsigned char ) c; >+} >+ >+static void do_catch_up( unsigned long data ) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+synth_stop_timer( ); >+ while ( synth_buff_out < synth_buff_in ) { >+ ch = *synth_buff_out; >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( !spk_serial_out( ch ) ) { >+ synth_delay( synth_full_time ); >+ return; >+ } >+ synth_buff_out++; >+ if ( jiffies >= jiff_max && ch == SPACE ) { >+ spk_serial_out( PROCSPEECH ); >+ synth_delay( synth_delay_time ); >+ return; >+ } >+ } >+ spk_serial_out( PROCSPEECH ); >+ synth_done( ); >+} >+ >+static const char *synth_immediate ( const char *buf ) >+{ >+ u_char ch; >+ while ( ( ch = *buf ) ) { >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( wait_for_xmitr( ) ) >+ outb( ch, synth_port_tts ); >+ else return buf; >+ buf++; >+ } >+ return 0; >+} >+ >+static void synth_flush( void ) >+{ >+ while ( ( inb( synth_port_tts + UART_LSR ) & BOTH_EMPTY ) != BOTH_EMPTY ); >+ outb( SYNTH_CLEAR, synth_port_tts ); >+ spk_serial_out( PROCSPEECH ); >+ } >+ >+static char synth_id[40] = ""; >+ >+static int serprobe( int index ) >+{ >+ u_char test = 0; >+ struct serial_state *ser = spk_serial_init( index ); >+ if ( ser == NULL ) return -1; >+ /* ignore any error results, if port was forced */ >+ if ( synth_port_forced ) >+ return 0; >+ synth_immediate( "\x05[Q]" ); >+ if ( ( synth_id[test] = spk_serial_in( ) ) == 'A' ) { >+ do { /* read version string from synth */ >+ synth_id[++test] = spk_serial_in( ); >+ } while ( synth_id[test] != '\n' && test < 32 ); >+ synth_id[++test] = 0x00; >+ if ( test != 32 ) >+ return 0; >+ } >+ spk_serial_release( ); >+ timeouts = synth_alive = 0; /* not ignoring */ >+ return -1; >+} >+ >+static int synth_probe( void ) >+{ >+ int i=0, failed=0; >+ pr_info( "Probing for %s.\n", synth->long_name ); >+ for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) { >+ if (( failed = serprobe( i )) == 0 ) break; /* found it */ >+ } >+ if ( failed ) { >+ pr_info( "%s: not found\n", synth->long_name ); >+ return -ENODEV; >+ } >+ pr_info( "%s: %03x-%03x, Driver %s,\n", synth->long_name, >+ synth_port_tts, synth_port_tts + 7, synth->version ); >+ if ( synth_id[0] == 'A' ) >+ pr_info( "%s version: %s", synth->long_name, synth_id ); >+ return 0; >+} >+ >+static int synth_is_alive( void ) >+{ >+ if ( synth_alive ) return 1; >+ if ( !synth_alive && wait_for_xmitr( ) > 0 ) { /* restart */ >+ synth_alive = 1; >+ synth_write_string( synth->init ); >+ return 2; >+ } >+ return 0; >+} >+ >+static const char init_string[] = "\x05[D1]\x05[Ol]"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "\x05[f99]" }, >+ { CAPS_STOP, "\x05[f80]" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "\x05[r%d]", 10, 0, 20, -100, 10, 0 }, >+ { PITCH, "\x05[f%d]", 80, 39, 4500, 0, 0, 0 }, >+ { VOL, "\x05[g%d]", 21, 0, 40, 0, 0, 0 }, >+ { TONE, "\x05[s%d]", 9, 0,63, 0, 0, 0 }, >+ { PUNCT, "\x05[A%c]", 0, 0, 3, 0, 0, "nmsa" }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_audptr = {"audptr", "1.1", "Audapter", >+ init_string, 400, 5, 30, 5000, 0, 0, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, spk_serial_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL, >+ {NULL,0,0,0} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >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 >--- linux-2.6.20/drivers/char/speakup/speakup_bns.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_bns.c 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,175 @@ >+/* >+ * originially written by: Kirk Reiser <kirk@braille.uwo.ca> >+* this version considerably modified by David Borowski, david575@rogers.com >+ >+ Copyright (C) 1998-99 Kirk Reiser. >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "serialio.h" >+ >+#define MY_SYNTH synth_bns >+#define SYNTH_CLEAR 0x18 >+#define PROCSPEECH '\r' >+ >+static int wait_for_xmitr( void ) >+{ >+ static int timeouts = 0; /* sequential number of timeouts */ >+ int check, tmout = SPK_XMITR_TIMEOUT; >+ if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) { >+ synth_alive = 0; >+ timeouts = 0; >+ return 0; >+ } >+ do { >+ check = inb( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) { >+ pr_warn( "BNS: timed out\n" ); >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY ); >+ tmout = SPK_XMITR_TIMEOUT; >+ do { >+ check = inb( synth_port_tts + UART_MSR ); >+ if ( --tmout == 0 ) { >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS ); >+ timeouts = 0; >+ return 1; >+} >+ >+static int spk_serial_out(const char ch) >+{ >+ if ( synth_alive && wait_for_xmitr( ) ) { >+ outb( ch, synth_port_tts ); >+ return 1; >+ } >+ return 0; >+} >+ >+static void do_catch_up( unsigned long data ) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+ synth_stop_timer( ); >+ while ( synth_buff_out < synth_buff_in ) { >+ ch = *synth_buff_out; >+ if ( ch == '\n' ) ch = PROCSPEECH; >+ if ( !spk_serial_out( ch ) ) { >+ synth_delay( synth_full_time ); >+ return; >+ } >+ synth_buff_out++; >+ if ( jiffies >= jiff_max && ch == ' ' ) { >+ spk_serial_out( PROCSPEECH ); >+ synth_delay( synth_delay_time ); >+ return; >+ } >+ } >+ spk_serial_out( PROCSPEECH ); >+ synth_done( ); >+} >+ >+static const char *synth_immediate ( const char *buf ) >+{ >+ u_char ch; >+ while ( ( ch = *buf ) ) { >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( wait_for_xmitr( ) ) >+ outb( ch, synth_port_tts ); >+ else return buf; >+ buf++; >+ } >+ return 0; >+} >+ >+static void synth_flush ( void ) >+{ >+ spk_serial_out ( SYNTH_CLEAR ); >+} >+ >+static int serprobe( int index ) >+{ >+ struct serial_state *ser = spk_serial_init( index ); >+ if ( ser == NULL ) return -1; >+ outb( '\r', ser->port ); >+ if ( synth_port_forced ) return 0; >+ /* check for bns now... */ >+ if ( !synth_immediate( "\x18" ) ) return 0; >+ spk_serial_release( ); >+ synth_alive = 0; >+ return -1; >+} >+ >+static int synth_probe( void ) >+{ >+ int i=0, failed=0; >+ pr_info( "Probing for %s.\n", synth->long_name ); >+ for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) { >+ if (( failed = serprobe( i )) == 0 ) break; /* found it */ >+ } >+ if ( failed ) { >+ pr_info( "%s: not found\n", synth->long_name ); >+ return -ENODEV; >+ } >+ pr_info( "%s: %03x-%03x, Driver version %s,\n", synth->long_name, >+ synth_port_tts, synth_port_tts + 7, synth->version ); >+ return 0; >+} >+ >+static int synth_is_alive( void ) >+{ >+ if ( synth_alive ) return 1; >+ if ( !synth_alive && wait_for_xmitr( ) > 0 ) { /* restart */ >+ synth_alive = 1; >+ synth_write_string( synth->init ); >+ return 2; >+ } >+ pr_warn( "%s: can't restart synth\n", synth->long_name ); >+ return 0; >+} >+ >+static const char init_string[] = "\x05Z\x05\x43"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "\x05\x31\x32P" }, >+ { CAPS_STOP, "\x05\x38P" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "\x05%dE", 8, 1, 16, 0, 0, 0 }, >+ { PITCH, "\x05%dP", 8, 0, 16, 0, 0, 0 }, >+ { VOL, "\x05%dV", 8, 0, 16, 0, 0, 0 }, >+ { TONE, "\x05%dT", 8, 0, 16, 0, 0, 0 }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_bns = {"bns", "1.1", "Braille 'N Speak", >+ init_string, 500, 50, 50, 5000, 0, 0, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, spk_serial_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL, >+ {NULL,0,0,0} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >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 >--- linux-2.6.20/drivers/char/speakup/speakup.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup.c 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,2873 @@ >+/* speakup.c >+ review functions for the speakup screen review package. >+ originally written by: Kirk Reiser and Andy Berdan. >+ >+ extensively modified by David Borowski. >+ >+ Copyright (C ) 1998 Kirk Reiser. >+ Copyright (C ) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option ) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+*/ >+ >+#include <linux/kernel.h> >+#include <linux/version.h> >+#include <linux/vt.h> >+#include <linux/tty.h> >+#include <linux/mm.h> /* __get_free_page( ) and friends */ >+#include <linux/vt_kern.h> >+#include <linux/ctype.h> >+#include <linux/selection.h> >+#include <asm/uaccess.h> /* copy_from|to|user( ) and others */ >+#include <linux/unistd.h> >+ >+#include <linux/keyboard.h> /* for KT_SHIFT */ >+#include <linux/kbd_kern.h> /* for vc_kbd_* and friends */ >+#include <linux/vt_kern.h> >+#include <linux/input.h> >+#include <linux/kmod.h> >+#include <linux/speakup.h> >+ >+#include "cvsversion.h" >+#include "spk_priv.h" >+#include <linux/bootmem.h> /* for alloc_bootmem */ >+ >+/* speakup_*_selection */ >+#include <linux/module.h> >+#include <linux/sched.h> >+#include <linux/slab.h> >+#include <linux/types.h> >+#include <asm/uaccess.h> >+#include <linux/consolemap.h> >+ >+#define SPEAKUP_VERSION "Speakup v-2.00" CVSVERSION >+#define MAX_DELAY ( (500 * HZ ) / 1000 ) >+#define KEY_MAP_VER 119 >+#define MINECHOCHAR SPACE >+ >+/* these are globals from the kernel code */ >+extern struct kbd_struct * kbd; >+extern int fg_console; >+extern short punc_masks[]; >+ >+static special_func special_handler = NULL; >+special_func help_handler = NULL; >+ >+short pitch_shift = 0, synth_flags = 0; >+static char buf[256]; >+short attrib_bleep = 0, bleeps = 0, bleep_time = 1; >+short no_intr = 0, spell_delay = 0; >+short key_echo = 0, cursor_timeout = 120, say_word_ctl = 0; >+short say_ctrl = 0, bell_pos = 0; >+short punc_mask = 0, punc_level = 0, reading_punc = 0; >+char str_caps_start[MAXVARLEN+1] = "\0", str_caps_stop[MAXVARLEN+1] = "\0"; >+static const struct st_bits_data punc_info[] = { >+ { "none", "", 0 }, >+ { "some", "/$%&@", SOME }, >+ { "most", "$%&#()=+*/@^<>|\\", MOST }, >+ { "all", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", PUNC }, >+ { "delimiters", "", B_WDLM }, >+ { "repeats", "()", CH_RPT }, >+ { "extended numeric", "", B_EXNUM }, >+ { "symbols", "", B_SYM }, >+ { 0, 0 } >+}; >+static char mark_cut_flag = 0; >+char synth_name[10] = CONFIG_SPEAKUP_DEFAULT; >+#define MAX_KEY 160 >+u_char *our_keys[MAX_KEY], *shift_table; >+static u_char key_buf[600]; >+static const u_char key_defaults[] = { >+#include "speakupmap.h" >+}; >+ >+/* Speakup Cursor Track Variables */ >+static int cursor_track = 1, prev_cursor_track = 1; >+ >+/* cursor track modes, must be ordered same as cursor_msgs */ >+enum { >+ CT_Off = 0, >+ CT_On, >+ CT_Highlight, >+ CT_Window, >+ CT_Max >+}; >+#define read_all_mode CT_Max >+ >+struct tty_struct *tty; >+#define key_handler k_handler >+typedef void (*k_handler_fn)(struct vc_data *vc, unsigned char value, >+ char up_flag); >+extern k_handler_fn key_handler[16]; >+static k_handler_fn do_shift, do_spec, do_latin, do_cursor; >+EXPORT_SYMBOL_GPL(help_handler); >+EXPORT_SYMBOL_GPL(special_handler); >+EXPORT_SYMBOL_GPL(our_keys); >+EXPORT_SYMBOL_GPL(synth_name); >+ >+static void spkup_write(const char *in_buf, int count); >+static int set_mask_bits(const char *input, const int which, const int how); >+ >+static const char str_ctl[] = "control-"; >+static const char *colors[] = { >+ "black", "blue", "green", "cyan", "red", "magenta", "yellow", "white", >+ "grey" >+}; >+ >+static char *phonetic[] = { >+ "alpha", "beta", "charley", "delta", "echo", "fox", "gamma", "hotel", >+ "india", "juleiet", "keelo", "leema", "mike", "november", "oscar", >+ "papa", >+ "quebec", "romeo", "seeara", "tango", "uniform", "victer", "wiskey", >+ "x ray", "yankee", "zooloo" >+}; >+ >+// array of 256 char pointers (one for each character description ) >+// initialized to default_chars and user selectable via /proc/speakup/characters >+static char *characters[256]; >+ >+static char *default_chars[256] = { >+ "null", "^a", "^b", "^c", "^d", "^e", "^f", "^g", >+ "^h", "^i", "^j", "^k", "^l", "^m", "^n", "^o", >+ "^p", "^q", "^r", "^s", "^t", "^u", "^v", "^w", >+ "^x", "^y", "^z", NULL, NULL, NULL, NULL, NULL, >+ "space", "bang!", "quote", "number", "dollar", "percent", "and", >+ "tick", >+ "left paren", "right paren", "star", "plus", "comma", "dash", "dot", >+ "slash", >+ "zero", "one", "two", "three", "four", "five", "six", "seven", >+ "eight", "nine", >+ "colon", "semmy", "less", "equals", "greater", "question", "at", >+ "eigh", "b", "c", "d", "e", "f", "g", >+ "h", "i", "j", "k", "l", "m", "n", "o", >+ "p", "q", "r", "s", "t", "u", "v", "w", "x", >+ "y", "zehd", "left bracket", "backslash", "right bracket", "caret", >+ "line", >+ "accent", NULL, NULL, NULL, NULL, NULL, NULL, NULL, >+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, >+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, >+ NULL, NULL, NULL, "left brace", "bar", "right brace", "tihlduh", >+ "delta", "see cedilla", "u oomlout", "e acute", /* 128 */ >+ "eigh circumflex", "eigh oomlout", "eigh grave", "eigh ring", /* 132 */ >+ "see cedilla", "e circumflex", "e oomlout", "e grave", /* 136 */ >+ "i oomlout", "i circumflex", "i grave", "eigh oomlout", /* 140 */ >+ "eigh ring", "e acute", "eigh e dipthong", "eigh e dipthong", /* 144 */ >+ "o circumflex", "o oomlout", "o grave", "u circumflex", /* 148 */ >+ "u grave", "y oomlout", "o oomlout", "u oomlout", /* 152 */ >+ "cents", "pounds", "yen", "peseta", /* 156 */ >+ "florin", "eigh acute", "i acute", "o acute", /* 160 */ >+ "u acute", "n tilde", "n tilde", "feminine ordinal", /* 164 */ >+ "masculin ordinal", "inverted question", "reversed not", "not", /* 168 */ >+ "half", "quarter", "inverted bang", "much less than", /* 172 */ >+ "much greater than", "dark shading", "medium shading", /* 176 */ >+ "light shading", "verticle line", "left tee", /* 179 */ >+ "double left tee", "left double tee", "double top right", /* 182 */ >+ "top double right", "double left double tee", /* 185 */ >+ "double vertical line", "double top double right", /* 187 */ >+ "double bottom double right", "double bottom right", /* 189 */ >+ "bottom double right", "top right", "left bottom", /* 191 */ >+ "up tee", "tee down", "tee right", "horizontal line", /* 194 */ >+ "cross bars", "tee double right", "double tee right", /* 198 */ >+ "double left double bottom", "double left double top", /* 201 */ >+ "double up double tee", "double tee double down", /* 203 */ >+ "double tee double right", "double horizontal line", /* 205 */ >+ "double cross bars", "up double tee", "double up tee", /* 207 */ >+ "double tee down", "tee double down", /* 210 */ >+ "double left bottom", "left double bottom", /* 212 */ >+ "double left top", "left double top", /* 214 */ >+ "double vertical cross", "double horizontal cross", /* 216 */ >+ "bottom right", "left top", "solid square", /* 218 */ >+ "solid lower half", "solid left half", "solid right half", /* 221 */ >+ "solid upper half", "alpha", "beta", "gamma", /* 224 */ >+ "pie", "sigma", "sigma", "mu", /* 228 */ >+ "tou", "phigh", "thayta", "ohmega", /* 232 */ >+ "delta", "infinity", "phigh", "epsilaun", /* 236 */ >+"intersection", "identical to", "plus or minus", "equal grater than", /* 240 */ >+ "less than equal", "upper integral", "lower integral", /* 244 */ >+ "divided by", "almost equal", "degrees", /* 247 */ >+ "centre dot", "bullet", "square root", /* 250 */ >+ "power", "squared", "black square", "white space" /* 252 */ >+}; >+ >+// array of 256 u_short (one for each character) >+// initialized to default_chartab and user selectable via /proc/speakup/chartab >+static u_short spk_chartab[256]; >+ >+static u_short default_chartab[256] = { >+ B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 0-7 */ >+ B_CTL, B_CTL, A_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 8-15 */ >+ B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /*16-23 */ >+ B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 24-31 */ >+WDLM, A_PUNC, PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC, /* !"#$%&' */ >+PUNC, PUNC, PUNC, PUNC, A_PUNC, A_PUNC, A_PUNC, PUNC, /* ( )*+, -./ */ >+NUM, NUM, NUM, NUM, NUM, NUM, NUM, NUM, /* 01234567 */ >+NUM, NUM, A_PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC, /* 89:;<=>? */ >+PUNC, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* @ABCDEFG */ >+A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* HIJKLMNO */ >+A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* PQRSTUVW */ >+A_CAP, A_CAP, A_CAP, PUNC, PUNC, PUNC, PUNC, PUNC, /* XYZ[\]^_ */ >+PUNC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* `abcdefg */ >+ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* hijklmno */ >+ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* pqrstuvw */ >+ALPHA, ALPHA, ALPHA, PUNC, PUNC, PUNC, PUNC, 0, /* xyz{|}~ */ >+B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 128-135 */ >+B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_CAPSYM, /* 136-143 */ >+B_CAPSYM, B_CAPSYM, B_SYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 144-151 */ >+B_SYM, B_SYM, B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 152-159 */ >+B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_CAPSYM, B_SYM, /* 160-167 */ >+B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 168-175 */ >+B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 176-183 */ >+B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 184-191 */ >+B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 192-199 */ >+B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 200-207 */ >+B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 208-215 */ >+B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 216-223 */ >+B_SYM, B_SYM, B_SYM, B_CAPSYM, B_SYM, B_CAPSYM, B_SYM, B_SYM, /* 224-231 */ >+B_SYM, B_CAPSYM, B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 232-239 */ >+B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 240-247 */ >+B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM /* 248-255 */ >+}; >+ >+static int spk_keydown = 0; >+static u_char spk_lastkey = 0, spk_close_press = 0, keymap_flags = 0; >+static u_char last_keycode = 0, this_speakup_key = 0; >+static u_long last_spk_jiffy = 0; >+ >+struct st_spk_t *speakup_console[MAX_NR_CONSOLES]; >+ >+static int spk_setup(char *str) >+{ >+ int ints[4]; >+ str = get_options(str, ARRAY_SIZE (ints), ints); >+ if (ints[0] > 0 && ints[1] >= 0) >+ synth_port_forced = ints[1]; >+ return 1; >+} >+ >+static int spk_ser_setup(char *str) >+{ >+ const int lookup[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; >+ int ints[4]; >+ str = get_options(str, ARRAY_SIZE (ints), ints); >+ if (ints[0] > 0 && ints[1] >= 0) >+ synth_port_forced = lookup[ints[1]]; >+ return 1; >+} >+ >+static int spk_synth_setup(char *str) >+{ >+ size_t len = min_t(size_t, strlen(str), 9); >+ memcpy (synth_name, str, len); >+ synth_name[len] = '\0'; >+ return 1; >+} >+ >+static int spk_quiet_setup(char *str) >+{ >+ if (strchr("1yt", *str) != NULL) >+ quiet_boot = 1; >+ return 1; >+} >+ >+__setup("speakup_port=", spk_setup); >+__setup("speakup_ser=", spk_ser_setup); >+__setup("speakup_synth=", spk_synth_setup); >+__setup("speakup_quiet=", spk_quiet_setup); >+ >+static unsigned char get_attributes(u16 *pos) >+{ >+ return (u_char)(scr_readw(pos) >> 8); >+} >+ >+static void speakup_date(struct vc_data *vc) >+{ >+ spk_x = spk_cx = vc->vc_x; >+ spk_y = spk_cy = vc->vc_y; >+ spk_pos = spk_cp = vc->vc_pos; >+ spk_old_attr = spk_attr; >+ spk_attr = get_attributes((u_short *) spk_pos); >+} >+ >+char *strlwr(char *s) >+{ >+ char *p; >+ for (p = s; *p; p++) >+ if (*p >= CAP_A && *p <= CAP_Z) >+ *p |= 32; >+ return s; >+} >+ >+static void bleep(u_short val) >+{ >+ static const short vals[] = { >+ 350, 370, 392, 414, 440, 466, 491, 523, 554, 587, 619, 659 >+ }; >+ short freq; >+ int time = bleep_time; >+ freq = vals[val%12]; >+ if (val > 11) >+ freq *= (1 << (val/12)); >+ kd_mksound(freq, time); >+} >+ >+static void speakup_shut_up(struct vc_data *vc) >+{ >+ if (spk_killed) >+ return; >+ spk_shut_up |= 0x01; >+ spk_parked &= 0xfe; >+ speakup_date(vc); >+ if (synth != NULL) >+ do_flush(); >+} >+ >+static void speech_kill(struct vc_data *vc) >+{ >+ char val = synth->is_alive(); >+ if (val == 0) >+ return; >+ >+ /* re-enables synth, if disabled */ >+ if (val == 2 || spk_killed) { /* dead */ >+ spk_shut_up &= ~0x40; >+ synth_write_msg("Eyem a Lighve!"); >+ } else { >+ synth_write_msg("You killed speak up!"); >+ spk_shut_up |= 0x40; >+ } >+} >+ >+static void speakup_off(struct vc_data *vc) >+{ >+ if (spk_shut_up & 0x80) { >+ spk_shut_up &= 0x7f; >+ synth_write_msg("hey. That's better!" ); >+ } else { >+ spk_shut_up |= 0x80; >+ synth_write_msg("You turned me off!" ); >+ } >+ speakup_date(vc); >+} >+ >+static void speakup_parked(struct vc_data *vc) >+{ >+ if (spk_parked & 0x80) { >+ spk_parked = 0; >+ synth_write_msg ("unparked!"); >+ } else { >+ spk_parked |= 0x80; >+ synth_write_msg ("parked!"); >+ } >+} >+ >+/* ------ cut and paste ----- */ >+/* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */ >+#undef isspace >+#define isspace(c) ((c) == ' ') >+/* Variables for selection control. */ >+static struct vc_data *spk_sel_cons; /* defined in selection.c must not be disallocated */ >+static volatile int sel_start = -1; /* cleared by clear_selection */ >+static int sel_end; >+static int sel_buffer_lth; >+static char *sel_buffer; >+ >+static unsigned char sel_pos(int n) >+{ >+ return inverse_translate(spk_sel_cons, screen_glyph(spk_sel_cons, n)); >+} >+ >+static u16 get_char(struct vc_data *vc, u16 *pos) >+{ >+ u16 ch = ' '; >+ if (vc && pos) { >+ u16 w = scr_readw(pos); >+ u16 c = w & 0xff; >+ >+ if (w & vc->vc_hi_font_mask) >+ c |= 0x100; >+ >+ ch = w & 0xff00; >+ ch |= inverse_translate(vc, c); >+ } >+ return ch; >+} >+ >+static void speakup_clear_selection(void) >+{ >+ sel_start = -1; >+} >+ >+/* does screen address p correspond to character at LH/RH edge of screen? */ >+static int atedge(const int p, int size_row) >+{ >+ return (!(p % size_row) || !((p + 2) % size_row)); >+} >+ >+/* constrain v such that v <= u */ >+static unsigned short limit(const unsigned short v, const unsigned short u) >+{ >+ return (v > u) ? u : v; >+} >+ >+static unsigned short xs, ys, xe, ye; /* our region points */ >+ >+static int speakup_set_selection(struct tty_struct *tty) >+{ >+ int new_sel_start, new_sel_end; >+ char *bp, *obp; >+ int i, ps, pe; >+ struct vc_data *vc = vc_cons[fg_console].d; >+ >+ xs = limit(xs, vc->vc_cols - 1); >+ ys = limit(ys, vc->vc_rows - 1); >+ xe = limit(xe, vc->vc_cols - 1); >+ ye = limit(ye, vc->vc_rows - 1); >+ ps = ys * vc->vc_size_row + (xs << 1); >+ pe = ye * vc->vc_size_row + (xe << 1); >+ >+ if (ps > pe) { /* make sel_start <= sel_end */ >+ int tmp = ps; >+ ps = pe; >+ pe = tmp; >+ } >+ >+ if (spk_sel_cons != vc_cons[fg_console].d) { >+ speakup_clear_selection(); >+ spk_sel_cons = vc_cons[fg_console].d; >+ printk(KERN_WARNING "Selection: mark console not the same as cut\n"); >+ return -EINVAL; >+ } >+ >+ new_sel_start = ps; >+ new_sel_end = pe; >+ >+ /* select to end of line if on trailing space */ >+ if (new_sel_end > new_sel_start && >+ !atedge(new_sel_end, vc->vc_size_row) && >+ isspace(sel_pos(new_sel_end))) { >+ for (pe = new_sel_end + 2; ; pe += 2) >+ if (!isspace(sel_pos(pe)) || >+ atedge(pe, vc->vc_size_row)) >+ break; >+ if (isspace(sel_pos(pe))) >+ new_sel_end = pe; >+ } >+ if ((new_sel_start == sel_start) && (new_sel_end == sel_end)) >+ return 0; /* no action required */ >+ >+ sel_start = new_sel_start; >+ sel_end = new_sel_end; >+ /* Allocate a new buffer before freeing the old one ... */ >+ bp = kmalloc((sel_end-sel_start)/2+1, GFP_ATOMIC); >+ if (!bp) { >+ printk(KERN_WARNING "selection: kmalloc() failed\n"); >+ speakup_clear_selection(); >+ return -ENOMEM; >+ } >+ if (sel_buffer) >+ kfree(sel_buffer); >+ sel_buffer = bp; >+ >+ obp = bp; >+ for (i = sel_start; i <= sel_end; i += 2) { >+ *bp = sel_pos(i); >+ if (!isspace(*bp++)) >+ obp = bp; >+ if (! ((i + 2) % vc->vc_size_row)) { >+ /* strip trailing blanks from line and add newline, >+ unless non-space at end of line. */ >+ if (obp != bp) { >+ bp = obp; >+ *bp++ = '\r'; >+ } >+ obp = bp; >+ } >+ } >+ sel_buffer_lth = bp - sel_buffer; >+ return 0; >+} >+ >+static int speakup_paste_selection(struct tty_struct *tty) >+{ >+ struct vc_data *vc = (struct vc_data *) tty->driver_data; >+ int pasted = 0, count; >+ DECLARE_WAITQUEUE(wait, current); >+ add_wait_queue(&vc->paste_wait, &wait); >+ while (sel_buffer && sel_buffer_lth > pasted) { >+ set_current_state(TASK_INTERRUPTIBLE); >+ if (test_bit(TTY_THROTTLED, &tty->flags)) { >+ schedule(); >+ continue; >+ } >+ count = sel_buffer_lth - pasted; >+ count = min_t(int, count, tty->receive_room); >+ tty->ldisc.receive_buf(tty, sel_buffer + pasted, 0, count); >+ pasted += count; >+ } >+ remove_wait_queue(&vc->paste_wait, &wait); >+ current->state = TASK_RUNNING; >+ return 0; >+} >+ >+static void speakup_cut(struct vc_data *vc) >+{ >+ static const char err_buf[] = "set selection failed"; >+ int ret; >+ >+ if (!mark_cut_flag) { >+ mark_cut_flag = 1; >+ xs = spk_x; >+ ys = spk_y; >+ spk_sel_cons = vc; >+ synth_write_msg("mark"); >+ return; >+ } >+ xe = (u_short) spk_x; >+ ye = (u_short) spk_y; >+ mark_cut_flag = 0; >+ synth_write_msg ("cut"); >+ >+ speakup_clear_selection(); >+ ret = speakup_set_selection(tty); >+ >+ switch (ret) { >+ case 0: >+ break; /* no error */ >+ case -EFAULT : >+ pr_warn( "%sEFAULT\n", err_buf ); >+ break; >+ case -EINVAL : >+ pr_warn( "%sEINVAL\n", err_buf ); >+ break; >+ case -ENOMEM : >+ pr_warn( "%sENOMEM\n", err_buf ); >+ break; >+ } >+} >+ >+static void speakup_paste(struct vc_data *vc) >+{ >+ if (mark_cut_flag) { >+ mark_cut_flag = 0; >+ synth_write_msg("mark, cleared"); >+ } else { >+ synth_write_msg ("paste"); >+ speakup_paste_selection(tty); >+ } >+} >+ >+static void say_attributes(struct vc_data *vc ) >+{ >+ int fg = spk_attr & 0x0f; >+ int bg = spk_attr>>4; >+ if (fg > 8) { >+ synth_write_string("bright "); >+ fg -= 8; >+ } >+ synth_write_string(colors[fg]); >+ if (bg > 7) { >+ synth_write_string(" on blinking "); >+ bg -= 8; >+ } else >+ synth_write_string(" on "); >+ synth_write_msg(colors[bg]); >+} >+ >+static char *blank_msg = "blank"; >+static char *edges[] = { "top, ", "bottom, ", "left, ", "right, ", "" }; >+enum { >+ edge_top = 1, >+ edge_bottom, >+ edge_left, >+ edge_right, >+ edge_quiet >+}; >+ >+static void announce_edge(struct vc_data *vc, int msg_id) >+{ >+ if (bleeps & 1) >+ bleep(spk_y); >+ if (bleeps & 2) >+ synth_write_msg(edges[msg_id-1]); >+} >+ >+static void speak_char( u_char ch) >+{ >+ char *cp = characters[ch]; >+ if (cp == NULL) { >+ pr_info ("speak_char: cp==NULL!\n"); >+ return; >+ } >+ synth_buffer_add(SPACE); >+ if (IS_CHAR(ch, B_CAP)) { >+ pitch_shift++; >+ synth_write_string(str_caps_start); >+ synth_write_string(cp); >+ synth_write_string(str_caps_stop); >+ } else { >+ if (*cp == '^') { >+ synth_write_string(str_ctl); >+ cp++; >+ } >+ synth_write_string(cp); >+ } >+ synth_buffer_add(SPACE); >+} >+ >+static void say_char(struct vc_data *vc) >+{ >+ u_short ch; >+ spk_old_attr = spk_attr; >+ ch = get_char(vc, (u_short *) spk_pos); >+ spk_attr = (ch >> 8); >+ if (spk_attr != spk_old_attr) { >+ if (attrib_bleep & 1) >+ bleep(spk_y); >+ if (attrib_bleep & 2) >+ say_attributes(vc); >+ } >+ speak_char(ch & 0xff); >+} >+ >+static void say_phonetic_char(struct vc_data *vc) >+{ >+ u_short ch; >+ spk_old_attr = spk_attr; >+ ch = get_char(vc, (u_short *) spk_pos); >+ spk_attr = ((ch & 0xff00) >> 8); >+ if (IS_CHAR(ch, B_ALPHA)) { >+ ch &= 0x1f; >+ synth_write_msg(phonetic[--ch] ); >+ } else { >+ if (IS_CHAR(ch, B_NUM)) >+ synth_write_string("number "); >+ speak_char(ch); >+ } >+} >+ >+static void say_prev_char(struct vc_data *vc) >+{ >+ spk_parked |= 0x01; >+ if (spk_x == 0) { >+ announce_edge(vc, edge_left); >+ return; >+ } >+ spk_x--; >+ spk_pos -= 2; >+ say_char(vc); >+} >+ >+static void say_next_char(struct vc_data *vc) >+{ >+ spk_parked |= 0x01; >+ if (spk_x == vc->vc_cols - 1) { >+ announce_edge(vc, edge_right); >+ return; >+ } >+ spk_x++; >+ spk_pos += 2; >+ say_char(vc); >+} >+ >+/* get_word - will first check to see if the character under the >+ reading cursor is a space and if say_word_ctl is true it will >+ return the word space. If say_word_ctl is not set it will check to >+ see if there is a word starting on the next position to the right >+ and return that word if it exists. If it does not exist it will >+ move left to the beginning of any previous word on the line or the >+ beginning off the line whichever comes first.. */ >+ >+static u_long get_word(struct vc_data *vc) >+{ >+ u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos; >+ char ch; >+ u_short attr_ch; >+ spk_old_attr = spk_attr; >+ ch = (char) get_char(vc, (u_short *) tmp_pos); >+ >+/* decided to take out the sayword if on a space (mis-information */ >+ if (say_word_ctl && ch == SPACE) { >+ *buf = '\0'; >+ synth_write_msg("space"); >+ return 0; >+ } else if ((tmpx < vc->vc_cols - 2) >+ && (ch == SPACE || IS_WDLM(ch )) >+ && ((char) get_char (vc, (u_short * ) tmp_pos+1 ) > SPACE)) { >+ tmp_pos += 2; >+ tmpx++; >+ } else >+ while (tmpx > 0 ) { >+ ch = (char) get_char(vc, (u_short *) tmp_pos - 1); >+ if ((ch == SPACE || IS_WDLM(ch)) >+ && ((char) get_char(vc, (u_short *) tmp_pos) > SPACE)) >+ break; >+ tmp_pos -= 2; >+ tmpx--; >+ } >+ attr_ch = get_char(vc, (u_short *) tmp_pos); >+ spk_attr = attr_ch >> 8; >+ buf[cnt++] = attr_ch & 0xff; >+ while (tmpx < vc->vc_cols - 1) { >+ tmp_pos += 2; >+ tmpx++; >+ ch = (char) get_char(vc, (u_short *) tmp_pos); >+ if ((ch == SPACE) || (IS_WDLM(buf[cnt-1]) && (ch > SPACE))) >+ break; >+ buf[cnt++] = ch; >+ } >+ buf[cnt] = '\0'; >+ return cnt; >+} >+ >+static void say_word(struct vc_data *vc) >+{ >+ u_long cnt = get_word(vc ); >+ u_short saved_punc_mask = punc_mask; >+ if (cnt == 0) >+ return; >+ punc_mask = PUNC; >+ buf[cnt++] = SPACE; >+ spkup_write(buf, cnt); >+ punc_mask = saved_punc_mask; >+} >+ >+static void say_prev_word(struct vc_data *vc) >+{ >+ char ch; >+ u_short edge_said = 0, last_state = 0, state = 0; >+ spk_parked |= 0x01; >+ if (spk_x == 0) { >+ if (spk_y == 0) { >+ announce_edge(vc, edge_top); >+ return; >+ } >+ spk_y--; >+ spk_x = vc->vc_cols; >+ edge_said = edge_quiet; >+ } >+ while (1) { >+ if (spk_x == 0) { >+ if (spk_y == 0) { >+ edge_said = edge_top; >+ break; >+ } >+ if (edge_said != edge_quiet) >+ edge_said = edge_left; >+ if (state > 0) >+ break; >+ spk_y--; >+ spk_x = vc->vc_cols - 1; >+ } else spk_x--; >+ spk_pos -= 2; >+ ch = (char) get_char(vc, (u_short *) spk_pos); >+ if (ch == SPACE) >+ state = 0; >+ else if (IS_WDLM(ch)) >+ state = 1; >+ else state = 2; >+ if (state < last_state) { >+ spk_pos += 2; >+ spk_x++; >+ break; >+ } >+ last_state = state; >+ } >+ if (spk_x == 0 && edge_said == edge_quiet) >+ edge_said = edge_left; >+ if (edge_said > 0 && edge_said < edge_quiet) >+ announce_edge(vc, edge_said); >+ say_word(vc); >+} >+ >+static void say_next_word(struct vc_data *vc) >+{ >+ char ch; >+ u_short edge_said = 0, last_state = 2, state = 0; >+ spk_parked |= 0x01; >+ if (spk_x == vc->vc_cols - 1 && spk_y == vc->vc_rows - 1) { >+ announce_edge(vc, edge_bottom); >+ return; >+ } >+ while (1) { >+ ch = (char) get_char(vc, (u_short *) spk_pos ); >+ if (ch == SPACE) >+ state = 0; >+ else if (IS_WDLM(ch)) >+ state = 1; >+ else state = 2; >+ if (state > last_state) break; >+ if (spk_x >= vc->vc_cols - 1) { >+ if (spk_y == vc->vc_rows - 1) { >+ edge_said = edge_bottom; >+ break; >+ } >+ state = 0; >+ spk_y++; >+ spk_x = 0; >+ edge_said = edge_right; >+ } else spk_x++; >+ spk_pos += 2; >+ last_state = state; >+ } >+ if (edge_said > 0) >+ announce_edge(vc, edge_said); >+ say_word(vc); >+} >+ >+static void spell_word(struct vc_data *vc) >+{ >+ static char *delay_str[] = { " ", ", ", ". ", ". . ", ". . . " }; >+ char *cp = buf, *str_cap = str_caps_stop; >+ char *cp1, *last_cap = str_caps_stop; >+ u_char ch; >+ if (!get_word(vc)) >+ return; >+ while ((ch = (u_char) *cp)) { >+ if (cp != buf) >+ synth_write_string(delay_str[spell_delay]); >+ if (IS_CHAR(ch, B_CAP)) { >+ str_cap = str_caps_start; >+ if (*str_caps_stop) >+ pitch_shift++; >+ else /* synth has no pitch */ >+ last_cap = str_caps_stop; >+ } else >+ str_cap = str_caps_stop; >+ if (str_cap != last_cap) { >+ synth_write_string(str_cap); >+ last_cap = str_cap; >+ } >+ if (this_speakup_key == SPELL_PHONETIC >+ && (IS_CHAR(ch, B_ALPHA))) { >+ ch &= 31; >+ cp1 = phonetic[--ch]; >+ } else { >+ cp1 = characters[ch]; >+ if (*cp1 == '^') { >+ synth_write_string(str_ctl); >+ cp1++; >+ } >+ } >+ synth_write_string(cp1); >+ cp++; >+ } >+ if (str_cap != str_caps_stop) >+ synth_write_string(str_caps_stop); >+} >+ >+static int get_line(struct vc_data *vc) >+{ >+ u_long tmp = spk_pos - (spk_x * 2); >+ int i = 0; >+ spk_old_attr = spk_attr; >+ spk_attr = get_attributes((u_short *) spk_pos); >+ for (i = 0; i < vc->vc_cols; i++) { >+ buf[i] = (u_char) get_char(vc, (u_short *) tmp); >+ tmp += 2; >+ } >+ for (--i; i >= 0; i--) >+ if (buf[i] != SPACE) >+ break; >+ return ++i; >+} >+ >+static void say_line(struct vc_data *vc) >+{ >+ int i = get_line(vc); >+ char *cp; >+ char num_buf[8]; >+ u_short saved_punc_mask = punc_mask; >+ if (i == 0) { >+ synth_write_msg(blank_msg); >+ return; >+ } >+ buf[i++] = '\n'; >+ if (this_speakup_key == SAY_LINE_INDENT) { >+ for (cp = buf; *cp == SPACE; cp++) >+ ; >+ sprintf(num_buf, "%d, ", (cp - buf) + 1); >+ synth_write_string(num_buf); >+ } >+ punc_mask = punc_masks[reading_punc]; >+ spkup_write(buf, i); >+ punc_mask = saved_punc_mask; >+} >+ >+static void say_prev_line(struct vc_data *vc) >+{ >+ spk_parked |= 0x01; >+ if (spk_y == 0) { >+ announce_edge(vc, edge_top); >+ return; >+ } >+ spk_y--; >+ spk_pos -= vc->vc_size_row; >+ say_line(vc); >+} >+ >+static void say_next_line(struct vc_data *vc) >+{ >+ spk_parked |= 0x01; >+ if (spk_y == vc->vc_rows - 1) { >+ announce_edge(vc, edge_bottom); >+ return; >+ } >+ spk_y++; >+ spk_pos += vc->vc_size_row; >+ say_line(vc); >+} >+ >+static int say_from_to(struct vc_data *vc, u_long from, u_long to, >+ int read_punc) >+{ >+ int i = 0; >+ u_short saved_punc_mask = punc_mask; >+ spk_old_attr = spk_attr; >+ spk_attr = get_attributes((u_short *) from); >+ while (from < to) { >+ buf[i++] = (char) get_char(vc, (u_short *) from); >+ from += 2; >+ if (i >= vc->vc_size_row) >+ break; >+ } >+ for (--i; i >= 0; i--) >+ if (buf[i] != SPACE) >+ break; >+ buf[++i] = SPACE; >+ buf[++i] = '\0'; >+ if (i < 1) >+ return i; >+ if (read_punc) >+ punc_mask = punc_info[reading_punc].mask; >+ spkup_write(buf, i); >+ if (read_punc) >+ punc_mask = saved_punc_mask; >+ return i - 1; >+} >+ >+static void say_line_from_to(struct vc_data *vc, u_long from, u_long to, >+ int read_punc) >+{ >+ u_long start = vc->vc_origin + (spk_y * vc->vc_size_row); >+ u_long end = start + (to * 2); >+ start += from * 2; >+ if (say_from_to(vc, start, end, read_punc) <= 0) >+ if (cursor_track != read_all_mode) >+ synth_write_msg(blank_msg); >+} >+ >+// Sentence Reading Commands >+ >+void synth_insert_next_index(int); >+ >+static int currsentence; >+static int numsentences[2]; >+static char *sentbufend[2]; >+static char *sentmarks[2][10]; >+static int currbuf=0; >+static int bn; >+static char sentbuf[2][256]; >+ >+static int say_sentence_num(int num , int prev) >+{ >+ bn = currbuf; >+ currsentence = num + 1; >+ if (prev && --bn == -1) >+ bn = 1; >+ >+ if (num > numsentences[bn]) >+ return 0; >+ >+ spkup_write(sentmarks[bn][num], sentbufend[bn] - sentmarks[bn][num]); >+ return 1; >+} >+ >+static int get_sentence_buf(struct vc_data *vc, int read_punc) >+{ >+ u_long start, end; >+ int i, bn; >+ currbuf++; >+ if (currbuf == 2) >+ currbuf = 0; >+ bn = currbuf; >+ start = vc->vc_origin + ((spk_y) *vc->vc_size_row); >+ end = vc->vc_origin+((spk_y) *vc->vc_size_row) + vc->vc_cols * 2; >+ >+ numsentences[bn] = 0; >+ sentmarks[bn][0] = &sentbuf[bn][0]; >+ i = 0; >+ spk_old_attr = spk_attr; >+ spk_attr = get_attributes((u_short *) start); >+ >+ while (start < end) { >+ sentbuf[bn][i] = (char) get_char(vc, (u_short *) start); >+ if (i > 0) { >+ if (sentbuf[bn][i] == SPACE && sentbuf[bn][i-1] == '.' >+ && numsentences[bn] < 9) { >+ // Sentence Marker >+ numsentences[bn]++; >+ sentmarks[bn][numsentences[bn]] = >+ &sentbuf[bn][i]; >+ } >+ } >+ i++; >+ start += 2; >+ if (i >= vc->vc_size_row) >+ break; >+ } >+ >+ for (--i; i >= 0; i--) >+ if (sentbuf[bn][i] != SPACE) >+ break; >+ >+ if (i < 1) >+ return -1; >+ >+ sentbuf[bn][++i] = SPACE; >+ sentbuf[bn][++i] = '\0'; >+ >+ sentbufend[bn] = &sentbuf[bn][i]; >+ return numsentences[bn]; >+} >+ >+static void say_screen_from_to(struct vc_data *vc, u_long from, u_long to) >+{ >+ u_long start = vc->vc_origin, end; >+ if (from > 0) >+ start += from * vc->vc_size_row; >+ if (to > vc->vc_rows) >+ to = vc->vc_rows; >+ end = vc->vc_origin + (to * vc->vc_size_row); >+ for (from = start; from < end; from = to) { >+ to = from + vc->vc_size_row; >+ say_from_to(vc, from, to, 1); >+ } >+} >+ >+static void say_screen(struct vc_data *vc) >+{ >+ say_screen_from_to(vc, 0, vc->vc_rows); >+} >+ >+static void speakup_win_say(struct vc_data *vc) >+{ >+ u_long start, end, from, to; >+ if (win_start < 2) { >+ synth_write_msg("no window"); >+ return; >+ } >+ start = vc->vc_origin + (win_top * vc->vc_size_row); >+ end = vc->vc_origin + (win_bottom * vc->vc_size_row); >+ while (start <= end) { >+ from = start + (win_left * 2); >+ to = start + (win_right * 2); >+ say_from_to(vc, from, to, 1); >+ start += vc->vc_size_row; >+ } >+} >+ >+static void top_edge (struct vc_data *vc) >+{ >+ spk_parked |= 0x01; >+ spk_pos = vc->vc_origin + 2 * spk_x; >+ spk_y = 0; >+ say_line(vc); >+} >+ >+static void bottom_edge(struct vc_data *vc) >+{ >+ spk_parked |= 0x01; >+ spk_pos += (vc->vc_rows - spk_y - 1) * vc->vc_size_row; >+ spk_y = vc->vc_rows - 1; >+ say_line(vc); >+} >+ >+static void left_edge(struct vc_data *vc) >+{ >+ spk_parked |= 0x01; >+ spk_pos -= spk_x * 2; >+ spk_x = 0; >+ say_char (vc ); >+} >+ >+static void right_edge(struct vc_data *vc) >+{ >+ spk_parked |= 0x01; >+ spk_pos += (vc->vc_cols - spk_x - 1) * 2; >+ spk_x = vc->vc_cols - 1; >+ say_char(vc); >+} >+ >+static void say_first_char(struct vc_data *vc) >+{ >+ int i, len = get_line(vc); >+ u_char ch; >+ spk_parked |= 0x01; >+ if (len == 0) { >+ synth_write_msg(blank_msg); >+ return; >+ } >+ for (i = 0; i < len; i++) >+ if (buf[i] != SPACE) >+ break; >+ ch = buf[i]; >+ spk_pos -= (spk_x - i) * 2; >+ spk_x = i; >+ sprintf(buf, "%d, ", ++i); >+ synth_write_string(buf); >+ speak_char(ch); >+} >+ >+static void say_last_char(struct vc_data *vc) >+{ >+ int len = get_line(vc); >+ u_char ch; >+ spk_parked |= 0x01; >+ if (len == 0) { >+ synth_write_msg(blank_msg); >+ return; >+ } >+ ch = buf[--len]; >+ spk_pos -= (spk_x - len) * 2; >+ spk_x = len; >+ sprintf (buf, "%d, ", ++len); >+ synth_write_string(buf); >+ speak_char(ch); >+} >+ >+static void say_position(struct vc_data *vc) >+{ >+ sprintf(buf, "line %ld, col %ld, t t y %d\n", spk_y + 1, spk_x + 1, >+ vc->vc_num + 1); >+ synth_write_string(buf); >+} >+ >+// Added by brianb >+static void say_char_num(struct vc_data *vc) >+{ >+ u_short ch = get_char(vc, (u_short *) spk_pos); >+ ch &= 0xff; >+ sprintf(buf, "hex %02x, decimal %d", ch, ch); >+ synth_write_msg(buf); >+} >+ >+/* these are stub functions to keep keyboard.c happy. */ >+ >+static void say_from_top(struct vc_data *vc) >+{ >+ say_screen_from_to(vc, 0, spk_y); >+} >+ >+static void say_to_bottom(struct vc_data *vc) >+{ >+ say_screen_from_to(vc, spk_y, vc->vc_rows); >+} >+ >+static void say_from_left(struct vc_data *vc) >+{ >+ say_line_from_to(vc, 0, spk_x, 1); >+} >+ >+static void say_to_right(struct vc_data *vc) >+{ >+ say_line_from_to(vc, spk_x, vc->vc_cols, 1); >+} >+ >+/* end of stub functions. */ >+ >+static void spkup_write(const char *in_buf, int count) >+{ >+ static int rep_count = 0; >+ static u_char ch = '\0', old_ch = '\0'; >+ static u_short char_type = 0, last_type = 0; >+ static u_char *exn_ptr = NULL; >+ int in_count = count; >+ char rpt_buf[32]; >+ spk_keydown = 0; >+ while ( count-- ) { >+ if ( cursor_track == read_all_mode ) { >+ // Insert Sentence Index >+ if (( in_buf == sentmarks[bn][currsentence] ) && >+ ( currsentence <= numsentences[bn] )) >+ synth_insert_next_index(currsentence++); >+ } >+ ch = (u_char )*in_buf++; >+ char_type = spk_chartab[ch]; >+ if (ch == old_ch && !(char_type&B_NUM ) ) { >+ if (++rep_count > 2 ) continue; >+ } else { >+ if ( (last_type&CH_RPT) && rep_count > 2 ) { >+ sprintf (rpt_buf, " times %d . ", ++rep_count ); >+ synth_write_string (rpt_buf ); >+ } >+ rep_count = 0; >+ } >+ if ( !( char_type&B_NUM ) ) >+ exn_ptr = NULL; >+ if (ch == spk_lastkey ) { >+ rep_count = 0; >+ if ( key_echo == 1 && ch >= MINECHOCHAR ) >+ speak_char( ch ); >+ } else if ( ( char_type&B_ALPHA ) ) { >+ if ( (synth_flags&SF_DEC) && (last_type&PUNC) ) >+ synth_buffer_add ( SPACE ); >+ synth_write( &ch, 1 ); >+ } else if ( ( char_type&B_NUM ) ) { >+ rep_count = 0; >+ if ( (last_type&B_EXNUM) && synth_buff_in == exn_ptr+1 ) { >+ synth_buff_in--; >+ synth_buffer_add( old_ch ); >+ exn_ptr = NULL; >+ } >+ synth_write( &ch, 1 ); >+ } else if ( (char_type&punc_mask) ) { >+ speak_char( ch ); >+ char_type &= ~PUNC; /* for dec nospell processing */ >+ } else if ( ( char_type&SYNTH_OK ) ) { >+/* these are usually puncts like . and , which synth needs for expression. >+ * suppress multiple to get rid of long pausesand clear repeat count so if >+ *someone has repeats on you don't get nothing repeated count */ >+ if ( ch != old_ch ) >+ synth_write( &ch, 1 ); >+ else rep_count = 0; >+ } else { >+ if ( ( char_type&B_EXNUM ) ) >+ exn_ptr = (u_char *)synth_buff_in; >+/* send space and record position, if next is num overwrite space */ >+ if ( old_ch != ch ) synth_buffer_add ( SPACE ); >+ else rep_count = 0; >+ } >+ old_ch = ch; >+ last_type = char_type; >+ } >+ spk_lastkey = 0; >+ if (in_count > 2 && rep_count > 2 ) { >+ if ( (last_type&CH_RPT) ) { >+ sprintf (rpt_buf, " repeated %d . ", ++rep_count ); >+ synth_write_string (rpt_buf ); >+ } >+ rep_count = 0; >+ } >+} >+ >+static char *ctl_key_ids[] = { >+ "shift", "altgr", "control", "ault", "l shift", "speakup", >+"l control", "r control" >+}; >+#define NUM_CTL_LABELS 8 >+ >+static void read_all_doc(struct vc_data *vc); >+static void cursor_stop_timer(void); >+ >+static void handle_shift(struct vc_data *vc, u_char value, char up_flag) >+{ >+ (*do_shift)(vc, value, up_flag); >+ if (synth == NULL || up_flag || spk_killed) >+ return; >+ if (cursor_track == read_all_mode) { >+ switch (value) { >+ case KVAL(K_SHIFT): >+ cursor_stop_timer(); >+ spk_shut_up &= 0xfe; >+ do_flush(); >+ read_all_doc(vc); >+ break; >+ case KVAL(K_CTRL): >+ cursor_stop_timer(); >+ cursor_track=prev_cursor_track; >+ spk_shut_up &= 0xfe; >+ do_flush(); >+ break; >+ } >+ } else { >+ spk_shut_up &= 0xfe; >+ do_flush(); >+ } >+ if (say_ctrl && value < NUM_CTL_LABELS) >+ synth_write_string(ctl_key_ids[value]); >+} >+ >+static void handle_latin(struct vc_data *vc, u_char value, char up_flag) >+{ >+ (*do_latin)(vc, value, up_flag); >+ if (up_flag) { >+ spk_lastkey = spk_keydown = 0; >+ return; >+ } >+ if (synth == NULL || spk_killed) >+ return; >+ spk_shut_up &= 0xfe; >+ spk_lastkey = value; >+ spk_keydown++; >+ spk_parked &= 0xfe; >+ if (key_echo == 2 && value >= MINECHOCHAR) >+ speak_char( value ); >+} >+ >+static int set_key_info(const u_char *key_info, u_char *k_buffer) >+{ >+ int i = 0, states, key_data_len; >+ const u_char *cp = key_info; >+ u_char *cp1 = k_buffer; >+ u_char ch, version, num_keys; >+ version = *cp++; >+ if (version != KEY_MAP_VER) >+ return -1; >+ num_keys = *cp; >+ states = (int) cp[1]; >+ key_data_len = (states + 1) * (num_keys + 1); >+ if (key_data_len + SHIFT_TBL_SIZE + 4 >= sizeof(key_buf)) >+ return -2; >+ memset(k_buffer, 0, SHIFT_TBL_SIZE); >+ memset(our_keys, 0, sizeof(our_keys)); >+ shift_table = k_buffer; >+ our_keys[0] = shift_table; >+ cp1 += SHIFT_TBL_SIZE; >+ memcpy(cp1, cp, key_data_len + 3); >+ /* get num_keys, states and data*/ >+ cp1 += 2; /* now pointing at shift states */ >+ for (i = 1; i <= states; i++) { >+ ch = *cp1++; >+ if (ch >= SHIFT_TBL_SIZE) >+ return -3; >+ shift_table[ch] = i; >+ } >+ keymap_flags = *cp1++; >+ while ((ch = *cp1)) { >+ if (ch >= MAX_KEY) >+ return -4; >+ our_keys[ch] = cp1; >+ cp1 += states + 1; >+ } >+ return 0; >+} >+ >+static struct st_num_var spk_num_vars[] = { /* bell must be first to set high limit */ >+ { BELL_POS, 0, 0, 0, 0, 0, 0, 0 }, >+ { SPELL_DELAY, 0, 0, 0, 5, 0, 0, 0 }, >+ { ATTRIB_BLEEP, 0, 1, 0, 3, 0, 0, 0 }, >+ { BLEEPS, 0, 3, 0, 3, 0, 0, 0 }, >+ { BLEEP_TIME, 0, 30, 1, 200, 0, 0, 0 }, >+ { PUNC_LEVEL, 0, 1, 0, 4, 0, 0, 0 }, >+ { READING_PUNC, 0, 1, 0, 4, 0, 0, 0 }, >+ { CURSOR_TIME, 0, 120, 50, 600, 0, 0, 0 }, >+ { SAY_CONTROL, TOGGLE_0 }, >+ { SAY_WORD_CTL, TOGGLE_0 }, >+ { NO_INTERRUPT, TOGGLE_0 }, >+ { KEY_ECHO, 0, 1, 0, 2, 0, 0, 0 }, >+ V_LAST_NUM >+}; >+ >+static char *cursor_msgs[] = { "cursoring off", "cursoring on", >+ "highlight tracking", "read windo", >+"read all" }; >+ >+static void toggle_cursoring(struct vc_data *vc) >+{ >+ if (cursor_track == read_all_mode) >+ cursor_track = prev_cursor_track; >+ if (++cursor_track >= CT_Max) >+ cursor_track = 0; >+ synth_write_msg(cursor_msgs[cursor_track]); >+} >+ >+static void reset_default_chars(void) >+{ >+ int i; >+ if (default_chars[(int )'a'] == NULL) /* lowers are null first time */ >+ for (i = (int )'a'; default_chars[i] == NULL; i++) >+ default_chars[i] = default_chars[i - 32]; >+ else /* free any non-default */ >+ for (i = 0; i < 256; i++) { >+ if (characters[i] != default_chars[i]) >+ kfree(characters[i]); >+ } >+ memcpy(characters, default_chars, sizeof(default_chars)); >+} >+ >+static void reset_default_chartab(void) >+{ >+ memcpy(spk_chartab, default_chartab, sizeof(default_chartab)); >+} >+ >+static void handle_cursor(struct vc_data *vc, u_char value, char up_flag); >+static void handle_spec(struct vc_data *vc, u_char value, char up_flag); >+static void cursor_done(u_long data ); >+ >+static declare_timer(cursor_timer); >+ >+static void __init speakup_open(struct vc_data *vc, >+ struct st_spk_t *first_console) >+{ >+ int i; >+ struct st_num_var *n_var; >+ >+ reset_default_chars(); >+ reset_default_chartab(); >+ memset(speakup_console, 0, sizeof(speakup_console)); >+ if (first_console == NULL) >+ return; >+ speakup_console[vc->vc_num] = first_console; >+ speakup_date(vc); >+ pr_info("%s: initialized\n", SPEAKUP_VERSION); >+ init_timer(&cursor_timer); >+ cursor_timer.entry.prev = NULL; >+ cursor_timer.function = cursor_done; >+ init_sleeper(synth_sleeping_list); >+ strlwr(synth_name); >+ spk_num_vars[0].high = vc->vc_cols; >+ for (n_var = spk_num_vars; n_var->var_id >= 0; n_var++) >+ speakup_register_var(n_var); >+ for (i = 1; punc_info[i].mask != 0; i++) >+ set_mask_bits(0, i, 2); >+ do_latin = key_handler[KT_LATIN]; >+ key_handler[KT_LATIN] = handle_latin; >+ do_spec = key_handler[KT_SPEC]; >+ key_handler[KT_SPEC] = handle_spec; >+ do_cursor = key_handler[KT_CUR]; >+ key_handler[KT_CUR] = handle_cursor; >+ do_shift = key_handler[KT_SHIFT]; >+ key_handler[KT_SHIFT] = handle_shift; >+ set_key_info(key_defaults, key_buf); >+ if (quiet_boot) spk_shut_up |= 0x01; >+} >+ >+#ifdef CONFIG_PROC_FS >+ >+// speakup /proc interface code >+ >+/* Usage: >+cat /proc/speakup/version >+ >+cat /proc/speakup/characters > foo >+less /proc/speakup/characters >+vi /proc/speakup/characters >+ >+cat foo > /proc/speakup/characters >+cat > /proc/speakup/characters >+echo 39 apostrophe > /proc/speakup/characters >+echo 87 w > /proc/speakup/characters >+echo 119 w > /proc/speakup/characters >+echo defaults > /proc/speakup/characters >+echo reset > /proc/speakup/characters >+ >+ >+cat /proc/speakup/chartab > foo >+less /proc/speakup/chartab >+vi /proc/speakup/chartab >+ >+cat foo > /proc/speakup/chartab >+cat > /proc/speakup/chartab >+echo 233 ALPHA > /proc/speakup/chartab >+echo 46 A_PUNC > /proc/speakup/chartab >+echo defaults > /proc/speakup/chartab >+echo reset > /proc/speakup/chartab >+*/ >+ >+// keymap handlers >+ >+static int keys_read_proc(char *page, char **start, off_t off, int count, >+ int *eof, void *data) >+{ >+ char *cp = page; >+ int i, n, num_keys, nstates; >+ u_char *cp1 = key_buf + SHIFT_TBL_SIZE, ch; >+ num_keys = (int)(*cp1); >+ nstates = (int)cp1[1]; >+ cp += sprintf( cp, "%d, %d, %d,\n", KEY_MAP_VER, num_keys, nstates ); >+ cp1 += 2; /* now pointing at shift states */ >+/* dump num_keys+1 as first row is shift states + flags, >+ each subsequent row is key + states */ >+ for ( n = 0; n <= num_keys; n++ ) { >+ for ( i = 0; i <= nstates; i++ ) { >+ ch = *cp1++; >+ cp += sprintf( cp, "%d,", (int)ch ); >+ *cp++ = ( i < nstates ) ? SPACE : '\n'; >+ } >+ } >+ cp += sprintf( cp, "0, %d\n", KEY_MAP_VER ); >+ *start = 0; >+ *eof = 1; >+ return (int)(cp-page); >+} >+ >+static char * >+s2uchar ( char *start, char *dest ) >+{ >+ int val = 0; >+ while ( *start && *start <= SPACE ) start++; >+ while ( *start >= '0' && *start <= '9' ) { >+ val *= 10; >+ val += ( *start ) - '0'; >+ start++; >+ } >+ if ( *start == ',' ) start++; >+ *dest = (u_char)val; >+ return start; >+} >+ >+static int keys_write_proc(struct file *file, const char *buffer, u_long count, >+ void *data) >+{ >+ int i, ret = count; >+ char *in_buff, *cp; >+ u_char *cp1; >+ if (count < 1 || count > 1800 ) >+ return -EINVAL; >+ in_buff = ( char * ) __get_free_page ( GFP_KERNEL ); >+ if ( !in_buff ) return -ENOMEM; >+ if (copy_from_user (in_buff, buffer, count ) ) { >+ free_page ( ( unsigned long ) in_buff ); >+ return -EFAULT; >+ } >+ if (in_buff[count - 1] == '\n' ) count--; >+ in_buff[count] = '\0'; >+ if ( count == 1 && *in_buff == 'd' ) { >+ free_page ( ( unsigned long ) in_buff ); >+ set_key_info( key_defaults, key_buf ); >+ return ret; >+ } >+ cp = in_buff; >+ cp1 = (u_char *)in_buff; >+ for ( i = 0; i < 3; i++ ) { >+ cp = s2uchar( cp, cp1 ); >+ cp1++; >+ } >+ i = (int)cp1[-2]+1; >+ i *= (int)cp1[-1]+1; >+ i+= 2; /* 0 and last map ver */ >+ if ( cp1[-3] != KEY_MAP_VER || cp1[-1] > 10 || >+ i+SHIFT_TBL_SIZE+4 >= sizeof(key_buf ) ) { >+pr_warn( "i %d %d %d %d\n", i, (int)cp1[-3], (int)cp1[-2], (int)cp1[-1] ); >+ free_page ( ( unsigned long ) in_buff ); >+ return -EINVAL; >+ } >+ while ( --i >= 0 ) { >+ cp = s2uchar( cp, cp1 ); >+ cp1++; >+ if ( !(*cp) ) break; >+ } >+ if ( i != 0 || cp1[-1] != KEY_MAP_VER || cp1[-2] != 0 ) { >+ ret = -EINVAL; >+pr_warn( "end %d %d %d %d\n", i, (int)cp1[-3], (int)cp1[-2], (int)cp1[-1] ); >+ } else { >+ if ( set_key_info( in_buff, key_buf ) ) { >+ set_key_info( key_defaults, key_buf ); >+ ret = -EINVAL; >+pr_warn( "set key failed\n" ); >+ } >+ } >+ free_page ( ( unsigned long ) in_buff ); >+ return ret; >+} >+ >+// this is the handler for /proc/speakup/version >+static int version_read_proc(char *page, char **start, off_t off, int count, >+ int *eof, void *data) >+{ >+ int len = sprintf (page, "%s\n", SPEAKUP_VERSION ); >+ if (synth != NULL) >+ len += sprintf(page+len, "synth %s version %s\n", synth->name, >+ synth->version); >+ *start = 0; >+ *eof = 1; >+ return len; >+} >+ >+// this is the read handler for /proc/speakup/characters >+static int chars_read_proc(char *page, char **start, off_t off, int count, >+ int *eof, void *data) >+{ >+ int i, len = 0; >+ off_t begin = 0; >+ char *cp; >+ for (i = 0; i < 256; i++) { >+ cp = (characters[i]) ? characters[i] : "NULL"; >+ len += sprintf(page + len, "%d\t%s\n", i, cp); >+ if (len + begin > off + count) >+ break; >+ if (len + begin < off) { >+ begin += len; >+ len = 0; >+ } >+ } >+ if (i >= 256) >+ *eof = 1; >+ if (off >= len + begin) >+ return 0; >+ *start = page + (off - begin); >+ return ((count < begin + len - off) ? count : begin + len - off); >+} >+ >+static volatile int chars_timer_active = 0; // indicates when timer is set >+static declare_timer(chars_timer); >+ >+static void chars_stop_timer(void) >+{ >+ if (chars_timer_active) >+ stop_timer(chars_timer); >+} >+ >+static int strings, rejects, updates; >+ >+static void show_char_results (u_long data) >+{ >+ int len; >+ char buf[80]; >+ chars_stop_timer(); >+ len = sprintf(buf, " updated %d of %d character descriptions\n", >+ updates, strings); >+ if (rejects) >+ sprintf(buf + (len - 1), " with %d reject%s\n", >+ rejects, rejects > 1 ? "s" : ""); >+ printk(buf); >+} >+ >+// this is the read handler for /proc/speakup/chartab >+static int chartab_read_proc(char *page, char **start, off_t off, int count, >+ int *eof, void *data) >+{ >+ int i, len = 0; >+ off_t begin = 0; >+ char *cp; >+ for (i = 0; i < 256; i++) { >+ cp = "0"; >+ if (IS_TYPE(i, B_CTL)) >+ cp = "B_CTL"; >+ else if (IS_TYPE(i, WDLM)) >+ cp = "WDLM"; >+ else if (IS_TYPE(i, A_PUNC)) >+ cp = "A_PUNC"; >+ else if (IS_TYPE(i, PUNC)) >+ cp = "PUNC"; >+ else if (IS_TYPE(i, NUM)) >+ cp = "NUM"; >+ else if (IS_TYPE(i, A_CAP)) >+ cp = "A_CAP"; >+ else if (IS_TYPE(i, ALPHA)) >+ cp = "ALPHA"; >+ else if (IS_TYPE(i, B_CAPSYM)) >+ cp = "B_CAPSYM"; >+ else if (IS_TYPE(i, B_SYM)) >+ cp = "B_SYM"; >+ >+ len += sprintf(page + len, "%d\t%s\n", i, cp); >+ if (len + begin > off + count) >+ break; >+ if (len + begin < off) { >+ begin += len; >+ len = 0; >+ } >+ } >+ if (i >= 256) >+ *eof = 1; >+ if (off >= len + begin) >+ return 0; >+ *start = page + (off - begin); >+ return ((count < begin + len - off) ? count : begin + len - off); >+} >+ >+static int chartab_get_value(char *keyword) >+{ >+ int value = 0; >+ >+ if (!strcmp(keyword, "ALPHA")) >+ value = ALPHA; >+ else if (!strcmp(keyword, "B_CTL")) >+ value = B_CTL; >+ else if (!strcmp(keyword, "WDLM")) >+ value = WDLM; >+ else if (!strcmp(keyword, "A_PUNC")) >+ value = A_PUNC; >+ else if (!strcmp(keyword, "PUNC")) >+ value = PUNC; >+ else if (!strcmp(keyword, "NUM")) >+ value = NUM; >+ else if (!strcmp(keyword, "A_CAP")) >+ value = A_CAP; >+ else if (!strcmp(keyword, "B_CAPSYM")) >+ value = B_CAPSYM; >+ else if (!strcmp(keyword, "B_SYM")) >+ value = B_SYM; >+ return value; >+} >+ >+/* this is the write handler for /proc/speakup/silent */ >+static int silent_write_proc(struct file *file, const char *buffer, >+ u_long count, void *data) >+{ >+ struct vc_data *vc = vc_cons[fg_console].d; >+ char ch = 0, shut; >+ if (count > 0 || count < 3 ) { >+ get_user (ch, buffer ); >+ if ( ch == '\n' ) ch = '0'; >+ } >+ if ( ch < '0' || ch > '7' ) { >+ pr_warn ( "silent value not in range (0,7)\n" ); >+ return count; >+ } >+ if ( (ch&2) ) { >+ shut = 1; >+ do_flush( ); >+ } else shut = 0; >+ if ( (ch&4) ) shut |= 0x40; >+ if ( (ch&1) ) >+ spk_shut_up |= shut; >+ else spk_shut_up &= ~shut; >+ return count; >+} >+ >+// this is the write handler for /proc/speakup/characters >+static int chars_write_proc(struct file *file, const char *buffer, >+ u_long count, void *data) >+{ >+#define max_desc_len 72 >+ static int cnt = 0, state = 0; >+ static char desc[max_desc_len + 1]; >+ static u_long jiff_last = 0; >+ short i = 0, num; >+ int len; >+ char ch, *cp, *p_new; >+ // reset certain vars if enough time has elapsed since last called >+ if (jiffies - jiff_last > 10 ) { >+ cnt = state = strings = rejects = updates = 0; >+ } >+ jiff_last = jiffies; >+get_more: >+ desc[cnt] = '\0'; >+ state = 0; >+ for (; i < count && state < 2; i++ ) { >+ get_user (ch, buffer + i ); >+ if ( ch == '\n' ) { >+ desc[cnt] = '\0'; >+ state = 2; >+ } else if (cnt < max_desc_len ) >+ desc[cnt++] = ch; >+ } >+ if (state < 2 ) return count; >+ cp = desc; >+ while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++; >+ if ((!cnt ) || strchr ("dDrR", *cp ) ) { >+ reset_default_chars ( ); >+ pr_info( "character descriptions reset to defaults\n" ); >+ cnt = 0; >+ return count; >+ } >+ cnt = 0; >+ if (*cp == '#' ) goto get_more; >+ num = -1; >+ cp = speakup_s2i(cp, &num ); >+ while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++; >+ if (num < 0 || num > 255 ) { // not in range >+ rejects++; >+ strings++; >+ goto get_more; >+ } >+ if (num >= 27 && num <= 31 ) goto get_more; >+ if (!strcmp(cp, characters[num] ) ) { >+ strings++; >+ goto get_more; >+ } >+ len = strlen(cp ); >+ if (characters[num] == default_chars[num] ) >+ p_new = kmalloc(sizeof (char) * len+1, GFP_KERNEL ); >+ else if ( strlen(characters[num] ) >= len ) >+ p_new = characters[num]; >+ else { >+ kfree(characters[num] ); >+ characters[num] = default_chars[num]; >+ p_new = kmalloc(sizeof (char) * len+1, GFP_KERNEL ); >+ } >+ if (!p_new ) return -ENOMEM; >+ strcpy ( p_new, cp ); >+ characters[num] = p_new; >+ updates++; >+ strings++; >+ if (i < count ) goto get_more; >+ chars_stop_timer ( ); >+ init_timer (&chars_timer ); >+ chars_timer.function = show_char_results; >+ chars_timer.expires = jiffies + 5; >+ start_timer (chars_timer ); >+ chars_timer_active++; >+ return count; >+} >+ >+// this is the write handler for /proc/speakup/chartab >+static int chartab_write_proc(struct file *file, const char *buffer, >+ u_long count, void *data) >+{ >+#define max_desc_len 72 >+ static int cnt = 0, state = 0; >+ static char desc[max_desc_len + 1]; >+ static u_long jiff_last = 0; >+ short i = 0, num; >+ char ch, *cp; >+ int value=0; >+ // reset certain vars if enough time has elapsed since last called >+ if (jiffies - jiff_last > 10 ) { >+ cnt = state = strings = rejects = updates = 0; >+ } >+ jiff_last = jiffies; >+get_more: >+ desc[cnt] = '\0'; >+ state = 0; >+ for (; i < count && state < 2; i++ ) { >+ get_user (ch, buffer + i ); >+ if ( ch == '\n' ) { >+ desc[cnt] = '\0'; >+ state = 2; >+ } else if (cnt < max_desc_len ) >+ desc[cnt++] = ch; >+ } >+ if (state < 2 ) return count; >+ cp = desc; >+ while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++; >+ if ((!cnt ) || strchr ("dDrR", *cp ) ) { >+ reset_default_chartab ( ); >+ pr_info( "character descriptions reset to defaults\n" ); >+ cnt = 0; >+ return count; >+ } >+ cnt = 0; >+ if (*cp == '#' ) goto get_more; >+ num = -1; >+ cp = speakup_s2i(cp, &num ); >+ while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++; >+ if (num < 0 || num > 255 ) { // not in range >+ rejects++; >+ strings++; >+ goto get_more; >+ } >+ /* if (num >= 27 && num <= 31 ) goto get_more; */ >+ >+ value = chartab_get_value (cp); >+ if (!value) { // not in range >+ rejects++; >+ strings++; >+ goto get_more; >+ } >+ >+ if (value==spk_chartab[num]) { >+ strings++; >+ goto get_more; >+ } >+ >+ spk_chartab[num] = value; >+ updates++; >+ strings++; >+ if (i < count ) goto get_more; >+ chars_stop_timer ( ); >+ init_timer (&chars_timer ); >+ chars_timer.function = show_char_results; >+ chars_timer.expires = jiffies + 5; >+ start_timer (chars_timer ); >+ chars_timer_active++; >+ return count; >+} >+ >+static int bits_read_proc(char *page, char **start, off_t off, int count, >+ int *eof, void *data) >+{ >+ int i; >+ struct st_var_header *p_header = data; >+ struct st_proc_var *var = p_header->data; >+ const struct st_bits_data *pb = &punc_info[var->value]; >+ short mask = pb->mask; >+ char *cp = page; >+ *start = 0; >+ *eof = 1; >+ for ( i = 33; i < 128; i++ ) { >+ if ( !(spk_chartab[i]&mask ) ) continue; >+ *cp++ = (char )i; >+ } >+ *cp++ = '\n'; >+ return cp-page; >+} >+ >+/* set_mask_bits sets or clears the punc/delim/repeat bits, >+ * if input is null uses the defaults. >+ * values for how: 0 clears bits of chars supplied, >+ * 1 clears allk, 2 sets bits for chars */ >+ >+static int set_mask_bits(const char *input, const int which, const int how) >+{ >+ u_char *cp; >+ short mask = punc_info[which].mask; >+ if ( how&1 ) { >+ for ( cp = (u_char * )punc_info[3].value; *cp; cp++ ) >+ spk_chartab[*cp] &= ~mask; >+ } >+ cp = (u_char * )input; >+ if ( cp == 0 ) cp = punc_info[which].value; >+ else { >+ for ( ; *cp; cp++ ) { >+ if ( *cp < SPACE ) break; >+ if ( mask < PUNC ) { >+ if ( !(spk_chartab[*cp]&PUNC) ) break; >+ } else if ( (spk_chartab[*cp]&B_NUM) ) break; >+ } >+ if ( *cp ) return -EINVAL; >+ cp = (u_char * )input; >+ } >+ if ( how&2 ) { >+ for ( ; *cp; cp++ ) >+ if ( *cp > SPACE ) spk_chartab[*cp] |= mask; >+ } else { >+ for ( ; *cp; cp++ ) >+ if ( *cp > SPACE ) spk_chartab[*cp] &= ~mask; >+ } >+ return 0; >+} >+ >+static const struct st_bits_data *pb_edit = NULL; >+ >+static int edit_bits (struct vc_data *vc, u_char type, u_char ch, u_short key ) >+{ >+ short mask = pb_edit->mask, ch_type = spk_chartab[ch]; >+ if ( type != KT_LATIN || (ch_type&B_NUM ) || ch < SPACE ) return -1; >+ if ( ch == SPACE ) { >+ synth_write_msg( "edit done" ); >+ special_handler = NULL; >+ return 1; >+ } >+ if ( mask < PUNC && !(ch_type&PUNC) ) return -1; >+ spk_chartab[ch] ^= mask; >+ speak_char( ch ); >+ synth_write_msg( (spk_chartab[ch]&mask ) ? " on" : " off" ); >+ return 1; >+} >+ >+static int bits_write_proc(struct file *file, const char *buffer, u_long count, >+ void *data) >+{ >+ struct st_var_header *p_header = data; >+ struct st_proc_var *var = p_header->data; >+ int ret = count; >+ char punc_buf[100]; >+ if (count < 1 || count > 99 ) >+ return -EINVAL; >+ if (copy_from_user (punc_buf, buffer, count ) ) >+ return -EFAULT; >+ if (punc_buf[count - 1] == '\n' ) >+ count--; >+ punc_buf[count] = '\0'; >+ if ( *punc_buf == 'd' || *punc_buf == 'r' ) >+ count = set_mask_bits( 0, var->value, 3 ); >+ else >+ count = set_mask_bits( punc_buf, var->value, 3 ); >+ if ( count < 0 ) return count; >+ return ret; >+} >+ >+// this is the read handler for /proc/speakup/synth >+static int synth_read_proc(char *page, char **start, off_t off, int count, >+ int *eof, void *data) >+{ >+ int len; >+ if ( synth == NULL ) strcpy( synth_name, "none" ); >+ else strcpy( synth_name, synth->name ); >+ len = sprintf (page, "%s\n", synth_name ); >+ *start = 0; >+ *eof = 1; >+ return len; >+} >+ >+// this is the write handler for /proc/speakup/synth >+static int synth_write_proc(struct file *file, const char *buffer, >+ u_long count, void *data) >+{ >+ int ret = count; >+ char new_synth_name[10]; >+ const char *old_name = ( synth != NULL ) ? synth->name : "none"; >+ if (count < 2 || count > 9 ) >+ return -EINVAL; >+ if (copy_from_user (new_synth_name, buffer, count ) ) >+ return -EFAULT; >+ if (new_synth_name[count - 1] == '\n' ) >+ count--; >+ new_synth_name[count] = '\0'; >+ strlwr (new_synth_name ); >+ if (!strcmp (new_synth_name, old_name ) ) { >+ pr_warn ( "%s already in use\n", new_synth_name ); >+ return ret; >+ } >+ if ( synth_init( new_synth_name ) == 0 ) return ret; >+ pr_warn( "failed to init synth %s\n", new_synth_name ); >+ return -ENODEV; >+} >+ >+struct st_proc_var spk_proc_vars[] = { >+ { VERSION, version_read_proc, 0, 0 }, >+ { SILENT, 0, silent_write_proc, 0 }, >+ { CHARS, chars_read_proc, chars_write_proc, 0 }, >+ { SYNTH, synth_read_proc, synth_write_proc, 0 }, >+ { KEYMAP, keys_read_proc, keys_write_proc, 0 }, >+ { PUNC_SOME, bits_read_proc, bits_write_proc, 1 }, >+ { PUNC_MOST, bits_read_proc, bits_write_proc, 2 }, >+ { PUNC_ALL, bits_read_proc, 0, 3 }, >+ { DELIM, bits_read_proc, bits_write_proc, 4 }, >+ { REPEATS, bits_read_proc, bits_write_proc, 5 }, >+ { EXNUMBER, bits_read_proc, bits_write_proc, 6 }, >+ { CHARTAB, chartab_read_proc, chartab_write_proc, 0 }, >+ { -1, 0, 0, 0 } >+}; >+ >+#endif // CONFIG_PROC_FS >+ >+void __init speakup_init(struct vc_data *vc) >+{ >+ struct st_spk_t *first_console = >+ alloc_bootmem(sizeof(struct st_spk_t) + 1); >+ memset( first_console, 0, sizeof(struct st_spk_t)); >+ speakup_open(vc, first_console); >+} >+ >+void speakup_allocate(struct vc_data *vc) >+{ >+ int vc_num; >+ >+ vc_num = vc->vc_num; >+ if ( speakup_console[vc_num] == NULL ) { >+ speakup_console[vc_num] = kzalloc(sizeof(struct st_spk_t) + 1, >+ GFP_KERNEL); >+ if (speakup_console[vc_num] == NULL) >+ return; >+ speakup_date( vc); >+ } else if ( !spk_parked ) speakup_date( vc); >+} >+ >+static u_char is_cursor = 0; >+static u_long old_cursor_pos, old_cursor_x, old_cursor_y; >+static int cursor_con; >+static int cursor_timer_active = 0; >+ >+static void cursor_stop_timer(void) >+{ >+ if (!cursor_timer_active ) return; >+ stop_timer ( cursor_timer ); >+ cursor_timer_active = 0; >+} >+ >+static void reset_highlight_buffers( struct vc_data * ); >+ >+//extern void kbd_fakekey(unsigned int); >+extern struct input_dev *fakekeydev; >+ >+static int read_all_key; >+ >+void reset_index_count(int); >+void get_index_count(int *, int *); >+//int synth_supports_indexing(void); >+static void start_read_all_timer( struct vc_data *vc, int command ); >+ >+enum {RA_NOTHING,RA_NEXT_SENT,RA_PREV_LINE,RA_NEXT_LINE,RA_PREV_SENT,RA_DOWN_ARROW,RA_TIMER,RA_FIND_NEXT_SENT,RA_FIND_PREV_SENT}; >+ >+static void >+kbd_fakekey2(struct vc_data *vc,int v,int command) >+{ >+ cursor_stop_timer(); >+ (*do_cursor)( vc,v,0); >+ (*do_cursor)( vc,v,1); >+ start_read_all_timer(vc,command); >+} >+ >+static void >+read_all_doc( struct vc_data *vc) >+{ >+ if ( synth == NULL || spk_shut_up || (vc->vc_num != fg_console ) ) >+ return; >+ if (!synth_supports_indexing()) >+ return; >+ if (cursor_track!=read_all_mode) >+ prev_cursor_track=cursor_track; >+ cursor_track=read_all_mode; >+ reset_index_count(0); >+ if (get_sentence_buf(vc,0)==-1) >+ kbd_fakekey2(vc,0,RA_DOWN_ARROW); >+ else { >+ say_sentence_num(0,0); >+ synth_insert_next_index(0); >+ start_read_all_timer(vc,RA_TIMER); >+ } >+} >+ >+static void >+stop_read_all( struct vc_data *vc) >+{ >+ cursor_stop_timer( ); >+ cursor_track=prev_cursor_track; >+ spk_shut_up &= 0xfe; >+ do_flush(); >+} >+ >+static void >+start_read_all_timer( struct vc_data *vc, int command ) >+{ >+ cursor_con = vc->vc_num; >+ cursor_timer.expires = jiffies + cursor_timeout; >+ read_all_key=command; >+ start_timer (cursor_timer ); >+ cursor_timer_active++; >+} >+ >+static void >+handle_cursor_read_all( struct vc_data *vc,int command ) >+{ >+ int indcount,sentcount,rv,sn; >+ >+ switch (command) >+ { >+ case RA_NEXT_SENT: >+ // Get Current Sentence >+ get_index_count(&indcount,&sentcount); >+ //printk("%d %d ",indcount,sentcount); >+ reset_index_count(sentcount+1); >+ if (indcount==1) >+ { >+ if (!say_sentence_num(sentcount+1,0)) >+ { >+ kbd_fakekey2(vc,0,RA_FIND_NEXT_SENT); >+ return; >+ } >+ synth_insert_next_index(0); >+ } >+ else >+ { >+ sn=0; >+ if (!say_sentence_num(sentcount+1,1)) >+ { >+ sn=1; >+ reset_index_count(sn); >+ } >+ else >+ synth_insert_next_index(0); >+ if (!say_sentence_num(sn,0)) >+ { >+ kbd_fakekey2(vc,0,RA_FIND_NEXT_SENT); >+ return; >+ } >+ synth_insert_next_index(0); >+ } >+ start_read_all_timer(vc,RA_TIMER); >+ break; >+ case RA_PREV_SENT: >+ break; >+ case RA_NEXT_LINE: >+ read_all_doc(vc); >+ break; >+ case RA_PREV_LINE: >+ break; >+ case RA_DOWN_ARROW: >+ if (get_sentence_buf(vc,0)==-1) >+ { >+ kbd_fakekey2(vc,0,RA_DOWN_ARROW); >+ } >+ else >+ { >+ say_sentence_num(0,0); >+ synth_insert_next_index(0); >+ start_read_all_timer(vc,RA_TIMER); >+ } >+ break; >+ case RA_FIND_NEXT_SENT: >+ rv=get_sentence_buf(vc,0); >+ if (rv==-1) >+ { >+ read_all_doc(vc); >+ } >+ if (rv==0) >+ { >+ kbd_fakekey2(vc,0,RA_FIND_NEXT_SENT); >+ } >+ else >+ { >+ say_sentence_num(1,0); >+ synth_insert_next_index(0); >+ start_read_all_timer(vc,RA_TIMER); >+ } >+ break; >+ case RA_FIND_PREV_SENT: >+ break; >+ case RA_TIMER: >+ get_index_count(&indcount,&sentcount); >+ if (indcount<2) >+ { >+ kbd_fakekey2(vc,0,RA_DOWN_ARROW); >+ } >+ else >+ { >+ start_read_all_timer(vc,RA_TIMER); >+ } >+ break; >+ } >+} >+ >+static void handle_cursor(struct vc_data *vc, u_char value, char up_flag) >+{ >+ if (cursor_track == read_all_mode) >+ { >+ spk_parked &= 0xfe; >+ if ( synth == NULL || up_flag || spk_shut_up ) >+ return; >+ cursor_stop_timer(); >+ spk_shut_up &= 0xfe; >+ do_flush(); >+ start_read_all_timer(vc,value+1); >+ return; >+ } >+ (*do_cursor)(vc, value, up_flag); >+ spk_parked &= 0xfe; >+ if ( synth == NULL || up_flag || spk_shut_up || cursor_track == CT_Off ) >+ return; >+ spk_shut_up &= 0xfe; >+ if ( no_intr ) do_flush( ); >+/* the key press flushes if !no_inter but we want to flush on cursor >+ * moves regardless of no_inter state */ >+ is_cursor = value+1; >+ old_cursor_pos = vc->vc_pos; >+ old_cursor_x = vc->vc_x; >+ old_cursor_y = vc->vc_y; >+ speakup_console[vc->vc_num]->ht.cy=vc->vc_y; >+ cursor_con = vc->vc_num; >+ cursor_stop_timer( ); >+ cursor_timer.expires = jiffies + cursor_timeout; >+ if ( cursor_track == CT_Highlight) >+ reset_highlight_buffers( vc ); >+ read_all_key=value+1; >+ start_timer (cursor_timer ); >+ cursor_timer_active++; >+} >+ >+static void >+update_color_buffer( struct vc_data *vc , const char *ic , int len ) >+{ >+ int i,bi,hi; >+ int vc_num=vc->vc_num; >+ >+ bi = ( (vc->vc_attr & 0x70) >> 4 ) ; >+ hi=speakup_console[vc_num]->ht.highsize[bi]; >+ >+ i=0; >+ if (speakup_console[vc_num]->ht.highsize[bi]==0) >+ { >+ speakup_console[vc_num]->ht.rpos[bi]=vc->vc_pos; >+ speakup_console[vc_num]->ht.rx[bi]=vc->vc_x; >+ speakup_console[vc_num]->ht.ry[bi]=vc->vc_y; >+ } >+ while (( hi<COLOR_BUFFER_SIZE ) && ( i < len )) >+ { >+ if (( ic[i]>32 ) && ( ic[i]<127 )) >+ { >+ speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i]; >+ hi++; >+ } >+ else if (( ic[i] == 32 ) && ( hi != 0 )) >+ { >+ if (speakup_console[vc_num]->ht.highbuf[bi][hi-1]!=32) >+ { >+ speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i]; >+ hi++; >+ } >+ } >+ i++; >+ } >+ speakup_console[vc_num]->ht.highsize[bi]=hi; >+} >+ >+static void >+reset_highlight_buffers( struct vc_data *vc ) >+{ >+ int i; >+ int vc_num=vc->vc_num; >+ for ( i=0 ; i<8 ; i++ ) >+ speakup_console[vc_num]->ht.highsize[i]=0; >+} >+ >+static int >+count_highlight_color(struct vc_data *vc) >+{ >+ int i,bg; >+ int cc; >+ int vc_num=vc->vc_num; >+ u16 ch; >+ u16 *start = (u16 *) vc->vc_origin; >+ >+ for ( i=0 ; i<8 ; i++ ) >+ speakup_console[vc_num]->ht.bgcount[i]=0; >+ >+ for ( i=0 ; i<vc->vc_rows; i++ ) { >+ u16 *end = start + vc->vc_cols*2; >+ u16 *ptr; >+ for ( ptr=start ; ptr<end ; ptr++) { >+ ch = get_attributes( ptr ); >+ bg = ( ch & 0x70 ) >> 4; >+ speakup_console[vc_num]->ht.bgcount[bg]++; >+ } >+ start += vc->vc_size_row; >+ } >+ >+ cc=0; >+ for ( i=0 ; i<8 ; i++ ) >+ if (speakup_console[vc_num]->ht.bgcount[i]>0) >+ cc++; >+ return cc; >+} >+ >+static int >+get_highlight_color( struct vc_data *vc ) >+{ >+ int i,j; >+ unsigned int cptr[8],tmp; >+ int vc_num=vc->vc_num; >+ >+ for ( i=0 ; i<8 ; i++ ) >+ cptr[i]=i; >+ >+ for ( i=0 ; i<7 ; i++ ) >+ for ( j=i+1 ; j<8 ; j++ ) >+ if ( speakup_console[vc_num]->ht.bgcount[cptr[i]] > speakup_console[vc_num]->ht.bgcount[cptr[j]]) { >+ tmp=cptr[i]; >+ cptr[i]=cptr[j]; >+ cptr[j]=tmp; >+ } >+ >+ for ( i=0; i<8; i++ ) >+ if ( speakup_console[vc_num]->ht.bgcount[cptr[i]] != 0) >+ if ( speakup_console[vc_num]->ht.highsize[cptr[i]] > 0) >+ { >+ return cptr[i]; >+ } >+ return -1; >+} >+ >+static int >+speak_highlight( struct vc_data *vc ) >+{ >+ int hc,d; >+ int vc_num=vc->vc_num; >+ if (count_highlight_color( vc )==1) >+ return 0; >+ hc=get_highlight_color( vc ); >+ if ( hc != -1 ) >+ { >+ d=vc->vc_y-speakup_console[vc_num]->ht.cy; >+ if ((d==1)||(d==-1)) >+ { >+ if (speakup_console[vc_num]->ht.ry[hc]!=vc->vc_y) >+ return 0; >+ } >+ spk_parked |= 0x01; >+ do_flush(); >+ spkup_write (speakup_console[vc_num]->ht.highbuf[hc] , speakup_console[vc_num]->ht.highsize[hc] ); >+ spk_pos=spk_cp=speakup_console[vc_num]->ht.rpos[hc]; >+ spk_x=spk_cx=speakup_console[vc_num]->ht.rx[hc]; >+ spk_y=spk_cy=speakup_console[vc_num]->ht.ry[hc]; >+ return 1; >+ } >+ return 0; >+} >+ >+static void >+cursor_done (u_long data ) >+{ >+ struct vc_data *vc = vc_cons[cursor_con].d; >+ cursor_stop_timer( ); >+ if (cursor_con != fg_console ) { >+ is_cursor = 0; >+ return; >+ } >+ speakup_date (vc ); >+ if ( win_enabled ) { >+ if ( vc->vc_x >= win_left && vc->vc_x <= win_right && >+ vc->vc_y >= win_top && vc->vc_y <= win_bottom ) { >+ spk_keydown = is_cursor = 0; >+ return; >+ } >+ } >+ if ( cursor_track == read_all_mode ) { >+ handle_cursor_read_all(vc,read_all_key); >+ return; >+ } >+ if ( cursor_track == CT_Highlight) { >+ if ( speak_highlight( vc )) { >+ spk_keydown = is_cursor = 0; >+ return; >+ } >+ } >+ if ( cursor_track == CT_Window) { >+ speakup_win_say (vc); >+ } else if ( is_cursor == 1 || is_cursor == 4 ) >+ say_line_from_to (vc, 0, vc->vc_cols, 0 ); >+ else >+ say_char ( vc ); >+ spk_keydown = is_cursor = 0; >+} >+ >+/* These functions are the interface to speakup from the actual kernel code. */ >+ >+void >+speakup_bs (struct vc_data *vc ) >+{ >+ if (!spk_parked ) >+ speakup_date (vc ); >+ if ( spk_shut_up || synth == NULL ) return; >+ if ( vc->vc_num == fg_console && spk_keydown ) { >+ spk_keydown = 0; >+ if (!is_cursor ) say_char (vc ); >+ } >+} >+ >+void >+speakup_con_write (struct vc_data *vc, const char *str, int len ) >+{ >+ if (spk_shut_up || (vc->vc_num != fg_console ) ) >+ return; >+ if (bell_pos && spk_keydown && (vc->vc_x == bell_pos - 1 ) ) >+ bleep(3 ); >+ if (synth == NULL) return; >+ if ((is_cursor)||(cursor_track == read_all_mode )) { >+ if (cursor_track == CT_Highlight ) >+ update_color_buffer( vc, str, len); >+ return; >+ } >+ if ( win_enabled ) { >+ if ( vc->vc_x >= win_left && vc->vc_x <= win_right && >+ vc->vc_y >= win_top && vc->vc_y <= win_bottom ) return; >+ } >+ >+ spkup_write (str, len ); >+} >+ >+void >+speakup_con_update (struct vc_data *vc ) >+{ >+ if ( speakup_console[vc->vc_num] == NULL || spk_parked ) >+ return; >+ speakup_date (vc ); >+} >+ >+static void handle_spec(struct vc_data *vc, u_char value, char up_flag) >+{ >+ int on_off = 2; >+ char *label; >+ static const char *lock_status[] = { " off", " on", "" }; >+ (*do_spec)(vc, value, up_flag); >+ if ( synth == NULL || up_flag || spk_killed ) return; >+ spk_shut_up &= 0xfe; >+ if ( no_intr ) do_flush( ); >+ switch (value ) { >+ case KVAL( K_CAPS ): >+ label = "caps lock"; >+ on_off = (vc_kbd_led(kbd , VC_CAPSLOCK ) ); >+ break; >+ case KVAL( K_NUM ): >+ label = "num lock"; >+ on_off = (vc_kbd_led(kbd , VC_NUMLOCK ) ); >+ break; >+ case KVAL( K_HOLD ): >+ label = "scroll lock"; >+ on_off = (vc_kbd_led(kbd , VC_SCROLLOCK ) ); >+ break; >+ default: >+ spk_parked &= 0xfe; >+ return; >+ } >+ synth_write_string ( label ); >+ synth_write_msg ( lock_status[on_off] ); >+} >+ >+static int >+inc_dec_var( u_char value ) >+{ >+ struct st_var_header *p_header; >+ struct st_num_var *var_data; >+ char num_buf[32]; >+ char *cp = num_buf, *pn; >+ int var_id = (int)value - VAR_START; >+ int how = (var_id&1) ? E_INC : E_DEC; >+ var_id = var_id/2+FIRST_SET_VAR; >+ p_header = get_var_header( var_id ); >+ if ( p_header == NULL ) return -1; >+ if ( p_header->var_type != VAR_NUM ) return -1; >+ var_data = p_header->data; >+ if ( set_num_var( 1, p_header, how ) != 0 ) >+ return -1; >+ if ( !spk_close_press ) { >+ for ( pn = p_header->name; *pn; pn++ ) { >+ if ( *pn == '_' ) *cp = SPACE; >+ else *cp++ = *pn; >+ } >+ } >+ sprintf( cp, " %d ", (int)var_data->value ); >+ synth_write_string( num_buf ); >+ return 0; >+} >+ >+static void >+speakup_win_set (struct vc_data *vc ) >+{ >+ char info[40]; >+ if ( win_start > 1 ) { >+ synth_write_msg( "window already set, clear then reset" ); >+ return; >+ } >+ if ( spk_x < win_left || spk_y < win_top ) { >+ synth_write_msg( "error end before start" ); >+ return; >+ } >+ if ( win_start && spk_x == win_left && spk_y == win_top ) { >+ win_left = 0; >+ win_right = vc->vc_cols-1; >+ win_bottom = spk_y; >+ sprintf( info, "window is line %d", (int)win_top+1 ); >+ } else { >+ if ( !win_start ) { >+ win_top = spk_y; >+ win_left = spk_x; >+ } else { >+ win_bottom = spk_y; >+ win_right = spk_x; >+ } >+ sprintf( info, "%s at line %d, column %d", >+ (win_start) ? "end" : "start", >+ (int)spk_y+1, (int)spk_x+1 ); >+ } >+ synth_write_msg( info ); >+ win_start++; >+} >+ >+static void >+speakup_win_clear (struct vc_data *vc ) >+{ >+ win_top = win_bottom = 0; >+ win_left = win_right = 0; >+ win_start = 0; >+ synth_write_msg( "window cleared" ); >+} >+ >+static void >+speakup_win_enable (struct vc_data *vc ) >+{ >+ if ( win_start < 2 ) { >+ synth_write_msg( "no window" ); >+ return; >+ } >+ win_enabled ^= 1; >+ if ( win_enabled ) synth_write_msg( "window silenced" ); >+ else synth_write_msg( "window silence disabled" ); >+} >+ >+static void >+speakup_bits (struct vc_data *vc ) >+{ >+ int val = this_speakup_key - ( FIRST_EDIT_BITS - 1 ); >+ if ( special_handler != NULL || val < 1 || val > 6 ) { >+ synth_write_msg( "error" ); >+ return; >+ } >+ pb_edit = &punc_info[val]; >+ sprintf( buf, "edit %s, press space when done", pb_edit->name ); >+ synth_write_msg( buf ); >+ special_handler = edit_bits; >+} >+ >+static int handle_goto (struct vc_data *vc, u_char type, u_char ch, u_short key ) >+{ >+ static u_char *goto_buf = "\0\0\0\0\0\0"; >+ static int num = 0; >+ short maxlen, go_pos; >+ char *cp; >+ if ( type == KT_SPKUP && ch == SPEAKUP_GOTO ) goto do_goto; >+ if ( type == KT_LATIN && ch == '\n' ) goto do_goto; >+ if ( type != 0 ) goto oops; >+ if (ch == 8 ) { >+ if ( num == 0 ) return -1; >+ ch = goto_buf[--num]; >+ goto_buf[num] = '\0'; >+ spkup_write( &ch, 1 ); >+ return 1; >+} >+ if ( ch < '+' || ch > 'y' ) goto oops; >+ goto_buf[num++] = ch; >+ goto_buf[num] = '\0'; >+ spkup_write( &ch, 1 ); >+ maxlen = ( *goto_buf >= '0' ) ? 3 : 4; >+ if ((ch == '+' || ch == '-' ) && num == 1 ) return 1; >+ if (ch >= '0' && ch <= '9' && num < maxlen ) return 1; >+ if ( num < maxlen-1 || num > maxlen ) goto oops; >+ if ( ch < 'x' || ch > 'y' ) { >+oops: >+ if (!spk_killed ) >+ synth_write_msg (" goto canceled" ); >+ goto_buf[num = 0] = '\0'; >+ special_handler = NULL; >+ return 1; >+ } >+ cp = speakup_s2i (goto_buf, &go_pos ); >+ goto_pos = (u_long)go_pos; >+ if (*cp == 'x' ) { >+ if (*goto_buf < '0' ) goto_pos += spk_x; >+ else goto_pos--; >+ if (goto_pos < 0 ) goto_pos = 0; >+ if (goto_pos >= vc->vc_cols ) >+ goto_pos = vc->vc_cols-1; >+ goto_x = 1; >+ } else { >+ if (*goto_buf < '0' ) goto_pos += spk_y; >+ else goto_pos--; >+ if (goto_pos < 0 ) goto_pos = 0; >+ if (goto_pos >= vc->vc_rows ) goto_pos = vc->vc_rows-1; >+ goto_x = 0; >+ } >+ goto_buf[num = 0] = '\0'; >+do_goto: >+ special_handler = NULL; >+ spk_parked |= 0x01; >+ if ( goto_x ) { >+ spk_pos -= spk_x * 2; >+ spk_x = goto_pos; >+ spk_pos += goto_pos * 2; >+ say_word( vc ); >+ } else { >+ spk_y = goto_pos; >+ spk_pos = vc->vc_origin + ( goto_pos * vc->vc_size_row ); >+ say_line( vc ); >+ } >+ return 1; >+} >+ >+static void >+speakup_goto (struct vc_data *vc ) >+{ >+ if ( special_handler != NULL ) { >+ synth_write_msg( "error" ); >+ return; >+ } >+ synth_write_msg( "go to?" ); >+ special_handler = handle_goto; >+ return; >+} >+ >+static void >+load_help ( struct work_struct *dummy ) >+{ >+ request_module( "speakup_keyhelp" ); >+ if ( help_handler ) { >+ (*help_handler)(0, KT_SPKUP, SPEAKUP_HELP, 0 ); >+ } else synth_write_string( "help module not found" ); >+} >+ >+static DECLARE_WORK(ld_help, load_help); >+#define schedule_help schedule_work >+ >+static void >+speakup_help (struct vc_data *vc ) >+{ >+ if ( help_handler == NULL ) { >+/* we can't call request_module from this context so schedule it*/ >+/* **** note kernel hangs and my wrath will be on you */ >+ schedule_help (&ld_help); >+ return; >+ } >+ (*help_handler)(vc, KT_SPKUP, SPEAKUP_HELP, 0 ); >+} >+ >+static void >+do_nothing (struct vc_data *vc ) >+{ >+ return; /* flush done in do_spkup */ >+} >+static u_char key_speakup = 0, spk_key_locked = 0; >+ >+static void >+speakup_lock (struct vc_data *vc ) >+{ >+ if ( !spk_key_locked ) >+ spk_key_locked = key_speakup = 16; >+ else spk_key_locked = key_speakup = 0; >+} >+ >+typedef void (*spkup_hand )(struct vc_data * ); >+spkup_hand spkup_handler[] = { /* must be ordered same as defines in speakup.h */ >+ do_nothing, speakup_goto, speech_kill, speakup_shut_up, >+ speakup_cut, speakup_paste, say_first_char, say_last_char, >+ say_char, say_prev_char, say_next_char, >+ say_word, say_prev_word, say_next_word, >+ say_line, say_prev_line, say_next_line, >+ top_edge, bottom_edge, left_edge, right_edge, >+ spell_word, spell_word, say_screen, >+ say_position, say_attributes, >+ speakup_off, speakup_parked, say_line, // this is for indent >+ say_from_top, say_to_bottom, >+ say_from_left, say_to_right, >+ say_char_num, speakup_bits, speakup_bits, say_phonetic_char, >+ speakup_bits, speakup_bits, speakup_bits, >+ speakup_win_set, speakup_win_clear, speakup_win_enable, speakup_win_say, >+ speakup_lock, speakup_help, toggle_cursoring, read_all_doc, NULL >+}; >+ >+static void do_spkup( struct vc_data *vc,u_char value ) >+{ >+ if (spk_killed && value != SPEECH_KILL ) return; >+ spk_keydown = 0; >+ spk_lastkey = 0; >+ spk_shut_up &= 0xfe; >+ this_speakup_key = value; >+ if (value < SPKUP_MAX_FUNC && spkup_handler[value] ) { >+ do_flush( ); >+ (*spkup_handler[value] )(vc ); >+ } else { >+ if ( inc_dec_var( value ) < 0 ) >+ bleep( 9 ); >+ } >+} >+ >+ static const char *pad_chars = "0123456789+-*/\015,.?()"; >+ >+int >+speakup_key (struct vc_data *vc, int shift_state, int keycode, u_short keysym, int up_flag) >+{ >+ int kh; >+ u_char *key_info; >+ u_char type = KTYP( keysym ), value = KVAL( keysym ), new_key = 0; >+ u_char shift_info, offset; >+ tty = vc->vc_tty; >+ if ( synth == NULL ) return 0; >+ if ( type >= 0xf0 ) type -= 0xf0; >+ if ( type == KT_PAD && (vc_kbd_led(kbd , VC_NUMLOCK ) ) ) { >+ if ( up_flag ) { >+ spk_keydown = 0; >+ return 0; >+ } >+ value = spk_lastkey = pad_chars[value]; >+ spk_keydown++; >+ spk_parked &= 0xfe; >+ goto no_map; >+ } >+ if ( keycode >= MAX_KEY ) goto no_map; >+ if ( ( key_info = our_keys[keycode] ) == 0 ) goto no_map; >+ // Check valid read all mode keys >+ if ( (cursor_track==read_all_mode) && ( !up_flag )) >+ { >+ switch (value) >+ { >+ case KVAL(K_DOWN): >+ case KVAL(K_UP): >+ case KVAL(K_LEFT): >+ case KVAL(K_RIGHT): >+ case KVAL(K_PGUP): >+ case KVAL(K_PGDN): >+ break; >+ default: >+ stop_read_all(vc); >+ break; >+ } >+ } >+ shift_info = ( shift_state&0x0f ) + key_speakup; >+ offset = shift_table[shift_info]; >+ if ( offset && ( new_key = key_info[offset] ) ) { >+ if ( new_key == SPK_KEY ) { >+ if ( !spk_key_locked ) >+ key_speakup = ( up_flag ) ? 0 : 16; >+ if ( up_flag || spk_killed ) return 1; >+ spk_shut_up &= 0xfe; >+ do_flush( ); >+ return 1; >+ } >+ if ( up_flag ) return 1; >+ if ( last_keycode == keycode && last_spk_jiffy+MAX_DELAY > jiffies ) { >+ spk_close_press = 1; >+ offset = shift_table[shift_info+32]; >+/* double press? */ >+ if ( offset && key_info[offset] ) >+ new_key = key_info[offset]; >+ } >+ last_keycode = keycode; >+ last_spk_jiffy = jiffies; >+ type = KT_SPKUP; >+ value = new_key; >+ } >+no_map: >+ if ( type == KT_SPKUP && special_handler == NULL ) { >+ do_spkup( vc, new_key ); >+ spk_close_press = 0; >+ return 1; >+ } >+ if ( up_flag || spk_killed || type == KT_SHIFT ) return 0; >+ spk_shut_up &= 0xfe; >+ kh=(value==KVAL(K_DOWN))||(value==KVAL(K_UP))||(value==KVAL(K_LEFT))||(value==KVAL(K_RIGHT)); >+ if ((cursor_track != read_all_mode) || !kh) >+ if (!no_intr ) do_flush( ); >+ if ( special_handler ) { >+ int status; >+ if ( type == KT_SPEC && value == 1 ) { >+ value = '\n'; >+ type = KT_LATIN; >+ } else if ( type == KT_LETTER ) type = KT_LATIN; >+ else if ( value == 0x7f ) value = 8; /* make del = backspace */ >+ status = (*special_handler)(vc, type, value, keycode ); >+ spk_close_press = 0; >+ if ( status < 0 ) bleep( 9 ); >+ return status; >+ } >+ last_keycode = 0; >+ return 0; >+} >+ >+#ifdef MODULE >+ >+extern void speakup_remove(void); >+extern void speakup_set_addresses ( spk_con_func, spk_con_func, spk_write_func, spk_con_func, spk_key_func); >+ >+static void __exit mod_speakup_exit(void) >+{ >+ int i; >+ >+ key_handler[KT_LATIN] = do_latin; >+ key_handler[KT_SPEC] = do_spec; >+ key_handler[KT_CUR] = do_cursor; >+ key_handler[KT_SHIFT] = do_shift; >+ speakup_set_addresses(NULL, NULL, NULL, NULL, NULL); >+ synth_release(); >+ speakup_remove(); >+ for(i = 0; i < 256; i++) { >+ if (characters[i] != default_chars[i]) >+ kfree(characters[i]); >+ } >+ for(i = 0; speakup_console[i]; i++) { >+ kfree(speakup_console[i]); >+ speakup_console[i] = NULL; >+ } >+} >+ >+static int __init mod_speakup_init( void ) >+{ >+ int i; >+ struct st_spk_t *first_console = kzalloc(sizeof(struct st_spk_t) + 1, >+ GFP_KERNEL); >+ speakup_open( vc_cons[fg_console].d, first_console ); >+for ( i = 0; vc_cons[i].d; i++) >+ speakup_allocate(vc_cons[i].d); >+ speakup_set_addresses( speakup_allocate, speakup_bs, >+ speakup_con_write, speakup_con_update, speakup_key ); >+ speakup_dev_init(); >+ return 0; >+} >+ >+module_init( mod_speakup_init ); >+module_exit( mod_speakup_exit ); >+ >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakupconf linux-2.6.20-spk/drivers/char/speakup/speakupconf >--- linux-2.6.20/drivers/char/speakup/speakupconf 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakupconf 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,51 @@ >+#!/bin/sh >+# script to load/save all the vars in speakup >+# speakupconf save or speakupconf load >+# if root saves in /etc/speakup/<synth_name> else in $HOME/.speakup/<synth_name> >+if [ $UID -eq "0" ]; then >+ SAVEDIR="/etc/speakup" >+else >+ SAVEDIR="$HOME/.speakup" >+fi >+if [ ! -d /proc/speakup ]; then >+ echo "no directory /proc/speakup" >+ exit 0 >+fi >+SYNTH=`cat /proc/speakup/synth_name` >+case "$1" in >+*save) >+ if [ ! -d $SAVEDIR ] ; then >+ echo creating $SAVEDIR >+ mkdir $SAVEDIR >+ fi >+ if [ ! -d $SAVEDIR/$SYNTH ] ; then >+ echo creating $SAVEDIR/$SYNTH >+ mkdir $SAVEDIR/$SYNTH >+ fi >+ cd /proc/speakup >+ SAVELIST=` find . -perm -6 |sed 's/..//' |fgrep -v synth` >+ for f in $SAVELIST; do >+ cp $f $SAVEDIR/$SYNTH/$f >+ done >+;; >+*load) >+ if [ ! -d $SAVEDIR ] ; then >+ echo no directory $SAVEDIR >+ exit 1 >+ fi >+ if [ ! -d $SAVEDIR/$SYNTH ] ; then >+ echo no directory $SAVEDIR/$SYNTH >+ exit 1 >+ fi >+ cd $SAVEDIR/$SYNTH >+ for f in *; do >+ if [ -w /proc/speakup/$f ]; then >+ cat $f >/proc/speakup/$f >+ fi >+ done >+;; >+*) >+ echo "usage: speakupconf load/save" >+ exit 1 >+;; >+esac >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_decext.c linux-2.6.20-spk/drivers/char/speakup/speakup_decext.c >--- linux-2.6.20/drivers/char/speakup/speakup_decext.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_decext.c 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,206 @@ >+/* >+ * originially written by: Kirk Reiser <kirk@braille.uwo.ca> >+* this version considerably modified by David Borowski, david575@rogers.com >+ >+ Copyright (C) 1998-99 Kirk Reiser. >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "serialio.h" >+ >+#define MY_SYNTH synth_decext >+#define SYNTH_CLEAR 0x03 >+#define PROCSPEECH 0x0b >+#define synth_full( ) ( inb_p( synth_port_tts ) == 0x13 ) >+ >+static int timeouts = 0; >+static int in_escape = 0; >+ >+static int wait_for_xmitr ( void ) >+{ >+ int check, tmout = SPK_XMITR_TIMEOUT; >+ if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) { >+ synth_alive = 0; >+ timeouts = 0; >+ return 0; >+ } >+ do { /* holding register empty? */ >+ check = inb_p( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) { >+ pr_warn ( "%s: timed out\n", synth->long_name ); >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY ); >+ tmout = SPK_XMITR_TIMEOUT; >+ do { /* CTS */ >+ check = inb_p ( synth_port_tts + UART_MSR ); >+ if ( --tmout == 0 ) { >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS ); >+ timeouts = 0; >+ return 1; >+} >+ >+static int spk_serial_out(const char ch) >+{ >+ if ( synth_alive && wait_for_xmitr ( ) ) { >+ outb_p ( ch, synth_port_tts ); >+ return 1; >+ } >+ return 0; >+} >+ >+static u_char >+spk_serial_in ( void ) >+{ >+ int lsr, tmout = SPK_SERIAL_TIMEOUT, c; >+ do { >+ lsr = inb_p ( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) >+ return 0xff; >+ } while ( !( lsr & UART_LSR_DR ) ); >+ c = inb_p ( synth_port_tts + UART_RX ); >+ return ( u_char ) c; >+} >+ >+static void do_catch_up( unsigned long data ) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+static u_char last='\0'; >+ synth_stop_timer( ); >+ while ( synth_buff_out < synth_buff_in ) { >+ ch = *synth_buff_out; >+ if ( ch == '\n' ) ch = 0x0D; >+ if ( synth_full( ) || !spk_serial_out( ch ) ) { >+ synth_delay( synth_full_time ); >+ return; >+ } >+ synth_buff_out++; >+ if ( ch == '[' ) in_escape = 1; >+ else if ( ch == ']' ) in_escape = 0; >+ else if ( ch <= SPACE ) { >+ if ( !in_escape && strchr( ",.!?;:", last ) ) >+ spk_serial_out( PROCSPEECH ); >+ if ( jiffies >= jiff_max ) { >+ if ( !in_escape ) >+ spk_serial_out( PROCSPEECH ); >+ synth_delay( synth_delay_time ); >+ return; >+ } >+ } >+ last = ch; >+ } >+ if ( synth_done( ) || !in_escape ) >+ spk_serial_out( PROCSPEECH ); >+} >+ >+static const char *synth_immediate ( const char *buf ) >+{ >+ u_char ch; >+ while ( ( ch = *buf ) ) { >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( wait_for_xmitr( ) ) >+ outb( ch, synth_port_tts ); >+ else return buf; >+ buf++; >+ } >+ return 0; >+} >+ >+static void synth_flush( void ) >+{ >+ in_escape = 0; >+ synth_immediate( "\033P;10z\033\\" ); >+} >+ >+static int serprobe( int index ) >+{ >+ u_char test=0; >+ struct serial_state *ser = spk_serial_init( index ); >+ if ( ser == NULL ) return -1; >+ /* ignore any error results, if port was forced */ >+ if ( synth_port_forced ) >+ return 0; >+ synth_immediate( "\033[;5n\033\\" ); >+ if ( ( test = spk_serial_in( ) ) == '\033' ) >+ return 0; >+ spk_serial_release( ); >+ timeouts = synth_alive = synth_port_tts = 0; /* not ignoring */ >+ return -1; >+} >+ >+static int synth_probe( void ) >+{ >+ int i=0, failed=0; >+ pr_info( "Probing for %s.\n", synth->long_name ); >+ /* check ttyS0-ttyS3 */ >+ for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) { >+ if (( failed = serprobe( i )) == 0 ) break; /* found it */ >+ } >+ if ( failed ) { >+ pr_info( "%s: not found\n", synth->long_name ); >+ return -ENODEV; >+ } >+ pr_info( "%s: %03x-%03x, Driver Version %s,\n", synth->long_name, >+ synth_port_tts, synth_port_tts+7, synth->version ); >+ return 0; >+} >+ >+static int synth_is_alive( void ) >+{ >+ if ( synth_alive ) return 1; >+ if ( !synth_alive&& wait_for_xmitr( ) > 0 ) { /* restart */ >+ synth_alive = 1; >+ synth_write_string( synth->init ); >+ return 2; >+ } >+ pr_warn( "%s: can't restart synth\n", synth->long_name ); >+ return 0; >+} >+ >+static const char init_string[] = "[:pe -380]"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "[:dv ap 222]" }, >+ { CAPS_STOP, "[:dv ap 100]" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "[:ra %d]", 7, 0, 9, 150, 25, 0 }, >+ { PITCH, "[:dv ap %d]", 100, 0, 100, 0, 0, 0 }, >+ { VOL, "[:dv gv %d]", 13, 0, 16, 0, 5, 0 }, >+ { PUNCT, "[:pu %c]", 0, 0, 2, 0, 0, "nsa" }, >+ { VOICE, "[:n%c]", 0, 0, 9, 0, 0, "phfdburwkv" }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_decext = {"decext", "1.1", "Dectalk External", >+ init_string, 500, 50, 50, 1000, 0, SF_DEC, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, spk_serial_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL, >+ {NULL,0,0,0} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_decpc.c linux-2.6.20-spk/drivers/char/speakup/speakup_decpc.c >--- linux-2.6.20/drivers/char/speakup/speakup_decpc.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_decpc.c 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,243 @@ >+/* >+* written by David Borowski, david575@golden.net >+ >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "dtpc_reg.h" >+ >+#define MY_SYNTH synth_dec_pc >+#define PROCSPEECH 0x0b >+#define SYNTH_IO_EXTENT 8 >+ >+static int synth_portlist[] = { 0x340, 0x350, 0x240, 0x250, 0 }; >+static int in_escape = 0, is_flushing = 0; >+static int dt_stat, dma_state = 0; >+ >+static int dt_getstatus(void) >+{ >+ dt_stat = inb_p( synth_port_tts )|(inb_p( synth_port_tts+1 )<<8); >+ return dt_stat; >+} >+ >+static void dt_sendcmd(u_int cmd) >+{ >+ outb_p( cmd & 0xFF, synth_port_tts ); >+ outb_p( (cmd>>8) & 0xFF, synth_port_tts+1 ); >+} >+ >+static int dt_waitbit( int bit ) >+{ >+ int timeout = 100; >+ while ( --timeout > 0 ) { >+ if( (dt_getstatus( ) & bit ) == bit ) return 1; >+ udelay( 50 ); >+ } >+ return 0; >+} >+ >+static int dt_wait_dma( void ) >+{ >+ int timeout = 100, state = dma_state; >+ if( ! dt_waitbit( STAT_dma_ready ) ) return 0; >+ while ( --timeout > 0 ) { >+ if( (dt_getstatus()&STAT_dma_state) == state ) return 1; >+ udelay( 50 ); >+ } >+ dma_state = dt_getstatus( ) & STAT_dma_state; >+ return 1; >+} >+ >+static int dt_ctrl( u_int cmd ) >+{ >+ int timeout = 10; >+ if ( !dt_waitbit( STAT_cmd_ready ) ) return -1; >+ outb_p( 0, synth_port_tts+2 ); >+ outb_p( 0, synth_port_tts+3 ); >+ dt_getstatus( ); >+ dt_sendcmd( CMD_control|cmd ); >+ outb_p( 0, synth_port_tts+6 ); >+ while ( dt_getstatus( ) & STAT_cmd_ready ) { >+ udelay( 20 ); >+ if ( --timeout == 0 ) break; >+ } >+ dt_sendcmd( CMD_null ); >+ return 0; >+} >+ >+static void synth_flush( void ) >+{ >+ int timeout = 10; >+ if ( is_flushing ) return; >+ is_flushing = 4; >+ in_escape = 0; >+ while ( dt_ctrl( CTRL_flush ) ) { >+ if ( --timeout == 0 ) break; >+udelay( 50 ); >+ } >+ for ( timeout = 0; timeout < 10; timeout++ ) { >+ if ( dt_waitbit( STAT_dma_ready ) ) break; >+udelay( 50 ); >+ } >+ outb_p( DMA_sync, synth_port_tts+4 ); >+ outb_p( 0, synth_port_tts+4 ); >+ udelay( 100 ); >+ for ( timeout = 0; timeout < 10; timeout++ ) { >+ if ( !( dt_getstatus( ) & STAT_flushing ) ) break; >+udelay( 50 ); >+ } >+ dma_state = dt_getstatus( ) & STAT_dma_state; >+ dma_state ^= STAT_dma_state; >+ is_flushing = 0; >+} >+ >+static int dt_sendchar( char ch ) >+{ >+ if( ! dt_wait_dma( ) ) return -1; >+ if( ! (dt_stat & STAT_rr_char) ) return -2; >+ outb_p( DMA_single_in, synth_port_tts+4 ); >+ outb_p( ch, synth_port_tts+4 ); >+ dma_state ^= STAT_dma_state; >+ return 0; >+} >+ >+static int testkernel( void ) >+{ >+ int status = 0; >+ if ( dt_getstatus( ) == 0xffff ) { >+ status = -1; >+ goto oops; >+ } >+ dt_sendcmd( CMD_sync ); >+ if( ! dt_waitbit( STAT_cmd_ready ) ) status = -2; >+ else if ( ( dt_stat&0x8000 ) ) { >+ return 0; >+ } else if ( dt_stat == 0x0dec ) >+ pr_warn( "dec_pc at 0x%x, software not loaded\n", synth_port_tts ); >+ status = -3; >+oops: synth_release_region( synth_port_tts, SYNTH_IO_EXTENT ); >+ synth_port_tts = 0; >+ return status; >+} >+ >+static void do_catch_up( unsigned long data ) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+static u_char last='\0'; >+ synth_stop_timer( ); >+ while ( synth_buff_out < synth_buff_in ) { >+ ch = *synth_buff_out; >+ if ( ch == '\n' ) ch = 0x0D; >+ if ( dt_sendchar( ch ) ) { >+ synth_delay( synth_full_time ); >+ return; >+ } >+ synth_buff_out++; >+ if ( ch == '[' ) in_escape = 1; >+ else if ( ch == ']' ) in_escape = 0; >+ else if ( ch <= SPACE ) { >+ if ( !in_escape && strchr( ",.!?;:", last ) ) >+ dt_sendchar( PROCSPEECH ); >+ if ( jiffies >= jiff_max ) { >+ if ( !in_escape ) >+ dt_sendchar( PROCSPEECH ); >+ synth_delay( synth_delay_time ); >+ return; >+ } >+ } >+ last = ch; >+ } >+ if ( synth_done( ) || !in_escape ) >+ dt_sendchar( PROCSPEECH ); >+} >+ >+static const char *synth_immediate ( const char *buf ) >+{ >+ u_char ch; >+ while ( ( ch = *buf ) ) { >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( dt_sendchar ( ch ) ) >+ return buf; >+ buf++; >+ } >+ return 0; >+} >+ >+static int synth_probe ( void ) >+{ >+ int i=0, failed=0; >+ pr_info ( "Probing for %s.\n", synth->long_name ); >+ for( i=0; synth_portlist[i]; i++ ) { >+ if ( synth_request_region( synth_portlist[i], SYNTH_IO_EXTENT ) ) { >+ pr_warn( "request_region: failed with 0x%x, %d\n", >+ synth_portlist[i], SYNTH_IO_EXTENT ); >+ continue; >+ } >+ synth_port_tts = synth_portlist[i]; >+ if (( failed = testkernel( )) == 0 ) break; >+ } >+ if ( failed ) { >+ pr_info ( "%s: not found\n", synth->long_name ); >+ return -ENODEV; >+ } >+ pr_info ( "%s: %03x-%03x, Driver Version %s,\n", synth->long_name, >+ synth_port_tts, synth_port_tts + 7, synth->version ); >+ return 0; >+} >+ >+static void dtpc_release( void ) >+{ >+ if ( synth_port_tts ) >+ synth_release_region( synth_port_tts, SYNTH_IO_EXTENT ); >+ synth_port_tts = 0; >+} >+ >+static int synth_is_alive( void ) >+{ >+ synth_alive = 1; >+ return 1; >+} >+ >+static const char init_string[] = "[:pe -380]"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "[:dv ap 200]" }, >+ { CAPS_STOP, "[:dv ap 100]" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "[:ra %d]", 9, 0, 18, 150, 25, 0 }, >+ { PITCH, "[:dv ap %d]", 80, 0, 100, 20, 0, 0 }, >+ { VOL, "[:vo se %d]", 5, 0, 9, 5, 10, 0 }, >+ { PUNCT, "[:pu %c]", 0, 0, 2, 0, 0, "nsa" }, >+ { VOICE, "[:n%c]", 0, 0, 9, 0, 0, "phfdburwkv" }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_dec_pc = { "decpc", "1.1", "Dectalk PC", >+ init_string, 500, 50, 50, 1000, 0, SF_DEC, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, dtpc_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL, >+ {NULL,0,0,0} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_dectlk.c linux-2.6.20-spk/drivers/char/speakup/speakup_dectlk.c >--- linux-2.6.20/drivers/char/speakup/speakup_dectlk.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_dectlk.c 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,285 @@ >+/* >+ * originially written by: Kirk Reiser <kirk@braille.uwo.ca> >+* this version considerably modified by David Borowski, david575@rogers.com >+ >+ Copyright (C) 1998-99 Kirk Reiser. >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "serialio.h" >+#include <linux/unistd.h> >+#include <linux/proc_fs.h> >+ >+#define MY_SYNTH synth_dectlk >+#define SYNTH_CLEAR 0x03 >+#define PROCSPEECH 0x0b >+#define synth_full( ) ( inb_p( synth_port_tts ) == 0x13 ) >+ >+static int timeouts = 0; >+static int in_escape = 0, is_flushing = 0; >+atomic_t dectest=ATOMIC_INIT(0); >+ >+static int wait_for_xmitr ( void ) >+{ >+ int check, tmout = SPK_XMITR_TIMEOUT; >+ if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) { >+ synth_alive = 0; >+ timeouts = 0; >+ return 0; >+ } >+ do { /* holding register empty? */ >+ check = inb_p( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) { >+ pr_warn ( "%s: timed out\n", synth->long_name ); >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY ); >+ //} while ( ( check & UART_LSR_THRE ) != UART_LSR_THRE ); >+ tmout = SPK_XMITR_TIMEOUT; >+ do { /* CTS */ >+ check = inb_p ( synth_port_tts + UART_MSR ); >+ if ( --tmout == 0 ) { >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS ); >+ timeouts = 0; >+ return 1; >+} >+ >+static int spk_serial_out ( const char ch ) >+{ >+ if ( synth_alive && wait_for_xmitr ( ) ) { >+ outb_p ( ch, synth_port_tts ); >+ >+ return 1; >+ } >+ return 0; >+} >+ >+/*static u_char >+spk_serial_in ( void ) >+{ >+ int c = 0; >+ >+ while (inb_p(synth_port_tts + UART_LSR) & UART_LSR_DR) { >+ c = inb_p(synth_port_tts+UART_RX); >+ } >+ return (u_char) c; >+}*/ >+ >+static int is_indnum(u_char *ch) >+{ >+ if ((*ch>47)&&(*ch<58)) >+ { >+ *ch=*ch-48; >+ return 1; >+ } >+ return 0; >+} >+ >+static const char *synth_immediate (const char *); >+ >+static u_char lastind=0; >+ >+static unsigned char get_index( void ) >+{ >+ u_char rv; >+ rv=lastind; >+ lastind=0; >+ return rv; >+} >+ >+void read_buff_add(u_char c) >+{ >+ static int ind=-1; >+ >+ if (c==0x01) >+ { >+ is_flushing=0; >+ atomic_set(&dectest,0); >+ } >+ else if (is_indnum(&c)) >+ { >+ if (ind==-1) >+ ind=c; >+ else >+ ind=ind*10+c; >+ } >+ else if ((c>31) && (c<127)) >+ { >+ if (ind!=-1) >+ lastind=(u_char)ind; >+ ind=-1; >+ } >+} >+ >+static void do_catch_up( unsigned long data ) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+ static u_char last='\0'; >+ synth_stop_timer( ); >+ if (is_flushing) >+ { >+ if (--is_flushing == 0 ) >+ pr_warn ( "flush timeout\n" ); >+ else >+ { >+ synth_delay( synth_delay_time ); >+ return; >+ } >+ } >+ while ( synth_buff_out < synth_buff_in ) { >+ ch = *synth_buff_out; >+ if ( ch == '\n' ) ch = 0x0D; >+ if ( synth_full( ) || !spk_serial_out( ch ) ) { >+ synth_delay( synth_full_time ); >+ return; >+ } >+ synth_buff_out++; >+ if ( ch == '[' ) in_escape = 1; >+ else if ( ch == ']' ) in_escape = 0; >+ else if ( ch <= SPACE ) { >+ if ( !in_escape && strchr( ",.!?;:", last ) ) >+ spk_serial_out( PROCSPEECH ); >+ if ( jiffies >= jiff_max ) { >+ if ( !in_escape ) >+ spk_serial_out( PROCSPEECH ); >+ synth_delay( synth_delay_time ); >+ return; >+ } >+ } >+ last = ch; >+ } >+ if ( synth_done( ) || !in_escape ) >+ spk_serial_out( PROCSPEECH ); >+} >+ >+static const char *synth_immediate ( const char *buf ) >+{ >+ u_char ch; >+ while ( ( ch = *buf ) ) { >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( wait_for_xmitr( ) ) >+ outb( ch, synth_port_tts ); >+ else return buf; >+ buf++; >+ } >+ return 0; >+} >+ >+static void synth_flush( void ) >+{ >+ if (in_escape) >+ { >+ // if in command output ']' so we don't get an error >+ spk_serial_out( ']' ); >+ } >+ in_escape = 0; >+ spk_serial_out ( SYNTH_CLEAR ); >+ is_flushing = 5; /* if no ctl-a in 4, send data anyway */ >+} >+ >+static int serprobe ( int index ) >+{ >+ struct serial_state *ser = spk_serial_init( index ); >+ //u_char test;//, timeout = 10000; >+ int timeout=1000000; >+ if ( ser == NULL ) return -1; >+ outb ( 0x0d, ser->port ); >+ /* ignore any error results, if port was forced */ >+ if ( synth_port_forced ) return 0; >+ /* check for dectalk express now... */ >+ >+ atomic_set(&dectest,5); >+ if ( !synth_immediate ( "\x03" ) ) { >+ /*do { >+ test = spk_serial_in ( ); >+ if ( test == 0x01 ) return 0; >+ } while ( --timeout > 0 );*/ >+ >+ do { >+ if ( atomic_read(&dectest)==0) return 0; >+ outb('a',0x80); // Sleep about a microsecond >+ } while ( --timeout > 0); >+ >+ } >+ spk_serial_release( ); >+ timeouts = synth_alive = synth_port_tts = 0; /* not ignoring */ >+ return -1; >+} >+ >+static int synth_probe ( void ) >+{ >+ int i = 0, failed=0; >+ pr_info ( "Probing for %s.\n", synth->long_name ); >+ /* check ttyS0-ttyS3 */ >+ for ( i = SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) { >+ if (( failed = serprobe( i )) == 0 ) break; /* found it */ >+ } >+ if ( failed ) { >+ pr_info ( "%s: not found\n", synth->long_name ); >+ return -ENODEV; >+ } >+ pr_info ( "%s: %03x-%03x, Driver Version %s,\n", synth->long_name, >+ synth_port_tts, synth_port_tts + 7, synth->version ); >+ return 0; >+} >+ >+static int >+synth_is_alive ( void ) >+{ >+ if ( synth_alive ) return 1; >+ if ( !synth_alive && wait_for_xmitr ( ) > 0 ) { /* restart */ >+ synth_alive = 1; >+ synth_write_string ( synth->init ); >+ return 2; >+ } else >+ pr_warn ( "%s: can't restart synth\n", synth->long_name ); >+ return 0; >+} >+ >+static const char init_string[] = "[:pe -380][:dv ap 100][:error sp]"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "[:dv ap 200]" }, >+ { CAPS_STOP, "[:dv ap 100]" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "[:ra %d]", 9, 0, 18, 150, 25, 0 }, >+ { PITCH, "[:dv ap %d]", 80, 0, 200, 20, 0, 0 }, >+ { VOL, "[:dv gv %d]", 13, 0, 14, 0, 5, 0 }, >+ { PUNCT, "[:pu %c]", 0, 0, 2, 0, 0, "nsa" }, >+ { VOICE, "[:n%c]", 0, 0, 9, 0, 0, "phfdburwkv" }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_dectlk = { "dectlk", "1.3", "Dectalk Express", >+ init_string, 500, 50, 50, 1000, 0, SF_DEC, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, spk_serial_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, read_buff_add, >+ get_index, {"[:in re %d] ",1,8,1} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_drvcommon.c linux-2.6.20-spk/drivers/char/speakup/speakup_drvcommon.c >--- linux-2.6.20/drivers/char/speakup/speakup_drvcommon.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_drvcommon.c 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,1031 @@ >+#define KERNEL >+#include <linux/version.h> >+#include <linux/types.h> >+#include <linux/ctype.h> /* for isdigit( ) and friends */ >+#include <linux/fs.h> >+#include <linux/mm.h> /* for verify_area */ >+#include <linux/errno.h> /* for -EBUSY */ >+#include <linux/ioport.h> /* for check_region, request_region */ >+#include <linux/interrupt.h> >+#include <linux/delay.h> /* for loops_per_sec */ >+#include <asm/semaphore.h> >+#include <linux/wait.h> /* for wait_queue */ >+#include <linux/miscdevice.h> /* for misc_register, and SYNTH_MINOR */ >+#include "spk_priv.h" >+#include "serialio.h" >+#include <linux/kmod.h> >+ >+#ifdef __powerpc__ >+#include <asm-ppc/pc_serial.h> /* for SERIAL_PORT_DFNS */ >+#endif >+ >+static struct serial_state rs_table[] = { >+ SERIAL_PORT_DFNS >+}; >+ >+#include "synthlist.h" >+static struct spk_synth *synths[16] = { >+#include "synthlist.h" >+ NULL }; >+ >+#define synthBufferSize 8192 /* currently 8K bytes */ >+struct spk_synth *synth = NULL; >+int synth_port_tts = 0, synth_port_forced = 0; >+static int synth_timer_active = 0; /* indicates when a timer is set */ >+ static struct miscdevice synth_device; >+static int misc_registered = 0; >+static char pitch_buff[32] = ""; >+static DECLARE_MUTEX(sem); >+declare_sleeper( synth_sleeping_list ); >+static int module_status = 0; >+static declare_timer( synth_timer ); >+short synth_delay_time = 500, synth_trigger_time = 50; >+short synth_jiffy_delta = 50, synth_full_time = 1000; >+int synth_alive = 0, quiet_boot = 0; >+u_char synth_buffer[synthBufferSize]; /* guess what this is for! */ >+static u_char *buffer_highwater = synth_buffer+synthBufferSize-100; >+u_char *buffer_end = synth_buffer+synthBufferSize-1; >+volatile u_char *synth_buff_in = synth_buffer, *synth_buff_out = synth_buffer; >+static irqreturn_t synth_readbuf_handler(int irq, void *dev_id); >+static struct serial_state *serstate; >+ >+static void speakup_unregister_var(short var_id); >+static void start_serial_interrupt(int irq); >+static void speakup_register_devsynth(void); >+ >+static char *xlate(char *s) >+{ >+ static const char finds[] = "nrtvafe"; >+ static const char subs[] = "\n\r\t\013\001\014\033"; >+ static const char hx[] = "0123456789abcdefABCDEF"; >+ char *p = s, *p1, *p2, c; >+ int num; >+ while ( ( p = strchr ( p, '\\' ) ) ) { >+ p1 = p+1; >+ p2 = strchr( finds, *p1 ); >+ if ( p2 ) { >+ *p++ = subs[p2-finds]; >+ p1++; >+ } else if ( *p1 >= '0' && *p1 <= '7' ) { >+ num = ( *p1++ )&7; >+ while ( num < 256 && *p1 >= '0' && *p1 <= '7' ) { >+ num <<= 3; >+ num = ( *p1++ )&7; >+ } >+ *p++ = num; >+ } else if ( *p1 == 'x'&& strchr( hx, p1[1] ) && strchr( hx, p1[2] ) ) { >+ p1++; >+ c = *p1++; >+ if ( c > '9' ) >+ c = ( c-'7' )&0x0f; >+ else >+ c -= '0'; >+ num = c<<4; >+ c = *p1++; >+ if ( c > '9' ) >+ c = ( c-'7' )&0x0f; >+ else >+ c -= '0'; >+ num += c; >+ *p++ = num; >+ } else >+ *p++ = *p1++; >+ p2 = p; >+ while ( *p1 ) *p2++ = *p1++; >+ *p2 = '\0'; >+ } >+ return s; >+} >+ >+struct serial_state *spk_serial_init( int index ) >+{ >+ int baud = 9600, quot = 0; >+ unsigned int cval = 0; >+ int i, cflag = CREAD | HUPCL | CLOCAL | B9600 | CS8; >+ struct serial_state *ser = NULL; >+ >+ if ( synth_port_forced ) { >+ if ( index > 0 ) return NULL; >+ pr_info ( "probe forced to 0x%x by kernel command line\n", >+ synth_port_forced ); >+ for ( i=0; i <= SPK_HI_TTY; i++ ) >+ if ( ( rs_table+i )->port == synth_port_forced ) { >+ ser = rs_table+i; >+ break; >+ } >+ } else ser = rs_table + index; >+ /* Divisor, bytesize and parity */ >+ quot = ser->baud_base / baud; >+ cval = cflag & ( CSIZE | CSTOPB ); >+#if defined( __powerpc__ ) || defined( __alpha__ ) >+ cval >>= 8; >+#else /* !__powerpc__ && !__alpha__ */ >+ cval >>= 4; >+#endif /* !__powerpc__ && !__alpha__ */ >+ if ( cflag & PARENB ) >+ cval |= UART_LCR_PARITY; >+ if ( !( cflag & PARODD ) ) >+ cval |= UART_LCR_EPAR; >+ if ( synth_request_region( ser->port, 8 ) ) { // try to take it back. >+ __release_region(&ioport_resource, ser->port, 8 ); >+ if ( synth_request_region( ser->port, 8 ) ) return NULL; >+ } >+ >+ /* Disable UART interrupts, set DTR and RTS high >+ * and set speed. */ >+ outb( cval | UART_LCR_DLAB, ser->port + UART_LCR ); /* set DLAB */ >+ outb( quot & 0xff, ser->port + UART_DLL ); /* LS of divisor */ >+ outb( quot >> 8, ser->port + UART_DLM ); /* MS of divisor */ >+ outb( cval, ser->port + UART_LCR ); /* reset DLAB */ >+ >+ // Turn off Interrupts >+ outb( 0, ser->port + UART_IER ); >+ outb( UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR ); >+ >+ /* If we read 0xff from the LSR, there is no UART here. */ >+ if ( inb ( ser->port + UART_LSR ) == 0xff ) { >+ synth_release_region( ser->port, 8 ); >+ serstate=NULL; >+ return NULL; >+ } >+ >+ mdelay( 1 ); >+ synth_port_tts = ser->port; >+ serstate=ser; >+ >+ start_serial_interrupt(ser->irq); >+ >+ return ser; >+} >+ >+static void start_serial_interrupt(int irq) >+{ >+ int rv; >+ >+ if (synth->read_buff_add == NULL) >+ return; >+ >+ rv = request_irq(irq, synth_readbuf_handler, SA_SHIRQ, >+ "serial", (void *) synth_readbuf_handler); >+ >+ if (rv) >+ { >+ printk(KERN_ERR "Unable to request Speakup serial I R Q\n"); >+ } >+ // Set MCR >+ outb(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2, synth_port_tts + UART_MCR); >+ // Turn on Interrupts >+ outb(UART_IER_MSI|UART_IER_RLSI|UART_IER_RDI,synth_port_tts+ UART_IER ); >+ inb(synth_port_tts+UART_LSR); >+ inb(synth_port_tts+UART_RX); >+ inb(synth_port_tts+UART_IIR); >+ inb(synth_port_tts+UART_MSR); >+ outb( 1, synth_port_tts + UART_FCR ); /* Turn FIFO On */ >+} >+ >+static void stop_serial_interrupt(void) >+{ >+ if ( synth_port_tts == 0 ) return; >+ >+ // Turn off interrupts >+ outb(0,synth_port_tts+UART_IER); >+ // Free IRQ >+ free_irq(serstate->irq, (void *) synth_readbuf_handler); >+} >+ >+void spk_serial_release( void ) >+{ >+ if ( synth_port_tts == 0 ) return; >+ synth_release_region( synth_port_tts, 8 ); >+ synth_port_tts = 0; >+} >+ >+static irqreturn_t synth_readbuf_handler(int irq, void *dev_id) >+{ >+//printk(KERN_ERR "in irq\n"); >+//pr_warn("in IRQ\n"); >+ int c; >+ while (inb_p(synth_port_tts + UART_LSR) & UART_LSR_DR) >+ { >+ >+ c=inb_p(synth_port_tts+UART_RX); >+ synth->read_buff_add((u_char) c); >+//printk(KERN_ERR "c = %d\n",c); >+//pr_warn("C = %d\n",c); >+ } >+ return IRQ_HANDLED; >+} >+ >+/* sleep for ms milliseconds */ >+void >+synth_delay ( int val ) >+{ >+ if (val == 0) return; >+ synth_timer.expires = jiffies + val; >+ start_timer( synth_timer ); >+ synth_timer_active++; >+} >+ >+static void synth_dummy_catchup(unsigned long data) >+{ >+ synth_stop_timer(); >+ synth_done(); >+} /* a bogus catchup if no synth */ >+ >+void >+synth_stop_timer ( void ) >+{ >+ if ( synth_timer_active ) >+ stop_timer ( synth_timer ); >+ synth_timer_active = 0; >+} >+ >+int synth_done( void ) >+{ >+ synth_buff_out = synth_buff_in = synth_buffer; >+ if (waitqueue_active(&synth_sleeping_list)) { >+ wake_up_interruptible(&synth_sleeping_list); >+ return 0; >+ } >+ return 1; >+} >+ >+static void synth_start(void) >+{ >+ if (!synth_alive) >+ synth_done(); >+ else if (synth->start) >+ synth->start(); >+ else if (synth_timer_active == 0) >+ synth_delay(synth_trigger_time); >+} >+ >+void do_flush( void ) >+{ >+ synth_stop_timer( ); >+ synth_buff_out = synth_buff_in = synth_buffer; >+ if ( synth_alive ) { >+ synth->flush( ); >+ if ( synth->flush_wait ) >+ synth_delay( ( synth->flush_wait * HZ ) / 1000 ); >+ if ( pitch_shift ) { >+ synth_write_string( pitch_buff ); >+ pitch_shift = 0; >+ } >+ } >+ if (waitqueue_active(&synth_sleeping_list)) >+ wake_up_interruptible(&synth_sleeping_list); >+} >+ >+void >+synth_buffer_add ( char ch ) >+{ >+ if ( synth_buff_in >= buffer_highwater ) { >+ synth_start ( ); >+ if ( !waitqueue_active ( &synth_sleeping_list ) ) >+ interruptible_sleep_on ( &synth_sleeping_list ); >+ if ( synth_buff_in >= buffer_end ) return; >+ } >+ *synth_buff_in++ = ch; >+} >+ >+void >+synth_write ( const char *buf, size_t count ) >+{ >+ while ( count-- ) >+ synth_buffer_add ( *buf++ ); >+ synth_start ( ); >+} >+ >+void >+synth_write_string ( const char *buf ) >+{ >+ while ( *buf ) >+ synth_buffer_add ( *buf++ ); >+ synth_start ( ); >+} >+ >+void >+synth_write_msg ( const char *buf ) >+{ >+ while ( *buf ) >+ synth_buffer_add ( *buf++ ); >+ synth_buffer_add ( '\n' ); >+ synth_start ( ); >+} >+ >+static int index_count=0; >+static int sentence_count=0; >+ >+void >+reset_index_count(int sc) >+{ >+ static int first = 1; >+ if (first) >+ first=0; >+ else >+ synth->get_index(); >+ index_count=0; >+ sentence_count=sc; >+} >+ >+int >+synth_supports_indexing( void ) >+{ >+ if ( synth->get_index!=NULL ) >+ return 1; >+ return 0; >+} >+ >+void >+synth_insert_next_index( int sent_num ) >+{ >+ int out; >+ char buf[50]; >+ if ( synth_alive ) { >+ if (sent_num==0) >+ { >+ synth->indexing.currindex++; >+ index_count++; >+ if (synth->indexing.currindex>synth->indexing.highindex) >+ synth->indexing.currindex=synth->indexing.lowindex; >+ } >+ >+ out=synth->indexing.currindex*10+sent_num; >+ sprintf(buf,synth->indexing.command,out,out); >+ synth_write_string(buf); >+ } >+} >+ >+void >+get_index_count(int *linecount,int *sentcount) >+{ >+ int ind=synth->get_index(); >+ if (ind) >+ { >+ sentence_count=ind%10; >+ >+ if ((ind/10)<=synth->indexing.currindex) >+ index_count = synth->indexing.currindex-(ind/10); >+ else >+ index_count = synth->indexing.currindex-synth->indexing.lowindex + synth->indexing.highindex-(ind/10)+1; >+ >+ } >+ *sentcount=sentence_count; >+ *linecount=index_count; >+} >+ >+static struct resource synth_res; >+ >+int synth_request_region ( unsigned long start, unsigned long n ) >+{ >+ struct resource *parent = &ioport_resource; >+ memset ( &synth_res, 0, sizeof ( synth_res ) ); >+ synth_res.name = synth->name; >+ synth_res.start = start; >+ synth_res.end = start + n - 1; >+ synth_res.flags = IORESOURCE_BUSY; >+ return request_resource ( parent, &synth_res ); >+} >+ >+int synth_release_region ( unsigned long start, unsigned long n ) >+{ >+ return release_resource ( &synth_res ); >+} >+ >+#ifdef CONFIG_PROC_FS >+ >+// /proc/synth-specific code >+ >+#include <asm/uaccess.h> >+#include <linux/limits.h> >+ >+// this is the write handler for /proc/speakup/synth-specific/direct >+static int spk_direct_write_proc(struct file *file, const char *buffer, >+ u_long count, void *data) >+{ >+ u_char buf[256]; >+ int ret = count, bytes; >+ const char *ptr = buffer; >+ if ( synth == NULL ) return -EPERM; >+ while ( count > 0 ) { >+ bytes = min_t ( size_t, count, 250 ); >+ if ( copy_from_user ( buf, ptr, bytes ) ) >+ return -EFAULT; >+ buf[bytes] = '\0'; >+ xlate ( buf ); >+ synth_write_string ( buf ); >+ ptr += bytes; >+ count -= bytes; >+ } >+ return ret; >+} >+ >+struct st_proc_var synth_direct = { SYNTH_DIRECT, 0, spk_direct_write_proc, 0 }; >+ >+#endif >+ >+static struct st_num_var synth_time_vars[] = { >+ { DELAY, 0, 100, 100, 2000, 0, 0, 0 }, >+ { TRIGGER, 0, 20, 10, 200, 0, 0, 0 }, >+ { JIFFY, 0, 50, 20, 200, 0, 0, 0 }, >+ { FULL, 0, 400, 200, 10000, 0, 0, 0 }, >+ V_LAST_NUM >+}; >+ >+static struct spk_synth *do_load_synth(const char *synth_name) >+{ >+ int i; >+ >+ if (request_module("speakup_%s", synth_name)) >+ return NULL; >+ >+ for (i = 0; synths[i] != NULL; i++) { >+ if (strcmp(synths[i]->name, synth_name) == 0) >+ return synths[i]; >+ } >+ >+ return NULL; >+} >+ >+int synth_init(char *synth_name) >+{ >+ int i; >+ struct spk_synth *synth = NULL; >+ >+ if (synth_name == NULL) >+ return 0; >+ >+ if (strcmp(synth_name, "none") == 0) { >+ synth_release(); >+ return 0; >+ } >+ >+ /* First, check if we already have it loaded. */ >+ for (i = 0; synths[i] != NULL; i++) >+ if (strcmp(synths[i]->name, synth_name) == 0) >+ synth = synths[i]; >+ >+ /* No synth loaded matching this one, try loading it. */ >+ if (!synth) >+ synth = do_load_synth(synth_name); >+ >+ /* If we got one, initialize it now. */ >+ if (synth) >+ return do_synth_init(synth); >+ >+ return 0; >+} >+ >+int do_synth_init(struct spk_synth *in_synth) >+{ >+ struct st_num_var *n_var; >+ struct st_string_var *s_var; >+ >+ synth_release(); >+ if (in_synth->checkval != SYNTH_CHECK) return -EINVAL; >+ synth = in_synth; >+pr_warn("synth probe\n"); >+ if (synth->probe() < 0) { >+ pr_warn("%s: device probe failed\n", in_synth->name); >+ synth = NULL; >+ return -ENODEV; >+ } >+ synth_time_vars[0].default_val = synth->delay; >+ synth_time_vars[1].default_val = synth->trigger; >+ synth_time_vars[2].default_val = synth->jiffies; >+ synth_time_vars[3].default_val = synth->full; >+ synth_timer.function = synth->catch_up; >+ synth_timer.entry.prev = NULL; >+ init_timer(&synth_timer); >+ for(n_var = synth_time_vars; n_var->var_id >= 0; n_var++) >+ speakup_register_var(n_var); >+ synth_alive = 1; >+ synth_write_string(synth->init); >+ for(s_var = synth->string_vars; s_var->var_id >= 0; s_var++) >+ speakup_register_var((struct st_num_var *) s_var); >+ for(n_var = synth->num_vars; n_var->var_id >= 0; n_var++) >+ speakup_register_var(n_var); >+ if (!quiet_boot) { >+ synth_write_string(synth->long_name); >+ synth_write_msg(" found"); >+ } >+#ifdef CONFIG_PROC_FS >+ speakup_register_var((struct st_num_var *) &synth_direct); >+#endif >+ synth_flags = synth->flags; >+ return 0; >+} >+ >+void >+synth_release ( void ) >+{ >+ struct st_num_var *n_var; >+ struct st_string_var *s_var; >+ if ( synth == NULL ) return; >+ if (down_interruptible ( &sem )) return; >+ pr_info ( "releasing synth %s\n", synth->name ); >+ for ( s_var = synth->string_vars; s_var->var_id >= 0; s_var++ ) >+ speakup_unregister_var( s_var->var_id ); >+ for ( n_var = synth_time_vars; n_var->var_id >= 0; n_var++ ) >+ speakup_unregister_var( n_var->var_id ); >+ for ( n_var = synth->num_vars; n_var->var_id >= 0; n_var++ ) >+ speakup_unregister_var( n_var->var_id ); >+#ifdef CONFIG_PROC_FS >+ speakup_unregister_var( SYNTH_DIRECT ); >+#endif >+ synth_dummy_catchup((unsigned long) NULL ); >+ synth_timer.function = synth_dummy_catchup; >+ stop_serial_interrupt(); >+ synth->release( ); >+ synth = NULL; >+ up( &sem ); >+} >+ >+void synth_add ( struct spk_synth *in_synth ) >+{ >+ int i; >+ for (i = 0; synths[i] != NULL; i++ ) >+ if ( in_synth == synths[i] ) return; >+ synths[i++] = in_synth; >+ synths[i] = NULL; >+} >+ >+void synth_remove ( struct spk_synth *in_synth ) >+{ >+ int i; >+ for (i = 0; synths[i] != NULL; i++ ) { >+ if ( in_synth == synths[i] ) break; >+ } >+for ( ;synths[i] != NULL; i++ ) /* compress table */ >+ synths[i] = synths[i+1]; >+ module_status = 0; >+} >+ >+static struct st_var_header var_headers[] = { >+ { "version", VERSION, VAR_PROC, USER_R, 0, 0, 0 }, >+ { "synth_name", SYNTH, VAR_PROC, USER_RW, 0, 0, 0 }, >+ { "keymap", KEYMAP, VAR_PROC, USER_RW, 0, 0, 0 }, >+ { "silent", SILENT, VAR_PROC, USER_W, 0, 0, 0 }, >+ { "punc_some", PUNC_SOME, VAR_PROC, USER_RW, 0, 0, 0 }, >+ { "punc_most", PUNC_MOST, VAR_PROC, USER_RW, 0, 0, 0 }, >+ { "punc_all", PUNC_ALL, VAR_PROC, USER_R, 0, 0, 0 }, >+ { "delimiters", DELIM, VAR_PROC, USER_RW, 0, 0, 0 }, >+ { "repeats", REPEATS, VAR_PROC, USER_RW, 0, 0, 0 }, >+ { "ex_num", EXNUMBER, VAR_PROC, USER_RW, 0, 0, 0 }, >+ { "characters", CHARS, VAR_PROC, USER_RW, 0, 0, 0 }, >+ { "synth_direct", SYNTH_DIRECT, VAR_PROC, USER_W, 0, 0, 0 }, >+ { "caps_start", CAPS_START, VAR_STRING, USER_RW, 0, str_caps_start, 0 }, >+ { "caps_stop", CAPS_STOP, VAR_STRING, USER_RW, 0, str_caps_stop, 0 }, >+ { "delay_time", DELAY, VAR_TIME, ROOT_W, 0, &synth_delay_time, 0 }, >+ { "trigger_time", TRIGGER, VAR_TIME, ROOT_W, 0, &synth_trigger_time, 0 }, >+ { "jiffy_delta", JIFFY, VAR_TIME, ROOT_W, 0, &synth_jiffy_delta, 0 }, >+ { "full_time", FULL, VAR_TIME, ROOT_W, 0, &synth_full_time, 0 }, >+ { "spell_delay", SPELL_DELAY, VAR_NUM, USER_RW, 0, &spell_delay, 0 }, >+ { "bleeps", BLEEPS, VAR_NUM, USER_RW, 0, &bleeps, 0 }, >+ { "attrib_bleep", ATTRIB_BLEEP, VAR_NUM, USER_RW, 0, &attrib_bleep, 0 }, >+ { "bleep_time", BLEEP_TIME, VAR_TIME, USER_RW, 0, &bleep_time, 0 }, >+ { "cursor_time", CURSOR_TIME, VAR_TIME, USER_RW, 0, &cursor_timeout, 0 }, >+ { "punc_level", PUNC_LEVEL, VAR_NUM, USER_RW, 0, &punc_level, 0 }, >+ { "reading_punc", READING_PUNC, VAR_NUM, USER_RW, 0, &reading_punc, 0 }, >+ { "say_control", SAY_CONTROL, VAR_NUM, USER_RW, 0, &say_ctrl, 0 }, >+ { "say_word_ctl", SAY_WORD_CTL, VAR_NUM, USER_RW, 0, &say_word_ctl, 0 }, >+ { "no_interrupt", NO_INTERRUPT, VAR_NUM, USER_RW, 0, &no_intr, 0 }, >+ { "key_echo", KEY_ECHO, VAR_NUM, USER_RW, 0, &key_echo, 0 }, >+ { "bell_pos", BELL_POS, VAR_NUM, USER_RW, 0, &bell_pos, 0 }, >+ { "rate", RATE, VAR_NUM, USER_RW, 0, 0, 0 }, >+ { "pitch", PITCH, VAR_NUM, USER_RW, 0, 0, 0 }, >+ { "vol", VOL, VAR_NUM, USER_RW, 0, 0, 0 }, >+ { "tone", TONE, VAR_NUM, USER_RW, 0, 0, 0 }, >+ { "punct", PUNCT, VAR_NUM, USER_RW, 0, 0, 0 }, >+ { "voice", VOICE, VAR_NUM, USER_RW, 0, 0, 0 }, >+ { "freq", FREQ, VAR_NUM, USER_RW, 0, 0, 0 }, >+ { "lang", LANG, VAR_NUM, USER_RW, 0, 0, 0 }, >+ { "chartab", CHARTAB, VAR_PROC, USER_RW, 0, 0, 0 }, >+}; >+ >+static struct st_var_header *var_ptrs[MAXVARS] = { 0, 0, 0 }; >+ >+char * >+speakup_s2i ( char *start, short *dest ) >+{ >+ int val; >+ char ch = *start; >+ if ( ch == '-' || ch == '+' ) start++; >+ if ( *start < '0' || *start > '9' ) return start; >+ val = ( *start ) - '0'; >+ start++; >+ while ( *start >= '0' && *start <= '9' ) { >+ val *= 10; >+ val += ( *start ) - '0'; >+ start++; >+ } >+ if ( ch == '-' ) *dest = -val; >+ else *dest = val; >+ return start; >+} >+ >+short punc_masks[] = { 0, SOME, MOST, PUNC, PUNC|B_SYM }; >+ >+// handlers for setting vars >+int set_num_var(short input, struct st_var_header *var, int how) >+{ >+ short val, ret = 0; >+ short *p_val = var->p_val; >+ int l; >+ char buf[32], *cp; >+ struct st_num_var *var_data = var->data; >+ if (var_data == NULL) >+ return E_UNDEF; >+ if (how == E_DEFAULT) { >+ val = var_data->default_val; >+ ret = SET_DEFAULT; >+ } else { >+ if ( how == E_SET ) val = input; >+ else val = var_data->value; >+ if ( how == E_INC ) val += input; >+ else if ( how == E_DEC ) val -= input; >+ if ( val < var_data->low || val > var_data->high ) >+ return E_RANGE; >+ } >+ var_data->value = val; >+ if ( var->var_type == VAR_TIME && p_val != 0 ) { >+ *p_val = ( val * HZ + 1000 - HZ ) / 1000; >+ return ret; >+ } >+ if ( p_val != 0 ) *p_val = val; >+ if ( var->var_id == PUNC_LEVEL ) { >+ punc_mask = punc_masks[val]; >+ return ret; >+ } >+ if ( var_data->multiplier != 0 ) >+ val *= var_data->multiplier; >+ val += var_data->offset; >+ if ( var->var_id < FIRST_SYNTH_VAR || synth == NULL ) return ret; >+ if ( synth->synth_adjust != NULL ) { >+ int status = synth->synth_adjust( var ); >+ return ( status != 0 ) ? status : ret; >+ } >+ if ( !var_data->synth_fmt ) return ret; >+ if ( var->var_id == PITCH ) cp = pitch_buff; >+ else cp = buf; >+ if ( !var_data->out_str ) >+ l = sprintf( cp, var_data->synth_fmt, (int)val ); >+ else l = sprintf( cp, var_data->synth_fmt, var_data->out_str[val] ); >+ synth_write_string( cp ); >+ return ret; >+} >+ >+static int set_string_var(char *page, struct st_var_header *var, int len) >+{ >+ int ret = 0; >+ struct st_string_var *var_data = var->data; >+ if ( var_data == NULL ) return E_UNDEF; >+ if ( len > MAXVARLEN ) >+ return -E_TOOLONG; >+ if ( !len ) { >+ if ( !var_data->default_val ) return 0; >+ ret = SET_DEFAULT; >+ if ( !var->p_val ) var->p_val = var_data->default_val; >+ if ( var->p_val != var_data->default_val ) >+ strcpy( (char *)var->p_val, var_data->default_val ); >+ } else if ( var->p_val ) >+ strcpy( (char *)var->p_val, page ); >+ else return -E_TOOLONG; >+ return ret; >+} >+ >+struct st_var_header *get_var_header(short var_id) >+{ >+ struct st_var_header *p_header; >+ if ( var_id < 0 || var_id >= MAXVARS ) return NULL; >+ p_header = var_ptrs[var_id]; >+ if ( p_header->data == NULL ) return NULL; >+ return p_header; >+} >+ >+#ifdef CONFIG_PROC_FS >+// this is the write handler for /proc/speakup vars >+static int speakup_vars_write_proc(struct file *file, const char *buffer, >+ u_long count, void *data) >+{ >+ struct st_var_header *p_header = data; >+ int len = count, ret = 0; >+ char *page = ( char * ) __get_free_page ( GFP_KERNEL ); >+ char *v_name = p_header->name, *cp; >+ struct st_num_var *var_data; >+ short value; >+ if ( !page ) return -ENOMEM; >+ if ( copy_from_user ( page, buffer, count ) ) { >+ ret = -EFAULT; >+ goto out; >+ } >+ if ( page[len - 1] == '\n' ) --len; >+ page[len] = '\0'; >+ cp = xlate( page ); >+ switch( p_header->var_type ) { >+ case VAR_NUM: >+ case VAR_TIME: >+ if ( *cp == 'd' || *cp == 'r' || *cp == '\0' ) >+ len = E_DEFAULT; >+ else if ( *cp == '+' || *cp == '-' ) len = E_INC; >+ else len = E_SET; >+ speakup_s2i( cp, &value ); >+ ret = set_num_var( value, p_header, len ); >+ if ( ret != E_RANGE ) break; >+ var_data = p_header->data; >+ pr_warn( "value for %s out of range, expect %d to %d\n", >+ v_name, (int)var_data->low, (int)var_data->high ); >+ break; >+ case VAR_STRING: >+ len = strlen( page ); >+ ret = set_string_var( page, p_header, len ); >+ if ( ret != E_TOOLONG ) break; >+ pr_warn( "value too long for %s\n", v_name ); >+ break; >+ default: >+ pr_warn( "%s unknown type %d\n", >+ p_header->name, ( int )p_header->var_type ); >+ break; >+ } >+out: >+ if ( ret == SET_DEFAULT ) >+ pr_info( "%s reset to default value\n", v_name ); >+ free_page ( ( unsigned long ) page ); >+ return count; >+} >+ >+// this is the read handler for /proc/speakup vars >+static int speakup_vars_read_proc(char *page, char **start, off_t off, >+ int count, int *eof, void *data) >+{ >+ struct st_var_header *var = data; >+ struct st_num_var *n_var = var->data; >+ char ch, *cp, *cp1; >+ *start = 0; >+ *eof = 1; >+ switch( var->var_type ) { >+ case VAR_NUM: >+ case VAR_TIME: >+ return sprintf( page, "%d\n", ( int )n_var->value ); >+ break; >+ case VAR_STRING: >+ cp1 = page; >+ *cp1++ = '"'; >+ for ( cp = (char *)var->p_val; ( ch = *cp ); cp++ ) { >+ if ( ch >= ' ' && ch < '~' ) >+ *cp1++ = ch; >+ else >+ cp1 += sprintf( cp1, "\\""x%02x", ch ); >+ } >+ *cp1++ = '"'; >+ *cp1++ = '\n'; >+ *cp1 = '\0'; >+ return cp1-page; >+ break; >+ default: >+ return sprintf( page, "oops bad type %d\n", >+ ( int )var->var_type ); >+ } >+ return 0; >+} >+ >+static const char spk_dir[] = "speakup"; >+static struct proc_dir_entry *dir_ent = 0; >+ >+static int spk_make_proc(struct st_var_header *p_header) >+{ >+ struct proc_dir_entry *ent = p_header->proc_entry; >+ char *name = p_header->name; >+ struct st_proc_var *p_var; >+ if ( dir_ent == 0 || p_header->proc_mode == 0 || ent != 0 ) return 0; >+ ent = create_proc_entry ( name, p_header->proc_mode, dir_ent ); >+ if ( !ent ) { >+ pr_warn( "Unable to create /proc/%s/%s entry.\n", >+ spk_dir, name ); >+ return -1; >+ } >+ if ( p_header->var_type == VAR_PROC ) { >+ p_var = (struct st_proc_var *) p_header->data; >+ if ( p_header->proc_mode&S_IRUSR ) >+ ent->read_proc = p_var->read_proc; >+ if ( p_header->proc_mode&S_IWUSR ) >+ ent->write_proc = p_var->write_proc; >+ } else { >+ if ( p_header->proc_mode&S_IRUSR ) >+ ent->read_proc = speakup_vars_read_proc; >+ if ( p_header->proc_mode&S_IWUSR ) >+ ent->write_proc = speakup_vars_write_proc; >+ } >+ ent->data = ( void * )p_header; >+ p_header->proc_entry = ( void * ) ent; >+ return 0; >+} >+ >+#endif >+ >+int speakup_register_var(struct st_num_var *var) >+{ >+ static char nothing[2] = "\0"; >+ int i, var_id = var->var_id; >+ struct st_var_header *p_header; >+ struct st_string_var *s_var; >+ if (var_id < 0 || var_id >= MAXVARS) >+ return -1; >+ if ( var_ptrs[0] == 0 ) { >+ for ( i = 0; i < MAXVARS; i++ ) { >+ p_header = &var_headers[i]; >+ var_ptrs[p_header->var_id] = p_header; >+ p_header->data = 0; >+ } >+ } >+ p_header = var_ptrs[var_id]; >+ if ( p_header->data != 0 ) return 0; >+ p_header->data = var; >+ switch ( p_header->var_type ) { >+ case VAR_STRING: >+ s_var = (struct st_string_var *) var; >+ set_string_var( nothing, p_header, 0 ); >+ break; >+ case VAR_NUM: >+ case VAR_TIME: >+ set_num_var( 0, p_header, E_DEFAULT ); >+ break; >+ } >+#ifdef CONFIG_PROC_FS >+ return spk_make_proc( p_header ); >+#else >+ return 0; >+#endif >+} >+ >+static void speakup_unregister_var(short var_id) >+{ >+ struct st_var_header *p_header; >+ if ( var_id < 0 || var_id >= MAXVARS ) return; >+ p_header = var_ptrs[var_id]; >+ p_header->data = 0; >+#ifdef CONFIG_PROC_FS >+ if ( dir_ent != 0 && p_header->proc_entry != 0 ) >+ remove_proc_entry( p_header->name, dir_ent ); >+ p_header->proc_entry = 0; >+#endif >+} >+ >+extern char synth_name[]; >+ >+int speakup_dev_init(void) >+{ >+ int i; >+ struct st_var_header *p_header; >+ struct st_proc_var *pv = spk_proc_vars; >+ >+ //pr_warn("synth name on entry is: %s\n", synth_name); >+ synth_init(synth_name); >+ speakup_register_devsynth(); >+#ifdef CONFIG_PROC_FS >+ dir_ent = create_proc_entry(spk_dir, S_IFDIR, 0); >+ if (!dir_ent) { >+ pr_warn("Unable to create /proc/%s entry.\n", spk_dir); >+ return -1; >+ } >+ while(pv->var_id >= 0) { >+ speakup_register_var((void *) pv); >+ pv++; >+ } >+ for (i = 0; i < MAXVARS; i++) { >+ p_header = &var_headers[i]; >+ if ( p_header->data != 0 ) spk_make_proc(p_header); >+ } >+#endif >+ return 0; >+} >+ >+void speakup_remove(void) >+{ >+ int i; >+ >+ for (i = 0; i < MAXVARS; i++) >+ speakup_unregister_var(i); >+ pr_info("speakup: unregistering synth device /dev/synth\n"); >+ misc_deregister(&synth_device); >+ misc_registered = 0; >+#ifdef CONFIG_PROC_FS >+ if (dir_ent != 0) >+ remove_proc_entry(spk_dir, NULL); >+#endif >+} >+ >+// provide a file to users, so people can send to /dev/synth >+ >+static ssize_t >+speakup_file_write ( struct file *fp, const char *buffer, >+ size_t nbytes, loff_t * ppos ) >+{ >+ size_t count = nbytes; >+ const char *ptr = buffer; >+ int bytes; >+ u_char buf[256]; >+ if ( synth == NULL ) return -ENODEV; >+ while ( count > 0 ) { >+ bytes = min_t (size_t, count, sizeof ( buf ) ); >+ if ( copy_from_user ( buf, ptr, bytes ) ) >+ return -EFAULT; >+ count -= bytes; >+ ptr += bytes; >+ synth_write ( buf, bytes ); >+ } >+ return ( ssize_t ) nbytes; >+} >+ >+static int >+speakup_file_ioctl ( struct inode *inode, struct file *file, >+ unsigned int cmd, unsigned long arg ) >+{ >+ return 0; // silently ignore >+} >+ >+static ssize_t >+speakup_file_read ( struct file *fp, char *buf, size_t nbytes, loff_t * ppos ) >+{ >+ return 0; >+} >+ >+static int synth_file_inuse = 0; >+ >+static int >+speakup_file_open ( struct inode *ip, struct file *fp ) >+{ >+ if ( synth_file_inuse ) >+ return -EBUSY; >+ else if ( synth == NULL ) >+ return -ENODEV; >+ synth_file_inuse++; >+ return 0; >+} >+ >+static int >+speakup_file_release ( struct inode *ip, struct file *fp ) >+{ >+ synth_file_inuse = 0; >+ return 0; >+} >+ >+static struct file_operations synth_fops = { >+ read:speakup_file_read, >+ write:speakup_file_write, >+ ioctl:speakup_file_ioctl, >+ open:speakup_file_open, >+ release:speakup_file_release, >+}; >+ >+static void speakup_register_devsynth(void) >+{ >+ if ( misc_registered != 0 ) return; >+ misc_registered = 1; >+ memset( &synth_device, 0, sizeof( synth_device ) ); >+/* zero it so if register fails, deregister will not ref invalid ptrs */ >+ synth_device.minor = SYNTH_MINOR; >+ synth_device.name = "synth"; >+ synth_device.fops = &synth_fops; >+ if ( misc_register ( &synth_device ) ) >+ pr_warn( >+ "Couldn't initialize miscdevice /dev/synth.\n" ); >+ else >+ pr_info( >+ "initialized device: /dev/synth, node ( MAJOR 10, MINOR 25 )\n" ); >+} >+ >+__initcall(speakup_dev_init); >+ >+/* exported symbols needed by synth modules */ >+EXPORT_SYMBOL_GPL(speakup_dev_init); >+EXPORT_SYMBOL_GPL(synth_init); >+EXPORT_SYMBOL_GPL(do_synth_init); >+EXPORT_SYMBOL_GPL(spk_serial_init); >+EXPORT_SYMBOL_GPL(spk_serial_release); >+EXPORT_SYMBOL_GPL(synth); >+EXPORT_SYMBOL_GPL(synth_alive); >+EXPORT_SYMBOL_GPL(synth_buffer); >+EXPORT_SYMBOL_GPL(synth_buff_in); >+EXPORT_SYMBOL_GPL(synth_buff_out); >+EXPORT_SYMBOL_GPL(synth_delay); >+EXPORT_SYMBOL_GPL(synth_delay_time); >+EXPORT_SYMBOL_GPL(synth_done); >+EXPORT_SYMBOL_GPL(synth_full_time); >+EXPORT_SYMBOL_GPL(synth_jiffy_delta); >+EXPORT_SYMBOL_GPL(synth_port_forced); >+EXPORT_SYMBOL_GPL(synth_port_tts); >+EXPORT_SYMBOL_GPL(synth_request_region); >+EXPORT_SYMBOL_GPL(synth_release_region); >+EXPORT_SYMBOL_GPL(synth_release); >+EXPORT_SYMBOL_GPL(synth_add); >+EXPORT_SYMBOL_GPL(synth_remove); >+EXPORT_SYMBOL_GPL(synth_stop_timer); >+EXPORT_SYMBOL_GPL(synth_write_string); >+EXPORT_SYMBOL_GPL(synth_write_msg); >+EXPORT_SYMBOL_GPL(synth_write); >+EXPORT_SYMBOL_GPL(synth_supports_indexing); >+MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>"); >+MODULE_DESCRIPTION("Speakup module required by all synthesizer specific modules"); >+MODULE_LICENSE("GPL"); >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_dtlk.c linux-2.6.20-spk/drivers/char/speakup/speakup_dtlk.c >--- linux-2.6.20/drivers/char/speakup/speakup_dtlk.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_dtlk.c 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,233 @@ >+/* >+ * originially written by: Kirk Reiser <kirk@braille.uwo.ca> >+* this version considerably modified by David Borowski, david575@rogers.com >+ >+ Copyright (C) 1998-99 Kirk Reiser. >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "serialio.h" >+#include "speakup_dtlk.h" /* local header file for DoubleTalk values */ >+ >+#define MY_SYNTH synth_dtlk >+#define PROCSPEECH 0x00 >+#define synth_readable() ((synth_status = inb_p(synth_port_tts)) & TTS_READABLE) >+#define synth_full() ((synth_status = inb_p(synth_port_tts)) & TTS_ALMOST_FULL) >+ >+static int synth_lpc; >+static unsigned int synth_portlist[] = >+ { 0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0 }; >+static u_char synth_status = 0; >+ >+static void spk_out(const char ch) >+{ >+ int tmout = 100000; >+ while (((synth_status = inb_p(synth_port_tts)) & TTS_WRITABLE) == 0); >+ outb_p(ch, synth_port_tts); >+ while ((((synth_status = inb_p(synth_port_tts)) & TTS_WRITABLE) != 0) >+ && (--tmout != 0) ); >+} >+ >+static void do_catch_up(unsigned long data) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+ synth_stop_timer(); >+ synth_status = inb_p(synth_port_tts); >+ while (synth_buff_out < synth_buff_in) { >+ if (synth_status & TTS_ALMOST_FULL) { >+ synth_delay(synth_full_time); >+ return; >+ } >+ ch = *synth_buff_out++; >+ if (ch == 0x0a) ch = PROCSPEECH; >+ spk_out( ch ); >+ if (jiffies >= jiff_max && ch == SPACE) { >+ spk_out(PROCSPEECH); >+ synth_delay(synth_delay_time); >+ return; >+ } >+ } >+ spk_out(PROCSPEECH); >+ synth_done( ); >+} >+ >+static const char *synth_immediate(const char *buf ) >+{ >+ u_char ch; >+ synth_status = inb_p(synth_port_tts); >+ while ( (ch = (u_char)*buf ) ) { >+ if (synth_status & TTS_ALMOST_FULL) >+ return buf; >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ spk_out(ch); >+ buf++; >+ } >+ return 0; >+} >+ >+static unsigned char get_index( void ) >+{ >+ int c, lsr;//, tmout = SPK_SERIAL_TIMEOUT; >+ lsr = inb_p( synth_port_tts + UART_LSR ); >+ if ( ( lsr & UART_LSR_DR) == UART_LSR_DR ) >+ { >+ c = inb_p( synth_port_tts + UART_RX ); >+ return ( unsigned char ) c; >+ } >+ return 0; >+} >+ >+static void synth_flush(void) >+{ >+ outb_p(SYNTH_CLEAR, synth_port_tts); >+ while (((synth_status = inb_p(synth_port_tts)) & TTS_WRITABLE) != 0); >+ } >+ >+static char synth_read_tts(void) >+{ >+ u_char ch; >+ while (((synth_status = inb_p(synth_port_tts)) & TTS_READABLE) == 0); >+ ch = synth_status & 0x7f; >+ outb_p(ch, synth_port_tts); >+ while ((inb_p(synth_port_tts) & TTS_READABLE) != 0); >+return (char) ch; >+} >+ >+/* interrogate the DoubleTalk PC and return its settings */ >+static struct synth_settings * synth_interrogate(void) >+{ >+ u_char *t; >+ static char buf[sizeof(struct synth_settings) + 1]; >+ int total, i; >+ static struct synth_settings status; >+ synth_immediate("\x18\x01?"); >+ for (total = 0, i = 0; i < 50; i++) { >+ buf[total] = synth_read_tts(); >+ if (total > 2 && buf[total] == 0x7f) break; >+ if (total < sizeof(struct synth_settings)) total++; >+ } >+ t = buf; >+ status.serial_number = t[0] + t[1]*256; /* serial number is little endian */ >+ t += 2; >+ for ( i = 0; *t != '\r'; t++ ) { >+ status.rom_version[i] = *t; >+ if (i < sizeof(status.rom_version)-1) i++; >+ } >+ status.rom_version[i] = 0; >+ t++; >+ status.mode = *t++; >+ status.punc_level = *t++; >+ status.formant_freq = *t++; >+ status.pitch = *t++; >+ status.speed = *t++; >+ status.volume = *t++; >+ status.tone = *t++; >+ status.expression = *t++; >+ status.ext_dict_loaded = *t++; >+ status.ext_dict_status = *t++; >+ status.free_ram = *t++; >+ status.articulation = *t++; >+ status.reverb = *t++; >+ status.eob = *t++; >+ return &status; >+} >+ >+static int synth_probe(void) >+{ >+ unsigned int port_val = 0; >+ int i = 0; >+ struct synth_settings *sp; >+ pr_info("Probing for DoubleTalk.\n"); >+ if (synth_port_forced) { >+ synth_port_tts = synth_port_forced; >+ pr_info("probe forced to %x by kernel command line\n", synth_port_tts); >+ if (synth_request_region(synth_port_tts-1, SYNTH_IO_EXTENT)) { >+ pr_warn("sorry, port already reserved\n"); >+ return -EBUSY; >+ } >+ port_val = inw(synth_port_tts-1); >+ synth_lpc = synth_port_tts-1; >+ } else { >+ for(i=0; synth_portlist[i]; i++) { >+ if (synth_request_region(synth_portlist[i], SYNTH_IO_EXTENT)) >+ continue; >+ port_val = inw(synth_portlist[i]); >+ if ((port_val &= 0xfbff) == 0x107f) { >+ synth_lpc = synth_portlist[i]; >+ synth_port_tts = synth_lpc+1; >+ break; >+ } >+ synth_release_region(synth_portlist[i], SYNTH_IO_EXTENT); >+ } >+ } >+ if ((port_val &= 0xfbff) != 0x107f) { >+ pr_info("DoubleTalk PC: not found\n"); >+ return -ENODEV; >+ } >+ while (inw_p(synth_lpc) != 0x147f ); /* wait until it's ready */ >+ sp = synth_interrogate(); >+ pr_info("%s: %03x-%03x, ROM ver %s, s/n %u, driver: %s\n", >+ synth->long_name, synth_lpc, synth_lpc+SYNTH_IO_EXTENT - 1, >+ sp->rom_version, sp->serial_number, synth->version); >+ // synth_alive = 1; >+ return 0; >+} >+ >+static int synth_is_alive(void) >+{ >+ return 1; /* I'm *INVINCIBLE* */ >+} >+ >+static void >+dtlk_release( void ) >+{ >+ if ( synth_port_tts ) >+ synth_release_region(synth_port_tts-1, SYNTH_IO_EXTENT); >+ synth_port_tts = 0; >+} >+ >+static const char init_string[] = "\x01@\x01\x31y"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "\x01+35p" }, >+ { CAPS_STOP, "\x01-35p" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "\x01%ds", 8, 0, 9, 0, 0, 0 }, >+ { PITCH, "\x01%dp", 50, 0, 99, 0, 0, 0 }, >+ { VOL, "\x01%dv", 5, 0, 9, 0, 0, 0 }, >+ { TONE, "\x01%dx", 1, 0, 2, 0, 0, 0 }, >+ { PUNCT, "\x01%db", 7, 0, 15, 0, 0, 0 }, >+ { VOICE, "\x01%do", 0, 0, 7, 0, 0, 0 }, >+ { FREQ, "\x01%df", 5, 0, 9, 0, 0, 0 }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_dtlk = {"dtlk", "1.1", "DoubleTalk PC", >+ init_string, 500, 30, 50, 1000, 0, 0, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, dtlk_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, get_index, >+ {"\x01%di",1,5,1} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_dtlk.h linux-2.6.20-spk/drivers/char/speakup/speakup_dtlk.h >--- linux-2.6.20/drivers/char/speakup/speakup_dtlk.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_dtlk.h 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,54 @@ >+/* speakup_dtlk.h - header file for speakups DoubleTalk driver. */ >+ >+#define SYNTH_IO_EXTENT 0x02 >+#define SYNTH_CLEAR 0x18 /* stops speech */ >+ /* TTS Port Status Flags */ >+#define TTS_READABLE 0x80 /* mask for bit which is nonzero if a >+ byte can be read from the TTS port */ >+#define TTS_SPEAKING 0x40 /* mask for SYNC bit, which is nonzero >+ while DoubleTalk is producing >+ output with TTS, PCM or CVSD >+ synthesizers or tone generators >+ (that is, all but LPC) */ >+#define TTS_SPEAKING2 0x20 /* mask for SYNC2 bit, >+ which falls to zero up to 0.4 sec >+ before speech stops */ >+#define TTS_WRITABLE 0x10 /* mask for RDY bit, which when set to >+ 1, indicates the TTS port is ready >+ to accept a byte of data. The RDY >+ bit goes zero 2-3 usec after >+ writing, and goes 1 again 180-190 >+ usec later. */ >+#define TTS_ALMOST_FULL 0x08 /* mask for AF bit: When set to 1, >+ indicates that less than 300 bytes >+ are available in the TTS input >+ buffer. AF is always 0 in the PCM, >+ TGN and CVSD modes. */ >+#define TTS_ALMOST_EMPTY 0x04 /* mask for AE bit: When set to 1, >+ indicates that less than 300 bytes >+ are remaining in DoubleTalk's input >+ (TTS or PCM) buffer. AE is always 1 >+ in the TGN and CVSD modes. */ >+ >+ /* data returned by Interrogate command */ >+struct synth_settings { >+ u_short serial_number; /* 0-7Fh:0-7Fh */ >+ u_char rom_version[24]; /* null terminated string */ >+ u_char mode; /* 0=Character; 1=Phoneme; 2=Text */ >+ u_char punc_level; /* nB; 0-7 */ >+ u_char formant_freq; /* nF; 0-9 */ >+ u_char pitch; /* nP; 0-99 */ >+ u_char speed; /* nS; 0-9 */ >+ u_char volume; /* nV; 0-9 */ >+ u_char tone; /* nX; 0-2 */ >+ u_char expression; /* nE; 0-9 */ >+ u_char ext_dict_loaded; /* 1=exception dictionary loaded */ >+ u_char ext_dict_status; /* 1=exception dictionary enabled */ >+ u_char free_ram; /* # pages (truncated) remaining for >+ text buffer */ >+ u_char articulation; /* nA; 0-9 */ >+ u_char reverb; /* nR; 0-9 */ >+ u_char eob; /* 7Fh value indicating end of >+ parameter block */ >+ u_char has_indexing; /* nonzero if indexing is implemented */ >+}; >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_keyhelp.c linux-2.6.20-spk/drivers/char/speakup/speakup_keyhelp.c >--- linux-2.6.20/drivers/char/speakup/speakup_keyhelp.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_keyhelp.c 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,288 @@ >+/* speakup_keyhelp.c >+ help module for speakup >+ >+ written by David Borowski. >+ >+ Copyright (C ) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option ) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+*/ >+ >+#include <linux/version.h> >+#include <linux/keyboard.h> >+#include "spk_priv.h" >+ >+extern u_char *our_keys[]; >+extern special_func special_handler; >+extern special_func help_handler; >+#define MAXFUNCS 130 >+#define MAXKEYS 256 >+static u_short key_offsets[MAXFUNCS], key_buf[MAXKEYS]; >+static u_short masks[] = { 32, 16, 8, 4, 2, 1 }; >+static char help_info[] = >+ "press space to leav help, cursor up or down to scroll, or a letter to go to commands in list"; >+static char *statenames[] = { >+ " double", " speakup", " alt", >+ " ctrl", " altgr", " shift" >+}; >+static char *keynames[] = { >+ "escape", "1", "2", "3", "4", >+ "5", "6", "7", "8", "9", >+ "0", "minus", "equal", "back space", "tab", >+ "q", "w", "e", "r", "t", >+ "y", "u", "i", "o", "p", >+ "left brace", "right brace", "enter", "left control", "a", >+ "s", "d", "f", "g", "h", >+ "j", "k", "l", "semicolon", "apostrophe", >+ "accent", "left shift", "back slash", "z", "x", >+ "c", "v", "b", "n", "m", >+ "comma", "dot", "slash", "right shift", "keypad asterisk", >+ "left alt", "space", "caps lock", "f1", "f2", >+ "f3", "f4", "f5", "f6", "f7", >+ "f8", "f9", "f10", "num lock", "scroll lock", >+ "keypad 7", "keypad 8", "keypad 9", "keypad minus", "keypad 4", >+ "keypad 5", "keypad 6", "keypad plus", "keypad 1", "keypad 2", >+ "keypad 3", "keypad 0", "keypad dot", "103rd", "f13", >+ "102nd", "f11", "f12", "f14", "f15", >+ "f16", "f17", "f18", "f19", "f20", >+ "keypad enter", "right control", "keypad slash", "sysrq", "right alt", >+ "line feed", "home", "up", "page up", "left", >+ "right", "end", "down", "page down", "insert", >+ "delete", "macro", "mute", "volume down", "volume up", >+ "power", "keypad equal", "keypad plusminus", "pause", "f21", >+ "f22", "f23", "f24", "keypad comma", "left meta", >+ "right meta", "compose", "stop", "again", "props", >+ "undo", "front", "copy", "open", "paste", >+ "find", "cut", "help", "menu", "calc", >+ "setup", "sleep", "wakeup", "file", "send file", >+ "delete file", "transfer", "prog1", "prog2", "www", >+ "msdos", "coffee", "direction", "cycle windows", "mail", >+ "bookmarks", "computer", "back", "forward", "close cd", >+ "eject cd", "eject close cd", "next song", "play pause", "previous song", >+ "stop cd", "record", "rewind", "phone", "iso", >+ "config", "home page", "refresh", "exit", "move", >+ "edit", "scroll up", "scroll down", "keypad left paren", "keypad right paren", >+}; >+ >+static short letter_offsets[26]; >+ >+static u_char funcvals[] = { >+ ATTRIB_BLEEP_DEC, ATTRIB_BLEEP_INC, BLEEPS_DEC, BLEEPS_INC, >+ SAY_FIRST_CHAR, SAY_LAST_CHAR, SAY_CHAR, SAY_CHAR_NUM, >+ SAY_NEXT_CHAR, SAY_PHONETIC_CHAR, SAY_PREV_CHAR, SPEAKUP_PARKED, >+ SPEAKUP_CUT, EDIT_DELIM, EDIT_EXNUM, EDIT_MOST, >+ EDIT_REPEAT, EDIT_SOME, SPEAKUP_GOTO, BOTTOM_EDGE, >+ LEFT_EDGE, RIGHT_EDGE, TOP_EDGE, SPEAKUP_HELP, >+ SAY_LINE, SAY_NEXT_LINE, SAY_PREV_LINE, SAY_LINE_INDENT, >+ SPEAKUP_PASTE, PITCH_DEC, PITCH_INC, PUNCT_DEC, >+ PUNCT_INC, PUNC_LEVEL_DEC, PUNC_LEVEL_INC, SPEAKUP_QUIET, >+ RATE_DEC, RATE_INC, READING_PUNC_DEC, READING_PUNC_INC, >+ SAY_ATTRIBUTES, SAY_FROM_LEFT, SAY_FROM_TOP, SAY_POSITION, >+ SAY_SCREEN, SAY_TO_BOTTOM, SAY_TO_RIGHT, SPK_KEY, >+ SPK_LOCK, SPEAKUP_OFF, SPEECH_KILL, SPELL_DELAY_DEC, >+ SPELL_DELAY_INC, SPELL_WORD, SPELL_PHONETIC, TONE_DEC, >+ TONE_INC, VOICE_DEC, VOICE_INC, VOL_DEC, >+ VOL_INC, CLEAR_WIN, SAY_WIN, SET_WIN, >+ ENABLE_WIN, SAY_WORD, SAY_NEXT_WORD, SAY_PREV_WORD, 0 >+}; >+ >+static char *funcnames[] = { >+ "attribute bleep decrement", "attribute bleep increment", >+ "bleeps decrement", "bleeps increment", >+ "character, first", "character, last", >+ "character, say current", >+ "character, say hex and decimal", "character, say next", >+ "character, say phonetic", "character, say previous", >+ "cursor park", "cut", >+ "edit delimiters", "edit exnum", >+ "edit most", "edit repeats", "edit some", >+ "go to", "go to bottom edge", "go to left edge", >+ "go to right edge", "go to top edge", "help", >+ "line, say current", "line, say next", >+ "line, say previous", "line, say with indent", >+ "paste", "pitch decrement", "pitch increment", >+ "punctuation decrement", "punctuation increment", >+ "punc level decrement", "punc level increment", >+ "quiet", >+ "rate decrement", "rate increment", >+ "reading punctuation decrement", "reading punctuation increment", >+ "say attributes", >+ "say from left", "say from top", >+ "say position", "say screen", >+ "say to bottom", "say to right", >+ "speakup", "speakup lock", >+ "speakup off", "speech kill", >+ "spell delay decrement", "spell delay increment", >+ "spell word", "spell word phoneticly", >+ "tone decrement", "tone increment", >+ "voice decrement", "voice increment", >+ "volume decrement", "volume increment", >+ "window, clear", "window, say", >+ "window, set", "window, silence", >+ "word, say current", "word, say next", >+ "word, say previous", 0 >+}; >+ >+static u_char *state_tbl; >+static int cur_item = 0, nstates = 0; >+ >+static void build_key_data( void ) >+{ >+ u_char *kp, counters[MAXFUNCS], ch, ch1; >+ u_short *p_key = key_buf, key; >+ int i, offset = 1; >+ nstates = (int)( state_tbl[-1] ); >+ memset( counters, 0, sizeof( counters ) ); >+ memset( key_offsets, 0, sizeof( key_offsets ) ); >+ kp = state_tbl + nstates + 1; >+ while ( *kp++ ) { /* count occurrances of each function */ >+ for ( i = 0; i < nstates; i++, kp++ ) { >+ if ( !*kp ) continue; >+ if ( (state_tbl[i]&16) != 0 && *kp == SPK_KEY ) >+ continue; >+ counters[*kp]++; >+ } >+ } >+ for ( i = 0; i < MAXFUNCS; i++ ) { >+ if ( counters[i] == 0 ) continue; >+ key_offsets[i] = offset; >+ offset += ( counters[i]+1 ); >+ if ( offset >= MAXKEYS ) break; >+ } >+/* leave counters set so high keycodes come first. >+ this is done so num pad and other extended keys maps are spoken before >+ the alpha with speakup type mapping. */ >+ kp = state_tbl + nstates + 1; >+ while ( ( ch = *kp++ ) ) { >+ for ( i = 0; i < nstates; i++ ) { >+ ch1 = *kp++; >+ if ( !ch1 ) continue; >+ if ( (state_tbl[i]&16) != 0 && ch1 == SPK_KEY ) >+ continue; >+ key = ( state_tbl[i]<<8 ) + ch; >+ counters[ch1]--; >+ if ( !(offset = key_offsets[ch1]) ) continue; >+ p_key = key_buf + offset + counters[ch1]; >+ *p_key = key; >+ } >+ } >+} >+ >+static void say_key( int key ) >+{ >+ int i, state = key>>8; >+ key &= 0xff; >+ for ( i = 0; i < 6; i++ ) { >+ if ( ( state & masks[i] ) ) >+ synth_write_string( statenames[i] ); >+ } >+ synth_write_string( " " ); >+ synth_write_msg( keynames[--key] ); >+} >+ >+static int handle_help ( struct vc_data *vc, u_char type, u_char ch, u_short key ) >+{ >+ int i, n; >+ char *name; >+ u_char func, *kp; >+ u_short *p_keys, val; >+ if ( type == KT_LATIN ) { >+ if ( ch == SPACE ) { >+ special_handler = NULL; >+ synth_write_msg( "leaving help" ); >+ return 1; >+ } >+ ch |= 32; /* lower case */ >+ if ( ch < 'a' || ch > 'z' ) return -1; >+ if ( letter_offsets[ch-'a'] == -1 ) { >+ synth_write_string( "no commands for " ); >+ synth_write( &ch, 1 ); >+ synth_write( "\n", 1 ); >+ return 1; >+ } >+ cur_item = letter_offsets[ch-'a']; >+ } else if ( type == KT_CUR ) { >+ if ( ch == 0 && funcnames[cur_item+1] != NULL ) >+ cur_item++; >+ else if ( ch == 3 && cur_item > 0 ) >+ cur_item--; >+ else return -1; >+ } else if (type == KT_SPKUP && ch == SPEAKUP_HELP && !special_handler) { >+ special_handler = help_handler; >+ synth_write_msg( help_info ); >+ build_key_data( ); /* rebuild each time in case new mapping */ >+ return 1; >+ } else { >+ name = NULL; >+ if ( type != KT_SPKUP ) { >+ synth_write_msg( keynames[key-1] ); >+ return 1; >+ } >+ for ( i = 0; funcvals[i] != 0 && !name; i++ ) { >+ if ( ch == funcvals[i] ) >+ name = funcnames[i]; >+ } >+ if ( !name ) return -1; >+ kp = our_keys[key]+1; >+ for ( i = 0; i < nstates; i++ ) { >+ if ( ch == kp[i] ) break; >+ } >+ key += ( state_tbl[i]<<8 ); >+ say_key( key ); >+ synth_write_string( "is " ); >+ synth_write_msg( name ); >+ return 1; >+ } >+ name = funcnames[cur_item]; >+ func = funcvals[cur_item]; >+ synth_write_string( name ); >+ if ( key_offsets[func] == 0 ) { >+ synth_write_msg( " is unassigned" ); >+ return 1; >+ } >+ p_keys = key_buf + key_offsets[func]; >+ for ( n = 0; p_keys[n]; n++ ) { >+ val = p_keys[n]; >+ if ( n > 0 ) synth_write_string( "or " ); >+ say_key( val ); >+ } >+ return 1; >+} >+ >+static void __exit mod_help_exit( void ) >+{ >+ help_handler = 0; >+} >+ >+static int __init mod_help_init( void ) >+{ >+ char start = SPACE; >+ int i; >+state_tbl = our_keys[0]+SHIFT_TBL_SIZE+2; >+ for (i = 0; i < 26; i++ ) letter_offsets[i] = -1; >+ for ( i = 0; funcnames[i]; i++ ) { >+ if ( start == *funcnames[i] ) continue; >+ start = *funcnames[i]; >+ letter_offsets[(start&31)-1] = i; >+ } >+ help_handler = handle_help; >+ return 0; >+} >+ >+module_init( mod_help_init ); >+module_exit( mod_help_exit ); >+MODULE_AUTHOR("David Borowski"); >+MODULE_DESCRIPTION("Speakup keyboard help MODULE"); >+MODULE_LICENSE("GPL"); >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_keypc.c linux-2.6.20-spk/drivers/char/speakup/speakup_keypc.c >--- linux-2.6.20/drivers/char/speakup/speakup_keypc.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_keypc.c 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,190 @@ >+/* >+* written by David Borowski >+ >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+ >+#define MY_SYNTH synth_keypc >+#define SYNTH_IO_EXTENT 0x04 >+#define SWAIT udelay( 70 ) >+#define synth_writable( ) ( inb_p( synth_port ) & 0x10 ) >+#define synth_readable( ) ( inb_p( synth_port ) & 0x10 ) >+#define synth_full( ) ( ( inb_p( synth_port ) & 0x80 ) == 0 ) >+#define PROCSPEECH 0x1f >+#define SYNTH_CLEAR 0x03 >+ >+static int synth_port; >+static unsigned int synth_portlist[] = >+ { 0x2a8, 0 }; >+ >+static int >+oops( void ) >+{ >+ int s1, s2, s3, s4; >+ s1 = inb_p( synth_port ); >+ s2 = inb_p( synth_port+1 ); >+ s3 = inb_p( synth_port+2 ); >+ s4 = inb_p( synth_port+3 ); >+ pr_warn( "synth timeout %d %d %d %d\n", s1, s2, s3, s4 ); >+ return 0; >+} >+ >+static const char *synth_immediate ( const char *buf ) >+{ >+ u_char ch; >+ int timeout; >+ while ( ( ch = *buf ) ) { >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( synth_full( ) ) >+ return buf; >+ timeout = 1000; >+ while ( synth_writable( ) ) >+ if ( --timeout <= 0 ) return (char *) oops( ); >+ outb_p( ch, synth_port ); >+ SWAIT; >+ buf++; >+ } >+ return 0; >+} >+ >+static void do_catch_up( unsigned long data ) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+ int timeout; >+ synth_stop_timer( ); >+ while ( synth_buff_out < synth_buff_in ) { >+ if ( synth_full( ) ) { >+ synth_delay( synth_full_time ); >+ return; >+ } >+ timeout = 1000; >+ while ( synth_writable( ) ) >+ if ( --timeout <= 0 ) break; >+ if ( timeout <= 0 ) { >+ oops( ); >+ break; >+ } >+ ch = *synth_buff_out++; >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ outb_p( ch, synth_port ); >+ SWAIT; >+ if ( jiffies >= jiff_max && ch == SPACE ) { >+ timeout = 1000; >+ while ( synth_writable( ) ) >+ if ( --timeout <= 0 ) break; >+ if ( timeout <= 0 ) { >+ oops( ); >+ break; >+ } >+ outb_p( PROCSPEECH, synth_port ); >+ synth_delay( synth_delay_time ); >+ return; >+ } >+ } >+ timeout = 1000; >+ while ( synth_writable( ) ) >+ if ( --timeout <= 0 ) break; >+ if ( timeout <= 0 ) oops( ); >+ else >+ outb_p( PROCSPEECH, synth_port ); >+ synth_done( ); >+} >+ >+static void synth_flush( void ) >+{ >+ outb_p( SYNTH_CLEAR, synth_port ); >+} >+ >+static int synth_probe( void ) >+{ >+ unsigned int port_val = 0; >+ int i = 0; >+ pr_info( "Probing for %s.\n", synth->long_name ); >+ if ( synth_port_forced ) { >+ synth_port = synth_port_forced; >+ pr_info( "probe forced to %x by kernel command line\n", synth_port ); >+ if ( synth_request_region( synth_port-1, SYNTH_IO_EXTENT ) ) { >+ pr_warn( "sorry, port already reserved\n" ); >+ return -EBUSY; >+ } >+ port_val = inb( synth_port ); >+ } else { >+ for( i=0; synth_portlist[i]; i++ ) { >+ if ( synth_request_region( synth_portlist[i], SYNTH_IO_EXTENT ) ) { >+ pr_warn( "request_region: failed with 0x%x, %d\n", >+ synth_portlist[i], SYNTH_IO_EXTENT ); >+ continue; >+ } >+ port_val = inb( synth_portlist[i] ); >+ if ( port_val == 0x80 ) { >+ synth_port = synth_portlist[i]; >+ break; >+ } >+ } >+ } >+ if ( port_val != 0x80 ) { >+ pr_info( "%s: not found\n", synth->long_name ); >+ synth_release_region( synth_portlist[i], SYNTH_IO_EXTENT ); >+ synth_port = 0; >+ return -ENODEV; >+ } >+ pr_info( "%s: %03x-%03x, driver version %s,\n", synth->long_name, >+ synth_port, synth_port+SYNTH_IO_EXTENT-1, >+ synth->version ); >+ return 0; >+} >+ >+static void keynote_release( void ) >+{ >+ if ( synth_port ) >+ synth_release_region( synth_port, SYNTH_IO_EXTENT ); >+ synth_port = 0; >+} >+ >+static int synth_is_alive( void ) >+{ >+ synth_alive = 1; >+ return 1; >+} >+ >+static const char init_string[] = "[t][n7,1][n8,0]"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "[f130]" }, >+ { CAPS_STOP, "[f90]" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "\04%c ", 8, 0, 10, 81, -8, 0 }, >+ { PITCH, "[f%d]", 5, 0, 9, 40, 10, 0 }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_keypc = {"keypc", "1.1", "Keynote PC", >+ init_string, 500, 50, 50, 1000, 0, 0, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, keynote_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL, >+ {NULL,0,0,0} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_ltlk.c linux-2.6.20-spk/drivers/char/speakup/speakup_ltlk.c >--- linux-2.6.20/drivers/char/speakup/speakup_ltlk.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_ltlk.c 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,229 @@ >+/* >+ * originally written by: Kirk Reiser <kirk@braille.uwo.ca> >+* this version considerably modified by David Borowski, david575@rogers.com >+ >+ Copyright (C) 1998-99 Kirk Reiser. >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "serialio.h" >+ >+#include "speakup_dtlk.h" /* local header file for LiteTalk values */ >+ >+#define MY_SYNTH synth_ltlk >+#define PROCSPEECH 0x0d >+#define synth_full( ) ( !( inb( synth_port_tts + UART_MSR ) & UART_MSR_CTS ) ) >+ >+static int wait_for_xmitr( void ) >+{ >+ static int timeouts = 0; /* sequential number of timeouts */ >+ int check, tmout = SPK_XMITR_TIMEOUT; >+ if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) { >+ synth_alive = 0; >+ timeouts = 0; >+ return 0; >+ } >+ do { /* holding register empty? */ >+ check = inb( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) { >+ pr_warn( "%s: register timed out\n", synth->long_name ); >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY ); >+ tmout = SPK_XMITR_TIMEOUT; >+ do { /* CTS */ >+ check = inb( synth_port_tts + UART_MSR ); >+ if ( --tmout == 0 ) { >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS ); >+ timeouts = 0; >+ return 1; >+} >+ >+static int spk_serial_out( const char ch ) >+{ >+ if ( synth_alive && wait_for_xmitr( ) ) { >+ outb( ch, synth_port_tts ); >+ return 1; >+ } >+ return 0; >+} >+ >+static unsigned char spk_serial_in( void ) >+{ >+ int c, lsr, tmout = SPK_SERIAL_TIMEOUT; >+ do { >+ lsr = inb( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) { >+ pr_warn( "time out while waiting for input.\n" ); >+ return 0xff; >+ } >+ } while ( ( lsr & UART_LSR_DR ) != UART_LSR_DR ); >+ c = inb( synth_port_tts + UART_RX ); >+ return ( unsigned char ) c; >+} >+ >+static void do_catch_up( unsigned long data ) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+ synth_stop_timer( ); >+ while ( synth_buff_out < synth_buff_in ) { >+ ch = *synth_buff_out; >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( !spk_serial_out( ch ) ) { >+ synth_delay( synth_full_time ); >+ return; >+ } >+ synth_buff_out++; >+ if ( jiffies >= jiff_max && ch == SPACE ) { >+ spk_serial_out( PROCSPEECH ); >+ synth_delay( synth_delay_time ); >+ return; >+ } >+ } >+ spk_serial_out( PROCSPEECH ); >+ synth_done ( ); >+} >+ >+static const char *synth_immediate ( const char *buf ) >+{ >+ u_char ch; >+ while ( ( ch = *buf ) ) { >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( wait_for_xmitr( ) ) >+ outb( ch, synth_port_tts ); >+ else return buf; >+ buf++; >+ } >+ return 0; >+} >+ >+static void synth_flush( void ) >+{ >+ spk_serial_out( SYNTH_CLEAR ); >+} >+ >+static unsigned char get_index( void ) >+{ >+ int c, lsr;//, tmout = SPK_SERIAL_TIMEOUT; >+ lsr = inb( synth_port_tts + UART_LSR ); >+ if ( ( lsr & UART_LSR_DR) == UART_LSR_DR ) >+ { >+ c = inb( synth_port_tts + UART_RX ); >+ return ( unsigned char ) c; >+ } >+ return 0; >+} >+ >+/* interrogate the LiteTalk and print its settings */ >+static void synth_interrogate( void ) >+{ >+ unsigned char *t, i; >+ unsigned char buf[50], rom_v[20]; >+ synth_immediate( "\x18\x01?" ); >+ for ( i = 0; i < 50; i++ ) { >+ buf[i] = spk_serial_in( ); >+ if ( i > 2 && buf[i] == 0x7f ) break; >+ } >+ t = buf+2; >+ for ( i = 0; *t != '\r'; t++ ) { >+ rom_v[i] = *t; >+ if (i++ > 48) break; >+ } >+ rom_v[i] = 0; >+ pr_info( "%s: ROM version: %s\n", synth->long_name, rom_v ); >+} >+ >+static int serprobe( int index ) >+{ >+ struct serial_state *ser = spk_serial_init( index ); >+ if ( ser == NULL ) return -1; >+ outb( 0, ser->port ); >+ mdelay( 1 ); >+ outb( '\r', ser->port ); >+ /* ignore any error results, if port was forced */ >+ if ( synth_port_forced ) return 0; >+ /* check for device... */ >+ if ( !synth_immediate( "\x18" ) ) return 0; >+ spk_serial_release( ); >+ synth_alive = 0; /* try next port */ >+ return -1; >+} >+ >+static int synth_probe( void ) >+{ >+ int i, failed=0; >+ pr_info( "Probing for %s.\n", synth->long_name ); >+ for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) { >+ if (( failed = serprobe( i )) == 0 ) break; /* found it */ >+ } >+ if ( failed ) { >+ pr_info( "%s: not found\n", synth->long_name ); >+ return -ENODEV; >+ } >+ synth_interrogate( ); >+ pr_info( "%s: at %03x-%03x, driver %s\n", synth->long_name, >+ synth_port_tts, synth_port_tts + 7, synth->version ); >+ return 0; >+} >+ >+static int synth_is_alive( void ) >+{ >+ if ( synth_alive ) return 1; >+ if ( !synth_alive && wait_for_xmitr( ) > 0 ) { /* restart */ >+ synth_alive = 1; >+ synth_write_string( synth->init ); >+ return 2; >+ } else pr_warn( "%s: can't restart synth\n", synth->long_name ); >+ return 0; >+} >+ >+static const char init_string[] = "\01@\x01\x31y\n\0"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "\x01+35p" }, >+ { CAPS_STOP, "\x01-35p" }, >+ V_LAST_STRING >+}; >+ >+static struct st_num_var numvars[] = { >+ { RATE, "\x01%ds", 8, 0, 9, 0, 0, 0 }, >+ { PITCH, "\x01%dp", 50, 0, 99, 0, 0, 0 }, >+ { VOL, "\x01%dv", 5, 0, 9, 0, 0, 0 }, >+ { TONE, "\x01%dx", 1, 0, 2, 0, 0, 0 }, >+ { PUNCT, "\x01%db", 7, 0, 15, 0, 0, 0 }, >+ { VOICE, "\x01%do", 0, 0, 7, 0, 0, 0 }, >+ { FREQ, "\x01%df", 5, 0, 9, 0, 0, 0 }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_ltlk = { "ltlk", "1.1", "LiteTalk", >+ init_string, 500, 50, 50, 5000, 0, 0, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, spk_serial_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, get_index, >+ {"\x01%di",1,5,1} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakupmap.h linux-2.6.20-spk/drivers/char/speakup/speakupmap.h >--- linux-2.6.20/drivers/char/speakup/speakupmap.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakupmap.h 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,65 @@ >+ 119, 62, 6, >+ 0, 16, 20, 17, 32, 48, 0, >+ 2, 0, 78, 0, 0, 0, 0, >+ 3, 0, 79, 0, 0, 0, 0, >+ 4, 0, 76, 0, 0, 0, 0, >+ 5, 0, 77, 0, 0, 0, 0, >+ 6, 0, 74, 0, 0, 0, 0, >+ 7, 0, 75, 0, 0, 0, 0, >+ 9, 0, 5, 46, 0, 0, 0, >+ 10, 0, 4, 0, 0, 0, 0, >+ 11, 0, 0, 1, 0, 0, 0, >+ 12, 0, 27, 0, 33, 0, 0, >+ 19, 0, 47, 0, 0, 0, 0, >+ 21, 0, 29, 17, 0, 0, 0, >+ 22, 0, 15, 0, 0, 0, 0, >+ 23, 0, 14, 0, 0, 0, 28, >+ 24, 0, 16, 0, 0, 0, 0, >+ 25, 0, 30, 18, 0, 0, 0, >+ 28, 0, 3, 26, 0, 0, 0, >+ 35, 0, 31, 0, 0, 0, 0, >+ 36, 0, 12, 0, 0, 0, 0, >+ 37, 0, 11, 0, 0, 0, 22, >+ 38, 0, 13, 0, 0, 0, 0, >+ 39, 0, 32, 7, 0, 0, 0, >+ 40, 0, 23, 0, 0, 0, 0, >+ 44, 0, 44, 0, 0, 0, 0, >+ 49, 0, 24, 0, 0, 0, 0, >+ 50, 0, 9, 19, 6, 0, 0, >+ 51, 0, 8, 0, 0, 0, 36, >+ 52, 0, 10, 20, 0, 0, 0, >+ 53, 0, 25, 0, 0, 0, 0, >+ 55, 46, 1, 0, 0, 0, 0, >+ 58, 128, 128, 0, 0, 0, 0, >+ 59, 0, 45, 0, 0, 0, 0, >+ 60, 0, 40, 0, 0, 0, 0, >+ 61, 0, 41, 0, 0, 0, 0, >+ 62, 0, 42, 0, 0, 0, 0, >+ 63, 0, 34, 0, 0, 0, 0, >+ 64, 0, 35, 0, 0, 0, 0, >+ 65, 0, 37, 0, 0, 0, 0, >+ 66, 0, 38, 0, 0, 0, 0, >+ 67, 0, 66, 0, 39, 0, 0, >+ 68, 0, 67, 0, 0, 0, 0, >+ 71, 15, 19, 0, 0, 0, 0, >+ 72, 14, 29, 0, 0, 28, 0, >+ 73, 16, 17, 0, 0, 0, 0, >+ 74, 27, 33, 0, 0, 0, 0, >+ 75, 12, 31, 0, 0, 0, 0, >+ 76, 11, 21, 0, 0, 22, 0, >+ 77, 13, 32, 0, 0, 0, 0, >+ 78, 23, 43, 0, 0, 0, 0, >+ 79, 9, 20, 0, 0, 0, 0, >+ 80, 8, 30, 0, 0, 36, 0, >+ 81, 10, 18, 0, 0, 0, 0, >+ 82, 128, 128, 0, 0, 0, 0, >+ 83, 24, 25, 0, 0, 0, 0, >+ 87, 0, 68, 0, 0, 0, 0, >+ 88, 0, 69, 0, 0, 0, 0, >+ 96, 3, 26, 0, 0, 0, 0, >+ 98, 4, 5, 0, 0, 0, 0, >+ 99, 2, 0, 0, 0, 0, 0, >+ 104, 0, 6, 0, 0, 0, 0, >+ 109, 0, 7, 0, 0, 0, 0, >+ 125, 128, 128, 0, 0, 0, 0, >+ 0, 119 >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakupmap.map linux-2.6.20-spk/drivers/char/speakup/speakupmap.map >--- linux-2.6.20/drivers/char/speakup/speakupmap.map 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakupmap.map 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,93 @@ >+spk key_f9 = punc_level_dec >+spk key_f10 = punc_level_inc >+spk key_f11 = reading_punc_dec >+spk key_f12 = reading_punc_inc >+spk key_1 = vol_dec >+spk key_2 = vol_inc >+spk key_3 = pitch_dec >+spk key_4 = pitch_inc >+spk key_5 = rate_dec >+spk key_6 = rate_inc >+key_kpasterisk = toggle_cursoring >+ctrl spk key_8 = toggle_cursoring >+spk key_kpasterisk = speakup_goto >+spk key_f1 = speakup_help >+spk key_f2 = set_win >+spk key_f3 = clear_win >+spk key_f4 = enable_win >+spk key_f5 = edit_some >+spk key_f6 = edit_most >+spk key_f7 = edit_delim >+spk key_f8 = edit_repeat >+shift spk key_f9 = edit_exnum >+ key_kp7 = say_prev_line >+spk key_kp7 = left_edge >+ key_kp8 = say_line >+double key_kp8 = say_line_indent >+spk key_kp8 = say_from_top >+ key_kp9 = say_next_line >+spk key_kp9 = top_edge >+ key_kpminus = speakup_parked >+spk key_kpminus = say_char_num >+ key_kp4 = say_prev_word >+spk key_kp4 = say_from_left >+ key_kp5 = say_word >+double key_kp5 = spell_word >+spk key_kp5 = spell_phonetic >+ key_kp6 = say_next_word >+spk key_kp6 = say_to_right >+ key_kpplus = say_screen >+spk key_kpplus = say_win >+ key_kp1 = say_prev_char >+spk key_kp1 = right_edge >+ key_kp2 = say_char >+spk key_kp2 = say_to_bottom >+double key_kp2 = say_phonetic_char >+ key_kp3 = say_next_char >+spk key_kp3 = bottom_edge >+ key_kp0 = spk_key >+ key_kpdot = say_position >+spk key_kpdot = say_attributes >+key_kpenter = speakup_quiet >+spk key_kpenter = speakup_off >+key_sysrq = speech_kill >+ key_kpslash = speakup_cut >+spk key_kpslash = speakup_paste >+spk key_pageup = say_first_char >+spk key_pagedown = say_last_char >+key_capslock = spk_key >+ spk key_z = spk_lock >+key_leftmeta = spk_key >+ctrl spk key_0 = speakup_goto >+spk key_u = say_prev_line >+spk key_i = say_line >+double spk key_i = say_line_indent >+spk key_o = say_next_line >+spk key_minus = speakup_parked >+shift spk key_minus = say_char_num >+spk key_j = say_prev_word >+spk key_k = say_word >+double spk key_k = spell_word >+spk key_l = say_next_word >+spk key_m = say_prev_char >+spk key_comma = say_char >+double spk key_comma = say_phonetic_char >+spk key_dot = say_next_char >+spk key_n = say_position >+ ctrl spk key_m = left_edge >+ ctrl spk key_y = top_edge >+ ctrl spk key_dot = right_edge >+ctrl spk key_p = bottom_edge >+spk key_apostrophe = say_screen >+spk key_h = say_from_left >+spk key_y = say_from_top >+spk key_semicolon = say_to_right >+spk key_p = say_to_bottom >+spk key_slash = say_attributes >+ spk key_enter = speakup_quiet >+ ctrl spk key_enter = speakup_off >+ spk key_9 = speakup_cut >+spk key_8 = speakup_paste >+shift spk key_m = say_first_char >+ ctrl spk key_semicolon = say_last_char >+spk key_r = read_all_doc >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_sftsyn.c linux-2.6.20-spk/drivers/char/speakup/speakup_sftsyn.c >--- linux-2.6.20/drivers/char/speakup/speakup_sftsyn.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_sftsyn.c 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,206 @@ >+/* speakup_sftsynth.c - speakup driver to register and make available >+ * a user space device for software synthesizers. written by: Kirk >+ * Reiser <kirk@braille.uwo.ca> >+ >+ Copyright (C) 2003 Kirk Reiser. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. */ >+ >+#include <linux/unistd.h> >+#include <asm/semaphore.h> >+#include <linux/miscdevice.h> /* for misc_register, and SYNTH_MINOR */ >+#include <linux/poll.h> // for poll_wait() >+#include "spk_priv.h" >+ >+#define MY_SYNTH synth_sftsyn >+#define SOFTSYNTH_MINOR 26 // might as well give it one more than /dev/synth >+#define PROCSPEECH 0x0d >+#define CLEAR_SYNTH 0x18 >+ >+static struct miscdevice synth_device; >+static int misc_registered = 0; >+static int dev_opened = 0; >+static DECLARE_MUTEX(sem); >+DECLARE_WAIT_QUEUE_HEAD ( wait_on_output ); >+ >+ >+static int softsynth_open (struct inode *inode, struct file *fp) >+{ >+ if (dev_opened) return -EBUSY; >+ //if ((fp->f_flags & O_ACCMODE) != O_RDONLY ) return -EPERM; >+ dev_opened++; >+ return 0; >+} >+ >+static int softsynth_close (struct inode *inode, struct file *fp) >+{ >+ fp->f_op = NULL; >+ dev_opened = 0; >+ return 0; >+} >+ >+static ssize_t softsynth_read (struct file *fp, char *buf, size_t count, loff_t *pos) >+{ >+ int chars_sent=0; >+ >+ if (down_interruptible( &sem )) return -ERESTARTSYS; >+ while (synth_buff_in == synth_buff_out) { >+ up ( &sem ); >+ if (fp->f_flags & O_NONBLOCK) >+ return -EAGAIN; >+ if (wait_event_interruptible( wait_on_output, (synth_buff_in > synth_buff_out))) >+ return -ERESTARTSYS; >+ if (down_interruptible( &sem )) return -ERESTARTSYS; >+ } >+ >+ chars_sent = (count > synth_buff_in-synth_buff_out) >+ ? synth_buff_in-synth_buff_out : count; >+ if (copy_to_user(buf, (char *) synth_buff_out, chars_sent)) { >+ up ( &sem); >+ return -EFAULT; >+ } >+ synth_buff_out += chars_sent; >+ *pos += chars_sent; >+ if (synth_buff_out >= synth_buff_in) { >+ synth_done(); >+ *pos = 0; >+ } >+ up ( &sem ); >+ return chars_sent; >+} >+ >+static int last_index=0; >+ >+static ssize_t softsynth_write (struct file *fp, const char *buf, size_t count, loff_t *pos) >+{ >+ int i; >+ char indbuf[5]; >+ if (down_interruptible( &sem)) >+ return -ERESTARTSYS; >+ >+ if (copy_from_user(indbuf,buf,count)) >+ { >+ up(&sem); >+ return -EFAULT; >+ } >+ up(&sem); >+ last_index=0; >+ for (i=0;i<strlen(indbuf);i++) >+ last_index=last_index*10+indbuf[i]-48; >+ return count; >+} >+ >+static unsigned int softsynth_poll (struct file *fp, struct poll_table_struct *wait) >+{ >+ poll_wait(fp, &wait_on_output, wait); >+ >+ if (synth_buff_out < synth_buff_in) >+ return (POLLIN | POLLRDNORM); >+ return 0; >+} >+ >+static void >+softsynth_flush( void ) >+{ >+ synth_write( "\x18", 1 ); >+} >+ >+static unsigned char get_index( void ) >+{ >+ int rv; >+ rv=last_index; >+ last_index=0; >+ return rv; >+} >+ >+static struct file_operations softsynth_fops = { >+ poll:softsynth_poll, >+ read:softsynth_read, >+ write:softsynth_write, >+ open:softsynth_open, >+ release:softsynth_close, >+}; >+ >+ >+static int >+softsynth_probe( void ) >+{ >+ >+ if ( misc_registered != 0 ) return 0; >+ memset( &synth_device, 0, sizeof( synth_device ) ); >+ synth_device.minor = SOFTSYNTH_MINOR; >+ synth_device.name = "softsynth"; >+ synth_device.fops = &softsynth_fops; >+ if ( misc_register ( &synth_device ) ) { >+ pr_warn("Couldn't initialize miscdevice /dev/softsynth.\n" ); >+ return -ENODEV; >+ } >+ >+ misc_registered = 1; >+ pr_info("initialized device: /dev/softsynth, node (MAJOR 10, MINOR 26)\n" ); >+ return 0; >+} >+ >+static void >+softsynth_release(void) >+{ >+ misc_deregister( &synth_device ); >+ misc_registered = 0; >+ pr_info("unregistered /dev/softsynth\n"); >+} >+ >+static void >+softsynth_start ( void ) >+{ >+ wake_up_interruptible ( &wait_on_output ); >+} >+ >+static int >+softsynth_is_alive( void ) >+{ >+ if ( synth_alive ) return 1; >+ return 0; >+} >+ >+static const char init_string[] = "\01@\x01\x31y\n"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "\x01+3p" }, >+ { CAPS_STOP, "\x01-3p" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "\x01%ds", 5, 0, 9, 0, 0, 0 }, >+ { PITCH, "\x01%dp", 5, 0, 9, 0, 0, 0 }, >+ { VOL, "\x01%dv", 5, 0, 9, 0, 0, 0 }, >+ { TONE, "\x01%dx", 1, 0, 2, 0, 0, 0 }, >+ { PUNCT, "\x01%db", 7, 0, 15, 0, 0, 0 }, >+ { VOICE, "\x01%do", 0, 0, 7, 0, 0, 0 }, >+ { FREQ, "\x01%df", 5, 0, 9, 0, 0, 0 }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_sftsyn = { "sftsyn", "0.3", "software synth", >+ init_string, 0, 0, 0, 0, 0, 0, SYNTH_CHECK, >+ stringvars, numvars, softsynth_probe, softsynth_release, NULL, >+ NULL, softsynth_start, softsynth_flush, softsynth_is_alive, NULL, NULL, >+ get_index, {"\x01%di",1,5,1} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_spkout.c linux-2.6.20-spk/drivers/char/speakup/speakup_spkout.c >--- linux-2.6.20/drivers/char/speakup/speakup_spkout.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_spkout.c 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,201 @@ >+/* >+ * originially written by: Kirk Reiser <kirk@braille.uwo.ca> >+* this version considerably modified by David Borowski, david575@rogers.com >+ >+ Copyright (C) 1998-99 Kirk Reiser. >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "serialio.h" >+ >+#define MY_SYNTH synth_spkout >+#define SYNTH_CLEAR 0x18 >+#define PROCSPEECH '\r' >+ >+static int wait_for_xmitr(void) >+{ >+ static int timeouts = 0; /* sequential number of timeouts */ >+ int check, tmout = SPK_XMITR_TIMEOUT; >+ if ((synth_alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { >+ synth_alive = 0; >+ timeouts = 0; >+ return 0; >+ } >+ do { >+ check = inb(synth_port_tts + UART_LSR); >+ if (--tmout == 0) { >+ pr_warn("SpeakOut: timed out\n"); >+ timeouts++; >+ return 0; >+ } >+ } while ((check & BOTH_EMPTY) != BOTH_EMPTY); >+ tmout = SPK_XMITR_TIMEOUT; >+ do { >+ check = inb(synth_port_tts + UART_MSR); >+ if (--tmout == 0) { >+ timeouts++; >+ return 0; >+ } >+ } while ((check & UART_MSR_CTS) != UART_MSR_CTS); >+ timeouts = 0; >+ return 1; >+} >+ >+static int spk_serial_out(const char ch) >+{ >+ if (synth_alive && wait_for_xmitr()) { >+ outb(ch, synth_port_tts); >+ return 1; >+ } >+ return 0; >+} >+ >+static unsigned char spk_serial_in(void) >+{ >+ int c, lsr, tmout = SPK_SERIAL_TIMEOUT; >+ do { >+ lsr = inb(synth_port_tts + UART_LSR); >+ if (--tmout == 0) return 0xff; >+ } while (!(lsr & UART_LSR_DR)); >+ c = inb(synth_port_tts + UART_RX); >+ return (unsigned char) c; >+} >+ >+static void do_catch_up(unsigned long data) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+synth_stop_timer(); >+ while (synth_buff_out < synth_buff_in ) { >+ ch = *synth_buff_out; >+ if (ch == 0x0a) ch = PROCSPEECH; >+ if (!spk_serial_out(ch )) { >+ synth_delay(synth_full_time); >+ return; >+ } >+ synth_buff_out++; >+ if (jiffies >= jiff_max && ch == SPACE ) { >+ spk_serial_out(PROCSPEECH); >+ synth_delay(synth_delay_time); >+ return; >+ } >+ } >+spk_serial_out(PROCSPEECH); >+ synth_done( ); >+} >+ >+static const char *synth_immediate (const char *buf ) >+{ >+ u_char ch; >+ while ( ( ch = *buf ) ) { >+ if (ch == 0x0a) ch = PROCSPEECH; >+ if ( wait_for_xmitr( ) ) >+ outb( ch, synth_port_tts ); >+ else return buf; >+ buf++; >+ } >+ return 0; >+} >+ >+static void synth_flush(void) >+{ >+ while ((inb(synth_port_tts + UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY); >+ outb(SYNTH_CLEAR, synth_port_tts); >+} >+ >+static unsigned char get_index(void) >+{ >+ int c, lsr;//, tmout = SPK_SERIAL_TIMEOUT; >+ lsr = inb( synth_port_tts + UART_LSR ); >+ if ( ( lsr & UART_LSR_DR) == UART_LSR_DR ) >+ { >+ c = inb( synth_port_tts + UART_RX ); >+ return ( unsigned char ) c; >+ } >+ return 0; >+} >+ >+static int serprobe(int index) >+{ >+ struct serial_state *ser = spk_serial_init(index); >+ if ( ser == NULL ) return -1; >+ /* ignore any error results, if port was forced */ >+ if (synth_port_forced) return 0; >+ /* check for speak out now... */ >+ synth_immediate( "\x05[\x0f\r" ); >+ mdelay( 10 ); //failed with no delay >+ if (spk_serial_in() == 0x0f) return 0; >+ synth_release_region(ser->port,8); >+ synth_alive = 0; >+ return -1; >+} >+ >+static int synth_probe(void) >+{ >+ int i=0, failed=0; >+ pr_info("Probing for %s.\n", synth->long_name); >+ for (i=SPK_LO_TTY; i <= SPK_HI_TTY; i++) { >+ if (( failed = serprobe( i )) == 0 ) break; /* found it */ >+ } >+ if ( failed ) { >+ pr_info("%s Out: not found\n", synth->long_name); >+ return -ENODEV; >+ } >+ pr_info("%s Out: %03x-%03x, Driver version %s,\n", synth->long_name, >+ synth_port_tts, synth_port_tts + 7, synth->version); >+ return 0; >+} >+ >+static int synth_is_alive(void) >+{ >+ if (synth_alive) return 1; >+ if (wait_for_xmitr() > 0) { /* restart */ >+ synth_alive = 1; >+ synth_write_string(synth->init ); >+ return 2; >+ } else pr_warn("%s Out: can't restart synth\n", synth->long_name); >+ return 0; >+} >+ >+static const char init_string[] = "\005W1\005I2\005C3"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "\x05P+" }, >+ { CAPS_STOP, "\x05P-" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "\x05R%d", 7, 0, 9, 0, 0, 0 }, >+ { PITCH, "\x05P%d", 3, 0, 9, 0, 0, 0 }, >+ { VOL, "\x05V%d", 9, 0, 9, 0, 0, 0 }, >+ { TONE, "\x05T%c", 8, 0, 25, 65, 0, 0 }, >+ { PUNCT, "\x05M%c", 0, 0, 3, 0, 0, "nsma" }, >+ V_LAST_NUM >+}; >+ >+struct spk_synth synth_spkout = {"spkout", "1.1", "Speakout", >+ init_string, 500, 50, 50, 5000, 0, 0, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, spk_serial_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, >+ get_index, {"\x05[%c",1,5,1} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/speakup_txprt.c linux-2.6.20-spk/drivers/char/speakup/speakup_txprt.c >--- linux-2.6.20/drivers/char/speakup/speakup_txprt.c 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/speakup_txprt.c 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,196 @@ >+/* >+ * originially written by: Kirk Reiser <kirk@braille.uwo.ca> >+* this version considerably modified by David Borowski, david575@rogers.com >+ >+ Copyright (C) 1998-99 Kirk Reiser. >+ Copyright (C) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ * this code is specificly written as a driver for the speakup screenreview >+ * package and is not a general device driver. >+ */ >+#include "spk_priv.h" >+#include "serialio.h" >+ >+#define MY_SYNTH synth_txprt >+#define DRV_VERSION "1.2" >+#define SYNTH_CLEAR 0x18 >+#define PROCSPEECH '\r' /* process speech char */ >+ >+static int timeouts = 0; /* sequential number of timeouts */ >+ >+static int wait_for_xmitr( void ) >+{ >+ int check, tmout = SPK_XMITR_TIMEOUT; >+ if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) { >+ synth_alive = 0; >+ timeouts = 0; >+ return 0; >+ } >+ do { >+ check = inb( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) { >+ pr_warn( "TXPRT: timed out\n" ); >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY ); >+ tmout = SPK_XMITR_TIMEOUT; >+ do { >+ check = inb( synth_port_tts + UART_MSR ); >+ if ( --tmout == 0 ) { >+ timeouts++; >+ return 0; >+ } >+ } while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS ); >+ timeouts = 0; >+ return 1; >+} >+ >+static int spk_serial_out( const char ch ) >+{ >+ if ( synth_alive && wait_for_xmitr( ) ) { >+ outb( ch, synth_port_tts ); >+ return 1; >+ } >+ return 0; >+} >+ >+static unsigned char spk_serial_in( void ) >+{ >+ int c, lsr, tmout = SPK_SERIAL_TIMEOUT; >+ do { >+ lsr = inb( synth_port_tts + UART_LSR ); >+ if ( --tmout == 0 ) return 0xff; >+ } while ( !( lsr & UART_LSR_DR ) ); >+ c = inb( synth_port_tts + UART_RX ); >+ return ( unsigned char ) c; >+} >+ >+static void do_catch_up( unsigned long data ) >+{ >+ unsigned long jiff_max = jiffies+synth_jiffy_delta; >+ u_char ch; >+ >+ synth_stop_timer( ); >+ while ( synth_buff_out < synth_buff_in ) { >+ ch = *synth_buff_out; >+ if ( ch == '\n' ) ch = PROCSPEECH; >+ if ( !spk_serial_out( ch ) ) { >+ synth_delay( synth_full_time ); >+ return; >+ } >+ synth_buff_out++; >+ if ( jiffies >= jiff_max && ch == ' ' ) { >+ spk_serial_out( PROCSPEECH ); >+ synth_delay( synth_delay_time ); >+ return; >+ } >+ } >+ spk_serial_out( PROCSPEECH ); >+ synth_done( ); >+} >+ >+static const char *synth_immediate ( const char *buf ) >+{ >+ u_char ch; >+ while ( ( ch = *buf ) ) { >+ if ( ch == 0x0a ) ch = PROCSPEECH; >+ if ( wait_for_xmitr( ) ) >+ outb( ch, synth_port_tts ); >+ else return buf; >+ buf++; >+ } >+ return 0; >+} >+ >+static void synth_flush ( void ) >+{ >+ spk_serial_out ( SYNTH_CLEAR ); >+} >+ >+static int serprobe( int index ) >+{ >+ u_char test=0; >+ struct serial_state *ser = spk_serial_init( index ); >+ if ( ser == NULL ) return -1; >+ if ( synth_port_forced ) return 0; >+ /* check for txprt now... */ >+ if (synth_immediate( "\x05$" )) >+ pr_warn("synth_immediate could not unload\n"); >+ if (synth_immediate( "\x05Ik" )) >+ pr_warn("synth_immediate could not unload again\n"); >+ if (synth_immediate( "\x05Q\r" )) >+ pr_warn("synth_immediate could not unload a third time\n"); >+ if ( ( test = spk_serial_in( ) ) == 'k' ) return 0; >+ else pr_warn( "synth returned %x on port %03lx\n", test, ser->port ); >+ synth_release_region( ser->port,8 ); >+ timeouts = synth_alive = 0; >+ return -1; >+} >+ >+static int synth_probe( void ) >+{ >+ int i, failed=0; >+ pr_info( "Probing for %s.\n", synth->long_name ); >+ for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) { >+ if (( failed = serprobe( i )) == 0 ) break; /* found it */ >+ } >+ if ( failed ) { >+ pr_info( "%s: not found\n", synth->long_name ); >+ return -ENODEV; >+ } >+ pr_info( "%s: %03x-%03x..\n", synth->long_name, (int) synth_port_tts, (int) synth_port_tts+7 ); >+ pr_info( "%s: driver version %s.\n", synth->long_name, synth->version); >+ return 0; >+} >+ >+static int synth_is_alive( void ) >+{ >+ if ( synth_alive ) return 1; >+ if ( wait_for_xmitr( ) > 0 ) { /* restart */ >+ synth_alive = 1; >+ synth_write_string( synth->init ); >+ return 2; >+ } >+ pr_warn( "%s: can't restart synth\n", synth->long_name ); >+ return 0; >+} >+ >+static const char init_string[] = "\x05N1"; >+ >+static struct st_string_var stringvars[] = { >+ { CAPS_START, "\x05P8" }, >+ { CAPS_STOP, "\x05P5" }, >+ V_LAST_STRING >+}; >+static struct st_num_var numvars[] = { >+ { RATE, "\x05R%d", 5, 0, 9, 0, 0, 0 }, >+ { PITCH, "\x05P%d", 5, 0, 9, 0, 0, 0 }, >+ { VOL, "\x05V%d", 5, 0, 9, 0, 0, 0 }, >+ { TONE, "\x05T%c", 12, 0, 25, 61, 0, 0 }, >+ V_LAST_NUM >+ }; >+ >+struct spk_synth synth_txprt = {"txprt", DRV_VERSION, "Transport", >+ init_string, 500, 50, 50, 5000, 0, 0, SYNTH_CHECK, >+ stringvars, numvars, synth_probe, spk_serial_release, synth_immediate, >+ do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL, >+ {NULL,0,0,0} }; >+ >+#ifdef MODULE >+#include "mod_code.c" >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/spk_con_module.h linux-2.6.20-spk/drivers/char/speakup/spk_con_module.h >--- linux-2.6.20/drivers/char/speakup/spk_con_module.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/spk_con_module.h 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,43 @@ >+/* written bby David Borowski. >+ Copyright (C ) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option ) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+*/ >+ >+/* included by ../console.c for speakup modularization */ >+ >+static spk_con_func addr_spk_allocate = NULL; >+static spk_con_func addr_spk_bs = NULL; >+static spk_write_func addr_spk_con_write = NULL; >+static spk_con_func addr_spk_con_update = NULL; >+ >+#define speakup_allocate(c) if (addr_spk_allocate) (*addr_spk_allocate)(c) >+#define speakup_bs(c) if (addr_spk_bs) (*addr_spk_bs)(c) >+#define speakup_con_write(c,s,l) if (addr_spk_con_write) (*addr_spk_con_write)(c,s,l) >+#define speakup_con_update(c) if (addr_spk_con_update) (*addr_spk_con_update)(c) >+ >+extern spk_key_func addr_spk_key; >+ >+void speakup_set_addresses( spk_con_func allocate, spk_con_func bs, >+ spk_write_func con_write, spk_con_func con_update, spk_key_func key ) >+{ >+ addr_spk_allocate = allocate; >+ addr_spk_bs = bs; >+ addr_spk_con_write = con_write; >+ addr_spk_con_update = con_update; >+ addr_spk_key = key; >+} >+ >+EXPORT_SYMBOL_GPL(speakup_set_addresses); >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/spk_priv.h linux-2.6.20-spk/drivers/char/speakup/spk_priv.h >--- linux-2.6.20/drivers/char/speakup/spk_priv.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/spk_priv.h 2007-02-04 16:09:20.000000000 -0500 >@@ -0,0 +1,262 @@ >+/* spk_priv.h >+ review functions for the speakup screen review package. >+ originally written by: Kirk Reiser and Andy Berdan. >+ >+ extensively modified by David Borowski. >+ >+ Copyright (C ) 1998 Kirk Reiser. >+ Copyright (C ) 2003 David Borowski. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option ) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+*/ >+#ifndef __SPEAKUP_PRIVATE_H >+#define __SPEAKUP_PRIVATE_H >+ >+#define KERNEL >+#include <linux/version.h> >+#include <linux/types.h> >+#include <linux/fs.h> >+#include <linux/errno.h> >+#include <asm/io.h> /* for inb_p, outb_p, inb, outb, etc... */ >+#include <linux/delay.h> >+#include <linux/wait.h> /* for wait_queue */ >+#include <linux/init.h> /* for __init */ >+#include <linux/module.h> >+#ifdef CONFIG_PROC_FS >+#include <linux/proc_fs.h> >+#endif >+#include <linux/speakup.h> >+#include "keyinfo.h" >+ >+#define SHIFT_TBL_SIZE 64 >+/* proc permissions */ >+#define USER_R ( S_IFREG|S_IRUGO ) >+#define USER_W ( S_IFREG|S_IWUGO ) >+#define USER_RW ( S_IFREG|S_IRUGO|S_IWUGO ) >+#define ROOT_W ( S_IFREG|S_IRUGO|S_IWUSR ) >+ >+#define V_LAST_STRING { -1, 0 } >+#define V_LAST_NUM { -1, 0, 0, 0, 0, 0, 0, 0 } >+#define TOGGLE_0 0, 0, 0, 1, 0, 0, 0 >+#define TOGGLE_1 0, 1, 0, 1, 0, 0, 0 >+#define MAXVARLEN 15 >+#define TAB 0x9 >+#define SPACE 0x20 >+#define CAP_A 'A' >+#define CAP_Z 'Z' >+#define SYNTH_OK 0x0001 >+#define B_ALPHA 0x0002 >+#define ALPHA 0x0003 >+#define B_CAP 0x0004 >+#define A_CAP 0x0007 >+#define B_NUM 0x0008 >+#define NUM 0x0009 >+#define ALPHANUM ( B_ALPHA|B_NUM ) >+#define SOME 0x0010 >+#define MOST 0x0020 >+#define PUNC 0x0040 >+#define A_PUNC 0x0041 >+#define B_WDLM 0x0080 >+#define WDLM 0x0081 >+#define B_EXNUM 0x0100 >+#define CH_RPT 0x0200 >+#define B_CTL 0x0400 >+#define A_CTL ( B_CTL+SYNTH_OK ) >+#define B_SYM 0x0800 >+#define B_CAPSYM ( B_CAP|B_SYM ) >+#define IS_WDLM( x ) ( spk_chartab[( ( u_char )x )]&B_WDLM ) >+#define IS_CHAR( x, type ) ( spk_chartab[( ( u_char )x )]&type ) >+#define IS_TYPE( x, type ) ( (spk_chartab[( ( u_char )x )]&type) == type ) >+#define SET_DEFAULT -4 >+#define E_RANGE -3 >+#define E_TOOLONG -2 >+#define E_UNDEF -1 >+ >+enum { >+ VAR_NUM = 0, >+ VAR_TIME, >+ VAR_STRING, >+ VAR_PROC >+}; >+ >+enum { >+ E_DEFAULT = 0, >+ E_SET, >+ E_INC, >+ E_DEC >+}; >+ >+typedef int (*special_func)( struct vc_data *vc, u_char type, u_char ch, u_short key ); >+ >+struct st_var_header { >+ char *name; >+ short var_id, var_type, proc_mode; >+ void *proc_entry; >+ void *p_val; /* ptr to programs variable to store value */ >+ void *data; /* ptr to the vars data */ >+}; >+ >+struct st_num_var { >+ short var_id; >+ char *synth_fmt; >+ short default_val, low, high; >+ short offset, multiplier; /* for fiddling rates etc. */ >+ char *out_str; /* if synth needs char representation of number */ >+ short value; /* current value */ >+}; >+ >+struct st_string_var { >+ short var_id; >+ char *default_val; >+}; >+ >+struct st_proc_var { >+ short var_id; >+ int (*read_proc)(char *page, char **start, off_t off, int count, >+ int *eof, void *data); >+ int (*write_proc)(struct file *file, const char *buffer, u_long count, >+ void *data); >+ short value; >+}; >+ >+struct st_bits_data { /* punc, repeats, word delim bits */ >+ char *name; >+ char *value; >+ short mask; >+}; >+ >+extern struct st_proc_var spk_proc_vars[]; >+char *speakup_s2i( char *, short * ); >+int speakup_register_var(struct st_num_var *var); >+extern struct st_var_header *get_var_header( short var_id ); >+extern int set_num_var(short val, struct st_var_header *var, int how); >+ >+#define COLOR_BUFFER_SIZE 160 >+struct spk_highlight_color_track{ >+ unsigned int bgcount[8]; // Count of each background color >+ char highbuf[8][COLOR_BUFFER_SIZE]; // Buffer for characters drawn with each background color >+ unsigned int highsize[8]; // Current index into highbuf >+ u_long rpos[8],rx[8],ry[8]; // Reading Position for each color >+ ulong cy; // Real Cursor Y Position >+}; >+ >+struct st_spk_t { >+ u_long reading_x, cursor_x; >+ u_long reading_y, cursor_y; >+ u_long reading_pos, cursor_pos; >+ u_long go_x, go_pos; >+ u_long w_top, w_bottom, w_left, w_right; >+ u_char w_start, w_enabled; >+ u_char reading_attr, old_attr; >+ char parked, shut_up; >+ struct spk_highlight_color_track ht; >+}; >+ >+/* now some defines to make these easier to use. */ >+#define spk_shut_up speakup_console[vc->vc_num]->shut_up >+#define spk_killed ( speakup_console[vc->vc_num]->shut_up & 0x40 ) >+#define spk_x speakup_console[vc->vc_num]->reading_x >+#define spk_cx speakup_console[vc->vc_num]->cursor_x >+#define spk_y speakup_console[vc->vc_num]->reading_y >+#define spk_cy speakup_console[vc->vc_num]->cursor_y >+#define spk_pos ( speakup_console[vc->vc_num]->reading_pos ) >+#define spk_cp speakup_console[vc->vc_num]->cursor_pos >+#define goto_pos ( speakup_console[vc->vc_num]->go_pos ) >+#define goto_x ( speakup_console[vc->vc_num]->go_x ) >+#define win_top ( speakup_console[vc->vc_num]->w_top ) >+#define win_bottom ( speakup_console[vc->vc_num]->w_bottom ) >+#define win_left ( speakup_console[vc->vc_num]->w_left ) >+#define win_right ( speakup_console[vc->vc_num]->w_right ) >+#define win_start ( speakup_console[vc->vc_num]->w_start ) >+#define win_enabled ( speakup_console[vc->vc_num]->w_enabled ) >+#define spk_attr speakup_console[vc->vc_num]->reading_attr >+#define spk_old_attr speakup_console[vc->vc_num]->old_attr >+#define spk_parked speakup_console[vc->vc_num]->parked >+#define SYNTH_CHECK 20030716 /* today's date ought to do for check value */ >+/* synth flags, for odd synths */ >+#define SF_DEC 1 /* to fiddle puncs in alpha strings so it doesn't spell */ >+ >+struct synth_indexing { >+ char *command; >+ unsigned char lowindex; >+ unsigned char highindex; >+ unsigned char currindex; >+}; >+ >+struct spk_synth { >+ const char *name; >+ const char *version; >+ const char *long_name; >+ const char *init; >+ short delay, trigger, jiffies, full, flush_wait, flags; >+ const int checkval; /* for validating a proper synth module */ >+ struct st_string_var *string_vars; >+ struct st_num_var *num_vars; >+ int ( *probe )( void ); >+ void ( *release )( void ); >+ const char *( *synth_immediate )( const char *buff ); >+ void ( *catch_up )( u_long data ); >+ void ( *start )( void ); >+ void ( *flush )( void ); >+ int ( *is_alive )( void ); >+ int (*synth_adjust)(struct st_var_header *var); >+ void ( *read_buff_add )(u_char); >+ unsigned char ( *get_index )( void ); >+ struct synth_indexing indexing; >+}; >+ >+extern struct spk_synth *synth; >+int synth_request_region( u_long, u_long ); >+int synth_release_region( u_long, u_long ); >+void spk_serial_release( void ); >+extern int synth_port_tts, synth_port_forced; >+#define declare_timer( name ) struct timer_list name; >+#define start_timer( name ) if ( ! name.entry.prev ) add_timer ( & name ) >+#define stop_timer( name ) del_timer ( & name ); name.entry.prev = NULL >+#define declare_sleeper( name ) wait_queue_head_t name >+#define init_sleeper( name ) init_waitqueue_head ( &name ) >+extern declare_sleeper( synth_sleeping_list ); >+extern char str_caps_start[], str_caps_stop[]; >+extern short no_intr, say_ctrl, say_word_ctl, punc_level; >+extern short reading_punc, attrib_bleep, bleeps; >+extern short bleep_time, bell_pos; >+extern short spell_delay, key_echo, punc_mask; >+extern short synth_jiffy_delta, synth_delay_time; >+extern short synth_trigger_time, synth_full_time; >+extern short cursor_timeout, pitch_shift, synth_flags; >+extern int synth_alive, quiet_boot; >+extern u_char synth_buffer[]; /* guess what this is for! */ >+extern volatile u_char *synth_buff_in, *synth_buff_out; >+int synth_init( char *name ); >+int do_synth_init( struct spk_synth *in_synth ); >+void synth_release( void ); >+void synth_add( struct spk_synth *in_synth ); >+void synth_remove( struct spk_synth *in_synth ); >+struct serial_state * spk_serial_init( int index ); >+void synth_delay( int ms ); >+void synth_stop_timer( void ); >+int synth_done( void ); >+void do_flush( void ); >+void synth_buffer_add( char ch ); >+void synth_write( const char *buf, size_t count ); >+void synth_write_string( const char *buf ); >+void synth_write_msg( const char *buf ); >+int synth_supports_indexing( void ); >+ >+#ifndef pr_warn >+#define pr_warn(fmt,arg...) printk(KERN_WARNING fmt,##arg) >+#endif >+ >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/speakup/synthlist.h linux-2.6.20-spk/drivers/char/speakup/synthlist.h >--- linux-2.6.20/drivers/char/speakup/synthlist.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/speakup/synthlist.h 2007-02-04 16:09:19.000000000 -0500 >@@ -0,0 +1,51 @@ >+/* this is included two times */ >+#if defined(PASS2) >+/* table of built in synths */ >+#define SYNTH_DECL(who) &synth_##who, >+#else >+/* declare extern built in synths */ >+#define SYNTH_DECL(who) extern struct spk_synth synth_##who; >+#define PASS2 >+#endif >+ >+#ifdef CONFIG_SPEAKUP_ACNTPC >+SYNTH_DECL(acntpc) >+#endif >+#ifdef CONFIG_SPEAKUP_ACNTSA >+SYNTH_DECL(acntsa) >+#endif >+#ifdef CONFIG_SPEAKUP_APOLLO >+SYNTH_DECL(apollo) >+#endif >+#ifdef CONFIG_SPEAKUP_AUDPTR >+SYNTH_DECL(audptr) >+#endif >+#ifdef CONFIG_SPEAKUP_BNS >+SYNTH_DECL(bns) >+#endif >+#ifdef CONFIG_SPEAKUP_DECEXT >+SYNTH_DECL(decext) >+#endif >+#ifdef CONFIG_SPEAKUP_DECTLK >+SYNTH_DECL(dectlk) >+#endif >+#ifdef CONFIG_SPEAKUP_DTLK >+SYNTH_DECL(dtlk) >+#endif >+#ifdef CONFIG_SPEAKUP_KEYPC >+SYNTH_DECL(keypc) >+#endif >+#ifdef CONFIG_SPEAKUP_LTLK >+SYNTH_DECL(ltlk) >+#endif >+#ifdef CONFIG_SPEAKUP_SFTSYN >+SYNTH_DECL(sftsyn) >+#endif >+#ifdef CONFIG_SPEAKUP_SPKOUT >+SYNTH_DECL(spkout) >+#endif >+#ifdef CONFIG_SPEAKUP_TXPRT >+SYNTH_DECL(txprt) >+#endif >+ >+#undef SYNTH_DECL >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/char/vt.c linux-2.6.20-spk/drivers/char/vt.c >--- linux-2.6.20/drivers/char/vt.c 2007-02-04 16:08:01.000000000 -0500 >+++ linux-2.6.20-spk/drivers/char/vt.c 2007-02-04 16:09:21.000000000 -0500 >@@ -103,6 +103,11 @@ > #include <asm/system.h> > #include <asm/uaccess.h> > >+#include <linux/speakup.h> >+#ifdef CONFIG_SPEAKUP_MODULE >+#include "speakup/spk_con_module.h" >+#endif >+ > #define MAX_NR_CON_DRIVER 16 > > #define CON_DRIVER_FLAG_MODULE 1 >@@ -739,6 +744,7 @@ int vc_allocate(unsigned int currcons) / > } > vc->vc_kmalloced = 1; > vc_init(vc, vc->vc_rows, vc->vc_cols, 1); >+ speakup_allocate(vc); > } > return 0; > } >@@ -1003,6 +1009,7 @@ static void lf(struct vc_data *vc) > vc->vc_pos += vc->vc_size_row; > } > vc->vc_need_wrap = 0; >+ speakup_con_write(vc, "\n",1); > } > > static void ri(struct vc_data *vc) >@@ -1031,6 +1038,7 @@ static inline void bs(struct vc_data *vc > vc->vc_pos -= 2; > vc->vc_x--; > vc->vc_need_wrap = 0; >+ speakup_bs(vc); > } > } > >@@ -1568,6 +1576,7 @@ static void do_con_trol(struct tty_struc > break; > } > vc->vc_pos += (vc->vc_x << 1); >+ speakup_con_write(vc, " ", 1); > return; > case 10: case 11: case 12: > lf(vc); >@@ -2107,6 +2116,7 @@ display_glyph: > } > if (vc->vc_decim) > insert_char(vc, 1); >+ speakup_con_write(vc, (char *) &c, 1); > scr_writew(himask ? > ((vc->vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : > (vc->vc_attr << 8) + tc, >@@ -2141,6 +2151,7 @@ display_glyph: > release_console_sem(); > > out: >+ speakup_con_update(vc); > return n; > #undef FLUSH > } >@@ -2166,6 +2177,7 @@ static void console_callback(struct work > /* we only changed when the console had already > been allocated - a new console is not created > in an interrupt routine */ >+ speakup_con_update(vc_cons[want_console].d); > } > want_console = -1; > } >@@ -2184,6 +2196,7 @@ static void console_callback(struct work > do_blank_screen(0); > blank_timer_expired = 0; > } >+ speakup_con_update(vc_cons[fg_console].d); > > release_console_sem(); > } >@@ -2229,6 +2242,7 @@ static void vt_console_print(struct cons > /* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */ > goto quit; > } >+ speakup_con_update(vc_cons[fg_console].d); > > if (vc->vc_mode != KD_TEXT) > goto quit; >@@ -2241,6 +2255,7 @@ static void vt_console_print(struct cons > > /* Contrived structure to try to emulate original need_wrap behaviour > * Problems caused when we have need_wrap set on '\n' character */ >+ speakup_con_write(vc, b, count); > while (count--) { > c = *b++; > if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) { >@@ -2285,6 +2300,7 @@ static void vt_console_print(struct cons > } > } > set_cursor(vc); >+ speakup_con_update(vc); > > quit: > clear_bit(0, &printing); >@@ -2650,6 +2666,7 @@ static int __init con_init(void) > master_display_fg = vc = vc_cons[currcons].d; > set_origin(vc); > save_screen(vc); >+ speakup_init(vc); > gotoxy(vc, vc->vc_x, vc->vc_y); > csi_J(vc, 0); > update_screen(vc); >@@ -3820,3 +3837,4 @@ EXPORT_SYMBOL(vc_cons); > EXPORT_SYMBOL(take_over_console); > EXPORT_SYMBOL(give_up_console); > #endif >+EXPORT_SYMBOL_GPL(screen_glyph); >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/Kconfig linux-2.6.20-spk/drivers/Kconfig >--- linux-2.6.20/drivers/Kconfig 2007-02-04 16:08:01.000000000 -0500 >+++ linux-2.6.20-spk/drivers/Kconfig 2007-02-04 16:09:21.000000000 -0500 >@@ -62,6 +62,8 @@ source "drivers/media/Kconfig" > > source "drivers/video/Kconfig" > >+source "drivers/char/speakup/Kconfig" >+ > source "sound/Kconfig" > > source "drivers/hid/Kconfig" >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/drivers/Makefile linux-2.6.20-spk/drivers/Makefile >--- linux-2.6.20/drivers/Makefile 2007-02-04 16:08:01.000000000 -0500 >+++ linux-2.6.20-spk/drivers/Makefile 2007-02-04 16:09:21.000000000 -0500 >@@ -28,6 +28,10 @@ obj-$(CONFIG_FB_INTEL) += video > obj-y += serial/ > obj-$(CONFIG_PARPORT) += parport/ > obj-y += base/ block/ misc/ mfd/ net/ media/ >+obj-$(CONFIG_SERIO) += input/serio/ >+obj-$(CONFIG_GAMEPORT) += input/gameport/ >+# load keyboard early so speakup can be quieted >+obj-$(CONFIG_INPUT) += input/ > obj-$(CONFIG_NUBUS) += nubus/ > obj-$(CONFIG_ATM) += atm/ > obj-$(CONFIG_PPC_PMAC) += macintosh/ >@@ -52,9 +56,6 @@ obj-$(CONFIG_TC) += tc/ > obj-$(CONFIG_USB) += usb/ > obj-$(CONFIG_PCI) += usb/ > obj-$(CONFIG_USB_GADGET) += usb/gadget/ >-obj-$(CONFIG_SERIO) += input/serio/ >-obj-$(CONFIG_GAMEPORT) += input/gameport/ >-obj-$(CONFIG_INPUT) += input/ > obj-$(CONFIG_I2O) += message/ > obj-$(CONFIG_RTC_LIB) += rtc/ > obj-$(CONFIG_I2C) += i2c/ >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/include/linux/keyboard.h linux-2.6.20-spk/include/linux/keyboard.h >--- linux-2.6.20/include/linux/keyboard.h 2006-09-19 23:42:06.000000000 -0400 >+++ linux-2.6.20-spk/include/linux/keyboard.h 2007-02-04 16:09:21.000000000 -0500 >@@ -45,6 +45,7 @@ extern unsigned short plain_map[NR_KEYS] > #define KT_LOCK 10 > #define KT_SLOCK 12 > #define KT_BRL 14 >+#define KT_SPKUP 15 > > #define K(t,v) (((t)<<8)|(v)) > #define KTYP(x) ((x) >> 8) >@@ -427,6 +428,7 @@ extern unsigned short plain_map[NR_KEYS] > #define K_CTRLR_SLOCK K(KT_SLOCK,KG_CTRLR) > > #define NR_LOCK 8 >+#define NR_SPKUP 0x45 > > #define K_BRL_BLANK K(KT_BRL, 0) > #define K_BRL_DOT1 K(KT_BRL, 1) >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/include/linux/miscdevice.h linux-2.6.20-spk/include/linux/miscdevice.h >--- linux-2.6.20/include/linux/miscdevice.h 2007-02-04 16:08:03.000000000 -0500 >+++ linux-2.6.20-spk/include/linux/miscdevice.h 2007-02-04 16:09:21.000000000 -0500 >@@ -12,6 +12,7 @@ > #define APOLLO_MOUSE_MINOR 7 > #define PC110PAD_MINOR 9 > /*#define ADB_MOUSE_MINOR 10 FIXME OBSOLETE */ >+#define SYNTH_MINOR 25 > #define WATCHDOG_MINOR 130 /* Watchdog timer */ > #define TEMP_MINOR 131 /* Temperature Sensor */ > #define RTC_MINOR 135 >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/include/linux/speakup.h linux-2.6.20-spk/include/linux/speakup.h >--- linux-2.6.20/include/linux/speakup.h 1969-12-31 19:00:00.000000000 -0500 >+++ linux-2.6.20-spk/include/linux/speakup.h 2007-02-04 16:09:21.000000000 -0500 >@@ -0,0 +1,35 @@ >+#ifndef __SPEAKUP_H >+#define __SPEAKUP_H >+ >+#include <linux/version.h> >+ >+struct kbd_struct; >+struct vc_data; >+ >+/* how about some prototypes! */ >+ >+#if defined(CONFIG_SPEAKUP) >+extern void speakup_init(struct vc_data *); >+extern int speakup_dev_init(void); >+extern void speakup_allocate(struct vc_data *); >+extern void speakup_bs(struct vc_data *); >+extern void speakup_con_write(struct vc_data *, const char *, int); >+extern void speakup_con_update(struct vc_data *); >+extern int speakup_key(struct vc_data*, int, int, u_short, int); >+#elif defined(CONFIG_SPEAKUP_MODULE) >+typedef void (*spk_con_func)(struct vc_data * ); >+typedef void (*spk_write_func)(struct vc_data *, const char *, int); >+typedef int (*spk_key_func)(struct vc_data*, int, int, u_short, int); >+extern void spk_set_addresses( spk_con_func allocate, spk_con_func bs, >+ spk_write_func con_write, spk_con_func con_update, spk_key_func key ); >+#define speakup_init(vc) >+extern int speakup_dev_init(void); >+#else >+#define speakup_allocate(vc) >+#define speakup_bs(vc) >+#define speakup_con_write(vc, str, len) >+#define speakup_con_update(vc) >+#define speakup_init(currcons) >+#define speakup_dev_init() >+#endif >+#endif >diff --exclude='*.orig' --exclude='*.patch' -urNp linux-2.6.20/MAINTAINERS linux-2.6.20-spk/MAINTAINERS >--- linux-2.6.20/MAINTAINERS 2007-02-04 16:08:00.000000000 -0500 >+++ linux-2.6.20-spk/MAINTAINERS 2007-02-04 16:09:21.000000000 -0500 >@@ -3088,6 +3088,13 @@ M: wli@holomorphy.com > L: sparclinux@vger.kernel.org > S: Maintained > >+SPEAKUP Console speech output >+P: Kirk Reiser >+M: kirk@braille.uwo.ca >+L: speakup@braille.uwo.ca >+W: http://www.linux-speakup.org >+S: Maintained >+ > SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER > P: Roger Wolff > M: R.E.Wolff@BitWizard.nl
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 166086
:
109648
| 112063