Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
serial_port.c
Go to the documentation of this file.
1#include "serial_port.h"
2
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <fcntl.h>
6#include <errno.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
11
16// for definition of baud rates
17#if !USE_ARBITRARY_BAUDRATE
18#include <termios.h>
19#else
20#include <linux/termios.h>
21#endif
22
23// strange speed for SBUS
24#ifndef B100000
25#define B100000 100000
26#endif
27
28// for conversion between linux baud rate definition and actual speed
29static inline int uart_speed(int def)
30{
31 switch (def) {
32 case B1200: return 1200;
33 case B2400: return 2400;
34 case B4800: return 4800;
35 case B9600: return 9600;
36 case B19200: return 19200;
37 case B38400: return 38400;
38 case B57600: return 57600;
39 case B100000: return 100000;
40 case B115200: return 115200;
41 case B230400: return 230400;
42#ifdef B921600
43 case B921600: return 921600;
44#endif
45 default: return 9600;
46 }
47}
48
49#define UBITS_7 7
50#define UBITS_8 8
51
52#define USTOP_1 1
53#define USTOP_2 2
54
55#define UPARITY_NO 0
56#define UPARITY_ODD 1
57#define UPARITY_EVEN 2
58
60
61
62
63
64// IUCLC flag translates upper case to lower case (actually needed here?)
65// but is not in POSIX and OSX
66#ifndef IUCLC
67#define IUCLC 0
68#endif
69
70//#define TRACE(type,fmt,args...) fprintf(stderr, fmt, args)
71#define TRACE(type,fmt,args...)
72#define TRACE_ERROR 1
73
75{
76 struct SerialPort *me = malloc(sizeof(struct SerialPort));
77 return me;
78}
79
81{
82 free(me);
83}
84
85
86#if !USE_ARBITRARY_BAUDRATE
87// classic set baud function
88
90{
91 /*
92 * flush any input that might be on the port so we start fresh.
93 */
94 if (tcflush(me->fd, TCIFLUSH)) {
95 TRACE(TRACE_ERROR, "%s, set term attr failed: %s (%d)\n", "", strerror(errno), errno);
96 fprintf(stderr, "flush (%d) failed: %s (%d)\n", me->fd, strerror(errno), errno);
97 }
98}
99
101{
102 /*
103 * flush any input that might be on the port so we start fresh.
104 */
105 if (tcflush(me->fd, TCOFLUSH)) {
106 TRACE(TRACE_ERROR, "%s, set term attr failed: %s (%d)\n", "", strerror(errno), errno);
107 fprintf(stderr, "flush (%d) failed: %s (%d)\n", me->fd, strerror(errno), errno);
108 }
109}
110
111int serial_port_open_raw(struct SerialPort *me, const char *device, speed_t speed)
112{
113 if ((me->fd = open(device, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
114 TRACE(TRACE_ERROR, "%s, open failed: %s (%d)\n", device, strerror(errno), errno);
115 return -1;
116 }
117 if (tcgetattr(me->fd, &me->orig_termios) < 0) {
118 TRACE(TRACE_ERROR, "%s, get term settings failed: %s (%d)\n", device, strerror(errno), errno);
119 close(me->fd);
120 return -1;
121 }
122 me->cur_termios = me->orig_termios;
123 /* input modes */
124 me->cur_termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
125 | ICRNL | IUCLC | IXON | IXANY | IXOFF | IMAXBEL);
126 me->cur_termios.c_iflag |= IGNPAR;
127 /* control modes*/
128 me->cur_termios.c_cflag &= ~(CSIZE | PARENB | CRTSCTS | PARODD | HUPCL | CSTOPB);
129 me->cur_termios.c_cflag |= CREAD | CS8 | CLOCAL;
130 /* local modes */
131 me->cur_termios.c_lflag &= ~(ISIG | ICANON | IEXTEN | ECHO | FLUSHO | PENDIN);
132 me->cur_termios.c_lflag |= NOFLSH;
133 /* output modes */
134 me->cur_termios.c_oflag &=~(OPOST|ONLCR|OCRNL|ONOCR|ONLRET);
135 /* no buffering */
136 me->cur_termios.c_cc[VTIME] = 0;
137 me->cur_termios.c_cc[VMIN] = 0;
138
139 if (cfsetispeed(&me->cur_termios, speed)) {
140 TRACE(TRACE_ERROR, "%s, set term speed failed: %s (%d)\n", device, strerror(errno), errno);
141 close(me->fd);
142 return -1;
143 }
144 if (tcsetattr(me->fd, TCSADRAIN, &me->cur_termios)) {
145 TRACE(TRACE_ERROR, "%s, set term attr failed: %s (%d)\n", device, strerror(errno), errno);
146 close(me->fd);
147 return -1;
148 }
150 return 0;
151}
152
153int serial_port_open(struct SerialPort *me, const char *device,
154 void(*term_conf_callback)(struct termios *, speed_t *))
155{
156
157 speed_t speed;
158 if ((me->fd = open(device, O_RDWR | O_NONBLOCK)) < 0) {
159 TRACE(TRACE_ERROR, "%s, open failed: %s (%d)\n", device, strerror(errno), errno);
160 return -1;
161 }
162 if (tcgetattr(me->fd, &me->orig_termios) < 0) {
163 TRACE(TRACE_ERROR, "%s, get term settings failed: %s (%d)\n", device, strerror(errno), errno);
164 close(me->fd);
165 return -1;
166 }
167 me->cur_termios = me->orig_termios;
168 term_conf_callback(&me->cur_termios, &speed);
169 if (cfsetispeed(&me->cur_termios, speed)) {
170 TRACE(TRACE_ERROR, "%s, set term speed failed: %s (%d)\n", device, strerror(errno), errno);
171 close(me->fd);
172 return -1;
173 }
174 if (tcsetattr(me->fd, TCSADRAIN, &me->cur_termios)) {
175 TRACE(TRACE_ERROR, "%s, set term attr failed: %s (%d)\n", device, strerror(errno), errno);
176 close(me->fd);
177 return -1;
178 }
180 return 0;
181
182}
183
185{
186
187 /* if null pointer or file descriptor indicates error just bail */
188 if (!me || me->fd < 0) {
189 return;
190 }
191 if (tcflush(me->fd, TCIOFLUSH)) {
192 TRACE(TRACE_ERROR, "flushing (%s) (%d)\n", strerror(errno), errno);
193 close(me->fd);
194 return;
195 }
196 if (tcsetattr(me->fd, TCSADRAIN, &me->orig_termios)) { // Restore modes.
197 TRACE(TRACE_ERROR, "restoring term attributes (%s) (%d)\n", strerror(errno), errno);
198 close(me->fd);
199 return;
200 }
201 if (close(me->fd)) {
202 TRACE(TRACE_ERROR, "closing %s (%d)\n", strerror(errno), errno);
203 return;
204 }
205 return;
206
207
208}
209
211{
212 /* if null pointer or file descriptor indicates error just bail */
213 if (!me || me->fd < 0) {
214 return -1;
215 }
216 if (cfsetispeed(&me->cur_termios, speed)) {
217 TRACE(TRACE_ERROR, "%s, set term speed failed: %s (%d)\n", device, strerror(errno), errno);
218 close(me->fd);
219 return -1;
220 }
221 return 0;
222}
223
224int serial_port_set_bits_stop_parity(struct SerialPort *me, const int bits, const int stop, const int parity)
225{
226 /* if null pointer or file descriptor indicates error just bail */
227 if (!me || me->fd < 0) {
228 return -1;
229 }
230 // clear data bits
231 me->cur_termios.c_cflag &= ~CSIZE;
232 if (bits == UBITS_7) {
233 me->cur_termios.c_cflag |= CS7;
234 } else {
235 me->cur_termios.c_cflag |= CS8;
236 }
237 // set stops
238 if (stop == USTOP_1) {
239 me->cur_termios.c_cflag &= ~CSTOPB;
240 } else {
241 me->cur_termios.c_cflag |= CSTOPB;
242 }
243 // set parity
244 if (parity == UPARITY_EVEN) {
245 me->cur_termios.c_cflag |= PARENB;
246 me->cur_termios.c_cflag &= ~PARODD;
247 } else if (parity == UPARITY_ODD) {
248 me->cur_termios.c_cflag |= PARENB;
249 me->cur_termios.c_cflag |= PARODD;
250 } else {
251 me->cur_termios.c_cflag &= ~PARENB;
252 }
253 // set new parameters
254 if (tcsetattr(me->fd, TCSADRAIN, &me->cur_termios)) {
255 TRACE(TRACE_ERROR, "setting term attributes (%s) (%d)\n", strerror(errno), errno);
256 return -2;
257 }
258 return 0;
259}
260
261#else // USE_ARBITRARY_BAUDRATE
262// use termios2 interface
263// needed to set arbitrary speed
264// it is the case for the SBUS RC input
265
266int ioctl(int d, int request, ...); // avoid warning
267int tcflush (int __fd, int __queue_selector); // avoid warning
268
269void serial_port_flush(struct SerialPort *me)
270{
271 /*
272 * flush any input that might be on the port so we start fresh.
273 */
274 if (tcflush(me->fd, TCIFLUSH)) {
275 TRACE(TRACE_ERROR, "%s, set term attr failed: %s (%d)\n", "", strerror(errno), errno);
276 fprintf(stderr, "flush (%d) failed: %s (%d)\n", me->fd, strerror(errno), errno);
277 }
278}
279
281{
282 /*
283 * flush any input that might be on the port so we start fresh.
284 */
285 if (tcflush(me->fd, TCOFLUSH)) {
286 TRACE(TRACE_ERROR, "%s, set term attr failed: %s (%d)\n", "", strerror(errno), errno);
287 fprintf(stderr, "flush (%d) failed: %s (%d)\n", me->fd, strerror(errno), errno);
288 }
289}
290
291int serial_port_open_raw(struct SerialPort *me, const char *device, speed_t speed)
292{
293 if ((me->fd = open(device, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
294 TRACE(TRACE_ERROR, "%s, open failed: %s (%d)\n", device, strerror(errno), errno);
295 return -1;
296 }
297
298 if (ioctl(me->fd, TCGETS2, &me->orig_termios)) {
299 perror("TCGETS2");
300 close(me->fd);
301 return -1;
302 }
303
304 me->cur_termios = me->orig_termios;
305 /* input modes */
306 me->cur_termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
307 | ICRNL | IUCLC | IXON | IXANY | IXOFF | IMAXBEL);
308 me->cur_termios.c_iflag |= IGNPAR;
309 /* control modes*/
310 me->cur_termios.c_cflag &= ~(CSIZE | PARENB | CRTSCTS | PARODD | HUPCL | CSTOPB);
311 me->cur_termios.c_cflag |= CREAD | CS8 | CLOCAL;
312 /* local modes */
313 me->cur_termios.c_lflag &= ~(ISIG | ICANON | IEXTEN | ECHO | FLUSHO | PENDIN);
314 me->cur_termios.c_lflag |= NOFLSH;
315 /* output modes */
316 me->cur_termios.c_oflag &=~(OPOST|ONLCR|OCRNL|ONOCR|ONLRET);
317 /* no buffering */
318 me->cur_termios.c_cc[VTIME] = 0;
319 me->cur_termios.c_cc[VMIN] = 0;
320
321 me->cur_termios.c_cflag &= ~CBAUD;
322 me->cur_termios.c_cflag |= BOTHER;
323 me->cur_termios.c_ispeed = uart_speed(speed); // set real speed
324 me->cur_termios.c_ospeed = uart_speed(speed); // set real speed
325
326 if (ioctl(me->fd, TCSETS2, &me->cur_termios)) {
327 perror("TCSETS2");
328 close(me->fd);
329 return -1;
330 }
331
333
334 if (ioctl(me->fd, TCGETS2, &me->cur_termios))
335 {
336 perror("TCGETS2");
337 return 5;
338 }
339
340 return 0;
341}
342
343int serial_port_open(struct SerialPort *me, const char *device,
344 void(*term_conf_callback)(struct termios *, speed_t *))
345{
346 (void)me;
347 (void)device;
349 return 0;
350}
351
352void serial_port_close(struct SerialPort *me)
353{
354
355 /* if null pointer or file descriptor indicates error just bail */
356 if (!me || me->fd < 0) {
357 return;
358 }
359 if (tcflush(me->fd, TCIOFLUSH)) {
360 TRACE(TRACE_ERROR, "flushing (%s) (%d)\n", strerror(errno), errno);
361 close(me->fd);
362 return;
363 }
364 if (ioctl(me->fd, TCSETS2, &me->orig_termios)) { // Restore modes.
365 TRACE(TRACE_ERROR, "restoring term attributes (%s) (%d)\n", strerror(errno), errno);
366 perror("TCSETS2");
367 close(me->fd);
368 return;
369 }
370 if (close(me->fd)) {
371 TRACE(TRACE_ERROR, "closing %s (%d)\n", strerror(errno), errno);
372 return;
373 }
374 return;
375
376}
377
379{
380 /* if null pointer or file descriptor indicates error just bail */
381 if (!me || me->fd < 0) {
382 return -1;
383 }
384
385 me->cur_termios.c_cflag &= ~CBAUD;
386 me->cur_termios.c_cflag |= BOTHER;
387 me->cur_termios.c_ispeed = uart_speed(speed); // set real speed
388 me->cur_termios.c_ospeed = uart_speed(speed); // set real speed
389
390 // set new parameters
391 if (ioctl(me->fd, TCSETS2, &me->cur_termios)) {
392 perror("TCSETS2");
393 close(me->fd);
394 return -1;
395 }
396 return 0;
397}
398
399
400int serial_port_set_bits_stop_parity(struct SerialPort *me, const int bits, const int stop, const int parity)
401{
402 /* if null pointer or file descriptor indicates error just bail */
403 if (!me || me->fd < 0) {
404 return -1;
405 }
406 // clear data bits
407 me->cur_termios.c_cflag &= ~CSIZE;
408 if (bits == UBITS_7) {
409 me->cur_termios.c_cflag |= CS7;
410 } else {
411 me->cur_termios.c_cflag |= CS8;
412 }
413 // set stops
414 if (stop == USTOP_1) {
415 me->cur_termios.c_cflag &= ~CSTOPB;
416 } else {
417 me->cur_termios.c_cflag |= CSTOPB;
418 }
419 // set parity
420 if (parity == UPARITY_EVEN) {
421 me->cur_termios.c_cflag |= PARENB;
422 me->cur_termios.c_cflag &= ~PARODD;
423 me->cur_termios.c_iflag |= INPCK;
424 } else if (parity == UPARITY_ODD) {
425 me->cur_termios.c_cflag |= PARENB;
426 me->cur_termios.c_cflag |= PARODD;
427 me->cur_termios.c_iflag |= INPCK;
428 } else {
429 me->cur_termios.c_cflag &= ~PARENB;
430 me->cur_termios.c_iflag &= ~INPCK;
431 }
432 // set new parameters
433 if (ioctl(me->fd, TCSETS2, &me->cur_termios)) {
434 perror("TCSETS2");
435 close(me->fd);
436 return -1;
437 }
438 return 0;
439}
440
441#endif
442
#define B1200
Definition uart_arch.h:40
#define B4800
Definition uart_arch.h:42
#define B57600
Definition uart_arch.h:46
#define B230400
Definition uart_arch.h:49
#define B38400
Definition uart_arch.h:45
#define B9600
Definition uart_arch.h:43
#define B921600
Definition uart_arch.h:51
#define B19200
Definition uart_arch.h:44
#define B115200
Definition uart_arch.h:48
#define B2400
Definition uart_arch.h:41
uint16_t foo
Definition main_demo5.c:58
#define TRACE(type, fmt, args...)
Definition serial_port.c:71
#define UBITS_7
Definition serial_port.c:49
void serial_port_free(struct SerialPort *me)
Definition serial_port.c:80
#define UPARITY_ODD
Definition serial_port.c:56
void serial_port_close(struct SerialPort *me)
static int uart_speed(int def)
Definition serial_port.c:29
#define IUCLC
Definition serial_port.c:67
int serial_port_open_raw(struct SerialPort *me, const char *device, speed_t speed)
#define TRACE_ERROR
Definition serial_port.c:72
#define B100000
some definitions from PPRZ uart driver as we can't include it directly
Definition serial_port.c:25
struct SerialPort * serial_port_new(void)
Definition serial_port.c:74
void serial_port_flush_output(struct SerialPort *me)
#define USTOP_1
Definition serial_port.c:52
int serial_port_set_bits_stop_parity(struct SerialPort *me, const int bits, const int stop, const int parity)
int serial_port_open(struct SerialPort *me, const char *device, void(*term_conf_callback)(struct termios *, speed_t *))
#define UPARITY_EVEN
Definition serial_port.c:57
int serial_port_set_baudrate(struct SerialPort *me, speed_t speed)
void serial_port_flush(struct SerialPort *me)
Definition serial_port.c:89