serial  1.2.1
Cross-platform, serial port library written in C++
Public Member Functions | Protected Member Functions
serial::serial::Serial::SerialImpl Class Reference

#include <unix.h>

Public Member Functions

 SerialImpl (const string &port, unsigned long baudrate, bytesize_t bytesize, parity_t parity, stopbits_t stopbits, flowcontrol_t flowcontrol)
 
virtual ~SerialImpl ()
 
void open ()
 
void close ()
 
bool isOpen () const
 
size_t available ()
 
bool waitReadable (uint32_t timeout)
 
void waitByteTimes (size_t count)
 
size_t read (uint8_t *buf, size_t size=1)
 
size_t write (const uint8_t *data, size_t length)
 
void flush ()
 
void flushInput ()
 
void flushOutput ()
 
void sendBreak (int duration)
 
void setBreak (bool level)
 
void setRTS (bool level)
 
void setDTR (bool level)
 
bool waitForChange ()
 
bool getCTS ()
 
bool getDSR ()
 
bool getRI ()
 
bool getCD ()
 
void setPort (const string &port)
 
string getPort () const
 
void setTimeout (Timeout &timeout)
 
Timeout getTimeout () const
 
void setBaudrate (unsigned long baudrate)
 
unsigned long getBaudrate () const
 
void setBytesize (bytesize_t bytesize)
 
bytesize_t getBytesize () const
 
void setParity (parity_t parity)
 
parity_t getParity () const
 
void setStopbits (stopbits_t stopbits)
 
stopbits_t getStopbits () const
 
void setFlowcontrol (flowcontrol_t flowcontrol)
 
flowcontrol_t getFlowcontrol () const
 
void readLock ()
 
void readUnlock ()
 
void writeLock ()
 
void writeUnlock ()
 

Protected Member Functions

void reconfigurePort ()
 

Constructor & Destructor Documentation

Serial::SerialImpl::SerialImpl ( const string &  port,
unsigned long  baudrate,
bytesize_t  bytesize,
parity_t  parity,
stopbits_t  stopbits,
flowcontrol_t  flowcontrol 
)
112  : port_ (port), fd_ (-1), is_open_ (false), xonxoff_ (false), rtscts_ (false),
113  baudrate_ (baudrate), parity_ (parity),
114  bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol)
115 {
116  pthread_mutex_init(&this->read_mutex, NULL);
117  pthread_mutex_init(&this->write_mutex, NULL);
118  if (port_.empty () == false)
119  open ();
120 }
void open()
Definition: unix.cc:130
Serial::SerialImpl::~SerialImpl ( )
virtual
123 {
124  close();
125  pthread_mutex_destroy(&this->read_mutex);
126  pthread_mutex_destroy(&this->write_mutex);
127 }
void close()
Definition: unix.cc:455

Member Function Documentation

