125 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <linux/console.h>3#include <linux/types.h>4#include <linux/wait.h>5 6#include "speakup.h"7#include "spk_priv.h"8 9#define SYNTH_BUF_SIZE 8192 /* currently 8K bytes */10 11static u16 synth_buffer[SYNTH_BUF_SIZE]; /* guess what this is for! */12static u16 *buff_in = synth_buffer;13static u16 *buff_out = synth_buffer;14static u16 *buffer_end = synth_buffer + SYNTH_BUF_SIZE - 1;15 16/* These try to throttle applications by stopping the TTYs17 * Note: we need to make sure that we will restart them eventually, which is18 * usually not possible to do from the notifiers. TODO: it should be possible19 * starting from linux 2.6.26.20 *21 * So we only stop when we know alive == 1 (else we discard the data anyway),22 * and the alive synth will eventually call start_ttys from the thread context.23 */24void speakup_start_ttys(void)25{26 int i;27 28 for (i = 0; i < MAX_NR_CONSOLES; i++) {29 if (speakup_console[i] && speakup_console[i]->tty_stopped)30 continue;31 if (vc_cons[i].d && vc_cons[i].d->port.tty)32 start_tty(vc_cons[i].d->port.tty);33 }34}35EXPORT_SYMBOL_GPL(speakup_start_ttys);36 37static void speakup_stop_ttys(void)38{39 int i;40 41 for (i = 0; i < MAX_NR_CONSOLES; i++)42 if (vc_cons[i].d && vc_cons[i].d->port.tty)43 stop_tty(vc_cons[i].d->port.tty);44}45 46static int synth_buffer_free(void)47{48 int chars_free;49 50 if (buff_in >= buff_out)51 chars_free = SYNTH_BUF_SIZE - (buff_in - buff_out);52 else53 chars_free = buff_out - buff_in;54 return chars_free;55}56 57int synth_buffer_empty(void)58{59 return (buff_in == buff_out);60}61EXPORT_SYMBOL_GPL(synth_buffer_empty);62 63void synth_buffer_add(u16 ch)64{65 if (!synth->alive) {66 /* This makes sure that we won't stop TTYs if there is no synth67 * to restart them68 */69 return;70 }71 if (synth_buffer_free() <= 100) {72 synth_start();73 speakup_stop_ttys();74 }75 if (synth_buffer_free() <= 1)76 return;77 *buff_in++ = ch;78 if (buff_in > buffer_end)79 buff_in = synth_buffer;80 /* We have written something to the speech synthesis, so we are not81 * paused any more.82 */83 spk_paused = false;84}85 86u16 synth_buffer_getc(void)87{88 u16 ch;89 90 if (buff_out == buff_in)91 return 0;92 ch = *buff_out++;93 if (buff_out > buffer_end)94 buff_out = synth_buffer;95 return ch;96}97EXPORT_SYMBOL_GPL(synth_buffer_getc);98 99u16 synth_buffer_peek(void)100{101 if (buff_out == buff_in)102 return 0;103 return *buff_out;104}105EXPORT_SYMBOL_GPL(synth_buffer_peek);106 107void synth_buffer_skip_nonlatin1(void)108{109 while (buff_out != buff_in) {110 if (*buff_out < 0x100)111 return;112 buff_out++;113 if (buff_out > buffer_end)114 buff_out = synth_buffer;115 }116}117EXPORT_SYMBOL_GPL(synth_buffer_skip_nonlatin1);118 119void synth_buffer_clear(void)120{121 buff_in = synth_buffer;122 buff_out = synth_buffer;123}124EXPORT_SYMBOL_GPL(synth_buffer_clear);125