📄 rwser.c
字号:
/** * rwser.c * Utility to read and write data from serial port in a straightforward * command-line fashion. Helpful when dealing with crickets. * * David Moore <dcm@csail.mit.edu> * * * Copyright (C) 2004 David C. Moore * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <stdio.h>#include <termios.h>#include <unistd.h>#include <fcntl.h>#include <sys/time.h>#include <getopt.h>#include <signal.h>#include <readline/readline.h>#include <readline/history.h>#define USAGE "Usage: rwser [-itesh] [-d dev] [-b rate] [-c size] [-p prompt]\n\Read data from and optionally write data to a serial port device.\n\\n\Optional arguments:\n\ -i interactive, text typed by user will be sent to device\n\ -t prefix input/output lines with unix-style time\n\ -d serial device to use (default: /dev/ttyS0)\n\ -b baud rate (default: 115200)\n\ -c serial character size (5, 6, 7, or 8; default: 8)\n\ -e enable even parity on the serial port (default: none)\n\ -p text prompt to use when awaiting user input\n\ -s send command to initialize cricket debug mode\n\ -h --help this help\n"#define DEVICE "/dev/ttyS0"struct _baud_t { int rate; speed_t val;};/* List of valid baud rates and their cfsetispeed() constants */#define NUM_BAUDS 8struct _baud_t bauds[NUM_BAUDS] = { { 1200, B1200 }, { 2400, B2400 }, { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 }, { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }};/* List of long-style command-line arguments */struct option longopts[] = { { "help", no_argument, NULL, 'h' }, { 0 },};static int fd;static int dotime = 0;static int do_init = 0;/* Clean up when we quit */void quit(int status){ if (do_init) { char * dbg_off = "DEBUG OFF\n"; write(fd, dbg_off, strlen(dbg_off)); } tcdrain(fd); close(fd); printf("Quitting...\n"); exit(0);}/* Callback for user typing a new line */void gotnewline(char * str){ char newstr[256]; struct timeval tv; /* NULL str means end of file */ if (!str) { fprintf(stderr, "\nquitting\n"); quit(1); } /* Add the command to the readline history */ add_history(str); if (dotime) { gettimeofday(&tv, NULL); printf("%d.%d ", tv.tv_sec, tv.tv_usec); } /* Echo the line */ printf("output: %s\n", str); fflush(stdout); /* Don't send comments to the serial port device */ if (str[0] != '%') { snprintf(newstr, sizeof(newstr), "%s\n", str); write(fd, newstr, strlen(newstr)); }}int main(int argc, char ** argv){ struct termios tio; char buf[256]; char * dev = DEVICE; int doinput = 0; char c; int baud = 115200; speed_t baudval; int i; char * prompt = ""; int was_at_end = 1; int bytesize = 8; int parity = 0; /* We want readline to use stderr, not stdin */ rl_outstream = stderr; /* Process command-line arguments */ while ((c = getopt_long(argc, argv, "ithd:b:p:sec:", longopts, NULL)) >= 0) { switch (c) { case 'i': doinput = 1; break; case 't': dotime = 1; break; case 'd': dev = optarg; break; case 'b': baud = atoi(optarg); break; case 'p': prompt = optarg; break; case 's': do_init = 1; break; case 'e': parity = 1; break; case 'c': bytesize = atoi(optarg); break; case 'h': printf("%s", USAGE); exit(1); default: exit(1); } } /* Interpret the baud rate */ for (i=0; i < NUM_BAUDS; i++) { if (bauds[i].rate == baud) { baudval = bauds[i].val; break; } } if (i == NUM_BAUDS) { fprintf(stderr, "Invalid baud rate %d\n", baud); exit(1); } if (bytesize > 8 || bytesize < 5) { fprintf(stderr, "Invalid character size %d\n", bytesize); exit(1); } fprintf(stderr, "Using %s at %d baud\n", dev, baud); fd = open(dev, O_RDWR); if (fd == -1) { perror("open"); return 1; } /* Set the serial port attributes */ tcgetattr(fd, &tio); cfmakeraw(&tio);// tio.c_iflag = IGNPAR | IGNCR;// tio.c_cflag = CLOCAL | CREAD; tio.c_iflag |= IGNCR; tio.c_cflag &= ~(CSIZE|PARENB); switch (bytesize) { case 8: tio.c_cflag |= CS8; break; case 7: tio.c_cflag |= CS7; break; case 6: tio.c_cflag |= CS6; break; case 5: tio.c_cflag |= CS5; break; } if (parity) { tio.c_iflag |= INPCK; tio.c_cflag |= PARENB; } cfsetospeed(&tio, baudval); cfsetispeed(&tio, baudval); tcflush(fd, TCIFLUSH); if (tcsetattr(fd, TCSANOW, &tio) == -1) { perror("tcsetattr"); return 1; } if (do_init) { char * dbg_on = "DEBUG ON\n"; write(fd, dbg_on, strlen(dbg_on)); } signal(SIGINT, quit); /* Install the readline handler if we want user input */ if (doinput) rl_callback_handler_install(prompt, gotnewline); while (1) { struct timeval tv; int c; fd_set readfds; FD_ZERO(&readfds); if (doinput) FD_SET(0, &readfds); FD_SET(fd, &readfds); /* Wait for data from device and optionally stdin */ c = select(fd+1, &readfds, NULL, NULL, NULL); if (c < 0) break; /* Got data from serial device */ if (FD_ISSET(fd, &readfds)) { char * b, * a = buf; c = read(fd, buf, sizeof(buf)); // printf("\nread -- %.*s --\n", c, a); if (dotime) { gettimeofday(&tv, NULL); while (c > 0) { if (was_at_end) { printf("%d.%03d: ", tv.tv_sec, tv.tv_usec/1000); was_at_end = 0; } b = memchr(a, '\n', c); if (!b) break; printf("%.*s", b-a+1, a); c -= (b-a)+1; a = b+1; was_at_end = 1; } } printf("%.*s", c, a); fflush(stdout); } /* Got data from stdin */ if (FD_ISSET(0, &readfds)) { rl_callback_read_char(); } } if (doinput) rl_callback_handler_remove(); quit(1); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -