Add support for termios2 ioctls

Based on patch by Thomas Shaddack <shaddack@shaddack.mauriceward.com>
https://www.improwis.com/projects/sw_SerialOverIP_RFC2217/
This commit is contained in:
Kim Woelders
2021-01-13 19:20:16 +01:00
parent 33de2e875c
commit bf11b1dd15
+67 -13
View File
@@ -66,7 +66,7 @@ typedef struct {
char net_buf[NET_BUF_SIZE]; char net_buf[NET_BUF_SIZE];
int net_cnt; int net_cnt;
struct termios tio; struct termios2 tio;
int cmcr; /* Commanded by ioctl */ int cmcr; /* Commanded by ioctl */
volatile int smcr; /* Status from modem */ volatile int smcr; /* Status from modem */
@@ -661,9 +661,13 @@ static const char *_ioctl_name(int cmd)
snprintf(buf, sizeof(buf), "0x%x", cmd); snprintf(buf, sizeof(buf), "0x%x", cmd);
return buf; return buf;
CASE(TCSETSF); CASE(TCSETSF);
CASE(TCSETSF2);
CASE(TCSETSW); CASE(TCSETSW);
CASE(TCSETSW2);
CASE(TCSETS); CASE(TCSETS);
CASE(TCSETS2);
CASE(TCGETS); CASE(TCGETS);
CASE(TCGETS2);
CASE(TIOCINQ); CASE(TIOCINQ);
CASE(TIOCOUTQ); CASE(TIOCOUTQ);
CASE(TCFLSH); 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; unsigned int par;
@@ -712,12 +716,17 @@ static unsigned int _tio_parity(const struct termios *tio)
return par; 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)); 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; unsigned int csize;
@@ -733,7 +742,7 @@ static unsigned int _tio_csize(const struct termios *tio)
return csize; return csize;
} }
static unsigned int _tio_stopb(const struct termios *tio) static unsigned int _tio_stopb(const struct termios2 *tio)
{ {
unsigned int stopb; unsigned int stopb;
@@ -745,7 +754,7 @@ static unsigned int _tio_stopb(const struct termios *tio)
return stopb; 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, DBG("%s: %u%c%u%u %cCTSRTS %cCREAD %cHUPCL %cCLOCAL\n", txt,
_tio_baud(tio), pstr[_tio_parity(tio)], _tio_csize(tio), _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 ? '+' : '-'); 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) \ #define CHECK_BUF_IN(sz) \
if (in_bufsz < sz) do { in_bufsz = sz; goto retry_in; } while(0) if (in_bufsz < sz) do { in_bufsz = sz; goto retry_in; } while(0)
#define CHECK_BUF_OUT(sz) \ #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) const void *in_buf, size_t in_bufsz, size_t out_bufsz)
{ {
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh; ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
struct termios *tio = &tty->tio; struct termios2 *tio = &tty->tio;
struct winsize ws; struct winsize ws;
unsigned int tiocm = 0; unsigned int tiocm = 0;
int mcr; int mcr;
@@ -783,11 +802,28 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
case TCSETSF: case TCSETSF:
case TCSETSW: case TCSETSW:
case TCSETS: 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); switch (cmd)
{
byte4 = htonl(_tio_baud(tio)); 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); telnet_rfc2217_cfg(tty->tn, TNS_SET_BAUDRATE, &byte4, 4);
byte = _tio_csize(tio); 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); 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); 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 */ tty->slave_suspended = 0; /* Re-enable polling of Slave */
fuse_reply_ioctl(req, 0, 0, 0); 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); _show_termios("TCGETS", tio);
fuse_reply_ioctl(req, 0, tio, sizeof(struct termios)); fuse_reply_ioctl(req, 0, tio, sizeof(struct termios));
break; 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 case TIOCINQ: /* Get the number of bytes in the input
* buffer */ * buffer */
CHECK_BUF_OUT(sizeof(int)); CHECK_BUF_OUT(sizeof(int));