1
0
mirror of https://github.com/UzixLS/picocom.git synced 2025-07-19 07:21:18 +03:00

Workaround for drivers with broken flush

term_flush() does not work with some drivers. If we try to drain or even
close the port while there are still data in it's output buffers *and*
flow-control is enabled, we may block forever. So we "fake" a flush, by
temporarily setting f/c to none, waiting for any data in the output
buffer to drain, and then reseting f/c to it's original setting.
This commit is contained in:
Nick Patavalis
2017-12-20 09:48:00 +02:00
parent e6653b45b5
commit 89be292023
3 changed files with 79 additions and 0 deletions

57
term.c
View File

@ -1642,6 +1642,63 @@ term_drain(int fd)
/***************************************************************************/
int
term_fake_flush(int fd)
{
struct termios tio;
int rval, i, r;
rval = 0;
do { /* dummy */
i = term_find(fd);
if ( i < 0 ) {
rval = -1;
break;
}
/* Get current termios */
r = tcgetattr(fd, &tio);
if ( r < 0 ) {
term_errno = TERM_EGETATTR;
rval = -1;
break;
}
term.currtermios[i] = tio;
/* Set flow-control to none */
tio.c_cflag &= ~(CRTSCTS);
tio.c_iflag &= ~(IXON | IXOFF | IXANY);
/* Apply termios */
r = tcsetattr(fd, TCSANOW, &tio);
if ( r < 0 ) {
term_errno = TERM_ESETATTR;
rval = -1;
break;
}
/* Wait for output to drain. Without flow-control this should
complete in finite time. */
r = tcdrain(fd);
if ( r < 0 ) {
term_errno = TERM_EDRAIN;
rval = -1;
break;
}
/* see comment in term_drain */
if ( DRAIN_DELAY ) usleep(DRAIN_DELAY);
/* Reset flow-control to original setting. */
r = tcsetattr(fd, TCSANOW, &term.currtermios[i]);
if ( r < 0 ) {
term_errno = TERM_ESETATTR;
rval = -1;
break;
}
} while (0);
return rval;
}
int
term_flush(int fd)
{