staging: speakup_soft: Fix alternate speech with other synths [Linux 3.16.72]

This Linux kernel change "staging: speakup_soft: Fix alternate speech with other synths" is included in the Linux 3.16.72 release. This change is authored by Samuel Thibault <samuel.thibault [at] ens-lyon.org> on Thu Mar 7 23:06:57 2019 +0100. The commit for this change in Linux stable tree is 2dc2961 (patch) which is from upstream commit 45ac7b3. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 45ac7b3.

staging: speakup_soft: Fix alternate speech with other synths

commit 45ac7b31bc6c4af885cc5b5d6c534c15bcbe7643 upstream.

When switching from speakup_soft to another synth, speakup_soft would
keep calling synth_buffer_getc() from softsynthx_read.

Let's thus make synth.c export the knowledge of the current synth, so
that speakup_soft can determine whether it should be running.

speakup_soft also needs to set itself alive, otherwise the switch would
let it remain silent.

Signed-off-by: Samuel Thibault <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16:
 - There's no Unicode support
 - Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>

There are 19 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/staging/speakup/speakup_soft.c | 12 +++++++++---
 drivers/staging/speakup/spk_priv.h     |  1 +
 drivers/staging/speakup/synth.c        |  6 ++++++
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c
index 9ed7265..c5bf6b1 100644
--- a/drivers/staging/speakup/speakup_soft.c
+++ b/drivers/staging/speakup/speakup_soft.c
@@ -213,10 +213,13 @@ static ssize_t softsynth_read(struct file *fp, char __user *buf, size_t count,
    DEFINE_WAIT(wait);

    spin_lock_irqsave(&speakup_info.spinlock, flags);
+   synth_soft.alive = 1;
    while (1) {
        prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE);
-       if (!synth_buffer_empty() || speakup_info.flushing)
-           break;
+       if (synth_current() == &synth_soft) {
+           if (!synth_buffer_empty() || speakup_info.flushing)
+               break;
+       }
        spin_unlock_irqrestore(&speakup_info.spinlock, flags);
        if (fp->f_flags & O_NONBLOCK) {
            finish_wait(&speakup_event, &wait);
@@ -234,6 +237,8 @@ static ssize_t softsynth_read(struct file *fp, char __user *buf, size_t count,
    cp = buf;
    init = get_initstring();
    while (chars_sent < count) {
+       if (synth_current() != &synth_soft)
+           break;
        if (speakup_info.flushing) {
            speakup_info.flushing = 0;
            ch = '\x18';
@@ -286,7 +291,8 @@ static unsigned int softsynth_poll(struct file *fp,
    poll_wait(fp, &speakup_event, wait);

    spin_lock_irqsave(&speakup_info.spinlock, flags);
-   if (!synth_buffer_empty() || speakup_info.flushing)
+   if (synth_current() == &synth_soft &&
+       (!synth_buffer_empty() || speakup_info.flushing))
        ret = POLLIN | POLLRDNORM;
    spin_unlock_irqrestore(&speakup_info.spinlock, flags);
    return ret;
diff --git a/drivers/staging/speakup/spk_priv.h b/drivers/staging/speakup/spk_priv.h
index 637ba67..b669021 100644
--- a/drivers/staging/speakup/spk_priv.h
+++ b/drivers/staging/speakup/spk_priv.h
@@ -72,6 +72,7 @@ extern ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
 extern int synth_release_region(u_long, u_long);
 extern int synth_add(struct spk_synth *in_synth);
 extern void synth_remove(struct spk_synth *in_synth);
+struct spk_synth *synth_current(void);

 extern struct speakup_info_t speakup_info;

diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c
index 172cf62..1219089 100644
--- a/drivers/staging/speakup/synth.c
+++ b/drivers/staging/speakup/synth.c
@@ -475,4 +475,10 @@ void synth_remove(struct spk_synth *in_synth)
 }
 EXPORT_SYMBOL_GPL(synth_remove);

+struct spk_synth *synth_current(void)
+{
+   return synth;
+}
+EXPORT_SYMBOL_GPL(synth_current);
+
 short spk_punc_masks[] = { 0, SOME, MOST, PUNC, PUNC|B_SYM };

Leave a Reply

Your email address will not be published. Required fields are marked *