// code by SASANO Takayoshi, CC BY-SA #include #include #include #include #include #include static int char_length = 8; static int stop_length = 1; static int use_parity = 0; static int odd_parity = 0; static int use_rtscts = 0; static int serial_bps = 38400; #define BUFSIZE 256 static void tx_test(int fd) { uint8_t i, mask; uint8_t buf[BUFSIZE + 1]; buf[0] = 0; mask = (1 << char_length) - 1; for (i = 0; ; i++) { if ((i & mask) == 0) continue; memset(buf + 1, i & mask, BUFSIZE); write(fd, buf, sizeof(buf)); printf("."); fflush(stdout); } } static void rx_test(int fd) { int rxchar; uint8_t buf; uint32_t good, bad; rxchar = -1; good = bad = 0; while (1) { read(fd, &buf, sizeof(buf)); if (buf == 0) { /* reset, show prev result */ if (rxchar >= 0) { if (good == BUFSIZE && bad == 0) { printf("o"); } else { printf("x(%d/%d)", good, bad); } fflush(stdout); rxchar = -1; } } else if (rxchar < 0) { /* 1st char */ rxchar = buf; good = 1; bad = 0; } else { /* 2nd and later */ if (buf == rxchar) good++; else bad++; } } } static void parse_serialmode(char *p) { int i; for (i = 0; ; i++) { if (*p == '\0') break; switch (i) { case 0: /* character length */ if (*p >= '5' && *p <= '8') char_length = *p - '0'; break; case 1: /* parity bit */ use_parity = (*p == 'E' || *p == 'e' || *p == 'O' || *p == 'o'); odd_parity = (*p == 'O' || *p == 'o'); break; case 2: /* stop bits */ if (*p >= '1' && *p <= '3') stop_length = *p - '0'; break; case 3: /* X flow control (not supported) */ /* do nothing */ break; case 4: /* RTS/CTS flow control */ use_rtscts = (*p == 'H' || *p == 'h'); break; default: /* do nothing */ break; } p++; } } static int get_baud(int baud) { switch (baud) { case 50: return B50; case 75: return B75; case 110: return B110; case 134: return B134; case 150: return B150; case 200: return B200; case 300: return B300; case 600: return B600; case 1200: return B1200; case 1800: return B1800; case 2400: return B2400; case 4800: return B4800; case 7200: return B7200; case 9600: return B9600; case 14400: return B14400; case 19200: return B19200; case 28800: return B28800; case 38400: return B38400; case 57600: return B57600; case 76800: return B76800; case 115200: return B115200; case 230400: return B230400; default: return -1; } } static int setup_serial(int fd) { struct termios t; static int cs[] = {CS5, CS6, CS7, CS8}; int baud; memset(&t, 0, sizeof(t)); baud = get_baud(serial_bps); if (baud < 0) goto fail; cfsetospeed(&t, baud); cfsetispeed(&t, baud); t.c_cflag = CREAD | CLOCAL | cs[char_length - 5];; if (stop_length - 1) t.c_cflag |= CSTOPB; if (use_parity) t.c_cflag |= PARENB; if (odd_parity) t.c_cflag |= PARODD; if (use_rtscts) t.c_cflag |= CRTSCTS; t.c_iflag = IGNPAR; t.c_oflag = 0; t.c_lflag = 0; t.c_cc[VTIME] = 0; t.c_cc[VMIN] = 1; tcflush(fd, TCIFLUSH); if (tcsetattr(fd, TCSANOW, &t) < 0) goto fail; return 0; fail: return -1; } int main(int argc, char *argv[]) { int fd; if (argc < 5) { printf("%s [device] [mode] [bps] [tx|rx]\n", argv[0]); goto fin0; } fd = open(argv[1], O_RDWR | O_NOCTTY); if (fd < 0) { printf("device open error\n"); goto fin0; } parse_serialmode(argv[2]); serial_bps = atoi(argv[3]); if (setup_serial(fd) < 0) { printf("serial parameter error\n"); goto fin1; } switch (argv[4][0]) { case 't': tx_test(fd); break; case 'r': rx_test(fd); break; default: printf("undefined test\n"); break; } fin1: close(fd); fin0: return 0; }