diff options
Diffstat (limited to 'drivers/staging/speakup')
29 files changed, 685 insertions, 497 deletions
diff --git a/drivers/staging/speakup/buffers.c b/drivers/staging/speakup/buffers.c index 723d5df..f459e40 100644 --- a/drivers/staging/speakup/buffers.c +++ b/drivers/staging/speakup/buffers.c @@ -7,10 +7,10 @@ #define SYNTH_BUF_SIZE 8192 /* currently 8K bytes */ -static u_char synth_buffer[SYNTH_BUF_SIZE]; /* 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 + SYNTH_BUF_SIZE - 1; +static u16 synth_buffer[SYNTH_BUF_SIZE]; /* guess what this is for! */ +static u16 *buff_in = synth_buffer; +static u16 *buff_out = synth_buffer; +static u16 *buffer_end = synth_buffer + SYNTH_BUF_SIZE - 1; /* These try to throttle applications by stopping the TTYs * Note: we need to make sure that we will restart them eventually, which is @@ -44,13 +44,13 @@ static void speakup_stop_ttys(void) static int synth_buffer_free(void) { - int bytes_free; + int chars_free; if (buff_in >= buff_out) - bytes_free = SYNTH_BUF_SIZE - (buff_in - buff_out); + chars_free = SYNTH_BUF_SIZE - (buff_in - buff_out); else - bytes_free = buff_out - buff_in; - return bytes_free; + chars_free = buff_out - buff_in; + return chars_free; } int synth_buffer_empty(void) @@ -59,7 +59,7 @@ int synth_buffer_empty(void) } EXPORT_SYMBOL_GPL(synth_buffer_empty); -void synth_buffer_add(char ch) +void synth_buffer_add(u16 ch) { if (!synth->alive) { /* This makes sure that we won't stop TTYs if there is no synth @@ -78,9 +78,9 @@ void synth_buffer_add(char ch) buff_in = synth_buffer; } -char synth_buffer_getc(void) +u16 synth_buffer_getc(void) { - char ch; + u16 ch; if (buff_out == buff_in) return 0; @@ -91,7 +91,7 @@ char synth_buffer_getc(void) } EXPORT_SYMBOL_GPL(synth_buffer_getc); -char synth_buffer_peek(void) +u16 synth_buffer_peek(void) { if (buff_out == buff_in) return 0; @@ -99,6 +99,18 @@ char synth_buffer_peek(void) } EXPORT_SYMBOL_GPL(synth_buffer_peek); +void synth_buffer_skip_nonlatin1(void) +{ + while (buff_out != buff_in) { + if (*buff_out < 0x100) + return; + buff_out++; + if (buff_out > buffer_end) + buff_out = synth_buffer; + } +} +EXPORT_SYMBOL_GPL(synth_buffer_skip_nonlatin1); + void synth_buffer_clear(void) { buff_in = synth_buffer; diff --git a/drivers/staging/speakup/fakekey.c b/drivers/staging/speakup/fakekey.c index d76da0a..294c74b 100644 --- a/drivers/staging/speakup/fakekey.c +++ b/drivers/staging/speakup/fakekey.c @@ -56,7 +56,7 @@ int speakup_add_virtual_keyboard(void) void speakup_remove_virtual_keyboard(void) { - if (virt_keyboard != NULL) { + if (virt_keyboard) { input_unregister_device(virt_keyboard); virt_keyboard = NULL; } diff --git a/drivers/staging/speakup/i18n.c b/drivers/staging/speakup/i18n.c index 2f9b3df..7809867 100644 --- a/drivers/staging/speakup/i18n.c +++ b/drivers/staging/speakup/i18n.c @@ -407,12 +407,12 @@ static char *next_specifier(char *input) int found = 0; char *next_percent = input; - while ((next_percent != NULL) && !found) { + while (next_percent && !found) { next_percent = strchr(next_percent, '%'); - if (next_percent != NULL) { + if (next_percent) { /* skip over doubled percent signs */ - while ((next_percent[0] == '%') - && (next_percent[1] == '%')) + while (next_percent[0] == '%' && + next_percent[1] == '%') next_percent += 2; if (*next_percent == '%') found = 1; @@ -476,19 +476,20 @@ static char *find_specifier_end(char *input) /* * Function: compare_specifiers * Compare the format specifiers pointed to by *input1 and *input2. - * Return 1 if they are the same, 0 otherwise. Advance *input1 and *input2 - * so that they point to the character following the end of the specifier. + * Return true if they are the same, false otherwise. + * Advance *input1 and *input2 so that they point to the character following + * the end of the specifier. */ -static int compare_specifiers(char **input1, char **input2) +static bool compare_specifiers(char **input1, char **input2) { - int same = 0; + bool same = false; char *end1 = find_specifier_end(*input1); char *end2 = find_specifier_end(*input2); size_t length1 = end1 - *input1; size_t length2 = end2 - *input2; if ((length1 == length2) && !memcmp(*input1, *input2, length1)) - same = 1; + same = true; *input1 = end1; *input2 = end2; @@ -499,12 +500,12 @@ static int compare_specifiers(char **input1, char **input2) * Function: fmt_validate * Check that two format strings contain the same number of format specifiers, * and that the order of specifiers is the same in both strings. - * Return 1 if the condition holds, 0 if it doesn't. + * Return true if the condition holds, false if it doesn't. */ -static int fmt_validate(char *template, char *user) +static bool fmt_validate(char *template, char *user) { - int valid = 1; - int still_comparing = 1; + bool valid = true; + bool still_comparing = true; char *template_ptr = template; char *user_ptr = user; @@ -516,10 +517,10 @@ static int fmt_validate(char *template, char *user) valid = compare_specifiers(&template_ptr, &user_ptr); } else { /* No more format specifiers in one or both strings. */ - still_comparing = 0; + still_comparing = false; /* See if one has more specifiers than the other. */ if (template_ptr || user_ptr) - valid = 0; + valid = false; } } return valid; @@ -540,34 +541,30 @@ static int fmt_validate(char *template, char *user) */ ssize_t spk_msg_set(enum msg_index_t index, char *text, size_t length) { - int rc = 0; char *newstr = NULL; unsigned long flags; - if ((index >= MSG_FIRST_INDEX) && (index < MSG_LAST_INDEX)) { - newstr = kmalloc(length + 1, GFP_KERNEL); - if (newstr) { - memcpy(newstr, text, length); - newstr[length] = '\0'; - if ((index >= MSG_FORMATTED_START - && index <= MSG_FORMATTED_END) - && !fmt_validate(speakup_default_msgs[index], - newstr)) { - kfree(newstr); - return -EINVAL; - } - spin_lock_irqsave(&speakup_info.spinlock, flags); - if (speakup_msgs[index] != speakup_default_msgs[index]) - kfree(speakup_msgs[index]); - speakup_msgs[index] = newstr; - spin_unlock_irqrestore(&speakup_info.spinlock, flags); - } else { - rc = -ENOMEM; - } - } else { - rc = -EINVAL; + if ((index < MSG_FIRST_INDEX) || (index >= MSG_LAST_INDEX)) + return -EINVAL; + + newstr = kmalloc(length + 1, GFP_KERNEL); + if (!newstr) + return -ENOMEM; + + memcpy(newstr, text, length); + newstr[length] = '\0'; + if (index >= MSG_FORMATTED_START && + index <= MSG_FORMATTED_END && + !fmt_validate(speakup_default_msgs[index], newstr)) { + kfree(newstr); + return -EINVAL; } - return rc; + spin_lock_irqsave(&speakup_info.spinlock, flags); + if (speakup_msgs[index] != speakup_default_msgs[index]) + kfree(speakup_msgs[index]); + speakup_msgs[index] = newstr; + spin_unlock_irqrestore(&speakup_info.spinlock, flags); + return 0; } /* @@ -607,7 +604,7 @@ void spk_reset_msg_group(struct msg_group_t *group) void spk_initialize_msgs(void) { memcpy(speakup_msgs, speakup_default_msgs, - sizeof(speakup_default_msgs)); + sizeof(speakup_default_msgs)); } /* Free user-supplied strings when module is unloaded: */ diff --git a/drivers/staging/speakup/keyhelp.c b/drivers/staging/speakup/keyhelp.c index ce94cb1..4e6e5da 100644 --- a/drivers/staging/speakup/keyhelp.c +++ b/drivers/staging/speakup/keyhelp.c @@ -117,7 +117,7 @@ static void say_key(int key) } if ((key > 0) && (key <= num_key_names)) synth_printf(" %s\n", - spk_msg_get(MSG_KEYNAMES_START + (key - 1))); + spk_msg_get(MSG_KEYNAMES_START + (key - 1))); } static int help_init(void) @@ -163,17 +163,15 @@ int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key) } cur_item = letter_offsets[ch - 'a']; } else if (type == KT_CUR) { - if (ch == 0 - && (MSG_FUNCNAMES_START + cur_item + 1) <= - MSG_FUNCNAMES_END) + if (ch == 0 && + (MSG_FUNCNAMES_START + cur_item + 1) <= MSG_FUNCNAMES_END) cur_item++; else if (ch == 3 && cur_item > 0) cur_item--; else return -1; - } else if (type == KT_SPKUP - && ch == SPEAKUP_HELP - && !spk_special_handler) { + } else if (type == KT_SPKUP && ch == SPEAKUP_HELP && + !spk_special_handler) { spk_special_handler = spk_handle_help; synth_printf("%s\n", spk_msg_get(MSG_HELP_INFO)); build_key_data(); /* rebuild each time in case new mapping */ @@ -182,7 +180,7 @@ int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key) name = NULL; if ((type != KT_SPKUP) && (key > 0) && (key <= num_key_names)) { synth_printf("%s\n", - spk_msg_get(MSG_KEYNAMES_START + key - 1)); + spk_msg_get(MSG_KEYNAMES_START + key - 1)); return 1; } for (i = 0; funcvals[i] != 0 && !name; i++) { diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c index 4e7ebc3..ca85476 100644 --- a/drivers/staging/speakup/kobjects.c +++ b/drivers/staging/speakup/kobjects.c @@ -26,7 +26,7 @@ * This is called when a user reads the characters or chartab sys file. */ static ssize_t chars_chartab_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) + struct kobj_attribute *attr, char *buf) { int i; int len = 0; @@ -79,7 +79,7 @@ static ssize_t chars_chartab_show(struct kobject *kobj, * character descriptions or chartab entries. */ static void report_char_chartab_status(int reset, int received, int used, - int rejected, int do_characters) + int rejected, int do_characters) { static char const *object_type[] = { "character class entries", @@ -92,8 +92,8 @@ static void report_char_chartab_status(int reset, int received, int used, pr_info("%s reset to defaults\n", object_type[do_characters]); } else if (received) { len = snprintf(buf, sizeof(buf), - " updated %d of %d %s\n", - used, received, object_type[do_characters]); + " updated %d of %d %s\n", + used, received, object_type[do_characters]); if (rejected) snprintf(buf + (len - 1), sizeof(buf) - (len - 1), " with %d reject%s\n", @@ -106,9 +106,10 @@ static void report_char_chartab_status(int reset, int received, int used, * This is called when a user changes the characters or chartab parameters. */ static ssize_t chars_chartab_store(struct kobject *kobj, - struct kobj_attribute *attr, const char *buf, size_t count) + struct kobj_attribute *attr, + const char *buf, size_t count) { - char *cp = (char *) buf; + char *cp = (char *)buf; char *end = cp + count; /* the null at the end of the buffer */ char *linefeed = NULL; char keyword[MAX_DESC_LEN + 1]; @@ -129,7 +130,6 @@ static ssize_t chars_chartab_store(struct kobject *kobj, spin_lock_irqsave(&speakup_info.spinlock, flags); while (cp < end) { - while ((cp < end) && (*cp == ' ' || *cp == '\t')) cp++; @@ -214,7 +214,7 @@ static ssize_t chars_chartab_store(struct kobject *kobj, spin_unlock_irqrestore(&speakup_info.spinlock, flags); report_char_chartab_status(reset, received, used, rejected, - do_characters); + do_characters); return retval; } @@ -222,7 +222,7 @@ static ssize_t chars_chartab_store(struct kobject *kobj, * This is called when a user reads the keymap parameter. */ static ssize_t keymap_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) + char *buf) { char *cp = buf; int i; @@ -258,7 +258,7 @@ static ssize_t keymap_show(struct kobject *kobj, struct kobj_attribute *attr, * This is called when a user changes the keymap parameter. */ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { int i; ssize_t ret = count; @@ -292,9 +292,9 @@ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr, i *= (int)cp1[-1] + 1; i += 2; /* 0 and last map ver */ if (cp1[-3] != KEY_MAP_VER || cp1[-1] > 10 || - i+SHIFT_TBL_SIZE+4 >= sizeof(spk_key_buf)) { + i + SHIFT_TBL_SIZE + 4 >= sizeof(spk_key_buf)) { pr_warn("i %d %d %d %d\n", i, - (int)cp1[-3], (int)cp1[-2], (int)cp1[-1]); + (int)cp1[-3], (int)cp1[-2], (int)cp1[-1]); kfree(in_buff); spin_unlock_irqrestore(&speakup_info.spinlock, flags); return -EINVAL; @@ -308,7 +308,7 @@ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr, if (i != 0 || cp1[-1] != KEY_MAP_VER || cp1[-2] != 0) { ret = -EINVAL; pr_warn("end %d %d %d %d\n", i, - (int)cp1[-3], (int)cp1[-2], (int)cp1[-1]); + (int)cp1[-3], (int)cp1[-2], (int)cp1[-1]); } else { if (spk_set_key_info(in_buff, spk_key_buf)) { spk_set_key_info(spk_key_defaults, spk_key_buf); @@ -325,7 +325,7 @@ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr, * This is called when a user changes the value of the silent parameter. */ static ssize_t silent_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { int len; struct vc_data *vc = vc_cons[fg_console].d; @@ -344,7 +344,7 @@ static ssize_t silent_store(struct kobject *kobj, struct kobj_attribute *attr, return -EINVAL; } spin_lock_irqsave(&speakup_info.spinlock, flags); - if (ch&2) { + if (ch & 2) { shut = 1; spk_do_flush(); } else { @@ -364,7 +364,7 @@ static ssize_t silent_store(struct kobject *kobj, struct kobj_attribute *attr, * This is called when a user reads the synth setting. */ static ssize_t synth_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) + char *buf) { int rv; @@ -379,7 +379,7 @@ static ssize_t synth_show(struct kobject *kobj, struct kobj_attribute *attr, * This is called when a user requests to change synthesizers. */ static ssize_t synth_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { int len; char new_synth_name[10]; @@ -392,7 +392,7 @@ static ssize_t synth_store(struct kobject *kobj, struct kobj_attribute *attr, len--; new_synth_name[len] = '\0'; spk_strlwr(new_synth_name); - if ((synth != NULL) && (!strcmp(new_synth_name, synth->name))) { + if (synth && !strcmp(new_synth_name, synth->name)) { pr_warn("%s already in use\n", new_synth_name); } else if (synth_init(new_synth_name) != 0) { pr_warn("failed to init synth %s\n", new_synth_name); @@ -405,7 +405,8 @@ static ssize_t synth_store(struct kobject *kobj, struct kobj_attribute *attr, * This is called when text is sent to the synth via the synth_direct file. */ static ssize_t synth_direct_store(struct kobject *kobj, - struct kobj_attribute *attr, const char *buf, size_t count) + struct kobj_attribute *attr, + const char *buf, size_t count) { u_char tmp[256]; int len; @@ -435,7 +436,7 @@ static ssize_t synth_direct_store(struct kobject *kobj, * This function is called when a user reads the version. */ static ssize_t version_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) + char *buf) { char *cp; @@ -451,7 +452,7 @@ static ssize_t version_show(struct kobject *kobj, struct kobj_attribute *attr, * This is called when a user reads the punctuation settings. */ static ssize_t punc_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) + char *buf) { int i; char *cp = buf; @@ -471,27 +472,27 @@ static ssize_t punc_show(struct kobject *kobj, struct kobj_attribute *attr, var = spk_get_punc_var(p_header->var_id); if (!var) { pr_warn("var is null, p_header->var_id is %i\n", - p_header->var_id); + p_header->var_id); return -EINVAL; } spin_lock_irqsave(&speakup_info.spinlock, flags); - pb = (struct st_bits_data *) &spk_punc_info[var->value]; + pb = (struct st_bits_data *)&spk_punc_info[var->value]; mask = pb->mask; for (i = 33; i < 128; i++) { - if (!(spk_chartab[i]&mask)) + if (!(spk_chartab[i] & mask)) continue; *cp++ = (char)i; } spin_unlock_irqrestore(&speakup_info.spinlock, flags); - return cp-buf; + return cp - buf; } /* * This is called when a user changes the punctuation settings. */ static ssize_t punc_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { int x; struct st_var_header *p_header; @@ -513,7 +514,7 @@ static ssize_t punc_store(struct kobject *kobj, struct kobj_attribute *attr, var = spk_get_punc_var(p_header->var_id); if (!var) { pr_warn("var is null, p_header->var_id is %i\n", - p_header->var_id); + p_header->var_id); return -EINVAL; } @@ -538,7 +539,7 @@ static ssize_t punc_store(struct kobject *kobj, struct kobj_attribute *attr, * This function is called when a user reads one of the variable parameters. */ ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) + char *buf) { int rv = 0; struct st_var_header *param; @@ -553,7 +554,7 @@ ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr, return -EINVAL; spin_lock_irqsave(&speakup_info.spinlock, flags); - var = (struct var_t *) param->data; + var = (struct var_t *)param->data; switch (param->var_type) { case VAR_NUM: case VAR_TIME: @@ -575,14 +576,14 @@ ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr, *cp1++ = '"'; *cp1++ = '\n'; *cp1 = '\0'; - rv = cp1-buf; + rv = cp1 - buf; } else { rv = sprintf(buf, "\"\"\n"); } break; default: rv = sprintf(buf, "Bad parameter %s, type %i\n", - param->name, param->var_type); + param->name, param->var_type); break; } spin_unlock_irqrestore(&speakup_info.spinlock, flags); @@ -594,7 +595,7 @@ EXPORT_SYMBOL_GPL(spk_var_show); * Used to reset either default_pitch or default_vol. */ static inline void spk_reset_default_value(char *header_name, - int *synth_default_value, int idx) + int *synth_default_value, int idx) { struct st_var_header *param; @@ -614,7 +615,7 @@ static inline void spk_reset_default_value(char *header_name, * variable parameters. */ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { struct st_var_header *param; int ret; @@ -663,9 +664,9 @@ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr, var_data = param->data; value = var_data->u.n.value; spk_reset_default_value("pitch", synth->default_pitch, - value); + value); spk_reset_default_value("vol", synth->default_vol, - value); + value); } break; case VAR_STRING: @@ -680,7 +681,7 @@ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr, ret = spk_set_string_var(cp, param, len); if (ret == -E2BIG) pr_warn("value too long for %s\n", - param->name); + param->name); break; default: pr_warn("%s unknown type %d\n", @@ -700,7 +701,7 @@ EXPORT_SYMBOL_GPL(spk_var_store); */ static ssize_t message_show_helper(char *buf, enum msg_index_t first, - enum msg_index_t last) + enum msg_index_t last) { size_t bufsize = PAGE_SIZE; char *buf_pointer = buf; @@ -713,7 +714,7 @@ static ssize_t message_show_helper(char *buf, enum msg_index_t first, if (bufsize <= 1) break; printed = scnprintf(buf_pointer, bufsize, "%d\t%s\n", - index, spk_msg_get(cursor)); + index, spk_msg_get(cursor)); buf_pointer += printed; bufsize -= printed; } @@ -722,7 +723,7 @@ static ssize_t message_show_helper(char *buf, enum msg_index_t first, } static void report_msg_status(int reset, int received, int used, - int rejected, char *groupname) + int rejected, char *groupname) { int len; char buf[160]; @@ -743,9 +744,9 @@ static void report_msg_status(int reset, int received, int used, } static ssize_t message_store_helper(const char *buf, size_t count, - struct msg_group_t *group) + struct msg_group_t *group) { - char *cp = (char *) buf; + char *cp = (char *)buf; char *end = cp + count; char *linefeed = NULL; char *temp = NULL; @@ -762,7 +763,6 @@ static ssize_t message_store_helper(const char *buf, size_t count, enum msg_index_t curmessage; while (cp < end) { - while ((cp < end) && (*cp == ' ' || *cp == '\t')) cp++; @@ -828,13 +828,15 @@ static ssize_t message_store_helper(const char *buf, size_t count, } static ssize_t message_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) + struct kobj_attribute *attr, char *buf) { ssize_t retval = 0; struct msg_group_t *group = spk_find_msg_group(attr->attr.name); unsigned long flags; - BUG_ON(!group); + if (WARN_ON(!group)) + return -EINVAL; + spin_lock_irqsave(&speakup_info.spinlock, flags); retval = message_show_helper(buf, group->start, group->end); spin_unlock_irqrestore(&speakup_info.spinlock, flags); @@ -842,11 +844,13 @@ static ssize_t message_show(struct kobject *kobj, } static ssize_t message_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { struct msg_group_t *group = spk_find_msg_group(attr->attr.name); - BUG_ON(!group); + if (WARN_ON(!group)) + return -EINVAL; + return message_store_helper(buf, count, group); } diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index c2f70ef..d2ad596 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -67,7 +67,7 @@ MODULE_PARM_DESC(quiet, "Do not announce when the synthesizer is found."); special_func spk_special_handler; short spk_pitch_shift, synth_flags; -static char buf[256]; +static u16 buf[256]; int spk_attrib_bleep, spk_bleeps, spk_bleep_time = 10; int spk_no_intr, spk_spell_delay; int spk_key_echo, spk_say_word_ctl; @@ -108,11 +108,12 @@ enum { CT_Window, CT_Max }; + #define read_all_mode CT_Max static struct tty_struct *tty; -static void spkup_write(const char *in_buf, int count); +static void spkup_write(const u16 *in_buf, int count); static char *phonetic[] = { "alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", @@ -238,7 +239,8 @@ static u_short default_chartab[256] = { struct task_struct *speakup_task; struct bleep spk_unprocessed_sound; static int spk_keydown; -static u_char spk_lastkey, spk_close_press, keymap_flags; +static u16 spk_lastkey; +static u_char spk_close_press, keymap_flags; static u_char last_keycode, this_speakup_key; static u_long last_spk_jiffy; @@ -299,7 +301,7 @@ static void speakup_shut_up(struct vc_data *vc) spk_shut_up |= 0x01; spk_parked &= 0xfe; speakup_date(vc); - if (synth != NULL) + if (synth) spk_do_flush(); } @@ -404,8 +406,9 @@ static void say_attributes(struct vc_data *vc) if (bg > 7) { synth_printf(" %s ", spk_msg_get(MSG_ON_BLINKING)); bg -= 8; - } else + } else { synth_printf(" %s ", spk_msg_get(MSG_ON)); + } synth_printf("%s\n", spk_msg_get(MSG_COLORS_START + bg)); } @@ -426,39 +429,38 @@ static void announce_edge(struct vc_data *vc, int msg_id) spk_msg_get(MSG_EDGE_MSGS_START + msg_id - 1)); } -static void speak_char(u_char ch) +static void speak_char(u16 ch) { - char *cp = spk_characters[ch]; + char *cp; struct var_t *direct = spk_get_var(DIRECT); - if (direct && direct->u.n.value) { - if (IS_CHAR(ch, B_CAP)) { + if (ch >= 0x100 || (direct && direct->u.n.value)) { + if (ch < 0x100 && IS_CHAR(ch, B_CAP)) { spk_pitch_shift++; synth_printf("%s", spk_str_caps_start); } - synth_printf("%c", ch); - if (IS_CHAR(ch, B_CAP)) + synth_putwc_s(ch); + if (ch < 0x100 && IS_CHAR(ch, B_CAP)) synth_printf("%s", spk_str_caps_stop); return; } - if (cp == NULL) { + + cp = spk_characters[ch]; + if (!cp) { pr_info("speak_char: cp == NULL!\n"); return; } - synth_buffer_add(SPACE); if (IS_CHAR(ch, B_CAP)) { spk_pitch_shift++; - synth_printf("%s", spk_str_caps_start); - synth_printf("%s", cp); - synth_printf("%s", spk_str_caps_stop); + synth_printf("%s %s %s", + spk_str_caps_start, cp, spk_str_caps_stop); } else { if (*cp == '^') { - synth_printf("%s", spk_msg_get(MSG_CTRL)); cp++; - } - synth_printf("%s", cp); + synth_printf(" %s%s ", spk_msg_get(MSG_CTRL), cp); + } else + synth_printf(" %s ", cp); } - synth_buffer_add(SPACE); } static u16 get_char(struct vc_data *vc, u16 *pos, u_char *attribs) @@ -478,7 +480,7 @@ static u16 get_char(struct vc_data *vc, u16 *pos, u_char *attribs) c |= 0x100; } - ch = inverse_translate(vc, c, 0); + ch = inverse_translate(vc, c, 1); *attribs = (w & 0xff00) >> 8; } return ch; @@ -486,7 +488,7 @@ static u16 get_char(struct vc_data *vc, u16 *pos, u_char *attribs) static void say_char(struct vc_data *vc) { - u_short ch; + u16 ch; spk_old_attr = spk_attr; ch = get_char(vc, (u_short *)spk_pos, &spk_attr); @@ -496,20 +498,20 @@ static void say_char(struct vc_data *vc) if (spk_attrib_bleep & 2) say_attributes(vc); } - speak_char(ch & 0xff); + speak_char(ch); } static void say_phonetic_char(struct vc_data *vc) { - u_short ch; + u16 ch; spk_old_attr = spk_attr; ch = get_char(vc, (u_short *)spk_pos, &spk_attr); - if (isascii(ch) && isalpha(ch)) { + if (ch <= 0x7f && isalpha(ch)) { ch &= 0x1f; synth_printf("%s\n", phonetic[--ch]); } else { - if (IS_CHAR(ch, B_NUM)) + if (ch < 0x100 && IS_CHAR(ch, B_NUM)) synth_printf("%s ", spk_msg_get(MSG_NUMBER)); speak_char(ch); } @@ -551,42 +553,42 @@ static void say_next_char(struct vc_data *vc) static u_long get_word(struct vc_data *vc) { u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos; - char ch; - u_short attr_ch; + u16 ch; + u16 attr_ch; u_char temp; spk_old_attr = spk_attr; - ch = (char)get_char(vc, (u_short *)tmp_pos, &temp); + ch = get_char(vc, (u_short *)tmp_pos, &temp); /* decided to take out the sayword if on a space (mis-information */ if (spk_say_word_ctl && ch == SPACE) { *buf = '\0'; synth_printf("%s\n", spk_msg_get(MSG_SPACE)); return 0; - } else if ((tmpx < vc->vc_cols - 2) - && (ch == SPACE || ch == 0 || IS_WDLM(ch)) - && ((char)get_char(vc, (u_short *)&tmp_pos + 1, &temp) > - SPACE)) { + } else if (tmpx < vc->vc_cols - 2 && + (ch == SPACE || ch == 0 || (ch < 0x100 && IS_WDLM(ch))) && + get_char(vc, (u_short *)&tmp_pos + 1, &temp) > SPACE) { tmp_pos += 2; tmpx++; } else while (tmpx > 0) { - ch = (char)get_char(vc, (u_short *)tmp_pos - 1, &temp); - if ((ch == SPACE || ch == 0 || IS_WDLM(ch)) - && ((char)get_char(vc, (u_short *)tmp_pos, &temp) > - SPACE)) + ch = get_char(vc, (u_short *)tmp_pos - 1, &temp); + if ((ch == SPACE || ch == 0 || + (ch < 0x100 && IS_WDLM(ch))) && + get_char(vc, (u_short *)tmp_pos, &temp) > SPACE) break; tmp_pos -= 2; tmpx--; } attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr); - buf[cnt++] = attr_ch & 0xff; + buf[cnt++] = attr_ch; while (tmpx < vc->vc_cols - 1) { tmp_pos += 2; tmpx++; - ch = (char)get_char(vc, (u_short *)tmp_pos, &temp); - if ((ch == SPACE) || ch == 0 - || (IS_WDLM(buf[cnt - 1]) && (ch > SPACE))) + ch = get_char(vc, (u_short *)tmp_pos, &temp); + if (ch == SPACE || ch == 0 || + (buf[cnt - 1] < 0x100 && IS_WDLM(buf[cnt - 1]) && + ch > SPACE)) break; buf[cnt++] = ch; } @@ -610,7 +612,7 @@ static void say_word(struct vc_data *vc) static void say_prev_word(struct vc_data *vc) { u_char temp; - char ch; + u16 ch; u_short edge_said = 0, last_state = 0, state = 0; spk_parked |= 0x01; @@ -636,13 +638,14 @@ static void say_prev_word(struct vc_data *vc) break; spk_y--; spk_x = vc->vc_cols - 1; - } else + } else { spk_x--; + } spk_pos -= 2; - ch = (char)get_char(vc, (u_short *)spk_pos, &temp); + ch = get_char(vc, (u_short *)spk_pos, &temp); if (ch == SPACE || ch == 0) state = 0; - else if (IS_WDLM(ch)) + else if (ch < 0x100 && IS_WDLM(ch)) state = 1; else state = 2; @@ -663,7 +666,7 @@ static void say_prev_word(struct vc_data *vc) static void say_next_word(struct vc_data *vc) { u_char temp; - char ch; + u16 ch; u_short edge_said = 0, last_state = 2, state = 0; spk_parked |= 0x01; @@ -672,10 +675,10 @@ static void say_next_word(struct vc_data *vc) return; } while (1) { - ch = (char)get_char(vc, (u_short *)spk_pos, &temp); + ch = get_char(vc, (u_short *)spk_pos, &temp); if (ch == SPACE || ch == 0) state = 0; - else if (IS_WDLM(ch)) + else if (ch < 0x100 && IS_WDLM(ch)) state = 1; else state = 2; @@ -690,8 +693,9 @@ static void say_next_word(struct vc_data *vc) spk_y++; spk_x = 0; edge_said = edge_right; - } else + } else { spk_x++; + } spk_pos += 2; last_state = state; } @@ -703,39 +707,47 @@ static void say_next_word(struct vc_data *vc) static void spell_word(struct vc_data *vc) { static char const *delay_str[] = { "", ",", ".", ". .", ". . ." }; - char *cp = buf, *str_cap = spk_str_caps_stop; - char *cp1, *last_cap = spk_str_caps_stop; - u_char ch; + u16 *cp = buf; + char *cp1; + char *str_cap = spk_str_caps_stop; + char *last_cap = spk_str_caps_stop; + struct var_t *direct = spk_get_var(DIRECT); + u16 ch; if (!get_word(vc)) return; - while ((ch = (u_char)*cp)) { + while ((ch = *cp)) { if (cp != buf) synth_printf(" %s ", delay_str[spk_spell_delay]); - if (IS_CHAR(ch, B_CAP)) { + /* FIXME: Non-latin1 considered as lower case */ + if (ch < 0x100 && IS_CHAR(ch, B_CAP)) { str_cap = spk_str_caps_start; if (*spk_str_caps_stop) spk_pitch_shift++; else /* synth has no pitch */ last_cap = spk_str_caps_stop; - } else + } else { str_cap = spk_str_caps_stop; + } if (str_cap != last_cap) { synth_printf("%s", str_cap); last_cap = str_cap; } - if (this_speakup_key == SPELL_PHONETIC - && (isascii(ch) && isalpha(ch))) { - ch &= 31; + if (ch >= 0x100 || (direct && direct->u.n.value)) { + synth_putwc_s(ch); + } else if (this_speakup_key == SPELL_PHONETIC && + ch <= 0x7f && isalpha(ch)) { + ch &= 0x1f; cp1 = phonetic[--ch]; + synth_printf("%s", cp1); } else { cp1 = spk_characters[ch]; if (*cp1 == '^') { synth_printf("%s", spk_msg_get(MSG_CTRL)); cp1++; } + synth_printf("%s", cp1); } - synth_printf("%s", cp1); cp++; } if (str_cap != spk_str_caps_stop) @@ -751,7 +763,7 @@ static int get_line(struct vc_data *vc) spk_old_attr = spk_attr; spk_attr = get_attributes(vc, (u_short *)spk_pos); for (i = 0; i < vc->vc_cols; i++) { - buf[i] = (u_char)get_char(vc, (u_short *)tmp, &tmp2); + buf[i] = get_char(vc, (u_short *)tmp, &tmp2); tmp += 2; } for (--i; i >= 0; i--) @@ -763,7 +775,7 @@ static int get_line(struct vc_data *vc) static void say_line(struct vc_data *vc) { int i = get_line(vc); - char *cp; + u16 *cp; u_short saved_punc_mask = spk_punc_mask; if (i == 0) { @@ -775,7 +787,7 @@ static void say_line(struct vc_data *vc) cp = buf; while (*cp == SPACE) cp++; - synth_printf("%d, ", (cp - buf) + 1); + synth_printf("%zd, ", (cp - buf) + 1); } spk_punc_mask = spk_punc_masks[spk_reading_punc]; spkup_write(buf, i); @@ -816,7 +828,7 @@ static int say_from_to(struct vc_data *vc, u_long from, u_long to, spk_old_attr = spk_attr; spk_attr = get_attributes(vc, (u_short *)from); while (from < to) { - buf[i++] = (char)get_char(vc, (u_short *)from, &tmp); + buf[i++] = get_char(vc, (u_short *)from, &tmp); from += 2; if (i >= vc->vc_size_row) break; @@ -852,11 +864,11 @@ static void say_line_from_to(struct vc_data *vc, u_long from, u_long to, static int currsentence; static int numsentences[2]; -static char *sentbufend[2]; -static char *sentmarks[2][10]; +static u16 *sentbufend[2]; +static u16 *sentmarks[2][10]; static int currbuf; static int bn; -static char sentbuf[2][256]; +static u16 sentbuf[2][256]; static int say_sentence_num(int num, int prev) { @@ -892,10 +904,10 @@ static int get_sentence_buf(struct vc_data *vc, int read_punc) spk_attr = get_attributes(vc, (u_short *)start); while (start < end) { - sentbuf[bn][i] = (char)get_char(vc, (u_short *)start, &tmp); + sentbuf[bn][i] = get_char(vc, (u_short *)start, &tmp); if (i > 0) { - if (sentbuf[bn][i] == SPACE && sentbuf[bn][i - 1] == '.' - && numsentences[bn] < 9) { + if (sentbuf[bn][i] == SPACE && sentbuf[bn][i - 1] == '.' && + numsentences[bn] < 9) { /* Sentence Marker */ numsentences[bn]++; sentmarks[bn][numsentences[bn]] = @@ -995,7 +1007,7 @@ static void right_edge(struct vc_data *vc) static void say_first_char(struct vc_data *vc) { int i, len = get_line(vc); - u_char ch; + u16 ch; spk_parked |= 0x01; if (len == 0) { @@ -1015,7 +1027,7 @@ static void say_first_char(struct vc_data *vc) static void say_last_char(struct vc_data *vc) { int len = get_line(vc); - u_char ch; + u16 ch; spk_parked |= 0x01; if (len == 0) { @@ -1040,9 +1052,8 @@ static void say_position(struct vc_data *vc) static void say_char_num(struct vc_data *vc) { u_char tmp; - u_short ch = get_char(vc, (u_short *)spk_pos, &tmp); + u16 ch = get_char(vc, (u_short *)spk_pos, &tmp); - ch &= 0xff; synth_printf(spk_msg_get(MSG_CHAR_INFO), ch, ch); } @@ -1070,10 +1081,10 @@ static void say_to_right(struct vc_data *vc) /* end of stub functions. */ -static void spkup_write(const char *in_buf, int count) +static void spkup_write(const u16 *in_buf, int count) { static int rep_count; - static u_char ch = '\0', old_ch = '\0'; + static u16 ch = '\0', old_ch = '\0'; static u_short char_type, last_type; int in_count = count; @@ -1085,8 +1096,11 @@ static void spkup_write(const char *in_buf, int count) (currsentence <= numsentences[bn])) synth_insert_next_index(currsentence++); } - ch = (u_char)*in_buf++; - char_type = spk_chartab[ch]; + ch = *in_buf++; + if (ch < 0x100) + char_type = spk_chartab[ch]; + else + char_type = ALPHA; if (ch == old_ch && !(char_type & B_NUM)) { if (++rep_count > 2) continue; @@ -1106,10 +1120,10 @@ static void spkup_write(const char *in_buf, int count) } else if (char_type & B_ALPHA) { if ((synth_flags & SF_DEC) && (last_type & PUNC)) synth_buffer_add(SPACE); - synth_printf("%c", ch); + synth_putwc_s(ch); } else if (char_type & B_NUM) { rep_count = 0; - synth_printf("%c", ch); + synth_putwc_s(ch); } else if (char_type & spk_punc_mask) { speak_char(ch); char_type &= ~PUNC; /* for dec nospell processing */ @@ -1122,7 +1136,7 @@ static void spkup_write(const char *in_buf, int count) * repeats on you don't get nothing repeated count */ if (ch != old_ch) - synth_printf("%c", ch); + synth_putwc_s(ch); else rep_count = 0; } else { @@ -1140,7 +1154,7 @@ static void spkup_write(const char *in_buf, int count) if (last_type & CH_RPT) { synth_printf(" "); synth_printf(spk_msg_get(MSG_REPEAT_DESC2), - ++rep_count); + ++rep_count); synth_printf(" "); } rep_count = 0; @@ -1157,7 +1171,7 @@ static void do_handle_shift(struct vc_data *vc, u_char value, char up_flag) { unsigned long flags; - if (synth == NULL || up_flag || spk_killed) + if (!synth || up_flag || spk_killed) return; spin_lock_irqsave(&speakup_info.spinlock, flags); if (cursor_track == read_all_mode) { @@ -1195,7 +1209,7 @@ static void do_handle_latin(struct vc_data *vc, u_char value, char up_flag) spin_unlock_irqrestore(&speakup_info.spinlock, flags); return; } - if (synth == NULL || spk_killed) { + if (!synth || spk_killed) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); return; } @@ -1216,13 +1230,19 @@ int spk_set_key_info(const u_char *key_info, u_char *k_buffer) u_char ch, version, num_keys; version = *cp++; - if (version != KEY_MAP_VER) - return -1; + if (version != KEY_MAP_VER) { + pr_debug("version found %d should be %d\n", + version, KEY_MAP_VER); + return -EINVAL; + } num_keys = *cp; states = (int)cp[1]; key_data_len = (states + 1) * (num_keys + 1); - if (key_data_len + SHIFT_TBL_SIZE + 4 >= sizeof(spk_key_buf)) - return -2; + if (key_data_len + SHIFT_TBL_SIZE + 4 >= sizeof(spk_key_buf)) { + pr_debug("too many key_infos (%d over %u)\n", + key_data_len + SHIFT_TBL_SIZE + 4, (unsigned int)(sizeof(spk_key_buf))); + return -EINVAL; + } memset(k_buffer, 0, SHIFT_TBL_SIZE); memset(spk_our_keys, 0, sizeof(spk_our_keys)); spk_shift_table = k_buffer; @@ -1233,14 +1253,19 @@ int spk_set_key_info(const u_char *key_info, u_char *k_buffer) cp1 += 2; /* now pointing at shift states */ for (i = 1; i <= states; i++) { ch = *cp1++; - if (ch >= SHIFT_TBL_SIZE) - return -3; + if (ch >= SHIFT_TBL_SIZE) { + pr_debug("(%d) not valid shift state (max_allowed = %d)\n", ch, + SHIFT_TBL_SIZE); + return -EINVAL; + } spk_shift_table[ch] = i; } keymap_flags = *cp1++; while ((ch = *cp1)) { - if (ch >= MAX_KEY) - return -4; + if (ch >= MAX_KEY) { + pr_debug("(%d), not valid key, (max_allowed = %d)\n", ch, MAX_KEY); + return -EINVAL; + } spk_our_keys[ch] = cp1; cp1 += states + 1; } @@ -1279,8 +1304,8 @@ void spk_reset_default_chars(void) /* First, free any non-default */ for (i = 0; i < 256; i++) { - if ((spk_characters[i] != NULL) - && (spk_characters[i] != spk_default_chars[i])) + if (spk_characters[i] && + (spk_characters[i] != spk_default_chars[i])) kfree(spk_characters[i]); } @@ -1316,19 +1341,20 @@ static int edit_bits(struct vc_data *vc, u_char type, u_char ch, u_short key) } /* Allocation concurrency is protected by the console semaphore */ -static int speakup_allocate(struct vc_data *vc) +static int speakup_allocate(struct vc_data *vc, gfp_t gfp_flags) { int vc_num; vc_num = vc->vc_num; - if (speakup_console[vc_num] == NULL) { + if (!speakup_console[vc_num]) { speakup_console[vc_num] = kzalloc(sizeof(*speakup_console[0]), - GFP_ATOMIC); - if (speakup_console[vc_num] == NULL) + gfp_flags); + if (!speakup_console[vc_num]) return -ENOMEM; speakup_date(vc); - } else if (!spk_parked) + } else if (!spk_parked) { speakup_date(vc); + } return 0; } @@ -1373,7 +1399,7 @@ static void kbd_fakekey2(struct vc_data *vc, int command) static void read_all_doc(struct vc_data *vc) { - if ((vc->vc_num != fg_console) || synth == NULL || spk_shut_up) + if ((vc->vc_num != fg_console) || !synth || spk_shut_up) return; if (!synth_supports_indexing()) return; @@ -1381,9 +1407,9 @@ static void read_all_doc(struct vc_data *vc) prev_cursor_track = cursor_track; cursor_track = read_all_mode; spk_reset_index_count(0); - if (get_sentence_buf(vc, 0) == -1) + if (get_sentence_buf(vc, 0) == -1) { kbd_fakekey2(vc, RA_DOWN_ARROW); - else { + } else { say_sentence_num(0, 0); synth_insert_next_index(0); start_read_all_timer(vc, RA_TIMER); @@ -1430,8 +1456,9 @@ static void handle_cursor_read_all(struct vc_data *vc, int command) if (!say_sentence_num(sentcount + 1, 1)) { sn = 1; spk_reset_index_count(sn); - } else + } else { synth_insert_next_index(0); + } if (!say_sentence_num(sn, 0)) { kbd_fakekey2(vc, RA_FIND_NEXT_SENT); return; @@ -1460,9 +1487,9 @@ static void handle_cursor_read_all(struct vc_data *vc, int command) rv = get_sentence_buf(vc, 0); if (rv == -1) read_all_doc(vc); - if (rv == 0) + if (rv == 0) { kbd_fakekey2(vc, RA_FIND_NEXT_SENT); - else { + } else { say_sentence_num(1, 0); synth_insert_next_index(0); start_read_all_timer(vc, RA_TIMER); @@ -1487,7 +1514,7 @@ static int pre_handle_cursor(struct vc_data *vc, u_char value, char up_flag) spin_lock_irqsave(&speakup_info.spinlock, flags); if (cursor_track == read_all_mode) { spk_parked &= 0xfe; - if (synth == NULL || up_flag || spk_shut_up) { + if (!synth || up_flag || spk_shut_up) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); return NOTIFY_STOP; } @@ -1509,7 +1536,7 @@ static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag) spin_lock_irqsave(&speakup_info.spinlock, flags); spk_parked &= 0xfe; - if (synth == NULL || up_flag || spk_shut_up || cursor_track == CT_Off) { + if (!synth || up_flag || spk_shut_up || cursor_track == CT_Off) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); return; } @@ -1533,7 +1560,7 @@ static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag) spin_unlock_irqrestore(&speakup_info.spinlock, flags); } -static void update_color_buffer(struct vc_data *vc, const char *ic, int len) +static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len) { int i, bi, hi; int vc_num = vc->vc_num; @@ -1548,7 +1575,7 @@ static void update_color_buffer(struct vc_data *vc, const char *ic, int len) speakup_console[vc_num]->ht.ry[bi] = vc->vc_y; } while ((hi < COLOR_BUFFER_SIZE) && (i < len)) { - if ((ic[i] > 32) && (ic[i] < 127)) { + if (ic[i] > 32) { speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i]; hi++; } else if ((ic[i] == 32) && (hi != 0)) { @@ -1705,7 +1732,7 @@ static void speakup_bs(struct vc_data *vc) return; if (!spk_parked) speakup_date(vc); - if (spk_shut_up || synth == NULL) { + if (spk_shut_up || !synth) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); return; } @@ -1718,11 +1745,11 @@ static void speakup_bs(struct vc_data *vc) } /* called by: vt_notifier_call() */ -static void speakup_con_write(struct vc_data *vc, const char *str, int len) +static void speakup_con_write(struct vc_data *vc, u16 *str, int len) { unsigned long flags; - if ((vc->vc_num != fg_console) || spk_shut_up || synth == NULL) + if ((vc->vc_num != fg_console) || spk_shut_up || !synth) return; if (!spin_trylock_irqsave(&speakup_info.spinlock, flags)) /* Speakup output, discard */ @@ -1751,7 +1778,7 @@ static void speakup_con_update(struct vc_data *vc) { unsigned long flags; - if (speakup_console[vc->vc_num] == NULL || spk_parked) + if (!speakup_console[vc->vc_num] || spk_parked) return; if (!spin_trylock_irqsave(&speakup_info.spinlock, flags)) /* Speakup output, discard */ @@ -1766,7 +1793,7 @@ static void do_handle_spec(struct vc_data *vc, u_char value, char up_flag) int on_off = 2; char *label; - if (synth == NULL || up_flag || spk_killed) + if (!synth || up_flag || spk_killed) return; spin_lock_irqsave(&speakup_info.spinlock, flags); spk_shut_up &= 0xfe; @@ -1810,7 +1837,7 @@ static int inc_dec_var(u_char value) var_id = var_id / 2 + FIRST_SET_VAR; p_header = spk_get_var_header(var_id); - if (p_header == NULL) + if (!p_header) return -1; if (p_header->var_type != VAR_NUM) return -1; @@ -1893,7 +1920,7 @@ static void speakup_bits(struct vc_data *vc) { int val = this_speakup_key - (FIRST_EDIT_BITS - 1); - if (spk_special_handler != NULL || val < 1 || val > 6) { + if (spk_special_handler || val < 1 || val > 6) { synth_printf("%s\n", spk_msg_get(MSG_ERROR)); return; } @@ -1908,6 +1935,7 @@ static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key) static int num; int maxlen; char *cp; + u16 wch; if (type == KT_SPKUP && ch == SPEAKUP_GOTO) goto do_goto; @@ -1916,18 +1944,20 @@ static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key) if (type != 0) goto oops; if (ch == 8) { + u16 wch; if (num == 0) return -1; - ch = goto_buf[--num]; + wch = goto_buf[--num]; goto_buf[num] = '\0'; - spkup_write(&ch, 1); + spkup_write(&wch, 1); return 1; } if (ch < '+' || ch > 'y') goto oops; + wch = ch; goto_buf[num++] = ch; goto_buf[num] = '\0'; - spkup_write(&ch, 1); + spkup_write(&wch, 1); maxlen = (*goto_buf >= '0') ? 3 : 4; if ((ch == '+' || ch == '-') && num == 1) return 1; @@ -1984,7 +2014,7 @@ do_goto: static void speakup_goto(struct vc_data *vc) { - if (spk_special_handler != NULL) { + if (spk_special_handler) { synth_printf("%s\n", spk_msg_get(MSG_ERROR)); return; } @@ -2072,8 +2102,8 @@ speakup_key(struct vc_data *vc, int shift_state, int keycode, u_short keysym, tty = vc->port.tty; if (type >= 0xf0) type -= 0xf0; - if (type == KT_PAD - && (vt_get_leds(fg_console, VC_NUMLOCK))) { + if (type == KT_PAD && + (vt_get_leds(fg_console, VC_NUMLOCK))) { if (up_flag) { spk_keydown = 0; goto out; @@ -2135,7 +2165,7 @@ speakup_key(struct vc_data *vc, int shift_state, int keycode, u_short keysym, } } no_map: - if (type == KT_SPKUP && spk_special_handler == NULL) { + if (type == KT_SPKUP && !spk_special_handler) { do_spkup(vc, new_key); spk_close_press = 0; ret = 1; @@ -2144,10 +2174,10 @@ no_map: if (up_flag || spk_killed || type == KT_SHIFT) goto out; spk_shut_up &= 0xfe; - kh = (value == KVAL(K_DOWN)) - || (value == KVAL(K_UP)) - || (value == KVAL(K_LEFT)) - || (value == KVAL(K_RIGHT)); + kh = (value == KVAL(K_DOWN)) || + (value == KVAL(K_UP)) || + (value == KVAL(K_LEFT)) || + (value == KVAL(K_RIGHT)); if ((cursor_track != read_all_mode) || !kh) if (!spk_no_intr) spk_do_flush(); @@ -2155,10 +2185,11 @@ no_map: if (type == KT_SPEC && value == 1) { value = '\n'; type = KT_LATIN; - } else if (type == KT_LETTER) + } else if (type == KT_LETTER) { type = KT_LATIN; - else if (value == 0x7f) + } else if (value == 0x7f) { value = 8; /* make del = backspace */ + } ret = (*spk_special_handler) (vc, type, value, keycode); spk_close_press = 0; if (ret < 0) @@ -2246,17 +2277,16 @@ static int vt_notifier_call(struct notifier_block *nb, switch (code) { case VT_ALLOCATE: if (vc->vc_mode == KD_TEXT) - speakup_allocate(vc); + speakup_allocate(vc, GFP_ATOMIC); break; case VT_DEALLOCATE: speakup_deallocate(vc); break; case VT_WRITE: - if (param->c == '\b') + if (param->c == '\b') { speakup_bs(vc); - else if (param->c < 0x100) { - char d = param->c; - + } else { + u16 d = param->c; speakup_con_write(vc, &d, 1); } break; @@ -2306,7 +2336,6 @@ static int __init speakup_init(void) { int i; long err = 0; - struct st_spk_t *first_console; struct vc_data *vc = vc_cons[fg_console].d; struct var_t *var; @@ -2331,18 +2360,9 @@ static int __init speakup_init(void) if (err) goto error_virtkeyboard; - first_console = kzalloc(sizeof(*first_console), GFP_KERNEL); - if (!first_console) { - err = -ENOMEM; - goto error_alloc; - } - - speakup_console[vc->vc_num] = first_console; - speakup_date(vc); - for (i = 0; i < MAX_NR_CONSOLES; i++) if (vc_cons[i].d) { - err = speakup_allocate(vc_cons[i].d); + err = speakup_allocate(vc_cons[i].d, GFP_KERNEL); if (err) goto error_kobjects; } @@ -2401,7 +2421,6 @@ error_kobjects: for (i = 0; i < MAX_NR_CONSOLES; i++) kfree(speakup_console[i]); -error_alloc: speakup_remove_virtual_keyboard(); error_virtkeyboard: diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c index aeb2b86..08f68fc 100644 --- a/drivers/staging/speakup/selection.c +++ b/drivers/staging/speakup/selection.c @@ -75,7 +75,7 @@ int speakup_set_selection(struct tty_struct *tty) speakup_clear_selection(); spk_sel_cons = vc_cons[fg_console].d; dev_warn(tty->dev, - "Selection: mark console not the same as cut\n"); + "Selection: mark console not the same as cut\n"); return -EINVAL; } @@ -99,7 +99,7 @@ int speakup_set_selection(struct tty_struct *tty) sel_start = new_sel_start; sel_end = new_sel_end; /* Allocate a new buffer before freeing the old one ... */ - bp = kmalloc((sel_end-sel_start)/2+1, GFP_ATOMIC); + bp = kmalloc((sel_end - sel_start) / 2 + 1, GFP_ATOMIC); if (!bp) { speakup_clear_selection(); return -ENOMEM; @@ -175,7 +175,7 @@ static struct speakup_paste_work speakup_paste_work = { int speakup_paste_selection(struct tty_struct *tty) { - if (cmpxchg(&speakup_paste_work.tty, NULL, tty) != NULL) + if (cmpxchg(&speakup_paste_work.tty, NULL, tty)) return -EBUSY; tty_kref_get(tty); diff --git a/drivers/staging/speakup/serialio.c b/drivers/staging/speakup/serialio.c index ef89dc1..ba060d0 100644 --- a/drivers/staging/speakup/serialio.c +++ b/drivers/staging/speakup/serialio.c @@ -21,9 +21,21 @@ static void start_serial_interrupt(int irq); static const struct old_serial_port rs_table[] = { SERIAL_PORT_DFNS }; + static const struct old_serial_port *serstate; static int timeouts; +static int spk_serial_out(struct spk_synth *in_synth, const char ch); +static void spk_serial_send_xchar(char ch); +static void spk_serial_tiocmset(unsigned int set, unsigned int clear); + +struct spk_io_ops spk_serial_io_ops = { + .synth_out = spk_serial_out, + .send_xchar = spk_serial_send_xchar, + .tiocmset = spk_serial_tiocmset, +}; +EXPORT_SYMBOL_GPL(spk_serial_io_ops); + const struct old_serial_port *spk_serial_init(int index) { int baud = 9600, quot = 0; @@ -97,8 +109,7 @@ static irqreturn_t synth_readbuf_handler(int irq, void *dev_id) spin_lock_irqsave(&speakup_info.spinlock, flags); while (inb_p(speakup_info.port_tts + UART_LSR) & UART_LSR_DR) { - - c = inb_p(speakup_info.port_tts+UART_RX); + c = inb_p(speakup_info.port_tts + UART_RX); synth->read_buff_add((u_char)c); } spin_unlock_irqrestore(&speakup_info.spinlock, flags); @@ -119,17 +130,64 @@ static void start_serial_interrupt(int irq) pr_err("Unable to request Speakup serial I R Q\n"); /* Set MCR */ outb(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2, - speakup_info.port_tts + UART_MCR); + speakup_info.port_tts + UART_MCR); /* Turn on Interrupts */ outb(UART_IER_MSI|UART_IER_RLSI|UART_IER_RDI, speakup_info.port_tts + UART_IER); - inb(speakup_info.port_tts+UART_LSR); - inb(speakup_info.port_tts+UART_RX); - inb(speakup_info.port_tts+UART_IIR); - inb(speakup_info.port_tts+UART_MSR); + inb(speakup_info.port_tts + UART_LSR); + inb(speakup_info.port_tts + UART_RX); + inb(speakup_info.port_tts + UART_IIR); + inb(speakup_info.port_tts + UART_MSR); outb(1, speakup_info.port_tts + UART_FCR); /* Turn FIFO On */ } +static void spk_serial_send_xchar(char ch) +{ + int timeout = SPK_XMITR_TIMEOUT; + + while (spk_serial_tx_busy()) { + if (!--timeout) + break; + udelay(1); + } + outb(ch, speakup_info.port_tts); +} + +static void spk_serial_tiocmset(unsigned int set, unsigned int clear) +{ + int old = inb(speakup_info.port_tts + UART_MCR); + outb((old & ~clear) | set, speakup_info.port_tts + UART_MCR); +} + +int spk_serial_synth_probe(struct spk_synth *synth) +{ + const struct old_serial_port *ser; + int failed = 0; + + if ((synth->ser >= SPK_LO_TTY) && (synth->ser <= SPK_HI_TTY)) { + ser = spk_serial_init(synth->ser); + if (!ser) { + failed = -1; + } else { + outb_p(0, ser->port); + mdelay(1); + outb_p('\r', ser->port); + } + } else { + failed = -1; + pr_warn("ttyS%i is an invalid port\n", synth->ser); + } + if (failed) { + pr_info("%s: not found\n", synth->long_name); + return -ENODEV; + } + pr_info("%s: ttyS%i, Driver Version %s\n", + synth->long_name, synth->ser, synth->version); + synth->alive = 1; + return 0; +} +EXPORT_SYMBOL_GPL(spk_serial_synth_probe); + void spk_stop_serial_interrupt(void) { if (speakup_info.port_tts == 0) @@ -139,19 +197,20 @@ void spk_stop_serial_interrupt(void) return; /* Turn off interrupts */ - outb(0, speakup_info.port_tts+UART_IER); + outb(0, speakup_info.port_tts + UART_IER); /* Free IRQ */ free_irq(serstate->irq, (void *)synth_readbuf_handler); } +EXPORT_SYMBOL_GPL(spk_stop_serial_interrupt); -int spk_wait_for_xmitr(void) +int spk_wait_for_xmitr(struct spk_synth *in_synth) { int tmout = SPK_XMITR_TIMEOUT; - if ((synth->alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { + if ((in_synth->alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { pr_warn("%s: too many timeouts, deactivating speakup\n", - synth->long_name); - synth->alive = 0; + in_synth->long_name); + in_synth->alive = 0; /* No synth any more, so nobody will restart TTYs, and we thus * need to do it ourselves. Now that there is no synth we can * let application flood anyway @@ -162,7 +221,7 @@ int spk_wait_for_xmitr(void) } while (spk_serial_tx_busy()) { if (--tmout == 0) { - pr_warn("%s: timed out (tx busy)\n", synth->long_name); + pr_warn("%s: timed out (tx busy)\n", in_synth->long_name); timeouts++; return 0; } @@ -207,18 +266,35 @@ unsigned char spk_serial_in_nowait(void) } EXPORT_SYMBOL_GPL(spk_serial_in_nowait); -int spk_serial_out(const char ch) +static int spk_serial_out(struct spk_synth *in_synth, const char ch) { - if (synth->alive && spk_wait_for_xmitr()) { + if (in_synth->alive && spk_wait_for_xmitr(in_synth)) { outb_p(ch, speakup_info.port_tts); return 1; } return 0; } -EXPORT_SYMBOL_GPL(spk_serial_out); + +const char *spk_serial_synth_immediate(struct spk_synth *synth, const char *buff) +{ + u_char ch; + + while ((ch = *buff)) { + if (ch == '\n') + ch = synth->procspeech; + if (spk_wait_for_xmitr(synth)) + outb(ch, speakup_info.port_tts); + else + return buff; + buff++; + } + return NULL; +} +EXPORT_SYMBOL_GPL(spk_serial_synth_immediate); void spk_serial_release(void) { + spk_stop_serial_interrupt(); if (speakup_info.port_tts == 0) return; synth_release_region(speakup_info.port_tts, 8); diff --git a/drivers/staging/speakup/speakup.h b/drivers/staging/speakup/speakup.h index b203f0f..a654334 100644 --- a/drivers/staging/speakup/speakup.h +++ b/drivers/staging/speakup/speakup.h @@ -20,7 +20,7 @@ #define A_CAP 0x0007 #define B_NUM 0x0008 #define NUM 0x0009 -#define ALPHANUM (B_ALPHA|B_NUM) +#define ALPHANUM (B_ALPHA | B_NUM) #define SOME 0x0010 #define MOST 0x0020 #define PUNC 0x0040 @@ -30,13 +30,14 @@ #define B_EXNUM 0x0100 #define CH_RPT 0x0200 #define B_CTL 0x0400 -#define A_CTL (B_CTL+SYNTH_OK) +#define A_CTL (B_CTL + SYNTH_OK) #define B_SYM 0x0800 -#define B_CAPSYM (B_CAP|B_SYM) +#define B_CAPSYM (B_CAP | B_SYM) -#define IS_WDLM(x) (spk_chartab[((u_char)x)]&B_WDLM) -#define IS_CHAR(x, type) (spk_chartab[((u_char)x)]&type) -#define IS_TYPE(x, type) ((spk_chartab[((u_char)x)]&type) == type) +/* FIXME: u16 */ +#define IS_WDLM(x) (spk_chartab[((u_char)x)] & B_WDLM) +#define IS_CHAR(x, type) (spk_chartab[((u_char)x)] & type) +#define IS_TYPE(x, type) ((spk_chartab[((u_char)x)] & type) == type) int speakup_thread(void *data); void spk_reset_default_chars(void); @@ -66,7 +67,7 @@ void synth_release(void); void spk_do_flush(void); void speakup_start_ttys(void); -void synth_buffer_add(char ch); +void synth_buffer_add(u16 ch); void synth_buffer_clear(void); void speakup_clear_selection(void); int speakup_set_selection(struct tty_struct *tty); diff --git a/drivers/staging/speakup/speakup_acntpc.c b/drivers/staging/speakup/speakup_acntpc.c index c7fab26..ad72f8e 100644 --- a/drivers/staging/speakup/speakup_acntpc.c +++ b/drivers/staging/speakup/speakup_acntpc.c @@ -113,6 +113,7 @@ static struct spk_synth synth_acntpc = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = synth_probe, .release = accent_release, .synth_immediate = synth_immediate, @@ -196,6 +197,7 @@ static void do_catch_up(struct spk_synth *synth) synth->flush(synth); continue; } + synth_buffer_skip_nonlatin1(); if (synth_buffer_empty()) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); break; @@ -233,7 +235,7 @@ static void do_catch_up(struct spk_synth *synth) delay_time_val = delay_time->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); schedule_timeout(msecs_to_jiffies(delay_time_val)); - jiff_max = jiffies+jiffy_delta_val; + jiff_max = jiffies + jiffy_delta_val; } } timeout = SPK_XMITR_TIMEOUT; @@ -259,18 +261,18 @@ static int synth_probe(struct spk_synth *synth) if (port_forced) { speakup_info.port_tts = port_forced; pr_info("probe forced to %x by kernel command line\n", - speakup_info.port_tts); - if (synth_request_region(speakup_info.port_tts-1, - SYNTH_IO_EXTENT)) { + speakup_info.port_tts); + if (synth_request_region(speakup_info.port_tts - 1, + SYNTH_IO_EXTENT)) { pr_warn("sorry, port already reserved\n"); return -EBUSY; } - port_val = inw(speakup_info.port_tts-1); - synth_port_control = speakup_info.port_tts-1; + port_val = inw(speakup_info.port_tts - 1); + synth_port_control = speakup_info.port_tts - 1; } else { for (i = 0; synth_portlist[i]; i++) { if (synth_request_region(synth_portlist[i], - SYNTH_IO_EXTENT)) { + SYNTH_IO_EXTENT)) { pr_warn ("request_region: failed with 0x%x, %d\n", synth_portlist[i], SYNTH_IO_EXTENT); @@ -280,7 +282,7 @@ static int synth_probe(struct spk_synth *synth) if (port_val == 0x53fc) { /* 'S' and out&input bits */ synth_port_control = synth_portlist[i]; - speakup_info.port_tts = synth_port_control+1; + speakup_info.port_tts = synth_port_control + 1; break; } } @@ -294,7 +296,7 @@ static int synth_probe(struct spk_synth *synth) return -ENODEV; } pr_info("%s: %03x-%03x, driver version %s,\n", synth->long_name, - synth_port_control, synth_port_control+SYNTH_IO_EXTENT-1, + synth_port_control, synth_port_control + SYNTH_IO_EXTENT - 1, synth->version); synth->alive = 1; return 0; @@ -302,6 +304,7 @@ static int synth_probe(struct spk_synth *synth) static void accent_release(void) { + spk_stop_serial_interrupt(); if (speakup_info.port_tts) synth_release_region(speakup_info.port_tts-1, SYNTH_IO_EXTENT); speakup_info.port_tts = 0; diff --git a/drivers/staging/speakup/speakup_acntsa.c b/drivers/staging/speakup/speakup_acntsa.c index b2e3527..de67ffd 100644 --- a/drivers/staging/speakup/speakup_acntsa.c +++ b/drivers/staging/speakup/speakup_acntsa.c @@ -99,9 +99,10 @@ static struct spk_synth synth_acntsa = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = synth_probe, .release = spk_serial_release, - .synth_immediate = spk_synth_immediate, + .synth_immediate = spk_serial_synth_immediate, .catch_up = spk_do_catch_up, .flush = spk_synth_flush, .is_alive = spk_synth_is_alive_restart, @@ -126,7 +127,7 @@ static int synth_probe(struct spk_synth *synth) failed = spk_serial_synth_probe(synth); if (failed == 0) { - spk_synth_immediate(synth, "\033=R\r"); + synth->synth_immediate(synth, "\033=R\r"); mdelay(100); } synth->alive = !failed; diff --git a/drivers/staging/speakup/speakup_apollo.c b/drivers/staging/speakup/speakup_apollo.c index 3f43f81..cead8b1 100644 --- a/drivers/staging/speakup/speakup_apollo.c +++ b/drivers/staging/speakup/speakup_apollo.c @@ -108,9 +108,10 @@ static struct spk_synth synth_apollo = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = spk_serial_synth_probe, .release = spk_serial_release, - .synth_immediate = spk_synth_immediate, + .synth_immediate = spk_serial_synth_immediate, .catch_up = do_catch_up, .flush = spk_synth_flush, .is_alive = spk_synth_is_alive_restart, @@ -160,6 +161,7 @@ static void do_catch_up(struct spk_synth *synth) synth->flush(synth); continue; } + synth_buffer_skip_nonlatin1(); if (synth_buffer_empty()) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); break; @@ -168,10 +170,9 @@ static void do_catch_up(struct spk_synth *synth) set_current_state(TASK_INTERRUPTIBLE); full_time_val = full_time->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); - if (!spk_serial_out(ch)) { - outb(UART_MCR_DTR, speakup_info.port_tts + UART_MCR); - outb(UART_MCR_DTR | UART_MCR_RTS, - speakup_info.port_tts + UART_MCR); + if (!synth->io_ops->synth_out(synth, ch)) { + synth->io_ops->tiocmset(0, UART_MCR_RTS); + synth->io_ops->tiocmset(UART_MCR_RTS, 0); schedule_timeout(msecs_to_jiffies(full_time_val)); continue; } @@ -181,7 +182,7 @@ static void do_catch_up(struct spk_synth *synth) full_time_val = full_time->u.n.value; delay_time_val = delay_time->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); - if (spk_serial_out(synth->procspeech)) + if (synth->io_ops->synth_out(synth, synth->procspeech)) schedule_timeout(msecs_to_jiffies (delay_time_val)); else @@ -194,7 +195,7 @@ static void do_catch_up(struct spk_synth *synth) synth_buffer_getc(); spin_unlock_irqrestore(&speakup_info.spinlock, flags); } - spk_serial_out(PROCSPEECH); + synth->io_ops->synth_out(synth, PROCSPEECH); } module_param_named(ser, synth_apollo.ser, int, 0444); diff --git a/drivers/staging/speakup/speakup_audptr.c b/drivers/staging/speakup/speakup_audptr.c index e696b87..6880352 100644 --- a/drivers/staging/speakup/speakup_audptr.c +++ b/drivers/staging/speakup/speakup_audptr.c @@ -104,9 +104,10 @@ static struct spk_synth synth_audptr = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = synth_probe, .release = spk_serial_release, - .synth_immediate = spk_synth_immediate, + .synth_immediate = spk_serial_synth_immediate, .catch_up = spk_do_catch_up, .flush = synth_flush, .is_alive = spk_synth_is_alive_restart, @@ -127,15 +128,8 @@ static struct spk_synth synth_audptr = { static void synth_flush(struct spk_synth *synth) { - int timeout = SPK_XMITR_TIMEOUT; - - while (spk_serial_tx_busy()) { - if (!--timeout) - break; - udelay(1); - } - outb(SYNTH_CLEAR, speakup_info.port_tts); - spk_serial_out(PROCSPEECH); + synth->io_ops->send_xchar(SYNTH_CLEAR); + synth->io_ops->synth_out(synth, PROCSPEECH); } static void synth_version(struct spk_synth *synth) @@ -143,7 +137,7 @@ static void synth_version(struct spk_synth *synth) unsigned char test = 0; char synth_id[40] = ""; - spk_synth_immediate(synth, "\x05[Q]"); + synth->synth_immediate(synth, "\x05[Q]"); synth_id[test] = spk_serial_in(); if (synth_id[test] == 'A') { do { diff --git a/drivers/staging/speakup/speakup_bns.c b/drivers/staging/speakup/speakup_bns.c index da158c9..a972a51 100644 --- a/drivers/staging/speakup/speakup_bns.c +++ b/drivers/staging/speakup/speakup_bns.c @@ -96,9 +96,10 @@ static struct spk_synth synth_bns = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = spk_serial_synth_probe, .release = spk_serial_release, - .synth_immediate = spk_synth_immediate, + .synth_immediate = spk_serial_synth_immediate, .catch_up = spk_do_catch_up, .flush = spk_synth_flush, .is_alive = spk_synth_is_alive_restart, diff --git a/drivers/staging/speakup/speakup_decext.c b/drivers/staging/speakup/speakup_decext.c index 6b74a97..c564bf8 100644 --- a/drivers/staging/speakup/speakup_decext.c +++ b/drivers/staging/speakup/speakup_decext.c @@ -127,9 +127,10 @@ static struct spk_synth synth_decext = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = spk_serial_synth_probe, .release = spk_serial_release, - .synth_immediate = spk_synth_immediate, + .synth_immediate = spk_serial_synth_immediate, .catch_up = do_catch_up, .flush = synth_flush, .is_alive = spk_synth_is_alive_restart, @@ -175,6 +176,7 @@ static void do_catch_up(struct spk_synth *synth) synth->flush(synth); continue; } + synth_buffer_skip_nonlatin1(); if (synth_buffer_empty()) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); break; @@ -185,7 +187,7 @@ static void do_catch_up(struct spk_synth *synth) spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (ch == '\n') ch = 0x0D; - if (synth_full() || !spk_serial_out(ch)) { + if (synth_full() || !synth->io_ops->synth_out(synth, ch)) { schedule_timeout(msecs_to_jiffies(delay_time_val)); continue; } @@ -193,22 +195,22 @@ static void do_catch_up(struct spk_synth *synth) spin_lock_irqsave(&speakup_info.spinlock, flags); synth_buffer_getc(); spin_unlock_irqrestore(&speakup_info.spinlock, flags); - if (ch == '[') + if (ch == '[') { in_escape = 1; - else if (ch == ']') + } else if (ch == ']') { in_escape = 0; - else if (ch <= SPACE) { + } else if (ch <= SPACE) { if (!in_escape && strchr(",.!?;:", last)) - spk_serial_out(PROCSPEECH); + synth->io_ops->synth_out(synth, PROCSPEECH); if (time_after_eq(jiffies, jiff_max)) { if (!in_escape) - spk_serial_out(PROCSPEECH); + synth->io_ops->synth_out(synth, PROCSPEECH); spin_lock_irqsave(&speakup_info.spinlock, - flags); + flags); jiffy_delta_val = jiffy_delta->u.n.value; delay_time_val = delay_time->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, - flags); + flags); schedule_timeout(msecs_to_jiffies (delay_time_val)); jiff_max = jiffies + jiffy_delta_val; @@ -217,13 +219,13 @@ static void do_catch_up(struct spk_synth *synth) last = ch; } if (!in_escape) - spk_serial_out(PROCSPEECH); + synth->io_ops->synth_out(synth, PROCSPEECH); } static void synth_flush(struct spk_synth *synth) { in_escape = 0; - spk_synth_immediate(synth, "\033P;10z\033\\"); + synth->synth_immediate(synth, "\033P;10z\033\\"); } module_param_named(ser, synth_decext.ser, int, 0444); diff --git a/drivers/staging/speakup/speakup_decpc.c b/drivers/staging/speakup/speakup_decpc.c index 6bf38e4..5d22c3b 100644 --- a/drivers/staging/speakup/speakup_decpc.c +++ b/drivers/staging/speakup/speakup_decpc.c @@ -33,15 +33,15 @@ #include "spk_priv.h" #include "speakup.h" -#define MODULE_init 0x0dec /* module in boot code */ -#define MODULE_self_test 0x8800 /* module in self-test */ -#define MODULE_reset 0xffff /* reinit the whole module */ +#define MODULE_init 0x0dec /* module in boot code */ +#define MODULE_self_test 0x8800 /* module in self-test */ +#define MODULE_reset 0xffff /* reinit the whole module */ -#define MODE_mask 0xf000 /* mode bits in high nibble */ +#define MODE_mask 0xf000 /* mode bits in high nibble */ #define MODE_null 0x0000 -#define MODE_test 0x2000 /* in testing mode */ +#define MODE_test 0x2000 /* in testing mode */ #define MODE_status 0x8000 -#define STAT_int 0x0001 /* running in interrupt mode */ +#define STAT_int 0x0001 /* running in interrupt mode */ #define STAT_tr_char 0x0002 /* character data to transmit */ #define STAT_rr_char 0x0004 /* ready to receive char data */ #define STAT_cmd_ready 0x0008 /* ready to accept commands */ @@ -61,33 +61,31 @@ #define CMD_mask 0xf000 /* mask for command nibble */ #define CMD_null 0x0000 /* post status */ #define CMD_control 0x1000 /* hard control command */ -#define CTRL_mask 0x0F00 /* mask off control nibble */ -#define CTRL_data 0x00FF /* mask to get data byte */ -#define CTRL_null 0x0000 /* null control */ -#define CTRL_vol_up 0x0100 /* increase volume */ -#define CTRL_vol_down 0x0200 /* decrease volume */ -#define CTRL_vol_set 0x0300 /* set volume */ -#define CTRL_pause 0x0400 /* pause spc */ -#define CTRL_resume 0x0500 /* resume spc clock */ -#define CTRL_resume_spc 0x0001 /* resume spc soft pause */ -#define CTRL_flush 0x0600 /* flush all buffers */ -#define CTRL_int_enable 0x0700 /* enable status change ints */ -#define CTRL_buff_free 0x0800 /* buffer remain count */ -#define CTRL_buff_used 0x0900 /* buffer in use */ -#define CTRL_speech 0x0a00 /* immediate speech change */ -#define CTRL_SP_voice 0x0001 /* voice change */ -#define CTRL_SP_rate 0x0002 /* rate change */ -#define CTRL_SP_comma 0x0003 /* comma pause change */ -#define CTRL_SP_period 0x0004 /* period pause change */ -#define CTRL_SP_rate_delta 0x0005 /* delta rate change */ -#define CTRL_SP_get_param 0x0006 /* return the desired parameter */ -#define CTRL_last_index 0x0b00 /* get last index spoken */ -#define CTRL_io_priority 0x0c00 /* change i/o priority */ -#define CTRL_free_mem 0x0d00 /* get free paragraphs on module */ -#define CTRL_get_lang 0x0e00 /* return bit mask of loaded - * languages - */ -#define CMD_test 0x2000 /* self-test request */ +#define CTRL_mask 0x0F00 /* mask off control nibble */ +#define CTRL_data 0x00FF /* mask to get data byte */ +#define CTRL_null 0x0000 /* null control */ +#define CTRL_vol_up 0x0100 /* increase volume */ +#define CTRL_vol_down 0x0200 /* decrease volume */ +#define CTRL_vol_set 0x0300 /* set volume */ +#define CTRL_pause 0x0400 /* pause spc */ +#define CTRL_resume 0x0500 /* resume spc clock */ +#define CTRL_resume_spc 0x0001 /* resume spc soft pause */ +#define CTRL_flush 0x0600 /* flush all buffers */ +#define CTRL_int_enable 0x0700 /* enable status change ints */ +#define CTRL_buff_free 0x0800 /* buffer remain count */ +#define CTRL_buff_used 0x0900 /* buffer in use */ +#define CTRL_speech 0x0a00 /* immediate speech change */ +#define CTRL_SP_voice 0x0001 /* voice change */ +#define CTRL_SP_rate 0x0002 /* rate change */ +#define CTRL_SP_comma 0x0003 /* comma pause change */ +#define CTRL_SP_period 0x0004 /* period pause change */ +#define CTRL_SP_rate_delta 0x0005 /* delta rate change */ +#define CTRL_SP_get_param 0x0006 /* return the desired parameter */ +#define CTRL_last_index 0x0b00 /* get last index spoken */ +#define CTRL_io_priority 0x0c00 /* change i/o priority */ +#define CTRL_free_mem 0x0d00 /* get free paragraphs on module */ +#define CTRL_get_lang 0x0e00 /* return bit mask of loaded languages */ +#define CMD_test 0x2000 /* self-test request */ #define TEST_mask 0x0F00 /* isolate test field */ #define TEST_null 0x0000 /* no test requested */ #define TEST_isa_int 0x0100 /* assert isa irq */ @@ -101,19 +99,19 @@ #define ID_null 0x0000 /* null id */ #define ID_kernel 0x0100 /* kernel code executing */ #define ID_boot 0x0200 /* boot code executing */ -#define CMD_dma 0x4000 /* force a dma start */ -#define CMD_reset 0x5000 /* reset module status */ -#define CMD_sync 0x6000 /* kernel sync command */ -#define CMD_char_in 0x7000 /* single character send */ -#define CMD_char_out 0x8000 /* single character get */ -#define CHAR_count_1 0x0100 /* one char in cmd_low */ -#define CHAR_count_2 0x0200 /* the second in data_low */ -#define CHAR_count_3 0x0300 /* the third in data_high */ -#define CMD_spc_mode 0x9000 /* change spc mode */ -#define CMD_spc_to_text 0x0100 /* set to text mode */ -#define CMD_spc_to_digit 0x0200 /* set to digital mode */ -#define CMD_spc_rate 0x0400 /* change spc data rate */ -#define CMD_error 0xf000 /* severe error */ +#define CMD_dma 0x4000 /* force a dma start */ +#define CMD_reset 0x5000 /* reset module status */ +#define CMD_sync 0x6000 /* kernel sync command */ +#define CMD_char_in 0x7000 /* single character send */ +#define CMD_char_out 0x8000 /* single character get */ +#define CHAR_count_1 0x0100 /* one char in cmd_low */ +#define CHAR_count_2 0x0200 /* the second in data_low */ +#define CHAR_count_3 0x0300 /* the third in data_high */ +#define CMD_spc_mode 0x9000 /* change spc mode */ +#define CMD_spc_to_text 0x0100 /* set to text mode */ +#define CMD_spc_to_digit 0x0200 /* set to digital mode */ +#define CMD_spc_rate 0x0400 /* change spc data rate */ +#define CMD_error 0xf000 /* severe error */ enum { PRIMARY_DIC = 0, USER_DIC, COMMAND_DIC, ABBREV_DIC }; @@ -220,6 +218,7 @@ static struct spk_synth synth_dec_pc = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = synth_probe, .release = dtpc_release, .synth_immediate = synth_immediate, @@ -251,7 +250,7 @@ static int dt_getstatus(void) static void dt_sendcmd(u_int cmd) { outb_p(cmd & 0xFF, speakup_info.port_tts); - outb_p((cmd >> 8) & 0xFF, speakup_info.port_tts+1); + outb_p((cmd >> 8) & 0xFF, speakup_info.port_tts + 1); } static int dt_waitbit(int bit) @@ -287,11 +286,11 @@ static int dt_ctrl(u_int cmd) if (!dt_waitbit(STAT_cmd_ready)) return -1; - outb_p(0, speakup_info.port_tts+2); - outb_p(0, speakup_info.port_tts+3); + outb_p(0, speakup_info.port_tts + 2); + outb_p(0, speakup_info.port_tts + 3); dt_getstatus(); - dt_sendcmd(CMD_control|cmd); - outb_p(0, speakup_info.port_tts+6); + dt_sendcmd(CMD_control | cmd); + outb_p(0, speakup_info.port_tts + 6); while (dt_getstatus() & STAT_cmd_ready) { udelay(20); if (--timeout == 0) @@ -319,8 +318,8 @@ udelay(50); break; udelay(50); } - outb_p(DMA_sync, speakup_info.port_tts+4); - outb_p(0, speakup_info.port_tts+4); + outb_p(DMA_sync, speakup_info.port_tts + 4); + outb_p(0, speakup_info.port_tts + 4); udelay(100); for (timeout = 0; timeout < 10; timeout++) { if (!(dt_getstatus() & STAT_flushing)) @@ -338,8 +337,8 @@ static int dt_sendchar(char ch) return -1; if (!(dt_stat & STAT_rr_char)) return -2; - outb_p(DMA_single_in, speakup_info.port_tts+4); - outb_p(ch, speakup_info.port_tts+4); + outb_p(DMA_single_in, speakup_info.port_tts + 4); + outb_p(ch, speakup_info.port_tts + 4); dma_state ^= STAT_dma_state; return 0; } @@ -355,7 +354,7 @@ static int testkernel(void) dt_sendcmd(CMD_sync); if (!dt_waitbit(STAT_cmd_ready)) status = -2; - else if (dt_stat&0x8000) + else if (dt_stat & 0x8000) return 0; else if (dt_stat == 0x0dec) pr_warn("dec_pc at 0x%x, software not loaded\n", @@ -392,6 +391,7 @@ static void do_catch_up(struct spk_synth *synth) synth->flush(synth); continue; } + synth_buffer_skip_nonlatin1(); if (synth_buffer_empty()) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); break; @@ -410,11 +410,11 @@ static void do_catch_up(struct spk_synth *synth) spin_lock_irqsave(&speakup_info.spinlock, flags); synth_buffer_getc(); spin_unlock_irqrestore(&speakup_info.spinlock, flags); - if (ch == '[') + if (ch == '[') { in_escape = 1; - else if (ch == ']') + } else if (ch == ']') { in_escape = 0; - else if (ch <= SPACE) { + } else if (ch <= SPACE) { if (!in_escape && strchr(",.!?;:", last)) dt_sendchar(PROCSPEECH); if (time_after_eq(jiffies, jiff_max)) { @@ -481,6 +481,7 @@ static int synth_probe(struct spk_synth *synth) static void dtpc_release(void) { + spk_stop_serial_interrupt(); if (speakup_info.port_tts) synth_release_region(speakup_info.port_tts, SYNTH_IO_EXTENT); speakup_info.port_tts = 0; diff --git a/drivers/staging/speakup/speakup_dectlk.c b/drivers/staging/speakup/speakup_dectlk.c index 2603605..0cdbd5e 100644 --- a/drivers/staging/speakup/speakup_dectlk.c +++ b/drivers/staging/speakup/speakup_dectlk.c @@ -130,9 +130,10 @@ static struct spk_synth synth_dectlk = { .vars = vars, .default_pitch = ap_defaults, .default_vol = g5_defaults, + .io_ops = &spk_serial_io_ops, .probe = spk_serial_synth_probe, .release = spk_serial_release, - .synth_immediate = spk_synth_immediate, + .synth_immediate = spk_serial_synth_immediate, .catch_up = do_catch_up, .flush = synth_flush, .is_alive = spk_synth_is_alive_restart, @@ -239,6 +240,7 @@ static void do_catch_up(struct spk_synth *synth) synth->flush(synth); continue; } + synth_buffer_skip_nonlatin1(); if (synth_buffer_empty()) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); break; @@ -250,7 +252,7 @@ static void do_catch_up(struct spk_synth *synth) spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (ch == '\n') ch = 0x0D; - if (synth_full_val || !spk_serial_out(ch)) { + if (synth_full_val || !synth->io_ops->synth_out(synth, ch)) { schedule_timeout(msecs_to_jiffies(delay_time_val)); continue; } @@ -258,16 +260,16 @@ static void do_catch_up(struct spk_synth *synth) spin_lock_irqsave(&speakup_info.spinlock, flags); synth_buffer_getc(); spin_unlock_irqrestore(&speakup_info.spinlock, flags); - if (ch == '[') + if (ch == '[') { in_escape = 1; - else if (ch == ']') + } else if (ch == ']') { in_escape = 0; - else if (ch <= SPACE) { + } else if (ch <= SPACE) { if (!in_escape && strchr(",.!?;:", last)) - spk_serial_out(PROCSPEECH); + synth->io_ops->synth_out(synth, PROCSPEECH); if (time_after_eq(jiffies, jiff_max)) { if (!in_escape) - spk_serial_out(PROCSPEECH); + synth->io_ops->synth_out(synth, PROCSPEECH); spin_lock_irqsave(&speakup_info.spinlock, flags); jiffy_delta_val = jiffy_delta->u.n.value; @@ -282,17 +284,17 @@ static void do_catch_up(struct spk_synth *synth) last = ch; } if (!in_escape) - spk_serial_out(PROCSPEECH); + synth->io_ops->synth_out(synth, PROCSPEECH); } static void synth_flush(struct spk_synth *synth) { if (in_escape) /* if in command output ']' so we don't get an error */ - spk_serial_out(']'); + synth->io_ops->synth_out(synth, ']'); in_escape = 0; is_flushing = 1; - spk_serial_out(SYNTH_CLEAR); + synth->io_ops->synth_out(synth, SYNTH_CLEAR); } module_param_named(ser, synth_dectlk.ser, int, 0444); diff --git a/drivers/staging/speakup/speakup_dtlk.c b/drivers/staging/speakup/speakup_dtlk.c index e2bf2080..5973acc 100644 --- a/drivers/staging/speakup/speakup_dtlk.c +++ b/drivers/staging/speakup/speakup_dtlk.c @@ -43,6 +43,7 @@ static int port_forced; static unsigned int synth_portlist[] = { 0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0 }; + static u_char synth_status; static struct var_t vars[] = { @@ -128,6 +129,7 @@ static struct spk_synth synth_dtlk = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = synth_probe, .release = dtlk_release, .synth_immediate = synth_immediate, @@ -209,6 +211,7 @@ static void do_catch_up(struct spk_synth *synth) synth->flush(synth); continue; } + synth_buffer_skip_nonlatin1(); if (synth_buffer_empty()) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); break; @@ -297,7 +300,7 @@ static struct synth_settings *synth_interrogate(struct spk_synth *synth) t += 2; for (i = 0; *t != '\r'; t++) { status.rom_version[i] = *t; - if (i < sizeof(status.rom_version)-1) + if (i < sizeof(status.rom_version) - 1) i++; } status.rom_version[i] = 0; @@ -373,6 +376,7 @@ static int synth_probe(struct spk_synth *synth) static void dtlk_release(void) { + spk_stop_serial_interrupt(); if (speakup_info.port_tts) synth_release_region(speakup_info.port_tts-1, SYNTH_IO_EXTENT); speakup_info.port_tts = 0; diff --git a/drivers/staging/speakup/speakup_dtlk.h b/drivers/staging/speakup/speakup_dtlk.h index b3b3cfc..46d885f 100644 --- a/drivers/staging/speakup/speakup_dtlk.h +++ b/drivers/staging/speakup/speakup_dtlk.h @@ -24,11 +24,11 @@ * usec later. */ #define TTS_ALMOST_FULL 0x08 /* mask for AF bit: When set to 1, - * indicates that less than 300 bytes - * are available in the TTS input - * buffer. AF is always 0 in the PCM, - * TGN and CVSD modes. - */ + * indicates that less than 300 bytes + * are available in the TTS input + * buffer. AF is always 0 in the PCM, + * TGN and CVSD modes. + */ #define TTS_ALMOST_EMPTY 0x04 /* mask for AE bit: When set to 1, * indicates that less than 300 bytes * are remaining in DoubleTalk's input diff --git a/drivers/staging/speakup/speakup_dummy.c b/drivers/staging/speakup/speakup_dummy.c index cb7cef3..8db7aa3 100644 --- a/drivers/staging/speakup/speakup_dummy.c +++ b/drivers/staging/speakup/speakup_dummy.c @@ -98,9 +98,10 @@ static struct spk_synth synth_dummy = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = spk_serial_synth_probe, .release = spk_serial_release, - .synth_immediate = spk_synth_immediate, + .synth_immediate = spk_serial_synth_immediate, .catch_up = spk_do_catch_up, .flush = spk_synth_flush, .is_alive = spk_synth_is_alive_restart, diff --git a/drivers/staging/speakup/speakup_keypc.c b/drivers/staging/speakup/speakup_keypc.c index 10f4964..ba79011 100644 --- a/drivers/staging/speakup/speakup_keypc.c +++ b/drivers/staging/speakup/speakup_keypc.c @@ -105,6 +105,7 @@ static struct spk_synth synth_keypc = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = synth_probe, .release = keynote_release, .synth_immediate = synth_immediate, @@ -141,9 +142,9 @@ static char *oops(void) int s1, s2, s3, s4; s1 = inb_p(synth_port); - s2 = inb_p(synth_port+1); - s3 = inb_p(synth_port+2); - s4 = inb_p(synth_port+3); + s2 = inb_p(synth_port + 1); + s3 = inb_p(synth_port + 2); + s4 = inb_p(synth_port + 3); pr_warn("synth timeout %d %d %d %d\n", s1, s2, s3, s4); return NULL; } @@ -198,6 +199,7 @@ spin_lock_irqsave(&speakup_info.spinlock, flags); synth->flush(synth); continue; } + synth_buffer_skip_nonlatin1(); if (synth_buffer_empty()) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); break; @@ -304,6 +306,7 @@ static int synth_probe(struct spk_synth *synth) static void keynote_release(void) { + spk_stop_serial_interrupt(); if (synth_port) synth_release_region(synth_port, SYNTH_IO_EXTENT); synth_port = 0; diff --git a/drivers/staging/speakup/speakup_ltlk.c b/drivers/staging/speakup/speakup_ltlk.c index 9d22198..11275f4 100644 --- a/drivers/staging/speakup/speakup_ltlk.c +++ b/drivers/staging/speakup/speakup_ltlk.c @@ -111,9 +111,10 @@ static struct spk_synth synth_ltlk = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = synth_probe, .release = spk_serial_release, - .synth_immediate = spk_synth_immediate, + .synth_immediate = spk_serial_synth_immediate, .catch_up = spk_do_catch_up, .flush = spk_synth_flush, .is_alive = spk_synth_is_alive_restart, @@ -138,13 +139,13 @@ static void synth_interrogate(struct spk_synth *synth) unsigned char *t, i; unsigned char buf[50], rom_v[20]; - spk_synth_immediate(synth, "\x18\x01?"); + synth->synth_immediate(synth, "\x18\x01?"); for (i = 0; i < 50; i++) { buf[i] = spk_serial_in(); if (i > 2 && buf[i] == 0x7f) break; } - t = buf+2; + t = buf + 2; for (i = 0; *t != '\r'; t++) { rom_v[i] = *t; if (++i >= 19) diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c index d2ff0af..e454f56 100644 --- a/drivers/staging/speakup/speakup_soft.c +++ b/drivers/staging/speakup/speakup_soft.c @@ -29,6 +29,7 @@ #define DRV_VERSION "2.6" #define SOFTSYNTH_MINOR 26 /* might as well give it one more than /dev/synth */ +#define SOFTSYNTHU_MINOR 27 /* might as well give it one more than /dev/synth */ #define PROCSPEECH 0x0d #define CLEAR_SYNTH 0x18 @@ -37,7 +38,7 @@ static void softsynth_release(void); static int softsynth_is_alive(struct spk_synth *synth); static unsigned char get_index(void); -static struct miscdevice synth_device; +static struct miscdevice synth_device, synthu_device; static int init_pos; static int misc_registered; @@ -130,6 +131,7 @@ static struct spk_synth synth_soft = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = NULL, .probe = softsynth_probe, .release = softsynth_release, .synth_immediate = NULL, @@ -199,13 +201,13 @@ static int softsynth_close(struct inode *inode, struct file *fp) return 0; } -static ssize_t softsynth_read(struct file *fp, char __user *buf, size_t count, - loff_t *pos) +static ssize_t softsynthx_read(struct file *fp, char __user *buf, size_t count, + loff_t *pos, int unicode) { int chars_sent = 0; char __user *cp; char *init; - char ch; + u16 ch; int empty; unsigned long flags; DEFINE_WAIT(wait); @@ -213,6 +215,8 @@ static ssize_t softsynth_read(struct file *fp, char __user *buf, size_t count, spin_lock_irqsave(&speakup_info.spinlock, flags); while (1) { prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE); + if (!unicode) + synth_buffer_skip_nonlatin1(); if (!synth_buffer_empty() || speakup_info.flushing) break; spin_unlock_irqrestore(&speakup_info.spinlock, flags); @@ -231,23 +235,57 @@ static ssize_t softsynth_read(struct file *fp, char __user *buf, size_t count, cp = buf; init = get_initstring(); - while (chars_sent < count) { + + /* Keep 3 bytes available for a 16bit UTF-8-encoded character */ + while (chars_sent <= count - 3) { if (speakup_info.flushing) { speakup_info.flushing = 0; ch = '\x18'; - } else if (synth_buffer_empty()) { - break; } else if (init[init_pos]) { ch = init[init_pos++]; } else { + if (!unicode) + synth_buffer_skip_nonlatin1(); + if (synth_buffer_empty()) + break; ch = synth_buffer_getc(); } spin_unlock_irqrestore(&speakup_info.spinlock, flags); - if (copy_to_user(cp, &ch, 1)) - return -EFAULT; + + if ((!unicode && ch < 0x100) || (unicode && ch < 0x80)) { + u_char c = ch; + + if (copy_to_user(cp, &c, 1)) + return -EFAULT; + + chars_sent++; + cp++; + } else if (unicode && ch < 0x800) { + u_char s[2] = { + 0xc0 | (ch >> 6), + 0x80 | (ch & 0x3f) + }; + + if (copy_to_user(cp, s, sizeof(s))) + return -EFAULT; + + chars_sent += sizeof(s); + cp += sizeof(s); + } else if (unicode) { + u_char s[3] = { + 0xe0 | (ch >> 12), + 0x80 | ((ch >> 6) & 0x3f), + 0x80 | (ch & 0x3f) + }; + + if (copy_to_user(cp, s, sizeof(s))) + return -EFAULT; + + chars_sent += sizeof(s); + cp += sizeof(s); + } + spin_lock_irqsave(&speakup_info.spinlock, flags); - chars_sent++; - cp++; } *pos += chars_sent; empty = synth_buffer_empty(); @@ -259,6 +297,18 @@ static ssize_t softsynth_read(struct file *fp, char __user *buf, size_t count, return chars_sent; } +static ssize_t softsynth_read(struct file *fp, char __user *buf, size_t count, + loff_t *pos) +{ + return softsynthx_read(fp, buf, count, pos, 0); +} + +static ssize_t softsynthu_read(struct file *fp, char __user *buf, size_t count, + loff_t *pos) +{ + return softsynthx_read(fp, buf, count, pos, 1); +} + static int last_index; static ssize_t softsynth_write(struct file *fp, const char __user *buf, @@ -308,6 +358,15 @@ static const struct file_operations softsynth_fops = { .release = softsynth_close, }; +static const struct file_operations softsynthu_fops = { + .owner = THIS_MODULE, + .poll = softsynth_poll, + .read = softsynthu_read, + .write = softsynth_write, + .open = softsynth_open, + .release = softsynth_close, +}; + static int softsynth_probe(struct spk_synth *synth) { if (misc_registered != 0) @@ -321,16 +380,28 @@ static int softsynth_probe(struct spk_synth *synth) return -ENODEV; } + memset(&synthu_device, 0, sizeof(synthu_device)); + synthu_device.minor = SOFTSYNTHU_MINOR; + synthu_device.name = "softsynthu"; + synthu_device.fops = &softsynthu_fops; + if (misc_register(&synthu_device)) { + pr_warn("Couldn't initialize miscdevice /dev/softsynth.\n"); + return -ENODEV; + } + misc_registered = 1; pr_info("initialized device: /dev/softsynth, node (MAJOR 10, MINOR 26)\n"); + pr_info("initialized device: /dev/softsynthu, node (MAJOR 10, MINOR 27)\n"); return 0; } static void softsynth_release(void) { misc_deregister(&synth_device); + misc_deregister(&synthu_device); misc_registered = 0; pr_info("unregistered /dev/softsynth\n"); + pr_info("unregistered /dev/softsynthu\n"); } static int softsynth_is_alive(struct spk_synth *synth) diff --git a/drivers/staging/speakup/speakup_spkout.c b/drivers/staging/speakup/speakup_spkout.c index 143fada..d95c375 100644 --- a/drivers/staging/speakup/speakup_spkout.c +++ b/drivers/staging/speakup/speakup_spkout.c @@ -102,9 +102,10 @@ static struct spk_synth synth_spkout = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = spk_serial_synth_probe, .release = spk_serial_release, - .synth_immediate = spk_synth_immediate, + .synth_immediate = spk_serial_synth_immediate, .catch_up = spk_do_catch_up, .flush = synth_flush, .is_alive = spk_synth_is_alive_restart, @@ -125,14 +126,7 @@ static struct spk_synth synth_spkout = { static void synth_flush(struct spk_synth *synth) { - int timeout = SPK_XMITR_TIMEOUT; - - while (spk_serial_tx_busy()) { - if (!--timeout) - break; - udelay(1); - } - outb(SYNTH_CLEAR, speakup_info.port_tts); + synth->io_ops->send_xchar(SYNTH_CLEAR); } module_param_named(ser, synth_spkout.ser, int, 0444); diff --git a/drivers/staging/speakup/speakup_txprt.c b/drivers/staging/speakup/speakup_txprt.c index aa2f338..3f531fb 100644 --- a/drivers/staging/speakup/speakup_txprt.c +++ b/drivers/staging/speakup/speakup_txprt.c @@ -95,9 +95,10 @@ static struct spk_synth synth_txprt = { .startup = SYNTH_START, .checkval = SYNTH_CHECK, .vars = vars, + .io_ops = &spk_serial_io_ops, .probe = spk_serial_synth_probe, .release = spk_serial_release, - .synth_immediate = spk_synth_immediate, + .synth_immediate = spk_serial_synth_immediate, .catch_up = spk_do_catch_up, .flush = spk_synth_flush, .is_alive = spk_synth_is_alive_restart, diff --git a/drivers/staging/speakup/spk_priv.h b/drivers/staging/speakup/spk_priv.h index d5aa41d..995f586 100644 --- a/drivers/staging/speakup/spk_priv.h +++ b/drivers/staging/speakup/spk_priv.h @@ -42,14 +42,14 @@ const struct old_serial_port *spk_serial_init(int index); void spk_stop_serial_interrupt(void); -int spk_wait_for_xmitr(void); +int spk_wait_for_xmitr(struct spk_synth *in_synth); unsigned char spk_serial_in(void); unsigned char spk_serial_in_nowait(void); -int spk_serial_out(const char ch); void spk_serial_release(void); -char synth_buffer_getc(void); -char synth_buffer_peek(void); +void synth_buffer_skip_nonlatin1(void); +u16 synth_buffer_getc(void); +u16 synth_buffer_peek(void); int synth_buffer_empty(void); struct var_t *spk_get_var(enum var_id_t var_id); ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr, @@ -58,12 +58,17 @@ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count); int spk_serial_synth_probe(struct spk_synth *synth); -const char *spk_synth_immediate(struct spk_synth *synth, const char *buff); +const char *spk_serial_synth_immediate(struct spk_synth *synth, const char *buff); void spk_do_catch_up(struct spk_synth *synth); void spk_synth_flush(struct spk_synth *synth); int spk_synth_is_alive_nop(struct spk_synth *synth); int spk_synth_is_alive_restart(struct spk_synth *synth); +__printf(1, 2) void synth_printf(const char *buf, ...); +void synth_putwc(u16 wc); +void synth_putwc_s(u16 wc); +void synth_putws(const u16 *buf); +void synth_putws_s(const u16 *buf); int synth_request_region(unsigned long start, unsigned long n); int synth_release_region(unsigned long start, unsigned long n); int synth_add(struct spk_synth *in_synth); @@ -73,4 +78,6 @@ extern struct speakup_info_t speakup_info; extern struct var_t synth_time_vars[]; +extern struct spk_io_ops spk_serial_io_ops; + #endif diff --git a/drivers/staging/speakup/spk_types.h b/drivers/staging/speakup/spk_types.h index b07f6cc..c156975 100644 --- a/drivers/staging/speakup/spk_types.h +++ b/drivers/staging/speakup/spk_types.h @@ -55,7 +55,7 @@ struct spk_highlight_color_track { /* Count of each background color */ unsigned int bgcount[8]; /* Buffer for characters drawn with each background color */ - char highbuf[8][COLOR_BUFFER_SIZE]; + u16 highbuf[8][COLOR_BUFFER_SIZE]; /* Current index into highbuf */ unsigned int highsize[8]; /* Reading Position for each color */ @@ -146,6 +146,14 @@ struct synth_indexing { unsigned char currindex; }; +struct spk_synth; + +struct spk_io_ops { + int (*synth_out)(struct spk_synth *synth, const char ch); + void (*send_xchar)(char ch); + void (*tiocmset)(unsigned int set, unsigned int clear); +}; + struct spk_synth { const char *name; const char *version; @@ -164,6 +172,7 @@ struct spk_synth { struct var_t *vars; int *default_pitch; int *default_vol; + struct spk_io_ops *io_ops; int (*probe)(struct spk_synth *synth); void (*release)(void); const char *(*synth_immediate)(struct spk_synth *synth, diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index a61c02b..352e9ee 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c @@ -44,35 +44,6 @@ EXPORT_SYMBOL_GPL(speakup_info); static int do_synth_init(struct spk_synth *in_synth); -int spk_serial_synth_probe(struct spk_synth *synth) -{ - const struct old_serial_port *ser; - int failed = 0; - - if ((synth->ser >= SPK_LO_TTY) && (synth->ser <= SPK_HI_TTY)) { - ser = spk_serial_init(synth->ser); - if (ser == NULL) { - failed = -1; - } else { - outb_p(0, ser->port); - mdelay(1); - outb_p('\r', ser->port); - } - } else { - failed = -1; - pr_warn("ttyS%i is an invalid port\n", synth->ser); - } - if (failed) { - pr_info("%s: not found\n", synth->long_name); - return -ENODEV; - } - pr_info("%s: ttyS%i, Driver Version %s\n", - synth->long_name, synth->ser, synth->version); - synth->alive = 1; - return 0; -} -EXPORT_SYMBOL_GPL(spk_serial_synth_probe); - /* * Main loop of the progression thread: keep eating from the buffer * and push to the serial port, waiting as needed @@ -109,6 +80,7 @@ void spk_do_catch_up(struct spk_synth *synth) synth->flush(synth); continue; } + synth_buffer_skip_nonlatin1(); if (synth_buffer_empty()) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); break; @@ -119,7 +91,7 @@ void spk_do_catch_up(struct spk_synth *synth) spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (ch == '\n') ch = synth->procspeech; - if (!spk_serial_out(ch)) { + if (!synth->io_ops->synth_out(synth, ch)) { schedule_timeout(msecs_to_jiffies(full_time_val)); continue; } @@ -129,7 +101,7 @@ void spk_do_catch_up(struct spk_synth *synth) delay_time_val = delay_time->u.n.value; full_time_val = full_time->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); - if (spk_serial_out(synth->procspeech)) + if (synth->io_ops->synth_out(synth, synth->procspeech)) schedule_timeout( msecs_to_jiffies(delay_time_val)); else @@ -142,30 +114,13 @@ void spk_do_catch_up(struct spk_synth *synth) synth_buffer_getc(); spin_unlock_irqrestore(&speakup_info.spinlock, flags); } - spk_serial_out(synth->procspeech); + synth->io_ops->synth_out(synth, synth->procspeech); } EXPORT_SYMBOL_GPL(spk_do_catch_up); -const char *spk_synth_immediate(struct spk_synth *synth, const char *buff) -{ - u_char ch; - - while ((ch = *buff)) { - if (ch == '\n') - ch = synth->procspeech; - if (spk_wait_for_xmitr()) - outb(ch, speakup_info.port_tts); - else - return buff; - buff++; - } - return NULL; -} -EXPORT_SYMBOL_GPL(spk_synth_immediate); - void spk_synth_flush(struct spk_synth *synth) { - spk_serial_out(synth->clear); + synth->io_ops->synth_out(synth, synth->clear); } EXPORT_SYMBOL_GPL(spk_synth_flush); @@ -180,7 +135,7 @@ int spk_synth_is_alive_restart(struct spk_synth *synth) { if (synth->alive) return 1; - if (spk_wait_for_xmitr() > 0) { + if (spk_wait_for_xmitr(synth) > 0) { /* restart */ synth->alive = 1; synth_printf("%s", synth->init); @@ -255,6 +210,35 @@ void synth_printf(const char *fmt, ...) } EXPORT_SYMBOL_GPL(synth_printf); +void synth_putwc(u16 wc) +{ + synth_buffer_add(wc); +} +EXPORT_SYMBOL_GPL(synth_putwc); + +void synth_putwc_s(u16 wc) +{ + synth_buffer_add(wc); + synth_start(); +} +EXPORT_SYMBOL_GPL(synth_putwc_s); + +void synth_putws(const u16 *buf) +{ + const u16 *p; + + for (p = buf; *p; p++) + synth_buffer_add(*p); +} +EXPORT_SYMBOL_GPL(synth_putws); + +void synth_putws_s(const u16 *buf) +{ + synth_putws(buf); + synth_start(); +} +EXPORT_SYMBOL_GPL(synth_putws_s); + static int index_count; static int sentence_count; @@ -272,7 +256,7 @@ void spk_reset_index_count(int sc) int synth_supports_indexing(void) { - if (synth->get_index != NULL) + if (synth->get_index) return 1; return 0; } @@ -350,7 +334,7 @@ int synth_init(char *synth_name) int ret = 0; struct spk_synth *synth = NULL; - if (synth_name == NULL) + if (!synth_name) return 0; if (strcmp(synth_name, "none") == 0) { @@ -362,7 +346,7 @@ int synth_init(char *synth_name) mutex_lock(&spk_mutex); /* First, check if we already have it loaded. */ - for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) + for (i = 0; i < MAXSYNTHS && synths[i]; i++) if (strcmp(synths[i]->name, synth_name) == 0) synth = synths[i]; @@ -406,8 +390,8 @@ static int do_synth_init(struct spk_synth *in_synth) speakup_register_var(var); if (!spk_quiet_boot) synth_printf("%s found\n", synth->long_name); - if (synth->attributes.name && sysfs_create_group(speakup_kobj, - &synth->attributes) < 0) + if (synth->attributes.name && + sysfs_create_group(speakup_kobj, &synth->attributes) < 0) return -ENOMEM; synth_flags = synth->flags; wake_up_interruptible_all(&speakup_event); @@ -421,7 +405,7 @@ void synth_release(void) struct var_t *var; unsigned long flags; - if (synth == NULL) + if (!synth) return; spin_lock_irqsave(&speakup_info.spinlock, flags); pr_info("releasing synth %s\n", synth->name); @@ -432,7 +416,6 @@ void synth_release(void) sysfs_remove_group(speakup_kobj, &synth->attributes); for (var = synth->vars; var->var_id != MAXVARS; var++) speakup_unregister_var(var->var_id); - spk_stop_serial_interrupt(); synth->release(); synth = NULL; } @@ -444,7 +427,7 @@ int synth_add(struct spk_synth *in_synth) int status = 0; mutex_lock(&spk_mutex); - for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) + for (i = 0; i < MAXSYNTHS && synths[i]; i++) /* synth_remove() is responsible for rotating the array down */ if (in_synth == synths[i]) { mutex_unlock(&spk_mutex); @@ -471,11 +454,11 @@ void synth_remove(struct spk_synth *in_synth) mutex_lock(&spk_mutex); if (synth == in_synth) synth_release(); - for (i = 0; synths[i] != NULL; i++) { + for (i = 0; synths[i]; i++) { if (in_synth == synths[i]) break; } - for ( ; synths[i] != NULL; i++) /* compress table */ + for ( ; synths[i]; i++) /* compress table */ synths[i] = synths[i + 1]; module_status = 0; mutex_unlock(&spk_mutex); diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c index cc984196..d37d24e 100644 --- a/drivers/staging/speakup/varhandlers.c +++ b/drivers/staging/speakup/varhandlers.c @@ -98,7 +98,7 @@ void speakup_register_var(struct var_t *var) } } p_header = var_ptrs[var->var_id]; - if (p_header->data != NULL) + if (p_header->data) return; p_header->data = var; switch (p_header->var_type) { @@ -210,11 +210,11 @@ int spk_set_num_var(int input, struct st_var_header *var, int how) return -ERANGE; var_data->u.n.value = val; - if (var->var_type == VAR_TIME && p_val != NULL) { + if (var->var_type == VAR_TIME && p_val) { *p_val = msecs_to_jiffies(val); return 0; } - if (p_val != NULL) + if (p_val) *p_val = val; if (var->var_id == PUNC_LEVEL) { spk_punc_mask = spk_punc_masks[val]; @@ -258,10 +258,11 @@ int spk_set_string_var(const char *page, struct st_var_header *var, int len) if (var->p_val != var_data->u.s.default_val) strcpy((char *)var->p_val, var_data->u.s.default_val); return -ERESTART; - } else if (var->p_val) + } else if (var->p_val) { strcpy((char *)var->p_val, page); - else + } else { return -E2BIG; + } return 0; } @@ -281,17 +282,18 @@ int spk_set_mask_bits(const char *input, const int which, const int how) spk_chartab[*cp] &= ~mask; } cp = (u_char *)input; - if (!cp) + if (!cp) { cp = spk_punc_info[which].value; - else { + } else { for (; *cp; cp++) { if (*cp < SPACE) break; if (mask < PUNC) { if (!(spk_chartab[*cp] & PUNC)) break; - } else if (spk_chartab[*cp] & B_NUM) + } else if (spk_chartab[*cp] & B_NUM) { break; + } } if (*cp) return -EINVAL; |