summaryrefslogtreecommitdiffstats
path: root/sw/dmx2artnet/monitor.c
blob: b00e366b68e7fc3c7484fc4790efce77492f9d10 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#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;
}