size_t Serial::SerialImpl::available ( )
479 {
480  if (!is_open_) {
481  return 0;
482  }
483  int count = 0;
484  if (-1 == ioctl (fd_, TIOCINQ, &count)) {
485  THROW (IOException, errno);
486  } else {
487  return static_cast<size_t> (count);
488  }
489 }
#define TIOCINQ
Definition: unix.cc:41
Definition: serial.h:690
#define THROW(exceptionClass, message)
Definition: serial.h:48
void Serial::SerialImpl::close ( )
456 {
457  if (is_open_ == true) {
458  if (fd_ != -1) {
459  int ret;
460  ret = ::close (fd_);
461  if (ret == 0) {
462  fd_ = -1;
463  } else {
464  THROW (IOException, errno);
465  }
466  }
467  is_open_ = false;
468  }
469 }
void close()
Definition: unix.cc:455
Definition: serial.h:690
#define THROW(exceptionClass, message)
Definition: serial.h:48
void Serial::SerialImpl::flush ( )
790 {
791  if (is_open_ == false) {
792  throw PortNotOpenedException ("Serial::flush");
793  }
794  tcdrain (fd_);
795 }
Definition: serial.h:729
void Serial::SerialImpl::flushInput ( )
799 {
800  if (is_open_ == false) {
801  throw PortNotOpenedException ("Serial::flushInput");
802  }
803  tcflush (fd_, TCIFLUSH);
804 }
Definition: serial.h:729
void Serial::SerialImpl::flushOutput ( )
808 {
809  if (is_open_ == false) {
810  throw PortNotOpenedException ("Serial::flushOutput");
811  }
812  tcflush (fd_, TCOFLUSH);
813 }
Definition: serial.h:729
unsigned long Serial::SerialImpl::getBaudrate ( ) const
728 {
729  return baudrate_;
730 }
serial::bytesize_t Serial::SerialImpl::getBytesize ( ) const
742 {
743  return bytesize_;
744 }
bool Serial::SerialImpl::getCD ( )
1008 {
1009  if (is_open_ == false) {
1010  throw PortNotOpenedException ("Serial::getCD");
1011  }
1012 
1013  int status;
1014 
1015  if (-1 == ioctl (fd_, TIOCMGET, &status))
1016  {
1017  stringstream ss;
1018  ss << "getCD failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno);
1019  throw(SerialException(ss.str().c_str()));
1020  }
1021  else
1022  {
1023  return 0 != (status & TIOCM_CD);
1024  }
1025 }
Definition: serial.h:672
Definition: serial.h:729
bool Serial::SerialImpl::getCTS ( )
945 {
946  if (is_open_ == false) {
947  throw PortNotOpenedException ("Serial::getCTS");
948  }
949 
950  int status;
951 
952  if (-1 == ioctl (fd_, TIOCMGET, &status))
953  {
954  stringstream ss;
955  ss << "getCTS failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno);
956  throw(SerialException(ss.str().c_str()));
957  }
958  else
959  {
960  return 0 != (status & TIOCM_CTS);
961  }
962 }
Definition: serial.h:672
Definition: serial.h:729
bool Serial::SerialImpl::getDSR ( )
966 {
967  if (is_open_ == false) {
968  throw PortNotOpenedException ("Serial::getDSR");
969  }
970 
971  int status;
972 
973  if (-1 == ioctl (fd_, TIOCMGET, &status))
974  {
975  stringstream ss;
976  ss << "getDSR failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno);
977  throw(SerialException(ss.str().c_str()));
978  }
979  else
980  {
981  return 0 != (status & TIOCM_DSR);
982  }
983 }
Definition: serial.h:672
Definition: serial.h:729
serial::flowcontrol_t Serial::SerialImpl::getFlowcontrol ( ) const
784 {
785  return flowcontrol_;
786 }
serial::parity_t Serial::SerialImpl::getParity ( ) const
756 {
757  return parity_;
758 }
string Serial::SerialImpl::getPort ( ) const
702 {
703  return port_;
704 }
bool Serial::SerialImpl::getRI ( )
987 {
988  if (is_open_ == false) {
989  throw PortNotOpenedException ("Serial::getRI");
990  }
991 
992  int status;
993 
994  if (-1 == ioctl (fd_, TIOCMGET, &status))
995  {
996  stringstream ss;
997  ss << "getRI failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno);
998  throw(SerialException(ss.str().c_str()));
999  }
1000  else
1001  {
1002  return 0 != (status & TIOCM_RI);
1003  }
1004 }
Definition: serial.h:672
Definition: serial.h:729
serial::stopbits_t Serial::SerialImpl::getStopbits ( ) const
770 {
771  return stopbits_;
772 }
serial::Timeout Serial::SerialImpl::getTimeout ( ) const
714 {
715  return timeout_;
716 }
bool Serial::SerialImpl::isOpen ( ) const
473 {
474  return is_open_;
475 }
void Serial::SerialImpl::open ( )
131 {
132  if (port_.empty ()) {
133  throw invalid_argument ("Empty port is invalid.");
134  }
135  if (is_open_ == true) {
136  throw SerialException ("Serial port already open.");
137  }
138 
139  fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
140 
141  if (fd_ == -1) {
142  switch (errno) {
143  case EINTR:
144  // Recurse because this is a recoverable error.
145  open ();
146  return;
147  case ENFILE:
148  case EMFILE:
149  THROW (IOException, "Too many file handles open.");
150  default:
151  THROW (IOException, errno);
152  }
153  }
154 
155  reconfigurePort();
156  is_open_ = true;
157 }
Definition: serial.h:690
#define THROW(exceptionClass, message)
Definition: serial.h:48
void reconfigurePort()
Definition: unix.cc:160
Definition: serial.h:672
void open()
Definition: unix.cc:130
size_t Serial::SerialImpl::read ( uint8_t *  buf,
size_t  size = 1 
)
531 {
532  // If the port is not open, throw
533  if (!is_open_) {
534  throw PortNotOpenedException ("Serial::read");
535  }
536  size_t bytes_read = 0;
537 
538  // Calculate total timeout in milliseconds t_c + (t_m * N)
539  long total_timeout_ms = timeout_.read_timeout_constant;
540  total_timeout_ms += timeout_.read_timeout_multiplier * static_cast<long> (size);
541  MillisecondTimer total_timeout(total_timeout_ms);
542 
543  // Pre-fill buffer with available bytes
544  {
545  ssize_t bytes_read_now = ::read (fd_, buf, size);
546  if (bytes_read_now > 0) {
547  bytes_read = bytes_read_now;
548  }
549  }
550 
551  while (bytes_read < size) {
552  int64_t timeout_remaining_ms = total_timeout.remaining();
553  if (timeout_remaining_ms <= 0) {
554  // Timed out
555  break;
556  }
557  // Timeout for the next select is whichever is less of the remaining
558  // total read timeout and the inter-byte timeout.
559  uint32_t timeout = std::min(static_cast<uint32_t> (timeout_remaining_ms),
560  timeout_.inter_byte_timeout);
561  // Wait for the device to be readable, and then attempt to read.
562  if (waitReadable(timeout)) {
563  // If it's a fixed-length multi-byte read, insert a wait here so that
564  // we can attempt to grab the whole thing in a single IO call. Skip
565  // this wait if a non-max inter_byte_timeout is specified.
566  if (size > 1 && timeout_.inter_byte_timeout == Timeout::max()) {
567  size_t bytes_available = available();
568  if (bytes_available + bytes_read < size) {
569  waitByteTimes(size - (bytes_available + bytes_read));
570  }
571  }
572  // This should be non-blocking returning only what is available now
573  // Then returning so that select can block again.
574  ssize_t bytes_read_now =
575  ::read (fd_, buf + bytes_read, size - bytes_read);
576  // read should always return some data as select reported it was
577  // ready to read when we get to this point.
578  if (bytes_read_now < 1) {
579  // Disconnected devices, at least on Linux, show the
580  // behavior that they are always ready to read immediately
581  // but reading returns nothing.
582  throw SerialException ("device reports readiness to read but "
583  "returned no data (device disconnected?)");
584  }
585  // Update bytes_read
586  bytes_read += static_cast<size_t> (bytes_read_now);
587  // If bytes_read == size then we have read everything we need
588  if (bytes_read == size) {
589  break;
590  }
591  // If bytes_read < size then we have more to read
592  if (bytes_read < size) {
593  continue;
594  }
595  // If bytes_read > size then we have over read, which shouldn't happen
596  if (bytes_read > size) {
597  throw SerialException ("read over read, too many bytes where "
598  "read, this shouldn't happen, might be "
599  "a logical error!");
600  }
601  }
602  }
603  return bytes_read;
604 }
size_t available()
Definition: unix.cc:478
Definition: unix.h:56
void waitByteTimes(size_t count)
Definition: unix.cc:523
bool waitReadable(uint32_t timeout)
Definition: unix.cc:492
uint32_t read_timeout_multiplier
Definition: serial.h:123
uint32_t read_timeout_constant
Definition: serial.h:119
static uint32_t max()
Definition: serial.h:102
uint32_t inter_byte_timeout
Definition: serial.h:117
Definition: serial.h:672
size_t read(uint8_t *buf, size_t size=1)
Definition: unix.cc:530
Definition: serial.h:729
void Serial::SerialImpl::readLock ( )
1029 {
1030  int result = pthread_mutex_lock(&this->read_mutex);
1031  if (result) {
1032  THROW (IOException, result);
1033  }
1034 }
Definition: serial.h:690
#define THROW(exceptionClass, message)
Definition: serial.h:48
void Serial::SerialImpl::readUnlock ( )
1038 {
1039  int result = pthread_mutex_unlock(&this->read_mutex);
1040  if (result) {
1041  THROW (IOException, result);
1042  }
1043 }
Definition: serial.h:690
#define THROW(exceptionClass, message)
Definition: serial.h:48
void Serial::SerialImpl::reconfigurePort ( )
protected
161 {
162  if (fd_ == -1) {
163  // Can only operate on a valid file descriptor
164  THROW (IOException, "Invalid file descriptor, is the serial port open?");
165  }
166 
167  struct termios options; // The options for the file descriptor
168 
169  if (tcgetattr(fd_, &options) == -1) {
170  THROW (IOException, "::tcgetattr");
171  }
172 
173  // set up raw mode / no echo / binary
174  options.c_cflag |= (tcflag_t) (CLOCAL | CREAD);
175  options.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL |
176  ISIG | IEXTEN); //|ECHOPRT
177 
178  options.c_oflag &= (tcflag_t) ~(OPOST);
179  options.c_iflag &= (tcflag_t) ~(INLCR | IGNCR | ICRNL | IGNBRK);
180 #ifdef IUCLC
181  options.c_iflag &= (tcflag_t) ~IUCLC;
182 #endif
183 #ifdef PARMRK
184  options.c_iflag &= (tcflag_t) ~PARMRK;
185 #endif
186 
187  // setup baud rate
188  bool custom_baud = false;
189  speed_t baud;
190  switch (baudrate_) {
191 #ifdef B0
192  case 0: baud = B0; break;
193 #endif
194 #ifdef B50
195  case 50: baud = B50; break;
196 #endif
197 #ifdef B75
198  case 75: baud = B75; break;
199 #endif
200 #ifdef B110
201  case 110: baud = B110; break;
202 #endif
203 #ifdef B134
204  case 134: baud = B134; break;
205 #endif
206 #ifdef B150
207  case 150: baud = B150; break;
208 #endif
209 #ifdef B200
210  case 200: baud = B200; break;
211 #endif
212 #ifdef B300
213  case 300: baud = B300; break;
214 #endif
215 #ifdef B600
216  case 600: baud = B600; break;
217 #endif
218 #ifdef B1200
219  case 1200: baud = B1200; break;
220 #endif
221 #ifdef B1800
222  case 1800: baud = B1800; break;
223 #endif
224 #ifdef B2400
225  case 2400: baud = B2400; break;
226 #endif
227 #ifdef B4800
228  case 4800: baud = B4800; break;
229 #endif
230 #ifdef B7200
231  case 7200: baud = B7200; break;
232 #endif
233 #ifdef B9600
234  case 9600: baud = B9600; break;
235 #endif
236 #ifdef B14400
237  case 14400: baud = B14400; break;
238 #endif
239 #ifdef B19200
240  case 19200: baud = B19200; break;
241 #endif
242 #ifdef B28800
243  case 28800: baud = B28800; break;
244 #endif
245 #ifdef B57600
246  case 57600: baud = B57600; break;
247 #endif
248 #ifdef B76800
249  case 76800: baud = B76800; break;
250 #endif
251 #ifdef B38400
252  case 38400: baud = B38400; break;
253 #endif
254 #ifdef B115200
255  case 115200: baud = B115200; break;
256 #endif
257 #ifdef B128000
258  case 128000: baud = B128000; break;
259 #endif
260 #ifdef B153600
261  case 153600: baud = B153600; break;
262 #endif
263 #ifdef B230400
264  case 230400: baud = B230400; break;
265 #endif
266 #ifdef B256000
267  case 256000: baud = B256000; break;
268 #endif
269 #ifdef B460800
270  case 460800: baud = B460800; break;
271 #endif
272 #ifdef B576000
273  case 576000: baud = B576000; break;
274 #endif
275 #ifdef B921600
276  case 921600: baud = B921600; break;
277 #endif
278 #ifdef B1000000
279  case 1000000: baud = B1000000; break;
280 #endif
281 #ifdef B1152000
282  case 1152000: baud = B1152000; break;
283 #endif
284 #ifdef B1500000
285  case 1500000: baud = B1500000; break;
286 #endif
287 #ifdef B2000000
288  case 2000000: baud = B2000000; break;
289 #endif
290 #ifdef B2500000
291  case 2500000: baud = B2500000; break;
292 #endif
293 #ifdef B3000000
294  case 3000000: baud = B3000000; break;
295 #endif
296 #ifdef B3500000
297  case 3500000: baud = B3500000; break;
298 #endif
299 #ifdef B4000000
300  case 4000000: baud = B4000000; break;
301 #endif
302  default:
303  custom_baud = true;
304  // OS X support
305 #if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
306  // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates
307  // other than those specified by POSIX. The driver for the underlying serial hardware
308  // ultimately determines which baud rates can be used. This ioctl sets both the input
309  // and output speed.
310  speed_t new_baud = static_cast<speed_t> (baudrate_);
311  if (-1 == ioctl (fd_, IOSSIOSPEED, &new_baud, 1)) {
312  THROW (IOException, errno);
313  }
314  // Linux Support
315 #elif defined(__linux__) && defined (TIOCSSERIAL)
316  struct serial_struct ser;
317 
318  if (-1 == ioctl (fd_, TIOCGSERIAL, &ser)) {
319  THROW (IOException, errno);
320  }
321 
322  // set custom divisor
323  ser.custom_divisor = ser.baud_base / static_cast<int> (baudrate_);
324  // update flags
325  ser.flags &= ~ASYNC_SPD_MASK;
326  ser.flags |= ASYNC_SPD_CUST;
327 
328  if (-1 == ioctl (fd_, TIOCSSERIAL, &ser)) {
329  THROW (IOException, errno);
330  }
331 #else
332  throw invalid_argument ("OS does not currently support custom bauds");
333 #endif
334  }
335  if (custom_baud == false) {
336 #ifdef _BSD_SOURCE
337  ::cfsetspeed(&options, baud);
338 #else
339  ::cfsetispeed(&options, baud);
340  ::cfsetospeed(&options, baud);
341 #endif
342  }
343 
344  // setup char len
345  options.c_cflag &= (tcflag_t) ~CSIZE;
346  if (bytesize_ == eightbits)
347  options.c_cflag |= CS8;
348  else if (bytesize_ == sevenbits)
349  options.c_cflag |= CS7;
350  else if (bytesize_ == sixbits)
351  options.c_cflag |= CS6;
352  else if (bytesize_ == fivebits)
353  options.c_cflag |= CS5;
354  else
355  throw invalid_argument ("invalid char len");
356  // setup stopbits
357  if (stopbits_ == stopbits_one)
358  options.c_cflag &= (tcflag_t) ~(CSTOPB);
359  else if (stopbits_ == stopbits_one_point_five)
360  // ONE POINT FIVE same as TWO.. there is no POSIX support for 1.5
361  options.c_cflag |= (CSTOPB);
362  else if (stopbits_ == stopbits_two)
363  options.c_cflag |= (CSTOPB);
364  else
365  throw invalid_argument ("invalid stop bit");
366  // setup parity
367  options.c_iflag &= (tcflag_t) ~(INPCK | ISTRIP);
368  if (parity_ == parity_none) {
369  options.c_cflag &= (tcflag_t) ~(PARENB | PARODD);
370  } else if (parity_ == parity_even) {
371  options.c_cflag &= (tcflag_t) ~(PARODD);
372  options.c_cflag |= (PARENB);
373  } else if (parity_ == parity_odd) {
374  options.c_cflag |= (PARENB | PARODD);
375  }
376 #ifdef CMSPAR
377  else if (parity_ == parity_mark) {
378  options.c_cflag |= (PARENB | CMSPAR | PARODD);
379  }
380  else if (parity_ == parity_space) {
381  options.c_cflag |= (PARENB | CMSPAR);
382  options.c_cflag &= (tcflag_t) ~(PARODD);
383  }
384 #else
385  // CMSPAR is not defined on OSX. So do not support mark or space parity.
386  else if (parity_ == parity_mark || parity_ == parity_space) {
387  throw invalid_argument ("OS does not support mark or space parity");
388  }
389 #endif // ifdef CMSPAR
390  else {
391  throw invalid_argument ("invalid parity");
392  }
393  // setup flow control
394  if (flowcontrol_ == flowcontrol_none) {
395  xonxoff_ = false;
396  rtscts_ = false;
397  }
398  if (flowcontrol_ == flowcontrol_software) {
399  xonxoff_ = true;
400  rtscts_ = false;
401  }
402  if (flowcontrol_ == flowcontrol_hardware) {
403  xonxoff_ = false;
404  rtscts_ = true;
405  }
406  // xonxoff
407 #ifdef IXANY
408  if (xonxoff_)
409  options.c_iflag |= (IXON | IXOFF); //|IXANY)
410  else
411  options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY);
412 #else
413  if (xonxoff_)
414  options.c_iflag |= (IXON | IXOFF);
415  else
416  options.c_iflag &= (tcflag_t) ~(IXON | IXOFF);
417 #endif
418  // rtscts
419 #ifdef CRTSCTS
420  if (rtscts_)
421  options.c_cflag |= (CRTSCTS);
422  else
423  options.c_cflag &= (unsigned long) ~(CRTSCTS);
424 #elif defined CNEW_RTSCTS
425  if (rtscts_)
426  options.c_cflag |= (CNEW_RTSCTS);
427  else
428  options.c_cflag &= (unsigned long) ~(CNEW_RTSCTS);
429 #else
430 #error "OS Support seems wrong."
431 #endif
432 
433  // http://www.unixwiz.net/techtips/termios-vmin-vtime.html
434  // this basically sets the read call up to be a polling read,
435  // but we are using select to ensure there is data available
436  // to read before each call, so we should never needlessly poll
437  options.c_cc[VMIN] = 0;
438  options.c_cc[VTIME] = 0;
439 
440  // activate settings
441  ::tcsetattr (fd_, TCSANOW, &options);
442 
443  // Update byte_time_ based on the new settings.
444  uint32_t bit_time_ns = 1e9 / baudrate_;
445  byte_time_ns_ = bit_time_ns * (1 + bytesize_ + parity_ + stopbits_);
446 
447  // Compensate for the stopbits_one_point_five enum being equal to int 3,
448  // and not 1.5.
449  if (stopbits_ == stopbits_one_point_five) {
450  byte_time_ns_ += ((1.5 - stopbits_one_point_five) * bit_time_ns);
451  }
452 }
Definition: serial.h:70
Definition: serial.h:58
Definition: serial.h:69
Definition: serial.h:88
Definition: serial.h:68
Definition: serial.h:67
Definition: serial.h:690
Definition: serial.h:78
Definition: serial.h:79
Definition: serial.h:89
#define THROW(exceptionClass, message)
Definition: serial.h:48
Definition: serial.h:80
Definition: serial.h:87
Definition: serial.h:60
Definition: serial.h:57
Definition: serial.h:59
Definition: serial.h:71
void Serial::SerialImpl::sendBreak ( int  duration)
817 {
818  if (is_open_ == false) {
819  throw PortNotOpenedException ("Serial::sendBreak");
820  }
821  tcsendbreak (fd_, static_cast<int> (duration / 4));
822 }
Definition: serial.h:729
void Serial::SerialImpl::setBaudrate ( unsigned long  baudrate)
720 {
721  baudrate_ = baudrate;
722  if (is_open_)
723  reconfigurePort ();
724 }
void reconfigurePort()
Definition: unix.cc:160
void Serial::SerialImpl::setBreak ( bool  level)
826 {
827  if (is_open_ == false) {
828  throw PortNotOpenedException ("Serial::setBreak");
829  }
830 
831  if (level) {
832  if (-1 == ioctl (fd_, TIOCSBRK))
833  {
834  stringstream ss;
835  ss << "setBreak failed on a call to ioctl(TIOCSBRK): " << errno << " " << strerror(errno);
836  throw(SerialException(ss.str().c_str()));
837  }
838  } else {
839  if (-1 == ioctl (fd_, TIOCCBRK))
840  {
841  stringstream ss;
842  ss << "setBreak failed on a call to ioctl(TIOCCBRK): " << errno << " " << strerror(errno);
843  throw(SerialException(ss.str().c_str()));
844  }
845  }
846 }
Definition: serial.h:672
Definition: serial.h:729
void Serial::SerialImpl::setBytesize ( serial::bytesize_t  bytesize)
734 {
735  bytesize_ = bytesize;
736  if (is_open_)
737  reconfigurePort ();
738 }
void reconfigurePort()
Definition: unix.cc:160
void Serial::SerialImpl::setDTR ( bool  level)
876 {
877  if (is_open_ == false) {
878  throw PortNotOpenedException ("Serial::setDTR");
879  }
880 
881  int command = TIOCM_DTR;
882 
883  if (level) {
884  if (-1 == ioctl (fd_, TIOCMBIS, &command))
885  {
886  stringstream ss;
887  ss << "setDTR failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno);
888  throw(SerialException(ss.str().c_str()));
889  }
890  } else {
891  if (-1 == ioctl (fd_, TIOCMBIC, &command))
892  {
893  stringstream ss;
894  ss << "setDTR failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno);
895  throw(SerialException(ss.str().c_str()));
896  }
897  }
898 }
Definition: serial.h:672
Definition: serial.h:729
void Serial::SerialImpl::setFlowcontrol ( serial::flowcontrol_t  flowcontrol)
776 {
777  flowcontrol_ = flowcontrol;
778  if (is_open_)
779  reconfigurePort ();
780 }
void reconfigurePort()
Definition: unix.cc:160
void Serial::SerialImpl::setParity ( serial::parity_t  parity)
748 {
749  parity_ = parity;
750  if (is_open_)
751  reconfigurePort ();
752 }
void reconfigurePort()
Definition: unix.cc:160
void Serial::SerialImpl::setPort ( const string &  port)
696 {
697  port_ = port;
698 }
void Serial::SerialImpl::setRTS ( bool  level)
850 {
851  if (is_open_ == false) {
852  throw PortNotOpenedException ("Serial::setRTS");
853  }
854 
855  int command = TIOCM_RTS;
856 
857  if (level) {
858  if (-1 == ioctl (fd_, TIOCMBIS, &command))
859  {
860  stringstream ss;
861  ss << "setRTS failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno);
862  throw(SerialException(ss.str().c_str()));
863  }
864  } else {
865  if (-1 == ioctl (fd_, TIOCMBIC, &command))
866  {
867  stringstream ss;
868  ss << "setRTS failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno);
869  throw(SerialException(ss.str().c_str()));
870  }
871  }
872 }
Definition: serial.h:672
Definition: serial.h:729
void Serial::SerialImpl::setStopbits ( serial::stopbits_t  stopbits)
762 {
763  stopbits_ = stopbits;
764  if (is_open_)
765  reconfigurePort ();
766 }
void reconfigurePort()
Definition: unix.cc:160
void Serial::SerialImpl::setTimeout ( serial::Timeout timeout)
708 {
709  timeout_ = timeout;
710 }
void Serial::SerialImpl::waitByteTimes ( size_t  count)
524 {
525  timespec wait_time = { 0, static_cast<long>(byte_time_ns_ * count)};
526  pselect (0, NULL, NULL, NULL, &wait_time, NULL);
527 }
bool Serial::SerialImpl::waitForChange ( )
902 {
903 #ifndef TIOCMIWAIT
904 
905 while (is_open_ == true) {
906 
907  int status;
908 
909  if (-1 == ioctl (fd_, TIOCMGET, &status))
910  {
911  stringstream ss;
912  ss << "waitForChange failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno);
913  throw(SerialException(ss.str().c_str()));
914  }
915  else
916  {
917  if (0 != (status & TIOCM_CTS)
918  || 0 != (status & TIOCM_DSR)
919  || 0 != (status & TIOCM_RI)
920  || 0 != (status & TIOCM_CD))
921  {
922  return true;
923  }
924  }
925 
926  usleep(1000);
927  }
928 
929  return false;
930 #else
931  int command = (TIOCM_CD|TIOCM_DSR|TIOCM_RI|TIOCM_CTS);
932 
933  if (-1 == ioctl (fd_, TIOCMIWAIT, &command)) {
934  stringstream ss;
935  ss << "waitForDSR failed on a call to ioctl(TIOCMIWAIT): "
936  << errno << " " << strerror(errno);
937  throw(SerialException(ss.str().c_str()));
938  }
939  return true;
940 #endif
941 }
Definition: serial.h:672
bool Serial::SerialImpl::waitReadable ( uint32_t  timeout)
493 {
494  // Setup a select call to block for serial data or a timeout
495  fd_set readfds;
496  FD_ZERO (&readfds);
497  FD_SET (fd_, &readfds);
498  timespec timeout_ts (timespec_from_ms (timeout));
499  int r = pselect (fd_ + 1, &readfds, NULL, NULL, &timeout_ts, NULL);
500 
501  if (r < 0) {
502  // Select was interrupted
503  if (errno == EINTR) {
504  return false;
505  }
506  // Otherwise there was some error
507  THROW (IOException, errno);
508  }
509  // Timeout occurred
510  if (r == 0) {
511  return false;
512  }
513  // This shouldn't happen, if r > 0 our fd has to be in the list!
514  if (!FD_ISSET (fd_, &readfds)) {
515  THROW (IOException, "select reports ready to read, but our fd isn't"
516  " in the list, this shouldn't happen!");
517  }
518  // Data available to read.
519  return true;
520 }
Definition: serial.h:690
#define THROW(exceptionClass, message)
Definition: serial.h:48
timespec timespec_from_ms(const uint32_t millis)
Definition: unix.cc:100
size_t Serial::SerialImpl::write ( const uint8_t *  data,
size_t  length 
)

