diff --git a/picocom.c b/picocom.c index 96021a1..a01dc76 100644 --- a/picocom.c +++ b/picocom.c @@ -218,6 +218,7 @@ struct { int lower_dtr; int raise_rts; int raise_dtr; + int rs485; int quiet; } opts = { .port = NULL, @@ -248,6 +249,7 @@ struct { .lower_dtr = 0, .raise_rts = 0, .raise_dtr = 0, + .rs485 = 0, .quiet = 0 }; @@ -1657,6 +1659,7 @@ show_usage(char *name) printf(" --raise-rts\n"); printf(" --lower-dtr\n"); printf(" --raise-dtr\n"); + printf(" --rs485\n"); printf(" --uiet\n"); printf(" --elp\n"); printf(" is a comma-separated list of one or more of:\n"); @@ -1716,6 +1719,7 @@ parse_args(int argc, char *argv[]) {"lower-dtr", no_argument, 0, 2}, {"raise-rts", no_argument, 0, 3}, {"raise-dtr", no_argument, 0, 4}, + {"rs485", no_argument, 0, '4'}, {"quiet", no_argument, 0, 'q'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} @@ -1909,6 +1913,9 @@ parse_args(int argc, char *argv[]) case 'q': opts.quiet = 1; break; + case '4': + opts.rs485 = 1; + break; case 'h': show_usage(argv[0]); exit(EXIT_SUCCESS); @@ -1954,6 +1961,7 @@ parse_args(int argc, char *argv[]) printf("picocom v%s\n", VERSION_STR); printf("\n"); printf("port is : %s\n", opts.port); + printf("rs485 mode : %s\n", opts.rs485 ? "enabled" : "disabled"); printf("flowcontrol : %s\n", flow_str[opts.flow]); printf("baudrate is : %d\n", opts.baud); printf("parity is : %s\n", parity_str[opts.parity]); @@ -2098,6 +2106,15 @@ main (int argc, char *argv[]) /* Set DTR and RTS status, as quickly as possible after opening the serial port (i.e. before configuring it) */ set_dtr_rts(); + + if ( opts.rs485 ) + r = term_set_rs485(tty_fd, 1); + else + r = term_set_rs485(tty_fd, 0); + + if ( r < 0 ) + pinfo("!! failed to set rs485 mode !!"); + r = term_apply(tty_fd, 0); if ( r < 0 ) fatal("failed to config port: %s", diff --git a/term.c b/term.c index b45ab3d..b90e719 100644 --- a/term.c +++ b/term.c @@ -43,10 +43,14 @@ * CMSPAR, so we use the value from the generic bits/termios.h */ #ifdef __linux__ +#define USE_RS485 #ifndef CMSPAR #define CMSPAR 010000000000 #endif #endif +#ifdef USE_RS485 +#include +#endif /* Some BSDs (and possibly other systems too) have no mark / space * parity support, and they don't define CMSPAR. Use a zero CMSPAR in @@ -759,6 +763,56 @@ term_apply (int fd, int now) /***************************************************************************/ +int +term_set_rs485 (int fd, int status) +{ + int rval, i; + + rval = 0; + + do { /* dummy */ + + i = term_find(fd); + if ( i < 0 ) { + rval = -1; + break; + } + +#ifdef USE_RS485 +#ifdef USE_IOCTL + { + int r; + + struct serial_rs485 rs485conf; + memset(&rs485conf, 0x0, sizeof(struct serial_rs485)); + + if ( status == 1 ) { + rs485conf.flags |= SER_RS485_ENABLED; + rs485conf.flags |= SER_RS485_RTS_ON_SEND; + rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND); + } + + r = ioctl(fd, TIOCSRS485, &rs485conf); + if ( r < 0 ) { + rval = -1; + break; + } + } +#else + rval = -1; +#endif /* of USE_IOCTL */ +#else + /* If 485 not available return error only if trying to set 485 mode */ + if ( status == 1 ) + rval = -1 +#endif + } while (0); + + return rval; +} + +/***************************************************************************/ + int term_set_raw (int fd) { diff --git a/term.h b/term.h index 09acfe2..780a018 100644 --- a/term.h +++ b/term.h @@ -44,6 +44,7 @@ * F term_apply - configure a device to the settings in "nexttermios" * F term_revert - discard "nexttermios" by copying-over "currtermios" * F term_refresh - update "currtermios" from the device + * F term_set_rs485 - set the rs485 mode of a device * F term_set_raw - set "nexttermios" to raw mode * F term_set_baudrate - set the baudrate in "nexttermios" * F term_set_parity - set the parity mode in "nexttermios" @@ -383,6 +384,14 @@ int term_reset (int fd); */ int term_refresh (int fd); +/* F term_set_rs485 + * + * Sets the managed filedes "fd" to rs485 mode. + * + * Returns negative on failure, non-negative on success. + */ +int term_set_rs485 (int fd, int status); + /* F term_set_raw * * Sets the "nexttermios" structure associated with the managed