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:
+67
-13
@@ -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));
|
||||||
|
|||||||
Reference in New Issue
Block a user