Restructure for new transport configuration interface.
authormdw <mdw>
Wed, 30 Jan 2002 09:24:24 +0000 (09:24 +0000)
committermdw <mdw>
Wed, 30 Jan 2002 09:24:24 +0000 (09:24 +0000)
tx-serial-unix.c

index 3d45d9b..edb048e 100644 (file)
@@ -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@ --- *