#include #include #include #include #include #include #include #include #include #include #include volatile int quit; static void set_quit(int s) { quit = 1; } static void readline(int d, char *buf, int l) { int i; int bytes; do { for (i = 0; i < l; i++) { do { bytes = read(d, &buf[i], 1); if (quit) return; } while ((bytes < 0 && errno == EAGAIN) || buf[i] == '\r'); if (bytes != 1) { fprintf(stderr, "readline: read %d\n", bytes); err(1, "read line"); } if (buf[i] == '\n') break; } } while (i == 0); if (buf[i] != '\n') { errx(1, "realine: end of line not found"); } buf[i] = '\0'; } int main(int argc, const char *argv[]) { int d; int bytes; int nfds; char buf[256]; int i; fd_set rfds; char gpio[3], current[4], tension[4]; char *endp; int gpioi, currenti, tensioni; int gpioval, currentval, tensionval; int exitst = 0; enum { INIT, GPIO, CURRENT, TENSION, MARK } state; struct termios t, ot; state = INIT; gpioi = currenti = tensioni = 0; if (argc != 3) { errx(1, "usage: %s time", argv[0]); } d = open(argv[1], O_RDWR | O_NOCTTY | O_NONBLOCK, 0); if (d < 0) { err(1, "open %s", argv[1]); } fprintf(stderr, "o\n"); if (tcgetattr(d, &ot) < 0) { err(1, "tcgetattr"); } fprintf(stderr, "tg\n"); quit = 0; if (signal(SIGINT, set_quit) == SIG_ERR) { err(1, "signal(SIGINT)"); } if (signal(SIGQUIT, set_quit) == SIG_ERR) { err(1, "signal(SIGQUIT)"); } if (signal(SIGPIPE, set_quit) == SIG_ERR) { err(1, "signal(SIGPIPE)"); } if (signal(SIGTERM, set_quit) == SIG_ERR) { err(1, "signal(SIGTERM)"); } if (signal(SIGALRM, set_quit) == SIG_ERR) { err(1, "signal(SIGALRM)"); } t = ot; cfmakeraw(&t); t.c_cflag |= CLOCAL; t.c_cflag &= ~CRTSCTS; cfsetspeed(&t, B921600); if (tcsetattr(d, TCSANOW | TCSAFLUSH, &t) < 0) { err(1, "tcsetattr"); } fprintf(stderr, "tty ready\n"); write(d, "M0\n", 3); write(d, "M0\n", 3); do { readline(d, buf, sizeof(buf)); if (quit) goto quit; } while (memcmp(buf, "OK", 2) != 0); fprintf(stderr, "starting\n"); write(d, "M1\n", 3); alarm(atoi(argv[2])); FD_ZERO(&rfds); while (quit == 0) { FD_SET(d, &rfds); nfds = select(d+1, &rfds, NULL, NULL, NULL); if (nfds > 0 && FD_ISSET(d, &rfds)) { bytes = read(d, buf, sizeof(buf)); if (bytes > sizeof(buf)) { errx(1, "read %d/0x%x bytes", bytes, bytes); } if (bytes < 0 && errno != EAGAIN) { warn("read"); continue; } for (i = 0; i < bytes; i++) { if (i > sizeof(buf)) abort(); if (bytes > sizeof(buf)) abort(); if (gpioi > sizeof(buf)) abort(); if (tensioni > sizeof(buf)) abort(); if (currenti > sizeof(buf)) abort(); switch(state) { case INIT: /* look for an X mark */ if (buf[i] == 'X') { state = GPIO; gpioi = 0; } break; case GPIO: gpio[gpioi] = buf[i]; gpioi++; if (gpioi < 2) break; gpio[gpioi] = '\0'; gpioval = strtol(gpio, &endp, 16); if (*endp != '\0') { fprintf(stderr, "gpio error: %c\n", *endp); exitst = 1; state = INIT; } else { state = TENSION; tensioni = 0; } break; case CURRENT: current[currenti] = buf[i]; currenti++; if (currenti < 3) break; current[currenti] = '\0'; currentval = strtol(current, &endp, 16); if (*endp != '\0') { fprintf(stderr, "current error: %c\n", *endp); exitst = 1; state = INIT; } else { state = MARK; tensioni = 0; } break; case TENSION: tension[tensioni] = buf[i]; tensioni++; if (tensioni < 3) break; tension[tensioni] = '\0'; tensionval = strtol(tension, &endp, 16); if (*endp != '\0') { fprintf(stderr, "tension error: %c\n", *endp); exitst = 1; state = INIT; } else { state = CURRENT; currenti = 0; } break; case MARK: if (buf[i] != 'X') { fprintf(stderr, "mark error: %c\n", buf[i]); exitst = 1; state = INIT; } else { printf("%3d ", gpioval); printf("%4d ", tensionval); printf("%4d\n", currentval); state = GPIO; gpioi = 0; } break; } } } else if (nfds < 0) { warn("select"); } } quit: /* stop measures */ write(d, "M0\n", 3); if (fflush(stdout) == EOF) { warn("fflush"); } if (tcsetattr(d, TCSANOW, &ot) < 0) { err(1, "restore tcsetattr"); } exit(exitst); }