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

Better flowcntrl parsing/setting for RFC2217 ports

Use the same code to parse the flow-control setting from a termios
structure and to write the flow-control settings to a termios structure
for both: native and RFC2217 ports.
This commit is contained in:
Nick Patavalis
2018-02-19 01:04:08 +02:00
parent 35b992a344
commit df6b4a6d8a
3 changed files with 81 additions and 68 deletions

109
term.c
View File

@ -1234,82 +1234,75 @@ term_get_stopbits (int fd)
/***************************************************************************/
int
tios_set_flowcntrl(struct termios *tios, enum flowcntrl_e flowcntl)
{
int rval = 0;
switch (flowcntl) {
case FC_RTSCTS:
tios->c_cflag |= CRTSCTS;
tios->c_iflag &= ~(IXON | IXOFF | IXANY);
break;
case FC_XONXOFF:
tios->c_cflag &= ~(CRTSCTS);
tios->c_iflag |= IXON | IXOFF;
break;
case FC_NONE:
tios->c_cflag &= ~(CRTSCTS);
tios->c_iflag &= ~(IXON | IXOFF | IXANY);
break;
default:
term_errno = TERM_EFLOW;
rval = -1;
break;
}
return rval;
}
int
term_set_flowcntrl (int fd, enum flowcntrl_e flowcntl)
{
int rval;
struct term_s *t;
struct termios *tiop;
rval = 0;
t = term_find(fd);
if ( ! t ) return -1;
do { /* dummy */
return tios_set_flowcntrl(&t->nexttermios, flowcntl);
}
t = term_find(fd);
if ( ! t ) {
rval = -1;
break;
}
enum flowcntrl_e
tios_get_flowcntrl(const struct termios *tios)
{
enum flowcntrl_e flow;
int rtscts, xoff, xon;
tiop = &t->nexttermios;
rtscts = (tios->c_cflag & CRTSCTS) ? 1 : 0;
xoff = (tios->c_iflag & IXOFF) ? 1 : 0;
xon = (tios->c_iflag & (IXON | IXANY)) ? 1 : 0;
switch (flowcntl) {
case FC_RTSCTS:
tiop->c_cflag |= CRTSCTS;
tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
break;
case FC_XONXOFF:
tiop->c_cflag &= ~(CRTSCTS);
tiop->c_iflag |= IXON | IXOFF;
break;
case FC_NONE:
tiop->c_cflag &= ~(CRTSCTS);
tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
break;
default:
term_errno = TERM_EFLOW;
rval = -1;
break;
}
if ( rval < 0 ) break;
if ( rtscts && ! xoff && ! xon ) {
flow = FC_RTSCTS;
} else if ( ! rtscts && xoff && xon ) {
flow = FC_XONXOFF;
} else if ( ! rtscts && ! xoff && ! xon ) {
flow = FC_NONE;
} else {
flow = FC_OTHER;
}
} while (0);
return rval;
return flow;
}
enum flowcntrl_e
term_get_flowcntrl (int fd)
{
struct term_s *t;
enum flowcntrl_e flow;
int rtscts, xoff, xon;
do { /* dummy */
t = term_find(fd);
if ( ! t ) return FC_ERROR;
t = term_find(fd);
if ( ! t ) {
flow = FC_ERROR;
break;
}
rtscts = (t->currtermios.c_cflag & CRTSCTS) ? 1 : 0;
xoff = (t->currtermios.c_iflag & IXOFF) ? 1 : 0;
xon = (t->currtermios.c_iflag & (IXON | IXANY)) ? 1 : 0;
if ( rtscts && ! xoff && ! xon ) {
flow = FC_RTSCTS;
} else if ( ! rtscts && xoff && xon ) {
flow = FC_XONXOFF;
} else if ( ! rtscts && ! xoff && ! xon ) {
flow = FC_NONE;
} else {
flow = FC_OTHER;
}
} while (0);
return flow;
return tios_get_flowcntrl(&t->currtermios);
}
/***************************************************************************/

