25 #include <linux/kernel.h>
27 #include <linux/tty.h>
30 #include <linux/ctype.h>
35 #include <linux/keyboard.h>
37 #include <linux/input.h>
43 #include <linux/module.h>
44 #include <linux/sched.h>
45 #include <linux/slab.h>
46 #include <linux/types.h>
57 #define MAX_DELAY msecs_to_jiffies(500)
58 #define MINECHOCHAR SPACE
86 {
"some",
"/$%&@",
SOME},
87 {
"most",
"$%&#()=+*/@^<>|\\",
MOST},
88 {
"all",
"!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
PUNC},
89 {
"delimiters",
"",
B_WDLM},
91 {
"extended numeric",
"",
B_EXNUM},
92 {
"symbols",
"",
B_SYM},
96 static char mark_cut_flag;
105 static int cursor_track = 1, prev_cursor_track = 1;
115 #define read_all_mode CT_Max
119 static void spkup_write(
const char *in_buf,
int count);
121 static char *phonetic[] = {
122 "alfa",
"bravo",
"charlie",
"delta",
"echo",
"foxtrot",
"golf",
"hotel",
123 "india",
"juliett",
"keelo",
"leema",
"mike",
"november",
"oscar",
125 "keh beck",
"romeo",
"sierra",
"tango",
"uniform",
"victer",
"whiskey",
126 "x ray",
"yankee",
"zulu"
135 "null",
"^a",
"^b",
"^c",
"^d",
"^e",
"^f",
"^g",
136 "^h",
"^i",
"^j",
"^k",
"^l",
"^m",
"^n",
"^o",
137 "^p",
"^q",
"^r",
"^s",
"^t",
"^u",
"^v",
"^w",
138 "^x",
"^y",
"^z",
"control",
"control",
"control",
"control",
140 "space",
"bang!",
"quote",
"number",
"dollar",
"percent",
"and",
142 "left paren",
"right paren",
"star",
"plus",
"comma",
"dash",
145 "zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
147 "colon",
"semmy",
"less",
"equals",
"greater",
"question",
"at",
148 "EIGH",
"B",
"C",
"D",
"E",
"F",
"G",
149 "H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
150 "P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
151 "Y",
"ZED",
"left bracket",
"backslash",
"right bracket",
154 "accent",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
155 "h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
156 "p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
157 "x",
"y",
"zed",
"left brace",
"bar",
"right brace",
"tihlduh",
158 "del",
"control",
"control",
"control",
"control",
"control",
159 "control",
"control",
"control",
"control",
"control",
160 "control",
"control",
"control",
"control",
"control",
161 "control",
"control",
"control",
"control",
"control",
162 "control",
"control",
163 "control",
"control",
"control",
"control",
"control",
164 "control",
"control",
"control",
"control",
"control",
165 "nbsp",
"inverted bang",
166 "cents",
"pounds",
"currency",
"yen",
"broken bar",
"section",
167 "diaeresis",
"copyright",
"female ordinal",
"double left angle",
168 "not",
"soft hyphen",
"registered",
"macron",
169 "degrees",
"plus or minus",
"super two",
"super three",
170 "acute accent",
"micro",
"pilcrow",
"middle dot",
171 "cedilla",
"super one",
"male ordinal",
"double right angle",
172 "one quarter",
"one half",
"three quarters",
174 "A GRAVE",
"A ACUTE",
"A CIRCUMFLEX",
"A TILDE",
"A OOMLAUT",
176 "AE",
"C CIDELLA",
"E GRAVE",
"E ACUTE",
"E CIRCUMFLEX",
178 "I GRAVE",
"I ACUTE",
"I CIRCUMFLEX",
"I OOMLAUT",
"ETH",
180 "O GRAVE",
"O ACUTE",
"O CIRCUMFLEX",
"O TILDE",
"O OOMLAUT",
181 "multiplied by",
"O STROKE",
"U GRAVE",
"U ACUTE",
183 "U OOMLAUT",
"Y ACUTE",
"THORN",
"sharp s",
"a grave",
184 "a acute",
"a circumflex",
"a tilde",
"a oomlaut",
"a ring",
185 "ae",
"c cidella",
"e grave",
"e acute",
186 "e circumflex",
"e oomlaut",
"i grave",
"i acute",
188 "i oomlaut",
"eth",
"n tilde",
"o grave",
"o acute",
190 "o tilde",
"o oomlaut",
"divided by",
"o stroke",
"u grave",
192 "u circumflex",
"u oomlaut",
"y acute",
"thorn",
"y oomlaut"
200 static u_short default_chartab[256] = {
242 static int spk_keydown;
243 static u_char spk_lastkey, spk_close_press, keymap_flags;
244 static u_char last_keycode, this_speakup_key;
245 static u_long last_spk_jiffy;
255 .notifier_call = keyboard_notifier_call,
262 .notifier_call = vt_notifier_call,
265 static unsigned char get_attributes(
u16 *
pos)
270 static void speakup_date(
struct vc_data *
vc)
281 static const short vals[] = {
282 350, 370, 392, 414, 440, 466, 491, 523, 554, 587, 619, 659
286 freq = vals[val % 12];
288 freq *= (1 << (val / 12));
295 static void speakup_shut_up(
struct vc_data *vc)
306 static void speech_kill(
struct vc_data *vc)
323 static void speakup_off(
struct vc_data *vc)
335 static void speakup_parked(
struct vc_data *vc)
346 static void speakup_cut(
struct vc_data *vc)
348 static const char err_buf[] =
"set selection failed";
351 if (!mark_cut_flag) {
371 pr_warn(
"%sEFAULT\n", err_buf);
374 pr_warn(
"%sEINVAL\n", err_buf);
377 pr_warn(
"%sENOMEM\n", err_buf);
382 static void speakup_paste(
struct vc_data *vc)
393 static void say_attributes(
struct vc_data *vc)
418 static void announce_edge(
struct vc_data *vc,
int msg_id)
426 static void speak_char(
u_char ch)
430 if (direct && direct->
u.
n.value) {
441 pr_info(
"speak_char: cp == NULL!\n");
471 *attribs = (w & 0xff00) >> 8;
476 static void say_char(
struct vc_data *vc)
487 speak_char(ch & 0xff);
490 static void say_phonetic_char(
struct vc_data *vc)
505 static void say_prev_char(
struct vc_data *vc)
517 static void say_next_char(
struct vc_data *vc)
551 }
else if ((tmpx < vc->vc_cols - 2)
553 && ((
char)get_char(vc, (
u_short *) &tmp_pos + 1, &temp) >
568 buf[cnt++] = attr_ch & 0xff;
569 while (tmpx < vc->vc_cols - 1) {
573 if ((ch ==
SPACE) || ch == 0
582 static void say_word(
struct vc_data *vc)
584 u_long cnt = get_word(vc);
590 spkup_write(
buf, cnt);
594 static void say_prev_word(
struct vc_data *vc)
626 if (ch ==
SPACE || ch == 0)
632 if (
state < last_state) {
642 announce_edge(vc, edge_said);
646 static void say_next_word(
struct vc_data *vc)
659 if (ch ==
SPACE || ch == 0)
665 if (
state > last_state)
682 announce_edge(vc, edge_said);
686 static void spell_word(
struct vc_data *vc)
688 static char *delay_str[] = {
"",
",",
".",
". .",
". . ." };
694 while ((ch = (
u_char) *cp)) {
705 if (str_cap != last_cap) {
712 cp1 = phonetic[--ch];
727 static int get_line(
struct vc_data *vc)
735 for (i = 0; i < vc->
vc_cols; i++) {
739 for (--i; i >= 0; i--)
745 static void say_line(
struct vc_data *vc)
747 int i = get_line(vc);
766 static void say_prev_line(
struct vc_data *vc)
778 static void say_next_line(
struct vc_data *vc)
804 for (--i; i >= 0; i--)
825 if (say_from_to(vc, start, end, read_punc) <= 0)
832 static int currsentence;
833 static int numsentences[2];
834 static char *sentbufend[2];
835 static char *sentmarks[2][10];
838 static char sentbuf[2][256];
840 static int say_sentence_num(
int num,
int prev)
843 currsentence = num + 1;
844 if (prev && --bn == -1)
847 if (num > numsentences[bn])
850 spkup_write(sentmarks[bn][num], sentbufend[bn] - sentmarks[bn][num]);
854 static int get_sentence_buf(
struct vc_data *vc,
int read_punc)
867 numsentences[bn] = 0;
868 sentmarks[bn][0] = &sentbuf[bn][0];
873 while (start < end) {
876 if (sentbuf[bn][i] ==
SPACE && sentbuf[bn][i - 1] ==
'.'
877 && numsentences[bn] < 9) {
880 sentmarks[bn][numsentences[bn]] =
890 for (--i; i >= 0; i--)
891 if (sentbuf[bn][i] !=
SPACE)
898 sentbuf[bn][++
i] =
'\0';
900 sentbufend[bn] = &sentbuf[bn][
i];
901 return numsentences[bn];
912 for (from = start; from <
end; from = to) {
914 say_from_to(vc, from, to, 1);
918 static void say_screen(
struct vc_data *vc)
920 say_screen_from_to(vc, 0, vc->
vc_rows);
923 static void speakup_win_say(
struct vc_data *vc)
932 while (start <= end) {
935 say_from_to(vc, from, to, 1);
940 static void top_edge(
struct vc_data *vc)
948 static void bottom_edge(
struct vc_data *vc)
956 static void left_edge(
struct vc_data *vc)
964 static void right_edge(
struct vc_data *vc)
972 static void say_first_char(
struct vc_data *vc)
974 int i,
len = get_line(vc);
981 for (i = 0; i < len; i++)
991 static void say_last_char(
struct vc_data *vc)
993 int len = get_line(vc);
1007 static void say_position(
struct vc_data *vc)
1015 static void say_char_num(
struct vc_data *vc)
1025 static void say_from_top(
struct vc_data *vc)
1027 say_screen_from_to(vc, 0,
spk_y);
1030 static void say_to_bottom(
struct vc_data *vc)
1035 static void say_from_left(
struct vc_data *vc)
1037 say_line_from_to(vc, 0,
spk_x, 1);
1040 static void say_to_right(
struct vc_data *vc)
1047 static void spkup_write(
const char *in_buf,
int count)
1049 static int rep_count;
1050 static u_char ch =
'\0', old_ch =
'\0';
1051 static u_short char_type, last_type;
1052 int in_count =
count;
1057 if ((in_buf == sentmarks[bn][currsentence]) &&
1058 (currsentence <= numsentences[bn]))
1063 if (ch == old_ch && !(char_type &
B_NUM)) {
1064 if (++rep_count > 2)
1067 if ((last_type &
CH_RPT) && rep_count > 2) {
1075 if (ch == spk_lastkey) {
1079 }
else if (char_type &
B_ALPHA) {
1083 }
else if (char_type & B_NUM) {
1108 last_type = char_type;
1111 if (in_count > 2 && rep_count > 2) {
1112 if (last_type & CH_RPT) {
1123 static void read_all_doc(
struct vc_data *vc);
1129 unsigned long flags;
1143 cursor_track = prev_cursor_track;
1152 if (
say_ctrl && value < NUM_CTL_LABELS)
1157 static void do_handle_latin(
struct vc_data *vc,
u_char value,
char up_flag)
1159 unsigned long flags;
1162 spk_lastkey = spk_keydown = 0;
1171 spk_lastkey =
value;
1181 int i = 0, states, key_data_len;
1182 const u_char *cp = key_info;
1189 states = (
int)cp[1];
1190 key_data_len = (states + 1) * (num_keys + 1);
1198 memcpy(cp1, cp, key_data_len + 3);
1201 for (i = 1; i <= states; i++) {
1207 keymap_flags = *cp1++;
1208 while ((ch = *cp1)) {
1217 static struct var_t spk_vars[] = {
1234 static void toggle_cursoring(
struct vc_data *vc)
1237 cursor_track = prev_cursor_track;
1238 if (++cursor_track >=
CT_Max)
1248 for (i = 0; i < 256; i++) {
1274 if (mask <
PUNC && !(ch_type &
PUNC))
1290 if (speakup_console[vc_num] ==
NULL) {
1291 speakup_console[vc_num] = kzalloc(
sizeof(*speakup_console[0]),
1293 if (speakup_console[vc_num] ==
NULL)
1307 kfree(speakup_console[vc_num]);
1308 speakup_console[vc_num] =
NULL;
1312 static u_long old_cursor_pos, old_cursor_x, old_cursor_y;
1313 static int cursor_con;
1315 static void reset_highlight_buffers(
struct vc_data *);
1317 static int read_all_key;
1319 static void start_read_all_timer(
struct vc_data *vc,
int command);
1337 start_read_all_timer(vc, command);
1340 static void read_all_doc(
struct vc_data *vc)
1347 prev_cursor_track = cursor_track;
1350 if (get_sentence_buf(vc, 0) == -1)
1353 say_sentence_num(0, 0);
1355 start_read_all_timer(vc,
RA_TIMER);
1359 static void stop_read_all(
struct vc_data *vc)
1362 cursor_track = prev_cursor_track;
1367 static void start_read_all_timer(
struct vc_data *vc,
int command)
1369 struct var_t *cursor_timeout;
1378 static void handle_cursor_read_all(
struct vc_data *vc,
int command)
1380 int indcount, sentcount, rv,
sn;
1388 if (indcount == 1) {
1389 if (!say_sentence_num(sentcount + 1, 0)) {
1396 if (!say_sentence_num(sentcount + 1, 1)) {
1401 if (!say_sentence_num(sn, 0)) {
1407 start_read_all_timer(vc,
RA_TIMER);
1417 if (get_sentence_buf(vc, 0) == -1) {
1420 say_sentence_num(0, 0);
1422 start_read_all_timer(vc,
RA_TIMER);
1426 rv = get_sentence_buf(vc, 0);
1432 say_sentence_num(1, 0);
1434 start_read_all_timer(vc,
RA_TIMER);
1444 start_read_all_timer(vc,
RA_TIMER);
1449 static int pre_handle_cursor(
struct vc_data *vc,
u_char value,
char up_flag)
1451 unsigned long flags;
1462 start_read_all_timer(vc, value + 1);
1470 static void do_handle_cursor(
struct vc_data *vc,
u_char value,
char up_flag)
1472 unsigned long flags;
1473 struct var_t *cursor_timeout;
1486 is_cursor = value + 1;
1487 old_cursor_pos = vc->
vc_pos;
1488 old_cursor_x = vc->
vc_x;
1489 old_cursor_y = vc->
vc_y;
1493 reset_highlight_buffers(vc);
1500 static void update_color_buffer(
struct vc_data *vc,
const char *ic,
int len)
1505 bi = ((vc->
vc_attr & 0x70) >> 4);
1506 hi = speakup_console[vc_num]->
ht.highsize[
bi];
1509 if (speakup_console[vc_num]->ht.highsize[bi] == 0) {
1510 speakup_console[vc_num]->
ht.rpos[
bi] = vc->
vc_pos;
1511 speakup_console[vc_num]->
ht.rx[
bi] = vc->
vc_x;
1512 speakup_console[vc_num]->
ht.ry[
bi] = vc->
vc_y;
1515 if ((ic[i] > 32) && (ic[
i] < 127)) {
1516 speakup_console[vc_num]->
ht.highbuf[
bi][hi] = ic[
i];
1518 }
else if ((ic[i] == 32) && (hi != 0)) {
1519 if (speakup_console[vc_num]->ht.highbuf[bi][hi - 1] !=
1521 speakup_console[vc_num]->
ht.highbuf[
bi][hi] =
1528 speakup_console[vc_num]->
ht.highsize[
bi] = hi;
1531 static void reset_highlight_buffers(
struct vc_data *vc)
1535 for (i = 0; i < 8; i++)
1536 speakup_console[vc_num]->ht.highsize[i] = 0;
1539 static int count_highlight_color(
struct vc_data *vc)
1547 for (i = 0; i < 8; i++)
1548 speakup_console[vc_num]->ht.bgcount[i] = 0;
1553 for (ptr = start; ptr <
end; ptr++) {
1554 ch = get_attributes(ptr);
1555 bg = (ch & 0x70) >> 4;
1556 speakup_console[vc_num]->
ht.bgcount[
bg]++;
1562 for (i = 0; i < 8; i++)
1563 if (speakup_console[vc_num]->ht.bgcount[i] > 0)
1568 static int get_highlight_color(
struct vc_data *vc)
1571 unsigned int cptr[8],
tmp;
1574 for (i = 0; i < 8; i++)
1577 for (i = 0; i < 7; i++)
1578 for (j = i + 1; j < 8; j++)
1579 if (speakup_console[vc_num]->ht.bgcount[cptr[i]] >
1580 speakup_console[vc_num]->
ht.bgcount[cptr[j]]) {
1586 for (i = 0; i < 8; i++)
1587 if (speakup_console[vc_num]->ht.bgcount[cptr[i]] != 0)
1588 if (speakup_console[vc_num]->ht.highsize[cptr[i]] > 0)
1593 static int speak_highlight(
struct vc_data *vc)
1597 if (count_highlight_color(vc) == 1)
1599 hc = get_highlight_color(vc);
1601 d = vc->
vc_y - speakup_console[vc_num]->
ht.cy;
1602 if ((d == 1) || (d == -1))
1603 if (speakup_console[vc_num]->ht.ry[hc] != vc->
vc_y)
1607 spkup_write(speakup_console[vc_num]->ht.highbuf[hc],
1608 speakup_console[vc_num]->
ht.highsize[hc]);
1620 unsigned long flags;
1631 spk_keydown = is_cursor = 0;
1636 handle_cursor_read_all(vc, read_all_key);
1640 if (speak_highlight(vc)) {
1641 spk_keydown = is_cursor = 0;
1646 speakup_win_say(vc);
1647 else if (is_cursor == 1 || is_cursor == 4)
1648 say_line_from_to(vc, 0, vc->
vc_cols, 0);
1651 spk_keydown = is_cursor = 0;
1657 static void speakup_bs(
struct vc_data *vc)
1659 unsigned long flags;
1660 if (!speakup_console[vc->
vc_num])
1680 static void speakup_con_write(
struct vc_data *vc,
const char *
str,
int len)
1682 unsigned long flags;
1692 update_color_buffer(vc, str, len);
1704 spkup_write(str, len);
1710 unsigned long flags;
1720 static void do_handle_spec(
struct vc_data *vc,
u_char value,
char up_flag)
1722 unsigned long flags;
1743 if (speakup_console[vc->
vc_num])
1757 static int inc_dec_var(
u_char value)
1760 struct var_t *var_data;
1768 if (p_header ==
NULL)
1772 var_data = p_header->
data;
1775 if (!spk_close_press) {
1776 for (pn = p_header->
name; *pn; pn++) {
1783 snprintf(cp,
sizeof(num_buf) - (cp - num_buf),
" %d ",
1784 var_data->
u.
n.value);
1789 static void speakup_win_set(
struct vc_data *vc)
1822 static void speakup_win_clear(
struct vc_data *vc)
1830 static void speakup_win_enable(
struct vc_data *vc)
1843 static void speakup_bits(
struct vc_data *vc)
1850 pb_edit = &punc_info[
val];
1857 static u_char goto_buf[8];
1863 if (type ==
KT_LATIN && ch ==
'\n')
1870 ch = goto_buf[--num];
1871 goto_buf[num] =
'\0';
1872 spkup_write(&ch, 1);
1875 if (ch < '+' || ch >
'y')
1877 goto_buf[num++] = ch;
1878 goto_buf[num] =
'\0';
1879 spkup_write(&ch, 1);
1880 maxlen = (*goto_buf >=
'0') ? 3 : 4;
1881 if ((ch ==
'+' || ch ==
'-') && num == 1)
1883 if (ch >=
'0' && ch <=
'9' && num < maxlen)
1885 if (num < maxlen - 1 || num > maxlen)
1887 if (ch < 'x' || ch >
'y') {
1891 goto_buf[num = 0] =
'\0';
1898 if (*goto_buf <
'0')
1908 if (*goto_buf <
'0')
1918 goto_buf[num = 0] =
'\0';
1935 static void speakup_goto(
struct vc_data *vc)
1946 static void speakup_help(
struct vc_data *vc)
1951 static void do_nothing(
struct vc_data *vc)
1956 static u_char key_speakup, spk_key_locked;
1958 static void speakup_lock(
struct vc_data *vc)
1960 if (!spk_key_locked)
1961 spk_key_locked = key_speakup = 16;
1963 spk_key_locked = key_speakup = 0;
1969 do_nothing, speakup_goto, speech_kill, speakup_shut_up,
1970 speakup_cut, speakup_paste, say_first_char, say_last_char,
1971 say_char, say_prev_char, say_next_char,
1972 say_word, say_prev_word, say_next_word,
1973 say_line, say_prev_line, say_next_line,
1974 top_edge, bottom_edge, left_edge, right_edge,
1975 spell_word, spell_word, say_screen,
1976 say_position, say_attributes,
1977 speakup_off, speakup_parked, say_line,
1978 say_from_top, say_to_bottom,
1979 say_from_left, say_to_right,
1980 say_char_num, speakup_bits, speakup_bits, say_phonetic_char,
1981 speakup_bits, speakup_bits, speakup_bits,
1982 speakup_win_set, speakup_win_clear, speakup_win_enable, speakup_win_say,
1983 speakup_lock, speakup_help, toggle_cursoring, read_all_doc,
NULL
1993 this_speakup_key =
value;
1996 (*spkup_handler[
value]) (vc);
1998 if (inc_dec_var(value) < 0)
2003 static const char *pad_chars =
"0123456789+-*/\015,.?()";
2009 unsigned long flags;
2028 value = spk_lastkey = pad_chars[
value];
2053 shift_info = (shift_state & 0x0f) + key_speakup;
2056 new_key = key_info[
offset];
2060 if (!spk_key_locked)
2061 key_speakup = (up_flag) ? 0 : 16;
2070 if (last_keycode == keycode &&
2072 spk_close_press = 1;
2075 if (offset && key_info[offset])
2076 new_key = key_info[
offset];
2086 do_spkup(vc, new_key);
2087 spk_close_press = 0;
2102 if (type ==
KT_SPEC && value == 1) {
2107 else if (value == 0x7f)
2110 spk_close_press = 0;
2122 unsigned long code,
void *_param)
2127 int ret = NOTIFY_OK;
2148 keycode = param->
value;
2150 case KBD_UNBOUND_KEYCODE:
2160 ret = pre_handle_cursor(vc,
KVAL(param->
value), up);
2162 case KBD_POST_KEYSYM:{
2163 unsigned char type =
KTYP(param->
value) - 0xf0;
2167 do_handle_shift(vc, val, up);
2171 do_handle_latin(vc, val, up);
2174 do_handle_cursor(vc, val, up);
2177 do_handle_spec(vc, val, up);
2187 unsigned long code,
void *_param)
2200 if (param->
c ==
'\b')
2202 else if (param->
c < 0x100) {
2204 speakup_con_write(vc, &d, 1);
2215 static void __exit speakup_exit(
void)
2224 speakup_task =
NULL;
2232 kfree(speakup_console[i]);
2239 for (i = 0; i < 256; i++) {
2248 static int __init speakup_init(
void)
2267 for (i = 1; punc_info[
i].
mask != 0; i++)
2275 goto error_virtkeyboard;
2277 first_console = kzalloc(
sizeof(*first_console),
GFP_KERNEL);
2278 if (!first_console) {
2283 speakup_console[vc->
vc_num] = first_console;
2290 goto error_kobjects;
2298 goto error_kobjects;
2310 goto error_kbdnotifier;
2313 goto error_vtnotifier;
2317 if (IS_ERR(speakup_task)) {
2318 err = PTR_ERR(speakup_task);
2345 kfree(speakup_console[i]);
2354 for (i = 0; i < 256; i++) {