From bf11b1dd1511035d17caee9944064dfb0eab494f Mon Sep 17 00:00:00 2001 From: Kim Woelders Date: Wed, 13 Jan 2021 19:20:16 +0100 Subject: [PATCH] Add support for termios2 ioctls Based on patch by Thomas Shaddack https://www.improwis.com/projects/sw_SerialOverIP_RFC2217/ --- src/ttynvt.c | 80 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 13 deletions(-) diff --git a/src/ttynvt.c b/src/ttynvt.c index f1bea9a..862ba57 100644 --- a/src/ttynvt.c +++ b/src/ttynvt.c @@ -66,7 +66,7 @@ typedef struct { char net_buf[NET_BUF_SIZE]; int net_cnt; - struct termios tio; + struct termios2 tio; int cmcr; /* Commanded by ioctl */ volatile int smcr; /* Status from modem */ @@ -661,9 +661,13 @@ static const char *_ioctl_name(int cmd) snprintf(buf, sizeof(buf), "0x%x", cmd); return buf; CASE(TCSETSF); + CASE(TCSETSF2); CASE(TCSETSW); + CASE(TCSETSW2); CASE(TCSETS); + CASE(TCSETS2); CASE(TCGETS); + CASE(TCGETS2); CASE(TIOCINQ); CASE(TIOCOUTQ); CASE(TCFLSH); @@ -689,7 +693,7 @@ static const char *_ioctl_name(int cmd) } } -static unsigned int _tio_parity(const struct termios *tio) +static unsigned int _tio_parity(const struct termios2 *tio) { unsigned int par; @@ -712,12 +716,17 @@ static unsigned int _tio_parity(const struct termios *tio) return par; } -static unsigned int _tio_baud(const struct termios *tio) +static unsigned int _tio_baud(const struct termios2 *tio) { return baudrate(tio->c_cflag & (CBAUD | CBAUDEX)); } -static unsigned int _tio_csize(const struct termios *tio) +static unsigned int _tio2_baud(const struct termios2 *tio2) +{ + return tio2->c_ospeed; +} + +static unsigned int _tio_csize(const struct termios2 *tio) { unsigned int csize; @@ -733,7 +742,7 @@ static unsigned int _tio_csize(const struct termios *tio) return csize; } -static unsigned int _tio_stopb(const struct termios *tio) +static unsigned int _tio_stopb(const struct termios2 *tio) { unsigned int stopb; @@ -745,7 +754,7 @@ static unsigned int _tio_stopb(const struct termios *tio) return stopb; } -static void _show_termios(const char *txt, const struct termios *tio) +static void _show_termios(const char *txt, const struct termios2 *tio) { DBG("%s: %u%c%u%u %cCTSRTS %cCREAD %cHUPCL %cCLOCAL\n", txt, _tio_baud(tio), pstr[_tio_parity(tio)], _tio_csize(tio), @@ -754,6 +763,16 @@ static void _show_termios(const char *txt, const struct termios *tio) tio->c_cflag & HUPCL ? '+' : '-', tio->c_cflag & CLOCAL ? '+' : '-'); } +static void _show_termios2(const char *txt, const struct termios2 *tio) +{ + DBG("%s: %u%c%u%u %cCTSRTS %cCREAD %cHUPCL %cCLOCAL\n", txt, + _tio2_baud(tio), pstr[_tio_parity(tio)], _tio_csize(tio), + _tio_stopb(tio), + tio->c_cflag & CRTSCTS ? '+' : '-', tio->c_cflag & CREAD ? '+' : '-', + tio->c_cflag & HUPCL ? '+' : '-', tio->c_cflag & CLOCAL ? '+' : '-'); +} + + #define CHECK_BUF_IN(sz) \ if (in_bufsz < sz) do { in_bufsz = sz; goto retry_in; } while(0) #define CHECK_BUF_OUT(sz) \ @@ -765,7 +784,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg, const void *in_buf, size_t in_bufsz, size_t out_bufsz) { ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh; - struct termios *tio = &tty->tio; + struct termios2 *tio = &tty->tio; struct winsize ws; unsigned int tiocm = 0; int mcr; @@ -783,11 +802,28 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg, case TCSETSF: case TCSETSW: case TCSETS: - CHECK_BUF_IN(sizeof(struct termios)); + /* BEWARE of termios/termios2 buf structure difference! */ + case TCSETSF2: + case TCSETSW2: + case TCSETS2: { - memcpy(tio, in_buf, in_bufsz); - - byte4 = htonl(_tio_baud(tio)); + switch (cmd) + { + case TCSETSF: + case TCSETSW: + case TCSETS: + CHECK_BUF_IN(sizeof(struct termios)); + memcpy(tio, in_buf, in_bufsz); + byte4 = htonl(_tio_baud(tio)); + break; + case TCSETSF2: + case TCSETSW2: + case TCSETS2: + CHECK_BUF_IN(sizeof(struct termios2)); + memcpy(tio, in_buf, in_bufsz); + byte4 = htonl(_tio2_baud(tio)); + break; + } telnet_rfc2217_cfg(tty->tn, TNS_SET_BAUDRATE, &byte4, 4); byte = _tio_csize(tio); @@ -816,10 +852,22 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg, telnet_rfc2217_ctl(tty->tn, TNS_CTL_DTR_ON); } - _show_termios("TCSETS", tio); + switch (cmd) + { + case TCSETSF: + case TCSETSW: + case TCSETS: + _show_termios("TCSETS", tio); + break; + case TCSETSF2: + case TCSETSW2: + case TCSETS2: + _show_termios2("TCSETS2", tio); + break; + } ioctl(tty->fds[FD_SLAVE].fd, cmd, tio); - if (cmd == TCSETSF) + if (cmd == TCSETSF || cmd == TCSETSF2) tty->slave_suspended = 0; /* Re-enable polling of Slave */ fuse_reply_ioctl(req, 0, 0, 0); @@ -831,6 +879,12 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg, _show_termios("TCGETS", tio); fuse_reply_ioctl(req, 0, tio, sizeof(struct termios)); break; + case TCGETS2: + CHECK_BUF_OUT(sizeof(struct termios2)); + ioctl(tty->fds[FD_SLAVE].fd, TCGETS2, tio); + _show_termios2("TCGETS2", tio); + fuse_reply_ioctl(req, 0, tio, sizeof(struct termios2)); + break; case TIOCINQ: /* Get the number of bytes in the input * buffer */ CHECK_BUF_OUT(sizeof(int));