View File

@ -26,6 +26,7 @@
#define TERMINT_H
#include <termios.h>
#include "term.h"
struct term_s {
/* Read-only fields */
@ -55,6 +56,9 @@ struct term_ops {
int (*write)(struct term_s *t, const void *buf, unsigned bufsz);
};
enum flowcntrl_e tios_get_flowcntrl(const struct termios *tios);
int tios_set_flowcntrl(struct termios *tios, enum flowcntrl_e flowcntl);
#endif /* of TERMINT_H */
/***************************************************************************/

View File

@ -586,14 +586,25 @@ tn2217_send_set_stopsize(struct term_s *t, int c_flag)
/* Sends a SET-CONTROL message to control hardware flow control */
static void
tn2217_send_set_fc(struct term_s *t, int c_flag)
tn2217_send_set_fc(struct term_s *t, enum flowcntrl_e flow)
{
unsigned char val;
if (c_flag & CRTSCTS)
switch (flow) {
case FC_RTSCTS:
val = COMPORT_CONTROL_FC_HARDWARE;
else
fprintf(stderr,"--> FC_HARDWARE\r\n");
break;
case FC_XONXOFF:
val = COMPORT_CONTROL_FC_XONOFF;
fprintf(stderr,"--> FC_XONXOFF\r\n");
break;
case FC_NONE:
default:
val = COMPORT_CONTROL_FC_NONE;
fprintf(stderr,"--> FC_NONE\r\n");
break;
}
tn2217_send_comport_cmd1(t, COMPORT_SET_CONTROL, val);
}
@ -644,7 +655,7 @@ tn2217_comport_start(struct term_s *t)
tn2217_send_set_datasize(t, s->termios.c_cflag);
tn2217_send_set_parity(t, s->termios.c_cflag);
tn2217_send_set_stopsize(t, s->termios.c_cflag);
tn2217_send_set_fc(t, s->termios.c_cflag);
tn2217_send_set_fc(t, tios_get_flowcntrl(&s->termios));
} else {
/* If we're not going to specify it, ask for
* the current com port geometry. */
@ -782,14 +793,19 @@ tn2217_recv_comport_cmd(struct term_s *t, unsigned char cmd,
if (datalen >= 1) {
switch (data[0]) {
/* Flow control changes and COMPORT_CONTROL_FC_REQUEST reply */
case COMPORT_CONTROL_FC_NONE:
case COMPORT_CONTROL_FC_XONOFF:
fprintf(stderr, "[notified FC_XONXOFF]\r\n");
tios_set_flowcntrl(tio, FC_XONXOFF);
break;
case COMPORT_CONTROL_FC_HARDWARE:
fprintf(stderr, "[notified FC_RTSCTS]\r\n");
tios_set_flowcntrl(tio, FC_RTSCTS);
break;
case COMPORT_CONTROL_FC_NONE:
case COMPORT_CONTROL_FC_DCD:
case COMPORT_CONTROL_FC_DSR:
case COMPORT_CONTROL_FC_HARDWARE:
val = (data[0] == COMPORT_CONTROL_FC_HARDWARE ) ? CRTSCTS : 0;
tio->c_cflag &= ~CRTSCTS;
tio->c_cflag |= val;
fprintf(stderr, "[notified FC_NONE]\r\n");
tios_set_flowcntrl(tio, FC_NONE);
break;
/* DTR changes and COMPORT_CONTROL_DTR_REQUEST reply */
case COMPORT_CONTROL_DTR_ON:
@ -889,7 +905,7 @@ tn2217_tcsetattr(struct term_s *t, int when, const struct termios *tio)
tn2217_send_set_datasize(t, tio->c_cflag);
tn2217_send_set_parity(t, tio->c_cflag);
tn2217_send_set_stopsize(t, tio->c_cflag);
tn2217_send_set_fc(t, tio->c_cflag);
tn2217_send_set_fc(t, tios_get_flowcntrl(tio));
} else
s->set_termios = 1;
return 0;