summaryrefslogtreecommitdiff
path: root/drivers/staging/speakup
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2018-03-10 13:56:27 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-03-14 14:57:45 +0300
commit65fa72d34360c571b058afeb0e64367d3eaf064b (patch)
tree6630e1337bb45da67d5398f52440c6cf84828fab /drivers/staging/speakup
parentb8461ff7747416dca950aad43415f214cfcdbfa3 (diff)
downloadlinux-65fa72d34360c571b058afeb0e64367d3eaf064b.tar.xz
staging: speakup: Add unicode support to the speakup_dummy driver
This extends spk_io_ops with a synth_out_unicode which takes a u16 character instead of just a byte, and extends spk_ttyio to implement it to emit utf-8. spk_do_catch_up_unicode can then be introduced to benefit from synth_out_unicode, and speakup_dummy made to use spk_do_catch_up_unicode instead of spk_do_catch_up. Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/speakup')
-rw-r--r--drivers/staging/speakup/speakup_dummy.c2
-rw-r--r--drivers/staging/speakup/spk_priv.h1
-rw-r--r--drivers/staging/speakup/spk_ttyio.c18
-rw-r--r--drivers/staging/speakup/spk_types.h1
-rw-r--r--drivers/staging/speakup/synth.c25
5 files changed, 42 insertions, 5 deletions
diff --git a/drivers/staging/speakup/speakup_dummy.c b/drivers/staging/speakup/speakup_dummy.c
index a30d60450bd5..aa0c900f79f2 100644
--- a/drivers/staging/speakup/speakup_dummy.c
+++ b/drivers/staging/speakup/speakup_dummy.c
@@ -94,7 +94,7 @@ static struct spk_synth synth_dummy = {
.probe = spk_ttyio_synth_probe,
.release = spk_ttyio_release,
.synth_immediate = spk_ttyio_synth_immediate,
- .catch_up = spk_do_catch_up,
+ .catch_up = spk_do_catch_up_unicode,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
.synth_adjust = NULL,
diff --git a/drivers/staging/speakup/spk_priv.h b/drivers/staging/speakup/spk_priv.h
index 00430437eb4c..7b3a16e1fa23 100644
--- a/drivers/staging/speakup/spk_priv.h
+++ b/drivers/staging/speakup/spk_priv.h
@@ -57,6 +57,7 @@ int spk_ttyio_synth_probe(struct spk_synth *synth);
const char *spk_serial_synth_immediate(struct spk_synth *synth, const char *buff);
const char *spk_ttyio_synth_immediate(struct spk_synth *synth, const char *buff);
void spk_do_catch_up(struct spk_synth *synth);
+void spk_do_catch_up_unicode(struct spk_synth *synth);
void spk_synth_flush(struct spk_synth *synth);
unsigned char spk_synth_get_index(struct spk_synth *synth);
int spk_synth_is_alive_nop(struct spk_synth *synth);
diff --git a/drivers/staging/speakup/spk_ttyio.c b/drivers/staging/speakup/spk_ttyio.c
index 311940205bee..ade03b03bcd3 100644
--- a/drivers/staging/speakup/spk_ttyio.c
+++ b/drivers/staging/speakup/spk_ttyio.c
@@ -110,6 +110,7 @@ static struct tty_ldisc_ops spk_ttyio_ldisc_ops = {
};
static int spk_ttyio_out(struct spk_synth *in_synth, const char ch);
+static int spk_ttyio_out_unicode(struct spk_synth *in_synth, u16 ch);
static void spk_ttyio_send_xchar(char ch);
static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear);
static unsigned char spk_ttyio_in(void);
@@ -118,6 +119,7 @@ static void spk_ttyio_flush_buffer(void);
struct spk_io_ops spk_ttyio_ops = {
.synth_out = spk_ttyio_out,
+ .synth_out_unicode = spk_ttyio_out_unicode,
.send_xchar = spk_ttyio_send_xchar,
.tiocmset = spk_ttyio_tiocmset,
.synth_in = spk_ttyio_in,
@@ -221,6 +223,22 @@ static int spk_ttyio_out(struct spk_synth *in_synth, const char ch)
return 0;
}
+static int spk_ttyio_out_unicode(struct spk_synth *in_synth, u16 ch)
+{
+ int ret;
+ if (ch < 0x80)
+ ret = spk_ttyio_out(in_synth, ch);
+ else if (ch < 0x800) {
+ ret = spk_ttyio_out(in_synth, 0xc0 | (ch >> 6));
+ ret &= spk_ttyio_out(in_synth, 0x80 | (ch & 0x3f));
+ } else {
+ ret = spk_ttyio_out(in_synth, 0xe0 | (ch >> 12));
+ ret &= spk_ttyio_out(in_synth, 0x80 | ((ch >> 6) & 0x3f));
+ ret &= spk_ttyio_out(in_synth, 0x80 | (ch & 0x3f));
+ }
+ return ret;
+}
+
static int check_tty(struct tty_struct *tty)
{
if (!tty) {
diff --git a/drivers/staging/speakup/spk_types.h b/drivers/staging/speakup/spk_types.h
index c50de6035a9a..4203bed90b4f 100644
--- a/drivers/staging/speakup/spk_types.h
+++ b/drivers/staging/speakup/spk_types.h
@@ -151,6 +151,7 @@ struct spk_synth;
struct spk_io_ops {
int (*synth_out)(struct spk_synth *synth, const char ch);
+ int (*synth_out_unicode)(struct spk_synth *synth, u16 ch);
void (*send_xchar)(char ch);
void (*tiocmset)(unsigned int set, unsigned int clear);
unsigned char (*synth_in)(void);
diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c
index c06e6a810999..7deeb7061018 100644
--- a/drivers/staging/speakup/synth.c
+++ b/drivers/staging/speakup/synth.c
@@ -52,9 +52,9 @@ static int do_synth_init(struct spk_synth *in_synth);
* For devices that have a "full" notification mechanism, the driver can
* adapt the loop the way they prefer.
*/
-void spk_do_catch_up(struct spk_synth *synth)
+static void _spk_do_catch_up(struct spk_synth *synth, int unicode)
{
- u_char ch;
+ u16 ch;
unsigned long flags;
unsigned long jiff_max;
struct var_t *delay_time;
@@ -63,6 +63,7 @@ void spk_do_catch_up(struct spk_synth *synth)
int jiffy_delta_val;
int delay_time_val;
int full_time_val;
+ int ret;
jiffy_delta = spk_get_var(JIFFY);
full_time = spk_get_var(FULL);
@@ -81,7 +82,8 @@ void spk_do_catch_up(struct spk_synth *synth)
synth->flush(synth);
continue;
}
- synth_buffer_skip_nonlatin1();
+ if (!unicode)
+ synth_buffer_skip_nonlatin1();
if (synth_buffer_empty()) {
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
break;
@@ -92,7 +94,11 @@ void spk_do_catch_up(struct spk_synth *synth)
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
if (ch == '\n')
ch = synth->procspeech;
- if (!synth->io_ops->synth_out(synth, ch)) {
+ if (unicode)
+ ret = synth->io_ops->synth_out_unicode(synth, ch);
+ else
+ ret = synth->io_ops->synth_out(synth, ch);
+ if (!ret) {
schedule_timeout(msecs_to_jiffies(full_time_val));
continue;
}
@@ -117,8 +123,19 @@ void spk_do_catch_up(struct spk_synth *synth)
}
synth->io_ops->synth_out(synth, synth->procspeech);
}
+
+void spk_do_catch_up(struct spk_synth *synth)
+{
+ _spk_do_catch_up(synth, 0);
+}
EXPORT_SYMBOL_GPL(spk_do_catch_up);
+void spk_do_catch_up_unicode(struct spk_synth *synth)
+{
+ _spk_do_catch_up(synth, 1);
+}
+EXPORT_SYMBOL_GPL(spk_do_catch_up_unicode);
+
void spk_synth_flush(struct spk_synth *synth)
{
synth->io_ops->flush_buffer();