Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <swri_serial_util/serial_port.h>
00031
00032 #include <errno.h>
00033 #include <sys/ioctl.h>
00034 #include <fcntl.h>
00035 #include <unistd.h>
00036 #include <poll.h>
00037 #include <termios.h>
00038 #include <linux/serial.h>
00039 #include <cstring>
00040
00041 #include <boost/lexical_cast.hpp>
00042
00043 namespace swri_serial_util
00044 {
00045 SerialConfig::SerialConfig() :
00046 baud(B115200),
00047 data_bits(8),
00048 stop_bits(1),
00049 parity(NO_PARITY),
00050 flow_control(false),
00051 low_latency_mode(false),
00052 writable(false)
00053 {
00054 }
00055
00056 SerialConfig::SerialConfig(
00057 int32_t baud,
00058 int32_t data_bits,
00059 int32_t stop_bits,
00060 Parity parity,
00061 bool flow_control,
00062 bool low_latency_mode,
00063 bool writable) :
00064 baud(baud),
00065 data_bits(data_bits),
00066 stop_bits(stop_bits),
00067 parity(parity),
00068 flow_control(flow_control),
00069 low_latency_mode(low_latency_mode),
00070 writable(writable)
00071 {
00072 }
00073
00074 SerialPort::SerialPort() :
00075 fd_(-1),
00076 error_msg_("")
00077 {
00078 }
00079
00080 SerialPort::~SerialPort()
00081 {
00082 Close();
00083 }
00084
00085 void SerialPort::Close()
00086 {
00087 if (fd_ < 0)
00088 return;
00089
00090 close(fd_);
00091 fd_ = -1;
00092 }
00093
00094 bool SerialPort::Open(const std::string &device, SerialConfig config)
00095 {
00096 Close();
00097
00098 int32_t baud = ParseBaudRate(config.baud);
00099 if (baud == -1)
00100 {
00101 error_msg_ = "Invalid baud rate: " + boost::lexical_cast<std::string>(config.baud);
00102 return false;
00103 }
00104
00105 if (config.stop_bits != 1 && config.stop_bits != 2)
00106 {
00107 error_msg_ = "Invalid stop bits: " + boost::lexical_cast<std::string>(config.stop_bits);
00108 return false;
00109 }
00110
00111 if (config.data_bits != 7 && config.data_bits != 8)
00112 {
00113 error_msg_ = "Invalid data bits: " + boost::lexical_cast<std::string>(config.data_bits);
00114 return false;
00115 }
00116
00117 if (config.parity != SerialConfig::NO_PARITY &&
00118 config.parity != SerialConfig::EVEN_PARITY &&
00119 config.parity != SerialConfig::ODD_PARITY)
00120 {
00121 error_msg_ = "Invalid parity mode.";
00122 return false;
00123 }
00124
00125 fd_ = open(device.c_str(), config.writable ? O_RDWR : O_RDONLY);
00126 if (fd_ == -1)
00127 {
00128 error_msg_ = "Error opening serial port <" + device + ">: " + strerror(errno);
00129 return false;
00130 }
00131
00132 struct termios term;
00133 if (tcgetattr(fd_, &term) < 0)
00134 {
00135 error_msg_ = "Unable to set serial attributes <" + device + ">: " + strerror(errno);
00136 Close();
00137 return false;
00138 }
00139
00140 cfmakeraw(&term);
00141
00142 if (config.stop_bits == 2)
00143 {
00144 term.c_cflag |= CSTOPB;
00145 }
00146 else
00147 {
00148 term.c_cflag &= ~CSTOPB;
00149 }
00150
00151 if (config.parity == SerialConfig::EVEN_PARITY)
00152 {
00153 term.c_cflag |= PARENB;
00154 term.c_cflag &= ~PARODD;
00155 }
00156 else if (config.parity == SerialConfig::ODD_PARITY)
00157 {
00158 term.c_cflag |= PARENB;
00159 term.c_cflag |= PARODD;
00160 }
00161 else
00162 {
00163 term.c_cflag &= ~PARENB;
00164 term.c_cflag &= ~PARODD;
00165 }
00166
00167 if (config.data_bits == 8)
00168 {
00169 term.c_cflag &= ~CSIZE;
00170 term.c_cflag |= CS8;
00171 }
00172 else
00173 {
00174 term.c_cflag &= ~CSIZE;
00175 term.c_cflag |= CS7;
00176 }
00177
00178 if (cfsetspeed(&term, config.baud) < 0)
00179 {
00180 error_msg_ = "Invalid baud rate: " + boost::lexical_cast<std::string>(config.baud);
00181 Close();
00182 return false;
00183 }
00184
00185 if (tcsetattr(fd_, TCSAFLUSH, &term) < 0)
00186 {
00187 error_msg_ = "Unable to set serial port attributes <" + device + ">: " + strerror(errno);
00188 Close();
00189 return false;
00190 }
00191
00192 if (config.low_latency_mode && !SetLowLatencyMode())
00193 {
00194 Close();
00195 return false;
00196 }
00197
00198 return true;
00199 }
00200
00201 bool SerialPort::SetLowLatencyMode()
00202 {
00203 if (fd_ < 0)
00204 {
00205 error_msg_ = "Device not open.";
00206 return false;
00207 }
00208
00209 struct serial_struct serial_info;
00210
00211 if (ioctl(fd_, TIOCGSERIAL, &serial_info) < 0)
00212 {
00213 error_msg_ = "Failed to set low latency mode. Cannot get serial configuration: " + std::string(strerror(errno));
00214 return false;
00215 }
00216
00217 serial_info.flags |= ASYNC_LOW_LATENCY;
00218
00219 if (ioctl(fd_, TIOCSSERIAL, &serial_info) < 0)
00220 {
00221 error_msg_ = "Failed to set low latency mode. Cannot set serial configuration: " + std::string(strerror(errno));
00222 return false;
00223 }
00224
00225 return true;
00226 }
00227
00228 int32_t SerialPort::ParseBaudRate(int32_t baud)
00229 {
00230 int32_t value = -1;
00231
00232 if (baud == B50 || baud == 50)
00233 {
00234 value = B50;
00235 }
00236 else if (baud == B75 || baud == 75)
00237 {
00238 value = B75;
00239 }
00240 else if (baud == B110 || baud == 110)
00241 {
00242 value = B110;
00243 }
00244 else if (baud == B134 || baud == 134)
00245 {
00246 value = B134;
00247 }
00248 else if (baud == B150 || baud == 150)
00249 {
00250 value = B150;
00251 }
00252 else if (baud == B200 || baud == 200)
00253 {
00254 value = B200;
00255 }
00256 else if (baud == B300 || baud == 300)
00257 {
00258 value = B300;
00259 }
00260 else if (baud == B600 || baud == 600)
00261 {
00262 value = B600;
00263 }
00264 else if (baud == B1200 || baud == 1200)
00265 {
00266 value = B1200;
00267 }
00268 else if (baud == B1800 || baud == 1800)
00269 {
00270 value = B1800;
00271 }
00272 else if (baud == B2400 || baud == 2400)
00273 {
00274 value = B2400;
00275 }
00276 else if (baud == B4800 || baud == 4800)
00277 {
00278 value = B4800;
00279 }
00280 else if (baud == B9600 || baud == 9600)
00281 {
00282 value = B9600;
00283 }
00284 else if (baud == B19200 || baud == 19200)
00285 {
00286 value = B19200;
00287 }
00288 else if (baud == B38400 || baud == 38400)
00289 {
00290 value = B38400;
00291 }
00292 else if (baud == B57600 || baud == 57600)
00293 {
00294 value = B57600;
00295 }
00296 else if (baud == B115200 || baud == 115200)
00297 {
00298 value = B115200;
00299 }
00300 else if (baud == B230400 || baud == 230400)
00301 {
00302 value = B230400;
00303 }
00304 else if (baud == B460800 || baud == 460800)
00305 {
00306 value = B460800;
00307 }
00308 else if (baud == B576000 || baud == 576000)
00309 {
00310 value = B576000;
00311 }
00312 else if (baud == B921600 || baud == 921600)
00313 {
00314 value = B921600;
00315 }
00316 else if (baud == B1000000 || baud == 1000000)
00317 {
00318 value = B1000000;
00319 }
00320 else if (baud == B1152000 || baud == 1152000)
00321 {
00322 value = B1152000;
00323 }
00324 else if (baud == B1500000 || baud == 1500000)
00325 {
00326 value = B1500000;
00327 }
00328 else if (baud == B2000000 || baud == 2000000)
00329 {
00330 value = B2000000;
00331 }
00332 else if (baud == B2500000 || baud == 2500000)
00333 {
00334 value = B2500000;
00335 }
00336 else if (baud == B3000000 || baud == 3000000)
00337 {
00338 value = B3000000;
00339 }
00340 else if (baud == B3500000 || baud == 3500000)
00341 {
00342 value = B3500000;
00343 }
00344 else if (baud == B4000000 || baud == 4000000)
00345 {
00346 value = B4000000;
00347 }
00348
00349 return value;
00350 }
00351
00352 SerialPort::Result SerialPort::ReadBytes(std::vector<uint8_t>& output, size_t max_bytes, int32_t timeout)
00353 {
00354 if (fd_ < 0)
00355 {
00356 error_msg_ = "Device not open.";
00357 return ERROR;
00358 }
00359
00360 struct pollfd fds[1];
00361 fds[0].fd = fd_;
00362 fds[0].events = POLLIN;
00363
00364 int poll_return = poll(fds, 1, timeout);
00365 if (poll_return == 0)
00366 {
00367 error_msg_ = "Timed out while waiting for data.";
00368 return TIMEOUT;
00369 }
00370 else if (poll_return < 0)
00371 {
00372 int error_num = errno;
00373 switch (error_num)
00374 {
00375 case EINTR:
00376 return INTERRUPTED;
00377 default:
00378 error_msg_ = "Error polling serial port: " + std::string(strerror(errno));
00379 return ERROR;
00380 }
00381 }
00382
00383 size_t to_read = max_bytes;
00384 if (to_read <= 0)
00385 {
00386 int bytes;
00387 ioctl(fd_, FIONREAD, &bytes);
00388 if (bytes < 0)
00389 {
00390 error_msg_ = "Error getting number of available bytes from serial port: " + std::string(strerror(errno));
00391 return ERROR;
00392 }
00393 to_read = static_cast<size_t>(bytes);
00394 }
00395
00396 size_t output_size = output.size();
00397 output.resize(output_size + to_read);
00398
00399 int result = read(fd_, output.data() + output_size, to_read);
00400
00401 if (result > 0)
00402 {
00403 output.resize(output_size + result);
00404 }
00405 else
00406 {
00407 output.resize(output_size);
00408 }
00409
00410 if (result > 0)
00411 {
00412 return SUCCESS;
00413 }
00414 else if (result == 0)
00415 {
00416 return INTERRUPTED;
00417 }
00418 else
00419 {
00420 int error_num = errno;
00421 switch (error_num)
00422 {
00423 case EINTR:
00424 return INTERRUPTED;
00425 break;
00426 default:
00427 error_msg_ = "Error reading serial port: " + std::string(strerror(errno));
00428 return ERROR;
00429 }
00430 }
00431 }
00432
00433 int32_t SerialPort::Write(const std::vector<uint8_t>& input)
00434 {
00435 return write(fd_, input.data(), input.size());
00436 }
00437 }