Paparazzi UAS  v5.8.2_stable-0-g6260b7c
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 
12 // IUCLC flag translates upper case to lower case (actually needed here?)
13 // but is not in POSIX and OSX
14 #ifndef IUCLC
15 #define IUCLC 0
16 #endif
17 
18 //#define TRACE(type,fmt,args...) fprintf(stderr, fmt, args)
19 #define TRACE(type,fmt,args...)
20 #define TRACE_ERROR 1
21 
23 {
24  struct SerialPort *me = malloc(sizeof(struct SerialPort));
25  return me;
26 }
27 
28 void serial_port_free(struct SerialPort *me)
29 {
30  free(me);
31 }
32 
33 
34 void serial_port_flush(struct SerialPort *me)
35 {
36  /*
37  * flush any input that might be on the port so we start fresh.
38  */
39  if (tcflush(me->fd, TCIFLUSH)) {
40  TRACE(TRACE_ERROR, "%s, set term attr failed: %s (%d)\n", "", strerror(errno), errno);
41  fprintf(stderr, "flush (%d) failed: %s (%d)\n", me->fd, strerror(errno), errno);
42  }
43 }
44 
46 {
47  /*
48  * flush any input that might be on the port so we start fresh.
49  */
50  if (tcflush(me->fd, TCOFLUSH)) {
51  TRACE(TRACE_ERROR, "%s, set term attr failed: %s (%d)\n", "", strerror(errno), errno);
52  fprintf(stderr, "flush (%d) failed: %s (%d)\n", me->fd, strerror(errno), errno);
53  }
54 }
55 
56 int serial_port_open_raw(struct SerialPort *me, const char *device, speed_t speed)
57 {
58  if ((me->fd = open(device, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
59  TRACE(TRACE_ERROR, "%s, open failed: %s (%d)\n", device, strerror(errno), errno);
60  return -1;
61  }
62  if (tcgetattr(me->fd, &me->orig_termios) < 0) {
63  TRACE(TRACE_ERROR, "%s, get term settings failed: %s (%d)\n", device, strerror(errno), errno);
64  close(me->fd);
65  return -1;
66  }
67  me->cur_termios = me->orig_termios;
68  /* input modes */
69  me->cur_termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
70  | ICRNL | IUCLC | IXON | IXANY | IXOFF | IMAXBEL);
71  me->cur_termios.c_iflag |= IGNPAR;
72  /* control modes*/
73  me->cur_termios.c_cflag &= ~(CSIZE | PARENB | CRTSCTS | PARODD | HUPCL | CSTOPB);
74  me->cur_termios.c_cflag |= CREAD | CS8 | CLOCAL;
75  /* local modes */
76  me->cur_termios.c_lflag &= ~(ISIG | ICANON | IEXTEN | ECHO | FLUSHO | PENDIN);
77  me->cur_termios.c_lflag |= NOFLSH;
78  /* output modes */
79  me->cur_termios.c_oflag &=~(OPOST|ONLCR|OCRNL|ONOCR|ONLRET);
80 
81  if (cfsetispeed(&me->cur_termios, speed)) {
82  TRACE(TRACE_ERROR, "%s, set term speed failed: %s (%d)\n", device, strerror(errno), errno);
83  close(me->fd);
84  return -1;
85  }
86  if (tcsetattr(me->fd, TCSADRAIN, &me->cur_termios)) {
87  TRACE(TRACE_ERROR, "%s, set term attr failed: %s (%d)\n", device, strerror(errno), errno);
88  close(me->fd);
89  return -1;
90  }
92  return 0;
93 }
94 
95 int serial_port_open(struct SerialPort *me, const char *device,
96  void(*term_conf_callback)(struct termios *, speed_t *))
97 {
98 
99  speed_t speed;
100  if ((me->fd = open(device, O_RDWR | O_NONBLOCK)) < 0) {
101  TRACE(TRACE_ERROR, "%s, open failed: %s (%d)\n", device, strerror(errno), errno);
102  return -1;
103  }
104  if (tcgetattr(me->fd, &me->orig_termios) < 0) {
105  TRACE(TRACE_ERROR, "%s, get term settings failed: %s (%d)\n", device, strerror(errno), errno);
106  close(me->fd);
107  return -1;
108  }
109  me->cur_termios = me->orig_termios;
110  term_conf_callback(&me->cur_termios, &speed);
111  if (cfsetispeed(&me->cur_termios, speed)) {
112  TRACE(TRACE_ERROR, "%s, set term speed failed: %s (%d)\n", device, strerror(errno), errno);
113  close(me->fd);
114  return -1;
115  }
116  if (tcsetattr(me->fd, TCSADRAIN, &me->cur_termios)) {
117  TRACE(TRACE_ERROR, "%s, set term attr failed: %s (%d)\n", device, strerror(errno), errno);
118  close(me->fd);
119  return -1;
120  }
121  serial_port_flush(me);
122  return 0;
123 
124 }
125 
127 {
128 
129  /* if null pointer or file descriptor indicates error just bail */
130  if (!me || me->fd < 0) {
131  return;
132  }
133  if (tcflush(me->fd, TCIOFLUSH)) {
134  TRACE(TRACE_ERROR, "flushing (%s) (%d)\n", strerror(errno), errno);
135  close(me->fd);
136  return;
137  }
138  if (tcsetattr(me->fd, TCSADRAIN, &me->orig_termios)) { // Restore modes.
139  TRACE(TRACE_ERROR, "restoring term attributes (%s) (%d)\n", strerror(errno), errno);
140  close(me->fd);
141  return;
142  }
143  if (close(me->fd)) {
144  TRACE(TRACE_ERROR, "closing %s (%d)\n", strerror(errno), errno);
145  return;
146  }
147  return;
148 
149 
150 }
void serial_port_flush_output(struct SerialPort *me)
Definition: serial_port.c:45
#define TRACE(type, fmt, args...)
Definition: serial_port.c:19
struct termios orig_termios
Definition: serial_port.h:30
#define IUCLC
Definition: serial_port.c:15
void serial_port_flush(struct SerialPort *me)
Definition: serial_port.c:34
void serial_port_free(struct SerialPort *me)
Definition: serial_port.c:28
struct termios cur_termios
Definition: serial_port.h:31
struct SerialPort * serial_port_new(void)
Definition: serial_port.c:22
void serial_port_close(struct SerialPort *me)
Definition: serial_port.c:126
int serial_port_open_raw(struct SerialPort *me, const char *device, speed_t speed)
Definition: serial_port.c:56
int serial_port_open(struct SerialPort *me, const char *device, void(*term_conf_callback)(struct termios *, speed_t *))
Definition: serial_port.c:95
#define TRACE_ERROR
Definition: serial_port.c:20