"Adam Talbot" talbotx@comcast.net writes:
Hummm. Got both tomsrtbt and coyote Linux running. coyote Linux is very nice and I have other apps for it. But none of those had minicom on them. Any other ideas?
cat /dev/ttyS0 cat > /dev/ttyS0
Should just about do it.
Or for something a little more complete.
Eric
/* To compile run: gcc -g -O -Wall serial_echo.c -o serial_echo */ #include <sys/types.h> #include <sys/stat.h> #include <sys/poll.h> #include <fcntl.h> #include <unistd.h> #include <termios.h> #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h>
#define BUFFER_SIZE (1024) #define BUFFER_RESERVE 8
speed_t get_baud(int wanted) { speed_t result = B0; switch(wanted) { case 50: result = B50; break; case 75: result = B75; break; case 110: result = B110; break; case 134: result = B134; break; case 150: result = B150; break; case 200: result = B200; break; case 300: result = B300; break; case 600: result = B600; break; case 1200: result = B1200; break; case 1800: result = B1800; break; case 2400: result = B2400; break; case 4800: result = B4800; break; case 9600: result = B9600; break; case 19200: result = B19200; break; case 38400: result = B38400; break; case 57600: result = B57600; break; case 115200: result = B115200; break; case 230400: result = B230400; break; case 460800: result = B460800; break; case 500000: result = B500000; break; case 576000: result = B576000; break; case 921600: result = B921600; break; case 1000000: result = B1000000; break; case 1152000: result = B1152000; break; case 1500000: result = B1500000; break; case 2000000: result = B2000000; break; case 2500000: result = B2500000; break; case 3000000: result = B3000000; break; case 3500000: result = B3500000; break; case 4000000: result = B4000000; break; } return result; }
#define ESC_CHAR '\x1e' int do_inbuf_actions(char *in_buff, int len, int fd_serial, char *input_file, int *fd_input_file) { static int in_esc = 0; int i; for(i = 0; i < len ;) { if (!in_esc) { if (in_buff[i] == ESC_CHAR) { in_esc = 1; memmove(in_buff, in_buff +1, len - i -1); len--; continue; } } if (in_esc) { if (in_buff[i] == ESC_CHAR) { in_esc = 0; i++; continue; } else if (in_buff[i] == '\x3') { exit(0); } else if (in_buff[i] == 'b') { tcsendbreak(fd_serial, 0); } else if (in_buff[i] == 'f') { int fd; fd = open(input_file, O_RDONLY | O_NONBLOCK); if (fd < 0) { *fd_input_file = -1; fprintf(stderr, "Cannot open %s %s\n", input_file, strerror(errno)); } else { *fd_input_file = fd; } #if 0 do_transmit_file(fd_serial, input_file); #endif } memmove(in_buff, in_buff +1, len -i -1); len--; in_esc = 0; continue; } i++; } return len; }
static struct termios initial_term_options; void do_terminal_cleanup(void) { int result; result = tcsetattr(STDOUT_FILENO, TCSANOW, &initial_term_options); fprintf(stderr, "Exiting due to error %d -> %s\n", errno, strerror(errno)); } void usage(int argc, char **argv) { fprintf(stderr, "Usage: %s [[[[[device] speed] none|hard|soft] ro|rw]\n", argv[0]); exit(1); }
int main(int argc, char *argv[]) { int fd_serial; char serial_port[] = "/dev/ttyS0"; char *port; speed_t speed; struct pollfd fds_wait[3], fds_data_wait[3], *fds; int result; char out_buff[BUFFER_SIZE], in_buff[BUFFER_SIZE]; int out_buff_fill, in_buff_fill; struct termios serial_options, term_options; char *input_file; int fd_input_file; int hard_flow_control; int soft_flow_control; int read_only;
port = serial_port; speed = B115200; input_file = 0; hard_flow_control = 0; soft_flow_control = 0; read_only = 1; fd_input_file = -1; if (argc >= 2) { port = argv[1]; } if (argc >= 3) { speed = get_baud(atoi(argv[2])); } if (argc >= 4) { if (strcmp(argv[3], "none") == 0) { hard_flow_control = 0; soft_flow_control = 0; } else if (strcmp(argv[3], "hard") == 0) { hard_flow_control = 1; } else if (strcmp(argv[3], "soft") == 0) { soft_flow_control = 1; } else { usage(argc, argv); } } if (argc >= 5) { if (strcmp(argv[4], "ro") == 0) { read_only = 1; } else if (strcmp(argv[4], "rw") == 0) { read_only = 0; } else { usage(argc, argv); } } if (argc >= 6) { input_file = argv[5]; } fd_serial = open(port, O_RDWR | O_NONBLOCK); if (fd_serial < 0) { fprintf(stderr, "Can't open %s\n", port); exit(1); } result = tcgetattr(STDOUT_FILENO, &initial_term_options); if (result < 0) { fprintf(stderr, "result < 0 errno = %d -> %s\n", errno, strerror(errno)); exit(1); } atexit(do_terminal_cleanup); term_options = initial_term_options; term_options.c_iflag &= (ISTRIP | IGNBRK ); term_options.c_cflag &= ~(CSIZE | PARENB | IXON | IXOFF | IXANY); term_options.c_cflag |= (CS8 |CREAD) | ((soft_flow_control)?(IXON|IXOFF|IXANY): 0); term_options.c_lflag &= 0; term_options.c_cc[VMIN] = 1; term_options.c_cc[VTIME] = 0; result = tcsetattr(STDOUT_FILENO, TCSANOW, &term_options); if (result < 0) { fprintf(stderr, "result < 0 errno = %d -> %s\n", errno, strerror(errno)); exit(1); }
result = tcsetattr(STDIN_FILENO, TCSANOW, &term_options); if (result < 0) { fprintf(stderr, "result < 0 errno = %d -> %s\n", errno, strerror(errno)); exit(1); } result = tcgetattr(fd_serial, &serial_options); if (result < 0) { fprintf(stderr, "result < 0 errno = %d -> %s\n", errno, strerror(errno)); exit(1); }
serial_options.c_iflag = 0; serial_options.c_oflag = 0; serial_options.c_cflag = CS8 | CREAD | ((hard_flow_control)?CRTSCTS:0); serial_options.c_lflag = 0; cfsetispeed(&serial_options, speed); cfsetospeed(&serial_options, speed);
result = tcsetattr(fd_serial, TCSANOW, &serial_options); if (result < 0) { fprintf(stderr, "result < 0 errno = %d -> %s\n", errno, strerror(errno)); exit(1); }
fds_wait[0].fd = fd_serial; fds_wait[0].events = POLLIN; fds_wait[0].revents = 0; fds_wait[1].fd = STDIN_FILENO; fds_wait[1].events = POLLIN; fds_wait[1].revents = 0; fds_wait[2].fd = -1; fds_wait[2].events = 0; fds_wait[2].revents = 0; fds_data_wait[0].fd = fd_serial; fds_data_wait[0].events = POLLIN | POLLOUT; fds_data_wait[0].revents = 0; fds_data_wait[1].fd = STDIN_FILENO; fds_data_wait[1].events = POLLIN; fds_data_wait[1].revents = 0; fds_data_wait[2].fd = STDOUT_FILENO; fds_data_wait[2].events = POLLOUT; fds_data_wait[2].revents = 0;
out_buff_fill = 0; in_buff_fill = 0; fds = fds_wait; for (;;) { result = poll(fds, 3, -1); if (result < 0) { break; } if ((fds[0].revents & POLLIN) && (sizeof(out_buff) > out_buff_fill)){ result = read(fd_serial, out_buff + out_buff_fill, sizeof(out_buff) - out_buff_fill); if (result > 0) { out_buff_fill += result; } } if ((fds[1].revents & POLLIN) && (sizeof(in_buff) > in_buff_fill)) { result = read(STDIN_FILENO, in_buff + in_buff_fill, sizeof(in_buff) - in_buff_fill); if (result > 0) { int bytes; bytes = do_inbuf_actions(in_buff + in_buff_fill, result, fd_serial, input_file, &fd_input_file); if (read_only) bytes = 0; in_buff_fill += bytes; } } if ((fd_input_file >= 0) && ((sizeof(in_buff) - BUFFER_RESERVE) > in_buff_fill)) { result = read(fd_input_file, in_buff + in_buff_fill, (sizeof(in_buff) - BUFFER_RESERVE) - in_buff_fill); if (result > 0) { in_buff_fill += result; } else if (result == 0) { close(fd_input_file); fd_input_file = -1; } } if ((fds[2].revents & POLLOUT) && out_buff_fill) { result = write(STDOUT_FILENO, out_buff, out_buff_fill); if (result > 0) { out_buff_fill -= result; if (out_buff_fill) { memmove(out_buff, out_buff + result, out_buff_fill); } } } if ((fds[0].revents & POLLOUT) && in_buff_fill) { result = write(fd_serial, in_buff, in_buff_fill); if (result > 0) { in_buff_fill -= result; if (in_buff_fill) { memmove(in_buff, in_buff + result, in_buff_fill); } } } fds = (in_buff_fill || out_buff_fill || (fd_input_file >= 0))? fds_data_wait : fds_wait; } return 0; }