]> rtime.felk.cvut.cz Git - sojka/sterm.git/blobdiff - sterm.c
Update changelog for 20150821 release
[sojka/sterm.git] / sterm.c
diff --git a/sterm.c b/sterm.c
index 2402c95dbd3e1c5ae19b0d7d184cb9d9fe62a075..c075f8b73bcfe913624fd13a1f7ca32d5cd021aa 100644 (file)
--- a/sterm.c
+++ b/sterm.c
@@ -1,7 +1,7 @@
 /*
  * Simple serial terminal
  *
- * Copyright 2014 Michal Sojka <sojkam1@fel.cvut.cz>
+ * Copyright 2014, 2015 Michal Sojka <sojkam1@fel.cvut.cz>
  *
  * This program is free software: you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -85,12 +85,17 @@ int dtr_rts_arg(const char option)
        int val = -1;
 
        if (optarg) {
-               switch (optarg[0]) {
-               case '+': val = +1; break;
-               case '-': val = -1; break;
-               default:
-                       fprintf(stderr, "Unknown -%c argument: %s", option, optarg);
-                       exit(1);
+               char *end;
+               val = strtol(optarg, &end, 10);
+               if (end == optarg) {
+                       /* Not a number */
+                       switch (optarg[0]) {
+                       case '+': val = +1; break;
+                       case '-': val = -1; break;
+                       default:
+                               fprintf(stderr, "Unknown -%c argument: %s", option, optarg);
+                               exit(1);
+                       }
                }
        }
        return val;
@@ -101,27 +106,35 @@ void exit_on_escapeseq(const char *buf, int len)
        static const char escseq[] = "\r~.";
        static const char *state = escseq+1;
        int i;
-
        for (i = 0; i < len; i++) {
                if (buf[i] == *state) {
                        state++;
                        if (*state == 0)
                                exit(0);
-               } else
+               } else {
                        state = escseq;
+                       if (buf[i] == *state)
+                               state++;
+               }
        }
 }
 
 void usage(const char* argv0)
 {
        fprintf(stderr, "Usage: %s [options] <device>\n", argv0);
-       fprintf(stderr, "Options:\n");
-       fprintf(stderr, "  -d [+|-] create short positive/negative pulse on DTR\n");
-       fprintf(stderr, "  -e       ignore '~.' escape sequence\n");
-       fprintf(stderr, "  -n       do not switch the device to raw mode\n");
-       fprintf(stderr, "  -r [+|-] create short positive/negative pulse on RTS\n");
-       fprintf(stderr, "  -s <baudrate>\n");
-       fprintf(stderr, "  -v       verbose\n");
+       fprintf(stderr,
+               "Options:\n"
+               "  -d[PULSE] make pulse on DTR\n"
+               "  -e        ignore '~.' escape sequence\n"
+               "  -n        do not switch the device to raw mode\n"
+               "  -r[PULSE] make pulse on RTS\n"
+               "  -s <baudrate>\n"
+               "\n"
+               "PULSE is a number specifying the pulse. Absolute value defines the\n"
+               "length of the pulse in milliseconds, sign determines the polarity of\n"
+               "the pulse. Alternatively, PULSE can be either '+' or '-', which\n"
+               "corresponds to +1 or -1.\n"
+               );
 }
 
 int main(int argc, char *argv[])
@@ -207,10 +220,14 @@ int main(int argc, char *argv[])
        }
        atexit(unlock);
 
-       if ((fd = open(dev, O_RDWR)) < 0) {
+       /* O_NONBLOCK is needed to not wait for the CDC signal. See tty_ioctl(4). */
+       if ((fd = open(dev, O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0) {
                perror(dev);
                exit(1);
        }
+        /* Cancel the efect of O_NONBLOCK flag. */
+       int n = fcntl(fd, F_GETFL, 0);
+        fcntl(fd, F_SETFL, n & ~O_NDELAY);
 
        if (isatty(fd)) {
                CHECK(ioctl(fd, TIOCEXCL, NULL));
@@ -225,17 +242,30 @@ int main(int argc, char *argv[])
                }
 
                if (dtr || rts) {
-                       int status;
+                       int status, ms = 0;
                        /* tio.c_cflag &= ~HUPCL; */ /* Don't lower DTR/RTS on close */
 
                        CHECK(ioctl(fd, TIOCMGET, &status));
-                       if (dtr == -1) status &= ~TIOCM_DTR;
-                       if (dtr == +1) status |=  TIOCM_DTR;
-                       if (rts == -1) status &= ~TIOCM_RTS;
-                       if (rts == +1) status |=  TIOCM_RTS;
+                       if (dtr > 0) { status &= ~TIOCM_DTR; ms = +dtr; }
+                       if (dtr < 0) { status |=  TIOCM_DTR; ms = -dtr; }
+                       if (rts > 0) { status &= ~TIOCM_RTS; ms = +rts; }
+                       if (rts < 0) { status |=  TIOCM_RTS; ms = -rts; }
                        CHECK(ioctl(fd, TIOCMSET, &status));
+
+                       usleep(ms*1000);
+
+                       if (dtr < 0) { status &= ~TIOCM_DTR; }
+                       if (dtr > 0) { status |=  TIOCM_DTR; }
+                       if (rts < 0) { status &= ~TIOCM_RTS; }
+                       if (rts > 0) { status |=  TIOCM_RTS; }
+                       CHECK(ioctl(fd, TIOCMSET, &status));
+
                }
 
+                /* Disable flow control */
+               tio.c_cflag &= ~(CRTSCTS);
+               tio.c_iflag &= ~(IXON|IXOFF);
+
                CHECK(tcsetattr(fd, TCSANOW, &tio));
        } else if (speed || dtr || rts) {
                fprintf(stderr, "Cannot set speed, DTR or RTS on non-terminal %s\n", dev);