Error

Timeout

Port ready to write

608 {
609  if (is_open_ == false) {
610  throw PortNotOpenedException ("Serial::write");
611  }
612  fd_set writefds;
613  size_t bytes_written = 0;
614 
615  // Calculate total timeout in milliseconds t_c + (t_m * N)
616  long total_timeout_ms = timeout_.write_timeout_constant;
617  total_timeout_ms += timeout_.write_timeout_multiplier * static_cast<long> (length);
618  MillisecondTimer total_timeout(total_timeout_ms);
619 
620  bool first_iteration = true;
621  while (bytes_written < length) {
622  int64_t timeout_remaining_ms = total_timeout.remaining();
623  // Only consider the timeout if it's not the first iteration of the loop
624  // otherwise a timeout of 0 won't be allowed through
625  if (!first_iteration && (timeout_remaining_ms <= 0)) {
626  // Timed out
627  break;
628  }
629  first_iteration = false;
630 
631  timespec timeout(timespec_from_ms(timeout_remaining_ms));
632 
633  FD_ZERO (&writefds);
634  FD_SET (fd_, &writefds);
635 
636  // Do the select
637  int r = pselect (fd_ + 1, NULL, &writefds, NULL, &timeout, NULL);
638 
639  // Figure out what happened by looking at select's response 'r'
641  if (r < 0) {
642  // Select was interrupted, try again
643  if (errno == EINTR) {
644  continue;
645  }
646  // Otherwise there was some error
647  THROW (IOException, errno);
648  }
650  if (r == 0) {
651  break;
652  }
654  if (r > 0) {
655  // Make sure our file descriptor is in the ready to write list
656  if (FD_ISSET (fd_, &writefds)) {
657  // This will write some
658  ssize_t bytes_written_now =
659  ::write (fd_, data + bytes_written, length - bytes_written);
660  // write should always return some data as select reported it was
661  // ready to write when we get to this point.
662  if (bytes_written_now < 1) {
663  // Disconnected devices, at least on Linux, show the
664  // behavior that they are always ready to write immediately
665  // but writing returns nothing.
666  throw SerialException ("device reports readiness to write but "
667  "returned no data (device disconnected?)");
668  }
669  // Update bytes_written
670  bytes_written += static_cast<size_t> (bytes_written_now);
671  // If bytes_written == size then we have written everything we need to
672  if (bytes_written == length) {
673  break;
674  }
675  // If bytes_written < size then we have more to write
676  if (bytes_written < length) {
677  continue;
678  }
679  // If bytes_written > size then we have over written, which shouldn't happen
680  if (bytes_written > length) {
681  throw SerialException ("write over wrote, too many bytes where "
682  "written, this shouldn't happen, might be "
683  "a logical error!");
684  }
685  }
686  // This shouldn't happen, if r > 0 our fd has to be in the list!
687  THROW (IOException, "select reports ready to write, but our fd isn't"
688  " in the list, this shouldn't happen!");
689  }
690  }
691  return bytes_written;
692 }
Definition: unix.h:56
uint32_t write_timeout_multiplier
Definition: serial.h:129
Definition: serial.h:690
size_t write(const uint8_t *data, size_t length)
Definition: unix.cc:607
#define THROW(exceptionClass, message)
Definition: serial.h:48
Definition: serial.h:672
Definition: serial.h:729
timespec timespec_from_ms(const uint32_t millis)
Definition: unix.cc:100
uint32_t write_timeout_constant
Definition: serial.h:125
void Serial::SerialImpl::writeLock ( )
1047 {
1048  int result = pthread_mutex_lock(&this->write_mutex);
1049  if (result) {
1050  THROW (IOException, result);
1051  }
1052 }
Definition: serial.h:690
#define THROW(exceptionClass, message)
Definition: serial.h:48
void Serial::SerialImpl::writeUnlock ( )
1056 {
1057  int result = pthread_mutex_unlock(&this->write_mutex);
1058  if (result) {
1059  THROW (IOException, result);
1060  }
1061 }
Definition: serial.h:690
#define THROW(exceptionClass, message)
Definition: serial.h:48

The documentation for this class was generated from the following files: