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