2012-01-11 17:48:31 -06:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <paths.h>
|
|
|
|
|
#include <sysexits.h>
|
|
|
|
|
#include <termios.h>
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
|
#include <sys/select.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
|
2012-01-10 14:19:56 -06:00
|
|
|
#include "serial/impl/unix.h"
|
|
|
|
|
|
2012-01-11 17:48:31 -06:00
|
|
|
#ifndef TIOCINQ
|
|
|
|
|
#ifdef FIONREAD
|
|
|
|
|
#define TIOCINQ FIONREAD
|
|
|
|
|
#else
|
|
|
|
|
#define TIOCINQ 0x541B
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
using std::string;
|
2012-01-12 16:44:19 -06:00
|
|
|
using std::invalid_argument;
|
|
|
|
|
using serial::Serial;
|
|
|
|
|
using serial::SerialExecption;
|
|
|
|
|
using serial::PortNotOpenedException;
|
|
|
|
|
using serial::IOException;
|
2012-01-10 14:19:56 -06:00
|
|
|
|
2012-01-12 16:44:19 -06:00
|
|
|
Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
|
2012-01-11 23:53:10 -06:00
|
|
|
long timeout, bytesize_t bytesize,
|
|
|
|
|
parity_t parity, stopbits_t stopbits,
|
|
|
|
|
flowcontrol_t flowcontrol)
|
2012-01-12 16:44:19 -06:00
|
|
|
: port_(port), fd_(-1), interCharTimeout_(-1), writeTimeout_(-1),
|
|
|
|
|
isOpen_(false), xonxoff_(false), rtscts_(false), ___(0), timeout_(timeout),
|
|
|
|
|
baudrate_(baudrate), parity_(parity), bytesize_(bytesize),
|
|
|
|
|
stopbits_(stopbits), flowcontrol_(flowcontrol)
|
2012-01-10 14:19:56 -06:00
|
|
|
{
|
2012-01-11 23:53:10 -06:00
|
|
|
if (port_.empty() == false) this->open();
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::~SerialImpl () {
|
|
|
|
|
this->close();
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::open () {
|
2012-01-12 12:46:08 -06:00
|
|
|
if (port_.empty()) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw invalid_argument("bad port specified");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
if (isOpen_ == true) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw SerialExecption("port already open");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
|
|
|
|
|
|
|
|
|
|
if (fd_ == -1) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw IOException("invalid file descriptor");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reconfigurePort();
|
|
|
|
|
isOpen_ = true;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::reconfigurePort () {
|
2012-01-12 12:46:08 -06:00
|
|
|
if (fd_ == -1) {
|
2012-01-12 16:44:19 -06:00
|
|
|
// Can only operate on a valid file descriptor
|
|
|
|
|
throw IOException("invalid file descriptor");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
2012-01-12 12:54:45 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
struct termios options; // The current options for the file descriptor
|
|
|
|
|
struct termios originalTTYAttrs; // The orignal file descriptor options
|
2012-01-12 12:54:45 -06:00
|
|
|
|
2012-01-13 09:08:09 -06:00
|
|
|
uint8_t vmin = 0, vtime = 0; // timeout is done via select
|
2012-01-11 17:48:31 -06:00
|
|
|
if (interCharTimeout_ == -1) {
|
2012-01-12 12:46:08 -06:00
|
|
|
vmin = 1;
|
2012-01-12 16:44:19 -06:00
|
|
|
vtime = uint8_t(interCharTimeout_ * 10);
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
2012-01-13 09:08:09 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
if (tcgetattr(fd_, &originalTTYAttrs) == -1) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw IOException("::tcgetattr");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
2012-01-12 12:54:45 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
options = originalTTYAttrs;
|
2012-01-12 12:54:45 -06:00
|
|
|
|
2012-01-11 17:48:31 -06:00
|
|
|
// set up raw mode / no echo / binary
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_cflag |= (unsigned long)(CLOCAL|CREAD);
|
|
|
|
|
options.c_lflag &= (unsigned long) ~(ICANON|ECHO|ECHOE|ECHOK
|
2012-01-13 09:08:09 -06:00
|
|
|
|ECHONL|ISIG|IEXTEN); //|ECHOPRT
|
2012-01-11 17:48:31 -06:00
|
|
|
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_oflag &= (unsigned long) ~(OPOST);
|
|
|
|
|
options.c_iflag &= (unsigned long) ~(INLCR|IGNCR|ICRNL|IGNBRK);
|
2012-01-11 17:48:31 -06:00
|
|
|
#ifdef IUCLC
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_iflag &= (unsigned long) ~IUCLC;
|
2012-01-11 17:48:31 -06:00
|
|
|
#endif
|
|
|
|
|
#ifdef PARMRK
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_iflag &= (unsigned long) ~PARMRK;
|
2012-01-11 17:48:31 -06:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// setup baud rate
|
2012-01-12 12:46:08 -06:00
|
|
|
// TODO(ash_git): validate baud rate
|
|
|
|
|
cfsetspeed(&options, baudrate_);
|
2012-01-11 17:48:31 -06:00
|
|
|
|
|
|
|
|
// setup char len
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_cflag &= (unsigned long) ~CSIZE;
|
2012-01-11 17:48:31 -06:00
|
|
|
if (bytesize_ == EIGHTBITS)
|
|
|
|
|
options.c_cflag |= CS8;
|
|
|
|
|
else if (bytesize_ == SEVENBITS)
|
|
|
|
|
options.c_cflag |= CS7;
|
|
|
|
|
else if (bytesize_ == SIXBITS)
|
|
|
|
|
options.c_cflag |= CS6;
|
|
|
|
|
else if (bytesize_ == FIVEBITS)
|
|
|
|
|
options.c_cflag |= CS5;
|
|
|
|
|
else
|
2012-01-12 16:44:19 -06:00
|
|
|
throw invalid_argument("Invalid char len");
|
2012-01-11 17:48:31 -06:00
|
|
|
// setup stopbits
|
|
|
|
|
if (stopbits_ == STOPBITS_ONE)
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_cflag &= (unsigned long) ~(CSTOPB);
|
2012-01-11 17:48:31 -06:00
|
|
|
else if (stopbits_ == STOPBITS_ONE_POINT_FIVE)
|
|
|
|
|
options.c_cflag |= (CSTOPB); // XXX same as TWO.. there is no POSIX support for 1.5
|
|
|
|
|
else if (stopbits_ == STOPBITS_TWO)
|
|
|
|
|
options.c_cflag |= (CSTOPB);
|
2012-01-12 12:46:08 -06:00
|
|
|
else
|
2012-01-12 16:44:19 -06:00
|
|
|
throw invalid_argument("invalid stop bit");
|
2012-01-11 17:48:31 -06:00
|
|
|
// setup parity
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_iflag &= (unsigned long) ~(INPCK|ISTRIP);
|
2012-01-11 17:48:31 -06:00
|
|
|
if (parity_ == PARITY_NONE) {
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_cflag &= (unsigned long) ~(PARENB|PARODD);
|
2012-01-11 17:48:31 -06:00
|
|
|
}
|
2012-01-12 12:46:08 -06:00
|
|
|
else if (parity_ == PARITY_EVEN) {
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_cflag &= (unsigned long) ~(PARODD);
|
2012-01-11 17:48:31 -06:00
|
|
|
options.c_cflag |= (PARENB);
|
|
|
|
|
}
|
2012-01-12 12:46:08 -06:00
|
|
|
else if (parity_ == PARITY_ODD) {
|
2012-01-11 17:48:31 -06:00
|
|
|
options.c_cflag |= (PARENB|PARODD);
|
|
|
|
|
}
|
2012-01-12 12:46:08 -06:00
|
|
|
else {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw invalid_argument("invalid parity");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
2012-01-11 17:48:31 -06:00
|
|
|
// setup flow control
|
|
|
|
|
// xonxoff
|
|
|
|
|
#ifdef IXANY
|
|
|
|
|
if (xonxoff_)
|
|
|
|
|
options.c_iflag |= (IXON|IXOFF); //|IXANY)
|
|
|
|
|
else
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_iflag &= (unsigned long) ~(IXON|IXOFF|IXANY);
|
2012-01-11 17:48:31 -06:00
|
|
|
#else
|
|
|
|
|
if (xonxoff_)
|
|
|
|
|
options.c_iflag |= (IXON|IXOFF);
|
|
|
|
|
else
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_iflag &= (unsigned long) ~(IXON|IXOFF);
|
2012-01-11 17:48:31 -06:00
|
|
|
#endif
|
|
|
|
|
// rtscts
|
|
|
|
|
#ifdef CRTSCTS
|
|
|
|
|
if (rtscts_)
|
|
|
|
|
options.c_cflag |= (CRTSCTS);
|
|
|
|
|
else
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_cflag &= (unsigned long) ~(CRTSCTS);
|
2012-01-11 17:48:31 -06:00
|
|
|
#elif defined CNEW_RTSCTS
|
|
|
|
|
if (rtscts_)
|
2012-01-12 12:46:08 -06:00
|
|
|
options.c_cflag |= (CNEW_RTSCTS);
|
2012-01-11 17:48:31 -06:00
|
|
|
else
|
2012-01-12 16:44:19 -06:00
|
|
|
options.c_cflag &= (unsigned long) ~(CNEW_RTSCTS);
|
2012-01-11 17:48:31 -06:00
|
|
|
#else
|
|
|
|
|
#error "OS Support seems wrong."
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// buffer
|
|
|
|
|
// vmin "minimal number of characters to be read. = for non blocking"
|
|
|
|
|
options.c_cc[VMIN] = vmin;
|
|
|
|
|
// vtime
|
|
|
|
|
options.c_cc[VTIME] = vtime;
|
|
|
|
|
|
|
|
|
|
// activate settings
|
2012-01-12 12:46:08 -06:00
|
|
|
::tcsetattr(fd_, TCSANOW, &options);
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-11 17:48:31 -06:00
|
|
|
void
|
|
|
|
|
Serial::SerialImpl::close () {
|
2012-01-12 12:46:08 -06:00
|
|
|
if (isOpen_ == true) {
|
|
|
|
|
if (fd_ != -1) {
|
2012-01-12 16:44:19 -06:00
|
|
|
::close(fd_); // Ignoring the outcome
|
2012-01-12 12:46:08 -06:00
|
|
|
fd_ = -1;
|
|
|
|
|
}
|
|
|
|
|
isOpen_ = false;
|
|
|
|
|
}
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-11 17:48:31 -06:00
|
|
|
bool
|
2012-01-12 16:44:19 -06:00
|
|
|
Serial::SerialImpl::isOpen () const {
|
2012-01-11 17:48:31 -06:00
|
|
|
return isOpen_;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::available () {
|
2012-01-12 12:46:08 -06:00
|
|
|
if (!isOpen_) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
int count = 0;
|
|
|
|
|
int result = ioctl(fd_, TIOCINQ, &count);
|
|
|
|
|
if (result == 0) {
|
2012-01-12 16:44:19 -06:00
|
|
|
return (size_t)count;
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
else {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw IOException("ioctl");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-11 17:48:31 -06:00
|
|
|
string
|
|
|
|
|
Serial::SerialImpl::read (size_t size) {
|
|
|
|
|
if (!isOpen_) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::read");
|
2012-01-11 17:48:31 -06:00
|
|
|
}
|
2012-01-12 12:46:08 -06:00
|
|
|
string message = "";
|
2012-01-13 11:33:55 -06:00
|
|
|
char *buf = NULL;
|
|
|
|
|
// Using size+1 to leave room for a null character
|
|
|
|
|
if (size > 1024) {
|
|
|
|
|
buf = (char*)malloc((size + 1) * sizeof(*buf));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
buf = (char*)alloca((size + 1) * sizeof(*buf));
|
|
|
|
|
}
|
2012-01-12 12:46:08 -06:00
|
|
|
fd_set readfds;
|
2012-01-13 11:33:55 -06:00
|
|
|
memset(buf, 0, (size + 1) * sizeof(*buf));
|
|
|
|
|
ssize_t bytes_read = 0;
|
2012-01-13 11:58:33 -06:00
|
|
|
while (bytes_read < size) {
|
|
|
|
|
if (timeout_ != -1) {
|
2012-01-13 11:33:55 -06:00
|
|
|
FD_ZERO(&readfds);
|
|
|
|
|
FD_SET(fd_, &readfds);
|
|
|
|
|
struct timeval timeout;
|
|
|
|
|
timeout.tv_sec = timeout_ / 1000;
|
|
|
|
|
timeout.tv_usec = (int) timeout_ % 1000;
|
|
|
|
|
int r = select(fd_ + 1, &readfds, NULL, NULL, &timeout);
|
|
|
|
|
|
|
|
|
|
if (r == -1 && errno == EINTR)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (r == -1) {
|
|
|
|
|
perror("select()");
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
2012-01-11 17:48:31 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-13 11:58:33 -06:00
|
|
|
if (timeout_ == -1 || FD_ISSET(fd_, &readfds)) {
|
2012-01-13 11:33:55 -06:00
|
|
|
ssize_t newest_read = ::read(fd_,
|
|
|
|
|
buf + bytes_read,
|
|
|
|
|
size - static_cast<size_t>(bytes_read));
|
2012-01-12 12:46:08 -06:00
|
|
|
// read should always return some data as select reported it was
|
|
|
|
|
// ready to read when we get to this point.
|
2012-01-13 11:33:55 -06:00
|
|
|
if (newest_read < 1) {
|
2012-01-12 12:46:08 -06:00
|
|
|
// Disconnected devices, at least on Linux, show the
|
|
|
|
|
// behavior that they are always ready to read immediately
|
|
|
|
|
// but reading returns nothing.
|
2012-01-13 09:08:09 -06:00
|
|
|
throw SerialExecption("device reports readiness to read but "
|
|
|
|
|
"returned no data (device disconnected?)");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
2012-01-13 11:33:55 -06:00
|
|
|
bytes_read += newest_read;
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
break; // Timeout
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-01-13 11:33:55 -06:00
|
|
|
if (bytes_read > 0)
|
|
|
|
|
message.append(buf, (size_t)bytes_read);
|
|
|
|
|
if (size > 1024)
|
|
|
|
|
free(buf);
|
2012-01-11 17:48:31 -06:00
|
|
|
return message;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::write (const string &data) {
|
2012-01-11 21:53:26 -06:00
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::write");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
2012-01-12 16:44:19 -06:00
|
|
|
ssize_t n = ::write(fd_, data.c_str(), data.length());
|
2012-01-12 12:46:08 -06:00
|
|
|
if (n == -1) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw IOException("Write");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
2012-01-12 16:44:19 -06:00
|
|
|
return (size_t)n;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::setPort (const string &port) {
|
|
|
|
|
port_ = port;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-11 17:48:31 -06:00
|
|
|
string
|
|
|
|
|
Serial::SerialImpl::getPort () const {
|
|
|
|
|
return port_;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::setTimeout (long timeout) {
|
2012-01-11 21:53:26 -06:00
|
|
|
timeout_ = timeout;
|
2012-01-12 13:03:26 -06:00
|
|
|
if (isOpen_) reconfigurePort();
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::getTimeout () const {
|
2012-01-11 21:53:26 -06:00
|
|
|
return timeout_;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-01-12 16:44:19 -06:00
|
|
|
Serial::SerialImpl::setBaudrate (unsigned long baudrate) {
|
2012-01-12 12:46:08 -06:00
|
|
|
baudrate_ = baudrate;
|
2012-01-12 13:03:26 -06:00
|
|
|
if (isOpen_) reconfigurePort();
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-12 16:44:19 -06:00
|
|
|
unsigned long
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::getBaudrate () const {
|
|
|
|
|
return baudrate_;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) {
|
2012-01-12 12:46:08 -06:00
|
|
|
bytesize_ = bytesize;
|
2012-01-12 13:03:26 -06:00
|
|
|
if (isOpen_) reconfigurePort();
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-11 17:48:31 -06:00
|
|
|
serial::bytesize_t
|
|
|
|
|
Serial::SerialImpl::getBytesize () const {
|
2012-01-11 21:53:26 -06:00
|
|
|
return bytesize_;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::setParity (serial::parity_t parity) {
|
2012-01-11 21:53:26 -06:00
|
|
|
parity_ = parity;
|
2012-01-12 13:03:26 -06:00
|
|
|
if (isOpen_) reconfigurePort();
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-11 17:48:31 -06:00
|
|
|
serial::parity_t
|
|
|
|
|
Serial::SerialImpl::getParity () const {
|
2012-01-11 21:53:26 -06:00
|
|
|
return parity_;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) {
|
2012-01-11 21:53:26 -06:00
|
|
|
stopbits_ = stopbits;
|
2012-01-12 13:03:26 -06:00
|
|
|
if (isOpen_) reconfigurePort();
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-11 17:48:31 -06:00
|
|
|
serial::stopbits_t
|
|
|
|
|
Serial::SerialImpl::getStopbits () const {
|
2012-01-11 21:53:26 -06:00
|
|
|
return stopbits_;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-01-11 17:48:31 -06:00
|
|
|
Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) {
|
2012-01-11 21:53:26 -06:00
|
|
|
flowcontrol_ = flowcontrol;
|
2012-01-12 13:03:26 -06:00
|
|
|
if (isOpen_) reconfigurePort();
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-11 17:48:31 -06:00
|
|
|
serial::flowcontrol_t
|
|
|
|
|
Serial::SerialImpl::getFlowcontrol () const {
|
2012-01-11 21:53:26 -06:00
|
|
|
return flowcontrol_;
|
2012-01-10 14:19:56 -06:00
|
|
|
}
|
|
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
void Serial::SerialImpl::flush () {
|
|
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::flush");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
tcdrain(fd_);
|
|
|
|
|
}
|
2012-01-13 09:08:09 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
void Serial::SerialImpl::flushInput () {
|
|
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::flushInput");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
tcflush(fd_, TCIFLUSH);
|
|
|
|
|
}
|
2012-01-13 09:08:09 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
void Serial::SerialImpl::flushOutput () {
|
|
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::flushOutput");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
tcflush(fd_, TCOFLUSH);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Serial::SerialImpl::sendBreak(int duration) {
|
|
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::sendBreak");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
tcsendbreak(fd_, int(duration/4));
|
|
|
|
|
}
|
2012-01-13 09:08:09 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
void Serial::SerialImpl::setBreak(bool level) {
|
|
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::setBreak");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
if (level) {
|
|
|
|
|
ioctl(fd_, TIOCSBRK);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ioctl(fd_, TIOCCBRK);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-01-13 09:08:09 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
void Serial::SerialImpl::setRTS(bool level) {
|
|
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::setRTS");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
if (level) {
|
|
|
|
|
ioctl(fd_, TIOCMBIS, TIOCM_RTS);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ioctl(fd_, TIOCMBIC, TIOCM_RTS);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-01-13 09:08:09 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
void Serial::SerialImpl::setDTR(bool level) {
|
|
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::setDTR");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
if (level) {
|
|
|
|
|
ioctl(fd_, TIOCMBIS, TIOCM_DTR);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ioctl(fd_, TIOCMBIC, TIOCM_DTR);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-01-13 09:08:09 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
bool Serial::SerialImpl::getCTS() {
|
|
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::getCTS");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
int s = ioctl(fd_, TIOCMGET, 0);
|
|
|
|
|
return (s & TIOCM_CTS) != 0;
|
|
|
|
|
}
|
2012-01-13 09:08:09 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
bool Serial::SerialImpl::getDSR() {
|
|
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::getDSR");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
int s = ioctl(fd_, TIOCMGET, 0);
|
|
|
|
|
return (s & TIOCM_DSR) != 0;
|
|
|
|
|
}
|
2012-01-13 09:08:09 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
bool Serial::SerialImpl::getRI() {
|
|
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::getRI");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
int s = ioctl(fd_, TIOCMGET, 0);
|
|
|
|
|
return (s & TIOCM_RI) != 0;
|
|
|
|
|
}
|
2012-01-13 09:08:09 -06:00
|
|
|
|
2012-01-12 12:46:08 -06:00
|
|
|
bool Serial::SerialImpl::getCD() {
|
|
|
|
|
if (isOpen_ == false) {
|
2012-01-12 16:44:19 -06:00
|
|
|
throw PortNotOpenedException("Serial::getCD");
|
2012-01-12 12:46:08 -06:00
|
|
|
}
|
|
|
|
|
int s = ioctl(fd_, TIOCMGET, 0);
|
|
|
|
|
return (s & TIOCM_CD) != 0;
|
|
|
|
|
}
|