From 68ec29db5e728695590fbcfac19ef783d32c3ec5 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 22 Nov 2013 19:00:24 +0000 Subject: [PATCH] Check for termiox support at runtime. --- serialport.c | 198 +++++++++++++++++++++++++-------------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/serialport.c b/serialport.c index 9cef266..0f1b5a5 100644 --- a/serialport.c +++ b/serialport.c @@ -46,8 +46,7 @@ #include "linux/serial.h" #include "linux_termios.h" #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX) -// FIXME: Temporarily disabled, breaks all lib functionality on some systems. -// #define USE_TERMIOX +#define USE_TERMIOX #endif #endif @@ -59,10 +58,9 @@ struct port_data { #else struct termios term; int controlbits; -#ifdef USE_TERMIOX + int termiox_supported; int flow; #endif -#endif }; /* Standard baud rates. */ @@ -795,7 +793,16 @@ static enum sp_return get_config(struct sp_port *port, struct port_data *data, return SP_ERR_FAIL; #ifdef USE_TERMIOX - TRY(get_flow(port->fd, &data->flow)); + int ret = get_flow(port->fd, &data->flow); + + if (ret == SP_ERR_FAIL && errno == EINVAL) + data->termiox_supported = 0; + else if (ret < 0) + return ret; + else + data->termiox_supported = 1; +#else + data->termiox_supported = 0; #endif for (i = 0; i < NUM_STD_BAUDRATES; i++) { @@ -845,30 +852,22 @@ static enum sp_return get_config(struct sp_port *port, struct port_data *data, config->rts = SP_RTS_FLOW_CONTROL; config->cts = SP_CTS_FLOW_CONTROL; } else { -#ifdef USE_TERMIOX - if (data->flow & RTS_FLOW) + if (data->termiox_supported && data->flow & RTS_FLOW) config->rts = SP_RTS_FLOW_CONTROL; else config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF; - config->cts = (data->flow & CTS_FLOW) ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE; -#else - config->rts = (data->controlbits & TIOCM_RTS) ? SP_RTS_ON : SP_RTS_OFF; - config->cts = SP_CTS_IGNORE; -#endif + config->cts = (data->termiox_supported && data->flow & CTS_FLOW) ? + SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE; } -#ifdef USE_TERMIOX - if (data->flow & DTR_FLOW) + if (data->termiox_supported && data->flow & DTR_FLOW) config->dtr = SP_DTR_FLOW_CONTROL; else config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF; - config->dsr = (data->flow & DSR_FLOW) ? SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE; -#else - config->dtr = (data->controlbits & TIOCM_DTR) ? SP_DTR_ON : SP_DTR_OFF; - config->dsr = SP_DSR_IGNORE; -#endif + config->dsr = (data->termiox_supported && data->flow & DSR_FLOW) ? + SP_DSR_FLOW_CONTROL : SP_DSR_IGNORE; if (data->term.c_iflag & IXOFF) { if (data->term.c_iflag & IXON) @@ -1114,90 +1113,90 @@ static enum sp_return set_config(struct sp_port *port, struct port_data *data, } if (config->rts >= 0 || config->cts >= 0) { -#ifdef USE_TERMIOX - data->flow &= ~(RTS_FLOW | CTS_FLOW); - switch (config->rts) { - case SP_RTS_OFF: - case SP_RTS_ON: - controlbits = TIOCM_RTS; - if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0) - return SP_ERR_FAIL; - break; - case SP_RTS_FLOW_CONTROL: - data->flow |= RTS_FLOW; - break; - default: - break; - } - if (config->cts == SP_CTS_FLOW_CONTROL) - data->flow |= CTS_FLOW; - - if (data->flow & (RTS_FLOW | CTS_FLOW)) - data->term.c_iflag |= CRTSCTS; - else - data->term.c_iflag &= ~CRTSCTS; -#else - /* Asymmetric use of RTS/CTS not supported. */ - if (data->term.c_iflag & CRTSCTS) { - /* Flow control can only be disabled for both RTS & CTS together. */ - if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) { - if (config->cts != SP_CTS_IGNORE) - return SP_ERR_ARG; - } - if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) { - if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL) - return SP_ERR_ARG; - } - } else { - /* Flow control can only be enabled for both RTS & CTS together. */ - if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) || - ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL))) - return SP_ERR_ARG; - } - - if (config->rts >= 0) { - if (config->rts == SP_RTS_FLOW_CONTROL) { - data->term.c_iflag |= CRTSCTS; - } else { + if (data->termiox_supported) { + data->flow &= ~(RTS_FLOW | CTS_FLOW); + switch (config->rts) { + case SP_RTS_OFF: + case SP_RTS_ON: controlbits = TIOCM_RTS; - if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, + if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0) + return SP_ERR_FAIL; + break; + case SP_RTS_FLOW_CONTROL: + data->flow |= RTS_FLOW; + break; + default: + break; + } + if (config->cts == SP_CTS_FLOW_CONTROL) + data->flow |= CTS_FLOW; + + if (data->flow & (RTS_FLOW | CTS_FLOW)) + data->term.c_iflag |= CRTSCTS; + else + data->term.c_iflag &= ~CRTSCTS; + } else { + /* Asymmetric use of RTS/CTS not supported. */ + if (data->term.c_iflag & CRTSCTS) { + /* Flow control can only be disabled for both RTS & CTS together. */ + if (config->rts >= 0 && config->rts != SP_RTS_FLOW_CONTROL) { + if (config->cts != SP_CTS_IGNORE) + return SP_ERR_ARG; + } + if (config->cts >= 0 && config->cts != SP_CTS_FLOW_CONTROL) { + if (config->rts <= 0 || config->rts == SP_RTS_FLOW_CONTROL) + return SP_ERR_ARG; + } + } else { + /* Flow control can only be enabled for both RTS & CTS together. */ + if (((config->rts == SP_RTS_FLOW_CONTROL) && (config->cts != SP_CTS_FLOW_CONTROL)) || + ((config->cts == SP_CTS_FLOW_CONTROL) && (config->rts != SP_RTS_FLOW_CONTROL))) + return SP_ERR_ARG; + } + + if (config->rts >= 0) { + if (config->rts == SP_RTS_FLOW_CONTROL) { + data->term.c_iflag |= CRTSCTS; + } else { + controlbits = TIOCM_RTS; + if (ioctl(port->fd, config->rts == SP_RTS_ON ? TIOCMBIS : TIOCMBIC, + &controlbits) < 0) + return SP_ERR_FAIL; + } + } + } + } + + if (config->dtr >= 0 || config->dsr >= 0) { + if (data->termiox_supported) { + data->flow &= ~(DTR_FLOW | DSR_FLOW); + switch (config->dtr) { + case SP_DTR_OFF: + case SP_DTR_ON: + controlbits = TIOCM_DTR; + if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0) + return SP_ERR_FAIL; + break; + case SP_DTR_FLOW_CONTROL: + data->flow |= DTR_FLOW; + break; + default: + break; + } + if (config->dsr == SP_DSR_FLOW_CONTROL) + data->flow |= DSR_FLOW; + } else { + /* DTR/DSR flow control not supported. */ + if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL) + return SP_ERR_ARG; + + if (config->dtr >= 0) { + controlbits = TIOCM_DTR; + if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0) return SP_ERR_FAIL; } } -#endif - } - - if (config->dtr >= 0 || config->dsr >= 0) { -#ifdef USE_TERMIOX - data->flow &= ~(DTR_FLOW | DSR_FLOW); - switch (config->dtr) { - case SP_DTR_OFF: - case SP_DTR_ON: - controlbits = TIOCM_DTR; - if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, &controlbits) < 0) - return SP_ERR_FAIL; - break; - case SP_DTR_FLOW_CONTROL: - data->flow |= DTR_FLOW; - break; - default: - break; - } - if (config->dsr == SP_DSR_FLOW_CONTROL) - data->flow |= DSR_FLOW; -#else - /* DTR/DSR flow control not supported. */ - if (config->dtr == SP_DTR_FLOW_CONTROL || config->dsr == SP_DSR_FLOW_CONTROL) - return SP_ERR_ARG; - - if (config->dtr >= 0) { - controlbits = TIOCM_DTR; - if (ioctl(port->fd, config->dtr == SP_DTR_ON ? TIOCMBIS : TIOCMBIC, - &controlbits) < 0) - return SP_ERR_FAIL; - } -#endif } if (config->xon_xoff >= 0) { @@ -1235,7 +1234,8 @@ static enum sp_return set_config(struct sp_port *port, struct port_data *data, if (baud_nonstd) TRY(set_baudrate(port->fd, config->baudrate)); #ifdef USE_TERMIOX - TRY(set_flow(port->fd, data->flow)); + if (data->termiox_supported) + TRY(set_flow(port->fd, data->flow)); #endif #endif