X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/9a41f8d3877bc717e3eec330637122c390dc4240..038ec85e825fc940c1387f64a88ae73b75f6822b:/unix/uxser.c diff --git a/unix/uxser.c b/unix/uxser.c index d6471084..e45f3ae1 100644 --- a/unix/uxser.c +++ b/unix/uxser.c @@ -60,10 +60,10 @@ static int serial_select_result(int fd, int event); static void serial_uxsel_setup(Serial serial); static void serial_try_write(Serial serial); -static const char *serial_configure(Serial serial, Config *cfg) +static const char *serial_configure(Serial serial, Conf *conf) { struct termios options; - int bflag, bval; + int bflag, bval, speed, flow, parity; const char *str; char *msg; @@ -75,8 +75,9 @@ static const char *serial_configure(Serial serial, Config *cfg) /* * Find the appropriate baud rate flag. */ + speed = conf_get_int(conf, CONF_serspeed); #define SETBAUD(x) (bflag = B ## x, bval = x) -#define CHECKBAUD(x) do { if (cfg->serspeed >= x) SETBAUD(x); } while (0) +#define CHECKBAUD(x) do { if (speed >= x) SETBAUD(x); } while (0) SETBAUD(50); #ifdef B75 CHECKBAUD(75); @@ -129,9 +130,51 @@ static const char *serial_configure(Serial serial, Config *cfg) #ifdef B115200 CHECKBAUD(115200); #endif +#ifdef B153600 + CHECKBAUD(153600); +#endif #ifdef B230400 CHECKBAUD(230400); #endif +#ifdef B307200 + CHECKBAUD(307200); +#endif +#ifdef B460800 + CHECKBAUD(460800); +#endif +#ifdef B500000 + CHECKBAUD(500000); +#endif +#ifdef B576000 + CHECKBAUD(576000); +#endif +#ifdef B921600 + CHECKBAUD(921600); +#endif +#ifdef B1000000 + CHECKBAUD(1000000); +#endif +#ifdef B1152000 + CHECKBAUD(1152000); +#endif +#ifdef B1500000 + CHECKBAUD(1500000); +#endif +#ifdef B2000000 + CHECKBAUD(2000000); +#endif +#ifdef B2500000 + CHECKBAUD(2500000); +#endif +#ifdef B3000000 + CHECKBAUD(3000000); +#endif +#ifdef B3500000 + CHECKBAUD(3500000); +#endif +#ifdef B4000000 + CHECKBAUD(4000000); +#endif #undef CHECKBAUD #undef SETBAUD cfsetispeed(&options, bflag); @@ -141,18 +184,19 @@ static const char *serial_configure(Serial serial, Config *cfg) sfree(msg); options.c_cflag &= ~CSIZE; - switch (cfg->serdatabits) { + switch (conf_get_int(conf, CONF_serdatabits)) { case 5: options.c_cflag |= CS5; break; case 6: options.c_cflag |= CS6; break; case 7: options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: return "Invalid number of data bits (need 5, 6, 7 or 8)"; } - msg = dupprintf("Configuring %d data bits", cfg->serdatabits); + msg = dupprintf("Configuring %d data bits", + conf_get_int(conf, CONF_serdatabits)); logevent(serial->frontend, msg); sfree(msg); - if (cfg->serstopbits >= 4) { + if (conf_get_int(conf, CONF_serstopbits) >= 4) { options.c_cflag |= CSTOPB; } else { options.c_cflag &= ~CSTOPB; @@ -169,10 +213,11 @@ static const char *serial_configure(Serial serial, Config *cfg) #ifdef CNEW_RTSCTS options.c_cflag &= ~CNEW_RTSCTS; #endif - if (cfg->serflow == SER_FLOW_XONXOFF) { + flow = conf_get_int(conf, CONF_serflow); + if (flow == SER_FLOW_XONXOFF) { options.c_iflag |= IXON | IXOFF; str = "XON/XOFF"; - } else if (cfg->serflow == SER_FLOW_RTSCTS) { + } else if (flow == SER_FLOW_RTSCTS) { #ifdef CRTSCTS options.c_cflag |= CRTSCTS; #endif @@ -187,11 +232,12 @@ static const char *serial_configure(Serial serial, Config *cfg) sfree(msg); /* Parity */ - if (cfg->serparity == SER_PAR_ODD) { + parity = conf_get_int(conf, CONF_serparity); + if (parity == SER_PAR_ODD) { options.c_cflag |= PARENB; options.c_cflag |= PARODD; str = "odd"; - } else if (cfg->serparity == SER_PAR_EVEN) { + } else if (parity == SER_PAR_EVEN) { options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; str = "even"; @@ -214,7 +260,16 @@ static const char *serial_configure(Serial serial, Config *cfg) #ifdef ONLCR | ONLCR #endif - | OCRNL | ONOCR | ONLRET); +#ifdef OCRNL + | OCRNL +#endif +#ifdef ONOCR + | ONOCR +#endif +#ifdef ONLRET + | ONLRET +#endif + ); options.c_cc[VMIN] = 1; options.c_cc[VTIME] = 0; @@ -233,12 +288,13 @@ static const char *serial_configure(Serial serial, Config *cfg) * freed by the caller. */ static const char *serial_init(void *frontend_handle, void **backend_handle, - Config *cfg, + Conf *conf, char *host, int port, char **realhost, int nodelay, int keepalive) { Serial serial; const char *err; + char *line; serial = snew(struct serial_backend_data); *backend_handle = serial; @@ -248,20 +304,24 @@ static const char *serial_init(void *frontend_handle, void **backend_handle, serial->inbufsize = 0; bufchain_init(&serial->output_data); + line = conf_get_str(conf, CONF_serline); { - char *msg = dupprintf("Opening serial device %s", cfg->serline); + char *msg = dupprintf("Opening serial device %s", line); logevent(serial->frontend, msg); + sfree(msg); } - serial->fd = open(cfg->serline, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); + serial->fd = open(line, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); if (serial->fd < 0) return "Unable to open serial port"; - err = serial_configure(serial, cfg); + cloexec(serial->fd); + + err = serial_configure(serial, conf); if (err) return err; - *realhost = dupstr(cfg->serline); + *realhost = dupstr(line); if (!serial_by_fd) serial_by_fd = newtree234(serial_compare_by_fd); @@ -296,16 +356,14 @@ static void serial_free(void *handle) sfree(serial); } -static void serial_reconfig(void *handle, Config *cfg) +static void serial_reconfig(void *handle, Conf *conf) { Serial serial = (Serial) handle; - const char *err; - - err = serial_configure(serial, cfg); /* - * FIXME: what should we do if err returns something? + * FIXME: what should we do if this returns an error? */ + serial_configure(serial, conf); } static int serial_select_result(int fd, int event) @@ -331,6 +389,14 @@ static int serial_select_result(int fd, int event) */ finished = TRUE; } else if (ret < 0) { +#ifdef EAGAIN + if (errno == EAGAIN) + return 1; /* spurious */ +#endif +#ifdef EWOULDBLOCK + if (errno == EWOULDBLOCK) + return 1; /* spurious */ +#endif perror("read serial port"); exit(1); } else if (ret > 0) { @@ -525,5 +591,7 @@ Backend serial_backend = { serial_provide_logctx, serial_unthrottle, serial_cfg_info, - 1 + "serial", + PROT_SERIAL, + 0 };