-
-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathSerial.c
174 lines (154 loc) · 4.34 KB
/
Serial.c
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include "Serial.h"
extern void cleanup();
int open_port(char* port) {
int fd;
fd = open(port, O_RDWR | O_NOCTTY | O_SYNC | O_NDELAY);
if (fd == -1) {
perror("The serial port could not be opened");
cleanup();
exit(1);
} else {
fcntl(fd, F_SETFL, 0);
}
return fd;
}
int close_port(int fd) {
return close(fd);
}
void set_speed(void *tty_s, int speed) {
cfsetospeed(tty_s, speed);
cfsetispeed(tty_s, speed);
}
bool setup_port(int fd, int speed) {
struct termios tty;
if (tcgetattr(fd, &tty) != 0) {
perror("Error setting port speed, could not read port parameters");
return false;
}
switch (speed) {
case 0:
set_speed(&tty, B0);
break;
case 50:
set_speed(&tty, B50);
break;
case 75:
set_speed(&tty, B75);
break;
case 110:
set_speed(&tty, B110);
break;
case 134:
set_speed(&tty, B134);
break;
case 150:
set_speed(&tty, B150);
break;
case 200:
set_speed(&tty, B200);
break;
case 300:
set_speed(&tty, B300);
break;
case 600:
set_speed(&tty, B600);
break;
case 1200:
set_speed(&tty, B1200);
break;
case 2400:
set_speed(&tty, B2400);
break;
case 4800:
set_speed(&tty, B4800);
break;
case 9600:
set_speed(&tty, B9600);
break;
case 19200:
set_speed(&tty, B19200);
break;
case 38400:
set_speed(&tty, B38400);
break;
case 57600:
set_speed(&tty, B57600);
break;
case 115200:
set_speed(&tty, B115200);
break;
case 230400:
set_speed(&tty, B230400);
break;
default:
printf("Error: Invalid port speed %d specified\r\n", speed);
cleanup();
exit(1);
return false;
}
// Set 8-bit characters, no parity, one stop bit
tty.c_cflag |= CS8;
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;
// Disable hardware flow control
tty.c_cflag &= ~CRTSCTS;
// Enable reading and ignore modem
// control lines
tty.c_cflag |= CREAD | CLOCAL;
// Disable canonical mode, echo
// and signal characters.
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO;
tty.c_lflag &= ~ECHOE;
tty.c_lflag &= ~ECHONL;
tty.c_lflag &= ~ISIG;
// Disable processing of input,
// just pass the raw data.
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
// Disable XON/XOFF software flow control.
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
// Disable processing output bytes
// and new line conversions
tty.c_oflag &= ~OPOST;
tty.c_oflag &= ~ONLCR;
// Block forever until at least one byte is read.
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
// TODO: Check these
// Prevent conversion of tabs to spaces (NOT PRESENT IN LINUX)
// tty.c_oflag &= ~OXTABS;
// Prevent removal of C-d chars (0x004) in output (NOT PRESENT IN LINUX)
// tty.c_oflag &= ~ONOEOT;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
perror("Could not configure serial port parameters");
return false;
} else {
return true;
}
}
bool set_port_blocking(int fd, bool should_block) {
struct termios tty;
memset(&tty, 0, sizeof tty);
if (tcgetattr(fd, &tty) != 0) {
perror("Error configuring port blocking behaviour, could not read port parameters");
return false;
} else {
// TODO: Implement this correctly
if (should_block) {
// Block forever until at least one byte is read.
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
} else {
// Never block, always return immediately with
// whatever is available.
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 0;
}
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
perror("Could not set port parameters while configuring blocking behaviour");
return false;
} else {
return true;
}
}
}