SerialInterface.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #include "SerialInterface.h"
25 
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include <iostream>
32 
33 #include <fcntl.h>
34 #include <sys/ioctl.h>
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 #include <termios.h>
38 #include <unistd.h>
39 
40 #include <boost/format.hpp>
41 
42 static inline tcflag_t
43 __bitrate_to_flag(unsigned int bitrate)
44 {
45  switch (bitrate)
46  {
47  case 1200:
48  return B1200;
49 
50  case 2400:
51  return B2400;
52 
53  case 4800:
54  return B4800;
55 
56  case 9600:
57  return B9600;
58 
59  case 19200:
60  return B19200;
61 
62  case 38400:
63  return B38400;
64 
65  case 57600:
66  return B57600;
67 
68  case 115200:
69  return B115200;
70 
71  case 230400:
72  return B230400;
73 
74  case 460800:
75  return B460800;
76 
77  default:
78  return 0;
79  }
80 }
81 
82 SerialInterface::SerialInterface(const char* device, unsigned int bitrate)
83 {
84  this->device = device;
85  this->bitrate = bitrate;
86  this->fd = -1;
87 }
88 
90 {
91 }
92 
93 int
95 {
96  // Convert bitrate to flag
97  tcflag_t bitrate = __bitrate_to_flag(this->bitrate);
98 
99  if (bitrate == 0)
100  {
101  fprintf(stderr, "Invalid bitrate '%d' for serial device\n", this->bitrate);
102  return -1;
103  }
104 
105 
106  // Open serial device
107  fd = ::open(device, O_RDWR | O_NOCTTY);
108 
109  if (fd < 0)
110  {
111  fprintf(stderr, "Failed to open serial device '%s' (errno: %s)\n", device, strerror(errno));
112  return -1;
113  }
114 
115  if (::ioctl(fd, TIOCEXCL))
116  {
117  fprintf(stderr, "Failed to lock serial device '%s' (errno: %s)\n", device, strerror(errno));
118  return -1;
119  }
120 
121 
122  // Check if device is a terminal device
123  if (!isatty(fd))
124  {
125  fprintf(
126  stderr, "Device '%s' is not a terminal device (errno: %s)!\n", device, strerror(errno));
127  ::close(fd);
128  return -1;
129  }
130 
131  struct termios settings;
132 
133  // Set input flags
134  settings.c_iflag = IGNBRK // Ignore BREAKS on Input
135  | IGNPAR; // No Parity
136 
137  // ICRNL: map CR to NL (otherwise a CR input on the other computer will not terminate input)
138 
139  // Set output flags
140  settings.c_oflag = 0; // Raw output
141 
142  // Set controlflags
143  settings.c_cflag = bitrate | CS8 // 8 bits per byte
144  | CSTOPB // Stop bit
145  | CREAD // characters may be read
146  | CLOCAL; // ignore modem state, local connection
147 
148  // Set local flags
149  settings.c_lflag = 0; // Other option: ICANON = enable canonical input
150 
151  // Set maximum wait time on input - cf. Linux Serial Programming HowTo, non-canonical mode
152  // http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html
153  settings.c_cc[VTIME] = 10; // 0 means timer is not uses
154 
155  // Set minimum bytes to read
156  settings.c_cc[VMIN] = 0; // 1 means wait until at least 1 character is received
157 
158  // Now clean the modem line and activate the settings for the port
159  tcflush(fd, TCIFLUSH);
160 
161  tcsetattr(fd, TCSANOW, &settings);
162 
163  connected = true;
164 
165  return 0;
166 }
167 
168 void
170 {
171  if (connected)
172  {
173  ::close(fd);
174  }
175 
176  connected = false;
177 }
178 
179 int
180 SerialInterface::readInternal(unsigned char* buf, unsigned int len)
181 {
182  int res;
183 
184  res = blockingReadAll(buf, len);
185 
186  if (res < 0)
187  {
188  std::cerr << "Failed to read from serial device" << std::endl;
189  }
190 
191  return res;
192 }
193 
194 int
195 SerialInterface::blockingReadAll(unsigned char* buf, unsigned int len)
196 {
197  int dataToRead = len;
198 
199  while (1)
200  {
201  int res = ::read(fd, buf, dataToRead);
202 
203  if (res < 0)
204  {
205  return res;
206  }
207 
208  dataToRead -= res;
209  buf += res;
210 
211  if (dataToRead == 0)
212  {
213  return len;
214  }
215 
216  if (dataToRead < 0)
217  {
218  throw new std::runtime_error("Internal error: dataToRead < 0");
219  }
220 
221  usleep(1);
222  }
223 }
224 
225 int
226 SerialInterface::writeInternal(unsigned char* buf, unsigned int len)
227 {
228  return (::write(fd, (void*)buf, len));
229 }
230 
231 std::string
233 {
234  return str(boost::format("SerialInterface(connected=%1%, device=%2%, bitrate=%3%, fd=%4%)") %
235  connected % device % bitrate % fd);
236 }
AbstractInterface::read
int read(unsigned char *buf, unsigned int len)
Definition: AbstractInterface.cpp:46
str
std::string str(const T &t)
Definition: UserAssistedSegmenterGuiWidgetController.cpp:43
SerialInterface::readInternal
int readInternal(unsigned char *, unsigned int) override
Definition: SerialInterface.cpp:180
string.h
AbstractInterface::write
int write(unsigned char *buf, unsigned int len)
Definition: AbstractInterface.cpp:59
SerialInterface::close
void close() override
Definition: SerialInterface.cpp:169
SerialInterface::open
int open() override
Definition: SerialInterface.cpp:94
SerialInterface::~SerialInterface
~SerialInterface() override
Definition: SerialInterface.cpp:89
SerialInterface.h
AbstractInterface::connected
bool connected
Definition: AbstractInterface.h:81
SerialInterface::SerialInterface
SerialInterface(const char *device, const unsigned int bitrate)
Definition: SerialInterface.cpp:82
SerialInterface::writeInternal
int writeInternal(unsigned char *, unsigned int) override
Definition: SerialInterface.cpp:226
SerialInterface::toString
std::string toString() const override
Definition: SerialInterface.cpp:232