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 <iostream>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <termios.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/ioctl.h>
37 #include <iostream>
38 #include <boost/format.hpp>
39 
40 static inline tcflag_t __bitrate_to_flag(unsigned int bitrate)
41 {
42  switch (bitrate)
43  {
44  case 1200:
45  return B1200;
46 
47  case 2400:
48  return B2400;
49 
50  case 4800:
51  return B4800;
52 
53  case 9600:
54  return B9600;
55 
56  case 19200:
57  return B19200;
58 
59  case 38400:
60  return B38400;
61 
62  case 57600:
63  return B57600;
64 
65  case 115200:
66  return B115200;
67 
68  case 230400:
69  return B230400;
70 
71  case 460800:
72  return B460800;
73 
74  default:
75  return 0;
76  }
77 }
78 
79 
80 SerialInterface::SerialInterface(const char* device, unsigned int bitrate)
81 {
82  this->device = device;
83  this->bitrate = bitrate;
84  this->fd = -1;
85 }
86 
88 {
89 
90 }
91 
93 {
94  // Convert bitrate to flag
95  tcflag_t bitrate = __bitrate_to_flag(this->bitrate);
96 
97  if (bitrate == 0)
98  {
99  fprintf(stderr, "Invalid bitrate '%d' for serial device\n", this->bitrate);
100  return -1;
101  }
102 
103 
104  // Open serial device
105  fd = ::open(device, O_RDWR | O_NOCTTY);
106 
107  if (fd < 0)
108  {
109  fprintf(stderr, "Failed to open serial device '%s' (errno: %s)\n", device, strerror(errno));
110  return -1;
111  }
112 
113  if (::ioctl(fd, TIOCEXCL))
114  {
115  fprintf(stderr, "Failed to lock serial device '%s' (errno: %s)\n", device, strerror(errno));
116  return -1;
117  }
118 
119 
120 
121  // Check if device is a terminal device
122  if (!isatty(fd))
123  {
124  fprintf(stderr, "Device '%s' is not a terminal device (errno: %s)!\n", device, strerror(errno));
125  ::close(fd);
126  return -1;
127  }
128 
129  struct termios settings;
130 
131  // Set input flags
132  settings.c_iflag = IGNBRK // Ignore BREAKS on Input
133  | IGNPAR; // No Parity
134 
135  // ICRNL: map CR to NL (otherwise a CR input on the other computer will not terminate input)
136 
137  // Set output flags
138  settings.c_oflag = 0; // Raw output
139 
140  // Set controlflags
141  settings.c_cflag = bitrate
142  | CS8 // 8 bits per byte
143  | CSTOPB // Stop bit
144  | CREAD // characters may be read
145  | CLOCAL; // ignore modem state, local connection
146 
147  // Set local flags
148  settings.c_lflag = 0; // Other option: ICANON = enable canonical input
149 
150  // Set maximum wait time on input - cf. Linux Serial Programming HowTo, non-canonical mode
151  // http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html
152  settings.c_cc[VTIME] = 10; // 0 means timer is not uses
153 
154  // Set minimum bytes to read
155  settings.c_cc[VMIN] = 0; // 1 means wait until at least 1 character is received
156 
157  // Now clean the modem line and activate the settings for the port
158  tcflush(fd, TCIFLUSH);
159 
160  tcsetattr(fd, TCSANOW, &settings);
161 
162  connected = true;
163 
164  return 0;
165 }
166 
168 {
169  if (connected)
170  {
171  ::close(fd);
172  }
173 
174  connected = false;
175 }
176 
177 int SerialInterface::readInternal(unsigned char* buf, unsigned int len)
178 {
179  int res;
180 
181  res = blockingReadAll(buf, len);
182 
183  if (res < 0)
184  {
185  std::cerr << "Failed to read from serial device" << std::endl;
186  }
187 
188  return res;
189 
190 }
191 
192 int SerialInterface::blockingReadAll(unsigned char* buf, unsigned int len)
193 {
194  int dataToRead = len;
195 
196  while (1)
197  {
198  int res = ::read(fd, buf, dataToRead);
199 
200  if (res < 0)
201  {
202  return res;
203  }
204 
205  dataToRead -= res;
206  buf += res;
207 
208  if (dataToRead == 0)
209  {
210  return len;
211  }
212 
213  if (dataToRead < 0)
214  {
215  throw new std::runtime_error("Internal error: dataToRead < 0");
216  }
217 
218  usleep(1);
219  }
220 }
221 
222 int SerialInterface::writeInternal(unsigned char* buf, unsigned int len)
223 {
224  return (::write(fd, (void*) buf, len));
225 }
226 
227 
228 std::string SerialInterface::toString() const
229 {
230  return str(boost::format("SerialInterface(connected=%1%, device=%2%, bitrate=%3%, fd=%4%)")
231  % connected % device % bitrate % fd);
232 }
AbstractInterface::read
int read(unsigned char *buf, unsigned int len)
Definition: AbstractInterface.cpp:45
str
std::string str(const T &t)
Definition: UserAssistedSegmenterGuiWidgetController.cpp:42
SerialInterface::readInternal
int readInternal(unsigned char *, unsigned int) override
Definition: SerialInterface.cpp:177
string.h
AbstractInterface::write
int write(unsigned char *buf, unsigned int len)
Definition: AbstractInterface.cpp:57
SerialInterface::close
void close() override
Definition: SerialInterface.cpp:167
SerialInterface::open
int open() override
Definition: SerialInterface.cpp:92
SerialInterface::~SerialInterface
~SerialInterface() override
Definition: SerialInterface.cpp:87
SerialInterface.h
AbstractInterface::connected
bool connected
Definition: AbstractInterface.h:77
SerialInterface::SerialInterface
SerialInterface(const char *device, const unsigned int bitrate)
Definition: SerialInterface.cpp:80
SerialInterface::writeInternal
int writeInternal(unsigned char *, unsigned int) override
Definition: SerialInterface.cpp:222
SerialInterface::toString
std::string toString() const override
Definition: SerialInterface.cpp:228