From: mdw Date: Wed, 30 Jan 2002 09:24:24 +0000 (+0000) Subject: Restructure for new transport configuration interface. X-Git-Url: https://git.distorted.org.uk/~mdw/jog/commitdiff_plain/f43b77485dde4c40c7bee6975f0b020095fa7dfc Restructure for new transport configuration interface. --- diff --git a/tx-serial-unix.c b/tx-serial-unix.c index 3d45d9b..edb048e 100644 --- a/tx-serial-unix.c +++ b/tx-serial-unix.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: tx-serial-unix.c,v 1.1 2002/01/25 19:34:45 mdw Exp $ + * $Id: tx-serial-unix.c,v 1.2 2002/01/30 09:24:24 mdw Exp $ * * Unix/POSIX serial transport * @@ -29,6 +29,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: tx-serial-unix.c,v $ + * Revision 1.2 2002/01/30 09:24:24 mdw + * Restructure for new transport configuration interface. + * * Revision 1.1 2002/01/25 19:34:45 mdw * Initial revision * @@ -65,14 +68,15 @@ typedef struct txsu { txport tx; /* Transport base */ struct txsu *next, **prev; /* Chain of serial transports */ int fd; /* File descriptor */ - struct termios old_ta; /* Old terminal settings */ + serial_config sc; /* Internal serial config */ + struct termios ta, old_ta; /* External serial configs */ } txsu; /*----- Static variables --------------------------------------------------*/ struct baudmap { unsigned long baud; unsigned long magic; }; -static struct baudmap baudmap[] = { +static const struct baudmap baudmap[] = { #ifdef B50 { 50, B50 }, #endif @@ -153,91 +157,109 @@ void txsu_shutdown(void) tcsetattr(tx->fd, TCSAFLUSH, &tx->old_ta); } +/* --- @setconfig@ --- * + * + * Arguments: @txsu *tx@ = pointer to serial transport + * @serial_config *sc@ = pointer to configuration to set + * + * Returns: Zero if OK, nonzero on error. + * + * Use: Updates the external configuration from an internal + * representation. + */ + +static int setconfig(txsu *tx, serial_config *sc) +{ + struct termios *ta = &tx->ta; + const struct baudmap *b; + + for (b = baudmap; b->baud && b->baud != sc->baud; b++) + ; + if (!b->baud || + sc->wordlen < 5 || sc->wordlen > 8 || + sc->stopbits < 1 || sc->stopbits > 2) { + err_report(ERR_TXPORT, ERRTX_CONFIG, 0, "bad serial configuration"); + return (-1); + } + + ta->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); + ta->c_oflag &= ~OPOST; + ta->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + ta->c_cc[VMIN] = 1; + ta->c_cc[VTIME] = 0; + + cfsetospeed(ta, b->magic); + cfsetispeed(ta, b->magic); + ta->c_cflag = (ta->c_cflag & ~CSIZE) | csize[sc->wordlen - 5]; + switch (sc->parity) { + case PARITY_NONE: ta->c_cflag &= ~PARENB; break; + case PARITY_ODD: ta->c_cflag |= PARENB | PARODD; break; + case PARITY_EVEN: ta->c_cflag |= PARENB; ta->c_cflag &= ~PARODD; break; + } + switch (sc->stopbits) { + case 1: ta->c_cflag &= ~CSTOPB; break; + case 2: ta->c_cflag |= CSTOPB; break; + } + + switch (sc->flow) { + case FLOW_NONE: + ta->c_cflag &= ~CRTSCTS; + ta->c_iflag &= ~(IXON | IXOFF); + break; + case FLOW_XONXOFF: + ta->c_cflag &= ~CRTSCTS; + ta->c_iflag |= IXON | IXOFF; + break; + case FLOW_RTSCTS: + ta->c_cflag |= CRTSCTS; + ta->c_iflag &= ~(IXON | IXOFF); + break; + } + + if (tcsetattr(tx->fd, TCSAFLUSH, ta)) { + err_report(ERR_TXPORT, ERRTX_CREATE, errno, + "couldn't set terminal attributes: %s", strerror(errno)); + return (-1); + } + + tx->sc = *sc; + return (0); +} + /* --- @txsu_create@ --- * * * Arguments: @const char *file@ = filename for serial port - * @const char *config@ = configuration string * * Returns: Pointer to created transport block. * * Use: Creates a serial port transport. */ -txport *txsu_create(const char *file, const char *config) +txport *txsu_create(const char *file) { - txsu *tx; + txsu *tx = CREATE(txsu); serial_config sc = SERIAL_INIT; - struct termios ta, old_ta; - struct baudmap *b; - int fd; - - /* --- Parse the configuration and check it --- */ - if (config && *config && serial_parse(config, &sc)) - goto conferr; - - for (b = baudmap; b->baud && b->baud != sc.baud; b++) - ; - if (!b->baud || - sc.wordlen < 5 || sc.wordlen > 8 || - sc.stopbits < 1 || sc.stopbits > 2) - goto conferr; - - /* --- Open the serial port and fetch attributes --- */ - - if ((fd = open(file, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) { + if ((tx->fd = open(file, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) { err_report(ERR_TXPORT, ERRTX_CREATE, errno, "couldn't open device `%s': %s", file, strerror(errno)); goto fail_0; } - if (fdflags(fd, O_NONBLOCK, 0, 0, 0)) { + if (fdflags(tx->fd, O_NONBLOCK, 0, 0, 0)) { err_report(ERR_TXPORT, ERRTX_CREATE, errno, "fcntl(clear O_NONBLOCK): %s", file, strerror(errno)); goto fail_1; - } + } - if (tcgetattr(fd, &ta)) { + if (tcgetattr(tx->fd, &tx->old_ta)) { err_report(ERR_TXPORT, ERRTX_CREATE, errno, "couldn't get terminal attributes: %s", strerror(errno)); goto fail_1; } - old_ta = ta; - - /* --- Fix the attributes --- */ - - ta.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); - ta.c_oflag &= ~OPOST; - ta.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); - ta.c_cflag &= ~(CRTSCTS); - ta.c_cc[VMIN] = 1; - ta.c_cc[VTIME] = 0; - - cfsetospeed(&ta, b->magic); - cfsetispeed(&ta, b->magic); - ta.c_cflag = (ta.c_cflag & ~CSIZE) | csize[sc.wordlen - 5]; - switch (sc.parity) { - case PARITY_NONE: ta.c_cflag &= ~PARENB; break; - case PARITY_ODD: ta.c_cflag |= PARENB | PARODD; break; - case PARITY_EVEN: ta.c_cflag |= PARENB; ta.c_cflag &= ~PARODD; break; - } - switch (sc.stopbits) { - case 1: ta.c_cflag &= ~CSTOPB; break; - case 2: ta.c_cflag |= CSTOPB; break; - } - - /* --- Set attributes --- */ - - if (tcsetattr(fd, TCSAFLUSH, &ta)) { - err_report(ERR_TXPORT, ERRTX_CREATE, errno, - "couldn't set terminal attributes: %s", strerror(errno)); + tx->ta = tx->old_ta; + if (setconfig(tx, &sc)) goto fail_1; - } - - /* --- Done --- */ - tx = CREATE(txsu); - tx->fd = fd; - tx->old_ta = old_ta; tx->next = active; tx->prev = &active; active = tx; @@ -246,14 +268,41 @@ txport *txsu_create(const char *file, const char *config) /* --- Tidy up because it all went horribly wrong --- */ fail_1: - close(fd); + close(tx->fd); fail_0: + DESTROY(tx); return (0); +} -conferr: - err_report(ERR_TXPORT, ERRTX_CONFIG, 0, - "bad configuration for serial port transport"); - goto fail_0; +/* --- @txsu_configure@ --- * + * + * Arguments: @txport *txg@ = pointer to transport block + * @const char *k@ = configuration keyword + * @const char *v@ = value + * + * Returns: Nonzero if handled, zero otherwise. + * + * Use: Configures a serial port. + */ + +int txsu_configure(txport *txg, const char *k, const char *v) +{ + txsu *tx = (txsu *)txg; + serial_config sc = tx->sc; + + if (!v) { + err_report(ERR_TXPORT, ERRTX_CONFIG, 0, + "syntax error in serial config `%s'", k); + return (-1); + } + if (serial_parse(&sc, k, v)) { + err_report(ERR_TXPORT, ERRTX_CONFIG, 0, + "syntax error in serial config `%s=%s'", k, v); + return (-1); + } + if (setconfig(tx, &sc)) + return (-1); + return (1); } /* --- @txsu_write@ --- *