Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 166086
Collapse All | Expand All

(-)linux-2.6.20/arch/arm/Kconfig (+1 lines)
Lines 951-956 source "drivers/leds/Kconfig" Link Here
951
source "drivers/media/Kconfig"
951
source "drivers/media/Kconfig"
952
952
953
source "drivers/video/Kconfig"
953
source "drivers/video/Kconfig"
954
source "drivers/char/speakup/Kconfig"
954
955
955
source "sound/Kconfig"
956
source "sound/Kconfig"
956
957
(-)linux-2.6.20/Documentation/speakup/DefaultKeyAssignments (+46 lines)
Line 0 Link Here
1
This file is intended to give you an overview of the default keys used
2
by speakup for it's review functions.  You may change them to be
3
anything you want but that will take some familiarity with key
4
mapping.
5
6
We have remapped the insert or zero key on the keypad to act as a
7
shift key.  Well, actually as an altgr key.  So in the following list
8
InsKeyPad-period means hold down the insert key like a shift key and
9
hit the keypad period.
10
11
KeyPad-8		Say current Line
12
InsKeyPad-8		say from top of screen to reading cursor.
13
KeyPad-7		Say Previous Line (UP one line)
14
KeyPad-9		Say Next Line (down one line)
15
KeyPad-5		Say Current Word
16
InsKeyPad-5		Spell Current Word
17
KeyPad-4		Say Previous Word (left one word)
18
InsKeyPad-4		say from left edge of line to reading cursor.
19
KeyPad-6		Say Next Word (right one word)
20
InsKeyPad-6		Say from reading cursor to right edge of line.
21
KeyPad-2		Say Current Letter
22
InsKeyPad-2		say current letter phonetically
23
KeyPad-1		Say Previous Character (left one letter)
24
KeyPad-3		Say Next Character (right one letter)
25
KeyPad-plus		Say Entire Screen
26
InsKeyPad-plus		Say from reading cursor line to bottom of screen.
27
KeyPad-Minus		Park reading cursor (toggle)
28
InsKeyPad-minus		Say character hex and decimal value.
29
KeyPad-period		Say Position (current line, position and console)
30
InsKeyPad-period	say colour attributes of current position.
31
InsKeyPad-9		Move reading cursor to top of screen (insert pgup)
32
InsKeyPad-3		Move reading cursor to bottom of screen (insert pgdn)
33
InsKeyPad-7		Move reading cursor to left edge of screen (insert home)
34
InsKeyPad-1		Move reading cursor to right edge of screen (insert end)
35
ControlKeyPad-1		Move reading cursor to last character on current line.
36
KeyPad-Enter		Shut Up (until another key is hit) and sync reading cursor
37
InsKeyPad-Enter		Shut Up (until toggled back on).
38
InsKeyPad-star n<x|y>	go to line (y) or column (x). Where 'n' is any
39
		allowed value for the row or column for your current screen.
40
KeyPad-/		Mark and Cut screen region.
41
InsKeyPad-/		Paste screen region into any console.
42
43
Hitting any key while speakup is outputting speech will quiet the
44
synth until it has caught up with what is being printed on the
45
console.
46
(-)linux-2.6.20/Documentation/speakup/INSTALLATION (+108 lines)
Line 0 Link Here
1
This document assumes you have had some experience with kernel
2
compilation and installation.  If you have not, I recommend you get
3
the kernel source and read the README and various documents in the
4
linux/Documentation directory.  In particular the Changes file to make
5
sure you have the appropriate utilities needed for installing a 2.2.xx
6
or 2.4xx kernel.  It isn't as difficult as you might think.  The
7
kernel README is intimidating the first time but once you get the
8
steps down, it's really pretty easy.  Getting through the "make
9
config" is the tedious bit.
10
11
The first thing to do is to place a copy of the tarball in the /usr/src
12
directory which is the directory the linux tree is located in as well.
13
Next untar speakup by typing:
14
15
tar zxf speakup-1.00.tar.gz
16
cd speakup-1.00
17
./install
18
19
Note the dot-slash before the install.  This will copy the speakup
20
directory to the kernel tree and apply the various patches and
21
components to the appropriate kernel files.  Depending on how
22
experienced you are with kernel compiling and hacking will determine
23
whether you should bother looking at any failed patches.  If this
24
happens, you should probably write to the speakup mailing list for
25
help or myself.
26
27
If all of the patch hunks apply successfully then just continue with
28
the standard steps to compile the kernel with:
29
30
make mrproper
31
make config
32
33
When you get to the section console speech output, answer 'y' to the
34
CONFIG_SPEAKUP prompt.  You will be given a submenu with the list of
35
synthesizers which are currently supported.  You can include as many
36
synths in the kernel as you wish but remember each one takes up kernel
37
space.  You can only choose one of the synths as the default or none,
38
so just type dtlk or whatever is the correct string for the
39
synthesizer you have.  You will also be asked if you wish to build-in
40
a speakup key map.  If you do not say 'y' to this option you will need
41
to load a speakup map at boot time with whichever mechanism your
42
distribution uses for loading key maps.
43
44
We have placed the speakup configuration options in make config just
45
after the vga console choice.  For the DoubleTalk PC driver included
46
by Jim Van Zandt.  I recommend you say no to that option.  I have not
47
tried configuring them both in, but I wouldn't be at all surprised if
48
it didn't work.
49
50
If all goes well up to this point you can continue with the compiling
51
process by doing:
52
53
make dep >dep.file 2>&1 &
54
make bzImage >cc.file 2>&1 &
55
make modules >mod.file 2>&1 &
56
57
I always redirect output to the files dep.file and cc.file so I can
58
look over the compilation record to make sure there are no errors and
59
warnings.
60
61
Okay, you are ready to install the newly compiled kernel.  Make sure
62
you make an linux.old entry in your lilo.conf file so you can recover
63
if it blows up.  next as root run "make modules_install" to install
64
whatever modules you compiled and move the bzImage from
65
/usr/src/linux/arch/i386/boot to wherever your kernel lives.  Also
66
move the System.map from /usr/src/linux to where your System.map
67
lives.  On our systems we use debian so we create an vmlinuz-speakup
68
and System.map-speakup in our /boot directory and set the symbolic
69
links vmlinuz and System.map in the root (/) directory to point to the
70
images.  Now type lilo to tell lilo to build the new booter file and
71
install it.
72
73
As of version 0.07, the keymap for speakup is automatically built in
74
at compile time.  If you have other keymaps installed at boot time,
75
you might want to consider removing them before you reboot the system.
76
77
If everything has gone OK up until now, cross your fingers and type:
78
79
shutdown -r now
80
81
Your system should start talking to you as soon as it starts booting.
82
It will talk and talk and ... well, you might want to hit the
83
keypad-enter key to tell it to shut up.  You should also read the
84
DefaultKeyAssignments file to learn the various review functions
85
available.
86
87
As of v-0.10 the speakup configuration options are in the
88
/proc/speakup subtree.  The individual options should be fairly
89
obvious by their names such as rate, volume, punc_level and so forth.
90
You can manipulate them by cat'ing or echoing new values to them such
91
as:
92
93
echo 9 >/proc/speakup/rate
94
95
You can see what the current values are by cat'ing those files to the console:
96
97
cat /proc/speakup/rate
98
99
I have probably managed to overlook a whole whack of things because
100
this is the, enter version number here, draft.  Don't worry we'll get
101
it right eventually.  If you like the package you really should get on
102
the mailing list and start participating in it's development.
103
104
  Kirk
105
106
email: kirk@braille.uwo.ca
107
phone: (519) 679-6845 (home)
108
(-)linux-2.6.20/Documentation/speakup/keymap-tutorial (+140 lines)
Line 0 Link Here
1
		       Speakup Keymap Tutorial
2
3
This is meant to be a basic tutorial on how to change the Linux keymap
4
file to assign speakup review functions to desired keys.  It is not
5
intended to be a replacement for the loadkeys(8) or keymap(5) man
6
pages.
7
8
The basic lay-out of the keymap file is a series of lines with the
9
following fields.  The keyword keycode indicates this is the start of
10
a new key assignment.  It is then followed by a number which
11
represents the actual key on the keyboard.  That number is followed by
12
the equals '=' operator and finally a list of keywords representing
13
key names such as keypad5.  Each line can have quite a few key
14
functions on it.  They are interpreted by loadkeys in order and
15
assigned to key shift states depending on the order they are
16
encountered.  So for example, the first value after the equals is the
17
keys unshifted state, while the second is the keys shifted state.  If
18
you wish to learn the order they are interpreted in read the
19
loadkeys(8) and keymap(5) man pages.
20
21
You can have subsequent lines which are indented and start with
22
another keyword for the various shifted states.  This way you can
23
assign some of the states without having to specify them all in order
24
up until you get to the one you want to assign.
25
26
In speakup, we have assigned the insert key on the number pad to the
27
altgr keyword.  This is not required; you could choose any other
28
shifted state keyword.  We used altgr because it typically represents
29
the right hand alt key.  In Linux each shift key is separate and
30
independent, so the left shift and the right shift keys are not
31
necessarily the same.  The altgr key is not really used for anything
32
important, so we steel it.
33
34
Here are the default key assignments for the number eight on the
35
keypad:
36
37
keycode  72 = KP_8            
38
	alt     keycode  72 = Ascii_8         
39
40
As you can see, the first line starts with keycode followed by 72
41
which is the actual number assigned to the key when the keyboard port
42
is read.  The KP_8 after the equal sign, is the symbolic representation
43
of the function called when that key is hit.
44
45
The second line is the same format except it starts with the keyword
46
alt which is indented.  That means that the function at the end of
47
that line Ascii_8 is applied to the alt-shifted eight key.
48
49
Now here are the speakup assignments for that key:
50
51
keycode  72 = 0x0d0a
52
	altgr keycode 72 = 0x0d20
53
#keycode  72 = KP_8            
54
	alt     keycode  72 = Ascii_8         
55
56
Notice that the only thing which has changed on the first line is the
57
function called when the key is struck.  It is a hexadecimal number
58
identifying the function called in a look up table.  It is not a
59
symbolic representation yet because that means we need to change the
60
loadkeys program to understand our symbolic names.  We will do this in
61
the future but for now it is more expedient to just use the table
62
indices.  You will find a table at the bottom of this document
63
listing the review functions and their corresponding hex lookups.
64
65
The 0x0d0a in the first line above is speakup's say line function.
66
The second line ends with 0x0d20 which is speakup's read from top of
67
screen to reading cursor line.
68
69
The third line is the original key assignment commented out with a
70
number-sign '#' at the beginning.  I do that so I can easily find the
71
keys I want to affect by symbolic name.  Otherwise I would need to
72
keep a look up table for all the keycodes.  I recommend you do this as
73
well or you'll be very sorry at some point in the future.
74
75
The forth line is just the standard key assignment for the left hand
76
alt key.
77
78
Now let's say we want to design a different keyboard layout.  I'll use
79
an example for the JAWS style keypad because I've specifically been
80
asked to help with that.  JAWS uses the eight on the keypad to move up
81
a line or the speakup function to read previous line.  JAWS also uses
82
the keypad_8 key in a shifted mode to read the current line.  I
83
apologize if these are not quite right.  It has been a long time since
84
I used JAWS.  So we would have the following two lines:
85
86
keycode  72 = 0x0d0b
87
	altgr keycode 72 = 0x0d0a
88
89
The hex value 0x0d0b in the first line is speakup's SAY_PREVIOUS_LINE
90
function.  The 0x0d0a in the second line is the same say_line function
91
as we had earlier.  So when the number eight is hit on the keypad
92
speakup will read the previous line and when the number eight is
93
shifted with the insert key on the keypad it will read the current
94
line.
95
96
As you can tell, it is not really very difficult to reassign the keys
97
to different review functions.
98
99
Once you have carefully edited the keymap file, called default.map in
100
the speakup distribution, you copy it into the /etc/kbd directory.
101
Make sure you back up the original default.map from that directory
102
first, if there is one.  Then you run loadkeys to load the new map
103
into the kernel:
104
105
loadkeys /etc/kbd/default.map
106
107
If you wish to build your new keyboard lay-out into the kernel, after
108
testing it, copy the default.map file into the drivers/char directory,
109
with the name defkeymap.map, of your Linux source tree.  Then rm the
110
defkeymap.c file and recompile the kernel.  Because there is no
111
defkeymap.c `make' will rebuild it on the next compile.
112
113
Here is a list of the available speakup review functions at this point
114
in time.
115
116
SAY_CHAR 0x0d04 /* say this character */
117
SAY_PREV_CHAR 0x0d05 /* say character left of this char */
118
SAY_NEXT_CHAR 0x0d06 /* say char right of this char */
119
SAY_WORD 0x0d07 /* say this word under reading cursor */
120
SAY_PREV_WORD 0x0d08
121
SAY_NEXT_WORD 0x0d09
122
SAY_LINE 0x0d0a /* say this line */
123
SAY_PREV_LINE 0x0d0b /* say line above this line */
124
SAY_NEXT_LINE 0x0d0c
125
TOP_EDGE 0x0d0d /* move to top edge of screen */
126
BOTTOM_EDGE 0x0d0e
127
LEFT_EDGE 0x0d0f
128
RIGHT_EDGE 0x0d10
129
SAY_PHONETIC_CHAR 0x0d11 /* say this character phonetically */
130
SPELL_WORD 0x0d12 /* spell this word letter by letter */
131
SAY_SCREEN 0x0d14
132
SAY_POSITION 0x0d1b
133
SPEECH_OFF 0x0d1c
134
SAY_ATTRIBUTES 0x0d1d
135
SPEAKUP_PARKED 0x0d1e
136
SAY_FROM_TOP 0x0d20
137
SAY_TO_BOTTOM 0x0d21
138
SAY_FROM_LEFT 0x0d22
139
SAY_TO_RIGHT 0x0d23
140
(-)linux-2.6.20/Documentation/speakup/README (+98 lines)
Line 0 Link Here
1
Welcome to the speakup project for the Speakup speech package for Linux.
2
3
Speakup is written by Kirk Reiser and Andy Berdan.  It is licensed
4
under the GPL.  If you don't already know, the GPL stands for the GNU
5
General Public License.  Which basically states that this code is free to
6
copy, modify and distribute to anyone interested in playing with it.
7
The one thing you may not do is turn any part of it into proprietary
8
or commercial code without the permission of the author.  That's me.
9
10
If you are interested in being involved with the development of speech
11
output for Linux you can subscribe to the Speakup mailing list by
12
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.
13
14
We are at a very early stage in the development of this package.
15
Hopefully changes will happen often and many.  The current files in
16
this directory are:
17
18
DefaultKeyAssignments		# speakup's default review keys
19
INSTALLATION			#  for installing speakup from the tar ball.
20
README				# this file
21
keymap-tutorial			# a tutorial on how to layout the keyboard
22
23
Read the INSTALLATION file to learn how to apply the patches and the
24
default.map for the keyboard.  You should also read the Changes file.
25
It really has any new things I've added since last time.
26
27
There is no documentation in any of these files to instruct you what
28
to do if something goes wrong with the patching or compilation.  If
29
you would like that information you will need to subscribe to the
30
mailing list and ask for help, or write me kirk@braille.uwo.ca for
31
help.  I suggest the mailing list because I will probably tire quickly
32
of answering the same questions over and over.  You could always
33
decide to dig-in and take on the task, and write documentation to help
34
others.
35
36
There also is a speakup reflector for the Speak Freely package, which
37
many of us hang out on and discuss all sorts of topics from speakup
38
problems to ALSA driver installation and just about anything else
39
you'd like to talk about.  The reflector is at lwl.braille.uwo.ca:4074
40
with it's lwl page at lwl.braille.uwo.ca/speakup.html.  Come and join
41
us, it's fun!
42
43
Acknowledgements:
44
45
I am really very new at kernel hacking and screen review package
46
writing, so I have depended heavily on other folks kindness to help me
47
a long.  No doubt I will continue to abuse them freely and others
48
before this is a really good speech solution for Linux.  (Oh Well!,
49
somebody's got to do it.)
50
51
Theodore Ts'o.  He gave me a good discussion of unicode and UTF and
52
the like.  He doesn't even remember writing me about it.
53
54
Alan Cox.  He has answered many questions about scheduling and wait
55
queues and timers along with code fragments and so on.  I just wish I
56
understood it all totally.  He has also helped immensely in moving
57
this package toward inclusion in the standard kernel tree. (Maybe next
58
release!)
59
60
Martin Mares.  He pointed me in the right direction to figuring out
61
the colour attributes and other useful tidbits.
62
63
Paul McDermott.  He really is the catalyst for me to actually get
64
this all working.  Besides I like seeing him bounce around and get all
65
excited every time I have something new working.
66
67
John Covici, He was the first person to actually attempt writing
68
another synthesizer driver for speakup.  It was the Speakout driver so
69
it was also the first serial driver.
70
71
Brian Borowski, he was the first person to actually write a speakup
72
function other than Andy and I.
73
74
Jim Danley, he has more or less become my main man in helping test
75
code, add new features, bounce ideas off and generally become a good
76
friend.
77
78
Matt Campbell, he basically rewrote the drivers to be able to include
79
all synths in the kernel at the same time.  The distribution
80
maintainers appreciate him a lot as well.
81
82
Gene Collins, he was very helpful debugging the current release prior
83
to its public showing.  He has also worked hard educating others on
84
the list and writing the ALSA mini howto.
85
86
I would also like to really thank the folks that handle the
87
distribution packages.  I and many other people would not find access
88
to speakup nearly so convenient without their efforts.  They include
89
Bill Acker, Tom Moore, Matt Campbell, Joe Norton and Joshua Lambert.
90
91
There are probably many more I am forgetting right now.  I guess I'll
92
just have to add you all later.
93
94
95
Happy Hacking!
96
97
  Kirk
98
(-)linux-2.6.20/Documentation/speakup/spkguide.txt (+1279 lines)
Line 0 Link Here
1
2
The Speakup User's Guide
3
For Speakup 2.0 and Later
4
By Gene Collins
5
Last modified on Tue Mar 29 10:54:19 2005
6
Document version 1.0
7
8
Copyright (c) 2005  Gene Collins
9
10
Permission is granted to copy, distribute and/or modify this document
11
under the terms of the GNU Free Documentation License, Version 1.2 or
12
any later version published by the Free Software Foundation; with no
13
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
14
copy of the license is included in the section entitled "GNU Free
15
Documentation License".
16
17
Preface
18
19
The purpose of this document is to familiarize users with the user
20
interface to Speakup, a Linux Screen Reader.  If you need instructions
21
for installing or obtaining Speakup, visit the web site at
22
http://linux-speakup.org/.  Speakup is a set of patches to the standard
23
Linux kernel source tree.  It can be built as a series of modules, or as
24
a part of a monolithic kernel.  These details are beyond the scope of
25
this manual, but the user may need to be aware of the module
26
capabilities, depending on how your system administrator has installed
27
Speakup.  If Speakup is built as a part of a monolithic kernel, and the
28
user is using a hardware synthesizer, then Speakup will be able to
29
provide speech access from the time the kernel is loaded, until the time
30
the system is shutdown.  This means that if you have obtained Linux
31
installation media for a distribution which includes Speakup as a part
32
of its kernel, you will be able, as a blind person, to install Linux
33
with speech access unaided by a sighted person.  Again, these details
34
are beyond the scope of this manual, but the user should be aware of
35
them.  See the web site mentioned above for further details.
36
37
1.  Starting Speakup
38
39
If your system administrator has installed Speakup to work with your
40
specific synthesizer by default, then all you need to do to use Speakup
41
is to boot your system, and Speakup should come up talking.  This
42
assumes of course  that your synthesizer is a supported hardware
43
synthesizer, and that it is either installed in or connected to your
44
system, and is if necessary powered on.
45
46
It is possible, however, that Speakup may have been compiled into the
47
kernel with no default synthesizer.  It is even possible that your
48
kernel has been compiled with support for some of the supported
49
synthesizers and not others.  If you find that this is the case, and
50
your synthesizer is supported but not available, complain to the person
51
who compiled and installed your kernel.  Or better yet, go to the web
52
site, and learn how to patch Speakup into your own kernel source, and
53
build and install your own kernel.
54
55
If your kernel has been compiled with Speakup, and has no default
56
synthesizer set, or you would like to use a different synthesizer than
57
the default one, then you may issue the following command at the boot
58
prompt of your boot loader.
59
60
linux speakup_synth=ltlk
61
62
This command would tell Speakup to look for and use a LiteTalk or
63
DoubleTalk LT at boot up.  You may replace the ltlk synthesizer keyword
64
with the keyword for whatever synthesizer you wish to use.  The
65
speakup_synth parameter will accept the following keywords, provided
66
that support for the related synthesizers has been built into the
67
kernel.
68
69
acntsa -- Accent SA
70
acntpc -- Accent PC
71
apolo -- Apolo
72
audptr -- Audapter
73
bns -- Braille 'n Speak
74
dectlk -- DecTalk Express (old and new, db9 serial only)
75
decext -- DecTalk (old) External
76
dtlk -- DoubleTalk PC
77
keypc -- Keynote Gold PC
78
ltlk -- DoubleTalk LT, LiteTalk, or external Tripletalk (db9 serial only)
79
spkout -- Speak Out
80
txprt -- Transport
81
82
Note: Speakup does * NOT * support usb connections!  Speakup also does *
83
NOT * support the internal Tripletalk!
84
85
Speakup does support two other synthesizers, but because they work in
86
conjunction with other software, they must be loaded as modules after
87
their related software is loaded, and so are not available at boot up. 
88
These are as follows:
89
90
decpc -- DecTalk PC (not available at boot up)
91
sftsyn -- One of several software synthesizers (not available at boot up)
92
93
See the sections on loading modules and software synthesizers later in
94
this manual for further details.  It should be noted here that the
95
speakup_synth boot parameter will have no effect if Speakup has been
96
compiled as modules.  In order for Speakup modules to be loaded during
97
the boot process, such action must be configured by your system
98
administrator.  This will mean that you will hear some, but not all,  of
99
the bootup messages.
100
101
2.  Basic operation
102
103
Once you have booted the system, and if necessary, have supplied the
104
proper bootup parameter for your synthesizer, Speakup will begin
105
talking as soon as the kernel is loaded.  In fact, it will talk a lot! 
106
It will speak all the boot up messages that the kernel prints on the
107
screen during the boot process.  This is because Speakup is not a
108
separate screen reader, but is actually built into the operating
109
system.  Since almost all console applications must print text on the
110
screen using the kernel, and must get their keyboard input through the
111
kernel, they are automatically handled properly by Speakup.  There are a
112
few exceptions, but we'll come to those later.
113
114
Note:  In this guide I will refer to the numeric keypad as the keypad. 
115
This is done because the speakupmap.map file referred to later in this
116
manual uses the term keypad instead of numeric keypad.  Also I'm lazy
117
and would rather only type one word.  So keypad it is.  Got it?  Good.
118
119
Most of the Speakup review keys are located on the keypad at the far
120
right of the keyboard.  The numlock key should be off, in order for these
121
to work.  If you toggle the numlock on, the keypad will produce numbers,
122
which is exactly what you want for spreadsheets and such.  For the
123
purposes of this guide, you should have the numlock turned off, which is
124
its default state at bootup.
125
126
You probably won't want to listen to all the bootup messages every time
127
you start your system, though it's a good idea to listen to them at
128
least once, just so you'll know what kind of information is available to
129
you during the boot process.  You can always review these messages after
130
bootup with the command:
131
132
dmesg | more
133
134
In order to speed the boot process, and to silence the speaking of the
135
bootup messages, just press the keypad enter key.  This key is located
136
in the bottom right corner of the keypad.  Speakup will shut up and stay
137
that way, until you press another key.
138
139
You can check to see if the boot process has completed by pressing the 8
140
key on the keypad, which reads the current line.  This also has the
141
effect of starting Speakup talking again, so you can press keypad enter
142
to silence it again if the boot process has not completed.  
143
144
When the boot process is complete, you will arrive at a "login" prompt.
145
At this point, you'll need to type in your user id and password, as
146
provided by your system administrator.  You will hear Speakup speak the
147
letters of your user id as you type it, but not the password.  This is
148
because the password is not displayed on the screen for security
149
reasons.  This has nothing to do with Speakup, it's a Linux security
150
feature.
151
152
Once you've logged in, you can run any Linux command or program which is
153
allowed by your user id.  Normal users will not be able to run programs
154
which require root privileges.
155
156
When you are running a program or command, Speakup will automatically
157
speak new text as it arrives on the screen.  You can at any time silence
158
the speech with keypad enter, or use any of the Speakup review keys. 
159
160
Here are some basic Speakup review keys, and a short description of what
161
they do.
162
163
keypad 1 -- read previous character
164
keypad 2 -- read current character (pressing keypad 2 twice rapidly will speak
165
	the current character phonetically)
166
keypad 3 -- read next character
167
keypad 4 -- read previous word
168
keypad 5 -- read current word (press twice rapidly to spell the current word)
169
keypad 6 -- read next word
170
keypad 7 -- read previous line
171
keypad 8 -- read current line (press twice rapidly to hear how much the
172
	text on the current line is indented)
173
keypad 9 -- read next line
174
keypad period -- speak current cursor position and announce current
175
	virtual console
176
177
It's also worth noting that the insert key on the keypad is mapped
178
as the speakup key.  Instead of pressing and releasing this key, as you
179
do under DOS or Windows, you hold it like a shift key, and press other
180
keys in combination with it.  For example, repeatedly holding keypad
181
insert, from now on called speakup, and keypad enter will toggle the
182
speaking of new text on the screen on and off.  This is not the same as
183
just pressing keypad enter by itself, which just silences the speech
184
until you hit another key.  When you hit speakup plus keypad enter,
185
Speakup will say, "You turned me off.", or "Hey, that's better."  When
186
Speakup is turned off, no new text on the screen will be spoken.  You
187
can still use the reading controls to review the screen however.
188
189
3.  Using the Speakup Help System
190
191
Speakup has a help system, which is compiled as a module.  It is loaded
192
automatically whenever the Speakup help system is invoked for the first
193
time, and remains loaded after that, until speakup is unloaded.  Note
194
that if speakup was compiled into a monolithic kernel on your system,
195
you will not be able to unload Speakup from your kernel.  If you try to
196
use the help system, and find that it is unavailable, then your system
197
administrator has not installed the Speakup help module, which is called
198
speakup_help.  Complain to your system administrator about this.
199
200
In order to enter the Speakup help system, press and hold the speakup
201
key (remember that this is the keypad insert key), and press the f1 key.
202
You will hear the message:
203
204
"Press space to leave help, cursor up or down to scroll, or a letter to
205
go to commands in list."
206
207
When you press the spacebar to leave the help system, you will hear:
208
209
"Leaving help."
210
211
While you are in the Speakup help system, you can scroll up or down
212
through the list of available commands using the cursor keys.  The list
213
of commands is arranged in alphabetical order.  If you wish to jump to
214
commands in a specific part of the alphabet, you may press the letter of
215
the alphabet you wish to jump to.
216
217
You can also just explore by typing keyboard keys.  Pressing keys will
218
cause Speakup to speak the command associated with that key.  For
219
example, if you press the keypad 8 key, you will hear:
220
221
"Keypad 8 is line, say current."
222
223
You'll notice that some commands do not have keys assigned to them. 
224
This is because they are very infrequently used commands, and are also
225
accessible through the proc system.  We'll discuss the proc system later
226
in this manual.
227
228
You'll also notice that some commands have two keys assigned to them. 
229
This is because Speakup has a built in set of alternative key bindings
230
for laptop users.  The alternate speakup key is the caps lock key.  You
231
can press and hold the caps lock key, while pressing an alternate
232
speakup command key to activate the command.  On most laptops, the
233
numeric keypad is defined as the keys in the j k l area of the keyboard.
234
235
There is usually a function key which turns this keypad function on and
236
off, and some other key which controls the numlock state.  Toggling the
237
keypad functionality on and off can become a royal pain.  So, Speakup
238
gives you a simple way to get at an alternative set of key mappings for
239
your laptop.  These are also available by default on desktop systems,
240
because Speakup does not know whether it is running on a desktop or
241
laptop.  So you may choose which set of Speakup keys to use.  Some
242
system administrators may have chosen to compile Speakup for a desktop
243
system without this set of alternate key bindings, but these details are
244
beyond the scope of this manual.  To use the caps lock for its normal
245
purpose, hold the shift key while toggling the caps lock on and off.  We
246
should note here, that holding the caps lock key and pressing the z key
247
will toggle the alternate j k l keypad on and off.
248
249
4.  Keys and Their Assigned Commands
250
251
In this section, we'll go through a list of all the speakup keys and
252
commands.  You can also get a list of commands and assigned keys from
253
the help system.
254
255
The following list was taken from the speakupmap.map file.  Key
256
assignments are on the left of the equal sign, and the associated
257
Speakup commands are on the right.  The designation "spk" means to press
258
and hold the speakup key, a.k.a. keypad insert, a.k.a. caps lock, while
259
pressing the other specified key.
260
261
spk key_f9 = punc_level_dec
262
spk key_f10 = punc_level_inc
263
spk key_f11 = reading_punc_dec
264
spk key_f12 = reading_punc_inc
265
spk key_1 = vol_dec
266
spk key_2 =  vol_inc
267
spk key_3 = pitch_dec
268
spk key_4 = pitch_inc
269
spk key_5 = rate_dec
270
spk key_6 = rate_inc
271
key_kpasterisk = toggle_cursoring
272
spk key_kpasterisk = speakup_goto
273
spk key_f1 = speakup_help
274
spk key_f2 = set_win
275
spk key_f3 = clear_win
276
spk key_f4 = enable_win
277
spk key_f5 = edit_some
278
spk key_f6 = edit_most
279
spk key_f7 = edit_delim
280
spk key_f8 = edit_repeat
281
shift spk key_f9 = edit_exnum
282
 key_kp7 = say_prev_line
283
spk key_kp7 = left_edge
284
 key_kp8 = say_line
285
double  key_kp8 = say_line_indent
286
spk key_kp8 = say_from_top
287
 key_kp9 = say_next_line
288
spk  key_kp9 = top_edge
289
 key_kpminus = speakup_parked
290
spk key_kpminus = say_char_num
291
 key_kp4 = say_prev_word
292
spk key_kp4 = say_from_left
293
 key_kp5 = say_word
294
double key_kp5 = spell_word
295
spk key_kp5 = spell_phonetic
296
 key_kp6 = say_next_word
297
spk key_kp6 = say_to_right
298
 key_kpplus = say_screen
299
spk key_kpplus = say_win
300
 key_kp1 = say_prev_char 
301
spk key_kp1 = right_edge
302
 key_kp2 = say_char
303
spk key_kp2 = say_to_bottom
304
double key_kp2 = say_phonetic_char
305
 key_kp3 = say_next_char  
306
spk  key_kp3 = bottom_edge
307
 key_kp0 = spk_key
308
 key_kpdot = say_position
309
spk key_kpdot = say_attributes
310
key_kpenter = speakup_quiet
311
spk key_kpenter = speakup_off
312
key_sysrq = speech_kill
313
 key_kpslash = speakup_cut
314
spk key_kpslash = speakup_paste
315
spk key_pageup = say_first_char
316
spk key_pagedown = say_last_char
317
key_capslock = spk_key
318
 spk key_z = spk_lock
319
key_leftmeta = spk_key
320
ctrl spk key_0 = speakup_goto
321
spk key_u = say_prev_line
322
spk key_i = say_line
323
double spk key_i = say_line_indent
324
spk key_o = say_next_line
325
spk key_minus = speakup_parked
326
shift spk key_minus = say_char_num
327
spk key_j = say_prev_word
328
spk key_k = say_word
329
double spk key_k = spell_word
330
spk key_l = say_next_word
331
spk key_m = say_prev_char
332
spk key_comma = say_char
333
double spk key_comma = say_phonetic_char
334
spk key_dot = say_next_char
335
spk key_n = say_position
336
 ctrl spk key_m = left_edge
337
 ctrl spk key_y = top_edge
338
 ctrl spk key_dot = right_edge
339
ctrl spk key_p = bottom_edge
340
spk key_apostrophe = say_screen
341
spk key_h = say_from_left
342
spk key_y = say_from_top
343
spk key_semicolon = say_to_right
344
spk key_p = say_to_bottom
345
spk key_slash = say_attributes
346
 spk key_enter = speakup_quiet
347
 ctrl  spk key_enter = speakup_off
348
 spk key_9 = speakup_cut
349
spk key_8 = speakup_paste
350
shift spk key_m = say_first_char
351
 ctrl spk key_semicolon = say_last_char
352
353
5.  The Speakup Proc System
354
355
The Speakup screen reader also creates a speakup subdirectory as a part
356
of the proc system.  You can see these entries by typing the command:
357
358
ls -1 /proc/speakup/*
359
360
If you issue the above ls command, you will get back something like
361
this:
362
363
/proc/speakup/attrib_bleep
364
/proc/speakup/bell_pos
365
/proc/speakup/bleep_time
366
/proc/speakup/bleeps
367
/proc/speakup/caps_start
368
/proc/speakup/caps_stop
369
/proc/speakup/characters
370
/proc/speakup/cursor_time
371
/proc/speakup/delay_time
372
/proc/speakup/delimiters
373
/proc/speakup/ex_num
374
/proc/speakup/freq
375
/proc/speakup/full_time
376
/proc/speakup/jiffy_delta
377
/proc/speakup/key_echo
378
/proc/speakup/keymap
379
/proc/speakup/no_interrupt
380
/proc/speakup/pitch
381
/proc/speakup/punc_all
382
/proc/speakup/punc_level
383
/proc/speakup/punc_most
384
/proc/speakup/punc_some
385
/proc/speakup/punct
386
/proc/speakup/rate
387
/proc/speakup/reading_punc
388
/proc/speakup/repeats
389
/proc/speakup/say_control
390
/proc/speakup/say_word_ctl
391
/proc/speakup/silent
392
/proc/speakup/spell_delay
393
/proc/speakup/synth_direct
394
/proc/speakup/synth_name
395
/proc/speakup/tone
396
/proc/speakup/trigger_time
397
/proc/speakup/version
398
/proc/speakup/voice
399
/proc/speakup/vol
400
401
In addition to using the Speakup hot keys to change such things as
402
volume, pitch, and rate, you can also echo values to the appropriate
403
entry in the /proc/speakup directory.  This is very useful, since it
404
lets you control Speakup parameters from within a script.  How you
405
would write such scripts is somewhat beyond the scope of this manual,
406
but I will include a couple of simple examples here to give you a
407
general idea of what such scripts can do.
408
409
Suppose for example, that you wanted to control both the punctuation
410
level and the reading punctuation level at the same time.  For
411
simplicity, we'll call them punc0, punc1, punc2, and punc3.  The scripts
412
might look something like this:
413
414
#!/bin/bash
415
# punc0
416
# set punc and reading punc levels to 0
417
echo 0 >/proc/speakup/punc_level
418
echo 0 >/proc/speakup/reading_punc
419
echo Punctuation level set to 0.
420
421
#!/bin/bash
422
# punc1
423
# set punc and reading punc levels to 1
424
echo 1 >/proc/speakup/punc_level
425
echo 1 >/proc/speakup/reading_punc
426
echo Punctuation level set to 1.
427
428
#!/bin/bash
429
# punc2
430
# set punc and reading punc levels to 2
431
echo 2 >/proc/speakup/punc_level
432
echo 2 >/proc/speakup/reading_punc
433
echo Punctuation level set to 2.
434
435
#!/bin/bash
436
# punc3
437
# set punc and reading punc levels to 3
438
echo 3 >/proc/speakup/punc_level
439
echo 3 >/proc/speakup/reading_punc
440
echo Punctuation level set to 3.
441
442
If you were to store these four small scripts in a directory in your
443
path, perhaps /usr/local/bin, and set the permissions to 755 with the
444
chmod command, then you could change the default reading punc and
445
punctuation levels at the same time by issuing just one command.  For
446
example, if you were to execute the punc3 command at your shell prompt,
447
then the reading punc and punc level would both get set to 3.
448
449
I should note that the above scripts were written to work with bash, but
450
regardless of which shell you use, you should be able to do something
451
similar.
452
453
The Speakup proc system also has another interesting use.  You can echo
454
Speakup parameters into the proc system in a script during system
455
startup, and speakup will return to your preferred parameters every time
456
the system is rebooted.
457
458
Most of the Speakup proc parameters can be manipulated by a regular user
459
on the system.  However, there are a few parameters that are dangerous
460
enough that they should only be manipulated by the root user on your
461
system.  There are even some parameters that are read only, and cannot
462
be written to at all.  For example, the version entry in the Speakup
463
proc system is read only.  This is because there is no reason for a user
464
to tamper with the version number which is reported by Speakup.  Doing
465
an ls -l on /proc/speakup/version will return this:
466
467
-r--r--r--    1 root     root            0 Mar 21 13:46 /proc/speakup/version
468
469
As you can see, the version entry in the Speakup proc system is read
470
only, is owned by root, and belongs to the root group.  Doing a cat of
471
/proc/speakup/version will display the Speakup version number, like
472
this:
473
474
cat /proc/speakup/version
475
Speakup v-2.00 CVS: Thu Oct 21 10:38:21 EDT 2004 
476
synth dtlk version 1.1
477
478
The display shows the Speakup version number, along with the version
479
number of the driver for the current synthesizer.
480
481
Looking at entries in the Speakup proc system can be useful in many
482
ways.  For example, you might wish to know what level your volume is set
483
at.  You could type:
484
485
cat /proc/speakup/vol
486
5
487
488
The number five which comes back is the level at which the synthesizer
489
volume is set at.
490
491
All the entries in the Speakup proc system are readable, some are
492
writable by root only, and some are writable by everyone.  Unless you
493
know what you are doing, you should probably leave the ones that are
494
writable by root only alone.  Most of the names are self explanatory. 
495
Vol for controlling volume, pitch for pitch, rate for controlling speaking
496
rate, etc.  If you find one you aren't sure about, you can post a query
497
on the Speakup list.
498
499
6.  Changing Synthesizers
500
501
It is possible to change to a different synthesizer while speakup is
502
running.  In other words, it is not necessary to reboot the system
503
in order to use a different synthesizer.  You can simply echo the
504
synthesizer keyword to the /proc/speakup/synth_name proc entry. 
505
Depending on your situation, you may wish to echo none to the synth_name
506
proc entry, to disable speech while one synthesizer is disconnected and
507
a second one is connected in its place.  Then echo the keyword for the
508
new synthesizer into the synth_name proc entry in order to start speech
509
with the newly connected synthesizer.  See the list of synthesizer
510
keywords in section 1 to find the keyword which matches your synth.
511
512
7.  Loading modules
513
514
As mentioned earlier, Speakup can either be completely compiled into the
515
kernel, with the exception of the help module, or it can be compiled as
516
a series of modules.   When compiled as modules, Speakup will only be
517
able to speak some of the bootup messages if your system administrator
518
has configured the system to load the modules at boo time. The modules
519
can  be loaded after the file systems have been checked and mounted, or
520
from an initrd.  There is a third possibility.  Speakup can be compiled
521
with some components built into the kernel, and others as modules.  As
522
we'll see in the next section, this is particularly useful when you are
523
working with software synthesizers.
524
525
If Speakup is completely compiled as modules, then you must use the
526
modprobe command to load Speakup.  You do this by loading the module for
527
the synthesizer driver you wish to use.  The driver modules are all
528
named speakup_<keyword>, where <keyword> is the keyword for the
529
synthesizer you want.  So, in order to load the driver for the DecTalk
530
Express, you would type the following command:
531
532
modprobe speakup_dectlk
533
534
Issuing this command would load the DecTalk Express driver and all other
535
related Speakup modules necessary to get Speakup up and running.
536
537
To completely unload Speakup, again presuming that it is entirely built
538
as modules, you would give the command:
539
540
modprobe -r speakup_dectlk
541
542
The above command assumes you were running a DecTalk Express.  If you
543
were using a different synth, then you would substitute its keyword in
544
place of dectlk.
545
546
But now, suppose we have a situation where the main Speakup component
547
is built into the kernel, and some or all of the drivers are built as
548
modules.  Since the main part of Speakup is compiled into the kernel, a
549
partial Speakup proc system has been created which we can take advantage
550
of by simply echoing the synthesizer keyword into the
551
/proc/speakup/synth_name proc entry.  This will cause the kernel to
552
automatically load the appropriate driver module, and start Speakup
553
talking.  To switch to another synth, just echo a new keyword to the
554
synth_name proc entry.  For example, to load the DoubleTalk LT driver,
555
you would type:
556
557
echo ltlk >/proc/speakup/synth_name
558
559
You can use the modprobe -r command to unload driver modules, regardless
560
of whether the main part of Speakup has been built into the kernel or
561
not.
562
563
8.  Using Software Synthesizers
564
565
Using a software synthesizer requires that some other software be
566
installed and running on your system.  For this reason, software
567
synthesizers are not available for use at bootup, or during a system
568
installation process.
569
570
In order to use a software synthesizer, you must have a package called
571
Speech Dispatcher running on your system, and it must be configured to
572
work with one of its supported software synthesizers.
573
574
Two open source synthesizers you might use are Flite and Festival.  You
575
might also choose to purchase the Software DecTalk from Fonix Sales Inc.
576
If you run a google search for Fonix, you'll find their web site.
577
578
You can obtain a copy of Speech Dispatcher from free(b)soft at
579
http://www.freebsoft.org/.  Follow the installation instructions that
580
come with Speech Dispatcher in order to install and configure Speech
581
Dispatcher.  You can check out the web site for your Linux distribution
582
in order to get a copy of either Flite or Festival.  Your Linux
583
distribution may also have a precompiled Speech Dispatcher package.
584
585
Once you've installed, configured, and tested Speech Dispatcher with your
586
chosen software synthesizer, you still need one more piece of software
587
in order to make things work.  You need a package called speechd-up. 
588
You get it from the free(b)soft web site mentioned above.  After you've
589
compiled and installed speechd-up, you are almost ready to begin using
590
your software synthesizer.
591
592
Before you can use a software synthesizer, you must have created the
593
/dev/softsynth device.  If you have not already done so, issue the
594
following commands as root:
595
596
cd /dev
597
mknod softsynth c 10 26
598
599
While we are at it, we might just as well create the /dev/synth device,
600
which can be used to let user space programs send information to your
601
synthesizer.  To create /dev/synth, change to the /dev directory, and
602
issue the following command as root:
603
604
mknod synth c 10 25
605
606
Now you can begin using your software synthesizer.  In order to do so,
607
echo the sftsyn keyword to the synth_name proc entry like this:
608
609
echo sftsyn >/proc/speakup/synth_name
610
611
Next run the speechd_up command like this:
612
613
speechd_up &
614
615
Your synth should now start talking, and you should be able to adjust
616
the pitch, rate, etc.
617
618
In this section, we have assumed that your copy of Speakup was compiled
619
with the speakup_sftsyn component either built into the kernel, or
620
compiled as a module.
621
622
9.  Using The DecTalk PC Card
623
624
The DecTalk PC card is an ISA card that is inserted into one of the ISA
625
slots in your computer.  It requires that the DecTalk PC software be
626
installed on your computer, and that the software be loaded onto the
627
Dectalk PC card before it can be used.
628
629
You can get the dec_pc.tgz file from the linux-speakup.org site.  The
630
dec_pc.tgz file is in the ~ftp/pub/linux/speakup directory.
631
632
After you have downloaded the dec_pc.tgz file, untar it in your home
633
directory, and read the Readme file in the newly created dec_pc
634
directory.
635
636
The easiest way to get the software working is to copy the entire dec_pc
637
directory into /user/local/lib.  To do this, su to root in your home
638
directory, and issue the command:
639
640
cp dec_pc /usr/local/lib
641
642
You will need to copy the dtload command from the dec_pc directory to a
643
directory in your path.  Either /usr/bin or /usr/local/bin is a good
644
choice.
645
646
You can now run the dtload command in order to load the DecTalk PC
647
software onto the card.  After you have done this, echo the decpc
648
keyword to the synth_name entry in the proc system like this:
649
650
echo decpc >/proc/speakup/synth_name
651
652
Your DecTalk PC should start talking, and then you can adjust the pitch,
653
rate, volume, voice, etc.  The voice entry in the Speakup proc system
654
will accept a number from 0 through 7 for the DecTalk PC synthesizer,
655
which will give you access to some of the DecTalk voices.
656
657
10.  Using Cursor Tracking
658
659
In Speakup version 2.0 and later, cursor tracking is turned on by
660
default.  This means that when you are using an editor, Speakup will
661
automatically speak characters as you move left and right with the
662
cursor keys, and lines as you move up and down with the cursor keys.
663
664
This is extremely useful, and makes editing files a snap.  But there are
665
times when cursor tracking can get in your way.  So Speakup provides a
666
toggle to turn cursor tracking on and off.  You do this with the keypad
667
asterisk key.  Pressing this key repeatedly will toggle the cursor
668
tracking on and off, and you will hear Speakup say, "cursoring off", and
669
"cursoring on".
670
671
Some folks like to turn cursor tracking off while they are using the
672
lynx web browser.  You definitely want to turn cursor tracking off when
673
you are using the alsamixer application.  Otherwise, you won't be able
674
to hear your mixer settings while you are using the arrow keys.
675
676
11.  Cut and Paste
677
678
One of Speakup's more useful features is the ability to cut and paste
679
text on the screen.  This means that you can capture information from a
680
program, and paste that captured text into a different place in the
681
program, or into an entirely different program, which may even be
682
running on a different console.
683
684
For example, in this manual, we have made references to several web
685
sites.  It would be nice if you could cut and paste these urls into your
686
web browser.  Speakup does this quite nicely.  Suppose you wanted to
687
past the following url into your browser:
688
689
http://linux-speakup.org/
690
691
Use the speakup review keys to position the reading cursor on the first
692
character of the above url.  When the reading cursor is in position,
693
press the keypad slash key once.  Speakup will say, "mark".  Next,
694
position the reading cursor on the rightmost character of the above
695
url. Press the keypad slash key once again to actually cut the text
696
from the screen.  Speakup will say, "cut".  Although we call this
697
cutting, Speakup does not actually delete the cut text from the screen. 
698
It makes a copy of the text in a special buffer for later pasting.
699
700
Now that you have the url cut from the screen, you can paste it into
701
your browser, or even paste the url on a command line as an argument to
702
your browser.
703
704
Suppose you want to start lynx and go to the Speakup site.
705
706
You can switch to a different console with the alt left and right
707
arrows, or you can switch to a specific console by typing alt and a
708
function key.  These are not Speakup commands, just standard Linux
709
console capabilities.
710
711
Once you've changed to an appropriate console, and are at a shell prompt,
712
type the word lynx, followed by a space.  Now press and hold the speakup
713
key, while you type the keypad slash character.  The url will be pasted
714
onto the command line, just as though you had typed it in.  Press the
715
enter key to execute the command.
716
717
The paste buffer will continue to hold the cut information, until a new
718
mark and cut operation is carried out.  This means you can paste the cut
719
information as many times as you like before doing another cut
720
operation.
721
722
You are not limited to cutting and pasting only one line on the screen.
723
You can also cut and paste rectangular regions of the screen.  Just
724
position the reading cursor at the top left corner of the text to be
725
cut, mark it with the keypad slash key, then position the reading cursor
726
at the bottom right corner of the region to be cut, and cut it with the
727
keypad slash key.
728
729
12.  Changing the Pronunciation of Characters
730
731
Through the /proc/speakup/chars proc entry, Speakup gives you the
732
ability to change how Speakup pronounces a given character.  You could,
733
for example, change how some punctuation characters are spoken.  You can
734
even change how Speakup will pronounce certain letters.
735
736
You may, for example, wish to change how Speakup pronounces the z
737
character.  The author of Speakup, Kirk Reiser, is Canadian, and thus
738
believes that the z should be pronounced zed.  If you are an American,
739
you might wish to use the zee pronunciation instead of zed.  You can
740
change the pronunciation of both the upper and lower case z with the
741
following two commands:
742
743
echo 90 zee >/proc/speakup/characters
744
echo 122 zee >/proc/speakup/characters
745
746
Let's examine the parts of the two previous commands.  They are issued
747
at the shell prompt, and could be placed in a startup script.
748
749
The word echo tells the shell that you want to have it display the
750
string of characters that follow the word echo.  If you were to just
751
type:
752
753
echo hello.
754
755
You would get the word hello printed on your screen as soon as you
756
pressed the enter key.  In this case, we are echoing strings that we
757
want to be redirected into the proc system.
758
759
The numbers 90 and 122 in the above echo commands are the ascii numeric
760
values for the upper and lower case z, the characters we wish to change.
761
762
The string zee is the pronunciation that we want Speakup to use for the
763
upper and lower case z.
764
765
The > symbol redirects the output of the echo command to a file, just
766
like in DOS, or at the Windows command prompt.
767
768
And finally, /proc/speakup/chars is the file entry in the proc system
769
where we want the output to be directed.  Speakup looks at the numeric
770
value of the character we want to change, and inserts the pronunciation
771
string into an internal table.
772
773
You can look at the whole table with the following command:
774
775
cat /proc/speakup/chars
776
777
Speakup will then print out the entire character pronunciation table.  I
778
won't display it here, but leave you to look at it at your convenience.
779
780
13.  Mapping Keys
781
782
Speakup has the capability of allowing you to assign or "map" keys to
783
internal Speakup commands.  This section necessarily assumes you have a
784
Linux kernel source tree installed, and that it has been patched and
785
configured with Speakup.  How you do this is beyond the scope of this
786
manual.  For this information, visit the Speakup web site at
787
http://linux-speakup.org/.  The reason you'll need the kernel source
788
tree patched with Speakup is that the genmap utility you'll need for
789
processing keymaps is in the
790
/usr/src/linux-<version_number>/drivers/char/speakup directory.  The
791
<version_number> in the above directory path is the version number of
792
the Linux source tree you are working with.
793
794
So ok, you've gone off and gotten your kernel source tree, and patched
795
and configured it.  Now you can start manipulating keymaps.
796
797
You can either use the
798
/usr/src/linux-<version_number>/drivers/char/speakup/speakupmap.map file
799
included with the Speakup source, or you can cut and paste the copy in
800
section 4 into a separate file.  If you use the one in the Speakup
801
source tree, make sure you make a backup of it before you start making
802
changes.  You have been warned!
803
804
Suppose that you want to swap the key assignments for the Speakup
805
say_last_char and the Speakup say_first_char commands.  The
806
speakupmap.map lists the key mappings for these two commands as follows:
807
808
spk key_pageup = say_first_char
809
spk key_pagedown = say_last_char
810
811
You can edit your copy of the speakupmap.map file and swap the command
812
names on the right side of the = (equals) sign.  You did make a backup,
813
right?  The new keymap lines would look like this:
814
815
spk key_pageup = say_last_char
816
spk key_pagedown = say_first_char
817
818
After you edit your copy of the speakupmap.map file, save it under a new
819
file name, perhaps newmap.map.  Then exit your editor and return to the
820
shell prompt.
821
822
You are now ready to load your keymap with your swapped key assignments.
823
 Assuming that you saved your new keymap as the file newmap.map, you
824
would load your keymap into the proc system like this:
825
826
/usr/src/linux-<version_number>/drivers/char/speakup/genmap newmap.map
827
>/proc/speakup/keymap
828
829
Remember to substitute your kernel version number for the
830
<version_number> in the above command.  Also note that although the
831
above command wrapped onto two lines in this document, you should type
832
it all on one line.
833
834
Your say first and say last characters should now be swapped.  Pressing
835
speakup pagedown should read you the first non-whitespace character on
836
the line your reading cursor is in, and pressing speakup pageup should
837
read you the last character on the line your reading cursor is in.
838
839
You should note that these new mappings will only stay in effect until
840
you reboot, or until you load another keymap.
841
842
One final warning.  If you try to load a partial map, you will quickly
843
find that all the mappings you didn't include in your file got deleted
844
from the working map.  Be extremely careful, and always make a backup! 
845
You have been warned!
846
847
14.  Using Speakup's Windowing Capability
848
849
Speakup has the capability of defining and manipulating windows on the
850
screen.  Speakup uses the term "Window", to mean a user defined area of
851
the screen.  The key strokes for defining and manipulating Speakup
852
windows are as follows:
853
854
speakup + f2 -- Set the bounds of the window.
855
Speakup + f3 -- clear the current window definition.
856
speakup + f4 -- Toggle window silence on and off.
857
speakup + keypad plus -- Say the currently defined window.
858
859
These capabilities are useful for tracking a certain part of the screen
860
without rereading the whole screen, or for silencing a part of the
861
screen that is constantly changing, such as a clock or status line.
862
863
There is no way to save these window settings, and you can only have one
864
window defined for each virtual console.  There is also no way to have
865
windows automaticly defined for specific applications.
866
867
In order to define a window, use the review keys to move your reading
868
cursor to the beginning of the area you want to define.  Then press
869
speakup + f2.  Speakup will tell you that the window starts at the
870
indicated row and column position.  Then move the reading cursor to the
871
end of the area to be defined as a window, and press speakup + f2 again.
872
 If there is more than one line in the window, Speakup will tell you
873
that the window ends at the indicated row and column position.  If there
874
is only one line in the window, then Speakup will tell you that the
875
window is the specified line on the screen.  If you are only defining a
876
one line window, you can just press speakup + f2 twice after placing the
877
reading cursor on the line you want to define as a window.  It is not
878
necessary to position the reading cursor at the end of the line in order
879
to define the whole line as a window.
880
881
                GNU Free Documentation License
882
                  Version 1.2, November 2002
883
884
885
 Copyright (C) 2000,2001,2002  Free Software Foundation, Inc.
886
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
887
 Everyone is permitted to copy and distribute verbatim copies
888
 of this license document, but changing it is not allowed.
889
890
891
0. PREAMBLE
892
893
The purpose of this License is to make a manual, textbook, or other
894
functional and useful document "free" in the sense of freedom: to
895
assure everyone the effective freedom to copy and redistribute it,
896
with or without modifying it, either commercially or noncommercially.
897
Secondarily, this License preserves for the author and publisher a way
898
to get credit for their work, while not being considered responsible
899
for modifications made by others.
900
901
This License is a kind of "copyleft", which means that derivative
902
works of the document must themselves be free in the same sense.  It
903
complements the GNU General Public License, which is a copyleft
904
license designed for free software.
905
906
We have designed this License in order to use it for manuals for free
907
software, because free software needs free documentation: a free
908
program should come with manuals providing the same freedoms that the
909
software does.  But this License is not limited to software manuals;
910
it can be used for any textual work, regardless of subject matter or
911
whether it is published as a printed book.  We recommend this License
912
principally for works whose purpose is instruction or reference.
913
914
915
1. APPLICABILITY AND DEFINITIONS
916
917
This License applies to any manual or other work, in any medium, that
918
contains a notice placed by the copyright holder saying it can be
919
distributed under the terms of this License.  Such a notice grants a
920
world-wide, royalty-free license, unlimited in duration, to use that
921
work under the conditions stated herein.  The "Document", below,
922
refers to any such manual or work.  Any member of the public is a
923
licensee, and is addressed as "you".  You accept the license if you
924
copy, modify or distribute the work in a way requiring permission
925
under copyright law.
926
927
A "Modified Version" of the Document means any work containing the
928
Document or a portion of it, either copied verbatim, or with
929
modifications and/or translated into another language.
930
931
A "Secondary Section" is a named appendix or a front-matter section of
932
the Document that deals exclusively with the relationship of the
933
publishers or authors of the Document to the Document's overall subject
934
(or to related matters) and contains nothing that could fall directly
935
within that overall subject.  (Thus, if the Document is in part a
936
textbook of mathematics, a Secondary Section may not explain any
937
mathematics.)  The relationship could be a matter of historical
938
connection with the subject or with related matters, or of legal,
939
commercial, philosophical, ethical or political position regarding
940
them.
941
942
The "Invariant Sections" are certain Secondary Sections whose titles
943
are designated, as being those of Invariant Sections, in the notice
944
that says that the Document is released under this License.  If a
945
section does not fit the above definition of Secondary then it is not
946
allowed to be designated as Invariant.  The Document may contain zero
947
Invariant Sections.  If the Document does not identify any Invariant
948
Sections then there are none.
949
950
The "Cover Texts" are certain short passages of text that are listed,
951
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
952
the Document is released under this License.  A Front-Cover Text may
953
be at most 5 words, and a Back-Cover Text may be at most 25 words.
954
955
A "Transparent" copy of the Document means a machine-readable copy,
956
represented in a format whose specification is available to the
957
general public, that is suitable for revising the document
958
straightforwardly with generic text editors or (for images composed of
959
pixels) generic paint programs or (for drawings) some widely available
960
drawing editor, and that is suitable for input to text formatters or
961
for automatic translation to a variety of formats suitable for input
962
to text formatters.  A copy made in an otherwise Transparent file
963
format whose markup, or absence of markup, has been arranged to thwart
964
or discourage subsequent modification by readers is not Transparent.
965
An image format is not Transparent if used for any substantial amount
966
of text.  A copy that is not "Transparent" is called "Opaque".
967
968
Examples of suitable formats for Transparent copies include plain
969
ASCII without markup, Texinfo input format, LaTeX input format, SGML
970
or XML using a publicly available DTD, and standard-conforming simple
971
HTML, PostScript or PDF designed for human modification.  Examples of
972
transparent image formats include PNG, XCF and JPG.  Opaque formats
973
include proprietary formats that can be read and edited only by
974
proprietary word processors, SGML or XML for which the DTD and/or
975
processing tools are not generally available, and the
976
machine-generated HTML, PostScript or PDF produced by some word
977
processors for output purposes only.
978
979
The "Title Page" means, for a printed book, the title page itself,
980
plus such following pages as are needed to hold, legibly, the material
981
this License requires to appear in the title page.  For works in
982
formats which do not have any title page as such, "Title Page" means
983
the text near the most prominent appearance of the work's title,
984
preceding the beginning of the body of the text.
985
986
A section "Entitled XYZ" means a named subunit of the Document whose
987
title either is precisely XYZ or contains XYZ in parentheses following
988
text that translates XYZ in another language.  (Here XYZ stands for a
989
specific section name mentioned below, such as "Acknowledgements",
990
"Dedications", "Endorsements", or "History".)  To "Preserve the Title"
991
of such a section when you modify the Document means that it remains a
992
section "Entitled XYZ" according to this definition.
993
994
The Document may include Warranty Disclaimers next to the notice which
995
states that this License applies to the Document.  These Warranty
996
Disclaimers are considered to be included by reference in this
997
License, but only as regards disclaiming warranties: any other
998
implication that these Warranty Disclaimers may have is void and has
999
no effect on the meaning of this License.
1000
1001
1002
2. VERBATIM COPYING
1003
1004
You may copy and distribute the Document in any medium, either
1005
commercially or noncommercially, provided that this License, the
1006
copyright notices, and the license notice saying this License applies
1007
to the Document are reproduced in all copies, and that you add no other
1008
conditions whatsoever to those of this License.  You may not use
1009
technical measures to obstruct or control the reading or further
1010
copying of the copies you make or distribute.  However, you may accept
1011
compensation in exchange for copies.  If you distribute a large enough
1012
number of copies you must also follow the conditions in section 3.
1013
1014
You may also lend copies, under the same conditions stated above, and
1015
you may publicly display copies.
1016
1017
1018
3. COPYING IN QUANTITY
1019
1020
If you publish printed copies (or copies in media that commonly have
1021
printed covers) of the Document, numbering more than 100, and the
1022
Document's license notice requires Cover Texts, you must enclose the
1023
copies in covers that carry, clearly and legibly, all these Cover
1024
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
1025
the back cover.  Both covers must also clearly and legibly identify
1026
you as the publisher of these copies.  The front cover must present
1027
the full title with all words of the title equally prominent and
1028
visible.  You may add other material on the covers in addition.
1029
Copying with changes limited to the covers, as long as they preserve
1030
the title of the Document and satisfy these conditions, can be treated
1031
as verbatim copying in other respects.
1032
1033
If the required texts for either cover are too voluminous to fit
1034
legibly, you should put the first ones listed (as many as fit
1035
reasonably) on the actual cover, and continue the rest onto adjacent
1036
pages.
1037
1038
If you publish or distribute Opaque copies of the Document numbering
1039
more than 100, you must either include a machine-readable Transparent
1040
copy along with each Opaque copy, or state in or with each Opaque copy
1041
a computer-network location from which the general network-using
1042
public has access to download using public-standard network protocols
1043
a complete Transparent copy of the Document, free of added material.
1044
If you use the latter option, you must take reasonably prudent steps,
1045
when you begin distribution of Opaque copies in quantity, to ensure
1046
that this Transparent copy will remain thus accessible at the stated
1047
location until at least one year after the last time you distribute an
1048
Opaque copy (directly or through your agents or retailers) of that
1049
edition to the public.
1050
1051
It is requested, but not required, that you contact the authors of the
1052
Document well before redistributing any large number of copies, to give
1053
them a chance to provide you with an updated version of the Document.
1054
1055
1056
4. MODIFICATIONS
1057
1058
You may copy and distribute a Modified Version of the Document under
1059
the conditions of sections 2 and 3 above, provided that you release
1060
the Modified Version under precisely this License, with the Modified
1061
Version filling the role of the Document, thus licensing distribution
1062
and modification of the Modified Version to whoever possesses a copy
1063
of it.  In addition, you must do these things in the Modified Version:
1064
1065
A. Use in the Title Page (and on the covers, if any) a title distinct
1066
   from that of the Document, and from those of previous versions
1067
   (which should, if there were any, be listed in the History section
1068
   of the Document).  You may use the same title as a previous version
1069
   if the original publisher of that version gives permission.
1070
B. List on the Title Page, as authors, one or more persons or entities
1071
   responsible for authorship of the modifications in the Modified
1072
   Version, together with at least five of the principal authors of the
1073
   Document (all of its principal authors, if it has fewer than five),
1074
   unless they release you from this requirement.
1075
C. State on the Title page the name of the publisher of the
1076
   Modified Version, as the publisher.
1077
D. Preserve all the copyright notices of the Document.
1078
E. Add an appropriate copyright notice for your modifications
1079
   adjacent to the other copyright notices.
1080
F. Include, immediately after the copyright notices, a license notice
1081
   giving the public permission to use the Modified Version under the
1082
   terms of this License, in the form shown in the Addendum below.
1083
G. Preserve in that license notice the full lists of Invariant Sections
1084
   and required Cover Texts given in the Document's license notice.
1085
H. Include an unaltered copy of this License.
1086
I. Preserve the section Entitled "History", Preserve its Title, and add
1087
   to it an item stating at least the title, year, new authors, and
1088
   publisher of the Modified Version as given on the Title Page.  If
1089
   there is no section Entitled "History" in the Document, create one
1090
   stating the title, year, authors, and publisher of the Document as
1091
   given on its Title Page, then add an item describing the Modified
1092
   Version as stated in the previous sentence.
1093
J. Preserve the network location, if any, given in the Document for
1094
   public access to a Transparent copy of the Document, and likewise
1095
   the network locations given in the Document for previous versions
1096
   it was based on.  These may be placed in the "History" section.
1097
   You may omit a network location for a work that was published at
1098
   least four years before the Document itself, or if the original
1099
   publisher of the version it refers to gives permission.
1100
K. For any section Entitled "Acknowledgements" or "Dedications",
1101
   Preserve the Title of the section, and preserve in the section all
1102
   the substance and tone of each of the contributor acknowledgements
1103
   and/or dedications given therein.
1104
L. Preserve all the Invariant Sections of the Document,
1105
   unaltered in their text and in their titles.  Section numbers
1106
   or the equivalent are not considered part of the section titles.
1107
M. Delete any section Entitled "Endorsements".  Such a section
1108
   may not be included in the Modified Version.
1109
N. Do not retitle any existing section to be Entitled "Endorsements"
1110
   or to conflict in title with any Invariant Section.
1111
O. Preserve any Warranty Disclaimers.
1112
1113
If the Modified Version includes new front-matter sections or
1114
appendices that qualify as Secondary Sections and contain no material
1115
copied from the Document, you may at your option designate some or all
1116
of these sections as invariant.  To do this, add their titles to the
1117
list of Invariant Sections in the Modified Version's license notice.
1118
These titles must be distinct from any other section titles.
1119
1120
You may add a section Entitled "Endorsements", provided it contains
1121
nothing but endorsements of your Modified Version by various
1122
parties--for example, statements of peer review or that the text has
1123
been approved by an organization as the authoritative definition of a
1124
standard.
1125
1126
You may add a passage of up to five words as a Front-Cover Text, and a
1127
passage of up to 25 words as a Back-Cover Text, to the end of the list
1128
of Cover Texts in the Modified Version.  Only one passage of
1129
Front-Cover Text and one of Back-Cover Text may be added by (or
1130
through arrangements made by) any one entity.  If the Document already
1131
includes a cover text for the same cover, previously added by you or
1132
by arrangement made by the same entity you are acting on behalf of,
1133
you may not add another; but you may replace the old one, on explicit
1134
permission from the previous publisher that added the old one.
1135
1136
The author(s) and publisher(s) of the Document do not by this License
1137
give permission to use their names for publicity for or to assert or
1138
imply endorsement of any Modified Version.
1139
1140
1141
5. COMBINING DOCUMENTS
1142
1143
You may combine the Document with other documents released under this
1144
License, under the terms defined in section 4 above for modified
1145
versions, provided that you include in the combination all of the
1146
Invariant Sections of all of the original documents, unmodified, and
1147
list them all as Invariant Sections of your combined work in its
1148
license notice, and that you preserve all their Warranty Disclaimers.
1149
1150
The combined work need only contain one copy of this License, and
1151
multiple identical Invariant Sections may be replaced with a single
1152
copy.  If there are multiple Invariant Sections with the same name but
1153
different contents, make the title of each such section unique by
1154
adding at the end of it, in parentheses, the name of the original
1155
author or publisher of that section if known, or else a unique number.
1156
Make the same adjustment to the section titles in the list of
1157
Invariant Sections in the license notice of the combined work.
1158
1159
In the combination, you must combine any sections Entitled "History"
1160
in the various original documents, forming one section Entitled
1161
"History"; likewise combine any sections Entitled "Acknowledgements",
1162
and any sections Entitled "Dedications".  You must delete all sections
1163
Entitled "Endorsements".
1164
1165
1166
6. COLLECTIONS OF DOCUMENTS
1167
1168
You may make a collection consisting of the Document and other documents
1169
released under this License, and replace the individual copies of this
1170
License in the various documents with a single copy that is included in
1171
the collection, provided that you follow the rules of this License for
1172
verbatim copying of each of the documents in all other respects.
1173
1174
You may extract a single document from such a collection, and distribute
1175
it individually under this License, provided you insert a copy of this
1176
License into the extracted document, and follow this License in all
1177
other respects regarding verbatim copying of that document.
1178
1179
1180
7. AGGREGATION WITH INDEPENDENT WORKS
1181
1182
A compilation of the Document or its derivatives with other separate
1183
and independent documents or works, in or on a volume of a storage or
1184
distribution medium, is called an "aggregate" if the copyright
1185
resulting from the compilation is not used to limit the legal rights
1186
of the compilation's users beyond what the individual works permit.
1187
When the Document is included in an aggregate, this License does not
1188
apply to the other works in the aggregate which are not themselves
1189
derivative works of the Document.
1190
1191
If the Cover Text requirement of section 3 is applicable to these
1192
copies of the Document, then if the Document is less than one half of
1193
the entire aggregate, the Document's Cover Texts may be placed on
1194
covers that bracket the Document within the aggregate, or the
1195
electronic equivalent of covers if the Document is in electronic form.
1196
Otherwise they must appear on printed covers that bracket the whole
1197
aggregate.
1198
1199
1200
8. TRANSLATION
1201
1202
Translation is considered a kind of modification, so you may
1203
distribute translations of the Document under the terms of section 4.
1204
Replacing Invariant Sections with translations requires special
1205
permission from their copyright holders, but you may include
1206
translations of some or all Invariant Sections in addition to the
1207
original versions of these Invariant Sections.  You may include a
1208
translation of this License, and all the license notices in the
1209
Document, and any Warranty Disclaimers, provided that you also include
1210
the original English version of this License and the original versions
1211
of those notices and disclaimers.  In case of a disagreement between
1212
the translation and the original version of this License or a notice
1213
or disclaimer, the original version will prevail.
1214
1215
If a section in the Document is Entitled "Acknowledgements",
1216
"Dedications", or "History", the requirement (section 4) to Preserve
1217
its Title (section 1) will typically require changing the actual
1218
title.
1219
1220
1221
9. TERMINATION
1222
1223
You may not copy, modify, sublicense, or distribute the Document except
1224
as expressly provided for under this License.  Any other attempt to
1225
copy, modify, sublicense or distribute the Document is void, and will
1226
automatically terminate your rights under this License.  However,
1227
parties who have received copies, or rights, from you under this
1228
License will not have their licenses terminated so long as such
1229
parties remain in full compliance.
1230
1231
1232
10. FUTURE REVISIONS OF THIS LICENSE
1233
1234
The Free Software Foundation may publish new, revised versions
1235
of the GNU Free Documentation License from time to time.  Such new
1236
versions will be similar in spirit to the present version, but may
1237
differ in detail to address new problems or concerns.  See
1238
http://www.gnu.org/copyleft/.
1239
1240
Each version of the License is given a distinguishing version number.
1241
If the Document specifies that a particular numbered version of this
1242
License "or any later version" applies to it, you have the option of
1243
following the terms and conditions either of that specified version or
1244
of any later version that has been published (not as a draft) by the
1245
Free Software Foundation.  If the Document does not specify a version
1246
number of this License, you may choose any version ever published (not
1247
as a draft) by the Free Software Foundation.
1248
1249
1250
ADDENDUM: How to use this License for your documents
1251
1252
To use this License in a document you have written, include a copy of
1253
the License in the document and put the following copyright and
1254
license notices just after the title page:
1255
1256
    Copyright (c)  YEAR  YOUR NAME.
1257
    Permission is granted to copy, distribute and/or modify this document
1258
    under the terms of the GNU Free Documentation License, Version 1.2
1259
    or any later version published by the Free Software Foundation;
1260
    with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
1261
    A copy of the license is included in the section entitled "GNU
1262
    Free Documentation License".
1263
1264
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
1265
replace the "with...Texts." line with this:
1266
1267
    with the Invariant Sections being LIST THEIR TITLES, with the
1268
    Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
1269
1270
If you have Invariant Sections without Cover Texts, or some other
1271
combination of the three, merge those two alternatives to suit the
1272
situation.
1273
1274
If your document contains nontrivial examples of program code, we
1275
recommend releasing these examples in parallel under your choice of
1276
free software license, such as the GNU General Public License,
1277
to permit their use in free software.
1278
1279
The End.
(-)linux-2.6.20/drivers/char/consolemap.c (+1 lines)
Lines 667-669 console_map_init(void) Link Here
667
}
667
}
668
668
669
EXPORT_SYMBOL(con_copy_unimap);
669
EXPORT_SYMBOL(con_copy_unimap);
670
EXPORT_SYMBOL_GPL(inverse_translate);
(-)linux-2.6.20/drivers/char/keyboard.c (-3 / +39 lines)
Lines 41-46 Link Here
41
#include <linux/input.h>
41
#include <linux/input.h>
42
#include <linux/reboot.h>
42
#include <linux/reboot.h>
43
43
44
45
#include <linux/speakup.h>
46
47
#if defined(CONFIG_SPEAKUP_MODULE)
48
49
spk_key_func addr_spk_key = NULL;
50
#define speakup_key_call(__vc, __shift, __keycode, __key, __down)	\
51
	(addr_spk_key && (*addr_spk_key)(__vc, __shift, __keycode, __key, __down))
52
53
#elif defined(CONFIG_SPEAKUP)
54
#define speakup_key_call(__vc, __shift, __keycode, __key, __down)	\
55
	speakup_key(__vc, __shift, __keycode, __key, __down)
56
#else
57
#define speakup_key_call(__vc, __shift, __keycode, __key, __down)	0
58
#endif
59
44
static void kbd_disconnect(struct input_handle *handle);
60
static void kbd_disconnect(struct input_handle *handle);
45
extern void ctrl_alt_del(void);
61
extern void ctrl_alt_del(void);
46
62
Lines 65-70 extern void ctrl_alt_del(void); Link Here
65
81
66
#define KBD_DEFLOCK 0
82
#define KBD_DEFLOCK 0
67
83
84
/* Key types processed even in raw modes */
85
86
#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT) | (1 << KT_SPKUP))
87
68
void compute_shiftstate(void);
88
void compute_shiftstate(void);
69
89
70
/*
90
/*
Lines 80-86 void compute_shiftstate(void); Link Here
80
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
100
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
81
			    char up_flag);
101
			    char up_flag);
82
static k_handler_fn K_HANDLERS;
102
static k_handler_fn K_HANDLERS;
83
static k_handler_fn *k_handler[16] = { K_HANDLERS };
103
k_handler_fn *k_handler[16] = { K_HANDLERS };
84
104
85
#define FN_HANDLERS\
105
#define FN_HANDLERS\
86
	fn_null,	fn_enter,	fn_show_ptregs,	fn_show_mem,\
106
	fn_null,	fn_enter,	fn_show_ptregs,	fn_show_mem,\
Lines 101-113 static fn_handler_fn *fn_handler[] = { F Link Here
101
const int max_vals[] = {
121
const int max_vals[] = {
102
	255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
122
	255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
103
	NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
123
	NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
104
	255, NR_LOCK - 1, 255, NR_BRL - 1
124
	255, NR_LOCK - 1, 255, NR_BRL - 1, 255
105
};
125
};
106
126
107
const int NR_TYPES = ARRAY_SIZE(max_vals);
127
const int NR_TYPES = ARRAY_SIZE(max_vals);
108
128
109
struct kbd_struct kbd_table[MAX_NR_CONSOLES];
129
struct kbd_struct kbd_table[MAX_NR_CONSOLES];
110
static struct kbd_struct *kbd = kbd_table;
130
struct kbd_struct *kbd = kbd_table;
131
132
EXPORT_SYMBOL_GPL(kbd);
133
EXPORT_SYMBOL_GPL(k_handler);
111
134
112
struct vt_spawn_console vt_spawn_con = {
135
struct vt_spawn_console vt_spawn_con = {
113
	.lock = SPIN_LOCK_UNLOCKED,
136
	.lock = SPIN_LOCK_UNLOCKED,
Lines 266-271 void kd_mksound(unsigned int hz, unsigne Link Here
266
		kd_nosound(0);
289
		kd_nosound(0);
267
}
290
}
268
291
292
EXPORT_SYMBOL_GPL(kd_mksound);
293
269
/*
294
/*
270
 * Setting the keyboard rate.
295
 * Setting the keyboard rate.
271
 */
296
 */
Lines 623-628 static void k_spec(struct vc_data *vc, u Link Here
623
	if (up_flag)
648
	if (up_flag)
624
		return;
649
		return;
625
	if (value >= ARRAY_SIZE(fn_handler))
650
	if (value >= ARRAY_SIZE(fn_handler))
651
		if (up_flag || (value >= ARRAY_SIZE(fn_handler)))
626
		return;
652
		return;
627
	if ((kbd->kbdmode == VC_RAW ||
653
	if ((kbd->kbdmode == VC_RAW ||
628
	     kbd->kbdmode == VC_MEDIUMRAW) &&
654
	     kbd->kbdmode == VC_MEDIUMRAW) &&
Lines 1233-1238 static void kbd_keycode(unsigned int key Link Here
1233
	key_map = key_maps[shift_final];
1259
	key_map = key_maps[shift_final];
1234
1260
1235
	if (!key_map) {
1261
	if (!key_map) {
1262
		if (speakup_key_call(vc, shift_final, keycode, K(KT_SHIFT,0), !down))
1263
			return;
1264
1236
		compute_shiftstate();
1265
		compute_shiftstate();
1237
		kbd->slockstate = 0;
1266
		kbd->slockstate = 0;
1238
		return;
1267
		return;
Lines 1256-1261 static void kbd_keycode(unsigned int key Link Here
1256
1285
1257
	type -= 0xf0;
1286
	type -= 0xf0;
1258
1287
1288
	if (speakup_key_call(vc, shift_final, keycode, keysym, !down))
1289
		return;
1290
1259
	if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
1291
	if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
1260
		return;
1292
		return;
1261
1293
Lines 1274-1279 static void kbd_keycode(unsigned int key Link Here
1274
		kbd->slockstate = 0;
1306
		kbd->slockstate = 0;
1275
}
1307
}
1276
1308
1309
struct input_dev *fakekeydev=NULL;
1310
EXPORT_SYMBOL_GPL(fakekeydev);
1311
1277
static void kbd_event(struct input_handle *handle, unsigned int event_type,
1312
static void kbd_event(struct input_handle *handle, unsigned int event_type,
1278
		      unsigned int event_code, int value)
1313
		      unsigned int event_code, int value)
1279
{
1314
{
Lines 1311-1316 static struct input_handle *kbd_connect( Link Here
1311
		return NULL;
1346
		return NULL;
1312
1347
1313
	handle->dev = dev;
1348
	handle->dev = dev;
1349
	fakekeydev = dev;
1314
	handle->handler = handler;
1350
	handle->handler = handler;
1315
	handle->name = "kbd";
1351
	handle->name = "kbd";
1316
1352
(-)linux-2.6.20/drivers/char/Makefile (+1 lines)
Lines 91-96 obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu. Link Here
91
obj-$(CONFIG_TANBAC_TB0219)	+= tb0219.o
91
obj-$(CONFIG_TANBAC_TB0219)	+= tb0219.o
92
obj-$(CONFIG_TELCLOCK)		+= tlclk.o
92
obj-$(CONFIG_TELCLOCK)		+= tlclk.o
93
93
94
obj-$(CONFIG_SPEAKUP)		+= speakup/
94
obj-$(CONFIG_WATCHDOG)		+= watchdog/
95
obj-$(CONFIG_WATCHDOG)		+= watchdog/
95
obj-$(CONFIG_MWAVE)		+= mwave/
96
obj-$(CONFIG_MWAVE)		+= mwave/
96
obj-$(CONFIG_AGP)		+= agp/
97
obj-$(CONFIG_AGP)		+= agp/
(-)linux-2.6.20/drivers/char/speakup/Config.in (+26 lines)
Line 0 Link Here
1
tristate 'Speakup console speech' CONFIG_SPEAKUP
2
if [ "$CONFIG_SPEAKUP" != "n" ]; then
3
	comment 'Type "y" for each synthesizer you want built into the kernel.'
4
	dep_tristate "Accent SA, acntsa" CONFIG_SPEAKUP_ACNTSA $CONFIG_SPEAKUP
5
	dep_tristate "Accent PC, acntpc" CONFIG_SPEAKUP_ACNTPC $CONFIG_SPEAKUP
6
	dep_tristate "Apollo, apollo" CONFIG_SPEAKUP_APOLLO $CONFIG_SPEAKUP
7
	dep_tristate "Audapter, audptr" CONFIG_SPEAKUP_AUDPTR $CONFIG_SPEAKUP
8
	dep_tristate "Braille 'n' Speak, bns" CONFIG_SPEAKUP_BNS $CONFIG_SPEAKUP
9
	dep_tristate "DECtalk Express, dectlk" CONFIG_SPEAKUP_DECTLK $CONFIG_SPEAKUP
10
	dep_tristate "DECtalk External (old), decext" CONFIG_SPEAKUP_DECEXT $CONFIG_SPEAKUP
11
	dep_tristate "DECtalk PC (big ISA card), decpc" CONFIG_SPEAKUP_DECPC $CONFIG_SPEAKUP
12
	if [ "$CONFIG_SPEAKUP_DECPC" = "y" ] ;then
13
	  comment 'warning: decpc can only be built as a module'
14
	fi
15
	comment 'In order to use this you will need'
16
	comment 'the dtload program and DECPC software files '
17
	  comment 'Read the accompanying DECPC documentation for more details'
18
	dep_tristate "DoubleTalk PC, dtlk" CONFIG_SPEAKUP_DTLK $CONFIG_SPEAKUP
19
	dep_tristate "Keynote Gold PC, keypc" CONFIG_SPEAKUP_KEYPC $CONFIG_SPEAKUP
20
	dep_tristate "DoubleTalk LT or LiteTalk, ltlk" CONFIG_SPEAKUP_LTLK $CONFIG_SPEAKUP
21
	dep_tristate "Software synthesizers /dev/sftsyn, sftsyn" CONFIG_SPEAKUP_SFTSYN $CONFIG_SPEAKUP
22
	dep_tristate "Speak Out, spkout" CONFIG_SPEAKUP_SPKOUT $CONFIG_SPEAKUP
23
	dep_tristate "Transport, txprt" CONFIG_SPEAKUP_TXPRT $CONFIG_SPEAKUP
24
	comment 'Enter the three to six character synth string from above or none.'
25
	string "Default synthesizer for Speakup" CONFIG_SPEAKUP_DEFAULT "none"
26
fi
(-)linux-2.6.20/drivers/char/speakup/cvsversion.h (+1 lines)
Line 0 Link Here
1
#define CVSVERSION " CVS: Sat Oct 7 10:52:29 EDT 2006 "
(-)linux-2.6.20/drivers/char/speakup/dtload.c (+553 lines)
Line 0 Link Here
1
/*
2
 * This is the DECtalk PC firmware loader for the Linux kernel, version 1.0
3
 *
4
 * Original 386BSD source:
5
 *      Copyright ( c ) 1996 Brian Buhrow <buhrow@lothlorien.nfbcal.org>
6
 *
7
 * Adapted for Linux:
8
 *      Copyright ( c ) 1997 Nicolas Pitre <nico@cam.org>
9
 *
10
 * Adapted for speakup:
11
 *      Copyright ( c ) 2003 David Borowski <david575@golden.net>
12
 *
13
 * All rights reserved.
14
 *
15
 * This program is free software; you can redistribute it and/or modify
16
 * it under the terms of the GNU General Public License as published by
17
 * the Free Software Foundation; either version 2 of the License, or
18
 * ( at your option ) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU General Public License
26
 * along with this program; if not, write to the Free Software
27
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28
 *
29
 */
30
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <unistd.h>
34
#include <string.h>
35
#include <sys/types.h>
36
#include <sys/stat.h>
37
#include <fcntl.h>
38
#include <malloc.h>
39
#include <sys/errno.h>
40
#include <asm/io.h>
41
#include "dtload.h"
42
#include "dtpc_reg.h"
43
44
static int verbose = 0, intest = 0,infd = -1;
45
static int image_len, total_paras;
46
static int dt_stat, dma_state = 0, has_kernel = 0;
47
static struct dos_reloc fixups[512];
48
static char *read_buff = NULL;
49
static struct dos_exe_header header;
50
static u_short iobase = 0x350;
51
52
static int dt_getstatus( )
53
{
54
	dt_stat =  inb_p( iobase )|(inb_p( iobase+1 )<<8);
55
	return dt_stat;
56
}
57
58
static void dt_sendcmd( u_int cmd )
59
{
60
  outb_p( cmd & 0xFF, iobase );
61
  outb_p( (cmd>>8) & 0xFF, iobase+1 );
62
}
63
64
static int dt_waitbit( int bit )
65
{
66
  int timeout = 100;
67
  while ( --timeout > 0 ) {
68
    if( (dt_getstatus( ) & bit ) == bit ) return 1;
69
    usleep( 1000 );
70
  }
71
  return 0;
72
}
73
74
static int dt_sendcmd_wait( u_int cmd, int bit )
75
{
76
  int timeout = 1000;
77
  outb_p( cmd & 0xFF, iobase );
78
  outb_p( (cmd>>8) & 0xFF, iobase+1 );
79
  while ( --timeout > 0 ) {
80
    if( (dt_getstatus( ) & bit ) == bit ) return 1;
81
    usleep( 1000 );
82
  }
83
  return 0;
84
}
85
86
static int dt_waitmode( int pattern )
87
{
88
  int timeout = 1000;
89
  while ( --timeout > 0 ) {
90
    if( dt_getstatus( ) == pattern ) return 1;
91
    usleep( 1000 );
92
  }
93
  fprintf( stderr, "waitmode p=%x s = %x\n", pattern, dt_stat );
94
  return 0;
95
}
96
97
static int dt_wait_dma( )
98
{
99
  int timeout = 1000, state = dma_state;
100
  if( !has_kernel ){
101
    usleep( 500 );
102
    return( dt_waitbit( STAT_dma_ready ) );
103
  }
104
  if( ! dt_waitbit( STAT_dma_ready ) ) return 0;
105
  while ( --timeout > 0 ) {
106
    if( (dt_getstatus()&STAT_dma_state) == state ) return 1;
107
    usleep( 1000 );
108
  }
109
  dma_state = dt_getstatus( ) & STAT_dma_state;
110
  return 1;
111
}
112
113
dt_ctrl( u_int cmd )
114
{
115
  while ( ! dt_waitbit( STAT_cmd_ready ) ) usleep( 100 );
116
  outb_p( 0, iobase+2 );
117
  outb_p( 0, iobase+3 );
118
  dt_getstatus( );
119
  dt_sendcmd( CMD_control|cmd );
120
  outb_p( 0, iobase+6 );
121
  usleep( 100 );
122
  dt_sendcmd( CMD_null );
123
  while ( ! dt_waitbit( STAT_cmd_ready ) ) usleep( 100 );
124
}
125
126
int dt_flush( void )
127
{
128
  dt_ctrl( CTRL_flush );
129
  dt_waitbit( STAT_dma_ready );
130
  outb_p( DMA_sync, iobase+4 );
131
  outb_p( 0, iobase+4 );
132
  dma_state ^= STAT_dma_state;
133
  while( dt_getstatus( ) & STAT_flushing ) usleep( 100 );
134
  return 0;
135
}
136
137
static int dt_sendbuff( char *src, int len )
138
{
139
  while( len-- ){
140
    if( ! dt_wait_dma( ) ) return -1;
141
    if( ! (dt_getstatus( ) & STAT_rr_char) ) break;
142
    outb_p( DMA_single_in, iobase+4 );
143
    outb_p( *src++, iobase+4 );
144
    dma_state ^= STAT_dma_state;
145
  }
146
  return 0;
147
}
148
149
unsigned long dt_allocmem( unsigned long paras )
150
{
151
	unsigned long addr;
152
	if( ! dt_wait_dma( ) ) return 0;
153
	outb_p( DMA_control, iobase+4 );
154
	outb_p( DT_MEM_ALLOC, iobase+4 );
155
	dma_state ^= STAT_dma_state;
156
	if( ! dt_wait_dma( ) ) return 0;
157
	outb_p( paras & 0xFF, iobase+4 );
158
	outb_p( (paras>>8) & 0xFF, iobase+4 );
159
	dma_state ^= STAT_dma_state;
160
	if( ! dt_wait_dma( ) ) return 0;
161
	addr = inb_p( iobase+4 );
162
	addr |= (inb_p( iobase+4 )<<8);
163
	addr += (inb_p( iobase+4 )<<4);
164
	addr += (inb_p( iobase+4 )<<12);
165
	dma_state ^= STAT_dma_state;
166
  return addr;
167
}
168
169
static int testkernel( void )
170
{
171
  dt_sendcmd( CMD_sync );
172
  if( ! dt_waitbit( STAT_cmd_ready ) ) return -10;
173
  has_kernel = ( dt_stat&0x8000 ) ? 1 : 0;
174
  if ( verbose ) printf( "testkernel got %x\n", dt_stat );
175
  if ( has_kernel ) return 0;
176
	usleep( 100 );
177
  return 1;
178
}
179
180
static int dt_loadmem( int addr, int len, char *src )
181
{
182
  char c;
183
  int l;
184
  if ( verbose ) printf( "dt_loadmem: addr = %08X size = %d\n", addr, len );
185
  do {
186
    l = len;
187
    if ( l >= 0xc000 ) l = 0xc000;
188
    len -= l;
189
    if( ! dt_wait_dma( ) ) return -1;
190
    outb_p( DMA_control, iobase+4 );
191
    outb_p( DT_LOAD_MEM, iobase+4 );
192
    dma_state ^= STAT_dma_state;
193
    if( ! dt_wait_dma( ) ) return -2;
194
    outb_p( addr & 0xFF, iobase+4 );
195
    outb_p( (addr>>8) & 0xFF, iobase+4 );
196
    outb_p( (addr>>16) & 0xFF, iobase+4 );
197
    outb_p( (addr>>24) & 0xFF, iobase+4 );
198
    outb_p( l & 0xFF, iobase+4 );
199
    outb_p( (l>>8) & 0xFF, iobase+4 );
200
    dma_state ^= STAT_dma_state;
201
    if( ! dt_wait_dma( ) ) return -3;
202
    addr += l;
203
    while( l-- ){ 
204
      c = *src++;
205
      outb_p( c, iobase+4 );
206
    }
207
    dma_state ^= STAT_dma_state;
208
  } while ( len > 0 );
209
  return 0;
210
}
211
212
unsigned int loadfile ( char *filename )
213
{
214
  int i, header_size;
215
  unsigned int total_paras;
216
  long fix;
217
  infd = open ( filename, O_RDONLY );
218
  if ( infd == -1 ) {
219
      perror ( "Opening file: " );
220
      return 0;
221
    }
222
  read ( infd, &header, sizeof ( struct dos_exe_header ) );
223
  if ( header.id != 0x5a4d ) {
224
      fprintf ( stderr, "Invalid header file format\n" );
225
      fprintf ( stderr, "Want 0x5a4d, got 0x%x\n", header.id );
226
      return 0;
227
    }
228
  if ( header.relen > MAX_FIXUPS ) {
229
      fprintf ( stderr, "Too many fixups\n" );
230
      return 0;
231
    }
232
  lseek ( infd, ( long ) header.reloc, SEEK_SET );
233
  read ( infd, fixups, sizeof ( struct dos_reloc ) * header.relen );
234
  header_size = header.hsize * 16;
235
  lseek ( infd, ( long )header_size, SEEK_SET );
236
  image_len = ( ( header.pages-1 )*512 ) + ( header.rem- header_size );
237
  total_paras =  ( image_len >> 4 ) + header.hmin + 16;
238
  read ( infd, read_buff, image_len );
239
  close( infd );
240
  return total_paras;
241
}
242
243
static int loadkernel( char *filename )
244
{
245
  int segfix = 0x40, fix, i;
246
  int ipval, csval;
247
  if ( has_kernel ) return 0;
248
  if ( !loadfile( filename ) ) return -1;
249
  header.csval += segfix;
250
  header.ssval += segfix;
251
  if ( verbose ) {
252
      printf ( "Loading kernel of %ld bytes ( %d relocs )\n",
253
	      image_len, header.relen );
254
      printf ( "    cs:ip == %04x:%04x   ss:sp == %04x:%04x\n",
255
	      header.csval, header.ipval, header.ssval, header.spval );
256
    }
257
  for ( i = 0; i < header.relen; i++ ) {
258
      fix = ( fixups[i].segment << 4 ) + fixups[i].offset;
259
      ( *( unsigned int * ) &read_buff[fix] ) += segfix;
260
    }
261
  csval = header.csval;
262
  ipval = header.ipval;
263
  dt_sendcmd_wait( MODULE_reset, MODULE_init );
264
  dt_sendcmd( CMD_reset );
265
  if( dt_getstatus( ) == MODULE_self_test ){
266
    if( ! dt_waitmode( MODULE_init ) ) return -1;
267
  }
268
  if ( !dt_sendcmd_wait( CMD_reset, MODE_status ) ) return -2;
269
  if ( !dt_sendcmd_wait( CMD_sync, MODE_error ) ) return -3;
270
  if ( !dt_sendcmd_wait( CMD_reset, MODE_status ) ) return -4;
271
  if ( verbose ) printf( "card is ready\n" );
272
  dt_sendcmd( CMD_dma );
273
  if( ! dt_waitbit( STAT_dma_ready ) ) return -5;
274
  if( ( i = dt_loadmem( 0x00000400, image_len, read_buff ) ) ) {
275
   fprintf( stderr, "kernel load failed, status %d\n", i );
276
    return -6;
277
  }
278
  usleep(100);
279
  /* the kernel is loaded, start it */
280
  if ( !dt_sendcmd_wait( CMD_reset, MODE_status ) ) return -7;
281
  dt_sendcmd( CMD_dma+1 );   /**xxx**/
282
	usleep(100);
283
  if( ! dt_waitbit( STAT_dma_ready ) ) return-8;
284
  outb_p( DMA_control, iobase+4 );
285
  outb_p( DT_START_TASK, iobase+4 );
286
	usleep(100);
287
  outb_p( ipval & 0xFF, iobase+4 );
288
  outb_p( (ipval>>8) & 0xFF, iobase+4 );
289
  outb_p( csval & 0xFF, iobase+4 );
290
  outb_p( (csval>>8) & 0xFF, iobase+4 );
291
	if( ! dt_waitmode( 0xc001 ) ) return -9;
292
  if ( verbose ) {
293
    printf( "done loading kernel\n" );
294
  }
295
  return testkernel( );
296
}
297
298
int loaddict ( char *filename, char *name, int type )
299
{
300
  int i, read_index, read_size, act_size;
301
  unsigned short *index_fix, seg_fix;
302
  unsigned long entries, index, dic_bytes, dic_addr;
303
  unsigned int total_paras;
304
  unsigned long param, l;
305
  infd = open ( filename, O_RDONLY );
306
  if ( infd == -1 ) {
307
      perror ( filename );
308
      return -1;
309
    }
310
/* read in the entry count and the actual entry size excluding the
311
 * index table ( which is entries * 4 ) ...  */
312
  read ( infd, &entries, 4 );
313
  read ( infd, &dic_bytes, 4 );
314
  if ( verbose )
315
    printf ( "Loading %s dictionary of %lu entries, %lu bytes.\n",
316
	    name, entries, dic_bytes );
317
  total_paras = ( ( ( entries * 4 ) + dic_bytes ) >> 4 ) + 2;
318
  if ( verbose )
319
    printf ( "Allocating %d paragraphs of free ram ...\n", total_paras );
320
  l = dt_allocmem( total_paras );
321
  if ( l == 0 ) {
322
      perror ( "Error requesting memory from speech device" );
323
      return -1;
324
    }
325
  seg_fix = ( l >> 4 ) & 0xffff;
326
  dic_addr = l;
327
  index = entries;
328
  index_fix = ( unsigned short * ) &read_buff[0];
329
  if ( verbose )
330
    printf ( "Index table starts at %lx\n", l );
331
  read_index = index*4;
332
  act_size = read ( infd, read_buff, read_index );
333
  if ( act_size != read_index ) {
334
    fprintf ( stderr, "\nError reading indexes\n" );
335
    fprintf ( stderr, "    exp : %d  act : %d\n", read_index * 4, act_size );
336
    return -1;
337
  }
338
  for ( i = 1; i < index * 2; i += 2 )
339
    index_fix[i] += seg_fix;
340
  if( ( i = dt_loadmem( l, read_index, read_buff ) ) ) {
341
    fprintf ( stderr, "\nError loading indexes at 0x%lX: i %d\n",
342
      l, i );
343
    return -1;
344
  }
345
  l += read_index;
346
/* now, load up the dictionary bytes ...  */
347
  if ( verbose )
348
    printf ( "Dictionary text starts at %lx\n", l );
349
  read_size = dic_bytes;
350
  if ( ( act_size = read ( infd, read_buff, read_size ) ) != read_size ) {
351
    fprintf ( stderr, "\nError reading dictionary text!\n" );
352
    fprintf ( stderr, "asked : %d  actual : %d\n", act_size, read_size );
353
    return -1;
354
  }
355
  if( ( i = dt_loadmem( l, read_size, read_buff ) ) ) {
356
    fprintf ( stderr, "\nError loading dictionary at 0x%lX: status %d\n",
357
      l, i );
358
    return -1;
359
  }
360
  if( ! dt_wait_dma( ) ) return -1;
361
  outb_p( DMA_control, iobase+4 );
362
  outb_p( DT_SET_DIC, iobase+4 );
363
	dma_state ^= STAT_dma_state;
364
  if( ! dt_wait_dma( ) ) return -1;
365
  l  = dic_addr;
366
	l = ((l << 12) & 0xFFFF0000) + (l & 0x0000000F);
367
  outb_p( l & 0xFF, iobase+4 );
368
  outb_p( (l>>8) & 0xFF, iobase+4 );
369
  outb_p( (l>>16) & 0xFF, iobase+4 );
370
  outb_p( (l>>24) & 0xFF, iobase+4 );
371
  l = entries;
372
  outb_p( l & 0xFF, iobase+4 );
373
  outb_p( (l>>8) & 0xFF, iobase+4 );
374
  outb_p( (l>>16) & 0xFF, iobase+4 );
375
  outb_p( (l>>24) & 0xFF, iobase+4 );
376
	l = type;
377
  outb_p( l & 0xFF, iobase+4 );
378
  outb_p( (l>>8) & 0xFF, iobase+4 );
379
	dma_state ^= STAT_dma_state;
380
  close ( infd );
381
  if ( verbose ) printf( "dictionary load complete\n" );
382
  return 0;
383
}
384
385
int loadexe ( char *filename )
386
{
387
  unsigned int load_addr = 0, seg_fix;
388
  int i, read_size;
389
  int ipval, csval;
390
  long fix;
391
  unsigned long total_paras;
392
  total_paras = loadfile ( filename );
393
  if ( total_paras == 0 ) return -1;
394
  load_addr = dt_allocmem( total_paras );
395
  if ( load_addr == 0 ) {
396
    fprintf ( stderr, "Error allocating memory on card: " );
397
    return -1;
398
  }
399
  seg_fix = ( load_addr >> 4 ) & 0xffff;
400
  if ( verbose ) {
401
      printf ( "Loading %s %ld bytes ( %d relocs )\n",
402
	      filename, image_len, header.relen );
403
      printf ( "Allocating %ld bytes of free ram at %05x\n",
404
	      ( long ) header.hmin * 16, load_addr );
405
      printf ( "Total memory taken is %ld bytes\n", ( long ) total_paras * 16 );
406
      printf ( "    cs:ip == %04x:%04x   ss:sp == %04x:%04x\n",
407
	      header.csval + seg_fix, header.ipval, header.ssval + seg_fix, header.spval );
408
    }
409
    for ( i = 0; i < header.relen; i++ ) {
410
	fix = ( ( long ) fixups[i].segment << 4 ) + ( long ) fixups[i].offset;
411
	( *( unsigned int * ) &read_buff[fix] ) += seg_fix;
412
    	 }
413
  if( ( i = dt_loadmem( load_addr, image_len, read_buff ) ) ) {
414
    fprintf ( stderr, "Error loading speech device at 0x%lX: status %d\n",
415
      load_addr, i );
416
    return -1;
417
  }
418
  csval = header.csval + seg_fix;
419
  ipval = header.ipval;
420
  if( ! dt_wait_dma( ) ) return -1;
421
  outb_p( DMA_control, iobase+4 );
422
  outb_p( DT_START_TASK, iobase+4 );
423
	dma_state ^= STAT_dma_state;
424
  if( ! dt_wait_dma( ) ) return -1;
425
  outb_p( ipval & 0xFF, iobase+4 );
426
  outb_p( (ipval>>8) & 0xFF, iobase+4 );
427
  outb_p( csval & 0xFF, iobase+4 );
428
  outb_p( (csval>>8) & 0xFF, iobase+4 );
429
	dma_state ^= STAT_dma_state;
430
  return 0;
431
}
432
433
void release_io( void )
434
{
435
  ioperm( (long)iobase, 8, 0 );
436
  ioperm( (long)0x0080, 1, 0 );
437
  if ( read_buff ) free( read_buff );
438
}
439
440
parseparm( char *parm, char *value )
441
{
442
  char *cp = parm+strlen( parm );
443
  while ( --cp > parm ) if ( *cp > ' ' ) break;
444
  cp[1] = '\0';
445
  if ( !strcmp( parm, "io" ) ) {
446
    long io = strtol( value, 0, 0 );
447
    if ( io >= 0x100 && io <= 0x350 ) {
448
      iobase = (u_short)io;
449
      return;
450
    }
451
    fprintf( stderr, "invalid io value %s\n", value );
452
    exit( 1 );
453
  } else if ( !strcmp( parm,"verbose" ) ) {
454
    verbose = atoi( value );
455
  }
456
}
457
458
do_test( void )
459
{
460
  char buffer[512];
461
  int len;
462
  dma_state = dt_getstatus( ) & STAT_dma_state;
463
  while ( fgets( buffer, 510, stdin ) ) {
464
    len = strlen( buffer );
465
    if ( len == 1 ) dt_flush( );
466
    else {
467
      if ( buffer[len-1] == '\n' ) buffer[len-1] = '\013';
468
      dt_sendbuff( buffer, len );
469
    }
470
  }
471
  *buffer = '\013';
472
  dt_sendbuff( buffer, 1 );
473
}
474
475
int main ( int argc, char **argv )
476
{
477
  char name[80], *cp;
478
  char *dirname = 0, *confname = "dec_pc.conf";
479
  char *init_msg = "[:ra 360] dec pc initialized\011";
480
  FILE *confile;
481
  struct stat statbuf;
482
  int maxsize = 0, status = 0;
483
  while ( --argc > 0 ) {
484
    argv++;
485
    if ( !strcmp( *argv, "-v" ) ) verbose = 1;
486
    else if ( !strcmp( *argv, "-t" ) ) intest = 1;
487
    else dirname = *argv;
488
  }
489
  if ( !dirname ) dirname = "/usr/local/lib/dec_pc";
490
  if ( chdir( dirname ) != 0 ) {
491
    fprintf( stderr, "cannot chdir to %s\n", dirname );
492
    exit( 1 );
493
  }
494
  if ( !( confile = fopen( confname, "r" ) ) ) {
495
    fprintf( stderr, "could not open %s", confname );
496
    exit( 1 );
497
  }
498
  while ( fgets( name, 80, confile ) ) {
499
    cp = strchr( name, '\n' );
500
    if ( cp ) *cp = '\0';
501
    if ( ( cp = strchr( name, '=' ) ) ) {
502
      *cp++ = '\0';
503
      parseparm( name, cp );
504
      continue;
505
    }
506
    if ( stat( name, &statbuf ) != 0 ) {
507
      fprintf( stderr, "cannot stat %s\n", name );
508
      exit( 1 );
509
    }
510
    if ( statbuf.st_size > maxsize ) maxsize = statbuf.st_size;
511
  }
512
  rewind( confile );
513
  if ( ioperm( (long)0x0080, 1, 1 ) || ioperm( (long)iobase, 8, 1 ) ) {
514
    fprintf( stderr, "could not get ioperm\n" );
515
    exit( 1 );
516
  }
517
  atexit( release_io );
518
  if ( testkernel( ) == 0 ) {
519
    if ( intest ) do_test( );
520
    else fprintf( stderr, "kernel already loaded\n" );
521
    exit( 0 );
522
  }
523
  read_buff = malloc(  maxsize );
524
  if ( !read_buff ) {
525
    fprintf( stderr, "cannot malloc %d bytes\n", maxsize );
526
    exit( 1 );
527
  }
528
  while ( fgets( name, 80, confile ) && !status ) {
529
    cp = strchr( name, '\n' );
530
    if ( cp ) *cp = '\0';
531
    if ( strchr( name, '=' ) ) continue; /* a parameter */
532
    if ( !( cp = strchr( name, '.' ) ) ) continue;
533
    cp++;
534
    if ( !strcmp ( cp, "dic" ) ) {
535
      status = loaddict ( name, "primary", PRIMARY_DIC );
536
    } else if ( !strcmp ( cp, "dtu" ) ) {
537
      status = loaddict ( name, "user", USER_DIC );
538
    } else if ( !strcmp ( cp, "dta" ) ) {
539
      status = loaddict ( name, "abbreviation file", ABBREV_DIC );
540
    } else if ( !strcmp ( cp, "exe" ) ) {
541
      status = loadexe ( name );
542
    } else if ( !strcmp ( cp, "sys" ) ) {
543
      status = loadkernel ( name );
544
    }
545
  }
546
  if ( status ) fprintf( stderr, "status %d\n", status );
547
  fclose( confile );
548
  if ( status ) exit( status );
549
  dt_sendbuff( init_msg, strlen( init_msg ) );
550
  sleep( 1 );
551
  if ( intest ) do_test( );
552
  exit( 0 );
553
}
(-)linux-2.6.20/drivers/char/speakup/dtload.h (+57 lines)
Line 0 Link Here
1
/*
2
 * This is the DECtalk PC firmware loader for the Linux kernel, version 1.0
3
 *
4
 * Original 386BSD source:
5
 *      Copyright (c) 1996 Brian Buhrow <buhrow@lothlorien.nfbcal.org>
6
 *
7
 * Adapted for Linux:
8
 *      Copyright (c) 1997 Nicolas Pitre <nico@cam.org>
9
 *
10
 * Adapted for speakup:
11
 *      Copyright (c) 2003 David Borowski <david575@golden.net>
12
 *
13
 * All rights reserved.
14
 *
15
 * This program is free software; you can redistribute it and/or modify
16
 * it under the terms of the GNU General Public License as published by
17
 * the Free Software Foundation; either version 2 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU General Public License
26
 * along with this program; if not, write to the Free Software
27
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28
 *
29
 */
30
31
#define	MAX_FIXUPS	512	  	/* maximum fixups per exe */
32
/*
33
 *  msdos .exe files will look like ...
34
 */
35
36
struct dos_exe_header {
37
	unsigned short id;		/* Linker's signature, must be 0x5a4d */
38
	unsigned short rem;		/* length of image mod 512 */
39
	unsigned short pages;		/* length of image in pages of 512 bytes */
40
	unsigned short relen;		/* number of relocation items */
41
	unsigned short hsize;		/* header size in paragraphs of 16 bytes */
42
	unsigned short hmin;		/* min # of paragraphs above prog end */
43
	unsigned short hmax;
44
	unsigned short ssval;
45
	unsigned short spval;		/* to be loaded in sp */
46
	unsigned short	checksum;
47
	unsigned short	ipval;		/* to be loaded in ip */
48
	unsigned short	csval;  	/* segment offset to code */
49
	unsigned short	reloc;		/* location of relocation items	*/
50
	unsigned short	ovrlay;		/* overlay number */
51
};
52
53
/*  a dos relocation element looks like */
54
55
struct dos_reloc {
56
	short int offset, segment;
57
};
(-)linux-2.6.20/drivers/char/speakup/dtpc_reg.h (+132 lines)
Line 0 Link Here
1
/*
2
 * This is the DECtalk PC register constants (from DEC's DOS driver)
3
 *
4
 * Original code:
5
 *      Copyright (c) by Digital Equipment Corp.
6
 *
7
 * 386BSD DECtalk PC driver:
8
 *      Copyright (c) 1996 Brian Buhrow <buhrow@lothlorien.nfbcal.org>
9
 *
10
 * Linux DECtalk PC driver:
11
 *      Copyright (c) 1997 Nicolas Pitre <nico@cam.org>
12
 *
13
 * speakup DECtalk PC driver:
14
 *      Copyright (c) 2003 David Borowski <david575@golden.net>
15
 *
16
 * All rights reserved.
17
 *
18
 * This program is free software; you can redistribute it and/or modify
19
 * it under the terms of the GNU General Public License as published by
20
 * the Free Software Foundation; either version 2 of the License, or
21
 * (at your option) any later version.
22
 *
23
 * This program is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
 * GNU General Public License for more details.
27
 *
28
 * You should have received a copy of the GNU General Public License
29
 * along with this program; if not, write to the Free Software
30
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31
 *
32
 */
33
34
/*
35
 *  port interface defs ... used by dtpc.c
36
 */
37
38
#define	MODULE_init		0x0dec		/* module in boot code */			
39
#define	MODULE_self_test	0x8800		/* module in self-test */
40
#define	MODULE_reset		0xffff		/* reinit the whole module */
41
42
#define	MODE_mask		0xf000		/* mode bits in high nibble */
43
#define	MODE_null		0x0000
44
#define	MODE_test		0x2000		/* in testing mode */
45
#define	MODE_status		0x8000
46
#define	STAT_int		0x0001		/* running in interrupt mode */
47
#define	STAT_tr_char	0x0002		/* character data to transmit */
48
#define	STAT_rr_char	0x0004		/* ready to receive char data */
49
#define	STAT_cmd_ready	0x0008		/* ready to accept commands */
50
#define	STAT_dma_ready	0x0010		/* dma command ready */
51
#define	STAT_digitized	0x0020		/* spc in digitized mode */
52
#define	STAT_new_index	0x0040		/* new last index ready */
53
#define	STAT_new_status	0x0080		/* new status posted */
54
#define	STAT_dma_state	0x0100		/* dma state toggle */
55
#define	STAT_index_valid	0x0200		/* indexs are valid */
56
#define	STAT_flushing	0x0400		/* flush in progress */
57
#define	STAT_self_test	0x0800		/* module in self test */
58
#define	MODE_ready		0xc000		/* module ready for next phase */
59
#define	READY_boot		0x0000				
60
#define	READY_kernel	0x0001		
61
#define	MODE_error		0xf000
62
63
#define	CMD_mask			0xf000		/* mask for command nibble */
64
#define	CMD_null			0x0000		/* post status */
65
#define	CMD_control		0x1000		/* hard control command */
66
#define	CTRL_mask		0x0F00	/*   mask off control nibble */
67
#define	CTRL_data		0x00FF	/*   madk to get data byte */
68
#define	CTRL_null		0x0000	/*   null control */
69
#define	CTRL_vol_up		0x0100	/*   increase volume */
70
#define	CTRL_vol_down		0x0200	/*   decrease volume */
71
#define	CTRL_vol_set		0x0300	/*   set volume */
72
#define	CTRL_pause		0x0400	/*   pause spc */
73
#define	CTRL_resume		0x0500	/*   resume spc clock */
74
#define	CTRL_resume_spc		0x0001	/*   resume spc soft pause */
75
#define	CTRL_flush		0x0600	/*   flush all buffers */
76
#define	CTRL_int_enable	0x0700	/*   enable status change ints */
77
#define	CTRL_buff_free		0x0800	/*   buffer remain count */
78
#define	CTRL_buff_used		0x0900	/*   buffer in use */
79
#define	CTRL_speech		0x0a00	/*   immediate speech change */
80
#define		CTRL_SP_voice		0x0001	/*      voice change */
81
#define		CTRL_SP_rate		0x0002	/*      rate change */
82
#define		CTRL_SP_comma		0x0003	/*      comma pause change */
83
#define		CTRL_SP_period		0x0004	/*      period pause change */
84
#define		CTRL_SP_rate_delta	0x0005	/*	  delta rate change */
85
#define		CTRL_SP_get_param	0x0006	/*      return the desired parameter */
86
#define	CTRL_last_index	0x0b00	/*   get last index spoken */
87
#define	CTRL_io_priority	0x0c00	/*   change i/o priority */
88
#define	CTRL_free_mem		0x0d00	/*   get free paragraphs on module */
89
#define	CTRL_get_lang		0x0e00	/*   return bit mask of loaded languages */
90
#define	CMD_test			0x2000		/* self-test request */
91
#define	TEST_mask		0x0F00	/* isolate test field */
92
#define	TEST_null		0x0000	/* no test requested */
93
#define	TEST_isa_int		0x0100	/* assert isa irq */
94
#define	TEST_echo		0x0200	/* make data in == data out */
95
#define	TEST_seg			0x0300	/* set peek/poke segment */
96
#define	TEST_off			0x0400	/* set peek/poke offset */
97
#define	TEST_peek		0x0500	/* data out == *peek */
98
#define	TEST_poke		0x0600	/* *peek == data in */
99
#define	TEST_sub_code		0x00FF	/* user defined test sub codes */
100
#define	CMD_id			0x3000		/* return software id */
101
#define	ID_null			0x0000	/* null id */
102
#define	ID_kernel		0x0100	/* kernel code executing */
103
#define	ID_boot			0x0200	/* boot code executing */
104
#define	CMD_dma			0x4000		/* force a dma start */
105
#define	CMD_reset		0x5000		/* reset module status */
106
#define	CMD_sync			0x6000		/* kernel sync command */
107
#define	CMD_char_in		0x7000		/* single character send */
108
#define	CMD_char_out		0x8000		/* single character get */
109
#define	CHAR_count_1		0x0100	/*    one char in cmd_low */
110
#define	CHAR_count_2		0x0200	/*	the second in data_low */
111
#define	CHAR_count_3		0x0300	/*	the third in data_high */
112
#define	CMD_spc_mode		0x9000		/* change spc mode */
113
#define	CMD_spc_to_text	0x0100	/*   set to text mode */
114
#define	CMD_spc_to_digit	0x0200	/*   set to digital mode */
115
#define	CMD_spc_rate		0x0400	/*   change spc data rate */
116
#define	CMD_error		0xf000		/* severe error */
117
118
enum {	PRIMARY_DIC	= 0, USER_DIC, COMMAND_DIC, ABBREV_DIC };
119
120
#define	DMA_single_in		0x01
121
#define	DMA_single_out		0x02
122
#define	DMA_buff_in		0x03
123
#define	DMA_buff_out		0x04
124
#define	DMA_control		0x05
125
#define	DT_MEM_ALLOC		0x03
126
#define	DT_SET_DIC		0x04
127
#define	DT_START_TASK		0x05
128
#define	DT_LOAD_MEM		0x06
129
#define	DT_READ_MEM		0x07
130
#define	DT_DIGITAL_IN		0x08
131
#define	DMA_sync		0x06
132
#define	DMA_sync_char		0x07
(-)linux-2.6.20/drivers/char/speakup/genmap.c (+204 lines)
Line 0 Link Here
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <libgen.h>
4
#include <string.h>
5
#include <linux/version.h>
6
#include <ctype.h>
7
8
int get_define(void);
9
10
#define MAXKEYS 512
11
#define MAXKEYVAL 160
12
#define HASHSIZE 101
13
#define is_shift -3
14
#define is_spk -2
15
#define is_input -1
16
typedef struct st_key_init t_key_init;
17
struct st_key_init {
18
	char *name;
19
	int value, shift;
20
};
21
typedef struct st_key t_key;
22
struct st_key {
23
	char *name;
24
	t_key *next;
25
	int value, shift;
26
};
27
unsigned char key_data[MAXKEYVAL][16], *kp;
28
29
#include "mapdata.h"
30
t_key key_table[MAXKEYS];
31
t_key *extra_keys = key_table+HASHSIZE;
32
char buffer[256], filename[256];
33
FILE *infile;
34
char delims[] = "\t\n ";
35
char *def_name, *def_val, *cp;
36
int map_ver = 119; /* an arbitrary number so speakup can check */
37
int lc, shift_table[17];
38
int max_states = 1, flags = 0;
39
/* flags reserved for later, maybe for individual console maps */
40
41
void open_input( char *name )
42
{
43
	strcpy( filename, name );
44
	if ( ( infile = fopen( filename, "r" ) ) == 0 ) {
45
		fprintf( stderr, "can't open %s, version %d\n", filename, LINUX_VERSION_CODE );
46
		exit( 1 );
47
	}
48
	lc = 0;
49
}
50
51
int
52
oops( char *msg, char *info )
53
{
54
	if ( info == NULL ) info = " ";
55
	fprintf( stderr, "error: file %s line %d\n", filename, lc );
56
	fprintf( stderr, "%s %s\n", msg, info );
57
	exit( 1 );
58
}
59
60
t_key *hash_name( char *name )
61
{
62
	u_char *pn = (u_char *)name;
63
	int hash = 0;
64
	while ( *pn ) {
65
		hash = ( hash * 17 ) & 0xfffffff;
66
	if ( isupper( *pn ) ) *pn = tolower( *pn );
67
		hash += ( int )*pn;
68
		pn++;
69
	}
70
	hash %= HASHSIZE;
71
	return &key_table[hash];
72
}
73
74
t_key *find_key( char *name )
75
{
76
	t_key *this = hash_name( name );
77
	while ( this ) {
78
		if ( !strcmp( name, this->name ) ) return this;
79
		this = this->next;
80
	}
81
	return this;
82
}
83
84
t_key *add_key( char *name, int value, int shift )
85
{
86
	t_key *this = hash_name( name );
87
	if ( extra_keys-key_table >= MAXKEYS )
88
		oops( "out of key table space, enlarge MAXKEYS", NULL );
89
	if ( this->name != NULL ) {
90
		while ( this->next ) {
91
			if ( !strcmp( name, this->name ) )
92
				oops( "attempt to add duplicate key", name );
93
			this = this->next;
94
		}
95
		this->next = extra_keys++;
96
		this = this->next;
97
	}
98
	this->name = strdup( name );
99
	this->value = value;
100
	this->shift = shift;
101
	return this;
102
}
103
104
int get_shift_value( int state )
105
{
106
	int i;
107
	for ( i = 0; shift_table[i] != state; i++ ) {
108
		if ( shift_table[i] == -1 ) {
109
			if ( i >= 16 )
110
				oops( "too many shift states", NULL );
111
			shift_table[i] = state;
112
			max_states = i+1;
113
		break;
114
	}
115
	}
116
	return i;
117
}
118
119
int		
120
main( int argc, char *argv[] )
121
{
122
	int value, shift_state, i, spk_val = 0, lock_val = 0;
123
	int max_key_used = 0, num_keys_used = 0;
124
	t_key *this;
125
	t_key_init *p_init;
126
char *argpath, *argname, *argcopy;
127
128
	bzero( key_table, sizeof( key_table ) );
129
	bzero( key_data, sizeof( key_data ) );
130
	shift_table[0] = 0;
131
	for ( i = 1; i <= 16; i++ ) shift_table[i] = -1;
132
	if ( argc < 2 ) {
133
		fputs( "usage: genmap filename\n", stderr );
134
		exit( 1 );
135
	}
136
  for ( p_init = init_key_data; p_init->name[0] != '.'; p_init++ )
137
		add_key( p_init->name, p_init->value, p_init->shift );
138
	open_input( argv[1] );
139
	while ( fgets( buffer, 250, infile ) ) {
140
		lc++;
141
		value = shift_state = 0;
142
		cp = strtok( buffer, delims );
143
		if ( *cp == '#' ) continue;
144
		while ( cp ) {
145
			if ( *cp == '=' ) break;
146
			this = find_key( cp );
147
			if ( this == NULL )
148
				oops( "unknown key/modifier", cp );
149
			if ( this->shift == is_shift ) {
150
				if ( value )
151
					oops( "modifiers must come first", cp );
152
				shift_state += this->value;
153
			} else if ( this->shift == is_input )
154
				value = this->value;
155
			else oops( "bad modifier or key", cp );
156
			cp = strtok( 0, delims );
157
		}
158
		if ( !cp ) oops( "no = found", NULL );
159
		cp = strtok( 0, delims );
160
		if ( !cp ) oops( "no speakup function after =", NULL );
161
		this = find_key( cp );
162
		if ( this == NULL || this->shift != is_spk )
163
			oops( "invalid speakup function", cp );
164
		i = get_shift_value( shift_state );
165
		if ( key_data[value][i] ) {
166
			while ( --cp > buffer )
167
				if ( !*cp ) *cp = ' ';
168
			oops( "two functions on same key combination", cp );
169
		}
170
		key_data[value][i] = (char)this->value;
171
		if ( value > max_key_used ) max_key_used = value;
172
	}
173
	fclose( infile );
174
	this = find_key( "spk_key" );
175
	if ( this ) spk_val = this->value;
176
	this = find_key( "spk_lock" );
177
	if ( this ) lock_val = this->value;
178
	for ( lc = 1; lc <= max_key_used; lc++ ) {
179
		kp = key_data[lc];
180
		if ( !memcmp( key_data[0], kp, 16 ) ) continue;
181
		num_keys_used++;
182
		for ( i = 0; i < max_states; i++ ) {
183
			if ( kp[i] != spk_val&& kp[i] != lock_val ) continue;
184
			shift_state = shift_table[i];
185
			if ( ( shift_state&16 ) ) continue;
186
			shift_state = get_shift_value( shift_state+16 );
187
			kp[shift_state] = kp[i];
188
/* fill in so we can process the key up, as spk bit will be set */
189
		}
190
	}
191
	printf( "\t%d, %d, %d,\n\t", map_ver, num_keys_used, max_states );
192
	for ( i = 0; i < max_states; i++ )
193
		printf( "%d, ", shift_table[i] );
194
	printf( "%d,", flags );
195
	for ( lc = 1; lc <= max_key_used; lc++ ) {
196
		kp = key_data[lc];
197
		if ( !memcmp( key_data[0], kp, 16 ) ) continue;
198
		printf( "\n\t%d,", lc );
199
		for ( i = 0; i < max_states; i++ )
200
			printf( " %d,", (unsigned int)kp[i] );
201
	}
202
	printf( "\n\t0, %d\n", map_ver );
203
	exit( 0 );
204
}
(-)linux-2.6.20/drivers/char/speakup/Kconfig (+211 lines)
Line 0 Link Here
1
menu "Speakup console speech" 
2
config SPEAKUP
3
	tristate "Build speakup console speech"
4
	---help---
5
		
6
		This is the Speakup screen reader.  Think of it as a
7
		video console for blind people.  If built in to the
8
		kernel, it can speak evrything on the text console from
9
		boot up to shutdown.  For more information on Speakup,
10
		point your browser at http://www.linux-speakup.org/. 
11
		There is also a mailing list at the above url that you
12
		can subscribe to.
13
		
14
		Supported synthesizers are accent sa, accent pc, appollo
15
		II., Auddapter, Braille 'n Speak, Dectalk external
16
		(old), Dectalk PC (full length isa board), Dectalk
17
		express, Doubletalk, Doubletalk LT or Litetalk,
18
		Keynote
19
		Gold internal PC, software synthesizers, Speakout, and transport.
20
		
21
		Speakup can either be built in or compiled as a module
22
		by answering y or m.  If you answer y here, then you
23
		must answer either y or m to at least one of the
24
		synthesizer drivers below.  If you answer m here, then
25
		the synthesizer drivers below can only be built as
26
		modules.
27
		
28
		These drivers are not standalone drivers, but must be
29
		used in conjunction with Speakup.  Think of them as
30
		video cards for blind people.
31
		
32
		
33
		The Dectalk pc driver can only be built as a module, and
34
		requires software to be pre-loaded on to the card before
35
		the module can be loaded.  See the decpc choice below
36
		for more details.
37
		
38
		If you are not a blind person, or don't have access to
39
		one of the listed synthesizers, you should say n.
40
41
config SPEAKUP_ACNTSA
42
	depends on SPEAKUP
43
	tristate "Accent SA, acntsa"
44
	---help---
45
		
46
		This is the Speakup driver for the accent sa
47
		synthesizer.  You can say y to build it into the kernel,
48
		or m to build it as a module.  See the configuration
49
		help on the Speakup choice above for more info.
50
51
config SPEAKUP_ACNTPC
52
	depends on SPEAKUP
53
	tristate "Accent PC, acntpc"
54
	---help---
55
		
56
		This is the Speakup driver for the accent pc
57
		synthesizer.  You can say y to build it into the kernel,
58
		or m to build it as a module.  See the configuration
59
		help on the Speakup choice above for more info.
60
61
config SPEAKUP_APOLLO
62
	depends on SPEAKUP
63
	tristate "Apollo, apollo"
64
	---help---
65
		
66
		This is the Speakup driver for the Apollo II
67
		synthesizer.  You can say y to build it into the kernel,
68
		or m to build it as a module.  See the configuration
69
		help on the Speakup choice above for more info.
70
	
71
config SPEAKUP_AUDPTR
72
	depends on SPEAKUP
73
	tristate "Audapter, audptr"
74
	---help---
75
		
76
		This is the Speakup driver for the Audapter synthesizer.
77
		 You can say y to build it into the kernel, or m to
78
		build it as a module.  See the configuration help on the
79
		Speakup choice above for more info.
80
81
config SPEAKUP_BNS
82
	depends on SPEAKUP
83
	tristate "Braille 'n' Speak, bns"
84
	---help---
85
		
86
		This is the Speakup driver for the Braille 'n' Speak
87
		synthesizer.  You can say y to build it into the kernel,
88
		or m to build it as a module.  See the configuration
89
		help on the Speakup choice above for more info.
90
	 
91
config SPEAKUP_DECTLK
92
	depends on SPEAKUP
93
	tristate "DECtalk Express, dectlk"
94
	---help---
95
		
96
		This is the Speakup driver for the DecTalk Express
97
		synthesizer.  You can say y to build it into the kernel,
98
		or m to build it as a module.  See the configuration
99
		help on the Speakup choice above for more info.
100
101
config SPEAKUP_DECEXT
102
	depends on SPEAKUP
103
	tristate "DECtalk External (old), decext"
104
	---help---
105
		
106
		This is the Speakup driver for the DecTalk External
107
		(old) synthesizer.  You can say y to build it into the
108
		kernel, or m to build it as a module.  See the
109
		configuration help on the Speakup choice above for more
110
		info.
111
112
config SPEAKUP_DECPC
113
	depends on SPEAKUP
114
	tristate "DECtalk PC (big ISA card), decpc"
115
	---help---
116
		
117
		This is the Speakup driver for the DecTalk PC (full
118
		length ISA) synthesizer.  You can say  m to build it as
119
		a module.  See the configuration help on the Speakup
120
		choice above for more info.
121
		
122
		In order to use the DecTalk PC driver, you must download
123
		the dec_pc.tgz file from linux-speakup.org.  It is in
124
		the pub/linux/goodies directory.  The dec_pc.tgz file
125
		contains the software which must be pre-loaded on to the
126
		DecTalk PC board in order to use it with this driver. 
127
		This driver must be built as a module, and can not be
128
		loaded until the file system is mounted and the DecTalk
129
		PC software has been pre-loaded on to the board.
130
		
131
		See the README file in the dec_pc.tgz file for more
132
		details.
133
134
config SPEAKUP_DTLK
135
	depends on SPEAKUP
136
	tristate "DoubleTalk PC, dtlk"
137
	---help---
138
		
139
		This is the Speakup driver for the internal DoubleTalk
140
		PC synthesizer.  You can say y to build it into the
141
		kernel, or m to build it as a module.  See the
142
		configuration help on the Speakup choice above for more
143
		info.
144
145
config SPEAKUP_KEYPC
146
	depends on SPEAKUP
147
	tristate "Keynote Gold PC, keypc"
148
	---help---
149
		
150
		This is the Speakup driver for the Keynote Gold
151
		PC synthesizer.  You can say y to build it into the
152
		kernel, or m to build it as a module.  See the
153
		configuration help on the Speakup choice above for more
154
		info.
155
156
config SPEAKUP_LTLK
157
	depends on SPEAKUP
158
	tristate "DoubleTalk LT or LiteTalk, ltlk"
159
---help---
160
161
		This is the Speakup driver for the LiteTalk/DoubleTalk
162
		LT synthesizer.  You can say y to build it into the
163
		kernel, or m to build it as a module.  See the
164
		configuration help on the Speakup choice above for more
165
		info.
166
167
config SPEAKUP_SFTSYN
168
	depends on SPEAKUP
169
	tristate "Software synthesizers, sftsyn"
170
---help---
171
172
		This is the software synthesizer device node.  It will
173
		register a device /dev/sftsyn which midware programs
174
		and speech
175
		daemons may open and read to provide kernel output to
176
		software synths
177
		such as festival, flite, tuxtalk and so forth.  You
178
		can select 'y' or
179
		'm' to have it built-in to the kernel or loaded as a module.
180
181
config SPEAKUP_SPKOUT
182
	depends on SPEAKUP
183
	tristate "Speak Out, spkout"
184
	---help---
185
		
186
		This is the Speakup driver for the Speakout synthesizer.
187
		 You can say y to build it into the kernel, or m to
188
		build it as a module.  See the configuration help on the
189
		Speakup choice above for more info.
190
191
config SPEAKUP_TXPRT
192
	depends on SPEAKUP
193
	tristate "Transport, txprt"
194
	---help---
195
		
196
		This is the Speakup driver for the Transport
197
		synthesizer.  You can say y to build it into the kernel,
198
		or m to build it as a module.  See the configuration
199
		help on the Speakup choice above for more info.
200
201
if SPEAKUP != n
202
comment 'Enter the 3 to 6 character keyword from the list above, or none for no default synthesizer on boot up.'
203
	depends on SPEAKUP
204
endif
205
206
config SPEAKUP_DEFAULT
207
	string "Choose Default synthesizer for Speakup"
208
	depends on SPEAKUP
209
	default "none"
210
211
endmenu
(-)linux-2.6.20/drivers/char/speakup/keyinfo.h (+120 lines)
Line 0 Link Here
1
/* spk_priv.h
2
   review functions for the speakup screen review package.
3
   originally written by: Kirk Reiser and Andy Berdan.
4
5
  extensively modified by David Borowski.
6
7
    Copyright (C ) 1998  Kirk Reiser.
8
    Copyright (C ) 2003  David Borowski.
9
10
    This program is free software; you can redistribute it and/or modify
11
    it under the terms of the GNU General Public License as published by
12
    the Free Software Foundation; either version 2 of the License, or
13
    (at your option ) any later version.
14
15
    This program is distributed in the hope that it will be useful,
16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
    GNU General Public License for more details.
19
20
    You should have received a copy of the GNU General Public License
21
    along with this program; if not, write to the Free Software
22
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
*/
24
25
enum { /* var_ids */
26
	VERSION = 0, SYNTH, SILENT, SYNTH_DIRECT,
27
	KEYMAP, CHARS,
28
	PUNC_SOME, PUNC_MOST, PUNC_ALL,
29
	DELIM, REPEATS, EXNUMBER,
30
	DELAY, TRIGGER, JIFFY, FULL, /* all timers must be together */
31
	BLEEP_TIME, CURSOR_TIME, BELL_POS,
32
SAY_CONTROL, SAY_WORD_CTL, NO_INTERRUPT, KEY_ECHO,
33
	SPELL_DELAY, PUNC_LEVEL, READING_PUNC,
34
	ATTRIB_BLEEP, BLEEPS,
35
 RATE, PITCH, VOL, TONE, PUNCT, VOICE, FREQ, LANG,
36
	CAPS_START, CAPS_STOP, CHARTAB,
37
	MAXVARS
38
};
39
40
#define FIRST_SYNTH_VAR RATE
41
/* 0 is reserved for no remap */
42
#define SPEAKUP_GOTO 0x01
43
#define SPEECH_KILL 0x02
44
#define SPEAKUP_QUIET 0x03
45
#define SPEAKUP_CUT 0x04
46
#define SPEAKUP_PASTE 0x05
47
#define SAY_FIRST_CHAR 0x06
48
#define SAY_LAST_CHAR 0x07
49
#define SAY_CHAR 0x08
50
#define SAY_PREV_CHAR 0x09
51
#define SAY_NEXT_CHAR 0x0a
52
#define SAY_WORD 0x0b
53
#define SAY_PREV_WORD 0x0c
54
#define SAY_NEXT_WORD 0x0d
55
#define SAY_LINE 0x0e
56
#define SAY_PREV_LINE 0x0f
57
#define SAY_NEXT_LINE 0x10
58
#define TOP_EDGE 0x11
59
#define BOTTOM_EDGE 0x12
60
#define LEFT_EDGE 0x13
61
#define RIGHT_EDGE 0x14
62
#define SPELL_PHONETIC 0x15
63
#define SPELL_WORD 0x16
64
#define SAY_SCREEN 0x17
65
#define SAY_POSITION 0x18
66
#define SAY_ATTRIBUTES 0x19
67
#define SPEAKUP_OFF 0x1a
68
#define SPEAKUP_PARKED 0x1b
69
#define SAY_LINE_INDENT 0x1c
70
#define SAY_FROM_TOP 0x1d
71
#define SAY_TO_BOTTOM 0x1e
72
#define SAY_FROM_LEFT 0x1f
73
#define SAY_TO_RIGHT 0x20
74
#define SAY_CHAR_NUM 0x21
75
#define EDIT_SOME 0x22
76
#define EDIT_MOST 0x23
77
#define SAY_PHONETIC_CHAR 0x24
78
#define EDIT_DELIM 0x25
79
#define EDIT_REPEAT 0x26
80
#define EDIT_EXNUM 0x27
81
#define SET_WIN 0x28
82
#define CLEAR_WIN 0x29
83
#define ENABLE_WIN 0x2a
84
#define SAY_WIN 0x2b
85
#define SPK_LOCK 0x2c
86
#define SPEAKUP_HELP 0x2d
87
#define TOGGLE_CURSORING 0x2e
88
#define READ_ALL_DOC 0x2f
89
#define SPKUP_MAX_FUNC 0x30 /* one greater than the last func handler */
90
91
#define SPK_KEY 0x80
92
#define FIRST_EDIT_BITS 0x22
93
94
#define FIRST_SET_VAR SPELL_DELAY
95
#define VAR_START 0x40 /* increase if adding more than 0x3f functions */
96
97
/* keys for setting variables, must be ordered same as the enum for var_ids */
98
/* with dec being even and inc being 1 greater */
99
#define SPELL_DELAY_DEC VAR_START+0
100
#define SPELL_DELAY_INC SPELL_DELAY_DEC+1
101
#define PUNC_LEVEL_DEC SPELL_DELAY_DEC+2
102
#define PUNC_LEVEL_INC PUNC_LEVEL_DEC+1
103
#define READING_PUNC_DEC PUNC_LEVEL_DEC+2
104
#define READING_PUNC_INC READING_PUNC_DEC+1
105
#define ATTRIB_BLEEP_DEC READING_PUNC_DEC+2
106
#define ATTRIB_BLEEP_INC ATTRIB_BLEEP_DEC+1
107
#define BLEEPS_DEC ATTRIB_BLEEP_DEC+2
108
#define BLEEPS_INC BLEEPS_DEC+1
109
#define RATE_DEC BLEEPS_DEC+2
110
#define RATE_INC RATE_DEC+1
111
#define PITCH_DEC RATE_DEC+2
112
#define PITCH_INC PITCH_DEC+1
113
#define VOL_DEC PITCH_DEC+2
114
#define VOL_INC VOL_DEC+1
115
#define TONE_DEC VOL_DEC+2
116
#define TONE_INC TONE_DEC+1
117
#define PUNCT_DEC TONE_DEC+2
118
#define PUNCT_INC PUNCT_DEC+1
119
#define VOICE_DEC PUNCT_DEC+2
120
#define VOICE_INC VOICE_DEC+1
(-)linux-2.6.20/drivers/char/speakup/Makefile (+61 lines)
Line 0 Link Here
1
#
2
# Makefile for the speakup speech output system.
3
#
4
5
V := $(shell awk '/UTS_RELEASE/ {print substr($$3,2,3)}' $(TOPDIR)/include/linux/version.h)
6
ifeq ($V,2.4)
7
# Note! Dependencies are done automagically by 'make dep', which also
8
# removes any old dependencies. DON'T put your own dependencies here
9
# unless it's something special (ie not a .c file).
10
#
11
# Note 2! The CFLAGS definitions are now inherited from the
12
# parent makes..
13
#
14
O_TARGET       := spk.o
15
export-objs    := speakup_drvcommon.o speakup.o
16
endif
17
obj-m = speakup_keyhelp.o
18
speakupmain-objs := speakup.o speakup_drvcommon.o
19
obj-$(CONFIG_SPEAKUP)	+= speakupmain.o
20
obj-$(CONFIG_SPEAKUP_ACNTPC)	+= speakup_acntpc.o
21
obj-$(CONFIG_SPEAKUP_ACNTSA)	+= speakup_acntsa.o
22
obj-$(CONFIG_SPEAKUP_APOLLO)	+= speakup_apollo.o
23
obj-$(CONFIG_SPEAKUP_AUDPTR)	+= speakup_audptr.o
24
obj-$(CONFIG_SPEAKUP_BNS)	+= speakup_bns.o
25
obj-$(CONFIG_SPEAKUP_DECEXT)	+= speakup_decext.o
26
obj-$(CONFIG_SPEAKUP_DECPC)	+= speakup_decpc.o
27
obj-$(CONFIG_SPEAKUP_DECTLK)	+= speakup_dectlk.o
28
obj-$(CONFIG_SPEAKUP_DTLK)	+= speakup_dtlk.o
29
obj-$(CONFIG_SPEAKUP_KEYPC)	+= speakup_keypc.o
30
obj-$(CONFIG_SPEAKUP_LTLK)	+= speakup_ltlk.o
31
obj-$(CONFIG_SPEAKUP_SFTSYN)	+= speakup_sftsyn.o
32
obj-$(CONFIG_SPEAKUP_SPKOUT)	+= speakup_spkout.o
33
obj-$(CONFIG_SPEAKUP_TXPRT)	+= speakup_txprt.o
34
35
ifeq ($V,2.4)
36
	include $(TOPDIR)/Rules.make
37
38
speakupmap.h: speakupmap.map genmap
39
	./genmap speakupmap.map >$@
40
41
genmap: genmap.c mapdata.h
42
	cc -o genmap genmap.c
43
44
mapdata.h: makemapdata.c keyinfo.h
45
	cc -o makemapdata makemapdata.c
46
	./makemapdata >mapdata.h
47
48
endif	
49
speakupmain.o:speakup.o speakup_drvcommon.o
50
	ld -r -o speakupmain.o speakup.o speakup_drvcommon.o
51
52
$(obj)/speakupmap.h: $(src)/speakupmap.map $(src)/genmap
53
	$(src)/genmap $(src)/speakupmap.map >$@
54
55
$(obj)/mapdata.h: $(src)/keyinfo.h $(src)/makemapdata
56
	$(src)/makemapdata >$@
57
58
$(obj)/genmap: $(obj)/mapdata.h
59
60
HOSTCFLAGS := -Iinclude -I/usr/include
61
hostprogs-y := makemapdata genmap
(-)linux-2.6.20/drivers/char/speakup/makemapdata.c (+156 lines)
Line 0 Link Here
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <libgen.h>
4
#include <string.h>
5
#include <linux/version.h>
6
#include <ctype.h>
7
8
int get_define(void);
9
10
#define MAXKEYS 512
11
#define MAXKEYVAL 160
12
#define HASHSIZE 101
13
#define is_shift -3
14
#define is_spk -2
15
#define is_input -1
16
typedef struct st_key t_key;
17
struct st_key {
18
	char *name;
19
	t_key *next;
20
	int value, shift;
21
};
22
23
t_key key_table[MAXKEYS];
24
t_key *extra_keys = key_table+HASHSIZE;
25
char buffer[256], filename[256];
26
FILE *infile;
27
char delims[] = "\t\n ";
28
char *dir_name, *def_name, *def_val, *cp;
29
int lc;
30
31
void open_input( char *name )
32
{
33
	sprintf( filename, "%s/%s", dir_name, name );
34
	if ( ( infile = fopen( filename, "r" ) ) == 0 ) {
35
		fprintf( stderr, "can't open %s\n", filename );
36
		exit( 1 );
37
	}
38
	lc = 0;
39
}
40
41
int
42
oops( char *msg, char *info )
43
{
44
	if ( info == NULL ) info = " ";
45
	fprintf( stderr, "error: file %s line %d\n", filename, lc );
46
	fprintf( stderr, "%s %s\n", msg, info );
47
	exit( 1 );
48
}
49
50
int get_define( )
51
{
52
	while ( fgets( buffer, 250, infile ) ) {
53
		lc++;
54
		if ( strncmp( buffer, "#define", 7 ) ) continue;
55
		strtok( buffer, delims );
56
		def_name = strtok( 0, delims );
57
		def_val = strtok( 0, delims );
58
		if ( def_val != NULL ) return 1;
59
	}
60
	fclose( infile );
61
	infile = 0;
62
	return 0;
63
}
64
65
t_key *hash_name( char *name )
66
{
67
	u_char *pn = (u_char *)name;
68
	int hash = 0;
69
	while ( *pn ) {
70
		hash = ( hash * 17 ) & 0xfffffff;
71
	if ( isupper( *pn ) ) *pn = tolower( *pn );
72
		hash += ( int )*pn;
73
		pn++;
74
	}
75
	hash %= HASHSIZE;
76
	return &key_table[hash];
77
}
78
79
t_key *find_key( char *name )
80
{
81
	t_key *this = hash_name( name );
82
	while ( this ) {
83
		if ( !strcmp( name, this->name ) ) return this;
84
		this = this->next;
85
	}
86
	return this;
87
}
88
89
t_key *add_key( char *name, int value, int shift )
90
{
91
	t_key *this = hash_name( name );
92
	if ( extra_keys-key_table >= MAXKEYS )
93
		oops( "out of key table space, enlarge MAXKEYS", NULL );
94
	if ( this->name != NULL ) {
95
		while ( this->next ) {
96
			if ( !strcmp( name, this->name ) )
97
				oops( "attempt to add duplicate key", name );
98
			this = this->next;
99
		}
100
		this->next = extra_keys++;
101
		this = this->next;
102
	}
103
	this->name = strdup( name );
104
	this->value = value;
105
	this->shift = shift;
106
	return this;
107
}
108
109
int		
110
main( int argc, char *argv[] )
111
{
112
	int value, i;
113
	t_key *this;
114
	dir_name = getenv( "TOPDIR" );
115
	if ( !dir_name ) dir_name = "/usr/src/linux";
116
	bzero( key_table, sizeof( key_table ) );
117
	add_key( "shift",	1, is_shift );
118
	add_key( "altgr",	2, is_shift );
119
	add_key( "ctrl",	4, is_shift );
120
	add_key( "alt",	8, is_shift );
121
	add_key( "spk", 16, is_shift );
122
	add_key( "double", 32, is_shift );
123
	open_input( "include/linux/input.h" );
124
	while ( get_define( ) ) {
125
		if ( strncmp( def_name, "KEY_", 4 ) ) continue;
126
		value = atoi( def_val );
127
		if ( value > 0 && value < MAXKEYVAL )
128
			add_key(  def_name, value, is_input );
129
	}
130
	open_input( "drivers/char/speakup/keyinfo.h" );
131
	while ( get_define( ) ) {
132
		if ( strlen( def_val ) > 5 ) {
133
			if ( !( cp = strchr( def_val, '+' ) ) ) continue;
134
			*cp++ = '\0';
135
			this = find_key( def_val );
136
			if ( !this || *cp < '0' || *cp > '9' ) continue;
137
			value = this->value+atoi( cp );
138
		} else if ( !strncmp( def_val, "0x", 2 ) ) 
139
			sscanf( def_val+2, "%x", &value );
140
		else if ( *def_val >= '0' && *def_val <= '9' )
141
			value = atoi( def_val );
142
		else continue;
143
		add_key( def_name, value, is_spk );
144
	}
145
	printf( "t_key_init init_key_data[] = {\n" );
146
	for ( i = 0; i < HASHSIZE; i++ ) {
147
		this = &key_table[i];
148
		if ( !this->name ) continue;
149
		do {
150
			printf( "\t\"%s\", %d, %d,\n", this->name, this->value, this->shift );
151
			this = this->next;
152
		} while ( this );
153
	}
154
	printf( "\t\".\", 0, 0\n};\n" );
155
	exit( 0 );
156
}
(-)linux-2.6.20/drivers/char/speakup/mapdata.h (+239 lines)
Line 0 Link Here
1
t_key_init init_key_data[] = {
2
	"key_s", 31, -1,
3
	"top_edge", 17, -2,
4
	"key_t", 20, -1,
5
	"say_first_char", 6, -2,
6
	"attrib_bleep_inc", 71, -2,
7
	"key_u", 22, -1,
8
	"key_grave", 41, -1,
9
	"key_v", 47, -1,
10
	"key_w", 17, -1,
11
	"key_kpasterisk", 55, -1,
12
	"key_minus", 12, -1,
13
	"key_x", 45, -1,
14
	"key_down", 108, -1,
15
	"key_y", 21, -1,
16
	"key_kpdot", 83, -1,
17
	"key_leftmeta", 125, -1,
18
	"key_z", 44, -1,
19
	"key_volumedown", 114, -1,
20
	"say_next_word", 13, -2,
21
	"clear_win", 41, -2,
22
	"key_rightbrace", 27, -1,
23
	"right_edge", 20, -2,
24
	"key_scrolllock", 70, -1,
25
	"key_comma", 51, -1,
26
	"altgr", 2, -3,
27
	"say_screen", 23, -2,
28
	"key_cut", 137, -1,
29
	"say_to_bottom", 30, -2,
30
	"edit_most", 35, -2,
31
	"key_sleep", 142, -1,
32
	"say_phonetic_char", 36, -2,
33
	"speakup_quiet", 3, -2,
34
	"read_all_doc", 47, -2,
35
	"key_hanja", 123, -1,
36
	"say_next_line", 16, -2,
37
	"vol_dec", 78, -2,
38
	"key_help", 138, -1,
39
	"key_xfer", 147, -1,
40
	"speakup_goto", 1, -2,
41
	"punct_inc", 83, -2,
42
	"key_rightctrl", 97, -1,
43
	"attrib_bleep_dec", 70, -2,
44
	"key_rightshift", 54, -1,
45
	"key_linefeed", 101, -1,
46
	"key_wakeup", 143, -1,
47
	"key_enter", 28, -1,
48
	"key_hangeul", 122, -1,
49
	"key_again", 129, -1,
50
	"key_file", 144, -1,
51
	"key_tab", 15, -1,
52
	"speakup_off", 26, -2,
53
	"set_win", 40, -2,
54
	"key_insert", 110, -1,
55
	"key_setup", 141, -1,
56
	"key_equal", 13, -1,
57
	"tone_inc", 81, -2,
58
	"key_hiragana", 91, -1,
59
	"key_kpjpcomma", 95, -1,
60
	"key_pause", 119, -1,
61
	"key_volumeup", 115, -1,
62
	"key_f1", 59, -1,
63
	"double", 32, -3,
64
	"key_f2", 60, -1,
65
	"key_computer", 157, -1,
66
	"key_back", 158, -1,
67
	"key_leftctrl", 29, -1,
68
	"key_f3", 61, -1,
69
	"key_f4", 62, -1,
70
	"key_0", 11, -1,
71
	"key_f5", 63, -1,
72
	"key_yen", 124, -1,
73
	"key_copy", 133, -1,
74
	"speakup_paste", 5, -2,
75
	"key_1", 2, -1,
76
	"key_f6", 64, -1,
77
	"toggle_cursoring", 46, -2,
78
	"key_esc", 1, -1,
79
	"key_2", 3, -1,
80
	"key_f7", 65, -1,
81
	"speakup_parked", 27, -2,
82
	"punct_dec", 82, -2,
83
	"key_3", 4, -1,
84
	"key_f8", 66, -1,
85
	"key_4", 5, -1,
86
	"key_f9", 67, -1,
87
	"key_5", 6, -1,
88
	"key_calc", 140, -1,
89
	"spell_phonetic", 21, -2,
90
	"key_6", 7, -1,
91
	"key_7", 8, -1,
92
	"key_coffee", 152, -1,
93
	"key_mail", 155, -1,
94
	"say_attributes", 25, -2,
95
	"say_to_right", 32, -2,
96
	"key_8", 9, -1,
97
	"key_mute", 113, -1,
98
	"key_9", 10, -1,
99
	"key_katakana", 90, -1,
100
	"key_zenkakuhankaku", 85, -1,
101
	"key_forward", 159, -1,
102
	"key_up", 103, -1,
103
	"tone_dec", 80, -2,
104
	"key_leftalt", 56, -1,
105
	"say_next_char", 10, -2,
106
	"reading_punc_inc", 69, -2,
107
	"rate_inc", 75, -2,
108
	"key_backspace", 14, -1,
109
	"bottom_edge", 18, -2,
110
	"key_kp0", 82, -1,
111
	"key_delete", 111, -1,
112
	"key_prog1", 148, -1,
113
	"say_char_num", 33, -2,
114
	"key_kp1", 79, -1,
115
	"key_end", 107, -1,
116
	"key_prog2", 149, -1,
117
	"key_kp2", 80, -1,
118
	"say_prev_word", 12, -2,
119
	"left_edge", 19, -2,
120
	"key_kp3", 81, -1,
121
	"key_katakanahiragana", 93, -1,
122
	"key_right", 106, -1,
123
	"key_kp4", 75, -1,
124
	"key_find", 136, -1,
125
	"key_kp5", 76, -1,
126
	"speakup_cut", 4, -2,
127
	"key_kp6", 77, -1,
128
	"key_kp7", 71, -1,
129
	"spkup_max_func", 48, -2,
130
	"key_kp8", 72, -1,
131
	"key_deletefile", 146, -1,
132
	"key_f10", 68, -1,
133
	"key_kp9", 73, -1,
134
	"key_f11", 87, -1,
135
	"key_sendfile", 145, -1,
136
	"say_word", 11, -2,
137
	"edit_repeat", 38, -2,
138
	"key_leftbrace", 26, -1,
139
	"key_f12", 88, -1,
140
	"say_prev_line", 15, -2,
141
	"say_from_top", 29, -2,
142
	"var_start", 64, -2,
143
	"reading_punc_dec", 68, -2,
144
	"rate_dec", 74, -2,
145
	"key_backslash", 43, -1,
146
	"edit_exnum", 39, -2,
147
	"key_kpslash", 98, -1,
148
	"key_pagedown", 109, -1,
149
	"key_kpplusminus", 118, -1,
150
	"key_stop", 128, -1,
151
	"key_props", 130, -1,
152
	"pitch_inc", 77, -2,
153
	"key_semicolon", 39, -1,
154
	"key_rightalt", 100, -1,
155
	"key_pageup", 104, -1,
156
	"key_kpplus", 78, -1,
157
	"say_line", 14, -2,
158
	"bleeps_inc", 73, -2,
159
	"key_leftshift", 42, -1,
160
	"key_kpminus", 74, -1,
161
	"key_paste", 135, -1,
162
	"spell_delay_inc", 65, -2,
163
	"punc_level_inc", 67, -2,
164
	"key_www", 150, -1,
165
	"edit_delim", 37, -2,
166
	"key_capslock", 58, -1,
167
	"key_muhenkan", 94, -1,
168
	"key_compose", 127, -1,
169
	"spk_key", 128, -2,
170
	"key_sysrq", 99, -1,
171
	"key_apostrophe", 40, -1,
172
	"key_left", 105, -1,
173
	"key_power", 116, -1,
174
	"key_menu", 139, -1,
175
	"voice_inc", 85, -2,
176
	"key_kpcomma", 121, -1,
177
	"spell_word", 22, -2,
178
	"enable_win", 42, -2,
179
	"key_a", 30, -1,
180
	"key_henkan", 92, -1,
181
	"key_bookmarks", 156, -1,
182
	"say_line_indent", 28, -2,
183
	"key_b", 48, -1,
184
	"key_space", 57, -1,
185
	"key_c", 46, -1,
186
	"edit_some", 34, -2,
187
	"key_d", 32, -1,
188
	"key_numlock", 69, -1,
189
	"key_home", 102, -1,
190
	"shift", 1, -3,
191
	"key_e", 18, -1,
192
	"key_msdos", 151, -1,
193
	"say_position", 24, -2,
194
	"pitch_dec", 76, -2,
195
	"key_f", 33, -1,
196
	"key_cyclewindows", 154, -1,
197
	"speakup_help", 45, -2,
198
	"first_edit_bits", 34, -2,
199
	"alt", 8, -3,
200
	"key_g", 34, -1,
201
	"key_kpenter", 96, -1,
202
	"key_macro", 112, -1,
203
	"bleeps_dec", 72, -2,
204
	"ctrl", 4, -3,
205
	"key_h", 35, -1,
206
	"key_direction", 153, -1,
207
	"key_i", 23, -1,
208
	"spk_lock", 44, -2,
209
	"spell_delay_dec", 64, -2,
210
	"punc_level_dec", 66, -2,
211
	"key_j", 36, -1,
212
	"say_prev_char", 9, -2,
213
	"key_k", 37, -1,
214
	"key_102nd", 86, -1,
215
	"key_l", 38, -1,
216
	"key_ro", 89, -1,
217
	"key_rightmeta", 126, -1,
218
	"key_m", 50, -1,
219
	"key_kpequal", 117, -1,
220
	"key_undo", 131, -1,
221
	"speech_kill", 2, -2,
222
	"key_n", 49, -1,
223
	"key_front", 132, -1,
224
	"key_o", 24, -1,
225
	"key_open", 134, -1,
226
	"voice_dec", 84, -2,
227
	"spk", 16, -3,
228
	"key_p", 25, -1,
229
	"say_last_char", 7, -2,
230
	"say_from_left", 31, -2,
231
	"key_q", 16, -1,
232
	"key_slash", 53, -1,
233
	"say_win", 43, -2,
234
	"key_r", 19, -1,
235
	"key_dot", 52, -1,
236
	"say_char", 8, -2,
237
	"vol_inc", 79, -2,
238
	".", 0, 0
239
};
(-)linux-2.6.20/drivers/char/speakup/mod_code.c (+22 lines)
Line 0 Link Here
1
/* this code is to modularize a synth specific file, included at the end */
2
3
static void __exit mod_synth_exit( void )
4
{
5
        if ( synth == &MY_SYNTH ) 
6
	  synth_release( );
7
	synth_remove( &MY_SYNTH );
8
}
9
10
static int __init mod_synth_init( void )
11
{
12
	int status = do_synth_init( &MY_SYNTH );
13
	if ( status != 0 ) return status;
14
	synth_add( &MY_SYNTH );
15
	return 0;
16
}
17
18
module_init( mod_synth_init );
19
module_exit( mod_synth_exit );
20
MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
21
MODULE_DESCRIPTION("Synthesizer driver module for speakup for the  synth->long_name");
22
MODULE_LICENSE( "GPL" );
(-)linux-2.6.20/drivers/char/speakup/serialio.h (+18 lines)
Line 0 Link Here
1
#ifndef SSPK_SERIAL
2
#define SSPK_SERIAL
3
4
#include <linux/serial.h>	/* for rs_table, serial constants & 
5
				   serial_uart_config */
6
#include <linux/serial_reg.h>	/* for more serial constants */
7
#include <linux/serialP.h>	/* for struct serial_state */
8
#include <asm/serial.h>
9
10
#define SPK_SERIAL_TIMEOUT 1000000	/* countdown values for serial timeouts */
11
#define SPK_XMITR_TIMEOUT 1000000	/* countdown values transmitter/dsr timeouts */
12
#define SPK_LO_TTY 0		/* check ttyS0 ... ttyS3 */
13
#define SPK_HI_TTY 3
14
#define NUM_DISABLE_TIMEOUTS 3	/* # of timeouts permitted before disable */
15
#define SPK_TIMEOUT 100			/* buffer timeout in ms */
16
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
17
18
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_acnt.h (+16 lines)
Line 0 Link Here
1
/* speakup_acntpc.h - header file for speakups Accent-PC driver. */
2
3
#define SYNTH_IO_EXTENT	0x02
4
5
#define SYNTH_CLEAR 0x18		/* stops speech */
6
7
	/* Port Status Flags */
8
#define SYNTH_READABLE     0x01	/* mask for bit which is nonzero if a
9
				   byte can be read from the data port */
10
#define SYNTH_WRITABLE     0x02	/* mask for RDY bit, which when set to
11
             			   1, indicates the data port is ready
12
             			   to accept a byte of data. */
13
#define SYNTH_QUIET      'S' /* synth is not speaking */
14
#define SYNTH_FULL  'F' /* synth is full. */
15
#define SYNTH_ALMOST_EMPTY 'M' /* synth has les than 2 seconds of text left */
16
#define SYNTH_SPEAKING 's' /* synth is speaking and has a fare way to go */
(-)linux-2.6.20/drivers/char/speakup/speakup_acntpc.c (+161 lines)
Line 0 Link Here
1
/*
2
 * originially written by: Kirk Reiser <kirk@braille.uwo.ca>
3
* this version considerably modified by David Borowski, david575@rogers.com
4
5
		Copyright (C) 1998-99  Kirk Reiser.
6
		Copyright (C) 2003 David Borowski.
7
8
		This program is free software; you can redistribute it and/or modify
9
		it under the terms of the GNU General Public License as published by
10
		the Free Software Foundation; either version 2 of the License, or
11
		(at your option) any later version.
12
13
		This program is distributed in the hope that it will be useful,
14
		but WITHOUT ANY WARRANTY; without even the implied warranty of
15
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
		GNU General Public License for more details.
17
18
		You should have received a copy of the GNU General Public License
19
		along with this program; if not, write to the Free Software
20
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22
 * this code is specificly written as a driver for the speakup screenreview
23
 * package and is not a general device driver.
24
		*/
25
#include "spk_priv.h"
26
#include "speakup_acnt.h" /* local header file for Accent values */
27
28
#define MY_SYNTH synth_acntpc
29
#define synth_readable( ) ( inb_p( synth_port_control ) & SYNTH_READABLE ) 
30
#define synth_writable( ) ( inb_p( synth_port_control ) & SYNTH_WRITABLE ) 
31
#define synth_full( ) ( inb_p( synth_port_tts ) == 'F' ) 
32
#define PROCSPEECH '\r'
33
34
35
static int synth_port_control;
36
static unsigned int synth_portlist[] =
37
    { 0x2a8, 0 };
38
39
static const char *synth_immediate ( const char *buf )
40
{
41
	u_char ch;
42
	while (  (  ch = *buf ) ) {
43
	if ( ch == 0x0a ) ch = PROCSPEECH;
44
		if ( synth_full( ) )
45
			return buf;
46
		while ( synth_writable( ) ); 
47
		outb_p( ch, synth_port_tts );
48
	buf++;
49
	}
50
	return 0;
51
}
52
53
static void do_catch_up( unsigned long data )
54
{
55
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
56
	u_char ch;
57
	synth_stop_timer( );
58
	while (  synth_buff_out < synth_buff_in ) {
59
		if ( synth_full( ) ) {
60
			synth_delay( synth_full_time );
61
			return;
62
		}
63
		while ( synth_writable( ) ); 
64
		ch = *synth_buff_out++;
65
	if ( ch == 0x0a ) ch = PROCSPEECH;
66
		outb_p( ch, synth_port_tts );
67
		if ( jiffies >= jiff_max && ch == SPACE ) {
68
			while ( synth_writable( ) );
69
			outb_p( PROCSPEECH, synth_port_tts );
70
			synth_delay( synth_delay_time ); 
71
			return; 
72
		}
73
	}
74
	while ( synth_writable( ) );
75
	outb_p( PROCSPEECH, synth_port_tts );
76
	synth_done(  );
77
}
78
79
static void synth_flush( void )
80
{
81
	outb_p( SYNTH_CLEAR, synth_port_tts );
82
}
83
84
static int synth_probe( void )
85
{
86
	unsigned int port_val = 0;
87
	int i = 0;
88
	pr_info( "Probing for %s.\n", synth->long_name );
89
	if ( synth_port_forced ) {
90
		synth_port_tts = synth_port_forced;
91
		pr_info( "probe forced to %x by kernel command line\n", synth_port_tts );
92
		if ( synth_request_region( synth_port_tts-1, SYNTH_IO_EXTENT ) ) {
93
			pr_warn( "sorry, port already reserved\n" );
94
			return -EBUSY;
95
		}
96
		port_val = inw( synth_port_tts-1 );
97
		synth_port_control = synth_port_tts-1;
98
	} else {
99
		for( i=0; synth_portlist[i]; i++ ) {
100
			if ( synth_request_region( synth_portlist[i], SYNTH_IO_EXTENT ) ) {
101
				pr_warn( "request_region:  failed with 0x%x, %d\n",
102
					synth_portlist[i], SYNTH_IO_EXTENT );
103
				continue;
104
			}
105
			port_val = inw( synth_portlist[i] );
106
			if ( ( port_val &= 0xfffc ) == 0x53fc ) { /* 'S' and out&input bits */
107
				synth_port_control = synth_portlist[i];
108
				synth_port_tts = synth_port_control+1;
109
				break;
110
			}
111
		}
112
	}
113
	if ( ( port_val &= 0xfffc ) != 0x53fc ) { /* 'S' and out&input bits */
114
		pr_info( "%s:  not found\n", synth->long_name );
115
		synth_release_region( synth_portlist[i], SYNTH_IO_EXTENT );
116
		synth_port_control = 0;
117
		return -ENODEV;
118
	}
119
	pr_info( "%s:  %03x-%03x, driver version %s,\n", synth->long_name,
120
		synth_port_control,	synth_port_control+SYNTH_IO_EXTENT-1, 
121
		synth->version );
122
	return 0;
123
}
124
125
static void accent_release(  void )
126
{
127
	if (  synth_port_tts )
128
		synth_release_region( synth_port_tts-1, SYNTH_IO_EXTENT );
129
	synth_port_tts = 0;
130
}
131
132
static int synth_is_alive( void )
133
{
134
	synth_alive = 1;
135
	return 1;
136
}
137
138
static const char init_string[] = "\033=X \033Oi\033T2\033=M\033N1\n";
139
140
static struct st_string_var stringvars[] = {
141
	{ CAPS_START, "\033P8" },
142
	{ CAPS_STOP, "\033P5" },
143
	V_LAST_STRING
144
};
145
static struct st_num_var numvars[] = {
146
	{ RATE, "\033R%c", 9, 0, 17, 0, 0, "0123456789abcdefgh" },
147
	{ PITCH, "\033P%d", 5, 0, 9, 0, 0, 0 },
148
	{ VOL, "\033A%d", 5, 0, 9, 0, 0, 0 },
149
	{ TONE, "\033V%d", 5, 0, 9, 0, 0, 0 },
150
	V_LAST_NUM
151
};
152
153
struct spk_synth synth_acntpc = {"acntpc", "1.1", "Accent PC",
154
	 init_string, 500, 50, 50, 1000, 0, 0, SYNTH_CHECK,
155
	stringvars, numvars, synth_probe, accent_release, synth_immediate,
156
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL,
157
	{NULL,0,0,0} };
158
159
#ifdef MODULE
160
#include "mod_code.c"
161
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_acntsa.c (+184 lines)
Line 0 Link Here
1
/*
2
 * originially written by: Kirk Reiser <kirk@braille.uwo.ca>
3
* this version considerably modified by David Borowski, david575@rogers.com
4
5
		Copyright (C) 1998-99  Kirk Reiser.
6
		Copyright (C) 2003 David Borowski.
7
8
		This program is free software; you can redistribute it and/or modify
9
		it under the terms of the GNU General Public License as published by
10
		the Free Software Foundation; either version 2 of the License, or
11
		(at your option) any later version.
12
13
		This program is distributed in the hope that it will be useful,
14
		but WITHOUT ANY WARRANTY; without even the implied warranty of
15
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
		GNU General Public License for more details.
17
18
		You should have received a copy of the GNU General Public License
19
		along with this program; if not, write to the Free Software
20
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22
 * this code is specificly written as a driver for the speakup screenreview
23
 * package and is not a general device driver.
24
		*/
25
#include "spk_priv.h"
26
#include "serialio.h"
27
#include "speakup_acnt.h"	/* local header file for Accent values */
28
29
#define MY_SYNTH synth_acntsa
30
#define synth_full( ) ( inb_p( synth_port_tts ) == 'F' )
31
#define PROCSPEECH '\r'
32
33
static int timeouts = 0;	/* sequential number of timeouts */
34
35
static int
36
wait_for_xmitr ( void )
37
{
38
	int check, tmout = SPK_XMITR_TIMEOUT;
39
	if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) {
40
		synth_alive = 0;
41
		return 0;
42
	}
43
	do { /* holding register empty? */
44
		check = inb_p ( synth_port_tts + UART_LSR );
45
		if ( --tmout == 0 ) {
46
			pr_warn ( "%s:  timed out\n", synth->long_name );
47
			timeouts++;
48
			return 0;
49
		}
50
	} while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY );
51
	tmout = SPK_XMITR_TIMEOUT;
52
	do { /* CTS */
53
		check = inb_p ( synth_port_tts + UART_MSR );
54
		if ( --tmout == 0 ) {
55
			timeouts++;
56
			return 0;
57
		}
58
	} while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS );
59
	timeouts = 0;
60
	return 1;
61
}
62
63
static int spk_serial_out(const char ch)
64
{
65
	if (synth_alive && wait_for_xmitr()) {
66
		outb_p(ch, synth_port_tts);
67
		return 1;
68
	}
69
	return 0;
70
}
71
72
static void
73
do_catch_up ( unsigned long data )
74
{
75
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
76
	u_char ch;
77
	synth_stop_timer ( );
78
	while ( synth_buff_out < synth_buff_in ) {
79
		ch = *synth_buff_out;
80
	if ( ch == 0x0a ) ch = 0x0D;
81
		if ( !spk_serial_out ( ch ) ) {
82
			synth_delay ( synth_full_time );
83
			return;
84
		}
85
		synth_buff_out++;
86
		if ( jiffies >= jiff_max && ch == ' ' ) {
87
			spk_serial_out ( PROCSPEECH );
88
			synth_delay ( synth_delay_time );
89
			return;
90
		}
91
	}
92
	spk_serial_out ( PROCSPEECH );
93
	synth_done( );
94
}
95
96
static const char *synth_immediate ( const char *buff )
97
{
98
	u_char ch;
99
	while ( ( ch = *buff ) ) {
100
	if ( ch == 0x0a ) ch = PROCSPEECH;
101
        if ( wait_for_xmitr( ) )
102
          outb( ch, synth_port_tts );
103
        else return buff;
104
	buff++;
105
	}
106
	return 0;
107
}
108
109
static void synth_flush ( void )
110
{
111
	spk_serial_out ( SYNTH_CLEAR );
112
}
113
114
static int serprobe ( int index )
115
{
116
	struct serial_state *ser = spk_serial_init( index );
117
	if ( ser == NULL ) return -1;
118
	outb ( 0x0d, ser->port );
119
	//	mdelay ( 1 );
120
	/* ignore any error results, if port was forced */
121
	if ( synth_port_forced ) return 0;
122
	/* check for accent s.a now... */
123
	if ( !synth_immediate( "\x18" ) )
124
		return 0;
125
	spk_serial_release( );
126
	timeouts = synth_alive = 0;	/* not ignoring */
127
	return -1;
128
}
129
130
static int synth_probe ( void )
131
{
132
	int i = 0, failed=0;
133
	pr_info ( "Probing for %s.\n", synth->long_name );
134
	for ( i = SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) {
135
	  if (( failed = serprobe( i )) == 0 ) break; /* found it */
136
        }
137
        if ( failed ) {
138
		pr_info ( "%s:  not found\n", synth->long_name );
139
		return -ENODEV;
140
	}
141
	pr_info ( "%s: %03x-%03x, Driver Version %s,\n", synth->long_name,
142
		synth_port_tts, synth_port_tts + 7, synth->version );
143
	synth_immediate( "\033=R\r" );
144
	mdelay( 100 );
145
	return 0;
146
}
147
148
static int
149
synth_is_alive ( void )
150
{
151
	if ( synth_alive ) return 1;
152
	if ( !synth_alive && wait_for_xmitr ( ) > 0 ) {	/* restart */
153
		synth_alive = 1;
154
		synth_write_string ( synth->init );
155
		return 2;
156
	}
157
	pr_warn ( "%s: can't restart synth\n", synth->long_name );
158
	return 0;
159
}
160
161
static const char init_string[] = "\033T2\033=M\033Oi\033N1\n";
162
163
static struct st_string_var stringvars[] = {
164
	{ CAPS_START, "\033P8" },
165
	{ CAPS_STOP, "\033P5" },
166
	V_LAST_STRING
167
};
168
static struct st_num_var numvars[] = {
169
	{ RATE, "\033R%c", 9, 0, 17, 0, 0, "0123456789abcdefgh" },
170
	{ PITCH, "\033P%d", 5, 0, 9, 0, 0, 0 },
171
	{ VOL, "\033A%d", 9, 0, 9, 0, 0, 0 },
172
	{ TONE, "\033V%d", 5, 0, 9, 0, 0, 0 },
173
	V_LAST_NUM
174
};
175
   
176
struct spk_synth synth_acntsa = { "acntsa", "1.1", "Accent-SA",
177
	init_string, 400, 5, 30, 1000, 0, 0, SYNTH_CHECK,
178
	stringvars, numvars, synth_probe, spk_serial_release, synth_immediate,
179
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL,
180
	{NULL,0,0,0} };
181
182
#ifdef MODULE
183
#include "mod_code.c"
184
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_apollo.c (+196 lines)
Line 0 Link Here
1
/*
2
 * originially written by: Kirk Reiser <kirk@braille.uwo.ca>
3
* this version considerably modified by David Borowski, david575@rogers.com
4
5
		Copyright (C) 1998-99  Kirk Reiser.
6
		Copyright (C) 2003 David Borowski.
7
8
		This program is free software; you can redistribute it and/or modify
9
		it under the terms of the GNU General Public License as published by
10
		the Free Software Foundation; either version 2 of the License, or
11
		(at your option) any later version.
12
13
		This program is distributed in the hope that it will be useful,
14
		but WITHOUT ANY WARRANTY; without even the implied warranty of
15
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
		GNU General Public License for more details.
17
18
		You should have received a copy of the GNU General Public License
19
		along with this program; if not, write to the Free Software
20
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22
 * this code is specificly written as a driver for the speakup screenreview
23
 * package and is not a general device driver.
24
		*/
25
#include "spk_priv.h"
26
#include "serialio.h"
27
28
#define MY_SYNTH synth_apollo
29
#define SYNTH_CLEAR 0x18
30
#define PROCSPEECH '\r'
31
32
static int timeouts = 0;	/* sequential number of timeouts */
33
34
static int wait_for_xmitr( void )
35
{
36
	int check, tmout = SPK_XMITR_TIMEOUT;
37
	if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) {
38
		synth_alive = 0; 
39
		timeouts = 0;
40
		return 0; 
41
	}
42
	do {
43
		check = inb( synth_port_tts + UART_LSR );
44
		if ( --tmout == 0 ) {
45
			pr_warn( "APOLLO:  timed out\n" );
46
			timeouts++;
47
			return 0;
48
		}
49
	} while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY );
50
	tmout = SPK_XMITR_TIMEOUT;
51
	do {
52
		check = inb( synth_port_tts + UART_MSR );
53
				if ( --tmout == 0 ) {
54
					timeouts++;
55
					return 0;
56
				}
57
	} while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS );
58
	timeouts = 0;
59
	return 1;
60
}
61
62
static int spk_serial_out(const char ch)
63
{
64
 // int timer = 9000000; 
65
	if ( synth_alive && wait_for_xmitr( ) ) {
66
		outb( ch, synth_port_tts );
67
		/*while ( inb( synth_port_tts+UART_MSR ) & UART_MSR_CTS ) if ( --timer == 0 ) break;*/
68
		/*    outb( UART_MCR_DTR, synth_port_tts + UART_MCR );*/
69
		return 1;
70
	}
71
	return 0;
72
}
73
74
/*
75
static unsigned char spk_serial_in( void ) 
76
{
77
	int c, lsr, tmout = SPK_SERIAL_TIMEOUT;
78
	do {
79
		lsr = inb( synth_port_tts + UART_LSR );
80
		if ( --tmout == 0 ) return 0xff;
81
	} while ( !( lsr & UART_LSR_DR ) );
82
	c = inb( synth_port_tts + UART_RX );
83
	return ( unsigned char ) c;
84
}
85
*/
86
87
static void do_catch_up( unsigned long data )
88
{
89
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
90
	u_char ch;
91
synth_stop_timer( );
92
	while ( synth_buff_out < synth_buff_in ) {
93
		ch = *synth_buff_out;
94
		if ( !spk_serial_out( ch ) ) {
95
			outb( UART_MCR_DTR, synth_port_tts + UART_MCR );
96
			outb( UART_MCR_DTR | UART_MCR_RTS, synth_port_tts + UART_MCR );
97
			synth_delay( synth_full_time );
98
			return;
99
		}
100
		synth_buff_out++;
101
		if ( jiffies >= jiff_max && synth_buff_out-synth_buffer > 10 ) {
102
		spk_serial_out( PROCSPEECH );
103
		synth_delay( synth_delay_time ); 
104
		return; 
105
		}
106
	}
107
	spk_serial_out( PROCSPEECH );
108
	synth_done( );
109
}
110
111
static const char *synth_immediate ( const char *buf )
112
{
113
	u_char ch;
114
	while ( ( ch = *buf ) ) {
115
	if ( ch == 0x0a ) ch = PROCSPEECH;
116
        if ( wait_for_xmitr( ) )
117
	  outb( ch, synth_port_tts );
118
	else return buf;
119
	buf++;
120
	}
121
	return 0;
122
}
123
124
static void synth_flush ( void )
125
{
126
	spk_serial_out ( SYNTH_CLEAR );
127
}
128
129
static int serprobe( int index )
130
{
131
	struct serial_state *ser = spk_serial_init( index );
132
	if ( ser == NULL ) return -1;
133
	outb( 0x0d, ser->port ); /* wake it up if older BIOS */
134
	mdelay( 1 );
135
	synth_port_tts = ser->port;
136
	if ( synth_port_forced ) return 0;
137
	/* check for apollo now... */
138
	if ( !synth_immediate( "\x18" ) ) return 0;
139
	pr_warn( "port %x failed\n", synth_port_tts );
140
	spk_serial_release( );
141
	timeouts = synth_alive = synth_port_tts = 0;
142
	return -1;
143
}
144
145
static int synth_probe( void )
146
{
147
	int i, failed=0;
148
	pr_info( "Probing for %s.\n", synth->long_name );
149
	for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) {
150
	  if (( failed = serprobe( i )) == 0 ) break; /* found it */
151
	}
152
	if ( failed ) {
153
		pr_info( "%s:  not found\n", synth->long_name );
154
		return -ENODEV;
155
	}
156
	pr_info( "%s:  %03x-%03x, Driver version %s,\n", synth->long_name,
157
	 synth_port_tts, synth_port_tts + 7, synth->version );
158
	return 0;
159
}
160
161
static int synth_is_alive( void )
162
{
163
	if ( synth_alive ) return 1;
164
	if ( !synth_alive && wait_for_xmitr( ) > 0 ) { /* restart */
165
		synth_alive = 1;
166
		synth_write_string( synth->init );
167
		return 2;  /* reenabled */
168
	} else pr_warn( "%s: can't restart synth\n", synth->long_name );
169
	return 0;
170
}
171
172
static const char init_string[] = "@R3@D0@K1\r";
173
174
static struct st_string_var stringvars[] = {
175
	{ CAPS_START, "cap, " },
176
	{ CAPS_STOP, "" },
177
	V_LAST_STRING
178
};
179
static struct st_num_var numvars[] = {
180
	{ RATE, "@W%d", 6, 1, 9, 0, 0, 0 },
181
	{ PITCH, "@F%x", 10, 0, 15, 0, 0, 0 },
182
	{ VOL, "@A%x", 10, 0, 15, 0, 0, 0 },
183
	{ VOICE, "@V%d", 1, 1, 6, 0, 0, 0 },
184
	{ LANG, "@=%d,", 1, 1, 4, 0, 0, 0 },
185
	V_LAST_NUM
186
};
187
	 
188
struct spk_synth synth_apollo = {"apollo", "1.2", "Apollo",
189
	init_string, 500, 50, 50, 5000, 0, 0, SYNTH_CHECK,
190
	stringvars, numvars, synth_probe, spk_serial_release, synth_immediate,
191
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL,
192
	{NULL,0,0,0} };
193
194
#ifdef MODULE
195
#include "mod_code.c"
196
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_audptr.c (+202 lines)
Line 0 Link Here
1
/*
2
 * originially written by: Kirk Reiser <kirk@braille.uwo.ca>
3
* this version considerably modified by David Borowski, david575@rogers.com
4
5
		Copyright (C) 1998-99  Kirk Reiser.
6
		Copyright (C) 2003 David Borowski.
7
8
		This program is free software; you can redistribute it and/or modify
9
		it under the terms of the GNU General Public License as published by
10
		the Free Software Foundation; either version 2 of the License, or
11
		(at your option) any later version.
12
13
		This program is distributed in the hope that it will be useful,
14
		but WITHOUT ANY WARRANTY; without even the implied warranty of
15
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
		GNU General Public License for more details.
17
18
		You should have received a copy of the GNU General Public License
19
		along with this program; if not, write to the Free Software
20
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22
 * this code is specificly written as a driver for the speakup screenreview
23
 * package and is not a general device driver.
24
		*/
25
#include "spk_priv.h"
26
#include "serialio.h"
27
28
#define MY_SYNTH synth_audptr
29
#define SYNTH_CLEAR 0x18 /* flush synth buffer */
30
#define PROCSPEECH '\r' /* start synth processing speech char */
31
32
static int timeouts = 0;	/* sequential number of timeouts */
33
34
static int wait_for_xmitr( void )
35
{
36
	int check, tmout = SPK_XMITR_TIMEOUT;
37
	if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) {
38
		synth_alive = 0; 
39
		timeouts = 0;
40
		return 0; 
41
	}
42
	do { /* holding register empty? */
43
		check = inb( synth_port_tts + UART_LSR );
44
		if ( --tmout == 0 ) {
45
			pr_warn( "%s:  timed out\n", synth->long_name );
46
		  timeouts++;
47
		  return 0;
48
		}
49
	} while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY );
50
	tmout = SPK_XMITR_TIMEOUT;
51
	do { /* CTS */
52
		check = inb( synth_port_tts + UART_MSR );
53
		if ( --tmout == 0 ) {
54
			timeouts++;
55
			return 0;
56
		}
57
	} while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS );
58
	timeouts = 0;
59
	return 1;
60
}
61
62
static int spk_serial_out(const char ch)
63
{
64
	if ( synth_alive && wait_for_xmitr( ) ) {
65
		outb( ch, synth_port_tts );
66
		return 1;
67
	}
68
	return 0;
69
}
70
71
static unsigned char spk_serial_in( void )
72
{
73
	int c, lsr, tmout = SPK_SERIAL_TIMEOUT;
74
	do {
75
		lsr = inb( synth_port_tts + UART_LSR );
76
		if ( --tmout == 0 ) return 0xff;
77
	} while ( !( lsr & UART_LSR_DR ) );
78
	c = inb( synth_port_tts + UART_RX );
79
	return ( unsigned char ) c;
80
}
81
82
static void do_catch_up( unsigned long data )
83
{
84
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
85
	u_char ch;
86
synth_stop_timer( );
87
	while ( synth_buff_out < synth_buff_in ) {
88
		ch = *synth_buff_out;
89
		if ( ch == 0x0a ) ch = PROCSPEECH;
90
		if ( !spk_serial_out( ch ) ) {
91
		  	synth_delay( synth_full_time );
92
		  	return;
93
		}
94
		synth_buff_out++;
95
		if ( jiffies >= jiff_max && ch == SPACE ) {
96
		  	spk_serial_out( PROCSPEECH );
97
			synth_delay( synth_delay_time ); 
98
			return; 
99
		}
100
	}
101
	spk_serial_out( PROCSPEECH );
102
	synth_done( );
103
}
104
105
static const char *synth_immediate ( const char *buf )
106
{
107
	u_char ch;
108
	while ( ( ch = *buf ) ) {
109
	if ( ch == 0x0a ) ch = PROCSPEECH;
110
        if ( wait_for_xmitr( ) )
111
          outb( ch, synth_port_tts );
112
        else return buf;
113
	buf++;
114
	}
115
	return 0;
116
}
117
118
static void synth_flush( void )
119
{
120
	while ( ( inb( synth_port_tts + UART_LSR ) & BOTH_EMPTY ) != BOTH_EMPTY );
121
	outb( SYNTH_CLEAR, synth_port_tts );
122
		  spk_serial_out( PROCSPEECH );
123
		}
124
125
static char synth_id[40] = "";
126
127
static int serprobe( int index )
128
{
129
	u_char test = 0;
130
	struct serial_state *ser = spk_serial_init( index );
131
	if ( ser == NULL ) return -1;
132
	/* ignore any error results, if port was forced */
133
	if ( synth_port_forced )
134
		return 0;
135
	synth_immediate( "\x05[Q]" );
136
	if ( ( synth_id[test] = spk_serial_in( ) ) == 'A' ) {
137
		do { /* read version string from synth */
138
		  synth_id[++test] = spk_serial_in( );
139
		} while ( synth_id[test] != '\n' && test < 32 );
140
		synth_id[++test] = 0x00;
141
		if ( test != 32 ) 
142
		  return 0;
143
	}
144
	spk_serial_release( );
145
		    timeouts = synth_alive = 0; /* not ignoring */
146
		    return -1;
147
}
148
149
static int synth_probe( void )
150
{
151
	int i=0, failed=0;
152
	pr_info( "Probing for %s.\n", synth->long_name );
153
	for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) {
154
	  if (( failed = serprobe( i )) == 0 ) break; /* found it */
155
	}
156
	if ( failed ) {
157
		pr_info( "%s:  not found\n", synth->long_name );
158
		return -ENODEV;
159
	}
160
	pr_info( "%s:  %03x-%03x, Driver %s,\n", synth->long_name,
161
	 synth_port_tts, synth_port_tts + 7, synth->version );
162
	if ( synth_id[0] == 'A' )
163
	  pr_info( "%s version: %s", synth->long_name, synth_id );
164
		return 0;
165
}
166
167
static int synth_is_alive( void )
168
{
169
	if ( synth_alive ) return 1;
170
	if ( !synth_alive && wait_for_xmitr( ) > 0 ) { /* restart */
171
		synth_alive = 1;
172
		synth_write_string( synth->init );
173
		return 2;
174
	}
175
	return 0;
176
}
177
178
static const char init_string[] = "\x05[D1]\x05[Ol]";
179
180
static struct st_string_var stringvars[] = {
181
	{ CAPS_START, "\x05[f99]" },
182
	{ CAPS_STOP, "\x05[f80]" },
183
	V_LAST_STRING
184
};
185
static struct st_num_var numvars[] = {
186
	{ RATE, "\x05[r%d]", 10, 0, 20, -100, 10, 0 },
187
	{ PITCH, "\x05[f%d]", 80, 39, 4500, 0, 0, 0 },
188
	{ VOL, "\x05[g%d]", 21, 0, 40, 0, 0, 0 },
189
	{ TONE, "\x05[s%d]", 9, 0,63, 0, 0, 0 },
190
	{ PUNCT, "\x05[A%c]", 0, 0, 3, 0, 0, "nmsa" },
191
	V_LAST_NUM
192
};
193
	 
194
struct spk_synth synth_audptr = {"audptr", "1.1", "Audapter",
195
	 init_string, 400, 5, 30, 5000, 0, 0, SYNTH_CHECK,
196
	stringvars, numvars, synth_probe, spk_serial_release, synth_immediate,
197
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL,
198
	{NULL,0,0,0} };
199
200
#ifdef MODULE
201
#include "mod_code.c"
202
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_bns.c (+175 lines)
Line 0 Link Here
1
/*
2
 * originially written by: Kirk Reiser <kirk@braille.uwo.ca>
3
* this version considerably modified by David Borowski, david575@rogers.com
4
5
		Copyright (C) 1998-99  Kirk Reiser.
6
		Copyright (C) 2003 David Borowski.
7
8
		This program is free software; you can redistribute it and/or modify
9
		it under the terms of the GNU General Public License as published by
10
		the Free Software Foundation; either version 2 of the License, or
11
		(at your option) any later version.
12
13
		This program is distributed in the hope that it will be useful,
14
		but WITHOUT ANY WARRANTY; without even the implied warranty of
15
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
		GNU General Public License for more details.
17
18
		You should have received a copy of the GNU General Public License
19
		along with this program; if not, write to the Free Software
20
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22
 * this code is specificly written as a driver for the speakup screenreview
23
 * package and is not a general device driver.
24
		*/
25
#include "spk_priv.h"
26
#include "serialio.h"
27
28
#define MY_SYNTH synth_bns
29
#define SYNTH_CLEAR 0x18
30
#define PROCSPEECH '\r'
31
32
static int wait_for_xmitr( void )
33
{
34
	static int timeouts = 0;	/* sequential number of timeouts */
35
	int check, tmout = SPK_XMITR_TIMEOUT;
36
	if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) {
37
		synth_alive = 0; 
38
		timeouts = 0;
39
		return 0; 
40
	}
41
	do {
42
		check = inb( synth_port_tts + UART_LSR );
43
		if ( --tmout == 0 ) {
44
		 	pr_warn( "BNS:  timed out\n" );
45
			timeouts++;
46
			return 0;
47
		}
48
	} while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY );
49
	tmout = SPK_XMITR_TIMEOUT;
50
	do {
51
		check = inb( synth_port_tts + UART_MSR );
52
		if ( --tmout == 0 ) {
53
			timeouts++;
54
			return 0;
55
		}
56
	} while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS );
57
	timeouts = 0;
58
	return 1;
59
}
60
61
static int spk_serial_out(const char ch)
62
{
63
	if ( synth_alive && wait_for_xmitr( ) ) {
64
		outb( ch, synth_port_tts );
65
		return 1;
66
	}
67
	return 0;
68
}
69
70
static void do_catch_up( unsigned long data )
71
{
72
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
73
	u_char ch;
74
	synth_stop_timer( );
75
	while ( synth_buff_out < synth_buff_in ) {
76
		ch = *synth_buff_out;
77
		if ( ch == '\n' ) ch = PROCSPEECH;
78
		if ( !spk_serial_out( ch ) ) {
79
			synth_delay( synth_full_time );
80
			return;
81
		}
82
		synth_buff_out++;
83
		if ( jiffies >= jiff_max && ch == ' ' ) { 
84
			spk_serial_out( PROCSPEECH );
85
			synth_delay( synth_delay_time ); 
86
			return; 
87
		}
88
	}
89
	spk_serial_out( PROCSPEECH );
90
	synth_done( );
91
}
92
93
static const char *synth_immediate ( const char *buf )
94
{
95
	u_char ch;
96
	while ( ( ch = *buf ) ) {
97
	if ( ch == 0x0a ) ch = PROCSPEECH;
98
        if ( wait_for_xmitr( ) )
99
          outb( ch, synth_port_tts );
100
        else return buf;
101
	buf++;
102
	}
103
	return 0;
104
}
105
106
static void synth_flush ( void )
107
{
108
	spk_serial_out ( SYNTH_CLEAR );
109
}
110
111
static int serprobe( int index )
112
{
113
	struct serial_state *ser = spk_serial_init( index );
114
	if ( ser == NULL ) return -1;
115
	outb( '\r', ser->port );
116
	if ( synth_port_forced ) return 0;
117
	/* check for bns now... */
118
	if ( !synth_immediate( "\x18" ) ) return 0;
119
	spk_serial_release( );
120
	synth_alive = 0;
121
				return -1;
122
}
123
124
static int synth_probe( void )
125
{
126
	int i=0, failed=0;
127
	pr_info( "Probing for %s.\n", synth->long_name );
128
	for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) {
129
	  if (( failed = serprobe( i )) == 0 ) break; /* found it */
130
        }
131
        if ( failed ) {
132
		pr_info( "%s:  not found\n", synth->long_name );
133
		return -ENODEV;
134
	}
135
	pr_info( "%s:  %03x-%03x, Driver version %s,\n", synth->long_name,
136
		synth_port_tts, synth_port_tts + 7, synth->version );
137
	return 0;
138
}
139
140
static int synth_is_alive( void )
141
{
142
	if ( synth_alive ) return 1;
143
	if ( !synth_alive && wait_for_xmitr( ) > 0 ) { /* restart */
144
		synth_alive = 1;
145
		synth_write_string( synth->init );
146
		return 2;
147
	}
148
	pr_warn( "%s: can't restart synth\n", synth->long_name );
149
	return 0;
150
}
151
152
static const char init_string[] = "\x05Z\x05\x43";
153
154
static struct st_string_var stringvars[] = {
155
	{ CAPS_START, "\x05\x31\x32P" },
156
	{ CAPS_STOP, "\x05\x38P" },
157
	V_LAST_STRING
158
};
159
static struct st_num_var numvars[] = {
160
	{ RATE, "\x05%dE", 8, 1, 16, 0, 0, 0 },
161
	{ PITCH, "\x05%dP", 8, 0, 16, 0, 0, 0 },
162
	{ VOL, "\x05%dV", 8, 0, 16, 0, 0, 0 },
163
	{ TONE, "\x05%dT", 8, 0, 16, 0, 0, 0 },
164
	V_LAST_NUM
165
};
166
167
struct spk_synth synth_bns = {"bns", "1.1", "Braille 'N Speak",
168
	init_string, 500, 50, 50, 5000, 0, 0, SYNTH_CHECK,
169
	stringvars, numvars, synth_probe, spk_serial_release, synth_immediate,
170
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL,
171
	{NULL,0,0,0} };
172
173
#ifdef MODULE
174
#include "mod_code.c"
175
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup.c (+2873 lines)
Line 0 Link Here
1
/* speakup.c
2
   review functions for the speakup screen review package.
3
   originally written by: Kirk Reiser and Andy Berdan.
4
5
  extensively modified by David Borowski.
6
7
    Copyright (C ) 1998  Kirk Reiser.
8
    Copyright (C ) 2003  David Borowski.
9
10
    This program is free software; you can redistribute it and/or modify
11
    it under the terms of the GNU General Public License as published by
12
    the Free Software Foundation; either version 2 of the License, or
13
    (at your option ) any later version.
14
15
    This program is distributed in the hope that it will be useful,
16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
    GNU General Public License for more details.
19
20
    You should have received a copy of the GNU General Public License
21
    along with this program; if not, write to the Free Software
22
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
*/
24
25
#include <linux/kernel.h>
26
#include <linux/version.h>
27
#include <linux/vt.h>
28
#include <linux/tty.h>
29
#include <linux/mm.h> /* __get_free_page( ) and friends */
30
#include <linux/vt_kern.h>
31
#include <linux/ctype.h>
32
#include <linux/selection.h>
33
#include <asm/uaccess.h> /* copy_from|to|user( ) and others */
34
#include <linux/unistd.h>
35
36
#include <linux/keyboard.h>	/* for KT_SHIFT */
37
#include <linux/kbd_kern.h> /* for vc_kbd_* and friends */
38
#include <linux/vt_kern.h>
39
#include <linux/input.h>
40
#include <linux/kmod.h>
41
#include <linux/speakup.h>
42
43
#include "cvsversion.h"
44
#include "spk_priv.h"
45
#include <linux/bootmem.h>	/* for alloc_bootmem */
46
47
/* speakup_*_selection */
48
#include <linux/module.h>
49
#include <linux/sched.h>
50
#include <linux/slab.h>
51
#include <linux/types.h>
52
#include <asm/uaccess.h>
53
#include <linux/consolemap.h>
54
55
#define SPEAKUP_VERSION "Speakup v-2.00" CVSVERSION
56
#define MAX_DELAY ( (500 * HZ ) / 1000 )
57
#define KEY_MAP_VER 119
58
#define MINECHOCHAR SPACE
59
60
/* these are globals from the kernel code */
61
extern struct kbd_struct * kbd;
62
extern int fg_console;
63
extern short punc_masks[];
64
65
static special_func special_handler = NULL;
66
special_func help_handler = NULL;
67
68
short pitch_shift = 0, synth_flags = 0;
69
static char buf[256];
70
short attrib_bleep = 0, bleeps = 0,  bleep_time = 1;
71
short no_intr = 0, spell_delay = 0;
72
short key_echo = 0, cursor_timeout = 120, say_word_ctl = 0;
73
short say_ctrl = 0, bell_pos = 0;
74
short punc_mask = 0, punc_level = 0, reading_punc = 0;
75
char str_caps_start[MAXVARLEN+1] = "\0", str_caps_stop[MAXVARLEN+1] = "\0";
76
static const struct st_bits_data punc_info[] = {
77
	{ "none", "", 0 },
78
	{ "some", "/$%&@", SOME },
79
	{ "most", "$%&#()=+*/@^<>|\\", MOST },
80
	{ "all", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", PUNC },
81
	{ "delimiters", "", B_WDLM },
82
	{ "repeats", "()", CH_RPT },
83
	{ "extended numeric", "", B_EXNUM },
84
	{ "symbols", "", B_SYM },
85
	{ 0, 0 }
86
};
87
static char mark_cut_flag = 0;
88
char synth_name[10] = CONFIG_SPEAKUP_DEFAULT;
89
#define MAX_KEY 160
90
u_char *our_keys[MAX_KEY], *shift_table;
91
static u_char key_buf[600];
92
static const u_char key_defaults[] = {
93
#include "speakupmap.h"
94
};
95
96
/* Speakup Cursor Track Variables */
97
static int cursor_track = 1, prev_cursor_track = 1;
98
99
/* cursor track modes, must be ordered same as cursor_msgs */
100
enum {
101
	CT_Off = 0,
102
	CT_On,
103
	CT_Highlight,
104
	CT_Window,
105
	CT_Max
106
};
107
#define read_all_mode CT_Max
108
109
struct tty_struct *tty;
110
#define key_handler k_handler
111
typedef void (*k_handler_fn)(struct vc_data *vc, unsigned char value,
112
                            char up_flag);
113
extern k_handler_fn key_handler[16];
114
static k_handler_fn do_shift, do_spec, do_latin, do_cursor;
115
EXPORT_SYMBOL_GPL(help_handler);
116
EXPORT_SYMBOL_GPL(special_handler);
117
EXPORT_SYMBOL_GPL(our_keys);
118
EXPORT_SYMBOL_GPL(synth_name);
119
120
static void spkup_write(const char *in_buf, int count);
121
static int set_mask_bits(const char *input, const int which, const int how);
122
123
static const char str_ctl[] = "control-";
124
static const char *colors[] = {
125
	"black", "blue", "green", "cyan", "red", "magenta", "yellow", "white",
126
	"grey"
127
};
128
129
static char *phonetic[] = {
130
	"alpha", "beta", "charley", "delta", "echo", "fox", "gamma", "hotel",
131
	"india", "juleiet", "keelo", "leema", "mike", "november", "oscar",
132
	"papa",
133
	"quebec", "romeo", "seeara", "tango", "uniform", "victer", "wiskey",
134
	"x ray", "yankee", "zooloo"
135
};
136
137
// array of 256 char pointers (one for each character description )
138
// initialized to default_chars and user selectable via /proc/speakup/characters
139
static char *characters[256];
140
141
static char *default_chars[256] = {
142
	"null", "^a", "^b", "^c", "^d", "^e", "^f", "^g",
143
	"^h", "^i", "^j", "^k", "^l", "^m", "^n", "^o",
144
	"^p", "^q", "^r", "^s", "^t", "^u", "^v", "^w",
145
	"^x", "^y", "^z", NULL, NULL, NULL, NULL, NULL,
146
	"space", "bang!", "quote", "number", "dollar", "percent", "and",
147
	"tick",
148
	"left paren", "right paren", "star", "plus", "comma", "dash", "dot",
149
	"slash",
150
	"zero", "one", "two", "three", "four", "five", "six", "seven",
151
	"eight", "nine",
152
	"colon", "semmy", "less", "equals", "greater", "question", "at",
153
	"eigh", "b", "c", "d", "e", "f", "g",
154
	"h", "i", "j", "k", "l", "m", "n", "o",
155
	"p", "q", "r", "s", "t", "u", "v", "w", "x",
156
	"y", "zehd", "left bracket", "backslash", "right bracket", "caret",
157
	"line",
158
	"accent", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
159
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
160
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
161
	NULL, NULL, NULL, "left brace", "bar", "right brace", "tihlduh",
162
	"delta", "see cedilla", "u oomlout", "e acute", /* 128 */
163
	"eigh circumflex", "eigh oomlout", "eigh grave", "eigh ring", /* 132 */
164
	"see cedilla", "e circumflex", "e oomlout", "e grave", /* 136 */
165
	"i oomlout", "i circumflex", "i grave", "eigh oomlout", /* 140 */
166
	"eigh ring", "e acute", "eigh e dipthong", "eigh e dipthong", /* 144 */
167
	"o circumflex", "o oomlout", "o grave", "u circumflex", /* 148 */
168
	"u grave", "y oomlout", "o oomlout", "u oomlout", /* 152 */
169
	"cents", "pounds", "yen", "peseta", /* 156 */
170
	"florin", "eigh acute", "i acute", "o acute", /* 160 */
171
	"u acute", "n tilde", "n tilde", "feminine ordinal", /* 164 */
172
	"masculin ordinal", "inverted question", "reversed not", "not", /* 168 */
173
	"half", "quarter", "inverted bang", "much less than", /* 172 */
174
	"much greater than", "dark shading", "medium shading", /* 176 */
175
	"light shading", "verticle line", "left tee", /* 179 */
176
	"double left tee", "left double tee", "double top right", /* 182 */
177
	"top double right", "double left double tee", /* 185 */
178
	"double vertical line", "double top double right", /* 187 */
179
	"double bottom double right", "double bottom right", /* 189 */
180
	"bottom double right", "top right", "left bottom", /* 191 */
181
	"up tee", "tee down", "tee right", "horizontal line", /* 194 */
182
	"cross bars", "tee double right", "double tee right", /* 198 */
183
	"double left double bottom", "double left double top", /* 201 */
184
	"double up double tee", "double tee double down", /* 203 */
185
	"double tee double right", "double horizontal line", /* 205 */
186
	"double cross bars", "up double tee", "double up tee", /* 207 */
187
	"double tee down", "tee double down", /* 210 */
188
	"double left bottom", "left double bottom", /* 212 */
189
	"double left top", "left double top", /* 214 */
190
	"double vertical cross", "double horizontal cross", /* 216 */
191
	"bottom right", "left top", "solid square", /* 218 */
192
	"solid lower half", "solid left half", "solid right half", /* 221 */
193
	"solid upper half", "alpha", "beta", "gamma", /* 224 */
194
	"pie", "sigma", "sigma", "mu", /* 228 */
195
	"tou", "phigh", "thayta", "ohmega", /* 232 */
196
	"delta", "infinity", "phigh", "epsilaun", /* 236 */
197
"intersection", "identical to", "plus or minus", "equal grater than", /* 240 */
198
	"less than equal", "upper integral", "lower integral", /* 244 */
199
		"divided by", "almost equal", "degrees", /* 247 */
200
	"centre dot", "bullet", "square root", /* 250 */
201
	"power", "squared", "black square", "white space" /* 252 */
202
};
203
204
// array of 256 u_short (one for each character)
205
// initialized to default_chartab and user selectable via /proc/speakup/chartab
206
static u_short spk_chartab[256];
207
208
static u_short default_chartab[256] = {
209
 B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 0-7 */
210
 B_CTL, B_CTL, A_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 8-15 */
211
 B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /*16-23 */
212
 B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 24-31 */
213
WDLM, A_PUNC, PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC, /*  !"#$%&' */
214
PUNC, PUNC, PUNC, PUNC, A_PUNC, A_PUNC, A_PUNC, PUNC, /* ( )*+, -./ */
215
NUM, NUM, NUM, NUM, NUM, NUM, NUM, NUM, /* 01234567 */
216
NUM, NUM, A_PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC, /* 89:;<=>? */
217
PUNC, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* @ABCDEFG */
218
A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* HIJKLMNO */
219
A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* PQRSTUVW */
220
A_CAP, A_CAP, A_CAP, PUNC, PUNC, PUNC, PUNC, PUNC, /* XYZ[\]^_ */
221
PUNC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* `abcdefg */
222
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* hijklmno */
223
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* pqrstuvw */
224
ALPHA, ALPHA, ALPHA, PUNC, PUNC, PUNC, PUNC, 0, /* xyz{|}~ */
225
B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 128-135 */
226
B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_CAPSYM, /* 136-143 */
227
B_CAPSYM, B_CAPSYM, B_SYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 144-151 */
228
B_SYM, B_SYM, B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 152-159 */
229
B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_CAPSYM, B_SYM, /* 160-167 */
230
B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 168-175 */
231
B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 176-183 */
232
B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 184-191 */
233
B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 192-199 */
234
B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 200-207 */
235
B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 208-215 */
236
B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 216-223 */
237
B_SYM, B_SYM, B_SYM, B_CAPSYM, B_SYM, B_CAPSYM, B_SYM, B_SYM, /* 224-231 */
238
B_SYM, B_CAPSYM, B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 232-239 */
239
B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 240-247 */
240
B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM /* 248-255 */
241
};
242
243
static int spk_keydown = 0;
244
static u_char spk_lastkey = 0, spk_close_press = 0, keymap_flags = 0;
245
static u_char last_keycode = 0, this_speakup_key = 0;
246
static u_long last_spk_jiffy = 0;
247
248
struct st_spk_t *speakup_console[MAX_NR_CONSOLES];
249
250
static int spk_setup(char *str)
251
{
252
	int ints[4];
253
	str = get_options(str, ARRAY_SIZE (ints), ints);
254
	if (ints[0] > 0 && ints[1] >= 0)
255
		synth_port_forced = ints[1];
256
	return 1;
257
}
258
259
static int spk_ser_setup(char *str)
260
{
261
	const int lookup[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
262
	int ints[4];
263
	str = get_options(str, ARRAY_SIZE (ints), ints);
264
	if (ints[0] > 0 && ints[1] >= 0)
265
		synth_port_forced = lookup[ints[1]];
266
	return 1;
267
}
268
269
static int spk_synth_setup(char *str)
270
{
271
	size_t len = min_t(size_t, strlen(str), 9);
272
	memcpy (synth_name, str, len);
273
	synth_name[len] = '\0';
274
	return 1;
275
}
276
277
static int spk_quiet_setup(char *str)
278
{
279
	if (strchr("1yt", *str) != NULL)
280
		quiet_boot = 1;
281
	return 1;
282
}
283
284
__setup("speakup_port=", spk_setup);
285
__setup("speakup_ser=", spk_ser_setup);
286
__setup("speakup_synth=", spk_synth_setup);
287
__setup("speakup_quiet=", spk_quiet_setup);
288
289
static unsigned char get_attributes(u16 *pos)
290
{
291
	return (u_char)(scr_readw(pos) >> 8);
292
}
293
294
static void speakup_date(struct vc_data *vc)
295
{
296
	spk_x = spk_cx = vc->vc_x;
297
	spk_y = spk_cy = vc->vc_y;
298
	spk_pos = spk_cp = vc->vc_pos;
299
	spk_old_attr = spk_attr;
300
	spk_attr = get_attributes((u_short *) spk_pos);
301
}
302
303
char *strlwr(char *s)
304
{
305
	char *p;
306
	for (p = s; *p; p++)
307
		if (*p >= CAP_A && *p <= CAP_Z)
308
			*p |= 32;
309
	return s;
310
}
311
312
static void bleep(u_short val)
313
{
314
	static const short vals[] = {
315
		350, 370, 392, 414, 440, 466, 491, 523, 554, 587, 619, 659
316
	};
317
	short freq;
318
	int time = bleep_time;
319
	freq = vals[val%12];
320
	if (val > 11)
321
		freq *= (1 << (val/12));
322
	kd_mksound(freq, time);
323
}
324
325
static void speakup_shut_up(struct vc_data *vc)
326
{
327
	if (spk_killed)
328
		return;
329
	spk_shut_up |= 0x01;
330
	spk_parked &= 0xfe;
331
	speakup_date(vc);
332
	if (synth != NULL)
333
		do_flush();
334
}
335
336
static void speech_kill(struct vc_data *vc)
337
{
338
	char val = synth->is_alive();
339
	if (val == 0)
340
		return;
341
342
	/* re-enables synth, if disabled */
343
	if (val == 2 || spk_killed) {	/* dead */
344
		spk_shut_up &= ~0x40;
345
		synth_write_msg("Eyem a Lighve!");
346
	} else {
347
		synth_write_msg("You killed speak up!");
348
		spk_shut_up |= 0x40;
349
	}
350
}
351
352
static void speakup_off(struct vc_data *vc)
353
{
354
	if (spk_shut_up & 0x80) {
355
		spk_shut_up &= 0x7f;
356
		synth_write_msg("hey. That's better!" );
357
	} else {
358
		spk_shut_up |= 0x80;
359
		synth_write_msg("You turned me off!" );
360
	}
361
	speakup_date(vc);
362
}
363
364
static void speakup_parked(struct vc_data *vc)
365
{
366
	if (spk_parked & 0x80) {
367
		spk_parked = 0;
368
		synth_write_msg ("unparked!");
369
	} else {
370
		spk_parked |= 0x80;
371
		synth_write_msg ("parked!");
372
	}
373
}
374
375
/* ------ cut and paste ----- */
376
/* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
377
#undef isspace
378
#define isspace(c)      ((c) == ' ')
379
/* Variables for selection control. */
380
static struct vc_data *spk_sel_cons;      /* defined in selection.c must not be disallocated */
381
static volatile int sel_start = -1;     /* cleared by clear_selection */
382
static int sel_end;
383
static int sel_buffer_lth;
384
static char *sel_buffer;
385
386
static unsigned char sel_pos(int n)
387
{
388
	return inverse_translate(spk_sel_cons, screen_glyph(spk_sel_cons, n));
389
}
390
391
static u16 get_char(struct vc_data *vc, u16 *pos)
392
{
393
	u16 ch = ' ';
394
	if (vc && pos) {
395
		u16 w = scr_readw(pos);
396
		u16 c = w & 0xff;
397
  
398
		if (w & vc->vc_hi_font_mask)
399
			c |= 0x100;
400
401
		ch = w & 0xff00;		
402
		ch |= inverse_translate(vc, c);
403
	}
404
	return ch;
405
}
406
407
static void speakup_clear_selection(void)
408
{
409
	sel_start = -1;
410
}
411
412
/* does screen address p correspond to character at LH/RH edge of screen? */
413
static int atedge(const int p, int size_row)
414
{
415
	return (!(p % size_row) || !((p + 2) % size_row));
416
}
417
418
/* constrain v such that v <= u */
419
static unsigned short limit(const unsigned short v, const unsigned short u)
420
{
421
	return (v > u) ? u : v;
422
}
423
424
static unsigned short xs, ys, xe, ye; /* our region points */
425
426
static int speakup_set_selection(struct tty_struct *tty)
427
{
428
	int new_sel_start, new_sel_end;
429
	char *bp, *obp;
430
	int i, ps, pe;
431
	struct vc_data *vc = vc_cons[fg_console].d;
432
433
	xs = limit(xs, vc->vc_cols - 1);
434
	ys = limit(ys, vc->vc_rows - 1);
435
	xe = limit(xe, vc->vc_cols - 1);
436
	ye = limit(ye, vc->vc_rows - 1);
437
	ps = ys * vc->vc_size_row + (xs << 1);
438
	pe = ye * vc->vc_size_row + (xe << 1);
439
440
	if (ps > pe) {   /* make sel_start <= sel_end */
441
		int tmp = ps;
442
		ps = pe;
443
		pe = tmp;
444
	}
445
446
	if (spk_sel_cons != vc_cons[fg_console].d) {
447
	 	speakup_clear_selection();
448
		spk_sel_cons = vc_cons[fg_console].d;
449
		printk(KERN_WARNING "Selection: mark console not the same as cut\n");
450
		return -EINVAL;
451
	}
452
453
	new_sel_start = ps;
454
	new_sel_end = pe;
455
456
	/* select to end of line if on trailing space */
457
	if (new_sel_end > new_sel_start &&
458
	    !atedge(new_sel_end, vc->vc_size_row) &&
459
	    isspace(sel_pos(new_sel_end))) {
460
		for (pe = new_sel_end + 2; ; pe += 2)
461
			if (!isspace(sel_pos(pe)) ||
462
			    atedge(pe, vc->vc_size_row))
463
				break;
464
		if (isspace(sel_pos(pe)))
465
			new_sel_end = pe;
466
	}
467
	if ((new_sel_start == sel_start) && (new_sel_end == sel_end))
468
		return 0; /* no action required */
469
470
	sel_start = new_sel_start;
471
	sel_end = new_sel_end;
472
	/* Allocate a new buffer before freeing the old one ... */
473
	bp = kmalloc((sel_end-sel_start)/2+1, GFP_ATOMIC);
474
	if (!bp) {
475
		printk(KERN_WARNING "selection: kmalloc() failed\n");
476
		speakup_clear_selection();
477
		return -ENOMEM;
478
	}
479
	if (sel_buffer)
480
		kfree(sel_buffer);
481
	sel_buffer = bp;
482
483
	obp = bp;
484
	for (i = sel_start; i <= sel_end; i += 2) {
485
		*bp = sel_pos(i);
486
		if (!isspace(*bp++))
487
			obp = bp;
488
		if (! ((i + 2) % vc->vc_size_row)) {
489
			/* strip trailing blanks from line and add newline,
490
			   unless non-space at end of line. */
491
			if (obp != bp) {
492
				bp = obp;
493
				*bp++ = '\r';
494
			}
495
			obp = bp;
496
		}
497
	}
498
	sel_buffer_lth = bp - sel_buffer;
499
	return 0;
500
}
501
502
static int speakup_paste_selection(struct tty_struct *tty)
503
{
504
	struct vc_data *vc = (struct vc_data *) tty->driver_data;
505
	int pasted = 0, count;
506
	DECLARE_WAITQUEUE(wait, current);
507
	add_wait_queue(&vc->paste_wait, &wait);
508
	while (sel_buffer && sel_buffer_lth > pasted) {
509
		set_current_state(TASK_INTERRUPTIBLE);
510
		if (test_bit(TTY_THROTTLED, &tty->flags)) {
511
			schedule();
512
			continue;
513
		}
514
		count = sel_buffer_lth - pasted;
515
		count = min_t(int, count, tty->receive_room);
516
		tty->ldisc.receive_buf(tty, sel_buffer + pasted, 0, count);
517
		pasted += count;
518
	}
519
	remove_wait_queue(&vc->paste_wait, &wait);
520
	current->state = TASK_RUNNING;
521
	return 0;
522
}
523
524
static void speakup_cut(struct vc_data *vc)
525
{
526
	static const char err_buf[] = "set selection failed";
527
	int ret;
528
529
	if (!mark_cut_flag) {
530
		mark_cut_flag = 1;
531
		xs = spk_x;
532
		ys = spk_y;
533
		spk_sel_cons = vc;
534
		synth_write_msg("mark");
535
		return;
536
	}
537
	xe = (u_short) spk_x;
538
	ye = (u_short) spk_y;
539
	mark_cut_flag = 0;
540
	synth_write_msg ("cut");
541
	
542
	speakup_clear_selection();
543
	ret = speakup_set_selection(tty);
544
545
	switch (ret) {
546
	case 0:
547
		break; /* no error */
548
	case -EFAULT :
549
		pr_warn( "%sEFAULT\n", err_buf );
550
		break;
551
	case -EINVAL :
552
		pr_warn( "%sEINVAL\n", err_buf );
553
		break;
554
	case -ENOMEM :
555
		pr_warn( "%sENOMEM\n", err_buf );
556
		break;
557
	}
558
}
559
560
static void speakup_paste(struct vc_data *vc)
561
{
562
	if (mark_cut_flag) {
563
		mark_cut_flag = 0;
564
		synth_write_msg("mark, cleared");
565
	} else {
566
		synth_write_msg ("paste");
567
		speakup_paste_selection(tty);
568
	}
569
}
570
571
static void say_attributes(struct vc_data *vc )
572
{
573
	int fg = spk_attr & 0x0f;
574
	int bg = spk_attr>>4;
575
	if (fg > 8) {
576
		synth_write_string("bright ");
577
		fg -= 8;
578
	}
579
	synth_write_string(colors[fg]);
580
	if (bg > 7) {
581
		synth_write_string(" on blinking ");
582
		bg -= 8;
583
	} else
584
		synth_write_string(" on ");
585
	synth_write_msg(colors[bg]);
586
}
587
588
static char *blank_msg = "blank";
589
static char *edges[] = { "top, ", "bottom, ", "left, ", "right, ", "" };
590
enum {
591
	edge_top = 1,
592
	edge_bottom,
593
	edge_left,
594
	edge_right,
595
	edge_quiet
596
};
597
598
static void announce_edge(struct vc_data *vc, int msg_id)
599
{
600
	if (bleeps & 1)
601
		bleep(spk_y);
602
	if (bleeps & 2)
603
		synth_write_msg(edges[msg_id-1]);
604
}
605
606
static void speak_char( u_char ch)
607
{
608
	char *cp = characters[ch];
609
	if (cp == NULL) {
610
		pr_info ("speak_char: cp==NULL!\n");
611
		return;
612
	}
613
	synth_buffer_add(SPACE);
614
	if (IS_CHAR(ch, B_CAP)) {
615
		pitch_shift++;
616
		synth_write_string(str_caps_start);
617
		synth_write_string(cp);
618
		synth_write_string(str_caps_stop);
619
	} else {
620
		if (*cp == '^') {
621
			synth_write_string(str_ctl);
622
			cp++;
623
		}
624
		synth_write_string(cp);
625
	}
626
	synth_buffer_add(SPACE);
627
}
628
629
static void say_char(struct vc_data *vc)
630
{
631
	u_short ch;
632
	spk_old_attr = spk_attr;
633
	ch = get_char(vc, (u_short *) spk_pos);
634
	spk_attr = (ch >> 8);
635
	if (spk_attr != spk_old_attr) {
636
		if (attrib_bleep & 1)
637
			bleep(spk_y);
638
		if (attrib_bleep & 2)
639
			say_attributes(vc);
640
	}
641
	speak_char(ch & 0xff);
642
}
643
644
static void say_phonetic_char(struct vc_data *vc)
645
{
646
	u_short ch;
647
	spk_old_attr = spk_attr;
648
	ch = get_char(vc, (u_short *) spk_pos);
649
	spk_attr = ((ch & 0xff00) >> 8);
650
	if (IS_CHAR(ch, B_ALPHA)) {
651
		ch &= 0x1f;
652
		synth_write_msg(phonetic[--ch] );
653
	} else {
654
		if (IS_CHAR(ch, B_NUM))
655
			synth_write_string("number ");
656
		speak_char(ch);
657
	}
658
}
659
660
static void say_prev_char(struct vc_data *vc)
661
{
662
	spk_parked |= 0x01;
663
	if (spk_x == 0) {
664
		announce_edge(vc, edge_left);
665
		return;
666
	}
667
	spk_x--;
668
	spk_pos -= 2;
669
	say_char(vc);
670
}
671
672
static void say_next_char(struct vc_data *vc)
673
{
674
	spk_parked |= 0x01;
675
	if (spk_x == vc->vc_cols - 1) {
676
		announce_edge(vc, edge_right);
677
		return;
678
	}
679
	spk_x++;
680
	spk_pos += 2;
681
	say_char(vc);
682
}
683
684
/* get_word - will first check to see if the character under the
685
   reading cursor is a space and if say_word_ctl is true it will
686
   return the word space.  If say_word_ctl is not set it will check to
687
   see if there is a word starting on the next position to the right
688
   and return that word if it exists.  If it does not exist it will
689
   move left to the beginning of any previous word on the line or the
690
   beginning off the line whichever comes first.. */
691
692
static u_long get_word(struct vc_data *vc)
693
{
694
	u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos;
695
	char ch;
696
	u_short attr_ch;
697
	spk_old_attr = spk_attr;
698
	ch = (char) get_char(vc, (u_short *) tmp_pos);
699
700
/* decided to take out the sayword if on a space (mis-information */
701
	if (say_word_ctl && ch == SPACE) {
702
		*buf = '\0';
703
		synth_write_msg("space");
704
		return 0;
705
	} else if ((tmpx < vc->vc_cols - 2)
706
		   && (ch == SPACE || IS_WDLM(ch ))
707
		   && ((char) get_char (vc, (u_short * ) tmp_pos+1 ) > SPACE)) {
708
		tmp_pos += 2;
709
		tmpx++;
710
	} else
711
		while (tmpx > 0 ) {
712
			ch = (char) get_char(vc, (u_short *) tmp_pos - 1);
713
			if ((ch == SPACE || IS_WDLM(ch))
714
			    && ((char) get_char(vc, (u_short *) tmp_pos) > SPACE))
715
				break;
716
			tmp_pos -= 2;
717
			tmpx--;
718
		}
719
	attr_ch = get_char(vc, (u_short *) tmp_pos);
720
	spk_attr = attr_ch >> 8;
721
	buf[cnt++] = attr_ch & 0xff;
722
	while (tmpx < vc->vc_cols - 1) {
723
		tmp_pos += 2;
724
		tmpx++;
725
		ch = (char) get_char(vc, (u_short *) tmp_pos);
726
		if ((ch == SPACE) || (IS_WDLM(buf[cnt-1]) && (ch > SPACE)))
727
			break;
728
		buf[cnt++] = ch;
729
	}
730
	buf[cnt] = '\0';
731
	return cnt;
732
}
733
734
static void say_word(struct vc_data *vc)
735
{
736
	u_long cnt = get_word(vc );
737
	u_short saved_punc_mask = punc_mask;
738
	if (cnt == 0)
739
		return;
740
	punc_mask = PUNC;
741
	buf[cnt++] = SPACE;
742
	spkup_write(buf, cnt);
743
	punc_mask = saved_punc_mask;
744
}
745
746
static void say_prev_word(struct vc_data *vc)
747
{
748
	char ch;
749
	u_short edge_said = 0, last_state = 0, state = 0;
750
	spk_parked |= 0x01;
751
	if (spk_x == 0) {
752
		if (spk_y == 0) {
753
			announce_edge(vc, edge_top);
754
			return;
755
		}
756
		spk_y--;
757
		spk_x = vc->vc_cols;
758
		edge_said = edge_quiet;
759
	}
760
	while (1) {
761
		if (spk_x == 0) {
762
			if (spk_y == 0) {
763
				edge_said = edge_top;
764
				break;
765
			}
766
			if (edge_said != edge_quiet)
767
				edge_said = edge_left;
768
			if (state > 0)
769
				break;
770
			spk_y--;
771
			spk_x = vc->vc_cols - 1;
772
		} else spk_x--;
773
			spk_pos -= 2;
774
		ch = (char) get_char(vc, (u_short *) spk_pos);
775
		if (ch == SPACE)
776
			state = 0;
777
		else if (IS_WDLM(ch))
778
			state = 1;
779
		else state = 2;
780
		if (state < last_state) {
781
			spk_pos += 2;
782
			spk_x++;
783
			break;
784
		}
785
		last_state = state;
786
	}
787
	if (spk_x == 0 && edge_said == edge_quiet)
788
		edge_said = edge_left;
789
	if (edge_said > 0 && edge_said < edge_quiet)
790
		announce_edge(vc, edge_said);
791
	say_word(vc);
792
}
793
794
static void say_next_word(struct vc_data *vc)
795
{
796
	char ch;
797
	u_short edge_said = 0, last_state = 2, state = 0;
798
	spk_parked |= 0x01;
799
	if (spk_x == vc->vc_cols - 1 && spk_y == vc->vc_rows - 1) {
800
		announce_edge(vc, edge_bottom);
801
		return;
802
	}
803
	while (1) {
804
		ch = (char) get_char(vc, (u_short *) spk_pos );
805
		if (ch == SPACE)
806
			state = 0;
807
		else if (IS_WDLM(ch))
808
			state = 1;
809
		else state = 2;
810
		if (state > last_state) break;
811
		if (spk_x >= vc->vc_cols - 1) {
812
			if (spk_y == vc->vc_rows - 1) {
813
				edge_said = edge_bottom;
814
				break;
815
			}
816
			state = 0;
817
			spk_y++;
818
			spk_x = 0;
819
			edge_said = edge_right;
820
		} else spk_x++;
821
			spk_pos += 2;
822
		last_state = state;
823
	}
824
	if (edge_said > 0)
825
		announce_edge(vc, edge_said);
826
	say_word(vc);
827
}
828
829
static void spell_word(struct vc_data *vc)
830
{
831
	static char *delay_str[] = { " ", ", ", ". ", ". . ", ". . . " };
832
	char *cp = buf, *str_cap = str_caps_stop;
833
	char *cp1, *last_cap = str_caps_stop;
834
	u_char ch;
835
	if (!get_word(vc))
836
		return;
837
	while ((ch = (u_char) *cp)) {
838
		if (cp != buf)
839
			synth_write_string(delay_str[spell_delay]);
840
		if (IS_CHAR(ch, B_CAP)) {
841
			str_cap = str_caps_start;
842
			if (*str_caps_stop)
843
				pitch_shift++;
844
			else /* synth has no pitch */
845
				last_cap = str_caps_stop;
846
		} else
847
			str_cap = str_caps_stop;
848
		if (str_cap != last_cap) {
849
			synth_write_string(str_cap);
850
			last_cap = str_cap;
851
		}
852
		if (this_speakup_key == SPELL_PHONETIC
853
		    && (IS_CHAR(ch, B_ALPHA))) {
854
			ch &= 31;
855
			cp1 = phonetic[--ch];
856
		} else {
857
			cp1 = characters[ch];
858
			if (*cp1 == '^') {
859
				synth_write_string(str_ctl);
860
				cp1++;
861
			}
862
		}
863
		synth_write_string(cp1);
864
		cp++;
865
	}
866
	if (str_cap != str_caps_stop)
867
		synth_write_string(str_caps_stop);
868
}
869
870
static int get_line(struct vc_data *vc)
871
{
872
	u_long tmp = spk_pos - (spk_x * 2);
873
	int i = 0;
874
	spk_old_attr = spk_attr;
875
	spk_attr = get_attributes((u_short *) spk_pos);
876
	for (i = 0; i < vc->vc_cols; i++) {
877
		buf[i] = (u_char) get_char(vc, (u_short *) tmp);
878
		tmp += 2;
879
	}
880
	for (--i; i >= 0; i--)
881
		if (buf[i] != SPACE)
882
			break;
883
	return ++i;
884
}
885
886
static void say_line(struct vc_data *vc)
887
{
888
	int i = get_line(vc);
889
	char *cp;
890
	char num_buf[8];
891
	u_short saved_punc_mask = punc_mask;
892
	if (i == 0) {
893
		synth_write_msg(blank_msg);
894
		return;
895
	}
896
	buf[i++] = '\n';
897
	if (this_speakup_key == SAY_LINE_INDENT) {
898
		for (cp = buf; *cp == SPACE; cp++)
899
			;
900
		sprintf(num_buf, "%d, ", (cp - buf) + 1);
901
		synth_write_string(num_buf);
902
	}
903
	punc_mask = punc_masks[reading_punc];
904
	spkup_write(buf, i);
905
	punc_mask = saved_punc_mask;
906
}
907
908
static void say_prev_line(struct vc_data *vc)
909
{
910
	spk_parked |= 0x01;
911
	if (spk_y == 0) {
912
		announce_edge(vc, edge_top);
913
		return;
914
	}
915
	spk_y--;
916
	spk_pos -= vc->vc_size_row;
917
	say_line(vc);
918
}
919
920
static void say_next_line(struct vc_data *vc)
921
{
922
	spk_parked |= 0x01;
923
	if (spk_y == vc->vc_rows - 1) {
924
		announce_edge(vc, edge_bottom);
925
		return;
926
	}
927
	spk_y++;
928
	spk_pos += vc->vc_size_row;
929
	say_line(vc);
930
}
931
932
static int say_from_to(struct vc_data *vc, u_long from, u_long to,
933
		       int read_punc)
934
{
935
	int i = 0;
936
	u_short saved_punc_mask = punc_mask;
937
	spk_old_attr = spk_attr;
938
	spk_attr = get_attributes((u_short *) from);
939
	while (from < to) {
940
		buf[i++] = (char) get_char(vc, (u_short *) from);
941
		from += 2;
942
		if (i >= vc->vc_size_row)
943
			break;
944
	}
945
	for (--i; i >= 0; i--)
946
		if (buf[i] != SPACE)
947
			break;
948
	buf[++i] = SPACE;
949
	buf[++i] = '\0';
950
	if (i < 1)
951
		return i;
952
	if (read_punc)
953
		punc_mask = punc_info[reading_punc].mask;
954
	spkup_write(buf, i);
955
	if (read_punc)
956
		punc_mask = saved_punc_mask;
957
	return i - 1;
958
}
959
960
static void say_line_from_to(struct vc_data *vc, u_long from, u_long to,
961
			     int read_punc)
962
{
963
	u_long start = vc->vc_origin + (spk_y * vc->vc_size_row);
964
	u_long end = start + (to * 2);
965
	start += from * 2;
966
	if (say_from_to(vc, start, end, read_punc) <= 0)
967
		if (cursor_track != read_all_mode)
968
			synth_write_msg(blank_msg);
969
}
970
971
// Sentence Reading Commands
972
973
void synth_insert_next_index(int);
974
975
static int currsentence;
976
static int numsentences[2];
977
static char *sentbufend[2];
978
static char *sentmarks[2][10];
979
static int currbuf=0;
980
static int bn;
981
static char sentbuf[2][256];
982
983
static int say_sentence_num(int num , int prev)
984
{
985
	bn = currbuf;
986
	currsentence = num + 1;
987
	if (prev && --bn == -1)
988
		bn = 1;
989
990
	if (num > numsentences[bn])
991
		return 0;
992
993
	spkup_write(sentmarks[bn][num], sentbufend[bn] - sentmarks[bn][num]);
994
	return 1;
995
}
996
997
static int get_sentence_buf(struct vc_data *vc, int read_punc)
998
{
999
	u_long start, end;
1000
	int i, bn;
1001
	currbuf++;
1002
	if (currbuf == 2)
1003
		currbuf = 0;
1004
	bn = currbuf;
1005
	start = vc->vc_origin + ((spk_y) *vc->vc_size_row);
1006
	end = vc->vc_origin+((spk_y) *vc->vc_size_row) + vc->vc_cols * 2;
1007
1008
	numsentences[bn] = 0;
1009
	sentmarks[bn][0] = &sentbuf[bn][0];
1010
	i = 0;
1011
	spk_old_attr = spk_attr;
1012
	spk_attr = get_attributes((u_short *) start);
1013
1014
	while (start < end) {
1015
		sentbuf[bn][i] = (char) get_char(vc, (u_short *) start);
1016
		if (i > 0) {
1017
			if (sentbuf[bn][i] == SPACE && sentbuf[bn][i-1] == '.'
1018
			    && numsentences[bn] < 9) {
1019
				// Sentence Marker
1020
				numsentences[bn]++;
1021
				sentmarks[bn][numsentences[bn]] =
1022
					&sentbuf[bn][i];
1023
			}
1024
		}
1025
		i++;
1026
		start += 2;
1027
		if (i >= vc->vc_size_row)
1028
			break;
1029
	}
1030
1031
	for (--i; i >= 0; i--)
1032
		if (sentbuf[bn][i] != SPACE)
1033
			break;
1034
1035
	if (i < 1)
1036
		return -1;
1037
1038
	sentbuf[bn][++i] = SPACE;
1039
	sentbuf[bn][++i] = '\0';
1040
1041
	sentbufend[bn] = &sentbuf[bn][i];
1042
	return numsentences[bn];
1043
}
1044
1045
static void say_screen_from_to(struct vc_data *vc, u_long from, u_long to)
1046
{
1047
	u_long start = vc->vc_origin, end;
1048
	if (from > 0)
1049
		start += from * vc->vc_size_row;
1050
	if (to > vc->vc_rows)
1051
		to = vc->vc_rows;
1052
	end = vc->vc_origin + (to * vc->vc_size_row);
1053
	for (from = start; from < end; from = to) {
1054
		to = from + vc->vc_size_row;
1055
		say_from_to(vc, from, to, 1);
1056
	}
1057
}
1058
1059
static void say_screen(struct vc_data *vc)
1060
{
1061
	say_screen_from_to(vc, 0, vc->vc_rows);
1062
}
1063
1064
static void speakup_win_say(struct vc_data *vc)
1065
{
1066
	u_long start, end, from, to;
1067
	if (win_start < 2) {
1068
		synth_write_msg("no window");
1069
		return;
1070
	}
1071
	start = vc->vc_origin + (win_top * vc->vc_size_row);
1072
	end = vc->vc_origin + (win_bottom * vc->vc_size_row);
1073
	while (start <= end) {
1074
		from = start + (win_left * 2);
1075
		to = start + (win_right * 2);
1076
		say_from_to(vc, from, to, 1);
1077
		start += vc->vc_size_row;
1078
	}
1079
}
1080
1081
static void top_edge (struct vc_data *vc)
1082
{
1083
	spk_parked |= 0x01;
1084
	spk_pos = vc->vc_origin + 2 * spk_x;
1085
	spk_y = 0;
1086
	say_line(vc);
1087
}
1088
1089
static void bottom_edge(struct vc_data *vc)
1090
{
1091
	spk_parked |= 0x01;
1092
	spk_pos += (vc->vc_rows - spk_y - 1) * vc->vc_size_row;
1093
	spk_y = vc->vc_rows - 1;
1094
	say_line(vc);
1095
}
1096
1097
static void left_edge(struct vc_data *vc)
1098
{
1099
	spk_parked |= 0x01;
1100
	spk_pos -= spk_x * 2;
1101
	spk_x = 0;
1102
	say_char (vc );
1103
}
1104
1105
static void right_edge(struct vc_data *vc)
1106
{
1107
	spk_parked |= 0x01;
1108
	spk_pos += (vc->vc_cols - spk_x - 1) * 2;
1109
	spk_x = vc->vc_cols - 1;
1110
	say_char(vc);
1111
}
1112
1113
static void say_first_char(struct vc_data *vc)
1114
{
1115
	int i, len = get_line(vc);
1116
	u_char ch;
1117
	spk_parked |= 0x01;
1118
	if (len == 0) {
1119
		synth_write_msg(blank_msg);
1120
		return;
1121
	}
1122
	for (i = 0; i < len; i++)
1123
		if (buf[i] != SPACE)
1124
			break;
1125
	ch = buf[i];
1126
	spk_pos -= (spk_x - i) * 2;
1127
	spk_x = i;
1128
	sprintf(buf, "%d, ", ++i);
1129
	synth_write_string(buf);
1130
	speak_char(ch);
1131
}
1132
1133
static void say_last_char(struct vc_data *vc)
1134
{
1135
	int len = get_line(vc);
1136
	u_char ch;
1137
	spk_parked |= 0x01;
1138
	if (len == 0) {
1139
		synth_write_msg(blank_msg);
1140
		return;
1141
	}
1142
	ch = buf[--len];
1143
	spk_pos -= (spk_x - len) * 2;
1144
	spk_x = len;
1145
	sprintf (buf, "%d, ", ++len);
1146
	synth_write_string(buf);
1147
	speak_char(ch);
1148
}
1149
1150
static void say_position(struct vc_data *vc)
1151
{
1152
	sprintf(buf, "line %ld, col %ld, t t y %d\n", spk_y + 1, spk_x + 1,
1153
		vc->vc_num + 1);
1154
	synth_write_string(buf);
1155
}
1156
1157
// Added by brianb
1158
static void say_char_num(struct vc_data *vc)
1159
{
1160
	u_short ch = get_char(vc, (u_short *) spk_pos);
1161
	ch &= 0xff;
1162
	sprintf(buf, "hex %02x, decimal %d", ch, ch);
1163
	synth_write_msg(buf);
1164
}
1165
1166
/* these are stub functions to keep keyboard.c happy. */
1167
1168
static void say_from_top(struct vc_data *vc)
1169
{
1170
	say_screen_from_to(vc, 0, spk_y);
1171
}
1172
1173
static void say_to_bottom(struct vc_data *vc)
1174
{
1175
	say_screen_from_to(vc, spk_y, vc->vc_rows);
1176
}
1177
1178
static void say_from_left(struct vc_data *vc)
1179
{
1180
	say_line_from_to(vc, 0, spk_x, 1);
1181
}
1182
1183
static void say_to_right(struct vc_data *vc)
1184
{
1185
	say_line_from_to(vc, spk_x, vc->vc_cols, 1);
1186
}
1187
1188
/* end of stub functions. */
1189
1190
static void spkup_write(const char *in_buf, int count)
1191
{
1192
	static int rep_count = 0;
1193
	static u_char ch = '\0', old_ch = '\0';
1194
	static u_short char_type = 0, last_type = 0;
1195
	static u_char *exn_ptr = NULL;
1196
	int in_count = count;
1197
	char rpt_buf[32];
1198
	spk_keydown = 0;
1199
	while ( count-- ) {
1200
		if ( cursor_track == read_all_mode ) {
1201
			// Insert Sentence Index
1202
			if (( in_buf == sentmarks[bn][currsentence] ) &&
1203
			   ( currsentence <= numsentences[bn] ))
1204
				synth_insert_next_index(currsentence++);
1205
		}
1206
		ch = (u_char )*in_buf++;
1207
		char_type = spk_chartab[ch];
1208
		if (ch == old_ch && !(char_type&B_NUM ) ) {
1209
			if (++rep_count > 2 ) continue;
1210
		} else {
1211
			if ( (last_type&CH_RPT) && rep_count > 2 ) {
1212
				sprintf (rpt_buf, " times %d . ", ++rep_count );
1213
				synth_write_string (rpt_buf );
1214
			}
1215
			rep_count = 0;
1216
		}
1217
		if ( !( char_type&B_NUM ) )
1218
				exn_ptr = NULL;
1219
		if (ch == spk_lastkey ) {
1220
			rep_count = 0;
1221
			if ( key_echo == 1 && ch >= MINECHOCHAR )
1222
				speak_char( ch );
1223
		} else if ( ( char_type&B_ALPHA ) ) {
1224
			if ( (synth_flags&SF_DEC) && (last_type&PUNC) )
1225
				synth_buffer_add ( SPACE );
1226
			synth_write( &ch, 1 );
1227
		} else if ( ( char_type&B_NUM ) ) {
1228
			rep_count = 0;
1229
			if ( (last_type&B_EXNUM) && synth_buff_in == exn_ptr+1 ) {
1230
				synth_buff_in--;
1231
				synth_buffer_add( old_ch );
1232
				exn_ptr = NULL;
1233
			}
1234
			synth_write( &ch, 1 );
1235
		} else if ( (char_type&punc_mask) ) {
1236
			speak_char( ch );
1237
			char_type &= ~PUNC; /* for dec nospell processing */
1238
		} else if ( ( char_type&SYNTH_OK ) ) {
1239
/* these are usually puncts like . and , which synth needs for expression.
1240
 * suppress multiple to get rid of long pausesand clear repeat count so if
1241
 *someone has repeats on you don't get nothing repeated count */
1242
			if ( ch != old_ch )
1243
				synth_write( &ch, 1 );
1244
			else rep_count = 0;
1245
		} else {
1246
			if ( ( char_type&B_EXNUM ) )
1247
					exn_ptr = (u_char *)synth_buff_in;
1248
/* send space and record position, if next is num overwrite space */
1249
			if ( old_ch != ch ) synth_buffer_add ( SPACE );
1250
			else rep_count = 0;
1251
		}
1252
		old_ch = ch;
1253
		last_type = char_type;
1254
	}
1255
	spk_lastkey = 0;
1256
	if (in_count > 2 && rep_count > 2 ) {
1257
		if ( (last_type&CH_RPT) ) {
1258
			sprintf (rpt_buf, " repeated %d . ", ++rep_count );
1259
			synth_write_string (rpt_buf );
1260
		}
1261
		rep_count = 0;
1262
	}
1263
}
1264
1265
static char *ctl_key_ids[] = {
1266
	"shift", "altgr", "control", "ault", "l shift", "speakup",
1267
"l control", "r control"
1268
};
1269
#define NUM_CTL_LABELS 8
1270
1271
static void read_all_doc(struct vc_data *vc);
1272
static void cursor_stop_timer(void);
1273
1274
static void handle_shift(struct vc_data *vc, u_char value, char up_flag)
1275
{
1276
	(*do_shift)(vc, value, up_flag);
1277
	if (synth == NULL || up_flag || spk_killed)
1278
		return;
1279
	if (cursor_track == read_all_mode) {
1280
		switch (value) {
1281
		case KVAL(K_SHIFT):
1282
			cursor_stop_timer();
1283
			spk_shut_up &= 0xfe;
1284
			do_flush();
1285
			read_all_doc(vc);
1286
			break;
1287
		case KVAL(K_CTRL):
1288
			cursor_stop_timer();
1289
			cursor_track=prev_cursor_track;
1290
			spk_shut_up &= 0xfe;
1291
			do_flush();
1292
			break;
1293
		}
1294
	} else {
1295
		spk_shut_up &= 0xfe;
1296
		do_flush();
1297
	}
1298
	if (say_ctrl && value < NUM_CTL_LABELS)
1299
		synth_write_string(ctl_key_ids[value]);
1300
}
1301
1302
static void handle_latin(struct vc_data *vc, u_char value, char up_flag)
1303
{
1304
	(*do_latin)(vc, value, up_flag);
1305
	if (up_flag) {
1306
		spk_lastkey = spk_keydown = 0;
1307
		return;
1308
	}
1309
	if (synth == NULL || spk_killed)
1310
		return;
1311
	spk_shut_up &= 0xfe;
1312
	spk_lastkey = value;
1313
	spk_keydown++;
1314
	spk_parked &= 0xfe;
1315
	if (key_echo == 2 && value >= MINECHOCHAR)
1316
		speak_char( value );
1317
}
1318
1319
static int set_key_info(const u_char *key_info, u_char *k_buffer)
1320
{
1321
	int i = 0, states, key_data_len;
1322
	const u_char *cp = key_info;
1323
	u_char *cp1 = k_buffer;
1324
	u_char ch, version, num_keys;
1325
	version = *cp++;
1326
	if (version != KEY_MAP_VER)
1327
		return -1;
1328
	num_keys = *cp;
1329
	states = (int) cp[1];
1330
	key_data_len = (states + 1) * (num_keys + 1);
1331
	if (key_data_len + SHIFT_TBL_SIZE + 4 >= sizeof(key_buf))
1332
		return -2;
1333
	memset(k_buffer, 0, SHIFT_TBL_SIZE);
1334
	memset(our_keys, 0, sizeof(our_keys));
1335
	shift_table = k_buffer;
1336
	our_keys[0] = shift_table;
1337
	cp1 += SHIFT_TBL_SIZE;
1338
	memcpy(cp1, cp, key_data_len + 3);
1339
	/* get num_keys, states and data*/
1340
	cp1 += 2; /* now pointing at shift states */
1341
	for (i = 1; i <= states; i++) {
1342
		ch = *cp1++;
1343
		if (ch >= SHIFT_TBL_SIZE)
1344
			return -3;
1345
		shift_table[ch] = i;
1346
	}
1347
	keymap_flags = *cp1++;
1348
	while ((ch = *cp1)) {
1349
		if (ch >= MAX_KEY)
1350
			return -4;
1351
		our_keys[ch] = cp1;
1352
		cp1 += states + 1;
1353
	}
1354
	return 0;
1355
}
1356
1357
static struct st_num_var spk_num_vars[] = { /* bell must be first to set high limit */
1358
	{ BELL_POS, 0, 0, 0, 0, 0, 0, 0 },
1359
	{ SPELL_DELAY, 0, 0, 0, 5, 0, 0, 0 },
1360
	{ ATTRIB_BLEEP, 0, 1, 0, 3, 0, 0, 0 },
1361
	{ BLEEPS, 0, 3, 0, 3, 0, 0, 0 },
1362
	{ BLEEP_TIME, 0, 30, 1, 200, 0, 0, 0 },
1363
	{ PUNC_LEVEL, 0, 1, 0, 4, 0, 0, 0 },
1364
	{ READING_PUNC, 0, 1, 0, 4, 0, 0, 0 },
1365
	{ CURSOR_TIME, 0, 120, 50, 600, 0, 0, 0 },
1366
	{ SAY_CONTROL, TOGGLE_0 },
1367
	{ SAY_WORD_CTL, TOGGLE_0 },
1368
	{ NO_INTERRUPT, TOGGLE_0 },
1369
	{ KEY_ECHO, 0, 1, 0, 2, 0, 0, 0 },
1370
	V_LAST_NUM
1371
};
1372
1373
static char *cursor_msgs[] = { "cursoring off", "cursoring on",
1374
	"highlight tracking", "read windo",
1375
"read all" };
1376
1377
static void toggle_cursoring(struct vc_data *vc)
1378
{
1379
	if (cursor_track == read_all_mode)
1380
		cursor_track = prev_cursor_track;
1381
	if (++cursor_track >= CT_Max)
1382
		cursor_track = 0;
1383
	synth_write_msg(cursor_msgs[cursor_track]);
1384
}
1385
1386
static void reset_default_chars(void)
1387
{
1388
	int i;
1389
	if (default_chars[(int )'a'] == NULL) /* lowers are null first time */
1390
		for (i = (int )'a'; default_chars[i] == NULL; i++)
1391
			default_chars[i] = default_chars[i - 32];
1392
	else /* free any non-default */
1393
		for (i = 0; i < 256; i++) {
1394
			if (characters[i] != default_chars[i])
1395
				kfree(characters[i]);
1396
		}
1397
	memcpy(characters, default_chars, sizeof(default_chars));
1398
}
1399
1400
static void reset_default_chartab(void)
1401
{
1402
	memcpy(spk_chartab, default_chartab, sizeof(default_chartab));
1403
}
1404
1405
static void handle_cursor(struct vc_data *vc, u_char value, char up_flag);
1406
static void handle_spec(struct vc_data *vc, u_char value, char up_flag);
1407
static void cursor_done(u_long data );
1408
1409
static declare_timer(cursor_timer);
1410
1411
static void __init speakup_open(struct vc_data *vc,
1412
				struct st_spk_t *first_console)
1413
{
1414
	int i;
1415
	struct st_num_var *n_var;
1416
1417
	reset_default_chars();
1418
	reset_default_chartab();
1419
	memset(speakup_console, 0, sizeof(speakup_console));
1420
	if (first_console == NULL)
1421
		return;
1422
	speakup_console[vc->vc_num] = first_console;
1423
	speakup_date(vc);
1424
	pr_info("%s: initialized\n", SPEAKUP_VERSION);
1425
	init_timer(&cursor_timer);
1426
	cursor_timer.entry.prev = NULL;
1427
	cursor_timer.function = cursor_done;
1428
	init_sleeper(synth_sleeping_list);
1429
	strlwr(synth_name);
1430
 	spk_num_vars[0].high = vc->vc_cols;
1431
	for (n_var = spk_num_vars; n_var->var_id >= 0; n_var++)
1432
		speakup_register_var(n_var);
1433
	for (i = 1; punc_info[i].mask != 0; i++)
1434
		set_mask_bits(0, i, 2);
1435
	do_latin = key_handler[KT_LATIN];
1436
	key_handler[KT_LATIN] = handle_latin;
1437
	do_spec = key_handler[KT_SPEC];
1438
	key_handler[KT_SPEC] = handle_spec;
1439
	do_cursor = key_handler[KT_CUR];
1440
	key_handler[KT_CUR] = handle_cursor;
1441
	do_shift = key_handler[KT_SHIFT];
1442
	key_handler[KT_SHIFT] = handle_shift;
1443
	set_key_info(key_defaults, key_buf);
1444
	if (quiet_boot) spk_shut_up |= 0x01;
1445
}
1446
1447
#ifdef CONFIG_PROC_FS
1448
1449
// speakup /proc interface code
1450
1451
/* Usage:
1452
cat /proc/speakup/version
1453
1454
cat /proc/speakup/characters > foo
1455
less /proc/speakup/characters
1456
vi /proc/speakup/characters
1457
1458
cat foo > /proc/speakup/characters
1459
cat > /proc/speakup/characters
1460
echo 39 apostrophe > /proc/speakup/characters
1461
echo 87 w > /proc/speakup/characters
1462
echo 119 w > /proc/speakup/characters
1463
echo defaults > /proc/speakup/characters
1464
echo reset > /proc/speakup/characters
1465
1466
1467
cat /proc/speakup/chartab > foo
1468
less /proc/speakup/chartab
1469
vi /proc/speakup/chartab
1470
1471
cat foo > /proc/speakup/chartab
1472
cat > /proc/speakup/chartab
1473
echo 233 ALPHA > /proc/speakup/chartab
1474
echo 46 A_PUNC > /proc/speakup/chartab
1475
echo defaults > /proc/speakup/chartab
1476
echo reset > /proc/speakup/chartab
1477
*/
1478
1479
// keymap handlers
1480
1481
static int keys_read_proc(char *page, char **start, off_t off, int count,
1482
			  int *eof, void *data)
1483
{
1484
	char *cp = page;
1485
	int i, n, num_keys, nstates;
1486
	u_char *cp1 = key_buf + SHIFT_TBL_SIZE, ch;
1487
	num_keys = (int)(*cp1);
1488
	nstates = (int)cp1[1];
1489
	cp += sprintf( cp, "%d, %d, %d,\n", KEY_MAP_VER,  num_keys, nstates );
1490
	cp1 += 2; /* now pointing at shift states */
1491
/* dump num_keys+1 as first row is shift states + flags,
1492
   each subsequent row is key + states */
1493
	for ( n = 0; n <= num_keys; n++ ) {
1494
		for ( i = 0; i <= nstates; i++ ) {
1495
			ch = *cp1++;
1496
			cp += sprintf( cp, "%d,", (int)ch );
1497
			*cp++ = ( i < nstates ) ? SPACE : '\n';
1498
		}
1499
	}
1500
	cp += sprintf( cp, "0, %d\n", KEY_MAP_VER );
1501
	*start = 0;
1502
	*eof = 1;
1503
	return (int)(cp-page);
1504
}
1505
1506
static char *
1507
s2uchar ( char *start, char *dest )
1508
{
1509
	int val = 0;
1510
	while ( *start && *start <= SPACE ) start++;
1511
	while ( *start >= '0' && *start <= '9' ) {
1512
		val *= 10;
1513
		val += ( *start ) - '0';
1514
		start++;
1515
	}
1516
	if ( *start == ',' ) start++;
1517
	*dest = (u_char)val;
1518
	return start;
1519
}
1520
1521
static int keys_write_proc(struct file *file, const char *buffer, u_long count,
1522
			   void *data)
1523
{
1524
	int i, ret = count;
1525
	char *in_buff, *cp;
1526
	u_char *cp1;
1527
	if (count < 1 || count > 1800 )
1528
		return -EINVAL;
1529
	in_buff = ( char * ) __get_free_page ( GFP_KERNEL );
1530
	if ( !in_buff ) return -ENOMEM;
1531
	if (copy_from_user (in_buff, buffer, count ) ) {
1532
		free_page ( ( unsigned long ) in_buff );
1533
		return -EFAULT;
1534
	}
1535
	if (in_buff[count - 1] == '\n' ) count--;
1536
	in_buff[count] = '\0';
1537
	if ( count == 1 && *in_buff == 'd' ) {
1538
		free_page ( ( unsigned long ) in_buff );
1539
		set_key_info( key_defaults, key_buf );
1540
		return ret;
1541
	}
1542
	cp = in_buff;
1543
	cp1 = (u_char *)in_buff;
1544
	for ( i = 0; i < 3; i++ ) {
1545
		cp = s2uchar( cp, cp1 );
1546
		cp1++;
1547
	}
1548
	i = (int)cp1[-2]+1;
1549
	i *= (int)cp1[-1]+1;
1550
	i+= 2; /* 0 and last map ver */
1551
	if ( cp1[-3] != KEY_MAP_VER || cp1[-1] > 10 ||
1552
			i+SHIFT_TBL_SIZE+4 >= sizeof(key_buf ) ) {
1553
pr_warn( "i %d %d %d %d\n", i, (int)cp1[-3], (int)cp1[-2], (int)cp1[-1] );
1554
		free_page ( ( unsigned long ) in_buff );
1555
		return -EINVAL;
1556
	}
1557
	while ( --i >= 0 ) {
1558
		cp = s2uchar( cp, cp1 );
1559
		cp1++;
1560
		if ( !(*cp) ) break;
1561
	}
1562
	if ( i != 0 || cp1[-1] != KEY_MAP_VER || cp1[-2] != 0 ) {
1563
		ret = -EINVAL;
1564
pr_warn( "end %d %d %d %d\n", i, (int)cp1[-3], (int)cp1[-2], (int)cp1[-1] );
1565
	} else {
1566
		if ( set_key_info( in_buff, key_buf ) ) {
1567
			set_key_info( key_defaults, key_buf );
1568
		ret = -EINVAL;
1569
pr_warn( "set key failed\n" );
1570
		}
1571
	}
1572
	free_page ( ( unsigned long ) in_buff );
1573
	return ret;
1574
}
1575
1576
// this is the handler for /proc/speakup/version
1577
static int version_read_proc(char *page, char **start, off_t off, int count,
1578
			     int *eof, void *data)
1579
{
1580
	int len = sprintf (page, "%s\n", SPEAKUP_VERSION );
1581
	if (synth != NULL)
1582
		len += sprintf(page+len, "synth %s version %s\n", synth->name,
1583
			synth->version);
1584
	*start = 0;
1585
	*eof = 1;
1586
	return len;
1587
}
1588
1589
// this is the read handler for /proc/speakup/characters
1590
static int chars_read_proc(char *page, char **start, off_t off, int count,
1591
			   int *eof, void *data)
1592
{
1593
	int i, len = 0;
1594
	off_t begin = 0;
1595
	char *cp;
1596
	for (i = 0; i < 256; i++) {
1597
		cp = (characters[i]) ? characters[i] : "NULL";
1598
		len += sprintf(page + len, "%d\t%s\n", i, cp);
1599
		if (len + begin > off + count)
1600
			break;
1601
		if (len + begin < off) {
1602
			begin += len;
1603
			len = 0;
1604
		}
1605
	}
1606
	if (i >= 256)
1607
		*eof = 1;
1608
	if (off >= len + begin)
1609
		return 0;
1610
	*start = page + (off - begin);
1611
	return ((count < begin + len - off) ? count : begin + len - off);
1612
}
1613
1614
static volatile int chars_timer_active = 0;	// indicates when timer is set
1615
static declare_timer(chars_timer);
1616
1617
static void chars_stop_timer(void)
1618
{
1619
	if (chars_timer_active)
1620
		stop_timer(chars_timer);
1621
}
1622
1623
static int strings, rejects, updates;
1624
1625
static void show_char_results (u_long data)
1626
{
1627
	int len;
1628
	char buf[80];
1629
	chars_stop_timer();
1630
	len = sprintf(buf, " updated %d of %d character descriptions\n",
1631
		       updates, strings);
1632
	if (rejects)
1633
		sprintf(buf + (len - 1), " with %d reject%s\n",
1634
			 rejects, rejects > 1 ? "s" : "");
1635
	printk(buf);
1636
}
1637
1638
// this is the read handler for /proc/speakup/chartab
1639
static int chartab_read_proc(char *page, char **start, off_t off, int count,
1640
			     int *eof, void *data)
1641
{
1642
	int i, len = 0;
1643
	off_t begin = 0;
1644
	char *cp;
1645
	for (i = 0; i < 256; i++) {	  
1646
		cp = "0";
1647
		if (IS_TYPE(i, B_CTL))
1648
			cp = "B_CTL";
1649
		else if (IS_TYPE(i, WDLM))
1650
			cp = "WDLM";
1651
		else if (IS_TYPE(i, A_PUNC))
1652
			cp = "A_PUNC";
1653
		else if (IS_TYPE(i, PUNC))
1654
			cp = "PUNC";
1655
		else if (IS_TYPE(i, NUM))
1656
			cp = "NUM";
1657
		else if (IS_TYPE(i, A_CAP))
1658
			cp = "A_CAP";
1659
		else if (IS_TYPE(i, ALPHA))
1660
			cp = "ALPHA";
1661
		else if (IS_TYPE(i, B_CAPSYM))
1662
			cp = "B_CAPSYM";
1663
		else if (IS_TYPE(i, B_SYM))
1664
			cp = "B_SYM";
1665
1666
		len += sprintf(page + len, "%d\t%s\n", i, cp);
1667
		if (len + begin > off + count)
1668
			break;
1669
		if (len + begin < off) {
1670
			begin += len;
1671
			len = 0;
1672
		}
1673
	}
1674
	if (i >= 256)
1675
		*eof = 1;
1676
	if (off >= len + begin)
1677
		return 0;
1678
	*start = page + (off - begin);
1679
	return ((count < begin + len - off) ? count : begin + len - off);
1680
}
1681
1682
static int chartab_get_value(char *keyword)
1683
{
1684
	int value = 0;
1685
	
1686
	if (!strcmp(keyword, "ALPHA"))
1687
		value = ALPHA;
1688
	else if (!strcmp(keyword, "B_CTL"))
1689
		value = B_CTL;
1690
	else if (!strcmp(keyword, "WDLM"))
1691
		value = WDLM;
1692
	else if (!strcmp(keyword, "A_PUNC"))
1693
		value = A_PUNC;
1694
	else if (!strcmp(keyword, "PUNC"))
1695
		value = PUNC;
1696
	else if (!strcmp(keyword, "NUM"))
1697
		value = NUM;
1698
	else if (!strcmp(keyword, "A_CAP"))
1699
		value = A_CAP;
1700
	else if (!strcmp(keyword, "B_CAPSYM"))
1701
		value = B_CAPSYM;
1702
	else if (!strcmp(keyword, "B_SYM"))
1703
		value = B_SYM;
1704
	return value;
1705
}
1706
1707
/* this is the write handler for /proc/speakup/silent */
1708
static int silent_write_proc(struct file *file, const char *buffer,
1709
			     u_long count, void *data)
1710
{
1711
	struct vc_data *vc = vc_cons[fg_console].d;
1712
	char ch = 0, shut;
1713
	if (count > 0 || count < 3 ) {
1714
		get_user (ch, buffer );
1715
		if ( ch == '\n' ) ch = '0';
1716
	}
1717
	if ( ch < '0' || ch > '7' ) {
1718
		pr_warn ( "silent value not in range (0,7)\n" );
1719
		return count;
1720
	}
1721
	if ( (ch&2) ) {
1722
		shut = 1;
1723
		do_flush( );
1724
	} else shut = 0;
1725
	if ( (ch&4) ) shut |= 0x40;
1726
	if ( (ch&1) )
1727
		spk_shut_up |= shut;
1728
		else spk_shut_up &= ~shut;
1729
	return count;
1730
}
1731
1732
// this is the write handler for /proc/speakup/characters
1733
static int chars_write_proc(struct file *file, const char *buffer,
1734
			    u_long count, void *data)
1735
{
1736
#define max_desc_len 72
1737
	static int cnt = 0, state = 0;
1738
	static char desc[max_desc_len + 1];
1739
	static u_long jiff_last = 0;
1740
	short i = 0, num;
1741
	int len;
1742
	char ch, *cp, *p_new;
1743
	// reset certain vars if enough time has elapsed since last called
1744
	if (jiffies - jiff_last > 10 ) {
1745
		cnt = state = strings = rejects = updates = 0;
1746
	}
1747
	jiff_last = jiffies;
1748
get_more:
1749
	desc[cnt] = '\0';
1750
	state = 0;
1751
	for (; i < count && state < 2; i++ ) {
1752
		get_user (ch, buffer + i );
1753
		if ( ch == '\n' ) {
1754
			desc[cnt] = '\0';
1755
			state = 2;
1756
		} else if (cnt < max_desc_len )
1757
			desc[cnt++] = ch;
1758
	}
1759
	if (state < 2 ) return count;
1760
	cp = desc;
1761
	while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++;
1762
	if ((!cnt ) || strchr ("dDrR", *cp ) ) {
1763
		reset_default_chars ( );
1764
		pr_info( "character descriptions reset to defaults\n" );
1765
		cnt = 0;
1766
		return count;
1767
	}
1768
	cnt = 0;
1769
	if (*cp == '#' ) goto get_more;
1770
	num = -1;
1771
	cp = speakup_s2i(cp, &num );
1772
	while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++;
1773
	if (num < 0 || num > 255 ) {	// not in range
1774
		rejects++;
1775
		strings++;
1776
		goto get_more;
1777
	}
1778
	if (num >= 27 && num <= 31 ) goto get_more;
1779
	if (!strcmp(cp, characters[num] ) ) {
1780
		strings++;
1781
		goto get_more;
1782
	}
1783
	len = strlen(cp );
1784
	if (characters[num] == default_chars[num] )
1785
		p_new = kmalloc(sizeof (char) * len+1, GFP_KERNEL );
1786
	else if ( strlen(characters[num] ) >= len )
1787
		p_new = characters[num];
1788
	else {
1789
		kfree(characters[num] );
1790
		characters[num] = default_chars[num];
1791
		p_new = kmalloc(sizeof (char) * len+1, GFP_KERNEL );
1792
	}
1793
	if (!p_new ) return -ENOMEM;
1794
	strcpy ( p_new, cp );
1795
	characters[num] = p_new;
1796
	updates++;
1797
	strings++;
1798
	if (i < count ) goto get_more;
1799
	chars_stop_timer ( );
1800
	init_timer (&chars_timer );
1801
	chars_timer.function = show_char_results;
1802
	chars_timer.expires = jiffies + 5;
1803
		start_timer (chars_timer );
1804
	chars_timer_active++;
1805
	return count;
1806
}
1807
1808
// this is the write handler for /proc/speakup/chartab
1809
static int chartab_write_proc(struct file *file, const char *buffer,
1810
			      u_long count, void *data)
1811
{
1812
#define max_desc_len 72
1813
	static int cnt = 0, state = 0;
1814
	static char desc[max_desc_len + 1];
1815
	static u_long jiff_last = 0;
1816
	short i = 0, num;
1817
	char ch, *cp;
1818
	int value=0;
1819
	// reset certain vars if enough time has elapsed since last called
1820
	if (jiffies - jiff_last > 10 ) {
1821
		cnt = state = strings = rejects = updates = 0;
1822
	}
1823
	jiff_last = jiffies;
1824
get_more:
1825
	desc[cnt] = '\0';
1826
	state = 0;
1827
	for (; i < count && state < 2; i++ ) {
1828
		get_user (ch, buffer + i );
1829
		if ( ch == '\n' ) {
1830
			desc[cnt] = '\0';
1831
			state = 2;
1832
		} else if (cnt < max_desc_len )
1833
			desc[cnt++] = ch;
1834
	}
1835
	if (state < 2 ) return count;
1836
	cp = desc;
1837
	while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++;
1838
	if ((!cnt ) || strchr ("dDrR", *cp ) ) {
1839
		reset_default_chartab ( );
1840
		pr_info( "character descriptions reset to defaults\n" );
1841
		cnt = 0;
1842
		return count;
1843
	}
1844
	cnt = 0;
1845
	if (*cp == '#' ) goto get_more;
1846
	num = -1;
1847
	cp = speakup_s2i(cp, &num );
1848
	while ( *cp && (unsigned char)(*cp) <= SPACE ) cp++;
1849
	if (num < 0 || num > 255 ) {	// not in range
1850
		rejects++;
1851
		strings++;
1852
		goto get_more;
1853
	}
1854
	/*	if (num >= 27 && num <= 31 ) goto get_more; */
1855
1856
	value = chartab_get_value (cp);
1857
	if (!value) {	// not in range
1858
		rejects++;
1859
		strings++;
1860
		goto get_more;
1861
	}
1862
1863
	if (value==spk_chartab[num]) {
1864
		strings++;
1865
		goto get_more;
1866
	}
1867
1868
	spk_chartab[num] = value;
1869
	updates++;
1870
	strings++;
1871
	if (i < count ) goto get_more;
1872
	chars_stop_timer ( );
1873
	init_timer (&chars_timer );
1874
	chars_timer.function = show_char_results;
1875
	chars_timer.expires = jiffies + 5;
1876
		start_timer (chars_timer );
1877
	chars_timer_active++;
1878
	return count;
1879
}
1880
1881
static int bits_read_proc(char *page, char **start, off_t off, int count,
1882
			  int *eof, void *data)
1883
{
1884
	int i;
1885
	struct st_var_header *p_header = data;
1886
	struct st_proc_var *var = p_header->data;
1887
	const struct st_bits_data *pb = &punc_info[var->value];
1888
	short mask = pb->mask;
1889
	char *cp = page;
1890
	*start = 0;
1891
	*eof = 1;
1892
	for ( i = 33; i < 128; i++ ) {
1893
		if ( !(spk_chartab[i]&mask ) ) continue;
1894
		*cp++ = (char )i;
1895
	}
1896
	*cp++ = '\n';
1897
	return cp-page;
1898
}
1899
1900
/* set_mask_bits sets or clears the punc/delim/repeat bits,
1901
 * if input is null uses the defaults.
1902
 * values for how: 0 clears bits of chars supplied,
1903
 * 1 clears allk, 2 sets bits for chars */
1904
1905
static int set_mask_bits(const char *input, const int which, const int how)
1906
{
1907
	u_char *cp;
1908
	short mask = punc_info[which].mask;
1909
	if ( how&1 ) {
1910
		for ( cp = (u_char * )punc_info[3].value; *cp; cp++ )
1911
			spk_chartab[*cp] &= ~mask;
1912
	}
1913
	cp = (u_char * )input;
1914
	if ( cp == 0 ) cp = punc_info[which].value;
1915
	else {
1916
		for ( ; *cp; cp++ ) {
1917
			if ( *cp < SPACE ) break;
1918
			if ( mask < PUNC ) {
1919
				if ( !(spk_chartab[*cp]&PUNC) ) break;
1920
			} else if ( (spk_chartab[*cp]&B_NUM) ) break;
1921
		}
1922
		if ( *cp ) return -EINVAL;
1923
		cp = (u_char * )input;
1924
	}
1925
	if ( how&2 ) {
1926
		for ( ; *cp; cp++ )
1927
			if ( *cp > SPACE ) spk_chartab[*cp] |= mask;
1928
	} else {
1929
		for ( ; *cp; cp++ )
1930
			if ( *cp > SPACE ) spk_chartab[*cp] &= ~mask;
1931
	}
1932
	return 0;
1933
}
1934
1935
static const struct st_bits_data *pb_edit = NULL;
1936
1937
static int edit_bits (struct vc_data *vc, u_char type, u_char ch, u_short key )
1938
{
1939
	short mask = pb_edit->mask, ch_type = spk_chartab[ch];
1940
	if ( type != KT_LATIN || (ch_type&B_NUM ) || ch < SPACE ) return -1;
1941
	if ( ch == SPACE ) {
1942
		synth_write_msg( "edit done" );
1943
		special_handler = NULL;
1944
		return 1;
1945
	}
1946
	if ( mask < PUNC && !(ch_type&PUNC) ) return -1;
1947
	spk_chartab[ch] ^= mask;
1948
	speak_char( ch );
1949
	synth_write_msg( (spk_chartab[ch]&mask ) ? " on" : " off" );
1950
	return 1;
1951
}
1952
1953
static int bits_write_proc(struct file *file, const char *buffer, u_long count,
1954
			   void *data)
1955
{
1956
	struct st_var_header *p_header = data;
1957
	struct st_proc_var *var = p_header->data;
1958
	int ret = count;
1959
	char punc_buf[100];
1960
	if (count < 1 || count > 99 )
1961
		return -EINVAL;
1962
	if (copy_from_user (punc_buf, buffer, count ) )
1963
		return -EFAULT;
1964
	if (punc_buf[count - 1] == '\n' )
1965
		count--;
1966
	punc_buf[count] = '\0';
1967
	if ( *punc_buf == 'd' || *punc_buf == 'r' )
1968
		count = set_mask_bits( 0, var->value, 3 );
1969
	else
1970
		count = set_mask_bits( punc_buf, var->value, 3 );
1971
	if ( count < 0 ) return count;
1972
	return ret;
1973
}
1974
1975
// this is the read handler for /proc/speakup/synth
1976
static int synth_read_proc(char *page, char **start, off_t off, int count,
1977
			   int *eof, void *data)
1978
{
1979
	int len;
1980
	if ( synth == NULL ) strcpy( synth_name, "none" );
1981
	else strcpy( synth_name, synth->name );
1982
	len = sprintf (page, "%s\n", synth_name );
1983
	*start = 0;
1984
	*eof = 1;
1985
	return len;
1986
}
1987
1988
// this is the write handler for /proc/speakup/synth
1989
static int synth_write_proc(struct file *file, const char *buffer,
1990
			    u_long count, void *data)
1991
{
1992
	int ret = count;
1993
	char new_synth_name[10];
1994
	const char *old_name = ( synth != NULL ) ? synth->name : "none";
1995
	if (count < 2 || count > 9 )
1996
		return -EINVAL;
1997
	if (copy_from_user (new_synth_name, buffer, count ) )
1998
		return -EFAULT;
1999
	if (new_synth_name[count - 1] == '\n' )
2000
		count--;
2001
	new_synth_name[count] = '\0';
2002
	strlwr (new_synth_name );
2003
	if (!strcmp (new_synth_name, old_name ) ) {
2004
		pr_warn ( "%s already in use\n", new_synth_name );
2005
		return ret;
2006
	}
2007
	if ( synth_init( new_synth_name ) == 0 ) return ret;
2008
	pr_warn( "failed to init synth %s\n", new_synth_name );
2009
	return -ENODEV;
2010
}
2011
2012
struct st_proc_var spk_proc_vars[] = {
2013
	 { VERSION, version_read_proc, 0, 0 },
2014
	 { SILENT, 0, silent_write_proc, 0 },
2015
	 { CHARS, chars_read_proc, chars_write_proc, 0 },
2016
	 { SYNTH, synth_read_proc, synth_write_proc, 0 },
2017
	 { KEYMAP, keys_read_proc, keys_write_proc, 0 },
2018
	 { PUNC_SOME, bits_read_proc, bits_write_proc, 1 },
2019
	 { PUNC_MOST, bits_read_proc, bits_write_proc, 2 },
2020
	 { PUNC_ALL, bits_read_proc, 0, 3 },
2021
	 { DELIM, bits_read_proc, bits_write_proc, 4 },
2022
	 { REPEATS, bits_read_proc, bits_write_proc, 5 },
2023
	 { EXNUMBER, bits_read_proc, bits_write_proc, 6 },
2024
	 { CHARTAB, chartab_read_proc, chartab_write_proc, 0 },
2025
	{ -1, 0, 0, 0 }
2026
};
2027
2028
#endif // CONFIG_PROC_FS
2029
2030
void __init speakup_init(struct vc_data *vc)
2031
{
2032
	struct st_spk_t *first_console =
2033
		alloc_bootmem(sizeof(struct st_spk_t) + 1);
2034
	memset( first_console, 0, sizeof(struct st_spk_t));
2035
	speakup_open(vc, first_console);
2036
}
2037
2038
void speakup_allocate(struct vc_data *vc)
2039
{
2040
	int vc_num;
2041
2042
	vc_num = vc->vc_num;
2043
	if ( speakup_console[vc_num] == NULL ) {
2044
		speakup_console[vc_num] = kzalloc(sizeof(struct st_spk_t) + 1,
2045
			GFP_KERNEL);
2046
		if (speakup_console[vc_num] == NULL)
2047
			return;
2048
		speakup_date( vc);
2049
	} else if ( !spk_parked ) speakup_date( vc);
2050
}
2051
2052
static u_char is_cursor = 0;
2053
static u_long old_cursor_pos, old_cursor_x, old_cursor_y;
2054
static int cursor_con;
2055
static int cursor_timer_active = 0;
2056
2057
static void cursor_stop_timer(void)
2058
{
2059
  if (!cursor_timer_active ) return;
2060
		stop_timer ( cursor_timer );
2061
	cursor_timer_active = 0;
2062
}
2063
2064
static void reset_highlight_buffers( struct vc_data * );
2065
2066
//extern void kbd_fakekey(unsigned int);
2067
extern struct input_dev *fakekeydev;
2068
2069
static int read_all_key;
2070
2071
void reset_index_count(int);
2072
void get_index_count(int *, int *);
2073
//int synth_supports_indexing(void);
2074
static void start_read_all_timer( struct vc_data *vc, int command );
2075
2076
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};
2077
2078
static void
2079
kbd_fakekey2(struct vc_data *vc,int v,int command)
2080
{
2081
	cursor_stop_timer();
2082
        (*do_cursor)( vc,v,0);
2083
        (*do_cursor)( vc,v,1);
2084
	start_read_all_timer(vc,command);
2085
}
2086
2087
static void
2088
read_all_doc( struct vc_data *vc)
2089
{
2090
	if ( synth == NULL || spk_shut_up || (vc->vc_num != fg_console ) )
2091
		return;
2092
	if (!synth_supports_indexing())
2093
		return;
2094
	if (cursor_track!=read_all_mode)
2095
		prev_cursor_track=cursor_track;
2096
	cursor_track=read_all_mode;
2097
	reset_index_count(0);
2098
	if (get_sentence_buf(vc,0)==-1)
2099
		kbd_fakekey2(vc,0,RA_DOWN_ARROW);
2100
	else {
2101
		say_sentence_num(0,0);
2102
		synth_insert_next_index(0);
2103
		start_read_all_timer(vc,RA_TIMER);
2104
	}
2105
}
2106
2107
static void
2108
stop_read_all( struct vc_data *vc)
2109
{
2110
	cursor_stop_timer( );
2111
	cursor_track=prev_cursor_track;
2112
	spk_shut_up &= 0xfe;
2113
	do_flush();
2114
}
2115
2116
static void
2117
start_read_all_timer( struct vc_data *vc, int command )
2118
{
2119
	cursor_con = vc->vc_num;
2120
	cursor_timer.expires = jiffies + cursor_timeout;
2121
	read_all_key=command;
2122
	start_timer (cursor_timer );
2123
	cursor_timer_active++;
2124
}
2125
2126
static void
2127
handle_cursor_read_all( struct vc_data *vc,int command )
2128
{
2129
	int indcount,sentcount,rv,sn;
2130
2131
	switch (command)
2132
	{
2133
		case RA_NEXT_SENT:
2134
			// Get Current Sentence
2135
			get_index_count(&indcount,&sentcount);
2136
			//printk("%d %d  ",indcount,sentcount);
2137
			reset_index_count(sentcount+1);
2138
			if (indcount==1)
2139
			{
2140
				if (!say_sentence_num(sentcount+1,0))
2141
				{
2142
					kbd_fakekey2(vc,0,RA_FIND_NEXT_SENT);
2143
					return;
2144
				}
2145
				synth_insert_next_index(0);
2146
			}
2147
			else
2148
			{
2149
				sn=0;
2150
				if (!say_sentence_num(sentcount+1,1))
2151
				{
2152
					sn=1;
2153
					reset_index_count(sn);
2154
				}
2155
				else
2156
					synth_insert_next_index(0);
2157
				if (!say_sentence_num(sn,0))
2158
				{
2159
					kbd_fakekey2(vc,0,RA_FIND_NEXT_SENT);
2160
					return;
2161
				}
2162
				synth_insert_next_index(0);
2163
			}
2164
			start_read_all_timer(vc,RA_TIMER);
2165
			break;
2166
		case RA_PREV_SENT:
2167
			break;
2168
		case RA_NEXT_LINE:
2169
			read_all_doc(vc);
2170
			break;
2171
		case RA_PREV_LINE:
2172
			break;
2173
		case RA_DOWN_ARROW:
2174
			if (get_sentence_buf(vc,0)==-1)
2175
			{
2176
				kbd_fakekey2(vc,0,RA_DOWN_ARROW);
2177
			}
2178
			else
2179
			{
2180
				say_sentence_num(0,0);
2181
				synth_insert_next_index(0);
2182
				start_read_all_timer(vc,RA_TIMER);
2183
			}
2184
			break;
2185
		case RA_FIND_NEXT_SENT:
2186
			rv=get_sentence_buf(vc,0);
2187
			if (rv==-1)
2188
			{
2189
				read_all_doc(vc);
2190
			}
2191
			if (rv==0)
2192
			{
2193
				kbd_fakekey2(vc,0,RA_FIND_NEXT_SENT);
2194
			}
2195
			else
2196
			{
2197
				say_sentence_num(1,0);
2198
				synth_insert_next_index(0);
2199
				start_read_all_timer(vc,RA_TIMER);
2200
			}
2201
			break;
2202
		case RA_FIND_PREV_SENT:
2203
			break;
2204
		case RA_TIMER:
2205
			get_index_count(&indcount,&sentcount);
2206
			if (indcount<2)
2207
			{
2208
				kbd_fakekey2(vc,0,RA_DOWN_ARROW);
2209
			}
2210
			else
2211
			{
2212
				start_read_all_timer(vc,RA_TIMER);
2213
			}
2214
			break;
2215
	}
2216
}
2217
2218
static void handle_cursor(struct vc_data *vc, u_char value, char up_flag)
2219
{
2220
	if (cursor_track == read_all_mode)
2221
	{
2222
		spk_parked &= 0xfe;
2223
		if ( synth == NULL || up_flag || spk_shut_up )
2224
			return;
2225
		cursor_stop_timer();
2226
		spk_shut_up &= 0xfe;
2227
		do_flush();
2228
		start_read_all_timer(vc,value+1);
2229
		return;
2230
	}
2231
	(*do_cursor)(vc, value, up_flag);
2232
	spk_parked &= 0xfe;
2233
	if ( synth == NULL || up_flag || spk_shut_up || cursor_track == CT_Off )
2234
	  return;
2235
	spk_shut_up &= 0xfe;
2236
	if ( no_intr ) do_flush( );
2237
/* the key press flushes if !no_inter but we want to flush on cursor
2238
 * moves regardless of no_inter state */
2239
	is_cursor = value+1;
2240
	old_cursor_pos = vc->vc_pos;
2241
	old_cursor_x = vc->vc_x;
2242
	old_cursor_y = vc->vc_y;
2243
	speakup_console[vc->vc_num]->ht.cy=vc->vc_y;
2244
	cursor_con = vc->vc_num;
2245
	cursor_stop_timer( );
2246
	cursor_timer.expires = jiffies + cursor_timeout;
2247
	if ( cursor_track == CT_Highlight)
2248
		reset_highlight_buffers( vc );
2249
	read_all_key=value+1;
2250
	start_timer (cursor_timer );
2251
	cursor_timer_active++;
2252
}
2253
2254
static void
2255
update_color_buffer( struct vc_data *vc , const char *ic , int len )
2256
{
2257
	int i,bi,hi;
2258
	int vc_num=vc->vc_num;
2259
	
2260
	bi = ( (vc->vc_attr & 0x70) >> 4 ) ;
2261
	hi=speakup_console[vc_num]->ht.highsize[bi];
2262
	
2263
	i=0;
2264
	if (speakup_console[vc_num]->ht.highsize[bi]==0)
2265
	{
2266
		speakup_console[vc_num]->ht.rpos[bi]=vc->vc_pos;
2267
		speakup_console[vc_num]->ht.rx[bi]=vc->vc_x;
2268
		speakup_console[vc_num]->ht.ry[bi]=vc->vc_y;
2269
	}
2270
	while (( hi<COLOR_BUFFER_SIZE ) && ( i < len ))
2271
	{
2272
		if (( ic[i]>32 ) && ( ic[i]<127 ))
2273
		{
2274
			speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
2275
			hi++;
2276
		}
2277
		else if (( ic[i] == 32 ) && ( hi != 0 ))
2278
		{
2279
			if (speakup_console[vc_num]->ht.highbuf[bi][hi-1]!=32)
2280
			{
2281
				speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
2282
				hi++;
2283
			}
2284
		}
2285
		i++;
2286
	}
2287
	speakup_console[vc_num]->ht.highsize[bi]=hi;
2288
}
2289
2290
static void
2291
reset_highlight_buffers( struct vc_data *vc )
2292
{
2293
	int i;
2294
	int vc_num=vc->vc_num;
2295
	for ( i=0 ; i<8 ; i++ )
2296
		speakup_console[vc_num]->ht.highsize[i]=0;
2297
}
2298
2299
static int
2300
count_highlight_color(struct vc_data *vc)
2301
{
2302
	int i,bg;
2303
	int cc;
2304
	int vc_num=vc->vc_num;
2305
	u16 ch;
2306
	u16 *start = (u16 *) vc->vc_origin;
2307
2308
	for ( i=0 ; i<8 ; i++ )
2309
		speakup_console[vc_num]->ht.bgcount[i]=0;		
2310
2311
	for ( i=0 ; i<vc->vc_rows; i++ ) {
2312
		u16 *end = start + vc->vc_cols*2;
2313
		u16 *ptr;
2314
		for ( ptr=start ; ptr<end ; ptr++) {
2315
			ch = get_attributes( ptr );
2316
			bg = ( ch & 0x70 ) >> 4;
2317
			speakup_console[vc_num]->ht.bgcount[bg]++;
2318
		}
2319
		start += vc->vc_size_row;
2320
	}
2321
2322
	cc=0;
2323
	for ( i=0 ; i<8 ; i++ )
2324
		if (speakup_console[vc_num]->ht.bgcount[i]>0)
2325
			cc++;		
2326
	return cc;
2327
}
2328
2329
static int
2330
get_highlight_color( struct vc_data *vc )
2331
{
2332
	int i,j;
2333
	unsigned int cptr[8],tmp;
2334
	int vc_num=vc->vc_num;
2335
2336
	for ( i=0 ; i<8 ; i++ )
2337
		cptr[i]=i;
2338
2339
	for ( i=0 ; i<7 ; i++ )
2340
		for ( j=i+1 ; j<8 ; j++ )
2341
			if ( speakup_console[vc_num]->ht.bgcount[cptr[i]] > speakup_console[vc_num]->ht.bgcount[cptr[j]]) {
2342
				tmp=cptr[i];
2343
				cptr[i]=cptr[j];
2344
				cptr[j]=tmp;
2345
			}
2346
2347
	for ( i=0; i<8; i++ )
2348
		if ( speakup_console[vc_num]->ht.bgcount[cptr[i]] != 0)
2349
			if ( speakup_console[vc_num]->ht.highsize[cptr[i]] > 0)
2350
			{
2351
				return cptr[i];
2352
			}
2353
	return -1;
2354
}
2355
2356
static int
2357
speak_highlight( struct vc_data *vc )
2358
{
2359
	int hc,d;
2360
	int vc_num=vc->vc_num;
2361
	if (count_highlight_color( vc )==1)
2362
		return 0;
2363
	hc=get_highlight_color( vc );
2364
	if ( hc != -1 )
2365
	{
2366
		d=vc->vc_y-speakup_console[vc_num]->ht.cy;
2367
		if ((d==1)||(d==-1))
2368
		{
2369
			if (speakup_console[vc_num]->ht.ry[hc]!=vc->vc_y)
2370
				return 0;
2371
		}
2372
		spk_parked |= 0x01;
2373
		do_flush();
2374
		spkup_write (speakup_console[vc_num]->ht.highbuf[hc] , speakup_console[vc_num]->ht.highsize[hc] );
2375
		spk_pos=spk_cp=speakup_console[vc_num]->ht.rpos[hc];		
2376
		spk_x=spk_cx=speakup_console[vc_num]->ht.rx[hc];		
2377
		spk_y=spk_cy=speakup_console[vc_num]->ht.ry[hc];		
2378
		return 1;
2379
	}
2380
	return 0;
2381
}
2382
2383
static void
2384
cursor_done (u_long data )
2385
{
2386
	struct vc_data *vc = vc_cons[cursor_con].d;
2387
	cursor_stop_timer( );
2388
	if (cursor_con != fg_console ) {
2389
		is_cursor = 0;
2390
		return;
2391
	}
2392
	speakup_date (vc );
2393
	if ( win_enabled ) {
2394
		if ( vc->vc_x >= win_left && vc->vc_x <= win_right &&
2395
		vc->vc_y >= win_top && vc->vc_y <= win_bottom ) {
2396
			spk_keydown = is_cursor = 0;
2397
			return;
2398
		}
2399
	}
2400
	if ( cursor_track == read_all_mode ) {
2401
		handle_cursor_read_all(vc,read_all_key);
2402
		return;
2403
	}
2404
	if ( cursor_track == CT_Highlight) {
2405
		if ( speak_highlight( vc )) {
2406
			spk_keydown = is_cursor = 0;
2407
			return;
2408
		}
2409
	}
2410
	if ( cursor_track == CT_Window) {
2411
		speakup_win_say (vc);
2412
	} else if ( is_cursor == 1 || is_cursor == 4 )
2413
		say_line_from_to (vc, 0, vc->vc_cols, 0 );
2414
	else
2415
		say_char ( vc );
2416
	spk_keydown = is_cursor = 0;
2417
}
2418
2419
/* These functions are the interface to speakup from the actual kernel code. */
2420
2421
void
2422
speakup_bs (struct vc_data *vc )
2423
{
2424
	if (!spk_parked )
2425
		speakup_date (vc );
2426
	if ( spk_shut_up || synth == NULL ) return;
2427
	if ( vc->vc_num == fg_console  && spk_keydown ) {
2428
		spk_keydown = 0;
2429
		if (!is_cursor ) say_char (vc );
2430
	}
2431
}
2432
2433
void
2434
speakup_con_write (struct vc_data *vc, const char *str, int len )
2435
{
2436
	if (spk_shut_up || (vc->vc_num != fg_console ) )
2437
		return;
2438
	if (bell_pos && spk_keydown && (vc->vc_x == bell_pos - 1 ) )
2439
		bleep(3 );
2440
	if (synth == NULL) return;
2441
	if ((is_cursor)||(cursor_track == read_all_mode )) {
2442
		if (cursor_track == CT_Highlight )
2443
			update_color_buffer( vc, str, len);
2444
		return;
2445
	}
2446
	if ( win_enabled ) {
2447
		if ( vc->vc_x >= win_left && vc->vc_x <= win_right &&
2448
		vc->vc_y >= win_top && vc->vc_y <= win_bottom ) return;
2449
	}
2450
2451
	spkup_write (str, len );
2452
}
2453
2454
void
2455
speakup_con_update (struct vc_data *vc )
2456
{
2457
	if ( speakup_console[vc->vc_num] == NULL || spk_parked )
2458
		return;
2459
	speakup_date (vc );
2460
}
2461
2462
static void handle_spec(struct vc_data *vc, u_char value, char up_flag)
2463
{
2464
	int on_off = 2;
2465
	char *label;
2466
	static const char *lock_status[] = { " off", " on", "" };
2467
	(*do_spec)(vc, value, up_flag);
2468
	if ( synth == NULL || up_flag || spk_killed ) return;
2469
	spk_shut_up &= 0xfe;
2470
	if ( no_intr ) do_flush( );
2471
	switch (value ) {
2472
		case KVAL( K_CAPS ):
2473
			label = "caps lock";
2474
			on_off =  (vc_kbd_led(kbd , VC_CAPSLOCK ) );
2475
			break;
2476
		case KVAL( K_NUM ):
2477
			label = "num lock";
2478
			on_off = (vc_kbd_led(kbd , VC_NUMLOCK ) );
2479
			break;
2480
		case KVAL( K_HOLD ):
2481
			label = "scroll lock";
2482
			on_off = (vc_kbd_led(kbd , VC_SCROLLOCK ) );
2483
			break;
2484
	default:
2485
		spk_parked &= 0xfe;
2486
		return;
2487
	}
2488
	synth_write_string ( label );
2489
	synth_write_msg ( lock_status[on_off] );
2490
}
2491
2492
static int
2493
inc_dec_var( u_char value )
2494
{
2495
	struct st_var_header *p_header;
2496
	struct st_num_var *var_data;
2497
	char num_buf[32];
2498
	char *cp = num_buf, *pn;
2499
	int var_id = (int)value - VAR_START;
2500
	int how = (var_id&1) ? E_INC : E_DEC;
2501
	var_id = var_id/2+FIRST_SET_VAR;
2502
	p_header = get_var_header( var_id );
2503
	if ( p_header == NULL ) return -1;
2504
	if ( p_header->var_type != VAR_NUM ) return -1;
2505
	var_data = p_header->data;
2506
	if ( set_num_var( 1, p_header, how ) != 0 )
2507
		return -1;
2508
	if ( !spk_close_press ) {
2509
		for ( pn = p_header->name; *pn; pn++ ) {
2510
			if ( *pn == '_' ) *cp = SPACE;
2511
			else *cp++ = *pn;
2512
		}
2513
	}
2514
	sprintf( cp, " %d ", (int)var_data->value );
2515
	synth_write_string( num_buf );
2516
	return 0;
2517
}
2518
2519
static void
2520
speakup_win_set (struct vc_data *vc )
2521
{
2522
	char info[40];
2523
	if ( win_start > 1 ) {
2524
		synth_write_msg( "window already set, clear then reset" );
2525
		return;
2526
	}
2527
	if ( spk_x < win_left || spk_y < win_top ) {
2528
		synth_write_msg( "error end before start" );
2529
		return;
2530
	}
2531
	if ( win_start && spk_x == win_left && spk_y == win_top ) {
2532
		win_left = 0;
2533
		win_right = vc->vc_cols-1;
2534
		win_bottom = spk_y;
2535
		sprintf( info, "window is line %d", (int)win_top+1 );
2536
	} else {
2537
		if ( !win_start ) {
2538
			win_top = spk_y;
2539
			win_left = spk_x;
2540
		} else {
2541
			win_bottom = spk_y;
2542
			win_right = spk_x;
2543
		}
2544
		sprintf( info, "%s at line %d, column %d",
2545
			(win_start) ? "end" : "start",
2546
			(int)spk_y+1, (int)spk_x+1 );
2547
	}
2548
	synth_write_msg( info );
2549
	win_start++;
2550
}
2551
2552
static void
2553
speakup_win_clear (struct vc_data *vc )
2554
{
2555
	win_top = win_bottom = 0;
2556
	win_left = win_right = 0;
2557
	win_start = 0;
2558
	synth_write_msg( "window cleared" );
2559
}
2560
2561
static void
2562
speakup_win_enable (struct vc_data *vc )
2563
{
2564
	if ( win_start < 2 ) {
2565
		synth_write_msg( "no window" );
2566
		return;
2567
	}
2568
	win_enabled ^= 1;
2569
	if ( win_enabled ) synth_write_msg( "window silenced" );
2570
	else synth_write_msg( "window silence disabled" );
2571
}
2572
2573
static void
2574
speakup_bits (struct vc_data *vc )
2575
{
2576
	int val = this_speakup_key - ( FIRST_EDIT_BITS - 1 );
2577
	if ( special_handler != NULL || val < 1 || val > 6 ) {
2578
		synth_write_msg( "error" );
2579
		return;
2580
	}
2581
	pb_edit = &punc_info[val];
2582
	sprintf( buf, "edit  %s, press space when done", pb_edit->name );
2583
	synth_write_msg( buf );
2584
	special_handler = edit_bits;
2585
}
2586
2587
static int handle_goto (struct vc_data *vc, u_char type, u_char ch, u_short key )
2588
{
2589
	static u_char *goto_buf = "\0\0\0\0\0\0";
2590
	static int num = 0;
2591
	short maxlen, go_pos;
2592
	char *cp;
2593
	if ( type == KT_SPKUP && ch == SPEAKUP_GOTO ) goto do_goto;
2594
	if ( type == KT_LATIN && ch == '\n' ) goto do_goto;
2595
	if ( type != 0 ) goto oops;
2596
	if (ch == 8 ) {
2597
		if ( num == 0 ) return -1;
2598
		ch = goto_buf[--num];
2599
		goto_buf[num] = '\0';
2600
		spkup_write( &ch, 1 );
2601
		return 1;
2602
}
2603
	if ( ch < '+' || ch > 'y' ) goto oops;
2604
	goto_buf[num++] = ch;
2605
	goto_buf[num] = '\0';
2606
	spkup_write( &ch, 1 );
2607
	maxlen = ( *goto_buf >= '0' ) ? 3 : 4;
2608
	if ((ch == '+' || ch == '-' ) && num == 1 ) return 1;
2609
	if (ch >= '0' && ch <= '9' && num < maxlen ) return 1;
2610
	if ( num < maxlen-1 || num > maxlen ) goto oops;
2611
	if ( ch < 'x' || ch > 'y' ) {
2612
oops:
2613
		if (!spk_killed )
2614
			synth_write_msg (" goto canceled" );
2615
		goto_buf[num = 0] = '\0';
2616
		special_handler = NULL;
2617
		return 1;
2618
	}
2619
	cp = speakup_s2i (goto_buf, &go_pos );
2620
	goto_pos = (u_long)go_pos;
2621
	if (*cp == 'x' ) {
2622
		if (*goto_buf < '0' ) goto_pos += spk_x;
2623
		else goto_pos--;
2624
		if (goto_pos < 0 ) goto_pos = 0;
2625
		if (goto_pos >= vc->vc_cols )
2626
			goto_pos = vc->vc_cols-1;
2627
		goto_x = 1;
2628
	} else {
2629
		if (*goto_buf < '0' ) goto_pos += spk_y;
2630
		else goto_pos--;
2631
		if (goto_pos < 0 ) goto_pos = 0;
2632
	if (goto_pos >= vc->vc_rows ) goto_pos = vc->vc_rows-1;
2633
		goto_x = 0;
2634
	}
2635
		goto_buf[num = 0] = '\0';
2636
do_goto:
2637
	special_handler = NULL;
2638
	spk_parked |= 0x01;
2639
	if ( goto_x ) {
2640
		spk_pos -= spk_x * 2;
2641
		spk_x = goto_pos;
2642
		spk_pos += goto_pos * 2;
2643
		say_word( vc );
2644
	} else {
2645
		spk_y = goto_pos;
2646
		spk_pos = vc->vc_origin + ( goto_pos * vc->vc_size_row );
2647
		say_line( vc );
2648
	}
2649
	return 1;
2650
}
2651
2652
static void
2653
speakup_goto (struct vc_data *vc )
2654
{
2655
	if ( special_handler != NULL ) {
2656
		synth_write_msg( "error" );
2657
		return;
2658
	}
2659
	synth_write_msg( "go to?" );
2660
	special_handler = handle_goto;
2661
	return;
2662
}
2663
2664
static void
2665
load_help ( struct work_struct *dummy )
2666
{
2667
	request_module( "speakup_keyhelp" );
2668
	if ( help_handler ) {
2669
		(*help_handler)(0, KT_SPKUP, SPEAKUP_HELP, 0 );
2670
	} else synth_write_string( "help module not found" );
2671
}
2672
2673
static DECLARE_WORK(ld_help, load_help);
2674
#define schedule_help schedule_work
2675
2676
static void
2677
speakup_help (struct vc_data *vc )
2678
{
2679
	if ( help_handler == NULL ) {
2680
/* we can't call request_module from this context so schedule it*/
2681
/* **** note kernel hangs and my wrath will be on you */
2682
		schedule_help (&ld_help);
2683
		return;
2684
	}
2685
	(*help_handler)(vc, KT_SPKUP, SPEAKUP_HELP, 0 );
2686
}
2687
2688
static void
2689
do_nothing (struct vc_data *vc )
2690
{
2691
	return; /* flush done in do_spkup */
2692
}
2693
static u_char key_speakup = 0, spk_key_locked = 0;
2694
2695
static void
2696
speakup_lock (struct vc_data *vc )
2697
{
2698
	if ( !spk_key_locked )
2699
		spk_key_locked = key_speakup = 16;
2700
	else spk_key_locked = key_speakup = 0;
2701
}
2702
2703
typedef void (*spkup_hand )(struct vc_data * );
2704
spkup_hand spkup_handler[] = { /* must be ordered same as defines in speakup.h */
2705
	do_nothing, speakup_goto, speech_kill, speakup_shut_up,
2706
	speakup_cut, speakup_paste, say_first_char, say_last_char,
2707
	say_char, say_prev_char, say_next_char,
2708
	say_word, say_prev_word, say_next_word,
2709
	say_line, say_prev_line, say_next_line,
2710
	top_edge, bottom_edge, left_edge, right_edge,
2711
	        spell_word, spell_word, say_screen,
2712
	say_position, say_attributes,
2713
	speakup_off, speakup_parked, say_line, // this is for indent
2714
	say_from_top, say_to_bottom,
2715
	say_from_left, say_to_right,
2716
	say_char_num, speakup_bits, speakup_bits, say_phonetic_char,
2717
	speakup_bits, speakup_bits, speakup_bits,
2718
	speakup_win_set, speakup_win_clear, speakup_win_enable, speakup_win_say,
2719
	speakup_lock, speakup_help, toggle_cursoring, read_all_doc,  NULL
2720
};
2721
2722
static void do_spkup( struct vc_data *vc,u_char value )
2723
{
2724
	if (spk_killed && value != SPEECH_KILL ) return;
2725
	spk_keydown = 0;
2726
	spk_lastkey = 0;
2727
	spk_shut_up &= 0xfe;
2728
	this_speakup_key = value;
2729
	if (value < SPKUP_MAX_FUNC && spkup_handler[value] ) {
2730
		do_flush( );
2731
		(*spkup_handler[value] )(vc );
2732
	} else {
2733
		if ( inc_dec_var( value ) < 0 )
2734
			bleep( 9 );
2735
	}
2736
}
2737
2738
	static const char *pad_chars = "0123456789+-*/\015,.?()";
2739
2740
int
2741
speakup_key (struct vc_data *vc, int shift_state, int keycode, u_short keysym, int up_flag)
2742
{
2743
	int kh;
2744
	u_char *key_info;
2745
	u_char type = KTYP( keysym ), value = KVAL( keysym ), new_key = 0;
2746
	u_char shift_info, offset;
2747
	tty = vc->vc_tty;
2748
	if ( synth == NULL ) return 0;
2749
	if ( type >= 0xf0 ) type -= 0xf0;
2750
	if ( type == KT_PAD && (vc_kbd_led(kbd , VC_NUMLOCK ) ) ) {
2751
		if ( up_flag ) {
2752
			spk_keydown = 0;
2753
			return 0;
2754
		}
2755
		value = spk_lastkey = pad_chars[value];
2756
		spk_keydown++;
2757
		spk_parked &= 0xfe;
2758
		goto no_map;
2759
	}
2760
	if ( keycode >= MAX_KEY ) goto no_map;
2761
	if ( ( key_info = our_keys[keycode] ) == 0 ) goto no_map;
2762
	// Check valid read all mode keys
2763
        if ( (cursor_track==read_all_mode) && ( !up_flag ))
2764
	{
2765
                switch (value)
2766
                {
2767
                        case KVAL(K_DOWN):
2768
                        case KVAL(K_UP):
2769
                        case KVAL(K_LEFT):
2770
                        case KVAL(K_RIGHT):
2771
                        case KVAL(K_PGUP):
2772
                        case KVAL(K_PGDN):
2773
                                break;
2774
                        default:
2775
				stop_read_all(vc);
2776
                                break;
2777
                }
2778
	}
2779
	shift_info = ( shift_state&0x0f ) + key_speakup;
2780
	offset = shift_table[shift_info];
2781
	if ( offset && ( new_key = key_info[offset] ) ) {
2782
		if ( new_key == SPK_KEY ) {
2783
			if ( !spk_key_locked )
2784
				key_speakup = ( up_flag ) ? 0 : 16;
2785
			if ( up_flag || spk_killed ) return 1;
2786
			spk_shut_up &= 0xfe;
2787
			do_flush( );
2788
			return 1;
2789
		}
2790
		if ( up_flag ) return 1;
2791
		if ( last_keycode == keycode && last_spk_jiffy+MAX_DELAY > jiffies ) {
2792
			spk_close_press = 1;
2793
			offset = shift_table[shift_info+32];
2794
/* double press? */
2795
			if ( offset && key_info[offset] )
2796
				new_key = key_info[offset];
2797
		}
2798
		last_keycode = keycode;
2799
		last_spk_jiffy = jiffies;
2800
		type = KT_SPKUP;
2801
		value = new_key;
2802
	}
2803
no_map:
2804
	if ( type == KT_SPKUP && special_handler == NULL ) {
2805
		do_spkup( vc, new_key );
2806
		spk_close_press = 0;
2807
		return 1;
2808
	}
2809
	if ( up_flag || spk_killed || type == KT_SHIFT ) return 0;
2810
	spk_shut_up &= 0xfe;
2811
	kh=(value==KVAL(K_DOWN))||(value==KVAL(K_UP))||(value==KVAL(K_LEFT))||(value==KVAL(K_RIGHT));
2812
	if ((cursor_track != read_all_mode) || !kh)
2813
		if (!no_intr ) do_flush( );
2814
	if ( special_handler ) {
2815
		int status;
2816
		if ( type == KT_SPEC && value == 1 ) {
2817
			value = '\n';
2818
			type = KT_LATIN;
2819
		} else if ( type == KT_LETTER ) type = KT_LATIN;
2820
		else if ( value == 0x7f ) value = 8; /* make del = backspace */
2821
		status = (*special_handler)(vc, type, value, keycode );
2822
		spk_close_press = 0;
2823
		if ( status < 0 ) bleep( 9 );
2824
		return status;
2825
	}
2826
	last_keycode = 0;
2827
	return 0;
2828
}
2829
2830
#ifdef MODULE
2831
2832
extern void speakup_remove(void);
2833
extern void speakup_set_addresses ( spk_con_func, spk_con_func, spk_write_func, spk_con_func, spk_key_func);
2834
2835
static void __exit mod_speakup_exit(void)
2836
{
2837
	int i;
2838
2839
	key_handler[KT_LATIN] = do_latin;
2840
	key_handler[KT_SPEC] = do_spec;
2841
	key_handler[KT_CUR] = do_cursor;
2842
	key_handler[KT_SHIFT] = do_shift;
2843
	speakup_set_addresses(NULL, NULL, NULL, NULL, NULL);
2844
	synth_release();
2845
	speakup_remove();
2846
	for(i = 0; i < 256; i++) {
2847
		if (characters[i] != default_chars[i])
2848
			kfree(characters[i]);
2849
	}
2850
	for(i = 0; speakup_console[i]; i++) {
2851
	  kfree(speakup_console[i]);
2852
	  speakup_console[i] = NULL;
2853
	}
2854
}
2855
2856
static int __init mod_speakup_init( void )
2857
{
2858
	int i;
2859
	struct st_spk_t *first_console = kzalloc(sizeof(struct st_spk_t) + 1,
2860
		GFP_KERNEL);
2861
	speakup_open( vc_cons[fg_console].d, first_console );
2862
for ( i = 0; vc_cons[i].d; i++)
2863
  speakup_allocate(vc_cons[i].d);
2864
	speakup_set_addresses( speakup_allocate, speakup_bs,
2865
		speakup_con_write, speakup_con_update, speakup_key );
2866
	speakup_dev_init();
2867
	return 0;
2868
}
2869
2870
module_init( mod_speakup_init );
2871
module_exit( mod_speakup_exit );
2872
2873
#endif
(-)linux-2.6.20/drivers/char/speakup/speakupconf (+51 lines)
Line 0 Link Here
1
#!/bin/sh
2
# script to load/save all the vars in speakup
3
# speakupconf save or speakupconf load
4
# if root saves in /etc/speakup/<synth_name> else in $HOME/.speakup/<synth_name>
5
if [ $UID -eq "0" ]; then
6
  SAVEDIR="/etc/speakup"
7
else
8
  SAVEDIR="$HOME/.speakup"
9
fi
10
if [ ! -d /proc/speakup ]; then
11
  echo "no directory /proc/speakup"
12
  exit 0
13
fi
14
SYNTH=`cat /proc/speakup/synth_name`
15
case "$1" in
16
*save)
17
  if [ ! -d $SAVEDIR ] ; then
18
    echo creating $SAVEDIR
19
    mkdir $SAVEDIR
20
  fi
21
  if [ ! -d $SAVEDIR/$SYNTH ] ; then
22
    echo creating $SAVEDIR/$SYNTH
23
    mkdir $SAVEDIR/$SYNTH
24
  fi
25
  cd /proc/speakup
26
  SAVELIST=`    find . -perm -6 |sed 's/..//' |fgrep -v synth`
27
  for f in $SAVELIST; do
28
    cp $f $SAVEDIR/$SYNTH/$f
29
  done
30
;;
31
*load)
32
  if [ ! -d $SAVEDIR ] ; then
33
    echo no directory $SAVEDIR
34
    exit 1
35
  fi
36
  if [ ! -d $SAVEDIR/$SYNTH ] ; then
37
    echo no directory $SAVEDIR/$SYNTH
38
    exit 1
39
  fi
40
  cd $SAVEDIR/$SYNTH
41
  for f in *; do
42
    if [ -w /proc/speakup/$f ]; then
43
      cat $f >/proc/speakup/$f
44
    fi
45
  done
46
;;
47
*)
48
  echo "usage: speakupconf load/save"
49
  exit 1
50
;;
51
esac
(-)linux-2.6.20/drivers/char/speakup/speakup_decext.c (+206 lines)
Line 0 Link Here
1
/*
2
 * originially written by: Kirk Reiser <kirk@braille.uwo.ca>
3
* this version considerably modified by David Borowski, david575@rogers.com
4
5
		Copyright (C) 1998-99  Kirk Reiser.
6
		Copyright (C) 2003 David Borowski.
7
8
		This program is free software; you can redistribute it and/or modify
9
		it under the terms of the GNU General Public License as published by
10
		the Free Software Foundation; either version 2 of the License, or
11
		(at your option) any later version.
12
13
		This program is distributed in the hope that it will be useful,
14
		but WITHOUT ANY WARRANTY; without even the implied warranty of
15
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
		GNU General Public License for more details.
17
18
		You should have received a copy of the GNU General Public License
19
		along with this program; if not, write to the Free Software
20
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22
 * this code is specificly written as a driver for the speakup screenreview
23
 * package and is not a general device driver.
24
		*/
25
#include "spk_priv.h"
26
#include "serialio.h"
27
28
#define MY_SYNTH synth_decext
29
#define SYNTH_CLEAR 0x03
30
#define PROCSPEECH 0x0b
31
#define synth_full( ) ( inb_p( synth_port_tts ) == 0x13 )
32
33
static int timeouts = 0;
34
static int in_escape = 0;
35
36
static int wait_for_xmitr ( void )
37
{
38
	int check, tmout = SPK_XMITR_TIMEOUT;
39
	if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) {
40
		synth_alive = 0;
41
		timeouts = 0;
42
		return 0;
43
	}
44
	do { /* holding register empty? */
45
		check = inb_p( synth_port_tts + UART_LSR );
46
		if ( --tmout == 0 ) {
47
			pr_warn ( "%s:  timed out\n", synth->long_name );
48
			timeouts++;
49
			return 0;
50
		}
51
	} while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY );
52
	tmout = SPK_XMITR_TIMEOUT;
53
	do { /* CTS */
54
		check = inb_p ( synth_port_tts + UART_MSR );
55
		if ( --tmout == 0 ) {
56
			timeouts++;
57
			return 0;
58
		}
59
	} while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS );
60
	timeouts = 0;
61
	return 1;
62
}
63
64
static int spk_serial_out(const char ch)
65
{
66
	if ( synth_alive && wait_for_xmitr ( ) ) {
67
		outb_p ( ch, synth_port_tts );
68
		return 1;
69
	}
70
	return 0;
71
}
72
73
static u_char
74
spk_serial_in ( void )
75
{
76
	int lsr, tmout = SPK_SERIAL_TIMEOUT, c;
77
	do {
78
		lsr = inb_p ( synth_port_tts + UART_LSR );
79
		if ( --tmout == 0 )
80
			return 0xff;
81
	} while ( !( lsr & UART_LSR_DR ) );
82
	c = inb_p ( synth_port_tts + UART_RX );
83
	return ( u_char ) c;
84
}
85
86
static void do_catch_up( unsigned long data )
87
{
88
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
89
	u_char ch;
90
static u_char last='\0';
91
	synth_stop_timer( );
92
	while ( synth_buff_out < synth_buff_in ) {
93
		ch = *synth_buff_out;
94
		if ( ch == '\n' ) ch = 0x0D;
95
		if ( synth_full( ) || !spk_serial_out( ch ) ) {
96
			synth_delay( synth_full_time );
97
			return;
98
		}
99
		synth_buff_out++;
100
		if ( ch == '[' ) in_escape = 1;
101
		else if ( ch == ']' ) in_escape = 0;
102
		else if ( ch <= SPACE ) {
103
			if ( !in_escape && strchr( ",.!?;:", last ) )
104
				spk_serial_out( PROCSPEECH );
105
			if ( jiffies >= jiff_max ) { 
106
				if ( !in_escape )
107
					spk_serial_out( PROCSPEECH );
108
				synth_delay( synth_delay_time ); 
109
				return; 
110
			}
111
		}
112
		last = ch;
113
	}
114
	if ( synth_done( ) || !in_escape )
115
	spk_serial_out( PROCSPEECH );
116
}
117
118
static const char *synth_immediate ( const char *buf )
119
{
120
	u_char ch;
121
	while ( ( ch = *buf ) ) {
122
	if ( ch == 0x0a ) ch = PROCSPEECH;
123
        if ( wait_for_xmitr( ) )
124
          outb( ch, synth_port_tts );
125
        else return buf;
126
	buf++;
127
	}
128
	return 0;
129
}
130
131
static void synth_flush( void )
132
{
133
	in_escape = 0;
134
	synth_immediate( "\033P;10z\033\\" );
135
}
136
137
static int serprobe( int index )
138
{
139
		u_char test=0;
140
		struct serial_state *ser = spk_serial_init( index );
141
		if ( ser == NULL ) return -1;
142
		/* ignore any error results, if port was forced */
143
	if ( synth_port_forced ) 
144
				return 0;
145
	synth_immediate( "\033[;5n\033\\" );
146
	if ( ( test = spk_serial_in( ) ) == '\033' )
147
		return 0;  
148
	spk_serial_release( );
149
	timeouts = synth_alive = synth_port_tts = 0; /* not ignoring */
150
	return -1;
151
}
152
153
static int synth_probe( void )
154
{
155
	int i=0, failed=0;
156
	pr_info( "Probing for %s.\n", synth->long_name );
157
		/* check ttyS0-ttyS3 */
158
	for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) {
159
	  if (( failed = serprobe( i )) == 0 ) break; /* found it */
160
        }
161
        if ( failed ) {
162
		pr_info( "%s:  not found\n", synth->long_name );
163
		return -ENODEV;
164
	}
165
	pr_info( "%s: %03x-%03x, Driver Version %s,\n", synth->long_name,
166
		synth_port_tts, synth_port_tts+7, synth->version );
167
	return 0;
168
}
169
170
static int synth_is_alive( void )
171
{
172
	if ( synth_alive ) return 1;
173
	if ( !synth_alive&& wait_for_xmitr( ) > 0 ) { /* restart */
174
		synth_alive = 1;
175
		synth_write_string( synth->init );
176
		return 2;
177
	}
178
	pr_warn( "%s: can't restart synth\n", synth->long_name );
179
	return 0;
180
}
181
182
static const char init_string[] = "[:pe -380]";
183
184
static struct st_string_var stringvars[] = {
185
	{ CAPS_START, "[:dv ap 222]" },
186
	{ CAPS_STOP, "[:dv ap 100]" },
187
	V_LAST_STRING
188
};
189
static struct st_num_var numvars[] = {
190
	{ RATE, "[:ra %d]", 7, 0, 9, 150, 25, 0 },
191
	{ PITCH, "[:dv ap %d]", 100, 0, 100, 0, 0, 0 },
192
	{ VOL, "[:dv gv %d]", 13, 0, 16, 0, 5, 0 },
193
	{ PUNCT, "[:pu %c]", 0, 0, 2, 0, 0, "nsa" },
194
	{ VOICE, "[:n%c]", 0, 0, 9, 0, 0, "phfdburwkv" },
195
	V_LAST_NUM
196
};
197
198
struct spk_synth synth_decext = {"decext", "1.1", "Dectalk External",
199
	 init_string, 500, 50, 50, 1000, 0, SF_DEC, SYNTH_CHECK,
200
	stringvars, numvars, synth_probe, spk_serial_release, synth_immediate,
201
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL,
202
	{NULL,0,0,0} };
203
204
#ifdef MODULE
205
#include "mod_code.c"
206
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_decpc.c (+243 lines)
Line 0 Link Here
1
/*
2
* written by David Borowski, david575@golden.net
3
4
		Copyright (C) 2003 David Borowski.
5
6
		This program is free software; you can redistribute it and/or modify
7
		it under the terms of the GNU General Public License as published by
8
		the Free Software Foundation; either version 2 of the License, or
9
		(at your option) any later version.
10
11
		This program is distributed in the hope that it will be useful,
12
		but WITHOUT ANY WARRANTY; without even the implied warranty of
13
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
		GNU General Public License for more details.
15
16
		You should have received a copy of the GNU General Public License
17
		along with this program; if not, write to the Free Software
18
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20
 * this code is specificly written as a driver for the speakup screenreview
21
 * package and is not a general device driver.
22
		*/
23
#include "spk_priv.h"
24
#include "dtpc_reg.h"
25
26
#define MY_SYNTH synth_dec_pc
27
#define PROCSPEECH 0x0b
28
#define SYNTH_IO_EXTENT 8
29
30
static int synth_portlist[] = { 0x340, 0x350, 0x240, 0x250, 0 };
31
static int in_escape = 0, is_flushing = 0;
32
static int dt_stat, dma_state = 0;
33
34
static int dt_getstatus(void)
35
{
36
	dt_stat =  inb_p( synth_port_tts )|(inb_p( synth_port_tts+1 )<<8);
37
	return dt_stat;
38
}
39
40
static void dt_sendcmd(u_int cmd)
41
{
42
	outb_p( cmd & 0xFF, synth_port_tts );
43
	outb_p( (cmd>>8) & 0xFF, synth_port_tts+1 );
44
}
45
46
static int dt_waitbit( int bit )
47
{
48
	int timeout = 100;
49
	while ( --timeout > 0 ) {
50
		if( (dt_getstatus( ) & bit ) == bit ) return 1;
51
		udelay( 50 );
52
	}
53
	return 0;
54
}
55
56
static int dt_wait_dma( void )
57
{
58
	int timeout = 100, state = dma_state;
59
	if( ! dt_waitbit( STAT_dma_ready ) ) return 0;
60
	while ( --timeout > 0 ) {
61
		if( (dt_getstatus()&STAT_dma_state) == state ) return 1;
62
		udelay( 50 );
63
	}
64
	dma_state = dt_getstatus( ) & STAT_dma_state;
65
	return 1;
66
}
67
68
static int dt_ctrl( u_int cmd )
69
{
70
	int timeout = 10;
71
	if ( !dt_waitbit( STAT_cmd_ready ) ) return -1;
72
	outb_p( 0, synth_port_tts+2 );
73
	outb_p( 0, synth_port_tts+3 );
74
	dt_getstatus( );
75
	dt_sendcmd( CMD_control|cmd );
76
	outb_p( 0, synth_port_tts+6 );
77
	while ( dt_getstatus( ) & STAT_cmd_ready ) {
78
		udelay( 20 );
79
		if ( --timeout == 0 ) break;
80
	}
81
	dt_sendcmd( CMD_null );
82
	return 0;
83
}
84
85
static void synth_flush( void )
86
{
87
	int timeout = 10;
88
	if ( is_flushing ) return;
89
	is_flushing = 4;
90
	in_escape = 0;
91
	while ( dt_ctrl( CTRL_flush ) ) {
92
		if ( --timeout == 0 ) break;
93
udelay( 50 );
94
	}
95
	for ( timeout = 0; timeout < 10; timeout++ ) {
96
		if ( dt_waitbit( STAT_dma_ready ) ) break;
97
udelay( 50 );
98
	}
99
	outb_p( DMA_sync, synth_port_tts+4 );
100
	outb_p( 0, synth_port_tts+4 );
101
	udelay( 100 );
102
	for ( timeout = 0; timeout < 10; timeout++ ) {
103
		if ( !( dt_getstatus( ) & STAT_flushing ) ) break;
104
udelay( 50 );
105
	}
106
	dma_state = dt_getstatus( ) & STAT_dma_state;
107
	dma_state ^= STAT_dma_state;
108
	is_flushing = 0;
109
}
110
111
static int dt_sendchar( char ch )
112
{
113
	if( ! dt_wait_dma( ) ) return -1;
114
	if( ! (dt_stat & STAT_rr_char) ) return -2;
115
	outb_p( DMA_single_in, synth_port_tts+4 );
116
	outb_p( ch, synth_port_tts+4 );
117
	dma_state ^= STAT_dma_state;
118
	return 0;
119
}
120
121
static int testkernel( void )
122
{
123
	int status = 0;
124
	if ( dt_getstatus( ) == 0xffff ) {
125
		status = -1;
126
		goto oops;
127
	}
128
	dt_sendcmd( CMD_sync );
129
	if( ! dt_waitbit( STAT_cmd_ready ) ) status = -2;
130
	else if ( ( dt_stat&0x8000 ) ) {
131
		return 0;
132
	} else if ( dt_stat == 0x0dec )
133
		pr_warn( "dec_pc at 0x%x, software not loaded\n", synth_port_tts );
134
	status = -3;
135
oops:	synth_release_region( synth_port_tts, SYNTH_IO_EXTENT );
136
	synth_port_tts = 0;
137
	return status;
138
}
139
140
static void do_catch_up( unsigned long data )
141
{
142
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
143
	u_char ch;
144
static u_char last='\0';
145
	synth_stop_timer( );
146
	while ( synth_buff_out < synth_buff_in ) {
147
		ch = *synth_buff_out;
148
		if ( ch == '\n' ) ch = 0x0D;
149
		if ( dt_sendchar( ch ) ) {
150
			synth_delay( synth_full_time );
151
			return;
152
		}
153
		synth_buff_out++;
154
		if ( ch == '[' ) in_escape = 1;
155
		else if ( ch == ']' ) in_escape = 0;
156
		else if ( ch <= SPACE ) {
157
			if ( !in_escape && strchr( ",.!?;:", last ) )
158
				dt_sendchar( PROCSPEECH );
159
			if ( jiffies >= jiff_max ) { 
160
				if ( !in_escape )
161
					dt_sendchar( PROCSPEECH );
162
				synth_delay( synth_delay_time ); 
163
				return; 
164
			}
165
		}
166
		last = ch;
167
	}
168
	if ( synth_done( ) || !in_escape )
169
	dt_sendchar( PROCSPEECH );
170
}
171
172
static const char *synth_immediate ( const char *buf )
173
{
174
	u_char ch;
175
	while ( ( ch = *buf ) ) {
176
	if ( ch == 0x0a ) ch = PROCSPEECH;
177
		if ( dt_sendchar ( ch ) )
178
			return buf;
179
	buf++;
180
	}
181
	return 0;
182
}
183
184
static int synth_probe ( void )
185
{
186
	int i=0, failed=0;
187
	pr_info ( "Probing for %s.\n", synth->long_name );
188
	for( i=0; synth_portlist[i]; i++ ) {
189
		if ( synth_request_region( synth_portlist[i], SYNTH_IO_EXTENT ) ) {
190
			pr_warn( "request_region:  failed with 0x%x, %d\n",
191
				synth_portlist[i], SYNTH_IO_EXTENT );
192
			continue;
193
		}
194
		synth_port_tts = synth_portlist[i];
195
		if (( failed = testkernel( )) == 0 ) break;
196
	}
197
	if ( failed ) {
198
		pr_info ( "%s:  not found\n", synth->long_name );
199
		return -ENODEV;
200
	}
201
	pr_info ( "%s: %03x-%03x, Driver Version %s,\n", synth->long_name,
202
		synth_port_tts, synth_port_tts + 7, synth->version );
203
	return 0;
204
}
205
206
static void dtpc_release(  void )
207
{
208
	if (  synth_port_tts )
209
		synth_release_region( synth_port_tts, SYNTH_IO_EXTENT );
210
	synth_port_tts = 0;
211
}
212
213
static int synth_is_alive( void )
214
{
215
	synth_alive = 1;
216
	return 1;
217
}
218
219
static const char init_string[] = "[:pe -380]";
220
221
static struct st_string_var stringvars[] = {
222
	{ CAPS_START, "[:dv ap 200]" },
223
	{ CAPS_STOP, "[:dv ap 100]" },
224
	V_LAST_STRING
225
};
226
static struct st_num_var numvars[] = {
227
	{ RATE, "[:ra %d]", 9, 0, 18, 150, 25, 0 },
228
	{ PITCH, "[:dv ap %d]", 80, 0, 100, 20, 0, 0 },
229
	{ VOL, "[:vo se %d]", 5, 0, 9, 5, 10, 0 },
230
	{ PUNCT, "[:pu %c]", 0, 0, 2, 0, 0, "nsa" },
231
	{ VOICE, "[:n%c]", 0, 0, 9, 0, 0, "phfdburwkv" },
232
	V_LAST_NUM
233
};
234
   
235
struct spk_synth synth_dec_pc = { "decpc", "1.1", "Dectalk PC",
236
	init_string, 500, 50, 50, 1000, 0, SF_DEC, SYNTH_CHECK,
237
	stringvars, numvars, synth_probe, dtpc_release, synth_immediate,
238
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL,
239
	{NULL,0,0,0} };
240
241
#ifdef MODULE
242
#include "mod_code.c"
243
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_dectlk.c (+285 lines)
Line 0 Link Here
1
/*
2
 * originially written by: Kirk Reiser <kirk@braille.uwo.ca>
3
* this version considerably modified by David Borowski, david575@rogers.com
4
5
		Copyright (C) 1998-99  Kirk Reiser.
6
		Copyright (C) 2003 David Borowski.
7
8
		This program is free software; you can redistribute it and/or modify
9
		it under the terms of the GNU General Public License as published by
10
		the Free Software Foundation; either version 2 of the License, or
11
		(at your option) any later version.
12
13
		This program is distributed in the hope that it will be useful,
14
		but WITHOUT ANY WARRANTY; without even the implied warranty of
15
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
		GNU General Public License for more details.
17
18
		You should have received a copy of the GNU General Public License
19
		along with this program; if not, write to the Free Software
20
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22
 * this code is specificly written as a driver for the speakup screenreview
23
 * package and is not a general device driver.
24
		*/
25
#include "spk_priv.h"
26
#include "serialio.h"
27
#include <linux/unistd.h>
28
#include <linux/proc_fs.h>
29
30
#define MY_SYNTH synth_dectlk
31
#define SYNTH_CLEAR 0x03
32
#define PROCSPEECH 0x0b
33
#define synth_full( )  ( inb_p( synth_port_tts ) == 0x13 )
34
35
static int timeouts = 0;
36
static int in_escape = 0, is_flushing = 0;
37
atomic_t dectest=ATOMIC_INIT(0);
38
39
static int wait_for_xmitr ( void )
40
{
41
	int check, tmout = SPK_XMITR_TIMEOUT;
42
	if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) {
43
		synth_alive = 0;
44
		timeouts = 0;
45
		return 0;
46
	}
47
	do { /* holding register empty? */
48
		check = inb_p( synth_port_tts + UART_LSR );
49
		if ( --tmout == 0 ) {
50
			pr_warn ( "%s:  timed out\n", synth->long_name );
51
			timeouts++;
52
			return 0;
53
		}
54
	} while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY );
55
	//} while ( ( check & UART_LSR_THRE ) != UART_LSR_THRE );
56
	tmout = SPK_XMITR_TIMEOUT;
57
	do { /* CTS */
58
		check = inb_p ( synth_port_tts + UART_MSR );
59
		if ( --tmout == 0 ) {
60
			timeouts++;
61
			return 0;
62
		}
63
	} while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS );
64
	timeouts = 0;
65
	return 1;
66
}
67
68
static int spk_serial_out ( const char ch )
69
{
70
	if ( synth_alive && wait_for_xmitr ( ) ) {
71
		outb_p ( ch, synth_port_tts );
72
73
		return 1;
74
	}
75
	return 0;
76
}
77
78
/*static u_char
79
spk_serial_in ( void )
80
{
81
	int c = 0;
82
83
	while (inb_p(synth_port_tts + UART_LSR) & UART_LSR_DR) {
84
		c = inb_p(synth_port_tts+UART_RX);
85
	}
86
	return (u_char) c;
87
}*/
88
89
static int is_indnum(u_char *ch)
90
{
91
	if ((*ch>47)&&(*ch<58))
92
	{
93
		*ch=*ch-48;
94
		return 1;
95
	}
96
	return 0;
97
}
98
99
static const char *synth_immediate (const char *);
100
101
static u_char lastind=0;
102
103
static unsigned char get_index( void )
104
{
105
	u_char rv;
106
	rv=lastind;
107
	lastind=0;
108
	return rv;
109
}
110
111
void read_buff_add(u_char c)
112
{
113
	static int ind=-1;
114
115
	if (c==0x01)
116
	{
117
		is_flushing=0;
118
		atomic_set(&dectest,0);
119
	}
120
	else if (is_indnum(&c))
121
	{
122
		if (ind==-1)
123
			ind=c;
124
		else
125
			ind=ind*10+c;
126
	}
127
	else if ((c>31) && (c<127))
128
	{
129
		if (ind!=-1)
130
			lastind=(u_char)ind;
131
		ind=-1;
132
	}
133
}
134
135
static void do_catch_up( unsigned long data )
136
{
137
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
138
	u_char ch;
139
	static u_char last='\0';
140
	synth_stop_timer( );
141
	if (is_flushing)
142
	{
143
		if (--is_flushing == 0 )
144
			pr_warn ( "flush timeout\n" );
145
		else
146
		{
147
			synth_delay( synth_delay_time );
148
			return;
149
		}
150
	}
151
	while ( synth_buff_out < synth_buff_in ) {
152
		ch = *synth_buff_out;
153
		if ( ch == '\n' ) ch = 0x0D;
154
		if ( synth_full( ) || !spk_serial_out( ch ) ) {
155
			synth_delay( synth_full_time );
156
			return;
157
		}
158
		synth_buff_out++;
159
		if ( ch == '[' ) in_escape = 1;
160
		else if ( ch == ']' ) in_escape = 0;
161
		else if ( ch <= SPACE ) {
162
			if ( !in_escape && strchr( ",.!?;:", last ) )
163
				spk_serial_out( PROCSPEECH );
164
			if ( jiffies >= jiff_max ) { 
165
				if ( !in_escape )
166
					spk_serial_out( PROCSPEECH );
167
				synth_delay( synth_delay_time ); 
168
				return; 
169
			}
170
		}
171
		last = ch;
172
	}
173
	if ( synth_done( ) || !in_escape )
174
	spk_serial_out( PROCSPEECH );
175
}
176
177
static const char *synth_immediate ( const char *buf )
178
{
179
	u_char ch;
180
	while ( ( ch = *buf ) ) {
181
	if ( ch == 0x0a ) ch = PROCSPEECH;
182
        if ( wait_for_xmitr( ) )
183
          outb( ch, synth_port_tts );
184
        else return buf;
185
	buf++;
186
	}
187
	return 0;
188
}
189
190
static void synth_flush( void )
191
{
192
	if (in_escape)
193
	{
194
		// if in command output ']' so we don't get an error
195
		spk_serial_out( ']' );
196
	}
197
	in_escape = 0;
198
	spk_serial_out ( SYNTH_CLEAR );
199
	is_flushing = 5; /* if no ctl-a in 4, send data anyway */
200
}
201
202
static int serprobe ( int index )
203
{
204
	struct serial_state *ser = spk_serial_init( index );
205
	//u_char test;//, timeout = 10000;
206
	int timeout=1000000;
207
	if ( ser == NULL ) return -1;
208
	outb ( 0x0d, ser->port );
209
	/* ignore any error results, if port was forced */
210
	if ( synth_port_forced ) return 0;
211
	/* check for dectalk express now... */
212
213
	atomic_set(&dectest,5);
214
	if ( !synth_immediate ( "\x03" ) ) {
215
		/*do {
216
			test = spk_serial_in ( );
217
			if ( test == 0x01 ) return 0;
218
		} while ( --timeout > 0 );*/
219
	
220
		do {
221
			if ( atomic_read(&dectest)==0) return 0;
222
			outb('a',0x80);  // Sleep about a microsecond
223
		} while ( --timeout > 0);
224
		
225
	}
226
	spk_serial_release( );
227
	timeouts = synth_alive = synth_port_tts = 0;	/* not ignoring */
228
	return -1;
229
}
230
231
static int synth_probe ( void )
232
{
233
	int i = 0, failed=0;
234
	pr_info ( "Probing for %s.\n", synth->long_name );
235
	/* check ttyS0-ttyS3 */
236
	for ( i = SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) {
237
	  if (( failed = serprobe( i )) == 0 ) break; /* found it */
238
        }
239
        if ( failed ) {
240
		pr_info ( "%s:  not found\n", synth->long_name );
241
		return -ENODEV;
242
	}
243
	pr_info ( "%s: %03x-%03x, Driver Version %s,\n", synth->long_name,
244
		synth_port_tts, synth_port_tts + 7, synth->version );
245
	return 0;
246
}
247
248
static int
249
synth_is_alive ( void )
250
{
251
	if ( synth_alive ) return 1;
252
	if ( !synth_alive && wait_for_xmitr ( ) > 0 ) {	/* restart */
253
		synth_alive = 1;
254
		synth_write_string ( synth->init );
255
		return 2;
256
	} else
257
		pr_warn ( "%s: can't restart synth\n", synth->long_name );
258
	return 0;
259
}
260
261
static const char init_string[] = "[:pe -380][:dv ap 100][:error sp]";
262
263
static struct st_string_var stringvars[] = {
264
	{ CAPS_START, "[:dv ap 200]" },
265
	{ CAPS_STOP, "[:dv ap 100]" },
266
	V_LAST_STRING
267
};
268
static struct st_num_var numvars[] = {
269
	{ RATE, "[:ra %d]", 9, 0, 18, 150, 25, 0 },
270
	{ PITCH, "[:dv ap %d]", 80, 0, 200, 20, 0, 0 },
271
	{ VOL, "[:dv gv %d]", 13, 0, 14, 0, 5, 0 },
272
	{ PUNCT, "[:pu %c]", 0, 0, 2, 0, 0, "nsa" },
273
	{ VOICE, "[:n%c]", 0, 0, 9, 0, 0, "phfdburwkv" },
274
	V_LAST_NUM
275
};
276
   
277
struct spk_synth synth_dectlk = { "dectlk", "1.3", "Dectalk Express",
278
	init_string, 500, 50, 50, 1000, 0, SF_DEC, SYNTH_CHECK,
279
	stringvars, numvars, synth_probe, spk_serial_release, synth_immediate,
280
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, read_buff_add,
281
	get_index, {"[:in re %d] ",1,8,1} };
282
283
#ifdef MODULE
284
#include "mod_code.c"
285
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_drvcommon.c (+1031 lines)
Line 0 Link Here
1
#define KERNEL
2
#include <linux/version.h>
3
#include <linux/types.h>
4
#include <linux/ctype.h>	/* for isdigit( ) and friends */
5
#include <linux/fs.h>
6
#include <linux/mm.h>		/* for verify_area */
7
#include <linux/errno.h>	/* for -EBUSY */
8
#include <linux/ioport.h>	/* for check_region, request_region */
9
#include <linux/interrupt.h>
10
#include <linux/delay.h>	/* for loops_per_sec */
11
#include <asm/semaphore.h>
12
#include <linux/wait.h>		/* for wait_queue */
13
#include <linux/miscdevice.h>	/* for misc_register, and SYNTH_MINOR */
14
#include "spk_priv.h"
15
#include "serialio.h"
16
#include <linux/kmod.h>
17
18
#ifdef __powerpc__
19
#include <asm-ppc/pc_serial.h> /* for SERIAL_PORT_DFNS */
20
#endif
21
22
static struct serial_state rs_table[] = {
23
	SERIAL_PORT_DFNS
24
};
25
26
#include "synthlist.h"
27
static struct spk_synth *synths[16] = {
28
#include "synthlist.h"
29
	NULL };
30
31
#define synthBufferSize 8192	/* currently 8K bytes */
32
struct spk_synth *synth = NULL;
33
int synth_port_tts = 0, synth_port_forced = 0;
34
static int synth_timer_active = 0;	/* indicates when a timer is set */
35
	static struct miscdevice synth_device;
36
static int misc_registered = 0;
37
static char pitch_buff[32] = "";
38
static DECLARE_MUTEX(sem);
39
declare_sleeper( synth_sleeping_list );
40
static int module_status = 0;
41
static declare_timer( synth_timer );
42
short synth_delay_time = 500, synth_trigger_time = 50;
43
short synth_jiffy_delta = 50, synth_full_time = 1000;
44
int synth_alive = 0, quiet_boot = 0;
45
u_char synth_buffer[synthBufferSize];	/* guess what this is for! */
46
static u_char *buffer_highwater = synth_buffer+synthBufferSize-100;
47
u_char *buffer_end = synth_buffer+synthBufferSize-1;
48
volatile u_char *synth_buff_in = synth_buffer, *synth_buff_out = synth_buffer;
49
static irqreturn_t synth_readbuf_handler(int irq, void *dev_id);
50
static struct serial_state *serstate;
51
52
static void speakup_unregister_var(short var_id);
53
static void start_serial_interrupt(int irq);
54
static void speakup_register_devsynth(void);
55
56
static char *xlate(char *s)
57
{
58
	static const char finds[] = "nrtvafe";
59
	static const char subs[] = "\n\r\t\013\001\014\033";
60
	static const char hx[] = "0123456789abcdefABCDEF";
61
	char *p = s, *p1, *p2, c;
62
	int num;
63
	while ( ( p = strchr ( p, '\\' ) ) ) {
64
		p1 = p+1;
65
		p2 = strchr( finds, *p1 );
66
		if ( p2 ) {
67
			*p++ = subs[p2-finds];
68
			p1++;
69
		} else if ( *p1 >= '0' && *p1 <= '7' ) {
70
			num = ( *p1++ )&7;
71
			while ( num < 256 && *p1 >= '0' && *p1 <= '7' ) {
72
				num <<= 3;
73
				num = ( *p1++ )&7;
74
			}
75
			*p++ = num;
76
		} else if ( *p1 == 'x'&& strchr( hx, p1[1] ) && strchr( hx, p1[2] ) ) {
77
			p1++;
78
			c = *p1++;
79
			if ( c > '9' )
80
				c = ( c-'7' )&0x0f;
81
			else
82
				c -= '0';
83
			num = c<<4;
84
			c = *p1++;
85
			if ( c > '9' )
86
				c = ( c-'7' )&0x0f;
87
			else
88
				c -= '0';
89
			num += c;
90
			*p++ = num;
91
		} else
92
			*p++ = *p1++;
93
		p2 = p;
94
		while ( *p1 ) *p2++ = *p1++;
95
		*p2 = '\0';
96
	}
97
	return s;
98
}
99
100
struct serial_state *spk_serial_init( int index )
101
{
102
	int baud = 9600, quot = 0;
103
	unsigned int cval = 0;
104
	int     i, cflag = CREAD | HUPCL | CLOCAL | B9600 | CS8;
105
	struct serial_state *ser = NULL;
106
 
107
	if ( synth_port_forced ) {
108
		if ( index > 0 ) return NULL;
109
		pr_info ( "probe forced to 0x%x by kernel command line\n",
110
			synth_port_forced );
111
          for ( i=0; i <= SPK_HI_TTY; i++ )
112
            if ( ( rs_table+i )->port == synth_port_forced ) {
113
              ser = rs_table+i;
114
              break;
115
            }
116
        } else  ser = rs_table + index;
117
	/*	Divisor, bytesize and parity */
118
	quot = ser->baud_base / baud;
119
	cval = cflag & ( CSIZE | CSTOPB );
120
#if defined( __powerpc__ ) || defined( __alpha__ )
121
	cval >>= 8;
122
#else /* !__powerpc__ && !__alpha__ */
123
	cval >>= 4;
124
#endif /* !__powerpc__ && !__alpha__ */
125
	if ( cflag & PARENB )
126
		cval |= UART_LCR_PARITY;
127
	if ( !( cflag & PARODD ) )
128
		cval |= UART_LCR_EPAR;
129
	if ( synth_request_region( ser->port, 8 ) ) { // try to take it back.
130
	   __release_region(&ioport_resource, ser->port, 8 );
131
	if ( synth_request_region( ser->port, 8 ) ) return NULL;
132
	}
133
134
	/*	Disable UART interrupts, set DTR and RTS high
135
	 *	and set speed. */
136
	outb( cval | UART_LCR_DLAB, ser->port + UART_LCR );	/* set DLAB */
137
	outb( quot & 0xff, ser->port + UART_DLL );	/* LS of divisor */
138
	outb( quot >> 8, ser->port + UART_DLM );		/* MS of divisor */
139
	outb( cval, ser->port + UART_LCR );		/* reset DLAB */
140
141
	// Turn off Interrupts
142
	outb( 0, ser->port + UART_IER );
143
	outb( UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR );
144
145
	/* If we read 0xff from the LSR, there is no UART here. */
146
	if ( inb ( ser->port + UART_LSR ) == 0xff ) {
147
		synth_release_region( ser->port, 8 );
148
		serstate=NULL;
149
		return NULL;
150
	}
151
152
	mdelay( 1 );
153
	synth_port_tts = ser->port;
154
	serstate=ser;
155
156
	start_serial_interrupt(ser->irq);
157
158
	return ser;
159
}
160
161
static void start_serial_interrupt(int irq)
162
{
163
	int rv;
164
165
	if (synth->read_buff_add == NULL)
166
		return;
167
168
	rv = request_irq(irq, synth_readbuf_handler, SA_SHIRQ, 
169
			 "serial", (void *) synth_readbuf_handler);
170
171
	if (rv)
172
	{
173
		printk(KERN_ERR "Unable to request Speakup serial I R Q\n");
174
	}
175
	// Set MCR
176
	outb(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2, synth_port_tts + UART_MCR);
177
	// Turn on Interrupts
178
	outb(UART_IER_MSI|UART_IER_RLSI|UART_IER_RDI,synth_port_tts+ UART_IER );
179
	inb(synth_port_tts+UART_LSR);
180
	inb(synth_port_tts+UART_RX);
181
	inb(synth_port_tts+UART_IIR);
182
	inb(synth_port_tts+UART_MSR);
183
	outb( 1, synth_port_tts + UART_FCR );	/* Turn FIFO On */
184
}
185
186
static void stop_serial_interrupt(void)
187
{
188
	if ( synth_port_tts == 0 ) return;
189
190
	// Turn off interrupts
191
	outb(0,synth_port_tts+UART_IER);
192
	// Free IRQ
193
	free_irq(serstate->irq, (void *) synth_readbuf_handler);
194
}
195
196
void spk_serial_release( void )
197
{
198
	if ( synth_port_tts == 0 ) return;
199
	synth_release_region( synth_port_tts, 8 );
200
	synth_port_tts = 0;
201
}
202
203
static irqreturn_t synth_readbuf_handler(int irq, void *dev_id)
204
{
205
//printk(KERN_ERR "in irq\n");
206
//pr_warn("in IRQ\n");
207
	int c;
208
	while (inb_p(synth_port_tts + UART_LSR) & UART_LSR_DR)
209
	{
210
211
		c=inb_p(synth_port_tts+UART_RX);
212
		synth->read_buff_add((u_char) c);
213
//printk(KERN_ERR "c = %d\n",c);
214
//pr_warn("C = %d\n",c);
215
	}
216
	return IRQ_HANDLED;
217
}
218
219
/* sleep for ms milliseconds */
220
void
221
synth_delay ( int val )
222
{
223
        if (val == 0) return;
224
	synth_timer.expires = jiffies + val;
225
		start_timer( synth_timer );
226
	synth_timer_active++;
227
}
228
229
static void synth_dummy_catchup(unsigned long data)
230
{
231
	synth_stop_timer();
232
	synth_done();
233
} /* a bogus catchup if no synth */
234
235
void
236
synth_stop_timer ( void )
237
{
238
	if ( synth_timer_active )
239
		stop_timer ( synth_timer );
240
	synth_timer_active = 0;
241
}
242
243
int synth_done( void )
244
{
245
	synth_buff_out = synth_buff_in = synth_buffer;
246
	if (waitqueue_active(&synth_sleeping_list)) {
247
		  wake_up_interruptible(&synth_sleeping_list);
248
		return 0;
249
	}
250
	return 1;
251
}
252
253
static void synth_start(void)
254
{
255
	if (!synth_alive)
256
		synth_done();
257
	else if (synth->start)
258
		synth->start();
259
	else if (synth_timer_active == 0)
260
		synth_delay(synth_trigger_time);
261
}
262
263
void do_flush( void )
264
{
265
	synth_stop_timer( );
266
	synth_buff_out = synth_buff_in = synth_buffer;
267
	if ( synth_alive ) {
268
		synth->flush( );
269
		if ( synth->flush_wait )
270
			synth_delay( ( synth->flush_wait * HZ ) / 1000 );
271
		if ( pitch_shift ) {
272
			synth_write_string( pitch_buff );
273
			pitch_shift = 0;
274
		}
275
	}
276
	if (waitqueue_active(&synth_sleeping_list))
277
		wake_up_interruptible(&synth_sleeping_list);
278
}
279
280
void
281
synth_buffer_add ( char ch )
282
{
283
	if ( synth_buff_in >= buffer_highwater ) {
284
		synth_start ( );
285
		if ( !waitqueue_active ( &synth_sleeping_list ) )
286
			interruptible_sleep_on ( &synth_sleeping_list );
287
		if ( synth_buff_in >= buffer_end ) return;
288
	}
289
	*synth_buff_in++ = ch;
290
}
291
292
void
293
synth_write ( const char *buf, size_t count )
294
{
295
	while ( count-- )
296
		synth_buffer_add ( *buf++ );
297
	synth_start ( );
298
}
299
300
void
301
synth_write_string ( const char *buf )
302
{
303
	while ( *buf )
304
		synth_buffer_add ( *buf++ );
305
	synth_start ( );
306
}
307
308
void
309
synth_write_msg ( const char *buf )
310
{
311
	while ( *buf )
312
		synth_buffer_add ( *buf++ );
313
		synth_buffer_add ( '\n' );
314
	synth_start ( );
315
}
316
317
static int index_count=0;
318
static int sentence_count=0;
319
320
void
321
reset_index_count(int sc)
322
{
323
	static int first = 1;
324
	if (first)
325
		first=0;
326
	else
327
		synth->get_index();
328
	index_count=0;
329
	sentence_count=sc;
330
}
331
332
int
333
synth_supports_indexing( void )
334
{
335
	if ( synth->get_index!=NULL )
336
		return 1;
337
	return 0;
338
}
339
340
void
341
synth_insert_next_index( int sent_num )
342
{
343
	int out;
344
	char buf[50];
345
	if ( synth_alive ) {
346
		if (sent_num==0)
347
		{
348
			synth->indexing.currindex++;
349
			index_count++;
350
			if (synth->indexing.currindex>synth->indexing.highindex)
351
				synth->indexing.currindex=synth->indexing.lowindex;
352
		}
353
354
		out=synth->indexing.currindex*10+sent_num;
355
		sprintf(buf,synth->indexing.command,out,out);
356
		synth_write_string(buf);
357
	}
358
}
359
360
void
361
get_index_count(int *linecount,int *sentcount)
362
{
363
	int ind=synth->get_index();
364
	if (ind)
365
	{
366
		sentence_count=ind%10;
367
368
		if ((ind/10)<=synth->indexing.currindex)
369
			index_count = synth->indexing.currindex-(ind/10);
370
		else
371
			index_count = synth->indexing.currindex-synth->indexing.lowindex + synth->indexing.highindex-(ind/10)+1;
372
373
	}
374
	*sentcount=sentence_count;
375
	*linecount=index_count;
376
}
377
378
static struct resource synth_res;
379
380
int synth_request_region ( unsigned long start, unsigned long n )
381
{
382
	struct resource *parent = &ioport_resource;
383
	memset ( &synth_res, 0, sizeof ( synth_res ) );
384
	synth_res.name = synth->name;
385
	synth_res.start = start;
386
	synth_res.end = start + n - 1;
387
	synth_res.flags = IORESOURCE_BUSY;
388
	return request_resource ( parent, &synth_res );
389
}
390
391
int synth_release_region ( unsigned long start, unsigned long n )
392
{
393
	return release_resource ( &synth_res );
394
}
395
396
#ifdef CONFIG_PROC_FS
397
398
// /proc/synth-specific code
399
400
#include <asm/uaccess.h>
401
#include <linux/limits.h>
402
403
// this is the write handler for /proc/speakup/synth-specific/direct
404
static int spk_direct_write_proc(struct file *file, const char *buffer,
405
				 u_long count, void *data)
406
{
407
	u_char buf[256];
408
	int ret = count, bytes;
409
	const char *ptr = buffer;
410
	if ( synth == NULL ) return -EPERM;
411
	while ( count > 0 ) {
412
		bytes = min_t ( size_t, count, 250 );
413
		if ( copy_from_user ( buf, ptr, bytes  ) )
414
			return -EFAULT;
415
		buf[bytes] = '\0';
416
		xlate ( buf );
417
		synth_write_string ( buf );
418
		ptr += bytes;
419
		count -= bytes;
420
	}
421
	return ret;
422
}
423
424
struct st_proc_var synth_direct = { SYNTH_DIRECT, 0, spk_direct_write_proc, 0 };
425
426
#endif
427
428
static struct st_num_var synth_time_vars[] = {
429
	{ DELAY, 0, 100, 100, 2000, 0, 0, 0 },
430
	{ TRIGGER, 0, 20, 10, 200, 0, 0, 0 },
431
	{ JIFFY, 0, 50, 20, 200, 0, 0, 0 },
432
	{ FULL, 0, 400, 200, 10000, 0, 0, 0 },
433
	V_LAST_NUM
434
};
435
436
static struct spk_synth *do_load_synth(const char *synth_name)
437
{
438
	int i;
439
440
	if (request_module("speakup_%s", synth_name))
441
		return NULL;
442
443
	for (i = 0; synths[i] != NULL; i++) {
444
		if (strcmp(synths[i]->name, synth_name) == 0)
445
			return synths[i];
446
	}
447
448
	return NULL;
449
}
450
451
int synth_init(char *synth_name)
452
{
453
	int i;
454
	struct spk_synth *synth = NULL;
455
456
	if (synth_name == NULL)
457
		return 0;
458
459
	if (strcmp(synth_name, "none") == 0) {
460
		synth_release();
461
		return 0;
462
	}
463
464
	/* First, check if we already have it loaded. */
465
	for (i = 0; synths[i] != NULL; i++)
466
		if (strcmp(synths[i]->name, synth_name) == 0)
467
			synth = synths[i];
468
469
	/* No synth loaded matching this one, try loading it. */
470
	if (!synth)
471
		synth = do_load_synth(synth_name);
472
473
	/* If we got one, initialize it now. */
474
	if (synth)
475
		return do_synth_init(synth);
476
477
	return 0;
478
}
479
480
int do_synth_init(struct spk_synth *in_synth)
481
{
482
	struct st_num_var *n_var;
483
	struct st_string_var *s_var;
484
485
	synth_release();
486
	if (in_synth->checkval != SYNTH_CHECK) return -EINVAL;
487
	synth = in_synth;
488
pr_warn("synth probe\n");
489
	if (synth->probe() < 0) {
490
		pr_warn("%s: device probe failed\n", in_synth->name);
491
		synth = NULL;
492
		return -ENODEV;
493
	}
494
	synth_time_vars[0].default_val = synth->delay;
495
	synth_time_vars[1].default_val = synth->trigger;
496
	synth_time_vars[2].default_val = synth->jiffies;
497
	synth_time_vars[3].default_val = synth->full;
498
	  synth_timer.function = synth->catch_up;
499
	  synth_timer.entry.prev = NULL;
500
	  init_timer(&synth_timer);
501
	  for(n_var = synth_time_vars; n_var->var_id >= 0; n_var++)
502
	    speakup_register_var(n_var);
503
	synth_alive = 1;
504
	synth_write_string(synth->init);
505
	for(s_var = synth->string_vars; s_var->var_id >= 0; s_var++)
506
		speakup_register_var((struct st_num_var *) s_var);
507
	for(n_var = synth->num_vars; n_var->var_id >= 0; n_var++)
508
		speakup_register_var(n_var);
509
	if (!quiet_boot) {
510
		synth_write_string(synth->long_name);
511
		synth_write_msg(" found");
512
	}
513
#ifdef CONFIG_PROC_FS
514
	speakup_register_var((struct st_num_var *) &synth_direct);
515
#endif
516
	synth_flags = synth->flags;
517
	return 0;
518
}
519
520
void 
521
synth_release ( void )
522
{
523
	struct st_num_var *n_var;
524
	struct st_string_var *s_var;
525
	if ( synth == NULL ) return;
526
	if (down_interruptible ( &sem )) return;
527
	pr_info ( "releasing synth %s\n", synth->name );
528
	for ( s_var = synth->string_vars; s_var->var_id >= 0; s_var++ )
529
		speakup_unregister_var( s_var->var_id );
530
	for ( n_var = synth_time_vars; n_var->var_id >= 0; n_var++ )
531
		speakup_unregister_var( n_var->var_id );
532
	for ( n_var = synth->num_vars; n_var->var_id >= 0; n_var++ )
533
		speakup_unregister_var( n_var->var_id );
534
#ifdef CONFIG_PROC_FS
535
	speakup_unregister_var( SYNTH_DIRECT );
536
#endif
537
	synth_dummy_catchup((unsigned long) NULL );
538
	synth_timer.function = synth_dummy_catchup;
539
	stop_serial_interrupt();
540
	synth->release( );
541
	synth = NULL;
542
	up( &sem );
543
}
544
545
void synth_add ( struct spk_synth *in_synth )
546
{
547
	int i;
548
	for (i = 0; synths[i] != NULL; i++ )
549
	if ( in_synth == synths[i] ) return;
550
	synths[i++] = in_synth;
551
	synths[i] = NULL;
552
}
553
554
void synth_remove ( struct spk_synth *in_synth )
555
{
556
	int i;
557
	for (i = 0; synths[i] != NULL; i++ ) {
558
		if ( in_synth == synths[i] ) break;
559
	}
560
for ( ;synths[i] != NULL; i++ ) /* compress table */
561
		synths[i] = synths[i+1];
562
	module_status = 0;
563
}
564
565
static struct st_var_header var_headers[] = {
566
  { "version", VERSION, VAR_PROC, USER_R, 0, 0, 0 },
567
  { "synth_name", SYNTH, VAR_PROC, USER_RW, 0, 0, 0 },
568
  { "keymap", KEYMAP, VAR_PROC, USER_RW, 0, 0, 0 },
569
  { "silent", SILENT, VAR_PROC, USER_W, 0, 0, 0 },
570
  { "punc_some", PUNC_SOME, VAR_PROC, USER_RW, 0, 0, 0 },
571
  { "punc_most", PUNC_MOST, VAR_PROC, USER_RW, 0, 0, 0 },
572
  { "punc_all", PUNC_ALL, VAR_PROC, USER_R, 0, 0, 0 },
573
  { "delimiters", DELIM, VAR_PROC, USER_RW, 0, 0, 0 },
574
  { "repeats", REPEATS, VAR_PROC, USER_RW, 0, 0, 0 },
575
  { "ex_num", EXNUMBER, VAR_PROC, USER_RW, 0, 0, 0 },
576
  { "characters", CHARS, VAR_PROC, USER_RW, 0, 0, 0 },
577
  { "synth_direct", SYNTH_DIRECT, VAR_PROC, USER_W, 0, 0, 0 },
578
  { "caps_start", CAPS_START, VAR_STRING, USER_RW, 0, str_caps_start, 0 },
579
  { "caps_stop", CAPS_STOP, VAR_STRING, USER_RW, 0, str_caps_stop, 0 },
580
  { "delay_time", DELAY, VAR_TIME, ROOT_W, 0, &synth_delay_time, 0 },
581
  { "trigger_time", TRIGGER, VAR_TIME, ROOT_W, 0, &synth_trigger_time, 0 },
582
  { "jiffy_delta", JIFFY, VAR_TIME, ROOT_W, 0, &synth_jiffy_delta, 0 },
583
  { "full_time", FULL, VAR_TIME, ROOT_W, 0, &synth_full_time, 0 },
584
  { "spell_delay", SPELL_DELAY, VAR_NUM, USER_RW, 0, &spell_delay, 0 },
585
  { "bleeps", BLEEPS, VAR_NUM, USER_RW, 0, &bleeps, 0 },
586
  { "attrib_bleep", ATTRIB_BLEEP, VAR_NUM, USER_RW, 0, &attrib_bleep, 0 },
587
  { "bleep_time", BLEEP_TIME, VAR_TIME, USER_RW, 0, &bleep_time, 0 },
588
  { "cursor_time", CURSOR_TIME, VAR_TIME, USER_RW, 0, &cursor_timeout, 0 },
589
  { "punc_level", PUNC_LEVEL, VAR_NUM, USER_RW, 0, &punc_level, 0 },
590
  { "reading_punc", READING_PUNC, VAR_NUM, USER_RW, 0, &reading_punc, 0 },
591
  { "say_control", SAY_CONTROL, VAR_NUM, USER_RW, 0, &say_ctrl, 0 },
592
  { "say_word_ctl", SAY_WORD_CTL, VAR_NUM, USER_RW, 0, &say_word_ctl, 0 },
593
  { "no_interrupt", NO_INTERRUPT, VAR_NUM, USER_RW, 0, &no_intr, 0 },
594
  { "key_echo", KEY_ECHO, VAR_NUM, USER_RW, 0, &key_echo, 0 },
595
  { "bell_pos", BELL_POS, VAR_NUM, USER_RW, 0, &bell_pos, 0 },
596
  { "rate", RATE, VAR_NUM, USER_RW, 0, 0, 0 },
597
  { "pitch", PITCH, VAR_NUM, USER_RW, 0, 0, 0 },
598
  { "vol", VOL, VAR_NUM, USER_RW, 0, 0, 0 },
599
  { "tone", TONE, VAR_NUM, USER_RW, 0, 0, 0 },
600
  { "punct", PUNCT, VAR_NUM, USER_RW, 0, 0, 0 },
601
  { "voice", VOICE, VAR_NUM, USER_RW, 0, 0, 0 },
602
  { "freq", FREQ, VAR_NUM, USER_RW, 0, 0, 0 },
603
  { "lang", LANG, VAR_NUM, USER_RW, 0, 0, 0 },
604
  { "chartab", CHARTAB, VAR_PROC, USER_RW, 0, 0, 0 },
605
};
606
607
static struct st_var_header *var_ptrs[MAXVARS] = { 0, 0, 0 };
608
609
char *
610
speakup_s2i ( char *start, short *dest )
611
{
612
	int val;
613
	char ch = *start;
614
	if ( ch == '-' || ch == '+' ) start++;
615
	if ( *start < '0' || *start > '9' ) return start;
616
	val = ( *start ) - '0';
617
	start++;
618
	while ( *start >= '0' && *start <= '9' ) {
619
		val *= 10;
620
		val += ( *start ) - '0';
621
		start++;
622
	}
623
	if ( ch == '-' ) *dest = -val;
624
	else *dest = val;
625
	return start;
626
}
627
628
short punc_masks[] = { 0, SOME, MOST, PUNC, PUNC|B_SYM };
629
630
// handlers for setting vars
631
int set_num_var(short input, struct st_var_header *var, int how)
632
{
633
	short val, ret = 0;
634
	short *p_val = var->p_val;
635
	int l;
636
	char buf[32], *cp;
637
	struct st_num_var *var_data = var->data;
638
	if (var_data == NULL)
639
		return E_UNDEF;
640
	if (how == E_DEFAULT) {
641
		val = var_data->default_val;
642
		ret = SET_DEFAULT;
643
	} else {
644
		if ( how == E_SET ) val = input;
645
		else val = var_data->value;
646
		if ( how == E_INC ) val += input;
647
		else if ( how == E_DEC ) val -= input;
648
		if ( val < var_data->low || val > var_data->high )
649
			return E_RANGE;
650
	}
651
	var_data->value = val;
652
	if ( var->var_type == VAR_TIME && p_val != 0 ) {
653
		*p_val = ( val * HZ + 1000 - HZ ) / 1000;
654
		return ret;
655
	}
656
	if ( p_val != 0 ) *p_val = val;
657
	if ( var->var_id == PUNC_LEVEL ) {
658
		punc_mask = punc_masks[val];
659
	return ret;
660
	}
661
	if ( var_data->multiplier != 0 )
662
		val *= var_data->multiplier;
663
	val += var_data->offset;
664
	if ( var->var_id < FIRST_SYNTH_VAR || synth == NULL ) return ret;
665
	if ( synth->synth_adjust != NULL ) {
666
		int status = synth->synth_adjust( var );
667
		return ( status != 0 ) ? status : ret;
668
	}
669
	if ( !var_data->synth_fmt ) return ret;
670
	if ( var->var_id == PITCH ) cp = pitch_buff;
671
	else cp = buf;
672
	if ( !var_data->out_str )
673
		l = sprintf( cp, var_data->synth_fmt, (int)val );
674
	else l = sprintf( cp, var_data->synth_fmt, var_data->out_str[val] );
675
	synth_write_string( cp );
676
	return ret;
677
}
678
679
static int set_string_var(char *page, struct st_var_header *var, int len)
680
{
681
	int ret = 0;
682
	struct st_string_var *var_data = var->data;
683
	if ( var_data == NULL ) return E_UNDEF;
684
	if ( len > MAXVARLEN )
685
		return -E_TOOLONG;
686
	if ( !len ) {
687
	if ( !var_data->default_val ) return 0;
688
		ret = SET_DEFAULT;
689
		if ( !var->p_val ) var->p_val = var_data->default_val;
690
		if ( var->p_val != var_data->default_val )
691
			strcpy( (char *)var->p_val, var_data->default_val );
692
		} else if ( var->p_val )
693
			strcpy( (char *)var->p_val, page );
694
	else return -E_TOOLONG;
695
	return ret;
696
}
697
698
struct st_var_header *get_var_header(short var_id)
699
{
700
	struct st_var_header *p_header;
701
	if ( var_id < 0 || var_id >= MAXVARS ) return NULL;
702
	p_header = var_ptrs[var_id];
703
	if ( p_header->data == NULL ) return NULL;
704
	return p_header;
705
}
706
707
#ifdef CONFIG_PROC_FS
708
// this is the write handler for /proc/speakup vars
709
static int speakup_vars_write_proc(struct file *file, const char *buffer,
710
				   u_long count, void *data)
711
{
712
	struct st_var_header *p_header = data;
713
	int len = count, ret = 0;
714
	char *page = ( char * ) __get_free_page ( GFP_KERNEL );
715
	char *v_name = p_header->name, *cp;
716
	struct st_num_var *var_data;
717
	short value;
718
	if ( !page ) return -ENOMEM;
719
	if ( copy_from_user ( page, buffer, count ) ) {
720
		ret = -EFAULT;
721
		goto out;
722
	}
723
	if ( page[len - 1] == '\n' ) --len;
724
	page[len] = '\0';
725
	cp = xlate( page );
726
	switch( p_header->var_type ) {
727
		case VAR_NUM:
728
		case VAR_TIME:
729
			if ( *cp == 'd' || *cp == 'r' || *cp == '\0' )
730
				len = E_DEFAULT;
731
			else if ( *cp == '+' || *cp == '-' ) len = E_INC;
732
			else len = E_SET;
733
			speakup_s2i( cp, &value );
734
			ret = set_num_var( value, p_header, len );
735
			if ( ret != E_RANGE ) break;
736
	var_data = p_header->data;
737
			pr_warn( "value for %s out of range, expect %d to %d\n",
738
			v_name, (int)var_data->low, (int)var_data->high );
739
			break;
740
		case VAR_STRING:
741
			len = strlen( page );
742
			ret = set_string_var( page, p_header, len );
743
			if ( ret != E_TOOLONG ) break;
744
			pr_warn( "value too long for %s\n", v_name );
745
			break;
746
		default:
747
			pr_warn( "%s unknown type %d\n",
748
				p_header->name, ( int )p_header->var_type );
749
		break;
750
	}
751
out:
752
	if ( ret == SET_DEFAULT )
753
		pr_info( "%s reset to default value\n", v_name );
754
	free_page ( ( unsigned long ) page );
755
	return count;
756
}
757
758
// this is the read handler for /proc/speakup vars
759
static int speakup_vars_read_proc(char *page, char **start, off_t off,
760
				  int count, int *eof, void *data)
761
{
762
	struct st_var_header *var = data;
763
	struct st_num_var *n_var = var->data;
764
	char ch, *cp, *cp1;
765
	*start = 0;
766
	*eof = 1;
767
	switch( var->var_type ) {
768
		case VAR_NUM:
769
		case VAR_TIME:
770
			return sprintf( page, "%d\n", ( int )n_var->value );
771
			break;
772
		case VAR_STRING:
773
			cp1 = page;
774
			*cp1++ = '"';
775
			for ( cp = (char *)var->p_val; ( ch = *cp ); cp++ ) {
776
				if ( ch >= ' ' && ch < '~' )
777
					*cp1++ = ch;
778
				else
779
					cp1 += sprintf( cp1, "\\""x%02x", ch );
780
			}
781
			*cp1++ = '"';
782
			*cp1++ = '\n';
783
			*cp1 = '\0';
784
			return cp1-page;
785
			break;
786
		default:
787
			return sprintf( page, "oops bad type %d\n",
788
				( int )var->var_type );
789
	}
790
	return 0;
791
}
792
793
static const char spk_dir[] = "speakup";
794
static struct proc_dir_entry *dir_ent = 0;
795
796
static int spk_make_proc(struct st_var_header *p_header)
797
{
798
	struct proc_dir_entry *ent = p_header->proc_entry;
799
	char *name = p_header->name;
800
	struct st_proc_var *p_var;
801
	if ( dir_ent == 0 || p_header->proc_mode == 0 || ent != 0 ) return 0;
802
	ent = create_proc_entry ( name, p_header->proc_mode, dir_ent );
803
	if ( !ent ) {
804
		pr_warn( "Unable to create /proc/%s/%s entry.\n",
805
			spk_dir, name );
806
		return -1;
807
	}
808
	if ( p_header->var_type == VAR_PROC ) {
809
		p_var = (struct st_proc_var *) p_header->data;
810
		if ( p_header->proc_mode&S_IRUSR )
811
			ent->read_proc = p_var->read_proc;
812
		if ( p_header->proc_mode&S_IWUSR )
813
			ent->write_proc = p_var->write_proc;
814
	} else {
815
		if ( p_header->proc_mode&S_IRUSR )
816
			ent->read_proc = speakup_vars_read_proc;
817
		if ( p_header->proc_mode&S_IWUSR )
818
			ent->write_proc = speakup_vars_write_proc;
819
	}
820
	ent->data = ( void * )p_header;
821
	p_header->proc_entry = ( void * ) ent;
822
	return 0;
823
}
824
825
#endif
826
827
int speakup_register_var(struct st_num_var *var)
828
{
829
	static char nothing[2] = "\0";
830
	int i, var_id = var->var_id;
831
	struct st_var_header *p_header;
832
	struct st_string_var *s_var;
833
	if (var_id < 0 || var_id >= MAXVARS)
834
		return -1;
835
	if ( var_ptrs[0] == 0 ) {
836
		for ( i = 0; i < MAXVARS; i++ ) {
837
			p_header = &var_headers[i];
838
			var_ptrs[p_header->var_id] = p_header;
839
			p_header->data = 0;
840
		}
841
	}
842
	p_header = var_ptrs[var_id];
843
	if ( p_header->data != 0 ) return 0;
844
	p_header->data  = var;
845
	switch ( p_header->var_type ) {
846
		case VAR_STRING:
847
			s_var = (struct st_string_var *) var;
848
			set_string_var( nothing, p_header, 0 );
849
			break;
850
		case VAR_NUM:
851
		case VAR_TIME:
852
			set_num_var( 0, p_header, E_DEFAULT );
853
			break;
854
	}
855
#ifdef CONFIG_PROC_FS
856
	return spk_make_proc( p_header );
857
#else
858
	return 0;
859
#endif
860
}
861
862
static void speakup_unregister_var(short var_id)
863
{
864
	struct st_var_header *p_header;
865
	if ( var_id < 0 || var_id >= MAXVARS ) return;
866
	p_header = var_ptrs[var_id];
867
	p_header->data = 0;
868
#ifdef CONFIG_PROC_FS
869
	if ( dir_ent != 0 && p_header->proc_entry != 0 )
870
		remove_proc_entry( p_header->name, dir_ent );
871
	p_header->proc_entry = 0;
872
#endif
873
}
874
875
extern char synth_name[];
876
877
int speakup_dev_init(void)
878
{
879
	int i;
880
	struct st_var_header *p_header;
881
	struct st_proc_var *pv = spk_proc_vars;
882
883
	//pr_warn("synth name on entry is: %s\n", synth_name);
884
	synth_init(synth_name);
885
	speakup_register_devsynth();
886
#ifdef CONFIG_PROC_FS
887
	dir_ent = create_proc_entry(spk_dir, S_IFDIR, 0);
888
	if (!dir_ent) {
889
		pr_warn("Unable to create /proc/%s entry.\n", spk_dir);
890
		return -1;
891
	}
892
	while(pv->var_id >= 0) {
893
		speakup_register_var((void *) pv);
894
		pv++;
895
	}
896
		for (i = 0; i < MAXVARS; i++) {
897
			p_header = &var_headers[i];
898
		if ( p_header->data != 0 ) spk_make_proc(p_header);
899
	}
900
#endif
901
	return 0;
902
}
903
904
void speakup_remove(void)
905
{
906
	int i;
907
908
	for (i = 0; i < MAXVARS; i++)
909
		speakup_unregister_var(i);
910
	pr_info("speakup: unregistering synth device /dev/synth\n");
911
	misc_deregister(&synth_device);
912
	misc_registered = 0;
913
#ifdef CONFIG_PROC_FS
914
	if (dir_ent != 0)
915
		remove_proc_entry(spk_dir, NULL);
916
#endif
917
}
918
919
// provide a file to users, so people can send to /dev/synth
920
921
static ssize_t
922
speakup_file_write ( struct file *fp, const char *buffer,
923
		    size_t nbytes, loff_t * ppos )
924
{
925
	size_t count = nbytes;
926
	const char *ptr = buffer;
927
	int bytes;
928
	u_char buf[256];
929
	if ( synth == NULL ) return -ENODEV;
930
	while ( count > 0 ) {
931
		bytes = min_t (size_t, count, sizeof ( buf ) );
932
		if ( copy_from_user ( buf, ptr, bytes ) )
933
			return -EFAULT;
934
		count -= bytes;
935
		ptr += bytes;
936
		synth_write ( buf, bytes );
937
	}
938
	return ( ssize_t ) nbytes;
939
}
940
941
static int
942
speakup_file_ioctl ( struct inode *inode, struct file *file,
943
		    unsigned int cmd, unsigned long arg )
944
{
945
	return 0;		// silently ignore
946
}
947
948
static ssize_t
949
speakup_file_read ( struct file *fp, char *buf, size_t nbytes, loff_t * ppos )
950
{
951
	return 0;
952
}
953
954
static int synth_file_inuse = 0;
955
956
static int
957
speakup_file_open ( struct inode *ip, struct file *fp )
958
{
959
	if ( synth_file_inuse )
960
		return -EBUSY;
961
	else if ( synth == NULL )
962
		return -ENODEV;
963
	synth_file_inuse++;
964
	return 0;
965
}
966
967
static int
968
speakup_file_release ( struct inode *ip, struct file *fp )
969
{
970
	synth_file_inuse = 0;
971
	return 0;
972
}
973
974
static struct file_operations synth_fops = {
975
	read:speakup_file_read,
976
	write:speakup_file_write,
977
	ioctl:speakup_file_ioctl,
978
	open:speakup_file_open,
979
	release:speakup_file_release,
980
};
981
982
static void speakup_register_devsynth(void)
983
{
984
	if ( misc_registered != 0 ) return;
985
	misc_registered = 1;
986
	memset( &synth_device, 0, sizeof( synth_device ) );
987
/* zero it so if register fails, deregister will not ref invalid ptrs */
988
	synth_device.minor = SYNTH_MINOR;
989
	synth_device.name = "synth";
990
	synth_device.fops = &synth_fops;
991
	if ( misc_register ( &synth_device ) )
992
		pr_warn(
993
			"Couldn't initialize miscdevice /dev/synth.\n" );
994
	else
995
		pr_info(
996
		    "initialized device: /dev/synth, node ( MAJOR 10, MINOR 25 )\n" );
997
}
998
999
__initcall(speakup_dev_init);
1000
1001
/* exported symbols needed by synth modules */
1002
EXPORT_SYMBOL_GPL(speakup_dev_init);
1003
EXPORT_SYMBOL_GPL(synth_init);
1004
EXPORT_SYMBOL_GPL(do_synth_init);
1005
EXPORT_SYMBOL_GPL(spk_serial_init);
1006
EXPORT_SYMBOL_GPL(spk_serial_release);
1007
EXPORT_SYMBOL_GPL(synth);
1008
EXPORT_SYMBOL_GPL(synth_alive);
1009
EXPORT_SYMBOL_GPL(synth_buffer);
1010
EXPORT_SYMBOL_GPL(synth_buff_in);
1011
EXPORT_SYMBOL_GPL(synth_buff_out);
1012
EXPORT_SYMBOL_GPL(synth_delay);
1013
EXPORT_SYMBOL_GPL(synth_delay_time);
1014
EXPORT_SYMBOL_GPL(synth_done);
1015
EXPORT_SYMBOL_GPL(synth_full_time);
1016
EXPORT_SYMBOL_GPL(synth_jiffy_delta);
1017
EXPORT_SYMBOL_GPL(synth_port_forced);
1018
EXPORT_SYMBOL_GPL(synth_port_tts);
1019
EXPORT_SYMBOL_GPL(synth_request_region);
1020
EXPORT_SYMBOL_GPL(synth_release_region);
1021
EXPORT_SYMBOL_GPL(synth_release);
1022
EXPORT_SYMBOL_GPL(synth_add);
1023
EXPORT_SYMBOL_GPL(synth_remove);
1024
EXPORT_SYMBOL_GPL(synth_stop_timer);
1025
EXPORT_SYMBOL_GPL(synth_write_string);
1026
EXPORT_SYMBOL_GPL(synth_write_msg);
1027
EXPORT_SYMBOL_GPL(synth_write);
1028
EXPORT_SYMBOL_GPL(synth_supports_indexing);
1029
MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
1030
MODULE_DESCRIPTION("Speakup module required by all synthesizer specific modules");
1031
MODULE_LICENSE("GPL");
(-)linux-2.6.20/drivers/char/speakup/speakup_dtlk.c (+233 lines)
Line 0 Link Here
1
/*
2
 * originially written by: Kirk Reiser <kirk@braille.uwo.ca>
3
* this version considerably modified by David Borowski, david575@rogers.com
4
5
		Copyright (C) 1998-99  Kirk Reiser.
6
		Copyright (C) 2003 David Borowski.
7
8
		This program is free software; you can redistribute it and/or modify
9
		it under the terms of the GNU General Public License as published by
10
		the Free Software Foundation; either version 2 of the License, or
11
		(at your option) any later version.
12
13
		This program is distributed in the hope that it will be useful,
14
		but WITHOUT ANY WARRANTY; without even the implied warranty of
15
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
		GNU General Public License for more details.
17
18
		You should have received a copy of the GNU General Public License
19
		along with this program; if not, write to the Free Software
20
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22
 * this code is specificly written as a driver for the speakup screenreview
23
 * package and is not a general device driver.
24
		*/
25
#include "spk_priv.h"
26
#include "serialio.h"
27
#include "speakup_dtlk.h" /* local header file for DoubleTalk values */
28
29
#define MY_SYNTH synth_dtlk
30
#define PROCSPEECH 0x00
31
#define synth_readable() ((synth_status = inb_p(synth_port_tts)) & TTS_READABLE) 
32
#define synth_full() ((synth_status = inb_p(synth_port_tts)) & TTS_ALMOST_FULL) 
33
34
static int synth_lpc;
35
static unsigned int synth_portlist[] =
36
		{ 0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0 };
37
static u_char synth_status = 0;
38
39
static void spk_out(const char ch)
40
{
41
	int tmout = 100000;
42
	while (((synth_status = inb_p(synth_port_tts)) & TTS_WRITABLE) == 0); 
43
	outb_p(ch, synth_port_tts);
44
	while ((((synth_status = inb_p(synth_port_tts)) & TTS_WRITABLE) != 0)
45
		&& (--tmout != 0) );
46
}
47
48
static void do_catch_up(unsigned long data)
49
{
50
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
51
	u_char ch;
52
	synth_stop_timer();
53
	synth_status = inb_p(synth_port_tts);
54
	while (synth_buff_out < synth_buff_in) {
55
		if (synth_status & TTS_ALMOST_FULL) {
56
			synth_delay(synth_full_time);
57
			return;
58
		}
59
		ch = *synth_buff_out++;
60
		if (ch == 0x0a) ch = PROCSPEECH;
61
		spk_out( ch );
62
		if (jiffies >= jiff_max && ch == SPACE) { 
63
			spk_out(PROCSPEECH);
64
			synth_delay(synth_delay_time); 
65
			return; 
66
		}
67
	}
68
	spk_out(PROCSPEECH);
69
	synth_done( );
70
}
71
72
static const char *synth_immediate(const char *buf )
73
{
74
	u_char ch;
75
	synth_status = inb_p(synth_port_tts);
76
	while ( (ch = (u_char)*buf ) ) {
77
		if (synth_status & TTS_ALMOST_FULL)
78
			return buf;
79
		if ( ch == 0x0a ) ch = PROCSPEECH;
80
		spk_out(ch);
81
		buf++;
82
	}
83
	return 0;
84
}
85
86
static unsigned char get_index( void )
87
{
88
        int c, lsr;//, tmout = SPK_SERIAL_TIMEOUT;
89
        lsr = inb_p( synth_port_tts + UART_LSR );
90
        if ( ( lsr & UART_LSR_DR) == UART_LSR_DR )
91
        {
92
                c = inb_p( synth_port_tts + UART_RX );
93
                return ( unsigned char ) c;
94
        }
95
        return 0;
96
}
97
98
static void synth_flush(void)
99
{
100
	outb_p(SYNTH_CLEAR, synth_port_tts);
101
	while (((synth_status = inb_p(synth_port_tts)) & TTS_WRITABLE) != 0);
102
	}
103
104
static char synth_read_tts(void)
105
{
106
	u_char ch;
107
	while (((synth_status = inb_p(synth_port_tts)) & TTS_READABLE) == 0);
108
	ch = synth_status & 0x7f;
109
	outb_p(ch, synth_port_tts);
110
	while ((inb_p(synth_port_tts) & TTS_READABLE) != 0);
111
return (char) ch;
112
}
113
114
/* interrogate the DoubleTalk PC and return its settings */
115
static struct synth_settings * synth_interrogate(void)
116
{
117
	u_char *t;
118
	static char buf[sizeof(struct synth_settings) + 1];
119
	int total, i;
120
	static struct synth_settings status;
121
	synth_immediate("\x18\x01?");
122
	for (total = 0, i = 0; i < 50; i++) {
123
			buf[total] = synth_read_tts();
124
			if (total > 2 && buf[total] == 0x7f) break;
125
			if (total < sizeof(struct synth_settings)) total++;
126
		}
127
	t = buf;
128
	status.serial_number = t[0] + t[1]*256; /* serial number is little endian */
129
	t += 2;
130
	for ( i = 0; *t != '\r'; t++ ) {
131
			status.rom_version[i] = *t;
132
			if (i < sizeof(status.rom_version)-1) i++;
133
		}
134
	status.rom_version[i] = 0;
135
	t++;
136
	status.mode = *t++;
137
	status.punc_level = *t++;
138
	status.formant_freq = *t++;
139
	status.pitch = *t++;
140
	status.speed = *t++;
141
	status.volume = *t++;
142
	status.tone = *t++;
143
	status.expression = *t++;
144
	status.ext_dict_loaded = *t++;
145
	status.ext_dict_status = *t++;
146
	status.free_ram = *t++;
147
	status.articulation = *t++;
148
	status.reverb = *t++;
149
	status.eob = *t++;
150
	return &status;
151
}
152
153
static int synth_probe(void)
154
{
155
		unsigned int port_val = 0;
156
	int i = 0;
157
	struct synth_settings *sp;
158
	pr_info("Probing for DoubleTalk.\n");
159
	if (synth_port_forced) {
160
		synth_port_tts = synth_port_forced;
161
		pr_info("probe forced to %x by kernel command line\n", synth_port_tts);
162
		if (synth_request_region(synth_port_tts-1, SYNTH_IO_EXTENT)) {
163
			pr_warn("sorry, port already reserved\n");
164
			return -EBUSY;
165
		}
166
		port_val = inw(synth_port_tts-1);
167
		synth_lpc = synth_port_tts-1;
168
	} else {
169
		for(i=0; synth_portlist[i]; i++) {
170
			if (synth_request_region(synth_portlist[i], SYNTH_IO_EXTENT))
171
	continue;
172
			port_val = inw(synth_portlist[i]);
173
			if ((port_val &= 0xfbff) == 0x107f) {
174
	synth_lpc = synth_portlist[i];
175
	synth_port_tts = synth_lpc+1;
176
	break;
177
			}
178
			synth_release_region(synth_portlist[i], SYNTH_IO_EXTENT);
179
		}
180
	}
181
	if ((port_val &= 0xfbff) != 0x107f) {
182
		pr_info("DoubleTalk PC:  not found\n");
183
		return -ENODEV;
184
	}
185
	while (inw_p(synth_lpc) != 0x147f ); /* wait until it's ready */
186
	sp = synth_interrogate();
187
	pr_info("%s:  %03x-%03x, ROM ver %s, s/n %u, driver: %s\n",
188
		synth->long_name, synth_lpc, synth_lpc+SYNTH_IO_EXTENT - 1,
189
	 sp->rom_version, sp->serial_number, synth->version);
190
	//	synth_alive = 1;
191
	return 0;
192
}
193
194
static int synth_is_alive(void)
195
{
196
	return 1;	/* I'm *INVINCIBLE* */
197
}
198
199
static void
200
dtlk_release( void )
201
{
202
	if ( synth_port_tts )
203
		synth_release_region(synth_port_tts-1, SYNTH_IO_EXTENT);
204
	synth_port_tts = 0;
205
}
206
207
static const char init_string[] = "\x01@\x01\x31y";
208
209
static struct st_string_var stringvars[] = {
210
	{ CAPS_START, "\x01+35p" },
211
	{ CAPS_STOP, "\x01-35p" },
212
	V_LAST_STRING
213
};
214
static struct st_num_var numvars[] = {
215
	{ RATE, "\x01%ds", 8, 0, 9, 0, 0, 0 },
216
	{ PITCH, "\x01%dp", 50, 0, 99, 0, 0, 0 },
217
	{ VOL, "\x01%dv", 5, 0, 9, 0, 0, 0 },
218
	{ TONE, "\x01%dx", 1, 0, 2, 0, 0, 0 },
219
	{ PUNCT, "\x01%db", 7, 0, 15, 0, 0, 0 },
220
	{ VOICE, "\x01%do", 0, 0, 7, 0, 0, 0 },
221
	{ FREQ, "\x01%df", 5, 0, 9, 0, 0, 0 },
222
	V_LAST_NUM
223
};
224
	 
225
struct spk_synth synth_dtlk = {"dtlk", "1.1", "DoubleTalk PC",
226
			   init_string, 500, 30, 50, 1000, 0, 0, SYNTH_CHECK,
227
	stringvars, numvars, synth_probe, dtlk_release, synth_immediate,
228
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, get_index,
229
	{"\x01%di",1,5,1} };
230
231
#ifdef MODULE
232
#include "mod_code.c"
233
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_dtlk.h (+54 lines)
Line 0 Link Here
1
/* speakup_dtlk.h - header file for speakups DoubleTalk driver. */
2
3
#define SYNTH_IO_EXTENT	0x02
4
#define SYNTH_CLEAR 0x18		/* stops speech */
5
	/* TTS Port Status Flags */
6
#define TTS_READABLE	   0x80	/* mask for bit which is nonzero if a
7
					 byte can be read from the TTS port */
8
#define TTS_SPEAKING	   0x40	/* mask for SYNC bit, which is nonzero
9
					 while DoubleTalk is producing
10
					 output with TTS, PCM or CVSD
11
					 synthesizers or tone generators
12
					 (that is, all but LPC) */
13
#define TTS_SPEAKING2	  0x20	/* mask for SYNC2 bit,
14
					 which falls to zero up to 0.4 sec
15
					 before speech stops */
16
#define TTS_WRITABLE	   0x10	/* mask for RDY bit, which when set to
17
	           			   1, indicates the TTS port is ready
18
	           			   to accept a byte of data.  The RDY
19
	           			   bit goes zero 2-3 usec after
20
	           			   writing, and goes 1 again 180-190
21
	           			   usec later. */
22
#define TTS_ALMOST_FULL	0x08	/* mask for AF bit: When set to 1,
23
					 indicates that less than 300 bytes
24
					 are available in the TTS input
25
					 buffer. AF is always 0 in the PCM,
26
					 TGN and CVSD modes. */
27
#define TTS_ALMOST_EMPTY 0x04	/* mask for AE bit: When set to 1,
28
					 indicates that less than 300 bytes
29
					 are remaining in DoubleTalk's input
30
					 (TTS or PCM) buffer. AE is always 1
31
					 in the TGN and CVSD modes. */
32
33
				/* data returned by Interrogate command */
34
struct synth_settings {
35
	u_short serial_number;	/* 0-7Fh:0-7Fh */
36
	u_char rom_version[24]; /* null terminated string */
37
	u_char mode;		/* 0=Character; 1=Phoneme; 2=Text */
38
	u_char punc_level;	/* nB; 0-7 */
39
	u_char formant_freq;	/* nF; 0-9 */
40
	u_char pitch;		/* nP; 0-99 */
41
	u_char speed;		/* nS; 0-9 */
42
	u_char volume;		/* nV; 0-9 */
43
	u_char tone;		/* nX; 0-2 */
44
	u_char expression;	/* nE; 0-9 */
45
	u_char ext_dict_loaded; /* 1=exception dictionary loaded */
46
	u_char ext_dict_status; /* 1=exception dictionary enabled */
47
	u_char free_ram;	/* # pages (truncated) remaining for
48
	                                 text buffer */
49
	u_char articulation;	/* nA; 0-9 */
50
	u_char reverb;		/* nR; 0-9 */
51
	u_char eob;		/* 7Fh value indicating end of
52
	                                 parameter block */
53
	u_char has_indexing;	/* nonzero if indexing is implemented */
54
};
(-)linux-2.6.20/drivers/char/speakup/speakup_keyhelp.c (+288 lines)
Line 0 Link Here
1
/* speakup_keyhelp.c
2
   help module for speakup
3
4
  written by David Borowski.
5
6
    Copyright (C ) 2003  David Borowski.
7
8
    This program is free software; you can redistribute it and/or modify
9
    it under the terms of the GNU General Public License as published by
10
    the Free Software Foundation; either version 2 of the License, or
11
    (at your option ) any later version.
12
13
    This program is distributed in the hope that it will be useful,
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
    GNU General Public License for more details.
17
18
    You should have received a copy of the GNU General Public License
19
    along with this program; if not, write to the Free Software
20
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
*/
22
23
#include <linux/version.h>
24
#include <linux/keyboard.h>
25
#include "spk_priv.h"
26
27
extern u_char *our_keys[];
28
extern special_func special_handler;
29
extern special_func help_handler;
30
#define MAXFUNCS 130
31
#define MAXKEYS 256
32
static u_short key_offsets[MAXFUNCS], key_buf[MAXKEYS];
33
static u_short masks[] = { 32, 16, 8, 4, 2, 1 };
34
static char help_info[] =
35
	"press space to leav help, cursor up or down to scroll, or a letter to go to commands in list";
36
static char *statenames[] = {
37
	" double", " speakup", " alt",
38
	" ctrl", " altgr", " shift"
39
};
40
static char *keynames[] = {
41
	"escape", "1", "2", "3", "4",
42
	"5", "6", "7", "8", "9",
43
	"0", "minus", "equal", "back space", "tab",
44
	"q", "w", "e", "r", "t",
45
	"y", "u", "i", "o", "p",
46
	"left brace", "right brace", "enter", "left control", "a",
47
	"s", "d", "f", "g", "h",
48
	"j", "k", "l", "semicolon", "apostrophe",
49
	"accent", "left shift", "back slash", "z", "x",
50
	"c", "v", "b", "n", "m",
51
	"comma", "dot", "slash", "right shift", "keypad asterisk",
52
	"left alt", "space", "caps lock", "f1", "f2",
53
	"f3", "f4", "f5", "f6", "f7",
54
	"f8", "f9", "f10", "num lock", "scroll lock",
55
	"keypad 7", "keypad 8", "keypad 9", "keypad minus", "keypad 4",
56
	"keypad 5", "keypad 6", "keypad plus", "keypad 1", "keypad 2",
57
	"keypad 3", "keypad 0", "keypad dot", "103rd", "f13",
58
	"102nd", "f11", "f12", "f14", "f15",
59
	"f16", "f17", "f18", "f19", "f20",
60
	"keypad enter", "right control", "keypad slash", "sysrq", "right alt",
61
	"line feed", "home", "up", "page up", "left",
62
	"right", "end", "down", "page down", "insert",
63
	"delete", "macro", "mute", "volume down", "volume up",
64
	"power", "keypad equal", "keypad plusminus", "pause", "f21",
65
	"f22", "f23", "f24", "keypad comma", "left meta",
66
	"right meta", "compose", "stop", "again", "props",
67
	"undo", "front", "copy", "open", "paste",
68
	"find", "cut", "help", "menu", "calc",
69
	"setup", "sleep", "wakeup", "file", "send file",
70
	"delete file", "transfer", "prog1", "prog2", "www",
71
	"msdos", "coffee", "direction", "cycle windows", "mail",
72
	"bookmarks", "computer", "back", "forward", "close cd",
73
	"eject cd", "eject close cd", "next song", "play pause", "previous song",
74
	"stop cd", "record", "rewind", "phone", "iso",
75
	"config", "home page", "refresh", "exit", "move",
76
	"edit", "scroll up", "scroll down", "keypad left paren", "keypad right paren",
77
};
78
79
static short letter_offsets[26];
80
81
static u_char funcvals[] = {
82
	ATTRIB_BLEEP_DEC, ATTRIB_BLEEP_INC, BLEEPS_DEC, BLEEPS_INC,
83
	SAY_FIRST_CHAR, SAY_LAST_CHAR, SAY_CHAR, SAY_CHAR_NUM,
84
	SAY_NEXT_CHAR, SAY_PHONETIC_CHAR, SAY_PREV_CHAR, SPEAKUP_PARKED,
85
	SPEAKUP_CUT, EDIT_DELIM, EDIT_EXNUM, EDIT_MOST,
86
	EDIT_REPEAT, EDIT_SOME, SPEAKUP_GOTO, BOTTOM_EDGE,
87
	LEFT_EDGE, RIGHT_EDGE, TOP_EDGE, SPEAKUP_HELP,
88
	SAY_LINE, SAY_NEXT_LINE, SAY_PREV_LINE, SAY_LINE_INDENT,
89
	SPEAKUP_PASTE, PITCH_DEC, PITCH_INC, PUNCT_DEC,
90
	PUNCT_INC, PUNC_LEVEL_DEC, PUNC_LEVEL_INC, SPEAKUP_QUIET,
91
	RATE_DEC, RATE_INC, READING_PUNC_DEC, READING_PUNC_INC,
92
	SAY_ATTRIBUTES, SAY_FROM_LEFT, SAY_FROM_TOP, SAY_POSITION,
93
	SAY_SCREEN, SAY_TO_BOTTOM, SAY_TO_RIGHT, SPK_KEY,
94
	SPK_LOCK, SPEAKUP_OFF, SPEECH_KILL, SPELL_DELAY_DEC,
95
	SPELL_DELAY_INC, SPELL_WORD, SPELL_PHONETIC, TONE_DEC,
96
	TONE_INC, VOICE_DEC, VOICE_INC, VOL_DEC,
97
	VOL_INC, CLEAR_WIN, SAY_WIN, SET_WIN,
98
	ENABLE_WIN, SAY_WORD, SAY_NEXT_WORD, SAY_PREV_WORD, 0
99
};
100
101
static char *funcnames[] = {
102
	"attribute bleep decrement", "attribute bleep increment",
103
	"bleeps decrement", "bleeps increment",
104
	"character, first", "character, last",
105
	"character, say current",
106
	"character, say hex and decimal", "character, say next",
107
	"character, say phonetic", "character, say previous",
108
	"cursor park", "cut",
109
	"edit delimiters", "edit exnum",
110
	"edit most", "edit repeats", "edit some",
111
	"go to", "go to bottom edge", "go to left edge",
112
	"go to right edge", "go to top edge", "help",
113
	"line, say current", "line, say next",
114
	"line, say previous", "line, say with indent",
115
	"paste", "pitch decrement", "pitch increment",
116
	"punctuation decrement", "punctuation increment",
117
	"punc  level decrement", "punc level increment",
118
	"quiet",
119
	"rate decrement", "rate increment",
120
	"reading punctuation decrement", "reading punctuation increment",
121
	"say attributes",
122
	"say from left", "say from top",
123
	"say position", "say screen",
124
	"say to bottom", "say to right",
125
	"speakup", "speakup lock",
126
	"speakup off", "speech kill",
127
	"spell delay decrement", "spell delay increment",
128
	"spell word", "spell word phoneticly",
129
	"tone decrement", "tone increment",
130
	"voice decrement", "voice increment",
131
	"volume decrement", "volume increment",
132
	"window, clear", "window, say",
133
	"window, set", "window, silence",
134
	"word, say current", "word, say next",
135
	"word, say previous", 0
136
};
137
138
static u_char *state_tbl;
139
static int cur_item = 0, nstates = 0;
140
141
static void build_key_data( void )
142
{
143
	u_char *kp, counters[MAXFUNCS], ch, ch1;
144
	u_short *p_key = key_buf, key;
145
	int i, offset = 1;
146
	nstates = (int)( state_tbl[-1] );
147
	memset( counters, 0, sizeof( counters ) );
148
	memset( key_offsets, 0, sizeof( key_offsets ) );
149
	kp = state_tbl + nstates + 1;
150
	while ( *kp++ ) { /* count occurrances of each function */
151
		for ( i = 0; i < nstates; i++, kp++ ) {
152
			if ( !*kp ) continue;
153
			if ( (state_tbl[i]&16) != 0 && *kp == SPK_KEY )
154
				continue;
155
			counters[*kp]++;
156
		}
157
	}
158
	for ( i = 0; i < MAXFUNCS; i++ ) {
159
		if ( counters[i] == 0 ) continue;
160
		key_offsets[i] = offset;
161
		offset += ( counters[i]+1 );
162
		if ( offset >= MAXKEYS ) break;
163
	}
164
/* leave counters set so high keycodes come first.
165
   this is done so num pad and other extended keys maps are spoken before
166
   the alpha with speakup type mapping. */
167
	kp = state_tbl + nstates + 1;
168
	while ( ( ch = *kp++ ) ) {
169
		for ( i = 0; i < nstates; i++ ) {
170
			ch1 = *kp++;
171
			if ( !ch1 ) continue;
172
			if ( (state_tbl[i]&16) != 0 && ch1 == SPK_KEY )
173
				continue;
174
			key = ( state_tbl[i]<<8 ) + ch;
175
			counters[ch1]--;
176
			if ( !(offset = key_offsets[ch1]) ) continue;
177
			p_key = key_buf + offset + counters[ch1];
178
			*p_key = key;
179
		}
180
	}
181
}
182
183
static void say_key( int key )
184
{
185
	int i, state = key>>8;
186
	key &= 0xff;
187
	for ( i = 0; i < 6; i++ ) {
188
		if ( ( state & masks[i] ) )
189
			synth_write_string( statenames[i] );
190
	}
191
	synth_write_string( " " );
192
		synth_write_msg( keynames[--key] );
193
}
194
195
static int handle_help ( struct vc_data *vc, u_char type, u_char ch, u_short key )
196
{
197
	int i, n;
198
	char *name;
199
	u_char func, *kp;
200
	u_short *p_keys, val;
201
	if ( type == KT_LATIN ) {
202
		if ( ch == SPACE ) {
203
			special_handler = NULL;
204
			synth_write_msg( "leaving help" );
205
			return 1;
206
		}
207
		ch |= 32; /* lower case */
208
		if ( ch < 'a' || ch > 'z' ) return -1;
209
		if ( letter_offsets[ch-'a'] == -1 ) {
210
			synth_write_string( "no commands for " );
211
			synth_write( &ch, 1 );
212
			synth_write( "\n", 1 );
213
			return 1;
214
		}
215
	cur_item	= letter_offsets[ch-'a'];
216
	} else if ( type == KT_CUR ) {
217
		if ( ch == 0 && funcnames[cur_item+1] != NULL )
218
			cur_item++;
219
		else if ( ch == 3 && cur_item > 0 )
220
			cur_item--;
221
		else return -1;
222
	} else if (type == KT_SPKUP && ch == SPEAKUP_HELP && !special_handler) {
223
		special_handler = help_handler;
224
		synth_write_msg( help_info );
225
		build_key_data( ); /* rebuild each time in case new mapping */
226
		return 1;
227
	} else {
228
		name = NULL;
229
		if ( type != KT_SPKUP ) {
230
			synth_write_msg( keynames[key-1] );
231
			return 1;
232
		}
233
		for ( i = 0; funcvals[i] != 0 && !name; i++ ) {
234
			if ( ch == funcvals[i] )
235
				name = funcnames[i];
236
		}
237
		if ( !name ) return -1;
238
		kp = our_keys[key]+1;
239
		for ( i = 0; i < nstates; i++ ) {
240
			if ( ch == kp[i] ) break;
241
		}
242
		key += ( state_tbl[i]<<8 );
243
		say_key( key );
244
		synth_write_string( "is " );
245
		synth_write_msg( name );
246
		return 1;
247
	}
248
	name = funcnames[cur_item];
249
	func = funcvals[cur_item];
250
	synth_write_string( name );
251
	if ( key_offsets[func] == 0 ) {
252
		synth_write_msg( " is unassigned" );
253
		return 1;
254
	}
255
	p_keys = key_buf + key_offsets[func];
256
	for ( n = 0; p_keys[n]; n++ ) {
257
		val = p_keys[n];
258
		if ( n > 0 ) synth_write_string( "or " );
259
		say_key( val );
260
	}
261
	return 1;
262
}
263
264
static void __exit mod_help_exit( void )
265
{
266
	help_handler = 0;
267
}
268
269
static int __init mod_help_init( void )
270
{
271
	char start = SPACE;
272
	int i;
273
state_tbl = our_keys[0]+SHIFT_TBL_SIZE+2;
274
	for (i = 0; i < 26; i++ ) letter_offsets[i] = -1;
275
	for ( i = 0; funcnames[i]; i++ ) {
276
		if ( start == *funcnames[i] ) continue;
277
		start = *funcnames[i];
278
		letter_offsets[(start&31)-1] = i;
279
	}
280
	help_handler = handle_help;
281
	return 0;
282
}
283
284
module_init( mod_help_init );
285
module_exit( mod_help_exit );
286
MODULE_AUTHOR("David Borowski");
287
MODULE_DESCRIPTION("Speakup keyboard help MODULE");
288
MODULE_LICENSE("GPL");
(-)linux-2.6.20/drivers/char/speakup/speakup_keypc.c (+190 lines)
Line 0 Link Here
1
/*
2
* written by David Borowski
3
4
		Copyright (C) 2003 David Borowski.
5
6
		This program is free software; you can redistribute it and/or modify
7
		it under the terms of the GNU General Public License as published by
8
		the Free Software Foundation; either version 2 of the License, or
9
		(at your option) any later version.
10
11
		This program is distributed in the hope that it will be useful,
12
		but WITHOUT ANY WARRANTY; without even the implied warranty of
13
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
		GNU General Public License for more details.
15
16
		You should have received a copy of the GNU General Public License
17
		along with this program; if not, write to the Free Software
18
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20
 * this code is specificly written as a driver for the speakup screenreview
21
 * package and is not a general device driver.
22
		*/
23
#include "spk_priv.h"
24
25
#define MY_SYNTH synth_keypc
26
#define SYNTH_IO_EXTENT	0x04
27
#define SWAIT udelay( 70 )
28
#define synth_writable( ) ( inb_p( synth_port ) & 0x10 )
29
#define synth_readable( ) ( inb_p( synth_port ) & 0x10 )
30
#define synth_full( ) ( ( inb_p( synth_port ) & 0x80 ) == 0 )
31
#define PROCSPEECH 0x1f
32
#define SYNTH_CLEAR 0x03
33
34
static int synth_port;
35
static unsigned int synth_portlist[] =
36
    { 0x2a8, 0 };
37
38
static int 
39
oops( void ) 
40
{
41
	int s1, s2, s3, s4;
42
	s1 = inb_p( synth_port );
43
	s2 = inb_p( synth_port+1 );
44
	s3 = inb_p( synth_port+2 );
45
	s4 = inb_p( synth_port+3 );
46
	pr_warn( "synth timeout %d %d %d %d\n", s1, s2, s3, s4 );
47
	return 0;
48
}
49
50
static const char *synth_immediate ( const char *buf )
51
{
52
	u_char ch;
53
	int timeout;
54
	while (  (  ch = *buf ) ) {
55
		if ( ch == 0x0a ) ch = PROCSPEECH;
56
		if ( synth_full( ) )
57
			return buf;
58
	timeout = 1000;
59
		while ( synth_writable( ) )
60
			if ( --timeout <= 0 ) return (char *) oops( );
61
		outb_p( ch, synth_port );
62
		SWAIT;
63
	buf++;
64
	}
65
	return 0;
66
}
67
68
static void do_catch_up( unsigned long data )
69
{
70
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
71
	u_char ch;
72
	int timeout;
73
	synth_stop_timer( );
74
	while (  synth_buff_out < synth_buff_in ) {
75
 		if ( synth_full( ) ) {
76
			synth_delay( synth_full_time );
77
			return;
78
		}
79
	timeout = 1000;
80
		while ( synth_writable( ) )
81
			if ( --timeout <= 0 ) break;
82
		if ( timeout <= 0 ) {
83
			oops( );
84
			break;
85
		}
86
		ch = *synth_buff_out++;
87
	if ( ch == 0x0a ) ch = PROCSPEECH;
88
		outb_p( ch, synth_port );
89
		SWAIT;
90
		if ( jiffies >= jiff_max && ch == SPACE ) {
91
	timeout = 1000;
92
		while ( synth_writable( ) )
93
			if ( --timeout <= 0 ) break;
94
		if ( timeout <= 0 ) {
95
			oops( );
96
			break;
97
			}
98
			outb_p( PROCSPEECH, synth_port );
99
			synth_delay( synth_delay_time ); 
100
			return; 
101
		}
102
	}
103
	timeout = 1000;
104
		while ( synth_writable( ) )
105
			if ( --timeout <= 0 ) break;
106
		if ( timeout <= 0 ) oops( );
107
			else
108
	outb_p( PROCSPEECH, synth_port );
109
	synth_done(  );
110
}
111
112
static void synth_flush( void )
113
{
114
	outb_p( SYNTH_CLEAR, synth_port );
115
}
116
117
static int synth_probe( void )
118
{
119
	unsigned int port_val = 0;
120
	int i = 0;
121
	pr_info( "Probing for %s.\n", synth->long_name );
122
	if ( synth_port_forced ) {
123
		synth_port = synth_port_forced;
124
		pr_info( "probe forced to %x by kernel command line\n", synth_port );
125
		if ( synth_request_region( synth_port-1, SYNTH_IO_EXTENT ) ) {
126
			pr_warn( "sorry, port already reserved\n" );
127
			return -EBUSY;
128
		}
129
		port_val = inb( synth_port );
130
	} else {
131
		for( i=0; synth_portlist[i]; i++ ) {
132
			if ( synth_request_region( synth_portlist[i], SYNTH_IO_EXTENT ) ) {
133
				pr_warn( "request_region:  failed with 0x%x, %d\n",
134
					synth_portlist[i], SYNTH_IO_EXTENT );
135
				continue;
136
			}
137
			port_val = inb( synth_portlist[i] );
138
			if ( port_val == 0x80 ) {
139
				synth_port = synth_portlist[i];
140
				break;
141
			}
142
		}
143
	}
144
	if ( port_val != 0x80 ) {
145
		pr_info( "%s:  not found\n", synth->long_name );
146
		synth_release_region( synth_portlist[i], SYNTH_IO_EXTENT );
147
		synth_port = 0;
148
		return -ENODEV;
149
	}
150
	pr_info( "%s:  %03x-%03x, driver version %s,\n", synth->long_name,
151
		synth_port,	synth_port+SYNTH_IO_EXTENT-1, 
152
		synth->version );
153
	return 0;
154
}
155
156
static void keynote_release(  void )
157
{
158
	if (  synth_port )
159
		synth_release_region( synth_port, SYNTH_IO_EXTENT );
160
	synth_port = 0;
161
}
162
163
static int synth_is_alive( void )
164
{
165
	synth_alive = 1;
166
	return 1;
167
}
168
169
static const char init_string[] = "[t][n7,1][n8,0]";
170
171
static struct st_string_var stringvars[] = {
172
	{ CAPS_START, "[f130]" },
173
	{ CAPS_STOP, "[f90]" },
174
	V_LAST_STRING
175
};
176
static struct st_num_var numvars[] = {
177
	{ RATE, "\04%c ", 8, 0, 10, 81, -8, 0 },
178
	{ PITCH, "[f%d]", 5, 0, 9, 40, 10, 0 },
179
	V_LAST_NUM
180
};
181
182
struct spk_synth synth_keypc = {"keypc", "1.1", "Keynote PC",
183
	 init_string, 500, 50, 50, 1000, 0, 0, SYNTH_CHECK,
184
	stringvars, numvars, synth_probe, keynote_release, synth_immediate,
185
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL,
186
	{NULL,0,0,0} };
187
188
#ifdef MODULE
189
#include "mod_code.c"
190
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_ltlk.c (+229 lines)
Line 0 Link Here
1
/*
2
 * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
3
* this version considerably modified by David Borowski, david575@rogers.com
4
5
		Copyright (C) 1998-99  Kirk Reiser.
6
		Copyright (C) 2003 David Borowski.
7
8
		This program is free software; you can redistribute it and/or modify
9
		it under the terms of the GNU General Public License as published by
10
		the Free Software Foundation; either version 2 of the License, or
11
		(at your option) any later version.
12
13
		This program is distributed in the hope that it will be useful,
14
		but WITHOUT ANY WARRANTY; without even the implied warranty of
15
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
		GNU General Public License for more details.
17
18
		You should have received a copy of the GNU General Public License
19
		along with this program; if not, write to the Free Software
20
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22
 * this code is specificly written as a driver for the speakup screenreview
23
 * package and is not a general device driver.
24
		*/
25
#include "spk_priv.h"
26
#include "serialio.h"
27
28
#include "speakup_dtlk.h" /* local header file for LiteTalk values */
29
30
#define MY_SYNTH synth_ltlk
31
#define PROCSPEECH 0x0d
32
#define synth_full( ) ( !( inb( synth_port_tts + UART_MSR ) & UART_MSR_CTS ) )
33
34
static int wait_for_xmitr( void )
35
{
36
	static int timeouts = 0;	/* sequential number of timeouts */
37
	int check, tmout = SPK_XMITR_TIMEOUT;
38
	if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) {
39
		synth_alive = 0; 
40
		timeouts = 0;
41
		return 0; 
42
	}
43
	do { /* holding register empty? */
44
		check = inb( synth_port_tts + UART_LSR );
45
    		if ( --tmout == 0 ) {
46
    			pr_warn( "%s:  register timed out\n", synth->long_name );
47
			timeouts++;
48
    			return 0;
49
    		}
50
	} while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY );
51
	tmout = SPK_XMITR_TIMEOUT;
52
	do { /* CTS */
53
		check = inb( synth_port_tts + UART_MSR );
54
    		if ( --tmout == 0 ) {
55
    			timeouts++;
56
    			return 0;
57
    		}
58
	} while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS );
59
	timeouts = 0;
60
	return 1;
61
}
62
63
static int spk_serial_out( const char ch )
64
{
65
	if ( synth_alive && wait_for_xmitr( ) ) {
66
		outb( ch, synth_port_tts );
67
		return 1;
68
	}
69
	return 0;
70
}
71
72
static unsigned char spk_serial_in( void )
73
{
74
	int c, lsr, tmout = SPK_SERIAL_TIMEOUT;
75
	do {
76
		lsr = inb( synth_port_tts + UART_LSR );
77
		if ( --tmout == 0 ) {
78
			pr_warn( "time out while waiting for input.\n" );
79
			return 0xff; 
80
		}
81
	} while ( ( lsr & UART_LSR_DR ) != UART_LSR_DR );
82
	c = inb( synth_port_tts + UART_RX );
83
	return ( unsigned char ) c;
84
}
85
86
static void do_catch_up( unsigned long data )
87
{
88
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
89
	u_char ch;
90
	synth_stop_timer( );
91
	while ( synth_buff_out < synth_buff_in ) {
92
		ch = *synth_buff_out;
93
		if ( ch == 0x0a ) ch = PROCSPEECH;
94
		if ( !spk_serial_out( ch ) ) {
95
			synth_delay( synth_full_time );
96
			return;
97
		}
98
		synth_buff_out++;
99
		if ( jiffies >= jiff_max && ch == SPACE ) {
100
			spk_serial_out( PROCSPEECH );
101
			synth_delay( synth_delay_time ); 
102
			return; 
103
		}
104
	}
105
	spk_serial_out( PROCSPEECH );
106
	synth_done ( );
107
}
108
109
static const char *synth_immediate ( const char *buf )
110
{
111
	u_char ch;
112
	while ( ( ch = *buf ) ) {
113
	if ( ch == 0x0a ) ch = PROCSPEECH;
114
        if ( wait_for_xmitr( ) )
115
	  outb( ch, synth_port_tts );
116
	else return buf;
117
	buf++;
118
	}
119
	return 0;
120
}
121
122
static void synth_flush( void )
123
{
124
	spk_serial_out( SYNTH_CLEAR );
125
}
126
127
static unsigned char get_index( void )
128
{
129
	int c, lsr;//, tmout = SPK_SERIAL_TIMEOUT;
130
	lsr = inb( synth_port_tts + UART_LSR );
131
	if ( ( lsr & UART_LSR_DR) == UART_LSR_DR )
132
	{
133
		c = inb( synth_port_tts + UART_RX );
134
		return ( unsigned char ) c;
135
	}
136
	return 0;
137
}
138
139
/* interrogate the LiteTalk and print its settings */
140
static void synth_interrogate( void )
141
{
142
	unsigned char *t, i;
143
	unsigned char buf[50], rom_v[20];
144
	synth_immediate( "\x18\x01?" );
145
	for ( i = 0; i < 50; i++ ) {
146
		buf[i] = spk_serial_in( );
147
		if ( i > 2 && buf[i] == 0x7f ) break;
148
	}
149
	t = buf+2;
150
	for ( i = 0; *t != '\r'; t++ ) {
151
		rom_v[i] = *t;
152
		if (i++ > 48) break;
153
	}
154
	rom_v[i] = 0;
155
	pr_info( "%s: ROM version: %s\n", synth->long_name, rom_v );
156
}
157
158
static int serprobe( int index )
159
{
160
	struct serial_state *ser = spk_serial_init( index );
161
	if ( ser == NULL ) return -1;
162
	outb( 0, ser->port );
163
	mdelay( 1 );
164
	outb( '\r', ser->port );
165
	/* ignore any error results, if port was forced */
166
	if ( synth_port_forced ) return 0;
167
	/* check for device... */
168
	if ( !synth_immediate( "\x18" ) ) return 0;	
169
	spk_serial_release( );
170
	synth_alive = 0; /* try next port */
171
	return -1;
172
}
173
174
static int synth_probe( void )
175
{
176
	int i, failed=0;
177
	pr_info( "Probing for %s.\n", synth->long_name );
178
	for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) {
179
	  if (( failed = serprobe( i )) == 0 ) break; /* found it */
180
	}
181
	if ( failed ) {
182
	  pr_info( "%s:  not found\n", synth->long_name );
183
	  return -ENODEV;
184
	}
185
	synth_interrogate( );
186
	pr_info( "%s: at  %03x-%03x, driver %s\n", synth->long_name,
187
	       synth_port_tts, synth_port_tts + 7, synth->version );
188
	return 0;
189
}
190
191
static int synth_is_alive( void )
192
{
193
	if ( synth_alive ) return 1;
194
	if ( !synth_alive && wait_for_xmitr( ) > 0 ) { /* restart */
195
		synth_alive = 1;
196
		synth_write_string( synth->init );
197
		return 2;
198
	} else pr_warn( "%s: can't restart synth\n", synth->long_name );
199
	return 0;
200
}
201
202
static const char init_string[] = "\01@\x01\x31y\n\0";
203
204
static struct st_string_var stringvars[] = {
205
	{ CAPS_START, "\x01+35p" },
206
	{ CAPS_STOP, "\x01-35p" },
207
	V_LAST_STRING
208
};
209
210
static struct st_num_var numvars[] = {
211
	{ RATE, "\x01%ds", 8, 0, 9, 0, 0, 0 },
212
	{ PITCH, "\x01%dp", 50, 0, 99, 0, 0, 0 },
213
	{ VOL, "\x01%dv", 5, 0, 9, 0, 0, 0 },
214
	{ TONE, "\x01%dx", 1, 0, 2, 0, 0, 0 },
215
	{ PUNCT, "\x01%db", 7, 0, 15, 0, 0, 0 },
216
	{ VOICE, "\x01%do", 0, 0, 7, 0, 0, 0 },
217
	{ FREQ, "\x01%df", 5, 0, 9, 0, 0, 0 },
218
	V_LAST_NUM
219
};
220
221
struct spk_synth synth_ltlk = { "ltlk", "1.1", "LiteTalk",
222
	init_string, 500, 50, 50, 5000, 0, 0, SYNTH_CHECK,
223
	stringvars, numvars, synth_probe, spk_serial_release, synth_immediate,
224
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, get_index,
225
	{"\x01%di",1,5,1} };
226
227
#ifdef MODULE
228
#include "mod_code.c"
229
#endif
(-)linux-2.6.20/drivers/char/speakup/speakupmap.h (+65 lines)
Line 0 Link Here
1
	119, 62, 6,
2
	0, 16, 20, 17, 32, 48, 0,
3
	2, 0, 78, 0, 0, 0, 0,
4
	3, 0, 79, 0, 0, 0, 0,
5
	4, 0, 76, 0, 0, 0, 0,
6
	5, 0, 77, 0, 0, 0, 0,
7
	6, 0, 74, 0, 0, 0, 0,
8
	7, 0, 75, 0, 0, 0, 0,
9
	9, 0, 5, 46, 0, 0, 0,
10
	10, 0, 4, 0, 0, 0, 0,
11
	11, 0, 0, 1, 0, 0, 0,
12
	12, 0, 27, 0, 33, 0, 0,
13
	19, 0, 47, 0, 0, 0, 0,
14
	21, 0, 29, 17, 0, 0, 0,
15
	22, 0, 15, 0, 0, 0, 0,
16
	23, 0, 14, 0, 0, 0, 28,
17
	24, 0, 16, 0, 0, 0, 0,
18
	25, 0, 30, 18, 0, 0, 0,
19
	28, 0, 3, 26, 0, 0, 0,
20
	35, 0, 31, 0, 0, 0, 0,
21
	36, 0, 12, 0, 0, 0, 0,
22
	37, 0, 11, 0, 0, 0, 22,
23
	38, 0, 13, 0, 0, 0, 0,
24
	39, 0, 32, 7, 0, 0, 0,
25
	40, 0, 23, 0, 0, 0, 0,
26
	44, 0, 44, 0, 0, 0, 0,
27
	49, 0, 24, 0, 0, 0, 0,
28
	50, 0, 9, 19, 6, 0, 0,
29
	51, 0, 8, 0, 0, 0, 36,
30
	52, 0, 10, 20, 0, 0, 0,
31
	53, 0, 25, 0, 0, 0, 0,
32
	55, 46, 1, 0, 0, 0, 0,
33
	58, 128, 128, 0, 0, 0, 0,
34
	59, 0, 45, 0, 0, 0, 0,
35
	60, 0, 40, 0, 0, 0, 0,
36
	61, 0, 41, 0, 0, 0, 0,
37
	62, 0, 42, 0, 0, 0, 0,
38
	63, 0, 34, 0, 0, 0, 0,
39
	64, 0, 35, 0, 0, 0, 0,
40
	65, 0, 37, 0, 0, 0, 0,
41
	66, 0, 38, 0, 0, 0, 0,
42
	67, 0, 66, 0, 39, 0, 0,
43
	68, 0, 67, 0, 0, 0, 0,
44
	71, 15, 19, 0, 0, 0, 0,
45
	72, 14, 29, 0, 0, 28, 0,
46
	73, 16, 17, 0, 0, 0, 0,
47
	74, 27, 33, 0, 0, 0, 0,
48
	75, 12, 31, 0, 0, 0, 0,
49
	76, 11, 21, 0, 0, 22, 0,
50
	77, 13, 32, 0, 0, 0, 0,
51
	78, 23, 43, 0, 0, 0, 0,
52
	79, 9, 20, 0, 0, 0, 0,
53
	80, 8, 30, 0, 0, 36, 0,
54
	81, 10, 18, 0, 0, 0, 0,
55
	82, 128, 128, 0, 0, 0, 0,
56
	83, 24, 25, 0, 0, 0, 0,
57
	87, 0, 68, 0, 0, 0, 0,
58
	88, 0, 69, 0, 0, 0, 0,
59
	96, 3, 26, 0, 0, 0, 0,
60
	98, 4, 5, 0, 0, 0, 0,
61
	99, 2, 0, 0, 0, 0, 0,
62
	104, 0, 6, 0, 0, 0, 0,
63
	109, 0, 7, 0, 0, 0, 0,
64
	125, 128, 128, 0, 0, 0, 0,
65
	0, 119
(-)linux-2.6.20/drivers/char/speakup/speakupmap.map (+93 lines)
Line 0 Link Here
1
spk key_f9 = punc_level_dec
2
spk key_f10 = punc_level_inc
3
spk key_f11 = reading_punc_dec
4
spk key_f12 = reading_punc_inc
5
spk key_1 = vol_dec
6
spk key_2 =  vol_inc
7
spk key_3 = pitch_dec
8
spk key_4 = pitch_inc
9
spk key_5 = rate_dec
10
spk key_6 = rate_inc
11
key_kpasterisk = toggle_cursoring
12
ctrl spk key_8 = toggle_cursoring
13
spk key_kpasterisk = speakup_goto
14
spk key_f1 = speakup_help
15
spk key_f2 = set_win
16
spk key_f3 = clear_win
17
spk key_f4 = enable_win
18
spk key_f5 = edit_some
19
spk key_f6 = edit_most
20
spk key_f7 = edit_delim
21
spk key_f8 = edit_repeat
22
shift spk key_f9 = edit_exnum
23
 key_kp7 = say_prev_line
24
spk key_kp7 = left_edge
25
 key_kp8 = say_line
26
double  key_kp8 = say_line_indent
27
spk key_kp8 = say_from_top
28
 key_kp9 = say_next_line
29
spk  key_kp9 = top_edge
30
 key_kpminus = speakup_parked
31
spk key_kpminus = say_char_num
32
 key_kp4 = say_prev_word
33
spk key_kp4 = say_from_left
34
 key_kp5 = say_word
35
double key_kp5 = spell_word
36
spk key_kp5 = spell_phonetic
37
 key_kp6 = say_next_word
38
spk key_kp6 = say_to_right
39
 key_kpplus = say_screen
40
spk key_kpplus = say_win
41
 key_kp1 = say_prev_char 
42
spk key_kp1 = right_edge
43
 key_kp2 = say_char
44
spk key_kp2 = say_to_bottom
45
double key_kp2 = say_phonetic_char
46
 key_kp3 = say_next_char  
47
spk  key_kp3 = bottom_edge
48
 key_kp0 = spk_key
49
 key_kpdot = say_position
50
spk key_kpdot = say_attributes
51
key_kpenter = speakup_quiet
52
spk key_kpenter = speakup_off
53
key_sysrq = speech_kill
54
 key_kpslash = speakup_cut
55
spk key_kpslash = speakup_paste
56
spk key_pageup = say_first_char
57
spk key_pagedown = say_last_char
58
key_capslock = spk_key
59
 spk key_z = spk_lock
60
key_leftmeta = spk_key
61
ctrl spk key_0 = speakup_goto
62
spk key_u = say_prev_line
63
spk key_i = say_line
64
double spk key_i = say_line_indent
65
spk key_o = say_next_line
66
spk key_minus = speakup_parked
67
shift spk key_minus = say_char_num
68
spk key_j = say_prev_word
69
spk key_k = say_word
70
double spk key_k = spell_word
71
spk key_l = say_next_word
72
spk key_m = say_prev_char
73
spk key_comma = say_char
74
double spk key_comma = say_phonetic_char
75
spk key_dot = say_next_char
76
spk key_n = say_position
77
 ctrl spk key_m = left_edge
78
 ctrl spk key_y = top_edge
79
 ctrl spk key_dot = right_edge
80
ctrl spk key_p = bottom_edge
81
spk key_apostrophe = say_screen
82
spk key_h = say_from_left
83
spk key_y = say_from_top
84
spk key_semicolon = say_to_right
85
spk key_p = say_to_bottom
86
spk key_slash = say_attributes
87
 spk key_enter = speakup_quiet
88
 ctrl  spk key_enter = speakup_off
89
 spk key_9 = speakup_cut
90
spk key_8 = speakup_paste
91
shift spk key_m = say_first_char
92
 ctrl spk key_semicolon = say_last_char
93
spk key_r = read_all_doc
(-)linux-2.6.20/drivers/char/speakup/speakup_sftsyn.c (+206 lines)
Line 0 Link Here
1
/* speakup_sftsynth.c - speakup driver to register and make available
2
 * a user space device for software synthesizers.  written by: Kirk
3
 * Reiser <kirk@braille.uwo.ca>
4
5
		Copyright (C) 2003  Kirk Reiser.
6
7
		This program is free software; you can redistribute it and/or modify
8
		it under the terms of the GNU General Public License as published by
9
		the Free Software Foundation; either version 2 of the License, or
10
		(at your option) any later version.
11
12
		This program is distributed in the hope that it will be useful,
13
		but WITHOUT ANY WARRANTY; without even the implied warranty of
14
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
		GNU General Public License for more details.
16
17
		You should have received a copy of the GNU General Public License
18
		along with this program; if not, write to the Free Software
19
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21
 * this code is specificly written as a driver for the speakup screenreview
22
 * package and is not a general device driver.  */
23
24
#include <linux/unistd.h>
25
#include <asm/semaphore.h>
26
#include <linux/miscdevice.h>   /* for misc_register, and SYNTH_MINOR */
27
#include <linux/poll.h>  // for poll_wait()
28
#include "spk_priv.h"
29
30
#define MY_SYNTH synth_sftsyn
31
#define SOFTSYNTH_MINOR 26  // might as well give it one more than /dev/synth
32
#define PROCSPEECH 0x0d
33
#define CLEAR_SYNTH 0x18
34
35
static struct miscdevice synth_device;
36
static int misc_registered = 0;
37
static int dev_opened = 0;
38
static DECLARE_MUTEX(sem);
39
DECLARE_WAIT_QUEUE_HEAD ( wait_on_output );
40
41
42
static int softsynth_open (struct inode *inode, struct file *fp)
43
{
44
        if (dev_opened) return -EBUSY;
45
	//if ((fp->f_flags & O_ACCMODE) != O_RDONLY ) return -EPERM;
46
	dev_opened++;
47
        return 0;
48
}
49
50
static int softsynth_close (struct inode *inode, struct file *fp)
51
{
52
        fp->f_op = NULL;
53
	dev_opened = 0;
54
	return 0;
55
}
56
57
static ssize_t softsynth_read (struct file *fp, char *buf, size_t count, loff_t *pos)
58
{
59
	int chars_sent=0;
60
61
        if (down_interruptible( &sem )) return -ERESTARTSYS;
62
        while (synth_buff_in == synth_buff_out) {
63
	  up ( &sem );
64
	  if (fp->f_flags & O_NONBLOCK)
65
	    return -EAGAIN;
66
	  if (wait_event_interruptible( wait_on_output, (synth_buff_in > synth_buff_out)))
67
	    return -ERESTARTSYS;
68
	  if (down_interruptible( &sem )) return -ERESTARTSYS;
69
	}
70
71
	chars_sent = (count > synth_buff_in-synth_buff_out) 
72
	  ? synth_buff_in-synth_buff_out : count;
73
	if (copy_to_user(buf, (char *) synth_buff_out, chars_sent)) {
74
	  up ( &sem);
75
	  return -EFAULT;
76
	}
77
	synth_buff_out += chars_sent;
78
	*pos += chars_sent;
79
	if (synth_buff_out >= synth_buff_in) {
80
	  synth_done();
81
	  *pos = 0;
82
	}
83
	up ( &sem );
84
	return chars_sent;
85
}
86
87
static int last_index=0;
88
89
static ssize_t softsynth_write (struct file *fp, const char *buf, size_t count, loff_t *pos)
90
{
91
	int i;
92
	char indbuf[5];
93
	if (down_interruptible( &sem))
94
		return -ERESTARTSYS;
95
96
	if (copy_from_user(indbuf,buf,count))
97
	{
98
		up(&sem);
99
		return -EFAULT;
100
	}
101
	up(&sem);
102
	last_index=0;
103
	for (i=0;i<strlen(indbuf);i++)
104
		last_index=last_index*10+indbuf[i]-48;
105
	return count;
106
}
107
108
static unsigned int softsynth_poll (struct file *fp, struct poll_table_struct *wait)
109
{
110
        poll_wait(fp, &wait_on_output, wait);
111
112
	if (synth_buff_out < synth_buff_in)
113
	  return (POLLIN | POLLRDNORM);
114
	return 0;
115
}
116
117
static void 
118
softsynth_flush( void )
119
{
120
	synth_write( "\x18", 1 );
121
}
122
123
static unsigned char get_index( void )
124
{
125
	int rv;
126
	rv=last_index;
127
	last_index=0;
128
	return rv;
129
}
130
131
static struct file_operations softsynth_fops = {
132
        poll:softsynth_poll,
133
        read:softsynth_read,
134
	write:softsynth_write,
135
        open:softsynth_open,
136
        release:softsynth_close,
137
};
138
 
139
140
static int 
141
softsynth_probe( void )
142
{
143
144
        if ( misc_registered != 0 ) return 0;
145
	memset( &synth_device, 0, sizeof( synth_device ) );
146
        synth_device.minor = SOFTSYNTH_MINOR;
147
        synth_device.name = "softsynth";
148
        synth_device.fops = &softsynth_fops;
149
        if ( misc_register ( &synth_device ) ) {
150
	  pr_warn("Couldn't initialize miscdevice /dev/softsynth.\n" );
151
	  return -ENODEV;
152
        }
153
154
        misc_registered = 1;
155
	pr_info("initialized device: /dev/softsynth, node (MAJOR 10, MINOR 26)\n" );
156
	return 0;
157
}
158
159
static void 
160
softsynth_release(void)
161
{
162
        misc_deregister( &synth_device );
163
	misc_registered = 0;
164
	pr_info("unregistered /dev/softsynth\n");
165
}
166
167
static void 
168
softsynth_start ( void )
169
{
170
        wake_up_interruptible ( &wait_on_output );
171
}
172
173
static int 
174
softsynth_is_alive( void )
175
{
176
	if ( synth_alive ) return 1;
177
	return 0;
178
}
179
180
static const char init_string[] = "\01@\x01\x31y\n";
181
182
static struct st_string_var stringvars[] = {
183
	{ CAPS_START, "\x01+3p" },
184
	{ CAPS_STOP, "\x01-3p" },
185
	V_LAST_STRING
186
};
187
static struct st_num_var numvars[] = {
188
	{ RATE, "\x01%ds", 5, 0, 9, 0, 0, 0 },
189
	{ PITCH, "\x01%dp", 5, 0, 9, 0, 0, 0 },
190
	{ VOL, "\x01%dv", 5, 0, 9, 0, 0, 0 },
191
	{ TONE, "\x01%dx", 1, 0, 2, 0, 0, 0 },
192
	{ PUNCT, "\x01%db", 7, 0, 15, 0, 0, 0 },
193
	{ VOICE, "\x01%do", 0, 0, 7, 0, 0, 0 },
194
	{ FREQ, "\x01%df", 5, 0, 9, 0, 0, 0 },
195
	V_LAST_NUM
196
};
197
198
struct spk_synth synth_sftsyn = { "sftsyn", "0.3", "software synth",
199
	init_string, 0, 0, 0, 0, 0, 0, SYNTH_CHECK,
200
	stringvars, numvars, softsynth_probe, softsynth_release, NULL,
201
	NULL, softsynth_start, softsynth_flush, softsynth_is_alive, NULL, NULL,
202
	get_index, {"\x01%di",1,5,1} };
203
204
#ifdef MODULE
205
#include "mod_code.c"
206
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_spkout.c (+201 lines)
Line 0 Link Here
1
/*
2
 * originially written by: Kirk Reiser <kirk@braille.uwo.ca>
3
* this version considerably modified by David Borowski, david575@rogers.com
4
5
		Copyright (C) 1998-99  Kirk Reiser.
6
		Copyright (C) 2003 David Borowski.
7
8
		This program is free software; you can redistribute it and/or modify
9
		it under the terms of the GNU General Public License as published by
10
		the Free Software Foundation; either version 2 of the License, or
11
		(at your option) any later version.
12
13
		This program is distributed in the hope that it will be useful,
14
		but WITHOUT ANY WARRANTY; without even the implied warranty of
15
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
		GNU General Public License for more details.
17
18
		You should have received a copy of the GNU General Public License
19
		along with this program; if not, write to the Free Software
20
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22
 * this code is specificly written as a driver for the speakup screenreview
23
 * package and is not a general device driver.
24
		*/
25
#include "spk_priv.h"
26
#include "serialio.h"
27
28
#define MY_SYNTH synth_spkout
29
#define SYNTH_CLEAR 0x18
30
#define PROCSPEECH '\r'
31
32
static int wait_for_xmitr(void)
33
{
34
	static int timeouts = 0;	/* sequential number of timeouts */
35
	int check, tmout = SPK_XMITR_TIMEOUT;
36
	if ((synth_alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) {
37
		synth_alive = 0; 
38
		timeouts = 0;
39
		return 0; 
40
	}
41
	do {
42
		check = inb(synth_port_tts + UART_LSR);
43
		if (--tmout == 0) {
44
			pr_warn("SpeakOut:  timed out\n");
45
			timeouts++;
46
			return 0;
47
		}
48
	} while ((check & BOTH_EMPTY) != BOTH_EMPTY);
49
	tmout = SPK_XMITR_TIMEOUT;
50
	do {
51
		check = inb(synth_port_tts + UART_MSR);
52
				if (--tmout == 0) {
53
					timeouts++;
54
					return 0;
55
				}
56
	} while ((check & UART_MSR_CTS) != UART_MSR_CTS);
57
	timeouts = 0;
58
	return 1;
59
}
60
61
static int spk_serial_out(const char ch)
62
{
63
	if (synth_alive && wait_for_xmitr()) {
64
		outb(ch, synth_port_tts);
65
		return 1;
66
	}
67
	return 0;
68
}
69
70
static unsigned char spk_serial_in(void)
71
{
72
	int c, lsr, tmout = SPK_SERIAL_TIMEOUT;
73
	do {
74
		lsr = inb(synth_port_tts + UART_LSR);
75
		if (--tmout == 0) return 0xff;
76
	} while (!(lsr & UART_LSR_DR));
77
	c = inb(synth_port_tts + UART_RX);
78
	return (unsigned char) c;
79
}
80
81
static void do_catch_up(unsigned long data)
82
{
83
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
84
	u_char ch;
85
synth_stop_timer();
86
	while (synth_buff_out < synth_buff_in ) {
87
		ch = *synth_buff_out;
88
		if (ch == 0x0a) ch = PROCSPEECH;
89
		if (!spk_serial_out(ch )) {
90
			synth_delay(synth_full_time);
91
			return;
92
		}
93
		synth_buff_out++;
94
		if (jiffies >= jiff_max && ch == SPACE ) {
95
			spk_serial_out(PROCSPEECH);
96
			synth_delay(synth_delay_time); 
97
			return; 
98
		}
99
	}
100
spk_serial_out(PROCSPEECH);
101
	synth_done( );
102
}
103
104
static const char *synth_immediate (const char *buf )
105
{
106
	u_char ch;
107
	while ( ( ch = *buf ) ) {
108
	if (ch == 0x0a) ch = PROCSPEECH;
109
        if ( wait_for_xmitr( ) )
110
          outb( ch, synth_port_tts );
111
        else return buf;
112
	buf++;
113
	}
114
	return 0;
115
}
116
117
static void synth_flush(void)
118
{
119
	while ((inb(synth_port_tts + UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY);
120
	outb(SYNTH_CLEAR, synth_port_tts);
121
}
122
123
static unsigned char get_index(void)
124
{
125
	int c, lsr;//, tmout = SPK_SERIAL_TIMEOUT;
126
	lsr = inb( synth_port_tts + UART_LSR );
127
	if ( ( lsr & UART_LSR_DR) == UART_LSR_DR )
128
	{
129
		c = inb( synth_port_tts + UART_RX );
130
		return ( unsigned char ) c;
131
	}
132
	return 0;
133
}
134
135
static int serprobe(int index)
136
{
137
	struct serial_state *ser = spk_serial_init(index);
138
	if ( ser == NULL ) return -1;
139
	/* ignore any error results, if port was forced */
140
	if (synth_port_forced) return 0;
141
	/* check for speak out now... */
142
	synth_immediate( "\x05[\x0f\r" );
143
	mdelay( 10 ); //failed with no delay
144
	if (spk_serial_in() == 0x0f) return 0;
145
	synth_release_region(ser->port,8);
146
			  synth_alive = 0;
147
			  return -1;
148
}
149
150
static int synth_probe(void)
151
{
152
	int i=0, failed=0;
153
	pr_info("Probing for %s.\n", synth->long_name);
154
	for (i=SPK_LO_TTY; i <= SPK_HI_TTY; i++) {
155
	  if (( failed = serprobe( i )) == 0 ) break; /* found it */
156
        }
157
        if ( failed ) {
158
		pr_info("%s Out:  not found\n", synth->long_name);
159
		return -ENODEV;
160
	}
161
	pr_info("%s Out:  %03x-%03x, Driver version %s,\n", synth->long_name,
162
   synth_port_tts, synth_port_tts + 7, synth->version);
163
	return 0;
164
}
165
166
static int synth_is_alive(void)
167
{
168
	if (synth_alive) return 1;
169
	if (wait_for_xmitr() > 0) { /* restart */
170
		synth_alive = 1;
171
		synth_write_string(synth->init );
172
		return 2;
173
	} else pr_warn("%s Out: can't restart synth\n", synth->long_name);
174
	return 0;
175
}
176
177
static const char init_string[] = "\005W1\005I2\005C3";
178
179
static struct st_string_var stringvars[] = {
180
	{ CAPS_START, "\x05P+" },
181
	{ CAPS_STOP, "\x05P-" },
182
	V_LAST_STRING
183
};
184
static struct st_num_var numvars[] = {
185
	{ RATE, "\x05R%d", 7, 0, 9, 0, 0, 0 },
186
	{ PITCH, "\x05P%d", 3, 0, 9, 0, 0, 0 },
187
	{ VOL, "\x05V%d", 9, 0, 9, 0, 0, 0 },
188
	{ TONE, "\x05T%c", 8, 0, 25, 65, 0, 0 },
189
	{ PUNCT, "\x05M%c", 0, 0, 3, 0, 0, "nsma" },
190
	V_LAST_NUM
191
};
192
	 
193
struct spk_synth synth_spkout = {"spkout", "1.1", "Speakout",
194
	 init_string, 500, 50, 50, 5000, 0, 0, SYNTH_CHECK,
195
	stringvars, numvars, synth_probe, spk_serial_release, synth_immediate,
196
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, 
197
	get_index, {"\x05[%c",1,5,1} };
198
199
#ifdef MODULE
200
#include "mod_code.c"
201
#endif
(-)linux-2.6.20/drivers/char/speakup/speakup_txprt.c (+196 lines)
Line 0 Link Here
1
/*
2
 * originially written by: Kirk Reiser <kirk@braille.uwo.ca>
3
* this version considerably modified by David Borowski, david575@rogers.com
4
5
		Copyright (C) 1998-99  Kirk Reiser.
6
		Copyright (C) 2003 David Borowski.
7
8
		This program is free software; you can redistribute it and/or modify
9
		it under the terms of the GNU General Public License as published by
10
		the Free Software Foundation; either version 2 of the License, or
11
		(at your option) any later version.
12
13
		This program is distributed in the hope that it will be useful,
14
		but WITHOUT ANY WARRANTY; without even the implied warranty of
15
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
		GNU General Public License for more details.
17
18
		You should have received a copy of the GNU General Public License
19
		along with this program; if not, write to the Free Software
20
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22
 * this code is specificly written as a driver for the speakup screenreview
23
 * package and is not a general device driver.
24
		*/
25
#include "spk_priv.h"
26
#include "serialio.h"
27
28
#define MY_SYNTH synth_txprt
29
#define DRV_VERSION "1.2"
30
#define SYNTH_CLEAR 0x18
31
#define PROCSPEECH '\r' /* process speech char */
32
33
static int timeouts = 0;	/* sequential number of timeouts */
34
35
static int wait_for_xmitr( void )
36
{
37
	int check, tmout = SPK_XMITR_TIMEOUT;
38
	if ( ( synth_alive ) && ( timeouts >= NUM_DISABLE_TIMEOUTS ) ) {
39
		synth_alive = 0; 
40
		timeouts = 0;
41
		return 0; 
42
	}
43
	do {
44
		check = inb( synth_port_tts + UART_LSR );
45
		if ( --tmout == 0 ) {
46
			pr_warn( "TXPRT:  timed out\n" );
47
			timeouts++;
48
			return 0;
49
		}
50
	} while ( ( check & BOTH_EMPTY ) != BOTH_EMPTY );
51
	tmout = SPK_XMITR_TIMEOUT;
52
	do {
53
		check = inb( synth_port_tts + UART_MSR );
54
				if ( --tmout == 0 ) {
55
					timeouts++;
56
					return 0;
57
				}
58
	} while ( ( check & UART_MSR_CTS ) != UART_MSR_CTS );
59
	timeouts = 0;
60
	return 1;
61
}
62
63
static int spk_serial_out( const char ch )
64
{
65
	if ( synth_alive && wait_for_xmitr( ) ) {
66
		outb( ch, synth_port_tts );
67
		return 1;
68
	}
69
	return 0;
70
}
71
72
static unsigned char spk_serial_in( void )
73
{
74
	int c, lsr, tmout = SPK_SERIAL_TIMEOUT;
75
	do {
76
		lsr = inb( synth_port_tts + UART_LSR );
77
		if ( --tmout == 0 ) return 0xff;
78
	} while ( !( lsr & UART_LSR_DR ) );
79
	c = inb( synth_port_tts + UART_RX );
80
	return ( unsigned char ) c;
81
}
82
83
static void do_catch_up( unsigned long data )
84
{
85
	unsigned long jiff_max = jiffies+synth_jiffy_delta;
86
	u_char ch;
87
	
88
	synth_stop_timer( );
89
	while ( synth_buff_out < synth_buff_in ) {
90
		ch = *synth_buff_out;
91
		if ( ch == '\n' ) ch = PROCSPEECH;
92
		if ( !spk_serial_out( ch ) ) {
93
			synth_delay( synth_full_time );
94
			return;
95
		}
96
		synth_buff_out++;
97
		if ( jiffies >= jiff_max && ch == ' ' ) { 
98
			spk_serial_out( PROCSPEECH );
99
			synth_delay( synth_delay_time );
100
			return; 
101
		}
102
	}
103
	spk_serial_out( PROCSPEECH );
104
	synth_done( );
105
}
106
107
static const char *synth_immediate ( const char *buf )
108
{
109
	u_char ch;
110
	while ( ( ch = *buf ) ) {
111
	if ( ch == 0x0a ) ch = PROCSPEECH;
112
        if ( wait_for_xmitr( ) )
113
	  outb( ch, synth_port_tts );
114
	else return buf;
115
	buf++;
116
	}
117
	return 0;
118
}
119
120
static void synth_flush ( void )
121
{
122
	spk_serial_out ( SYNTH_CLEAR );
123
}
124
125
static int serprobe( int index )
126
{
127
	u_char test=0;
128
	struct serial_state *ser = spk_serial_init( index );
129
	if ( ser == NULL ) return -1;
130
	if ( synth_port_forced ) return 0;
131
	/* check for txprt now... */
132
	if (synth_immediate( "\x05$" ))
133
	  pr_warn("synth_immediate could not unload\n");
134
	if (synth_immediate( "\x05Ik" ))
135
	  pr_warn("synth_immediate could not unload again\n");
136
	if (synth_immediate( "\x05Q\r" ))
137
	  pr_warn("synth_immediate could not unload a third time\n");
138
	if ( ( test = spk_serial_in( ) ) == 'k' ) return 0;
139
	else pr_warn( "synth returned %x on port %03lx\n", test, ser->port );
140
	synth_release_region( ser->port,8 );
141
	timeouts = synth_alive = 0;
142
			  return -1;
143
}
144
145
static int synth_probe( void )
146
{
147
	int i, failed=0;
148
	pr_info( "Probing for %s.\n", synth->long_name );
149
	for ( i=SPK_LO_TTY; i <= SPK_HI_TTY; i++ ) {
150
		if (( failed = serprobe( i )) == 0 ) break; /* found it */
151
	}
152
	if ( failed ) {
153
		pr_info( "%s:  not found\n", synth->long_name );
154
		return -ENODEV;
155
	}
156
	pr_info( "%s: %03x-%03x..\n", synth->long_name, (int) synth_port_tts, (int) synth_port_tts+7 );
157
	pr_info( "%s: driver version %s.\n",  synth->long_name, synth->version);
158
	return 0;
159
}
160
161
static int synth_is_alive( void )
162
{
163
	if ( synth_alive ) return 1;
164
	if ( wait_for_xmitr( ) > 0 ) { /* restart */
165
		synth_alive = 1;
166
		synth_write_string( synth->init );
167
		return 2;
168
	}
169
	pr_warn( "%s: can't restart synth\n", synth->long_name );
170
	return 0;
171
}
172
173
static const char init_string[] = "\x05N1";
174
175
static struct st_string_var stringvars[] = {
176
	{ CAPS_START, "\x05P8" },
177
	{ CAPS_STOP, "\x05P5" },
178
	V_LAST_STRING
179
};
180
static struct st_num_var numvars[] = {
181
	{ RATE, "\x05R%d", 5, 0, 9, 0, 0, 0 },
182
	{ PITCH, "\x05P%d", 5, 0, 9, 0, 0, 0 },
183
	{ VOL, "\x05V%d", 5, 0, 9, 0, 0, 0 },
184
	{ TONE, "\x05T%c", 12, 0, 25, 61, 0, 0 },
185
	V_LAST_NUM
186
	 };
187
188
struct spk_synth synth_txprt = {"txprt", DRV_VERSION, "Transport",
189
	init_string, 500, 50, 50, 5000, 0, 0, SYNTH_CHECK,
190
	stringvars, numvars, synth_probe, spk_serial_release, synth_immediate,
191
	do_catch_up, NULL, synth_flush, synth_is_alive, NULL, NULL, NULL,
192
	{NULL,0,0,0} };
193
194
#ifdef MODULE
195
#include "mod_code.c"
196
#endif
(-)linux-2.6.20/drivers/char/speakup/spk_con_module.h (+43 lines)
Line 0 Link Here
1
/* written bby David Borowski.
2
    Copyright (C ) 2003  David Borowski.
3
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option ) any later version.
8
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18
19
/* included by ../console.c for speakup modularization */
20
21
static spk_con_func addr_spk_allocate = NULL;
22
static spk_con_func addr_spk_bs = NULL;
23
static spk_write_func addr_spk_con_write = NULL;
24
static spk_con_func addr_spk_con_update = NULL;
25
26
#define speakup_allocate(c) if (addr_spk_allocate) (*addr_spk_allocate)(c)
27
#define speakup_bs(c) if (addr_spk_bs) (*addr_spk_bs)(c)
28
#define speakup_con_write(c,s,l) if (addr_spk_con_write) (*addr_spk_con_write)(c,s,l)
29
#define speakup_con_update(c) if (addr_spk_con_update) (*addr_spk_con_update)(c)
30
31
extern spk_key_func addr_spk_key;
32
33
void speakup_set_addresses( spk_con_func allocate, spk_con_func bs,
34
	spk_write_func con_write, spk_con_func con_update, spk_key_func key )
35
{
36
	addr_spk_allocate = allocate;
37
	addr_spk_bs = bs;
38
	addr_spk_con_write = con_write;
39
	addr_spk_con_update = con_update;
40
	addr_spk_key = key;
41
}
42
43
EXPORT_SYMBOL_GPL(speakup_set_addresses);
(-)linux-2.6.20/drivers/char/speakup/spk_priv.h (+262 lines)
Line 0 Link Here
1
/* spk_priv.h
2
   review functions for the speakup screen review package.
3
   originally written by: Kirk Reiser and Andy Berdan.
4
5
  extensively modified by David Borowski.
6
7
    Copyright (C ) 1998  Kirk Reiser.
8
    Copyright (C ) 2003  David Borowski.
9
10
    This program is free software; you can redistribute it and/or modify
11
    it under the terms of the GNU General Public License as published by
12
    the Free Software Foundation; either version 2 of the License, or
13
    (at your option ) any later version.
14
15
    This program is distributed in the hope that it will be useful,
16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
    GNU General Public License for more details.
19
20
    You should have received a copy of the GNU General Public License
21
    along with this program; if not, write to the Free Software
22
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
*/
24
#ifndef __SPEAKUP_PRIVATE_H
25
#define __SPEAKUP_PRIVATE_H
26
27
#define KERNEL
28
#include <linux/version.h>
29
#include <linux/types.h>
30
#include <linux/fs.h>
31
#include <linux/errno.h>
32
#include <asm/io.h>		/* for inb_p, outb_p, inb, outb, etc... */
33
#include <linux/delay.h>
34
#include <linux/wait.h>		/* for wait_queue */
35
#include <linux/init.h> /* for __init */
36
#include <linux/module.h>
37
#ifdef CONFIG_PROC_FS
38
#include <linux/proc_fs.h>
39
#endif
40
#include <linux/speakup.h>
41
#include "keyinfo.h"
42
43
#define SHIFT_TBL_SIZE 64
44
/* proc permissions */
45
#define USER_R ( S_IFREG|S_IRUGO )
46
#define USER_W ( S_IFREG|S_IWUGO )
47
#define USER_RW ( S_IFREG|S_IRUGO|S_IWUGO )
48
#define ROOT_W ( S_IFREG|S_IRUGO|S_IWUSR )
49
50
#define V_LAST_STRING { -1, 0 }
51
#define V_LAST_NUM { -1, 0, 0, 0, 0, 0, 0, 0 }
52
#define TOGGLE_0 0, 0, 0, 1, 0, 0, 0
53
#define TOGGLE_1 0, 1, 0, 1, 0, 0, 0
54
#define MAXVARLEN 15
55
#define TAB 0x9
56
#define SPACE 0x20
57
#define CAP_A 'A'
58
#define CAP_Z 'Z'
59
#define SYNTH_OK 0x0001
60
#define B_ALPHA 0x0002
61
#define ALPHA 0x0003
62
#define B_CAP 0x0004
63
#define A_CAP 0x0007
64
#define B_NUM 0x0008
65
#define NUM 0x0009
66
#define ALPHANUM ( B_ALPHA|B_NUM )
67
#define SOME 0x0010
68
#define MOST 0x0020
69
#define PUNC 0x0040
70
#define A_PUNC 0x0041
71
#define B_WDLM 0x0080
72
#define WDLM 0x0081
73
#define B_EXNUM 0x0100
74
#define CH_RPT 0x0200
75
#define B_CTL 0x0400
76
#define A_CTL ( B_CTL+SYNTH_OK )
77
#define B_SYM 0x0800
78
#define B_CAPSYM ( B_CAP|B_SYM )
79
#define IS_WDLM( x ) ( spk_chartab[( ( u_char )x )]&B_WDLM )
80
#define IS_CHAR( x, type ) ( spk_chartab[( ( u_char )x )]&type )
81
#define IS_TYPE( x, type ) ( (spk_chartab[( ( u_char )x )]&type) == type )
82
#define SET_DEFAULT -4
83
#define E_RANGE -3
84
#define E_TOOLONG -2
85
#define E_UNDEF -1
86
87
enum {
88
	VAR_NUM = 0,
89
	VAR_TIME,
90
	VAR_STRING,
91
	VAR_PROC
92
};
93
94
enum {
95
	E_DEFAULT = 0,
96
	E_SET,
97
	E_INC,
98
	E_DEC
99
};
100
101
typedef int (*special_func)( struct vc_data *vc, u_char type, u_char ch, u_short key );
102
103
struct st_var_header {
104
	char *name;
105
	short var_id, var_type, proc_mode;
106
	void *proc_entry;
107
	void *p_val; /* ptr to programs variable to store value */
108
	void *data; /* ptr to the vars data */
109
};
110
111
struct st_num_var {
112
	short var_id;
113
	char *synth_fmt;
114
	short default_val, low, high;
115
	short offset, multiplier; /* for fiddling rates etc. */
116
	char *out_str; /* if synth needs char representation of number */
117
	short value; /* current value */
118
};
119
120
struct st_string_var {
121
	short var_id;
122
	char *default_val;
123
};
124
125
struct st_proc_var {
126
	short var_id;
127
	int (*read_proc)(char *page, char **start, off_t off, int count,
128
			 int *eof, void *data);
129
	int (*write_proc)(struct file *file, const char *buffer, u_long count,
130
			  void *data);
131
	short value;
132
};
133
134
struct st_bits_data { /* punc, repeats, word delim bits */
135
	char *name;
136
	char *value;
137
	short mask;
138
};
139
140
extern struct st_proc_var spk_proc_vars[];
141
char *speakup_s2i( char *, short * );
142
int speakup_register_var(struct st_num_var *var);
143
extern struct st_var_header *get_var_header( short var_id );
144
extern int set_num_var(short val, struct st_var_header *var, int how);
145
146
#define COLOR_BUFFER_SIZE 160
147
struct spk_highlight_color_track{
148
	unsigned int bgcount[8];	// Count of each background color
149
	char highbuf[8][COLOR_BUFFER_SIZE];	// Buffer for characters drawn with each background color
150
	unsigned int highsize[8];	// Current index into highbuf
151
	u_long rpos[8],rx[8],ry[8];	// Reading Position for each color
152
	ulong cy;			// Real Cursor Y Position
153
};
154
155
struct st_spk_t {
156
	u_long reading_x, cursor_x;
157
	u_long reading_y, cursor_y;
158
	u_long reading_pos, cursor_pos;
159
	u_long go_x, go_pos;
160
	u_long w_top, w_bottom, w_left, w_right;
161
	u_char w_start, w_enabled;
162
	u_char reading_attr, old_attr;
163
	char parked, shut_up;
164
	struct spk_highlight_color_track ht;
165
};
166
167
/* now some defines to make these easier to use. */
168
#define spk_shut_up speakup_console[vc->vc_num]->shut_up
169
#define spk_killed ( speakup_console[vc->vc_num]->shut_up & 0x40 )
170
#define spk_x speakup_console[vc->vc_num]->reading_x
171
#define spk_cx speakup_console[vc->vc_num]->cursor_x
172
#define spk_y speakup_console[vc->vc_num]->reading_y
173
#define spk_cy speakup_console[vc->vc_num]->cursor_y
174
#define spk_pos ( speakup_console[vc->vc_num]->reading_pos )
175
#define spk_cp speakup_console[vc->vc_num]->cursor_pos
176
#define goto_pos ( speakup_console[vc->vc_num]->go_pos )
177
#define goto_x ( speakup_console[vc->vc_num]->go_x )
178
#define win_top ( speakup_console[vc->vc_num]->w_top )
179
#define win_bottom ( speakup_console[vc->vc_num]->w_bottom )
180
#define win_left ( speakup_console[vc->vc_num]->w_left )
181
#define win_right ( speakup_console[vc->vc_num]->w_right )
182
#define win_start ( speakup_console[vc->vc_num]->w_start )
183
#define win_enabled ( speakup_console[vc->vc_num]->w_enabled )
184
#define spk_attr speakup_console[vc->vc_num]->reading_attr
185
#define spk_old_attr speakup_console[vc->vc_num]->old_attr
186
#define spk_parked speakup_console[vc->vc_num]->parked
187
#define SYNTH_CHECK 20030716 /* today's date ought to do for check value */
188
/* synth flags, for odd synths */
189
#define SF_DEC 1 /* to fiddle puncs in alpha strings so it doesn't spell */
190
191
struct synth_indexing {
192
	char *command;
193
	unsigned char lowindex;
194
	unsigned char highindex;
195
	unsigned char currindex;
196
};
197
198
struct spk_synth {
199
	const char *name;
200
	const char *version;
201
	const char *long_name;
202
	const char *init;
203
	short delay, trigger, jiffies, full, flush_wait, flags;
204
	const int checkval; /* for validating a proper synth module */
205
	struct st_string_var *string_vars;
206
	struct st_num_var *num_vars;
207
	int ( *probe )( void );
208
	void ( *release )( void );
209
	const char *( *synth_immediate )( const char *buff );
210
	void ( *catch_up )( u_long data );
211
	void ( *start )( void );
212
	void ( *flush )( void );
213
	int ( *is_alive )( void );
214
	int (*synth_adjust)(struct st_var_header *var);
215
	void ( *read_buff_add )(u_char);
216
	unsigned char ( *get_index )( void );
217
	struct synth_indexing indexing;
218
};
219
220
extern struct spk_synth *synth;
221
int synth_request_region( u_long, u_long );
222
int synth_release_region( u_long, u_long );
223
void spk_serial_release( void );
224
extern int synth_port_tts, synth_port_forced;
225
#define declare_timer( name ) struct timer_list name;
226
#define start_timer( name ) if ( ! name.entry.prev ) add_timer ( & name )
227
#define stop_timer( name ) del_timer ( & name ); name.entry.prev = NULL
228
#define declare_sleeper( name ) wait_queue_head_t name
229
#define init_sleeper( name ) 	init_waitqueue_head ( &name )
230
extern declare_sleeper( synth_sleeping_list );
231
extern char str_caps_start[], str_caps_stop[];
232
extern short no_intr, say_ctrl, say_word_ctl, punc_level;
233
extern short reading_punc, attrib_bleep, bleeps;
234
extern short bleep_time, bell_pos;
235
extern short spell_delay, key_echo, punc_mask;
236
extern short synth_jiffy_delta, synth_delay_time;
237
extern short synth_trigger_time, synth_full_time;
238
extern short cursor_timeout, pitch_shift, synth_flags;
239
extern int synth_alive, quiet_boot;
240
extern u_char synth_buffer[];  /* guess what this is for! */
241
extern volatile u_char *synth_buff_in, *synth_buff_out;
242
int synth_init( char *name );
243
int do_synth_init( struct spk_synth *in_synth );
244
void synth_release( void );
245
void synth_add( struct spk_synth *in_synth );
246
void synth_remove( struct spk_synth *in_synth );
247
struct serial_state * spk_serial_init( int index );
248
void synth_delay( int ms );
249
void synth_stop_timer( void );
250
int synth_done( void );
251
void do_flush( void );
252
void synth_buffer_add( char ch );
253
void synth_write( const char *buf, size_t count );
254
void synth_write_string( const char *buf );
255
void synth_write_msg( const char *buf );
256
int synth_supports_indexing( void );
257
258
#ifndef pr_warn
259
#define pr_warn(fmt,arg...) printk(KERN_WARNING fmt,##arg)
260
#endif
261
262
#endif
(-)linux-2.6.20/drivers/char/speakup/synthlist.h (+51 lines)
Line 0 Link Here
1
/* this is included two times */
2
#if defined(PASS2)
3
/* table of built in synths */
4
#define SYNTH_DECL(who) &synth_##who,
5
#else
6
/* declare extern built in synths */
7
#define SYNTH_DECL(who) extern struct spk_synth synth_##who;
8
#define PASS2
9
#endif
10
11
#ifdef CONFIG_SPEAKUP_ACNTPC
12
SYNTH_DECL(acntpc)
13
#endif
14
#ifdef CONFIG_SPEAKUP_ACNTSA
15
SYNTH_DECL(acntsa)
16
#endif
17
#ifdef CONFIG_SPEAKUP_APOLLO
18
SYNTH_DECL(apollo)
19
#endif
20
#ifdef CONFIG_SPEAKUP_AUDPTR
21
SYNTH_DECL(audptr)
22
#endif
23
#ifdef CONFIG_SPEAKUP_BNS
24
SYNTH_DECL(bns)
25
#endif
26
#ifdef CONFIG_SPEAKUP_DECEXT
27
SYNTH_DECL(decext)
28
#endif
29
#ifdef CONFIG_SPEAKUP_DECTLK
30
SYNTH_DECL(dectlk)
31
#endif
32
#ifdef CONFIG_SPEAKUP_DTLK
33
SYNTH_DECL(dtlk)
34
#endif
35
#ifdef CONFIG_SPEAKUP_KEYPC
36
SYNTH_DECL(keypc)
37
#endif
38
#ifdef CONFIG_SPEAKUP_LTLK
39
SYNTH_DECL(ltlk)
40
#endif
41
#ifdef CONFIG_SPEAKUP_SFTSYN
42
SYNTH_DECL(sftsyn)
43
#endif
44
#ifdef CONFIG_SPEAKUP_SPKOUT
45
SYNTH_DECL(spkout)
46
#endif
47
#ifdef CONFIG_SPEAKUP_TXPRT
48
SYNTH_DECL(txprt)
49
#endif
50
51
#undef SYNTH_DECL
(-)linux-2.6.20/drivers/char/vt.c (+18 lines)
Lines 103-108 Link Here
103
#include <asm/system.h>
103
#include <asm/system.h>
104
#include <asm/uaccess.h>
104
#include <asm/uaccess.h>
105
105
106
#include <linux/speakup.h>
107
#ifdef CONFIG_SPEAKUP_MODULE
108
#include "speakup/spk_con_module.h"
109
#endif
110
106
#define MAX_NR_CON_DRIVER 16
111
#define MAX_NR_CON_DRIVER 16
107
112
108
#define CON_DRIVER_FLAG_MODULE 1
113
#define CON_DRIVER_FLAG_MODULE 1
Lines 739-744 int vc_allocate(unsigned int currcons) / Link Here
739
	    }
744
	    }
740
	    vc->vc_kmalloced = 1;
745
	    vc->vc_kmalloced = 1;
741
	    vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
746
	    vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
747
 	    speakup_allocate(vc);
742
	}
748
	}
743
	return 0;
749
	return 0;
744
}
750
}
Lines 1003-1008 static void lf(struct vc_data *vc) Link Here
1003
		vc->vc_pos += vc->vc_size_row;
1009
		vc->vc_pos += vc->vc_size_row;
1004
	}
1010
	}
1005
	vc->vc_need_wrap = 0;
1011
	vc->vc_need_wrap = 0;
1012
	speakup_con_write(vc, "\n",1);
1006
}
1013
}
1007
1014
1008
static void ri(struct vc_data *vc)
1015
static void ri(struct vc_data *vc)
Lines 1031-1036 static inline void bs(struct vc_data *vc Link Here
1031
		vc->vc_pos -= 2;
1038
		vc->vc_pos -= 2;
1032
		vc->vc_x--;
1039
		vc->vc_x--;
1033
		vc->vc_need_wrap = 0;
1040
		vc->vc_need_wrap = 0;
1041
		speakup_bs(vc);
1034
	}
1042
	}
1035
}
1043
}
1036
1044
Lines 1568-1573 static void do_con_trol(struct tty_struc Link Here
1568
				break;
1576
				break;
1569
		}
1577
		}
1570
		vc->vc_pos += (vc->vc_x << 1);
1578
		vc->vc_pos += (vc->vc_x << 1);
1579
		speakup_con_write(vc, " ", 1);
1571
		return;
1580
		return;
1572
	case 10: case 11: case 12:
1581
	case 10: case 11: case 12:
1573
		lf(vc);
1582
		lf(vc);
Lines 2107-2112 display_glyph: Link Here
2107
			}
2116
			}
2108
			if (vc->vc_decim)
2117
			if (vc->vc_decim)
2109
				insert_char(vc, 1);
2118
				insert_char(vc, 1);
2119
			speakup_con_write(vc, (char *) &c, 1);
2110
			scr_writew(himask ?
2120
			scr_writew(himask ?
2111
				     ((vc->vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
2121
				     ((vc->vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
2112
				     (vc->vc_attr << 8) + tc,
2122
				     (vc->vc_attr << 8) + tc,
Lines 2141-2146 display_glyph: Link Here
2141
	release_console_sem();
2151
	release_console_sem();
2142
2152
2143
out:
2153
out:
2154
	speakup_con_update(vc);
2144
	return n;
2155
	return n;
2145
#undef FLUSH
2156
#undef FLUSH
2146
}
2157
}
Lines 2166-2171 static void console_callback(struct work Link Here
2166
			/* we only changed when the console had already
2177
			/* we only changed when the console had already
2167
			   been allocated - a new console is not created
2178
			   been allocated - a new console is not created
2168
			   in an interrupt routine */
2179
			   in an interrupt routine */
2180
			speakup_con_update(vc_cons[want_console].d);
2169
		}
2181
		}
2170
		want_console = -1;
2182
		want_console = -1;
2171
	}
2183
	}
Lines 2184-2189 static void console_callback(struct work Link Here
2184
		do_blank_screen(0);
2196
		do_blank_screen(0);
2185
		blank_timer_expired = 0;
2197
		blank_timer_expired = 0;
2186
	}
2198
	}
2199
	speakup_con_update(vc_cons[fg_console].d);
2187
2200
2188
	release_console_sem();
2201
	release_console_sem();
2189
}
2202
}
Lines 2229-2234 static void vt_console_print(struct cons Link Here
2229
		/* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */
2242
		/* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */
2230
		goto quit;
2243
		goto quit;
2231
	}
2244
	}
2245
	speakup_con_update(vc_cons[fg_console].d);
2232
2246
2233
	if (vc->vc_mode != KD_TEXT)
2247
	if (vc->vc_mode != KD_TEXT)
2234
		goto quit;
2248
		goto quit;
Lines 2241-2246 static void vt_console_print(struct cons Link Here
2241
2255
2242
	/* Contrived structure to try to emulate original need_wrap behaviour
2256
	/* Contrived structure to try to emulate original need_wrap behaviour
2243
	 * Problems caused when we have need_wrap set on '\n' character */
2257
	 * Problems caused when we have need_wrap set on '\n' character */
2258
	speakup_con_write(vc, b, count);
2244
	while (count--) {
2259
	while (count--) {
2245
		c = *b++;
2260
		c = *b++;
2246
		if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
2261
		if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
Lines 2285-2290 static void vt_console_print(struct cons Link Here
2285
		}
2300
		}
2286
	}
2301
	}
2287
	set_cursor(vc);
2302
	set_cursor(vc);
2303
	speakup_con_update(vc);
2288
2304
2289
quit:
2305
quit:
2290
	clear_bit(0, &printing);
2306
	clear_bit(0, &printing);
Lines 2650-2655 static int __init con_init(void) Link Here
2650
	master_display_fg = vc = vc_cons[currcons].d;
2666
	master_display_fg = vc = vc_cons[currcons].d;
2651
	set_origin(vc);
2667
	set_origin(vc);
2652
	save_screen(vc);
2668
	save_screen(vc);
2669
	speakup_init(vc);
2653
	gotoxy(vc, vc->vc_x, vc->vc_y);
2670
	gotoxy(vc, vc->vc_x, vc->vc_y);
2654
	csi_J(vc, 0);
2671
	csi_J(vc, 0);
2655
	update_screen(vc);
2672
	update_screen(vc);
Lines 3820-3822 EXPORT_SYMBOL(vc_cons); Link Here
3820
EXPORT_SYMBOL(take_over_console);
3837
EXPORT_SYMBOL(take_over_console);
3821
EXPORT_SYMBOL(give_up_console);
3838
EXPORT_SYMBOL(give_up_console);
3822
#endif
3839
#endif
3840
EXPORT_SYMBOL_GPL(screen_glyph);
(-)linux-2.6.20/drivers/Kconfig (+2 lines)
Lines 62-67 source "drivers/media/Kconfig" Link Here
62
62
63
source "drivers/video/Kconfig"
63
source "drivers/video/Kconfig"
64
64
65
source "drivers/char/speakup/Kconfig"
66
65
source "sound/Kconfig"
67
source "sound/Kconfig"
66
68
67
source "drivers/hid/Kconfig"
69
source "drivers/hid/Kconfig"
(-)linux-2.6.20/drivers/Makefile (-3 / +4 lines)
Lines 28-33 obj-$(CONFIG_FB_INTEL) += video Link Here
28
obj-y				+= serial/
28
obj-y				+= serial/
29
obj-$(CONFIG_PARPORT)		+= parport/
29
obj-$(CONFIG_PARPORT)		+= parport/
30
obj-y				+= base/ block/ misc/ mfd/ net/ media/
30
obj-y				+= base/ block/ misc/ mfd/ net/ media/
31
obj-$(CONFIG_SERIO)		+= input/serio/
32
obj-$(CONFIG_GAMEPORT)		+= input/gameport/
33
# load keyboard early so speakup can be quieted
34
obj-$(CONFIG_INPUT)		+= input/
31
obj-$(CONFIG_NUBUS)		+= nubus/
35
obj-$(CONFIG_NUBUS)		+= nubus/
32
obj-$(CONFIG_ATM)		+= atm/
36
obj-$(CONFIG_ATM)		+= atm/
33
obj-$(CONFIG_PPC_PMAC)		+= macintosh/
37
obj-$(CONFIG_PPC_PMAC)		+= macintosh/
Lines 52-60 obj-$(CONFIG_TC) += tc/ Link Here
52
obj-$(CONFIG_USB)		+= usb/
56
obj-$(CONFIG_USB)		+= usb/
53
obj-$(CONFIG_PCI)		+= usb/
57
obj-$(CONFIG_PCI)		+= usb/
54
obj-$(CONFIG_USB_GADGET)	+= usb/gadget/
58
obj-$(CONFIG_USB_GADGET)	+= usb/gadget/
55
obj-$(CONFIG_SERIO)		+= input/serio/
56
obj-$(CONFIG_GAMEPORT)		+= input/gameport/
57
obj-$(CONFIG_INPUT)		+= input/
58
obj-$(CONFIG_I2O)		+= message/
59
obj-$(CONFIG_I2O)		+= message/
59
obj-$(CONFIG_RTC_LIB)		+= rtc/
60
obj-$(CONFIG_RTC_LIB)		+= rtc/
60
obj-$(CONFIG_I2C)		+= i2c/
61
obj-$(CONFIG_I2C)		+= i2c/
(-)linux-2.6.20/include/linux/keyboard.h (+2 lines)
Lines 45-50 extern unsigned short plain_map[NR_KEYS] Link Here
45
#define KT_LOCK		10
45
#define KT_LOCK		10
46
#define KT_SLOCK	12
46
#define KT_SLOCK	12
47
#define KT_BRL		14
47
#define KT_BRL		14
48
#define KT_SPKUP       	15
48
49
49
#define K(t,v)		(((t)<<8)|(v))
50
#define K(t,v)		(((t)<<8)|(v))
50
#define KTYP(x)		((x) >> 8)
51
#define KTYP(x)		((x) >> 8)
Lines 427-432 extern unsigned short plain_map[NR_KEYS] Link Here
427
#define K_CTRLR_SLOCK	K(KT_SLOCK,KG_CTRLR)
428
#define K_CTRLR_SLOCK	K(KT_SLOCK,KG_CTRLR)
428
429
429
#define NR_LOCK		8
430
#define NR_LOCK		8
431
#define NR_SPKUP       0x45
430
432
431
#define K_BRL_BLANK     K(KT_BRL, 0)
433
#define K_BRL_BLANK     K(KT_BRL, 0)
432
#define K_BRL_DOT1      K(KT_BRL, 1)
434
#define K_BRL_DOT1      K(KT_BRL, 1)
(-)linux-2.6.20/include/linux/miscdevice.h (+1 lines)
Lines 12-17 Link Here
12
#define APOLLO_MOUSE_MINOR 7
12
#define APOLLO_MOUSE_MINOR 7
13
#define PC110PAD_MINOR 9
13
#define PC110PAD_MINOR 9
14
/*#define ADB_MOUSE_MINOR 10	FIXME OBSOLETE */
14
/*#define ADB_MOUSE_MINOR 10	FIXME OBSOLETE */
15
#define SYNTH_MINOR   25
15
#define WATCHDOG_MINOR		130	/* Watchdog timer     */
16
#define WATCHDOG_MINOR		130	/* Watchdog timer     */
16
#define TEMP_MINOR		131	/* Temperature Sensor */
17
#define TEMP_MINOR		131	/* Temperature Sensor */
17
#define RTC_MINOR 135
18
#define RTC_MINOR 135
(-)linux-2.6.20/include/linux/speakup.h (+35 lines)
Line 0 Link Here
1
#ifndef __SPEAKUP_H
2
#define __SPEAKUP_H
3
4
#include <linux/version.h>
5
6
struct kbd_struct;
7
struct vc_data;
8
9
/* how about some prototypes! */
10
11
#if defined(CONFIG_SPEAKUP)
12
extern void speakup_init(struct vc_data *);
13
extern int speakup_dev_init(void);
14
extern void speakup_allocate(struct vc_data *);
15
extern void speakup_bs(struct vc_data *);
16
extern void speakup_con_write(struct vc_data *, const char *, int);
17
extern void speakup_con_update(struct vc_data *);
18
extern int speakup_key(struct vc_data*, int, int, u_short, int);
19
#elif defined(CONFIG_SPEAKUP_MODULE)
20
typedef void (*spk_con_func)(struct vc_data * );
21
typedef void (*spk_write_func)(struct vc_data *, const char *, int);
22
typedef int (*spk_key_func)(struct vc_data*, int, int, u_short, int);
23
extern void spk_set_addresses( spk_con_func allocate, spk_con_func bs,
24
	spk_write_func con_write, spk_con_func con_update, spk_key_func key );
25
#define speakup_init(vc)
26
extern int speakup_dev_init(void);
27
#else
28
#define speakup_allocate(vc)
29
#define speakup_bs(vc)
30
#define speakup_con_write(vc, str, len)
31
#define speakup_con_update(vc)
32
#define speakup_init(currcons)
33
#define speakup_dev_init()
34
#endif
35
#endif
(-)linux-2.6.20/MAINTAINERS (+7 lines)
Lines 3088-3093 M: wli@holomorphy.com Link Here
3088
L:	sparclinux@vger.kernel.org
3088
L:	sparclinux@vger.kernel.org
3089
S:	Maintained
3089
S:	Maintained
3090
3090
3091
SPEAKUP Console speech output
3092
P:	Kirk Reiser
3093
M:	kirk@braille.uwo.ca
3094
L:	speakup@braille.uwo.ca
3095
W:	http://www.linux-speakup.org
3096
S:	Maintained
3097
3091
SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
3098
SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
3092
P:	Roger Wolff
3099
P:	Roger Wolff
3093
M:	R.E.Wolff@BitWizard.nl
3100
M:	R.E.Wolff@BitWizard.nl

Return to bug 166086