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