Annotation of nono/util/autoserial/autoserial.cpp, revision 1.1.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.