Annotation of nono/util/autoserial/autoserial.cpp, revision 1.1.1.2

1.1       root        1: #include "header.h"
                      2: #include "autofd.h"
                      3: #include "kevent.h"
                      4: #include <queue>
                      5: #include <string>
                      6: #include <vector>
                      7: #include <err.h>
                      8: #include <fcntl.h>
                      9: #include <stdio.h>
                     10: #include <stdint.h>
                     11: #include <stdlib.h>
                     12: #include <termios.h>
                     13: #include <time.h>
                     14: #include <unistd.h>
                     15: 
                     16: 
                     17: //#define DEFAULT_DEV "/dev/ttyS0"
                     18: #define DEFAULT_DEV "/dev/dty00"
                     19: 
                     20: // ナノ秒に対するスケール。
                     21: // ミリ秒単位になるようなスケール値とする
                     22: #define DEFAULT_TIMESCALE (1000LL * 1000LL)
                     23: 
1.1.1.2 ! root       24: static long timescale = DEFAULT_TIMESCALE;
        !            25: static bool opt_n = false;
1.1       root       26: 
                     27: [[noreturn]]
1.1.1.2 ! root       28: static void
1.1       root       29: usage()
                     30: {
                     31:        printf(
                     32: "%s [-d devname] [-t timescale] file\n"
                     33: "  -d devname: tty device (default:" DEFAULT_DEV ")\n"
                     34: "  -t timescale: timescale factor (default:%lld)\n"
                     35: "  -n: no transeive mode\n",
                     36:                getprogname(),
                     37:                DEFAULT_TIMESCALE
                     38:        );
                     39:        exit(1);
                     40: }
                     41: 
1.1.1.2 ! root       42: static void
1.1       root       43: Do(FILE *fp, int tty_fd)
                     44: {
                     45:        autofd kq;
                     46:        struct kevent kev;
                     47:        timespec timeout;
                     48:        int msec;
                     49:        int wait;
                     50:        int64 t;
                     51:        int r;
                     52: 
                     53:        std::queue<uint8> sbuf;
                     54:        std::vector<uint8> rbuf;
                     55: 
                     56:        kq = kqueue();
                     57:        if (kq == -1) {
                     58:                err(1, "kqueue");
                     59:        }
                     60: 
                     61:        if (tty_fd >= 0) {
1.1.1.2 ! root       62:                r = kevent_add(kq, tty_fd, EVFILT_READ, EV_ADD, 0);
1.1       root       63:                if (r == -1) {
1.1.1.2 ! root       64:                        err(1, "kevent_add(READ)");
1.1       root       65:                }
1.1.1.2 ! root       66:                r = kevent_add(kq, tty_fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, 1);
1.1       root       67:                if (r == -1) {
1.1.1.2 ! root       68:                        err(1, "kevent_add(WRITE)");
1.1       root       69:                }
                     70:        }
                     71: 
                     72:        // 受信タイムアウトデフォルト 100msec
                     73:        int64 recv_timeout = 1 * 100 * 1000 * 1000;
                     74: 
                     75:        char buf[1024];
                     76:        bool complete = false;
                     77:        bool prompt = true;
                     78:        bool writable = true;
                     79: 
                     80:        for (;;) {
                     81:                if (prompt && !complete) {
                     82:                        if (fgets(buf, sizeof(buf), fp) != NULL) {
                     83:                                if (strncmp(buf, "#", 1) == 0) {
                     84:                                        printf("%s", buf);
                     85:                                        continue;
                     86:                                }
                     87:                                // ウェイト時間はデフォルトでミリ秒で指定
                     88:                                if (sscanf(buf, "@%d", &wait)) {
                     89:                                        t = wait * timescale;
                     90:                                        timeout.tv_sec = t / (1000 * 1000 * 1000);
                     91:                                        timeout.tv_nsec = t % (1000 * 1000 * 1000);
                     92:                                        nanosleep(&timeout, NULL);
                     93:                                        continue;
                     94:                                } else if (sscanf(buf, "@R%d", &msec)) {
                     95:                                        // 受信タイムアウト変更
                     96:                                        recv_timeout = msec * 1000 * 1000;
                     97:                                        continue;
                     98:                                } else {
                     99:                                        for (char *p = buf; *p; p++) {
                    100:                                                if (*p == '\n') {
                    101:                                                        sbuf.push('\r');
                    102:                                                } else {
                    103:                                                        sbuf.push(*p);
                    104:                                                }
                    105:                                        }
                    106:                                        prompt = false;
                    107:                                }
                    108:                        } else {
                    109:                                complete = true;
                    110:                        }
                    111:                }
                    112: 
                    113:                if (writable && sbuf.size() > 0) {
                    114:                        buf[0] = sbuf.front();
                    115:                        sbuf.pop();
                    116:                        r = write(tty_fd, buf, 1);
                    117:                        if (r <= 0) {
                    118:                                err(1, "tty_fd write");
                    119:                        }
                    120:                        writable = false;
                    121:                }
                    122: 
                    123:                t = recv_timeout;
                    124:                timeout.tv_sec = t / (1000 * 1000 * 1000);
                    125:                timeout.tv_nsec = t % (1000 * 1000 * 1000);
                    126: 
                    127:                r = kevent_poll(kq, &kev, 1, &timeout);
                    128:                if (r == -1) {
                    129:                        err(1, "kevent_poll");
                    130:                }
                    131:                if (r == 0) {
                    132:                        break;
                    133:                }
                    134: 
1.1.1.2 ! root      135:                int udata = EV_UDATA2INT(kev.udata);
1.1       root      136:                if (udata == 0) {
                    137:                        r = read(tty_fd, buf, 1);
                    138:                        if (r < 0) {
                    139:                                err(1, "tty read");
                    140:                        }
                    141:                        if (r == 0) {
                    142:                                break;
                    143:                        }
                    144:                        // CR -> LF, LF -> discard
                    145:                        if (buf[0] == '\n') {
                    146:                                rbuf.push_back('\n');
                    147:                                fwrite(rbuf.data(), 1, rbuf.size(), stdout);
                    148:                                fflush(stdout);
                    149:                                rbuf.clear();
                    150:                        } else if (buf[0] == '\r') {
                    151:                        } else {
                    152:                                rbuf.push_back(buf[0]);
                    153:                        }
                    154: 
                    155:                        if (rbuf.size() == 1 && rbuf[0] == '>') {
                    156:                                prompt = true;
                    157:                        }
                    158:                        writable = true;
                    159:                }
                    160:        }
                    161: 
                    162:        if (!complete) {
                    163:                errx(1, "timeout");
                    164:        }
                    165: }
                    166: 
                    167: int
                    168: main(int ac, char *av[])
                    169: {
                    170:        int c;
                    171:        std::string dev = DEFAULT_DEV;
                    172: 
                    173:        while ((c = getopt(ac, av, "d:nt:")) >= 0) {
                    174:                switch (c) {
                    175:                 case 'd':
                    176:                        dev = optarg;
                    177:                        break;
                    178:                 case 'n':
                    179:                        opt_n = true;
                    180:                        break;
                    181:                 case 't':
                    182:                        timescale = atol(optarg);
                    183:                        break;
                    184:                 default:
                    185:                        usage();
                    186:                        break;
                    187:                }
                    188:        }
                    189: 
                    190:        ac -= optind;
                    191:        av += optind;
                    192: 
                    193:        if (ac == 0) {
                    194:                usage();
                    195:        }
                    196: 
                    197:        FILE *fp;
                    198: 
                    199:        if (strcmp(av[0], "-") == 0) {
                    200:                fp = stdin;
                    201:        } else {
                    202:                fp = fopen(av[0], "r");
                    203:                if (fp == NULL) {
                    204:                        err(1, "fopen %s", av[0]);
                    205:                }
                    206:        }
                    207: 
                    208:        int tty_fd = -1;
                    209:        if (!opt_n) {
                    210:                struct termios t;
                    211:                tty_fd = open(dev.c_str(), O_RDWR);
                    212:                if (tty_fd < 0) {
                    213:                        err(1, "open %s", dev.c_str());
                    214:                }
                    215:                tcgetattr(tty_fd, &t);
                    216:                cfmakeraw(&t);
                    217:                cfsetspeed(&t, B9600);
                    218:                t.c_iflag |= IGNBRK;
                    219:                t.c_oflag &= ~(OPOST);
                    220:                t.c_cflag |= CREAD | CLOCAL | HUPCL | CS8;
                    221:                t.c_lflag &= ~(ECHO | ICANON);
                    222:                t.c_cc[VTIME] = 0;
                    223:                t.c_cc[VMIN] = 1;
                    224:                tcsetattr(tty_fd, TCSAFLUSH, &t);
                    225: 
                    226:        }
                    227: 
                    228:        Do(fp, tty_fd);
                    229: 
                    230:        if (tty_fd >= 0) {
                    231:                close(tty_fd);
                    232:        }
                    233:        fclose(fp);
                    234:        return 0;
                    235: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.