Commit c6e3fd22 authored by William Hubbs's avatar William Hubbs Committed by Greg Kroah-Hartman

Staging: add speakup to the staging directory

Speakup is a kernel based screen review package for the linux operating
system.  It allows blind users to interact with applications on the
linux console by means of synthetic speech.

The authors and maintainers of this code include the following:

Kirk Reiser, Andy Berdan, John Covici, Brian and
David Borowski, Christopher Brannon, Samuel Thibault and William Hubbs.
Signed-off-by: default avatarWilliam Hubbs <w.d.hubbs@gmail.com>
Signed-off-by: Samuel Thibault's avatarSamuel Thibault <samuel.thibault@ens-lyon.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e59fe083
......@@ -173,5 +173,7 @@ source "drivers/staging/ft1000/Kconfig"
source "drivers/staging/intel_sst/Kconfig"
source "drivers/staging/speakup/Kconfig"
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING
......@@ -67,3 +67,4 @@ obj-$(CONFIG_USB_ENESTORAGE) += keucr/
obj-$(CONFIG_BCM_WIMAX) += bcm/
obj-$(CONFIG_FT1000) += ft1000/
obj-$(CONFIG_SND_INTEL_SST) += intel_sst/
obj-$(CONFIG_SPEAKUP) += speakup/
This file is intended to give you an overview of the default keys used
by speakup for it's review functions. You may change them to be
anything you want but that will take some familiarity with key
mapping.
We have remapped the insert or zero key on the keypad to act as a
shift key. Well, actually as an altgr key. So in the following list
InsKeyPad-period means hold down the insert key like a shift key and
hit the keypad period.
KeyPad-8 Say current Line
InsKeyPad-8 say from top of screen to reading cursor.
KeyPad-7 Say Previous Line (UP one line)
KeyPad-9 Say Next Line (down one line)
KeyPad-5 Say Current Word
InsKeyPad-5 Spell Current Word
KeyPad-4 Say Previous Word (left one word)
InsKeyPad-4 say from left edge of line to reading cursor.
KeyPad-6 Say Next Word (right one word)
InsKeyPad-6 Say from reading cursor to right edge of line.
KeyPad-2 Say Current Letter
InsKeyPad-2 say current letter phonetically
KeyPad-1 Say Previous Character (left one letter)
KeyPad-3 Say Next Character (right one letter)
KeyPad-plus Say Entire Screen
InsKeyPad-plus Say from reading cursor line to bottom of screen.
KeyPad-Minus Park reading cursor (toggle)
InsKeyPad-minus Say character hex and decimal value.
KeyPad-period Say Position (current line, position and console)
InsKeyPad-period say colour attributes of current position.
InsKeyPad-9 Move reading cursor to top of screen (insert pgup)
InsKeyPad-3 Move reading cursor to bottom of screen (insert pgdn)
InsKeyPad-7 Move reading cursor to left edge of screen (insert home)
InsKeyPad-1 Move reading cursor to right edge of screen (insert end)
ControlKeyPad-1 Move reading cursor to last character on current line.
KeyPad-Enter Shut Up (until another key is hit) and sync reading cursor
InsKeyPad-Enter Shut Up (until toggled back on).
InsKeyPad-star n<x|y> go to line (y) or column (x). Where 'n' is any
allowed value for the row or column for your current screen.
KeyPad-/ Mark and Cut screen region.
InsKeyPad-/ Paste screen region into any console.
Hitting any key while speakup is outputting speech will quiet the
synth until it has caught up with what is being printed on the
console.
menu "Speakup console speech"
config SPEAKUP
depends on VT
tristate "Speakup core"
---help---
This is the Speakup screen reader. Think of it as a
video console for blind people. If built in to the
kernel, it can speak everything on the text console from
boot up to shutdown. For more information on Speakup,
point your browser at http://www.linux-speakup.org/.
There is also a mailing list at the above url that you
can subscribe to.
Supported synthesizers are accent sa, accent pc,
appollo II., Auddapter, Braille 'n Speak, Dectalk
external (old), Dectalk PC (full length isa board),
Dectalk express, Doubletalk, Doubletalk LT or
Litetalk, Keynote Gold internal PC, software
synthesizers, Speakout, transport, and a dummy module
that can be used with a plain text terminal.
Speakup can either be built in or compiled as a module
by answering y or m. If you answer y here, then you
must answer either y or m to at least one of the
synthesizer drivers below. If you answer m here, then
the synthesizer drivers below can only be built as
modules.
These drivers are not standalone drivers, but must be
used in conjunction with Speakup. Think of them as
video cards for blind people.
The Dectalk pc driver can only be built as a module, and
requires software to be pre-loaded on to the card before
the module can be loaded. See the decpc choice below
for more details.
If you are not a blind person, or don't have access to
one of the listed synthesizers, you should say n.
if SPEAKUP
config SPEAKUP_SYNTH_ACNTSA
tristate "Accent SA synthesizer support"
---help---
This is the Speakup driver for the Accent SA
synthesizer. You can say y to build it into the kernel,
or m to build it as a module. See the configuration
help on the Speakup choice above for more info.
config SPEAKUP_SYNTH_ACNTPC
tristate "Accent PC synthesizer support"
---help---
This is the Speakup driver for the accent pc
synthesizer. You can say y to build it into the kernel,
or m to build it as a module. See the configuration
help on the Speakup choice above for more info.
config SPEAKUP_SYNTH_APOLLO
tristate "Apollo II synthesizer support"
---help---
This is the Speakup driver for the Apollo II
synthesizer. You can say y to build it into the kernel,
or m to build it as a module. See the configuration
help on the Speakup choice above for more info.
config SPEAKUP_SYNTH_AUDPTR
tristate "Audapter synthesizer support"
---help---
This is the Speakup driver for the Audapter synthesizer.
You can say y to build it into the kernel, or m to
build it as a module. See the configuration help on the
Speakup choice above for more info.
config SPEAKUP_SYNTH_BNS
tristate "Braille 'n' Speak synthesizer support"
---help---
This is the Speakup driver for the Braille 'n' Speak
synthesizer. You can say y to build it into the kernel,
or m to build it as a module. See the configuration
help on the Speakup choice above for more info.
config SPEAKUP_SYNTH_DECTLK
tristate "DECtalk Express synthesizer support"
---help---
This is the Speakup driver for the DecTalk Express
synthesizer. You can say y to build it into the kernel,
or m to build it as a module. See the configuration
help on the Speakup choice above for more info.
config SPEAKUP_SYNTH_DECEXT
tristate "DECtalk External (old) synthesizer support"
---help---
This is the Speakup driver for the DecTalk External
(old) synthesizer. You can say y to build it into the
kernel, or m to build it as a module. See the
configuration help on the Speakup choice above for more
info.
config SPEAKUP_SYNTH_DECPC
depends on m
tristate "DECtalk PC (big ISA card) synthesizer support"
---help---
This is the Speakup driver for the DecTalk PC (full
length ISA) synthesizer. You can say m to build it as
a module. See the configuration help on the Speakup
choice above for more info.
In order to use the DecTalk PC driver, you must download
the dec_pc.tgz file from linux-speakup.org. It is in
the pub/linux/goodies directory. The dec_pc.tgz file
contains the software which must be pre-loaded on to the
DecTalk PC board in order to use it with this driver.
This driver must be built as a module, and can not be
loaded until the file system is mounted and the DecTalk
PC software has been pre-loaded on to the board.
See the README file in the dec_pc.tgz file for more
details.
config SPEAKUP_SYNTH_DTLK
tristate "DoubleTalk PC synthesizer support"
---help---
This is the Speakup driver for the internal DoubleTalk
PC synthesizer. You can say y to build it into the
kernel, or m to build it as a module. See the
configuration help on the Speakup choice above for more
info.
config SPEAKUP_SYNTH_KEYPC
tristate "Keynote Gold PC synthesizer support"
---help---
This is the Speakup driver for the Keynote Gold
PC synthesizer. You can say y to build it into the
kernel, or m to build it as a module. See the
configuration help on the Speakup choice above for more
info.
config SPEAKUP_SYNTH_LTLK
tristate "DoubleTalk LT/LiteTalk synthesizer support"
---help---
This is the Speakup driver for the LiteTalk/DoubleTalk
LT synthesizer. You can say y to build it into the
kernel, or m to build it as a module. See the
configuration help on the Speakup choice above for more
info.
config SPEAKUP_SYNTH_SOFT
tristate "Userspace software synthesizer support"
---help---
This is the software synthesizer device node. It will
register a device /dev/softsynth which midware programs
and speech daemons may open and read to provide kernel
output to software synths such as espeak, festival,
flite and so forth. You can select 'y' or 'm' to have
it built-in to the kernel or loaded as a module.
config SPEAKUP_SYNTH_SPKOUT
tristate "Speak Out synthesizer support"
---help---
This is the Speakup driver for the Speakout synthesizer.
You can say y to build it into the kernel, or m to
build it as a module. See the configuration help on the
Speakup choice above for more info.
config SPEAKUP_SYNTH_TXPRT
tristate "Transport synthesizer support"
---help---
This is the Speakup driver for the Transport
synthesizer. You can say y to build it into the kernel,
or m to build it as a module. See the configuration
help on the Speakup choice above for more info.
config SPEAKUP_SYNTH_DUMMY
tristate "Dummy synthesizer driver (for testing)"
---help---
This is a dummy Speakup driver for plugging a mere serial
terminal. This is handy if you want to test speakup but
don't have the hardware. You can say y to build it into
the kernel, or m to build it as a module. See the
configuration help on the Speakup choice above for more info.
endif # SPEAKUP
endmenu
obj-$(CONFIG_SPEAKUP_SYNTH_ACNTSA) += speakup_acntsa.o
obj-$(CONFIG_SPEAKUP_SYNTH_ACNTPC) += speakup_acntpc.o
obj-$(CONFIG_SPEAKUP_SYNTH_APOLLO) += speakup_apollo.o
obj-$(CONFIG_SPEAKUP_SYNTH_AUDPTR) += speakup_audptr.o
obj-$(CONFIG_SPEAKUP_SYNTH_BNS) += speakup_bns.o
obj-$(CONFIG_SPEAKUP_SYNTH_DECTLK) += speakup_dectlk.o
obj-$(CONFIG_SPEAKUP_SYNTH_DECEXT) += speakup_decext.o
obj-$(CONFIG_SPEAKUP_SYNTH_DECPC) += speakup_decpc.o
obj-$(CONFIG_SPEAKUP_SYNTH_DTLK) += speakup_dtlk.o
obj-$(CONFIG_SPEAKUP_SYNTH_KEYPC) += speakup_keypc.o
obj-$(CONFIG_SPEAKUP_SYNTH_LTLK) += speakup_ltlk.o
obj-$(CONFIG_SPEAKUP_SYNTH_SOFT) += speakup_soft.o
obj-$(CONFIG_SPEAKUP_SYNTH_SPKOUT) += speakup_spkout.o
obj-$(CONFIG_SPEAKUP_SYNTH_TXPRT) += speakup_txprt.o
obj-$(CONFIG_SPEAKUP_SYNTH_DUMMY) += speakup_dummy.o
obj-$(CONFIG_SPEAKUP) += speakup.o
speakup-objs := \
buffers.o \
devsynth.o \
i18n.o \
fakekey.o \
main.o \
keyhelp.o \
kobjects.o \
selection.o \
serialio.o \
synth.o \
thread.o \
varhandlers.o
Speakup project home: http://www.linux-speakup.org
Mailing List: speakup@braille.uwo.ca
Speakup is a kernel based screen review package for the linux operating
system. It allows blind users to interact with applications on the
linux console by means of synthetic speech.
Currently, speakup has several issues we know of.
The first issue has to do with the way speakup communicates with serial
ports. Currently, we communicate directly with the hardware
ports. This however conflicts with the standard serial port drivers,
which poses various problems. This is also not working for modern hardware
such as PCI-based serial ports. Also, there is not a way we can
communicate with USB devices. The current serial port handling code is
in serialio.c in this directory.
Some places are currently using in_atomic() because speakup functions
are called in various contexts, and a couple of things can't happen
in these cases. Pushing work to some worker thread would probably help,
as was already done for the serial port driving part.
There is a duplication of the selection functions in selections.c. These
functions should get exported from drivers/char/selection.c (clear_selection
notably) and used from there instead.
The kobjects may have to move to a more proper place in /sys. The
discussion on lkml resulted to putting speech synthesizers in the
"speech" class, and the speakup screen reader itself into
/sys/class/vtconsole/vtcon0/speakup, the nasty path being handled by
userland tools.
Another issue seems to only happen on SMP systems. It seems
that text in the output buffer gets garbled because a lock is not set.
This bug happens regularly, but no one has been able to find a situation
which produces it consistently.
Patches, suggestions, corrections, etc, are definitely welcome.
We prefer that you contact us on the mailing list; however, if you do
not want to subscribe to a mailing list, send your email to all of the
following:
w.d.hubbs@gmail.com, chris@the-brannons.com, kirk@braille.uwo.ca and
samuel.thibault@ens-lyon.org.
#include <linux/console.h>
#include <linux/smp_lock.h>
#include <linux/types.h>
#include <linux/wait.h>
#include "speakup.h"
#include "spk_priv.h"
#define synthBufferSize 8192 /* currently 8K bytes */
static u_char synth_buffer[synthBufferSize]; /* guess what this is for! */
static u_char *buff_in = synth_buffer;
static u_char *buff_out = synth_buffer;
static u_char *buffer_end = synth_buffer+synthBufferSize-1;
/* These try to throttle applications by stopping the TTYs
* Note: we need to make sure that we will restart them eventually, which is
* usually not possible to do from the notifiers. TODO: it should be possible
* starting from linux 2.6.26.
*
* So we only stop when we know alive == 1 (else we discard the data anyway),
* and the alive synth will eventually call start_ttys from the thread context.
*/
void speakup_start_ttys(void)
{
int i;
for (i = 0; i < MAX_NR_CONSOLES; i++) {
if (speakup_console[i] && speakup_console[i]->tty_stopped)
continue;
if ((vc_cons[i].d != NULL) && (vc_cons[i].d->vc_tty != NULL))
start_tty(vc_cons[i].d->vc_tty);
}
}
EXPORT_SYMBOL_GPL(speakup_start_ttys);
static void speakup_stop_ttys(void)
{
int i;
for (i = 0; i < MAX_NR_CONSOLES; i++)
if ((vc_cons[i].d != NULL) && (vc_cons[i].d->vc_tty != NULL))
stop_tty(vc_cons[i].d->vc_tty);
return;
}
static int synth_buffer_free(void)
{
int bytesFree;
if (buff_in >= buff_out)
bytesFree = synthBufferSize - (buff_in - buff_out);
else
bytesFree = buff_out - buff_in;
return bytesFree;
}
int synth_buffer_empty(void)
{
return (buff_in == buff_out);
}
EXPORT_SYMBOL_GPL(synth_buffer_empty);
void synth_buffer_add(char ch)
{
if (!synth->alive) {
/* This makes sure that we won't stop TTYs if there is no synth
* to restart them */
return;
}
if (synth_buffer_free() <= 100) {
synth_start();
speakup_stop_ttys();
}
if (synth_buffer_free() <= 1)
return;
*buff_in++ = ch;
if (buff_in > buffer_end)
buff_in = synth_buffer;
}
char synth_buffer_getc(void)
{
char ch;
if (buff_out == buff_in)
return 0;
ch = *buff_out++;
if (buff_out > buffer_end)
buff_out = synth_buffer;
return ch;
}
EXPORT_SYMBOL_GPL(synth_buffer_getc);
char synth_buffer_peek(void)
{
if (buff_out == buff_in)
return 0;
return *buff_out;
}
EXPORT_SYMBOL_GPL(synth_buffer_peek);
void synth_buffer_clear(void)
{
buff_in = buff_out = synth_buffer;
return;
}
EXPORT_SYMBOL_GPL(synth_buffer_clear);
#include <linux/errno.h>
#include <linux/miscdevice.h> /* for misc_register, and SYNTH_MINOR */
#include <linux/types.h>
#include <linux/uaccess.h>
#include "speakup.h"
#include "spk_priv.h"
#ifndef SYNTH_MINOR
#define SYNTH_MINOR 25
#endif
static int misc_registered;
static int dev_opened;
static ssize_t speakup_file_write(struct file *fp, const char *buffer,
size_t nbytes, loff_t *ppos)
{
size_t count = nbytes;
const char *ptr = buffer;
int bytes;
unsigned long flags;
u_char buf[256];
if (synth == NULL)
return -ENODEV;
while (count > 0) {
bytes = min_t(size_t, count, sizeof(buf));
if (copy_from_user(buf, ptr, bytes))
return -EFAULT;
count -= bytes;
ptr += bytes;
spk_lock(flags);
synth_write(buf, bytes);
spk_unlock(flags);
}
return (ssize_t) nbytes;
}
static ssize_t speakup_file_read(struct file *fp, char *buf, size_t nbytes, loff_t *ppos)
{
return 0;
}
static int speakup_file_open(struct inode *ip, struct file *fp)
{
if (synth == NULL)
return -ENODEV;
if (xchg(&dev_opened, 1))
return -EBUSY;
return 0;
}
static int speakup_file_release(struct inode *ip, struct file *fp)
{
dev_opened = 0;
return 0;
}
static struct file_operations synth_fops = {
.read = speakup_file_read,
.write = speakup_file_write,
.open = speakup_file_open,
.release = speakup_file_release,
};
static struct miscdevice synth_device = {
.minor = SYNTH_MINOR,
.name = "synth",
.fops = &synth_fops,
};
void speakup_register_devsynth(void)
{
if (misc_registered != 0)
return;
/* zero it so if register fails, deregister will not ref invalid ptrs */
if (misc_register(&synth_device))
pr_warn("Couldn't initialize miscdevice /dev/synth.\n");
else {
pr_info("initialized device: /dev/synth, node (MAJOR %d, MINOR %d)\n", MISC_MAJOR, SYNTH_MINOR);
misc_registered = 1;
}
}
void speakup_unregister_devsynth(void)
{
if (!misc_registered)
return;
pr_info("speakup: unregistering synth device /dev/synth\n");
misc_deregister(&synth_device);
misc_registered = 0;
}
/* fakekey.c
* Functions for simulating keypresses.
*
* Copyright (C) 2010 the Speakup Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/preempt.h>
#include <linux/percpu.h>
#include <linux/input.h>
#include "speakup.h"
#define PRESSED 1
#define RELEASED 0
DEFINE_PER_CPU(bool, reporting_keystroke);
static struct input_dev *virt_keyboard;
int speakup_add_virtual_keyboard(void)
{
int err;
virt_keyboard = input_allocate_device();
if (!virt_keyboard)
return -ENOMEM;
virt_keyboard->name = "Speakup";
virt_keyboard->id.bustype = BUS_VIRTUAL;
virt_keyboard->phys = "speakup/input0";
virt_keyboard->dev.parent = NULL;
__set_bit(EV_KEY, virt_keyboard->evbit);
__set_bit(KEY_DOWN, virt_keyboard->keybit);
err = input_register_device(virt_keyboard);
if (err) {
input_free_device(virt_keyboard);
virt_keyboard = NULL;
}
return err;
}
void speakup_remove_virtual_keyboard(void)
{
if (virt_keyboard != NULL) {
input_unregister_device(virt_keyboard);
input_free_device(virt_keyboard);
virt_keyboard = NULL;
}
}
/*
* Send a simulated down-arrow to the application.
*/
void speakup_fake_down_arrow(void)
{
unsigned long flags;
/* disable keyboard interrupts */
local_irq_save(flags);
/* don't change CPU */
preempt_disable();
__get_cpu_var(reporting_keystroke) = true;
input_report_key(virt_keyboard, KEY_DOWN, PRESSED);
input_report_key(virt_keyboard, KEY_DOWN, RELEASED);
__get_cpu_var(reporting_keystroke) = false;
/* reenable preemption */
preempt_enable();
/* reenable keyboard interrupts */
local_irq_restore(flags);
}
/*
* Are we handling a simulated keypress on the current CPU?
* Returns a boolean.
*/
bool speakup_fake_key_pressed(void)
{
bool is_pressed;
is_pressed = get_cpu_var(reporting_keystroke);
put_cpu_var(reporting_keystroke);
return is_pressed;
}
This diff is collapsed.
#ifndef I18N_H
#define I18N_H
/* Internationalization declarations */
enum msg_index_t {
MSG_FIRST_INDEX ,
MSG_ANNOUNCEMENTS_START = MSG_FIRST_INDEX,
MSG_BLANK = MSG_ANNOUNCEMENTS_START,
MSG_IAM_ALIVE,
MSG_YOU_KILLED_SPEAKUP,
MSG_HEY_THATS_BETTER,
MSG_YOU_TURNED_ME_OFF,
MSG_PARKED,
MSG_UNPARKED,
MSG_MARK,
MSG_CUT,
MSG_MARK_CLEARED,
MSG_PASTE,
MSG_BRIGHT,
MSG_ON_BLINKING,
MSG_STATUS_START,
MSG_OFF = MSG_STATUS_START,
MSG_ON,
MSG_NO_WINDOW,
MSG_CURSOR_MSGS_START,
MSG_CURSORING_OFF = MSG_CURSOR_MSGS_START,
MSG_CURSORING_ON,
MSG_HIGHLIGHT_TRACKING,
MSG_READ_WINDOW,
MSG_READ_ALL,
MSG_EDIT_DONE,
MSG_WINDOW_ALREADY_SET,
MSG_END_BEFORE_START,
MSG_WINDOW_CLEARED,
MSG_WINDOW_SILENCED,
MSG_WINDOW_SILENCE_DISABLED,
MSG_ERROR,
MSG_GOTO_CANCELED,
MSG_GOTO,
MSG_LEAVING_HELP,
MSG_IS_UNASSIGNED,
MSG_HELP_INFO,
MSG_EDGE_MSGS_START,
MSG_EDGE_TOP = MSG_EDGE_MSGS_START,
MSG_EDGE_BOTTOM,
MSG_EDGE_LEFT,
MSG_EDGE_RIGHT,
MSG_NUMBER,
MSG_SPACE,
MSG_START, /* A little confusing, given our convention. */
MSG_END, /* A little confusing, given our convention. */
MSG_CTRL,
/* A message containing the single word "or". */
MSG_DISJUNCTION,
MSG_ANNOUNCEMENTS_END = MSG_DISJUNCTION,
/* Messages with format specifiers. */
MSG_FORMATTED_START,
MSG_POS_INFO = MSG_FORMATTED_START,
MSG_CHAR_INFO,
MSG_REPEAT_DESC,
MSG_REPEAT_DESC2,
MSG_WINDOW_LINE,
MSG_WINDOW_BOUNDARY,
MSG_EDIT_PROMPT,
MSG_NO_COMMAND,
MSG_KEYDESC,
MSG_FORMATTED_END = MSG_KEYDESC,
/* Control keys. */
MSG_CTL_START,
MSG_CTL_SHIFT = MSG_CTL_START,
MSG_CTL_ALTGR,
MSG_CTL_CONTROL,
MSG_CTL_ALT,
MSG_CTL_LSHIFT,
MSG_CTL_SPEAKUP,
MSG_CTL_LCONTROL,
MSG_CTL_RCONTROL,
MSG_CTL_CAPSSHIFT,
MSG_CTL_END = MSG_CTL_CAPSSHIFT,
/* Colors. */
MSG_COLORS_START,
MSG_COLOR_BLACK = MSG_COLORS_START,
MSG_COLOR_BLUE,
MSG_COLOR_GREEN,
MSG_COLOR_CYAN,
MSG_COLOR_RED,