staging: speakup: flush tty buffers and ensure hardware flow control
cover staging: speakup: flush tty buffers and ensure hardware flow control
Hi,
This patch applies on top of previous patchset which migrates synths to TTY [1]. It fixes couple of issues and tries to ensure hardware flow control is enabled.
Thanks,
Okash
[1] https://www.mail-archive.com/[email protected]/msg1387738.html
PATCH 1/1 staging: speakup: flush tty buffers and ensure hardware flow control
This patch fixes the issue where TTY-migrated synths would take a while to shut up after hitting numpad enter key. When calling synth_flush, even though XOFF character is sent as high priority, data buffered in TTY layer is still sent to the synth. This patch flushes that buffered data when synth_flush is called.
It also tries to ensure that hardware flow control is enabled, by setting CRTSCTS using tty's termios.
drivers/staging/speakup/serialio.c +7 -0
@@ -30,6 +30,7 @@static void spk_serial_tiocmset (unsigned int set,unsigned int clear);static unsigned char spk_serial_in (void );static unsigned char spk_serial_in_nowait (void ); +static void spk_serial_flush_buffer (void );struct spk_io_ops spk_serial_io_ops = { .synth_out = spk_serial_out,
@@ -37,6 +38,7 @@ .tiocmset = spk_serial_tiocmset, .synth_in = spk_serial_in, .synth_in_nowait = spk_serial_in_nowait, + .flush_buffer = spk_serial_flush_buffer, };EXPORT_SYMBOL_GPL (spk_serial_io_ops);
@@ -268,6 +270,11 @@return inb_p (speakup_info.port_tts +UART_RX ); } +static void spk_serial_flush_buffer (void ) +{ +/* TODO: flush the UART 16550 buffer */ +} +static int spk_serial_out (struct spk_synth *in_synth,const char ch) {if (in_synth->alive &&spk_wait_for_xmitr (in_synth)) {
drivers/staging/speakup/spk_ttyio.c +20 -0
@@ -85,6 +85,7 @@static void spk_ttyio_tiocmset (unsigned int set,unsigned int clear);static unsigned char spk_ttyio_in (void );static unsigned char spk_ttyio_in_nowait (void ); +static void spk_ttyio_flush_buffer (void );struct spk_io_ops spk_ttyio_ops = { .synth_out = spk_ttyio_out,
@@ -92,6 +93,7 @@ .tiocmset = spk_ttyio_tiocmset, .synth_in = spk_ttyio_in, .synth_in_nowait = spk_ttyio_in_nowait, + .flush_buffer = spk_ttyio_flush_buffer, };EXPORT_SYMBOL_GPL (spk_ttyio_ops);
@@ -99,6 +101,7 @@ {int ret =0 ;struct tty_struct *tty; +struct ktermios tmp_termios; ret =tty_register_ldisc (N_SPEAKUP , &spk_ttyio_ldisc_ops);if (ret) {
@@ -127,6 +130,18 @@ }clear_bit (TTY_HUPPED , &tty->flags); +/* ensure hardware flow control is enabled */ +down_read (&tty->termios_rwsem); + tmp_termios = tty->termios; +up_read (&tty->termios_rwsem); + +if (!(tmp_termios.c_cflag &CRTSCTS )) { + tmp_termios.c_cflag |=CRTSCTS ; + ret =tty_set_termios (tty, &tmp_termios); +if (ret) +pr_warn ("speakup: Failed to set hardware flow control\n" ); + } +tty_unlock (tty); ret =tty_set_ldisc (tty,N_SPEAKUP );
@@ -201,6 +216,11 @@return (rv ==0xff ) ?0 : rv; } +static void spk_ttyio_flush_buffer (void ) +{ + speakup_tty->ops->flush_buffer (speakup_tty); +} +int spk_ttyio_synth_probe (struct spk_synth *synth) {int rv =spk_ttyio_initialise_ldisc (synth->ser);
drivers/staging/speakup/spk_types.h +1 -0
@@ -154,6 +154,7 @@void (*tiocmset)(unsigned int set,unsigned int clear);unsigned char (*synth_in)(void );unsigned char (*synth_in_nowait)(void ); +void (*flush_buffer)(void ); };struct spk_synth {
drivers/staging/speakup/speakup_audptr.c +1 -0
@@ -127,6 +127,7 @@static void synth_flush (struct spk_synth *synth) { + synth->io_ops->flush_buffer (); synth->io_ops->send_xchar (SYNTH_CLEAR ); synth->io_ops->synth_out (synth,PROCSPEECH ); }
drivers/staging/speakup/speakup_decext.c +1 -0
@@ -221,6 +221,7 @@static void synth_flush (struct spk_synth *synth) { in_escape =0 ; + synth->io_ops->flush_buffer (); synth->synth_immediate (synth,"\033P;10z\033\\" ); }
drivers/staging/speakup/speakup_dectlk.c +1 -0
@@ -293,6 +293,7 @@ synth->io_ops->synth_out (synth,']' ); in_escape =0 ; is_flushing =1 ; + synth->io_ops->flush_buffer (); synth->io_ops->synth_out (synth,SYNTH_CLEAR ); }
drivers/staging/speakup/speakup_spkout.c +1 -0
@@ -125,6 +125,7 @@static void synth_flush (struct spk_synth *synth) { + synth->io_ops->flush_buffer (); synth->io_ops->send_xchar (SYNTH_CLEAR ); }
drivers/staging/speakup/synth.c +1 -0
@@ -120,6 +120,7 @@void spk_synth_flush (struct spk_synth *synth) { + synth->io_ops->flush_buffer (); synth->io_ops->synth_out (synth, synth->clear); }EXPORT_SYMBOL_GPL (spk_synth_flush);
drivers/staging/speakup/spk_ttyio.c line 142
Quoted 5 lines
drivers/staging/speakup/spk_ttyio.c +5
-0+if (!(tmp_termios.c_cflag &CRTSCTS )) { + tmp_termios.c_cflag |=CRTSCTS ; + ret =tty_set_termios (tty, &tmp_termios); +if (ret) +pr_warn ("speakup: Failed to set hardware flow control\n" );
You should check the tty c_cflag after the call rather than rely on an error code. Strictly speaking tty_set_termios should error if no tty bits are changed by the request but it never has on Linux. Instead check the tty gave you the result you wanted.
Alan
Hi Alan,
Quoted 10 lines · Alan Cox
drivers/staging/speakup/spk_ttyio.c line 142
Quoted 5 lines
drivers/staging/speakup/spk_ttyio.c +5
-0+if (!(tmp_termios.c_cflag &CRTSCTS )) { + tmp_termios.c_cflag |=CRTSCTS ; + ret =tty_set_termios (tty, &tmp_termios); +if (ret) +pr_warn ("speakup: Failed to set hardware flow control\n" );You should check the tty
c_cflagafter the call rather than rely on an error code. Strictly speakingtty_set_termiosshould error if no tty bits are changed by the request but it never has on Linux. Instead check the tty gave you the result you wanted.
Thanks. I will replace the check for return value with check for c_cflag.
May be we should fix this in tty_set_termios?
Quoted 13 lines · On Thu, 11 May 2017 09:29:14 +0100 Okash Khawaja <[email protected]>…
Hi Alan,
Quoted 10 lines · Alan Cox
drivers/staging/speakup/spk_ttyio.c line 142
Quoted 5 lines
drivers/staging/speakup/spk_ttyio.c +5
-0+if (!(tmp_termios.c_cflag &CRTSCTS )) { + tmp_termios.c_cflag |=CRTSCTS ; + ret =tty_set_termios (tty, &tmp_termios); +if (ret) +pr_warn ("speakup: Failed to set hardware flow control\n" );You should check the tty
c_cflagafter the call rather than rely on an error code. Strictly speakingtty_set_termiosshould error if no tty bits are changed by the request but it never has on Linux. Instead check the tty gave you the result you wanted.
Quoted 3 lines
Thanks. I will replace the check for return value with check for
c_cflag.May be we should fix this in
tty_set_termios?
Possibly. It however changes the external kernel ABI. It's also not a simple memcmp because any undefined bits must be ignored.
Make a patch, try it and see what breaks ? If nothing breaks then yes it makes sense IMHO too.
Alan
Quoted 18 lines · Alan Cox
Quoted 15 lines · On Thu, 11 May 2017 09:29:14 +0100 Okash Khawaja <[email protected]>…
Hi Alan,
Quoted 10 lines · Alan Cox
drivers/staging/speakup/spk_ttyio.c line 142
Quoted 5 lines
drivers/staging/speakup/spk_ttyio.c +5
-0+if (!(tmp_termios.c_cflag &CRTSCTS )) { + tmp_termios.c_cflag |=CRTSCTS ; + ret =tty_set_termios (tty, &tmp_termios); +if (ret) +pr_warn ("speakup: Failed to set hardware flow control\n" );You should check the tty
c_cflagafter the call rather than rely on an error code. Strictly speakingtty_set_termiosshould error if no tty bits are changed by the request but it never has on Linux. Instead check the tty gave you the result you wanted.Thanks. I will replace the check for return value with check for
c_cflag.
Quoted 7 lines
Quoted 1 line
May be we should fix this in
tty_set_termios?Possibly. It however changes the external kernel ABI. It's also not a simple memcmp because any undefined bits must be ignored.
Make a patch, try it and see what breaks ? If nothing breaks then yes it makes sense IMHO too.
Right, thanks for the heads up. I'll see if I get round to doing it. For external kernel ABI, will we need to check libc implementations of termios functions? Will that be sufficient?
Thanks,
Okash
Quoted 24 lines · On Fri, 12 May 2017 20:35:18 +0100 Okash Khawaja <[email protected]>…
Quoted 23 lines · Alan Cox
Quoted 13 lines · On Thu, 11 May 2017 09:29:14 +0100 Okash Khawaja <[email protected]>…
Hi Alan,
Quoted 10 lines · Alan Cox
drivers/staging/speakup/spk_ttyio.c line 142
Quoted 5 lines
drivers/staging/speakup/spk_ttyio.c +5
-0+if (!(tmp_termios.c_cflag &CRTSCTS )) { + tmp_termios.c_cflag |=CRTSCTS ; + ret =tty_set_termios (tty, &tmp_termios); +if (ret) +pr_warn ("speakup: Failed to set hardware flow control\n" );You should check the tty
c_cflagafter the call rather than rely on an error code. Strictly speakingtty_set_termiosshould error if no tty bits are changed by the request but it never has on Linux. Instead check the tty gave you the result you wanted.Quoted 3 lines
Thanks. I will replace the check for return value with check for
c_cflag.May be we should fix this in
tty_set_termios?Possibly. It however changes the external kernel ABI. It's also not a simple memcmp because any undefined bits must be ignored.
Quoted 6 lines
Quoted 2 lines
Make a patch, try it and see what breaks ? If nothing breaks then yes it makes sense IMHO too.
Right, thanks for the heads up. I'll see if I get round to doing it. For external kernel ABI, will we need to check libc implementations of termios functions? Will that be sufficient?
I think the only way you find out is to try it and run a distro like that. If it seems ok submit the patch to linux-next with a clear note it potentially changes the ABI so if people find bugs it can be reverted.
Alan
PATCH v2 1/1 staging: speakup: flush tty buffers and ensure hardware flow control
In reply to Alan CoxThis patch fixes the issue where TTY-migrated synths would take a while to shut up after hitting numpad enter key. When calling synth_flush, even though XOFF character is sent as high priority, data buffered in TTY layer is still sent to the synth. This patch flushes that buffered data when synth_flush is called.
It also tries to ensure that hardware flow control is enabled, by setting CRTSCTS using tty's termios.
drivers/staging/speakup/serialio.c +7 -0
@@ -30,6 +30,7 @@static void spk_serial_tiocmset (unsigned int set,unsigned int clear);static unsigned char spk_serial_in (void );static unsigned char spk_serial_in_nowait (void ); +static void spk_serial_flush_buffer (void );struct spk_io_ops spk_serial_io_ops = { .synth_out = spk_serial_out,
@@ -37,6 +38,7 @@ .tiocmset = spk_serial_tiocmset, .synth_in = spk_serial_in, .synth_in_nowait = spk_serial_in_nowait, + .flush_buffer = spk_serial_flush_buffer, };EXPORT_SYMBOL_GPL (spk_serial_io_ops);
@@ -268,6 +270,11 @@return inb_p (speakup_info.port_tts +UART_RX ); } +static void spk_serial_flush_buffer (void ) +{ +/* TODO: flush the UART 16550 buffer */ +} +static int spk_serial_out (struct spk_synth *in_synth,const char ch) {if (in_synth->alive &&spk_wait_for_xmitr (in_synth)) {
drivers/staging/speakup/spk_ttyio.c +29 -0
@@ -85,6 +85,7 @@static void spk_ttyio_tiocmset (unsigned int set,unsigned int clear);static unsigned char spk_ttyio_in (void );static unsigned char spk_ttyio_in_nowait (void ); +static void spk_ttyio_flush_buffer (void );struct spk_io_ops spk_ttyio_ops = { .synth_out = spk_ttyio_out,
@@ -92,13 +93,22 @@ .tiocmset = spk_ttyio_tiocmset, .synth_in = spk_ttyio_in, .synth_in_nowait = spk_ttyio_in_nowait, + .flush_buffer = spk_ttyio_flush_buffer, };EXPORT_SYMBOL_GPL (spk_ttyio_ops); +static inline void get_termios (struct tty_struct *tty,struct ktermios *out_termios) +{ +down_read (&tty->termios_rwsem); + *out_termios = tty->termios; +up_read (&tty->termios_rwsem); +} +static int spk_ttyio_initialise_ldisc (int ser) {int ret =0 ;struct tty_struct *tty; +struct ktermios tmp_termios; ret =tty_register_ldisc (N_SPEAKUP , &spk_ttyio_ldisc_ops);if (ret) {
@@ -127,6 +137,20 @@ }clear_bit (TTY_HUPPED , &tty->flags); +/* ensure hardware flow control is enabled */ +get_termios (tty, &tmp_termios); +if (!(tmp_termios.c_cflag &CRTSCTS )) { + tmp_termios.c_cflag |=CRTSCTS ; +tty_set_termios (tty, &tmp_termios); +/* +* check c_cflag to see if it's updated as tty_set_termios may not return +* error even when no tty bits are changed by the request. +*/ +get_termios (tty, &tmp_termios); +if (!(tmp_termios.c_cflag &CRTSCTS )) +pr_warn ("speakup: Failed to set hardware flow control\n" ); + } +tty_unlock (tty); ret =tty_set_ldisc (tty,N_SPEAKUP );
@@ -201,6 +225,11 @@return (rv ==0xff ) ?0 : rv; } +static void spk_ttyio_flush_buffer (void ) +{ + speakup_tty->ops->flush_buffer (speakup_tty); +} +int spk_ttyio_synth_probe (struct spk_synth *synth) {int rv =spk_ttyio_initialise_ldisc (synth->ser);
drivers/staging/speakup/spk_types.h +1 -0
@@ -154,6 +154,7 @@void (*tiocmset)(unsigned int set,unsigned int clear);unsigned char (*synth_in)(void );unsigned char (*synth_in_nowait)(void ); +void (*flush_buffer)(void ); };struct spk_synth {
drivers/staging/speakup/speakup_audptr.c +1 -0
@@ -127,6 +127,7 @@static void synth_flush (struct spk_synth *synth) { + synth->io_ops->flush_buffer (); synth->io_ops->send_xchar (SYNTH_CLEAR ); synth->io_ops->synth_out (synth,PROCSPEECH ); }
drivers/staging/speakup/speakup_decext.c +1 -0
@@ -221,6 +221,7 @@static void synth_flush (struct spk_synth *synth) { in_escape =0 ; + synth->io_ops->flush_buffer (); synth->synth_immediate (synth,"\033P;10z\033\\" ); }
drivers/staging/speakup/speakup_dectlk.c +1 -0
@@ -293,6 +293,7 @@ synth->io_ops->synth_out (synth,']' ); in_escape =0 ; is_flushing =1 ; + synth->io_ops->flush_buffer (); synth->io_ops->synth_out (synth,SYNTH_CLEAR ); }
drivers/staging/speakup/speakup_spkout.c +1 -0
@@ -125,6 +125,7 @@static void synth_flush (struct spk_synth *synth) { + synth->io_ops->flush_buffer (); synth->io_ops->send_xchar (SYNTH_CLEAR ); }
drivers/staging/speakup/synth.c +1 -0
@@ -120,6 +120,7 @@void spk_synth_flush (struct spk_synth *synth) { + synth->io_ops->flush_buffer (); synth->io_ops->synth_out (synth, synth->clear); }EXPORT_SYMBOL_GPL (spk_synth_flush);
Greg Kroah-Hartman
maintainerQuoted 6 lines · Okash Khawaja
This patch fixes the issue where TTY-migrated synths would take a while to shut up after hitting numpad enter key. When calling
synth_flush, even though XOFF character is sent as high priority, data buffered in TTY layer is still sent to the synth. This patch flushes that buffered data whensynth_flushis called.
Quoted 6 lines
It also tries to ensure that hardware flow control is enabled, by setting CRTSCTS using tty's termios.
Reported-by John Covici <[email protected]>Signed-off-by Okash Khawaja <[email protected]>Reviewed-by Samuel Thibault <[email protected]>
Doesn't apply as I didn't take your full series. Please resend it with that series fixed up.
thanks,
greg k-h