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

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: 
        !            24: long timescale = DEFAULT_TIMESCALE;
        !            25: bool opt_n = false;
        !            26: 
        !            27: [[noreturn]]
        !            28: void
        !            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: 
        !            42: void
        !            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) {
        !            62:                EV_SET(&kev, tty_fd, EVFILT_READ, EV_ADD, 0, 0, 0);
        !            63:                r = kevent_set(kq, &kev, 1);
        !            64:                if (r == -1) {
        !            65:                        err(1, "kevent_set");
        !            66:                }
        !            67:                EV_SET(&kev, tty_fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT,
        !            68:                        0, 0, (kevent_udata_t)1);
        !            69:                r = kevent_set(kq, &kev, 1);
        !            70:                if (r == -1) {
        !            71:                        err(1, "kevent_set");
        !            72:                }
        !            73:        }
        !            74: 
        !            75:        // 受信タイムアウトデフォルト 100msec
        !            76:        int64 recv_timeout = 1 * 100 * 1000 * 1000;
        !            77: 
        !            78:        char buf[1024];
        !            79:        bool complete = false;
        !            80:        bool prompt = true;
        !            81:        bool writable = true;
        !            82: 
        !            83:        for (;;) {
        !            84:                if (prompt && !complete) {
        !            85:                        if (fgets(buf, sizeof(buf), fp) != NULL) {
        !            86:                                if (strncmp(buf, "#", 1) == 0) {
        !            87:                                        printf("%s", buf);
        !            88:                                        continue;
        !            89:                                }
        !            90:                                // ウェイト時間はデフォルトでミリ秒で指定
        !            91:                                if (sscanf(buf, "@%d", &wait)) {
        !            92:                                        t = wait * timescale;
        !            93:                                        timeout.tv_sec = t / (1000 * 1000 * 1000);
        !            94:                                        timeout.tv_nsec = t % (1000 * 1000 * 1000);
        !            95:                                        nanosleep(&timeout, NULL);
        !            96:                                        continue;
        !            97:                                } else if (sscanf(buf, "@R%d", &msec)) {
        !            98:                                        // 受信タイムアウト変更
        !            99:                                        recv_timeout = msec * 1000 * 1000;
        !           100:                                        continue;
        !           101:                                } else {
        !           102:                                        for (char *p = buf; *p; p++) {
        !           103:                                                if (*p == '\n') {
        !           104:                                                        sbuf.push('\r');
        !           105:                                                } else {
        !           106:                                                        sbuf.push(*p);
        !           107:                                                }
        !           108:                                        }
        !           109:                                        prompt = false;
        !           110:                                }
        !           111:                        } else {
        !           112:                                complete = true;
        !           113:                        }
        !           114:                }
        !           115: 
        !           116:                if (writable && sbuf.size() > 0) {
        !           117:                        buf[0] = sbuf.front();
        !           118:                        sbuf.pop();
        !           119:                        r = write(tty_fd, buf, 1);
        !           120:                        if (r <= 0) {
        !           121:                                err(1, "tty_fd write");
        !           122:                        }
        !           123:                        writable = false;
        !           124:                }
        !           125: 
        !           126:                t = recv_timeout;
        !           127:                timeout.tv_sec = t / (1000 * 1000 * 1000);
        !           128:                timeout.tv_nsec = t % (1000 * 1000 * 1000);
        !           129: 
        !           130:                r = kevent_poll(kq, &kev, 1, &timeout);
        !           131:                if (r == -1) {
        !           132:                        err(1, "kevent_poll");
        !           133:                }
        !           134:                if (r == 0) {
        !           135:                        break;
        !           136:                }
        !           137: 
        !           138:                int udata = (int)kev.udata;
        !           139:                if (udata == 0) {
        !           140:                        r = read(tty_fd, buf, 1);
        !           141:                        if (r < 0) {
        !           142:                                err(1, "tty read");
        !           143:                        }
        !           144:                        if (r == 0) {
        !           145:                                break;
        !           146:                        }
        !           147:                        // CR -> LF, LF -> discard
        !           148:                        if (buf[0] == '\n') {
        !           149:                                rbuf.push_back('\n');
        !           150:                                fwrite(rbuf.data(), 1, rbuf.size(), stdout);
        !           151:                                fflush(stdout);
        !           152:                                rbuf.clear();
        !           153:                        } else if (buf[0] == '\r') {
        !           154:                        } else {
        !           155:                                rbuf.push_back(buf[0]);
        !           156:                        }
        !           157: 
        !           158:                        if (rbuf.size() == 1 && rbuf[0] == '>') {
        !           159:                                prompt = true;
        !           160:                        }
        !           161:                        writable = true;
        !           162:                }
        !           163:        }
        !           164: 
        !           165:        if (!complete) {
        !           166:                errx(1, "timeout");
        !           167:        }
        !           168: }
        !           169: 
        !           170: int
        !           171: main(int ac, char *av[])
        !           172: {
        !           173:        int c;
        !           174:        std::string dev = DEFAULT_DEV;
        !           175: 
        !           176:        while ((c = getopt(ac, av, "d:nt:")) >= 0) {
        !           177:                switch (c) {
        !           178:                 case 'd':
        !           179:                        dev = optarg;
        !           180:                        break;
        !           181:                 case 'n':
        !           182:                        opt_n = true;
        !           183:                        break;
        !           184:                 case 't':
        !           185:                        timescale = atol(optarg);
        !           186:                        break;
        !           187:                 default:
        !           188:                        usage();
        !           189:                        break;
        !           190:                }
        !           191:        }
        !           192: 
        !           193:        ac -= optind;
        !           194:        av += optind;
        !           195: 
        !           196:        if (ac == 0) {
        !           197:                usage();
        !           198:        }
        !           199: 
        !           200:        FILE *fp;
        !           201: 
        !           202:        if (strcmp(av[0], "-") == 0) {
        !           203:                fp = stdin;
        !           204:        } else {
        !           205:                fp = fopen(av[0], "r");
        !           206:                if (fp == NULL) {
        !           207:                        err(1, "fopen %s", av[0]);
        !           208:                }
        !           209:        }
        !           210: 
        !           211:        int tty_fd = -1;
        !           212:        if (!opt_n) {
        !           213:                struct termios t;
        !           214:                tty_fd = open(dev.c_str(), O_RDWR);
        !           215:                if (tty_fd < 0) {
        !           216:                        err(1, "open %s", dev.c_str());
        !           217:                }
        !           218:                tcgetattr(tty_fd, &t);
        !           219:                cfmakeraw(&t);
        !           220:                cfsetspeed(&t, B9600);
        !           221:                t.c_iflag |= IGNBRK;
        !           222:                t.c_oflag &= ~(OPOST);
        !           223:                t.c_cflag |= CREAD | CLOCAL | HUPCL | CS8;
        !           224:                t.c_lflag &= ~(ECHO | ICANON);
        !           225:                t.c_cc[VTIME] = 0;
        !           226:                t.c_cc[VMIN] = 1;
        !           227:                tcsetattr(tty_fd, TCSAFLUSH, &t);
        !           228: 
        !           229:        }
        !           230: 
        !           231:        Do(fp, tty_fd);
        !           232: 
        !           233:        if (tty_fd >= 0) {
        !           234:                close(tty_fd);
        !           235:        }
        !           236:        fclose(fp);
        !           237:        return 0;
        !           238: }

unix.superglobalmegacorp.com

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