#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <poll.h>
#include <sys/types.h>
#include <error.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#define termios asmtermios
#define winsize asmwinsize
#define termio asmtermio
#include <asm/termios.h>
#undef termios
#undef winsize
#undef termio
#define S0(x) (x ? x : "")
// start bit: low, 2 stop bits high
int rate (int what_rate, int uart) {
int r = 0;
struct termios2 uartattr2;
if (ioctl(uart, TCGETS2, &uartattr2) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "ioctl TCGETS2, fd: %d", uart);
r = 1;
goto r;
}
uartattr2.c_cflag &= ~CBAUD;
uartattr2.c_cflag |= BOTHER;
uartattr2.c_ispeed = what_rate;
uartattr2.c_ospeed = what_rate;
if (ioctl(uart, TCSETS2, &uartattr2) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "ioctl TCSETS2");
r = 2;
goto r;
}
r:
return r;
}
int main (int argc, char ** argv) {
int r = 0;
if (argc != 1+1)
error_at_line(1, 0, __FILE__, __LINE__, "usage: %s /dev/ttyUSB0", S0(argv[0]));
int uart = open(argv[1], O_RDONLY | O_NOCTTY | O_NDELAY | O_CLOEXEC);
if (uart == -1)
error_at_line(3, errno, __FILE__, __LINE__, "open");
struct termios uartattr;
if (tcgetattr(uart, &uartattr) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "tcgetattr");
r = 4;
goto r;
}
uartattr.c_iflag = 0;
uartattr.c_oflag = 0;
uartattr.c_cflag = CS8 | CSTOPB;
uartattr.c_lflag = 0;
if (tcflush(uart, TCIOFLUSH) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "tcflush");
r = 5;
goto r;
}
if (tcsetattr(uart, TCSANOW, &uartattr) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "tcsetattr");
r = 6;
goto r;
}
if (tcflush(uart, TCIOFLUSH) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "tcflush");
r = 15;
goto r;
}
switch (rate(250000, uart)) {
case 1:
r = 20;
goto r;
break;
case 2:
r = 21;
goto r;
break;
default:
break;
}
while (1) {
struct pollfd pollfd;
pollfd.fd = uart;
pollfd.events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
int poll_return;
if ((poll_return = poll(&pollfd, 1, -1)) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "poll");
r = 16;
goto r;
}
if (!poll_return) {
error_at_line(0, 0, __FILE__, __LINE__, "poll returned 0");
r = 17;
goto r;
}
if ((pollfd.revents & POLLERR) | (pollfd.revents & POLLHUP) | (pollfd.revents & POLLNVAL)) {
error_at_line(0, 0, __FILE__, __LINE__, "ERR | HUP | NVAL");
r = 18;
goto r;
}
char buf[2048];
ssize_t r = read(uart, buf, 2048);
if (r == -1)
if (errno != EAGAIN) {
error_at_line(0, errno, __FILE__, __LINE__, "read");
r = 19;
goto r;
}
fwrite(buf, 1, 2048, stdout);
}
r:
if (close(uart) == -1)
error_at_line(22, errno, __FILE__, __LINE__, "close(uart)");
return r;
}