unix.cc
Go to the documentation of this file.
1 /* Copyright 2012 William Woodall and John Harrison
2  *
3  * Additional Contributors: Christopher Baker @bakercp
4  */
5 
6 #if !defined(_WIN32)
7 
8 #include <stdio.h>
9 #include <string.h>
10 #include <sstream>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <sys/ioctl.h>
14 #include <sys/signal.h>
15 #include <errno.h>
16 #include <paths.h>
17 #include <sysexits.h>
18 #include <termios.h>
19 #include <sys/param.h>
20 #include <pthread.h>
21 
22 #if defined(__linux__)
23 # include <linux/serial.h>
24 #endif
25 
26 #include <sys/select.h>
27 #include <sys/time.h>
28 #include <time.h>
29 #ifdef __MACH__
30 #include <AvailabilityMacros.h>
31 #include <mach/clock.h>
32 #include <mach/mach.h>
33 #endif
34 
35 #include "serial/impl/unix.h"
36 
37 #ifndef TIOCINQ
38 #ifdef FIONREAD
39 #define TIOCINQ FIONREAD
40 #else
41 #define TIOCINQ 0x541B
42 #endif
43 #endif
44 
45 #if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
46 #include <IOKit/serial/ioss.h>
47 #endif
48 
49 using std::string;
50 using std::stringstream;
51 using std::invalid_argument;
53 using serial::Serial;
57 
58 
59 MillisecondTimer::MillisecondTimer (const uint32_t millis)
60  : expiry(timespec_now())
61 {
62  int64_t tv_nsec = expiry.tv_nsec + (millis * 1e6);
63  if (tv_nsec >= 1e9) {
64  int64_t sec_diff = tv_nsec / static_cast<int> (1e9);
65  expiry.tv_nsec = tv_nsec % static_cast<int>(1e9);
66  expiry.tv_sec += sec_diff;
67  } else {
68  expiry.tv_nsec = tv_nsec;
69  }
70 }
71 
72 int64_t
74 {
75  timespec now(timespec_now());
76  int64_t millis = (expiry.tv_sec - now.tv_sec) * 1e3;
77  millis += (expiry.tv_nsec - now.tv_nsec) / 1e6;
78  return millis;
79 }
80 
81 timespec
83 {
84  timespec time;
85 # ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
86  clock_serv_t cclock;
87  mach_timespec_t mts;
88  host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
89  clock_get_time(cclock, &mts);
90  mach_port_deallocate(mach_task_self(), cclock);
91  time.tv_sec = mts.tv_sec;
92  time.tv_nsec = mts.tv_nsec;
93 # else
94  clock_gettime(CLOCK_MONOTONIC, &time);
95 # endif
96  return time;
97 }
98 
99 timespec
100 timespec_from_ms (const uint32_t millis)
101 {
102  timespec time;
103  time.tv_sec = millis / 1e3;
104  time.tv_nsec = (millis - (time.tv_sec * 1e3)) * 1e6;
105  return time;
106 }
107 
108 Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
109  bytesize_t bytesize,
110  parity_t parity, stopbits_t stopbits,
111  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 }
121 
123 {
124  close();
125  pthread_mutex_destroy(&this->read_mutex);
126  pthread_mutex_destroy(&this->write_mutex);
127 }
128 
129 void
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 }
158 
159 void
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 B500000
273  case 500000: baud = B500000; break;
274 #endif
275 #ifdef B576000
276  case 576000: baud = B576000; break;
277 #endif
278 #ifdef B921600
279  case 921600: baud = B921600; break;
280 #endif
281 #ifdef B1000000
282  case 1000000: baud = B1000000; break;
283 #endif
284 #ifdef B1152000
285  case 1152000: baud = B1152000; break;
286 #endif
287 #ifdef B1500000
288  case 1500000: baud = B1500000; break;
289 #endif
290 #ifdef B2000000
291  case 2000000: baud = B2000000; break;
292 #endif
293 #ifdef B2500000
294  case 2500000: baud = B2500000; break;
295 #endif
296 #ifdef B3000000
297  case 3000000: baud = B3000000; break;
298 #endif
299 #ifdef B3500000
300  case 3500000: baud = B3500000; break;
301 #endif
302 #ifdef B4000000
303  case 4000000: baud = B4000000; break;
304 #endif
305  default:
306  custom_baud = true;
307  }
308  if (custom_baud == false) {
309 #ifdef _BSD_SOURCE
310  ::cfsetspeed(&options, baud);
311 #else
312  ::cfsetispeed(&options, baud);
313  ::cfsetospeed(&options, baud);
314 #endif
315  }
316 
317  // setup char len
318  options.c_cflag &= (tcflag_t) ~CSIZE;
319  if (bytesize_ == eightbits)
320  options.c_cflag |= CS8;
321  else if (bytesize_ == sevenbits)
322  options.c_cflag |= CS7;
323  else if (bytesize_ == sixbits)
324  options.c_cflag |= CS6;
325  else if (bytesize_ == fivebits)
326  options.c_cflag |= CS5;
327  else
328  throw invalid_argument ("invalid char len");
329  // setup stopbits
330  if (stopbits_ == stopbits_one)
331  options.c_cflag &= (tcflag_t) ~(CSTOPB);
332  else if (stopbits_ == stopbits_one_point_five)
333  // ONE POINT FIVE same as TWO.. there is no POSIX support for 1.5
334  options.c_cflag |= (CSTOPB);
335  else if (stopbits_ == stopbits_two)
336  options.c_cflag |= (CSTOPB);
337  else
338  throw invalid_argument ("invalid stop bit");
339  // setup parity
340  options.c_iflag &= (tcflag_t) ~(INPCK | ISTRIP);
341  if (parity_ == parity_none) {
342  options.c_cflag &= (tcflag_t) ~(PARENB | PARODD);
343  } else if (parity_ == parity_even) {
344  options.c_cflag &= (tcflag_t) ~(PARODD);
345  options.c_cflag |= (PARENB);
346  } else if (parity_ == parity_odd) {
347  options.c_cflag |= (PARENB | PARODD);
348  }
349 #ifdef CMSPAR
350  else if (parity_ == parity_mark) {
351  options.c_cflag |= (PARENB | CMSPAR | PARODD);
352  }
353  else if (parity_ == parity_space) {
354  options.c_cflag |= (PARENB | CMSPAR);
355  options.c_cflag &= (tcflag_t) ~(PARODD);
356  }
357 #else
358  // CMSPAR is not defined on OSX. So do not support mark or space parity.
359  else if (parity_ == parity_mark || parity_ == parity_space) {
360  throw invalid_argument ("OS does not support mark or space parity");
361  }
362 #endif // ifdef CMSPAR
363  else {
364  throw invalid_argument ("invalid parity");
365  }
366  // setup flow control
367  if (flowcontrol_ == flowcontrol_none) {
368  xonxoff_ = false;
369  rtscts_ = false;
370  }
371  if (flowcontrol_ == flowcontrol_software) {
372  xonxoff_ = true;
373  rtscts_ = false;
374  }
375  if (flowcontrol_ == flowcontrol_hardware) {
376  xonxoff_ = false;
377  rtscts_ = true;
378  }
379  // xonxoff
380 #ifdef IXANY
381  if (xonxoff_)
382  options.c_iflag |= (IXON | IXOFF); //|IXANY)
383  else
384  options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY);
385 #else
386  if (xonxoff_)
387  options.c_iflag |= (IXON | IXOFF);
388  else
389  options.c_iflag &= (tcflag_t) ~(IXON | IXOFF);
390 #endif
391  // rtscts
392 #ifdef CRTSCTS
393  if (rtscts_)
394  options.c_cflag |= (CRTSCTS);
395  else
396  options.c_cflag &= (unsigned long) ~(CRTSCTS);
397 #elif defined CNEW_RTSCTS
398  if (rtscts_)
399  options.c_cflag |= (CNEW_RTSCTS);
400  else
401  options.c_cflag &= (unsigned long) ~(CNEW_RTSCTS);
402 #else
403 #error "OS Support seems wrong."
404 #endif
405 
406  // http://www.unixwiz.net/techtips/termios-vmin-vtime.html
407  // this basically sets the read call up to be a polling read,
408  // but we are using select to ensure there is data available
409  // to read before each call, so we should never needlessly poll
410  options.c_cc[VMIN] = 0;
411  options.c_cc[VTIME] = 0;
412 
413  // activate settings
414  ::tcsetattr (fd_, TCSANOW, &options);
415 
416  // apply custom baud rate, if any
417  if (custom_baud == true) {
418  // OS X support
419 #if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
420  // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates
421  // other than those specified by POSIX. The driver for the underlying serial hardware
422  // ultimately determines which baud rates can be used. This ioctl sets both the input
423  // and output speed.
424  speed_t new_baud = static_cast<speed_t> (baudrate_);
425  // PySerial uses IOSSIOSPEED=0x80045402
426  if (-1 == ioctl (fd_, IOSSIOSPEED, &new_baud, 1)) {
427  THROW (IOException, errno);
428  }
429  // Linux Support
430 #elif defined(__linux__) && defined (TIOCSSERIAL)
431  struct serial_struct ser;
432 
433  if (-1 == ioctl (fd_, TIOCGSERIAL, &ser)) {
434  THROW (IOException, errno);
435  }
436 
437  // set custom divisor
438  ser.custom_divisor = ser.baud_base / static_cast<int> (baudrate_);
439  // update flags
440  ser.flags &= ~ASYNC_SPD_MASK;
441  ser.flags |= ASYNC_SPD_CUST;
442 
443  if (-1 == ioctl (fd_, TIOCSSERIAL, &ser)) {
444  THROW (IOException, errno);
445  }
446 #else
447  throw invalid_argument ("OS does not currently support custom bauds");
448 #endif
449  }
450 
451  // Update byte_time_ based on the new settings.
452  uint32_t bit_time_ns = 1e9 / baudrate_;
453  byte_time_ns_ = bit_time_ns * (1 + bytesize_ + parity_ + stopbits_);
454 
455  // Compensate for the stopbits_one_point_five enum being equal to int 3,
456  // and not 1.5.
457  if (stopbits_ == stopbits_one_point_five) {
458  byte_time_ns_ += ((1.5 - stopbits_one_point_five) * bit_time_ns);
459  }
460 }
461 
462 void
464 {
465  if (is_open_ == true) {
466  if (fd_ != -1) {
467  int ret;
468  ret = ::close (fd_);
469  if (ret == 0) {
470  fd_ = -1;
471  } else {
472  THROW (IOException, errno);
473  }
474  }
475  is_open_ = false;
476  }
477 }
478 
479 bool
481 {
482  return is_open_;
483 }
484 
485 size_t
487 {
488  if (!is_open_) {
489  return 0;
490  }
491  int count = 0;
492  if (-1 == ioctl (fd_, TIOCINQ, &count)) {
493  THROW (IOException, errno);
494  } else {
495  return static_cast<size_t> (count);
496  }
497 }
498 
499 bool
501 {
502  // Setup a select call to block for serial data or a timeout
503  fd_set readfds;
504  FD_ZERO (&readfds);
505  FD_SET (fd_, &readfds);
506  timespec timeout_ts (timespec_from_ms (timeout));
507  int r = pselect (fd_ + 1, &readfds, NULL, NULL, &timeout_ts, NULL);
508 
509  if (r < 0) {
510  // Select was interrupted
511  if (errno == EINTR) {
512  return false;
513  }
514  // Otherwise there was some error
515  THROW (IOException, errno);
516  }
517  // Timeout occurred
518  if (r == 0) {
519  return false;
520  }
521  // This shouldn't happen, if r > 0 our fd has to be in the list!
522  if (!FD_ISSET (fd_, &readfds)) {
523  THROW (IOException, "select reports ready to read, but our fd isn't"
524  " in the list, this shouldn't happen!");
525  }
526  // Data available to read.
527  return true;
528 }
529 
530 void
532 {
533  timespec wait_time = { 0, static_cast<long>(byte_time_ns_ * count)};
534  pselect (0, NULL, NULL, NULL, &wait_time, NULL);
535 }
536 
537 size_t
538 Serial::SerialImpl::read (uint8_t *buf, size_t size)
539 {
540  // If the port is not open, throw
541  if (!is_open_) {
542  throw PortNotOpenedException ("Serial::read");
543  }
544  size_t bytes_read = 0;
545 
546  // Calculate total timeout in milliseconds t_c + (t_m * N)
547  long total_timeout_ms = timeout_.read_timeout_constant;
548  total_timeout_ms += timeout_.read_timeout_multiplier * static_cast<long> (size);
549  MillisecondTimer total_timeout(total_timeout_ms);
550 
551  // Pre-fill buffer with available bytes
552  {
553  ssize_t bytes_read_now = ::read (fd_, buf, size);
554  if (bytes_read_now > 0) {
555  bytes_read = bytes_read_now;
556  }
557  }
558 
559  while (bytes_read < size) {
560  int64_t timeout_remaining_ms = total_timeout.remaining();
561  if (timeout_remaining_ms <= 0) {
562  // Timed out
563  break;
564  }
565  // Timeout for the next select is whichever is less of the remaining
566  // total read timeout and the inter-byte timeout.
567  uint32_t timeout = std::min(static_cast<uint32_t> (timeout_remaining_ms),
568  timeout_.inter_byte_timeout);
569  // Wait for the device to be readable, and then attempt to read.
570  if (waitReadable(timeout)) {
571  // If it's a fixed-length multi-byte read, insert a wait here so that
572  // we can attempt to grab the whole thing in a single IO call. Skip
573  // this wait if a non-max inter_byte_timeout is specified.
574  if (size > 1 && timeout_.inter_byte_timeout == Timeout::max()) {
575  size_t bytes_available = available();
576  if (bytes_available + bytes_read < size) {
577  waitByteTimes(size - (bytes_available + bytes_read));
578  }
579  }
580  // This should be non-blocking returning only what is available now
581  // Then returning so that select can block again.
582  ssize_t bytes_read_now =
583  ::read (fd_, buf + bytes_read, size - bytes_read);
584  // read should always return some data as select reported it was
585  // ready to read when we get to this point.
586  if (bytes_read_now < 1) {
587  // Disconnected devices, at least on Linux, show the
588  // behavior that they are always ready to read immediately
589  // but reading returns nothing.
590  throw SerialException ("device reports readiness to read but "
591  "returned no data (device disconnected?)");
592  }
593  // Update bytes_read
594  bytes_read += static_cast<size_t> (bytes_read_now);
595  // If bytes_read == size then we have read everything we need
596  if (bytes_read == size) {
597  break;
598  }
599  // If bytes_read < size then we have more to read
600  if (bytes_read < size) {
601  continue;
602  }
603  // If bytes_read > size then we have over read, which shouldn't happen
604  if (bytes_read > size) {
605  throw SerialException ("read over read, too many bytes where "
606  "read, this shouldn't happen, might be "
607  "a logical error!");
608  }
609  }
610  }
611  return bytes_read;
612 }
613 
614 size_t
615 Serial::SerialImpl::write (const uint8_t *data, size_t length)
616 {
617  if (is_open_ == false) {
618  throw PortNotOpenedException ("Serial::write");
619  }
620  fd_set writefds;
621  size_t bytes_written = 0;
622 
623  // Calculate total timeout in milliseconds t_c + (t_m * N)
624  long total_timeout_ms = timeout_.write_timeout_constant;
625  total_timeout_ms += timeout_.write_timeout_multiplier * static_cast<long> (length);
626  MillisecondTimer total_timeout(total_timeout_ms);
627 
628  bool first_iteration = true;
629  while (bytes_written < length) {
630  int64_t timeout_remaining_ms = total_timeout.remaining();
631  // Only consider the timeout if it's not the first iteration of the loop
632  // otherwise a timeout of 0 won't be allowed through
633  if (!first_iteration && (timeout_remaining_ms <= 0)) {
634  // Timed out
635  break;
636  }
637  first_iteration = false;
638 
639  timespec timeout(timespec_from_ms(timeout_remaining_ms));
640 
641  FD_ZERO (&writefds);
642  FD_SET (fd_, &writefds);
643 
644  // Do the select
645  int r = pselect (fd_ + 1, NULL, &writefds, NULL, &timeout, NULL);
646 
647  // Figure out what happened by looking at select's response 'r'
649  if (r < 0) {
650  // Select was interrupted, try again
651  if (errno == EINTR) {
652  continue;
653  }
654  // Otherwise there was some error
655  THROW (IOException, errno);
656  }
658  if (r == 0) {
659  break;
660  }
662  if (r > 0) {
663  // Make sure our file descriptor is in the ready to write list
664  if (FD_ISSET (fd_, &writefds)) {
665  // This will write some
666  ssize_t bytes_written_now =
667  ::write (fd_, data + bytes_written, length - bytes_written);
668 
669  // even though pselect returned readiness the call might still be
670  // interrupted. In that case simply retry.
671  if (bytes_written_now == -1 && errno == EINTR) {
672  continue;
673  }
674 
675  // write should always return some data as select reported it was
676  // ready to write when we get to this point.
677  if (bytes_written_now < 1) {
678  // Disconnected devices, at least on Linux, show the
679  // behavior that they are always ready to write immediately
680  // but writing returns nothing.
681  std::stringstream strs;
682  strs << "device reports readiness to write but "
683  "returned no data (device disconnected?)";
684  strs << " errno=" << errno;
685  strs << " bytes_written_now= " << bytes_written_now;
686  strs << " bytes_written=" << bytes_written;
687  strs << " length=" << length;
688  throw SerialException(strs.str().c_str());
689  }
690  // Update bytes_written
691  bytes_written += static_cast<size_t> (bytes_written_now);
692  // If bytes_written == size then we have written everything we need to
693  if (bytes_written == length) {
694  break;
695  }
696  // If bytes_written < size then we have more to write
697  if (bytes_written < length) {
698  continue;
699  }
700  // If bytes_written > size then we have over written, which shouldn't happen
701  if (bytes_written > length) {
702  throw SerialException ("write over wrote, too many bytes where "
703  "written, this shouldn't happen, might be "
704  "a logical error!");
705  }
706  }
707  // This shouldn't happen, if r > 0 our fd has to be in the list!
708  THROW (IOException, "select reports ready to write, but our fd isn't"
709  " in the list, this shouldn't happen!");
710  }
711  }
712  return bytes_written;
713 }
714 
715 void
716 Serial::SerialImpl::setPort (const string &port)
717 {
718  port_ = port;
719 }
720 
721 string
723 {
724  return port_;
725 }
726 
727 void
729 {
730  timeout_ = timeout;
731 }
732 
735 {
736  return timeout_;
737 }
738 
739 void
740 Serial::SerialImpl::setBaudrate (unsigned long baudrate)
741 {
742  baudrate_ = baudrate;
743  if (is_open_)
744  reconfigurePort ();
745 }
746 
747 unsigned long
749 {
750  return baudrate_;
751 }
752 
753 void
755 {
756  bytesize_ = bytesize;
757  if (is_open_)
758  reconfigurePort ();
759 }
760 
763 {
764  return bytesize_;
765 }
766 
767 void
769 {
770  parity_ = parity;
771  if (is_open_)
772  reconfigurePort ();
773 }
774 
777 {
778  return parity_;
779 }
780 
781 void
783 {
784  stopbits_ = stopbits;
785  if (is_open_)
786  reconfigurePort ();
787 }
788 
791 {
792  return stopbits_;
793 }
794 
795 void
797 {
798  flowcontrol_ = flowcontrol;
799  if (is_open_)
800  reconfigurePort ();
801 }
802 
805 {
806  return flowcontrol_;
807 }
808 
809 void
811 {
812  if (is_open_ == false) {
813  throw PortNotOpenedException ("Serial::flush");
814  }
815  tcdrain (fd_);
816 }
817 
818 void
820 {
821  if (is_open_ == false) {
822  throw PortNotOpenedException ("Serial::flushInput");
823  }
824  tcflush (fd_, TCIFLUSH);
825 }
826 
827 void
829 {
830  if (is_open_ == false) {
831  throw PortNotOpenedException ("Serial::flushOutput");
832  }
833  tcflush (fd_, TCOFLUSH);
834 }
835 
836 void
838 {
839  if (is_open_ == false) {
840  throw PortNotOpenedException ("Serial::sendBreak");
841  }
842  tcsendbreak (fd_, static_cast<int> (duration / 4));
843 }
844 
845 void
847 {
848  if (is_open_ == false) {
849  throw PortNotOpenedException ("Serial::setBreak");
850  }
851 
852  if (level) {
853  if (-1 == ioctl (fd_, TIOCSBRK))
854  {
855  stringstream ss;
856  ss << "setBreak failed on a call to ioctl(TIOCSBRK): " << errno << " " << strerror(errno);
857  throw(SerialException(ss.str().c_str()));
858  }
859  } else {
860  if (-1 == ioctl (fd_, TIOCCBRK))
861  {
862  stringstream ss;
863  ss << "setBreak failed on a call to ioctl(TIOCCBRK): " << errno << " " << strerror(errno);
864  throw(SerialException(ss.str().c_str()));
865  }
866  }
867 }
868 
869 void
871 {
872  if (is_open_ == false) {
873  throw PortNotOpenedException ("Serial::setRTS");
874  }
875 
876  int command = TIOCM_RTS;
877 
878  if (level) {
879  if (-1 == ioctl (fd_, TIOCMBIS, &command))
880  {
881  stringstream ss;
882  ss << "setRTS failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno);
883  throw(SerialException(ss.str().c_str()));
884  }
885  } else {
886  if (-1 == ioctl (fd_, TIOCMBIC, &command))
887  {
888  stringstream ss;
889  ss << "setRTS failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno);
890  throw(SerialException(ss.str().c_str()));
891  }
892  }
893 }
894 
895 void
897 {
898  if (is_open_ == false) {
899  throw PortNotOpenedException ("Serial::setDTR");
900  }
901 
902  int command = TIOCM_DTR;
903 
904  if (level) {
905  if (-1 == ioctl (fd_, TIOCMBIS, &command))
906  {
907  stringstream ss;
908  ss << "setDTR failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno);
909  throw(SerialException(ss.str().c_str()));
910  }
911  } else {
912  if (-1 == ioctl (fd_, TIOCMBIC, &command))
913  {
914  stringstream ss;
915  ss << "setDTR failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno);
916  throw(SerialException(ss.str().c_str()));
917  }
918  }
919 }
920 
921 bool
923 {
924 #ifndef TIOCMIWAIT
925 
926 while (is_open_ == true) {
927 
928  int status;
929 
930  if (-1 == ioctl (fd_, TIOCMGET, &status))
931  {
932  stringstream ss;
933  ss << "waitForChange failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno);
934  throw(SerialException(ss.str().c_str()));
935  }
936  else
937  {
938  if (0 != (status & TIOCM_CTS)
939  || 0 != (status & TIOCM_DSR)
940  || 0 != (status & TIOCM_RI)
941  || 0 != (status & TIOCM_CD))
942  {
943  return true;
944  }
945  }
946 
947  usleep(1000);
948  }
949 
950  return false;
951 #else
952  int command = (TIOCM_CD|TIOCM_DSR|TIOCM_RI|TIOCM_CTS);
953 
954  if (-1 == ioctl (fd_, TIOCMIWAIT, &command)) {
955  stringstream ss;
956  ss << "waitForDSR failed on a call to ioctl(TIOCMIWAIT): "
957  << errno << " " << strerror(errno);
958  throw(SerialException(ss.str().c_str()));
959  }
960  return true;
961 #endif
962 }
963 
964 bool
966 {
967  if (is_open_ == false) {
968  throw PortNotOpenedException ("Serial::getCTS");
969  }
970 
971  int status;
972 
973  if (-1 == ioctl (fd_, TIOCMGET, &status))
974  {
975  stringstream ss;
976  ss << "getCTS 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_CTS);
982  }
983 }
984 
985 bool
987 {
988  if (is_open_ == false) {
989  throw PortNotOpenedException ("Serial::getDSR");
990  }
991 
992  int status;
993 
994  if (-1 == ioctl (fd_, TIOCMGET, &status))
995  {
996  stringstream ss;
997  ss << "getDSR 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_DSR);
1003  }
1004 }
1005 
1006 bool
1008 {
1009  if (is_open_ == false) {
1010  throw PortNotOpenedException ("Serial::getRI");
1011  }
1012 
1013  int status;
1014 
1015  if (-1 == ioctl (fd_, TIOCMGET, &status))
1016  {
1017  stringstream ss;
1018  ss << "getRI 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_RI);
1024  }
1025 }
1026 
1027 bool
1029 {
1030  if (is_open_ == false) {
1031  throw PortNotOpenedException ("Serial::getCD");
1032  }
1033 
1034  int status;
1035 
1036  if (-1 == ioctl (fd_, TIOCMGET, &status))
1037  {
1038  stringstream ss;
1039  ss << "getCD failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno);
1040  throw(SerialException(ss.str().c_str()));
1041  }
1042  else
1043  {
1044  return 0 != (status & TIOCM_CD);
1045  }
1046 }
1047 
1048 void
1050 {
1051  int result = pthread_mutex_lock(&this->read_mutex);
1052  if (result) {
1053  THROW (IOException, result);
1054  }
1055 }
1056 
1057 void
1059 {
1060  int result = pthread_mutex_unlock(&this->read_mutex);
1061  if (result) {
1062  THROW (IOException, result);
1063  }
1064 }
1065 
1066 void
1068 {
1069  int result = pthread_mutex_lock(&this->write_mutex);
1070  if (result) {
1071  THROW (IOException, result);
1072  }
1073 }
1074 
1075 void
1077 {
1078  int result = pthread_mutex_unlock(&this->write_mutex);
1079  if (result) {
1080  THROW (IOException, result);
1081  }
1082 }
1083 
1084 #endif // !defined(_WIN32)
serial::parity_t
parity_t
Definition: serial.h:66
timespec_from_ms
timespec timespec_from_ms(const uint32_t millis)
Definition: unix.cc:100
serial::Serial::SerialImpl::close
void close()
Definition: unix.cc:463
serial::parity_mark
@ parity_mark
Definition: serial.h:70
THROW
#define THROW(exceptionClass, message)
Definition: serial.h:48
serial::Serial::SerialImpl::waitReadable
bool waitReadable(uint32_t timeout)
Definition: unix.cc:500
TIOCINQ
#define TIOCINQ
Definition: unix.cc:41
serial::Timeout::max
static uint32_t max()
Definition: serial.h:102
unix.h
serial::Serial::SerialImpl::sendBreak
void sendBreak(int duration)
Definition: unix.cc:837
serial::Serial::SerialImpl::getPort
string getPort() const
Definition: unix.cc:722
serial::Serial::SerialImpl::getCTS
bool getCTS()
Definition: unix.cc:965
serial::Serial::SerialImpl::SerialImpl
SerialImpl(const string &port, unsigned long baudrate, bytesize_t bytesize, parity_t parity, stopbits_t stopbits, flowcontrol_t flowcontrol)
Definition: unix.cc:108
serial::Serial::SerialImpl::flushInput
void flushInput()
Definition: unix.cc:819
serial::Serial::close
void close()
Definition: serial.cc:87
serial::Serial::SerialImpl::flush
void flush()
Definition: unix.cc:810
serial::Serial::SerialImpl::getParity
parity_t getParity() const
Definition: unix.cc:776
serial::Serial::SerialImpl::getStopbits
stopbits_t getStopbits() const
Definition: unix.cc:790
serial::Serial::SerialImpl::writeLock
void writeLock()
Definition: unix.cc:1067
serial::stopbits_one
@ stopbits_one
Definition: serial.h:78
serial::Serial::SerialImpl::setTimeout
void setTimeout(Timeout &timeout)
Definition: unix.cc:728
serial::MillisecondTimer::remaining
int64_t remaining()
Definition: unix.cc:73
serial::Serial::SerialImpl::available
size_t available()
Definition: unix.cc:486
serial::Serial::SerialImpl::setBreak
void setBreak(bool level)
Definition: unix.cc:846
serial::flowcontrol_software
@ flowcontrol_software
Definition: serial.h:88
serial::parity_even
@ parity_even
Definition: serial.h:69
serial::Serial::SerialImpl::getRI
bool getRI()
Definition: unix.cc:1007
serial::Serial::waitReadable
bool waitReadable()
Definition: serial.cc:105
serial::Serial::SerialImpl::~SerialImpl
virtual ~SerialImpl()
Definition: unix.cc:122
serial::Serial::SerialImpl::setParity
void setParity(parity_t parity)
Definition: unix.cc:768
serial::IOException
Definition: serial.h:690
serial::Serial::SerialImpl::write
size_t write(const uint8_t *data, size_t length)
Definition: unix.cc:615
serial::Serial::SerialImpl::getFlowcontrol
flowcontrol_t getFlowcontrol() const
Definition: unix.cc:804
serial::Serial::SerialImpl::setFlowcontrol
void setFlowcontrol(flowcontrol_t flowcontrol)
Definition: unix.cc:796
serial::bytesize_t
bytesize_t
Definition: serial.h:56
serial::Serial::SerialImpl::waitByteTimes
void waitByteTimes(size_t count)
Definition: unix.cc:531
serial::MillisecondTimer
Definition: unix.h:56
serial::MillisecondTimer::expiry
timespec expiry
Definition: unix.h:63
serial::Serial::SerialImpl::setPort
void setPort(const string &port)
Definition: unix.cc:716
python_serial_test.timeout
timeout
Definition: python_serial_test.py:10
serial::Serial::SerialImpl::getCD
bool getCD()
Definition: unix.cc:1028
serial::Serial::SerialImpl::readLock
void readLock()
Definition: unix.cc:1049
serial::Serial::SerialImpl::setStopbits
void setStopbits(stopbits_t stopbits)
Definition: unix.cc:782
serial::Serial::SerialImpl::setBaudrate
void setBaudrate(unsigned long baudrate)
Definition: unix.cc:740
serial::Serial::SerialImpl::getDSR
bool getDSR()
Definition: unix.cc:986
serial::Serial::SerialImpl::readUnlock
void readUnlock()
Definition: unix.cc:1058
serial::Serial::SerialImpl::reconfigurePort
void reconfigurePort()
Definition: unix.cc:160
serial::MillisecondTimer::timespec_now
static timespec timespec_now()
Definition: unix.cc:82
serial::Serial
Definition: serial.h:147
serial::Serial::SerialImpl::open
void open()
Definition: unix.cc:130
serial::parity_odd
@ parity_odd
Definition: serial.h:68
serial::Serial::SerialImpl::writeUnlock
void writeUnlock()
Definition: unix.cc:1076
serial::Serial::SerialImpl::flushOutput
void flushOutput()
Definition: unix.cc:828
serial::Serial::SerialImpl::setBytesize
void setBytesize(bytesize_t bytesize)
Definition: unix.cc:754
serial::Serial::open
void open()
Definition: serial.cc:81
serial::Serial::SerialImpl::read_mutex
pthread_mutex_t read_mutex
Definition: unix.h:212
serial::flowcontrol_t
flowcontrol_t
Definition: serial.h:86
serial::sevenbits
@ sevenbits
Definition: serial.h:59
serial::Serial::available
size_t available()
Definition: serial.cc:99
serial::Serial::SerialImpl::read
size_t read(uint8_t *buf, size_t size=1)
Definition: unix.cc:538
serial::stopbits_one_point_five
@ stopbits_one_point_five
Definition: serial.h:80
serial::parity_space
@ parity_space
Definition: serial.h:71
serial::stopbits_t
stopbits_t
Definition: serial.h:77
serial::Serial::SerialImpl::setRTS
void setRTS(bool level)
Definition: unix.cc:870
serial::Serial::SerialImpl::write_mutex
pthread_mutex_t write_mutex
Definition: unix.h:214
serial::flowcontrol_none
@ flowcontrol_none
Definition: serial.h:87
serial::Serial::SerialImpl::isOpen
bool isOpen() const
Definition: unix.cc:480
serial::Serial::SerialImpl::getTimeout
Timeout getTimeout() const
Definition: unix.cc:734
serial::Serial::SerialImpl::port_
string port_
Definition: unix.h:195
serial::flowcontrol_hardware
@ flowcontrol_hardware
Definition: serial.h:89
serial::Serial::SerialImpl::setDTR
void setDTR(bool level)
Definition: unix.cc:896
serial::Serial::waitByteTimes
void waitByteTimes(size_t count)
Definition: serial.cc:112
serial::fivebits
@ fivebits
Definition: serial.h:57
serial::SerialException
Definition: serial.h:672
serial::parity_none
@ parity_none
Definition: serial.h:67
serial::stopbits_two
@ stopbits_two
Definition: serial.h:79
serial::Serial::SerialImpl::waitForChange
bool waitForChange()
Definition: unix.cc:922
serial::Serial::SerialImpl::getBytesize
bytesize_t getBytesize() const
Definition: unix.cc:762
serial::PortNotOpenedException
Definition: serial.h:729
serial::Serial::write
size_t write(const uint8_t *data, size_t size)
Definition: serial.cc:270
serial::sixbits
@ sixbits
Definition: serial.h:58
serial::Serial::read
size_t read(uint8_t *buffer, size_t size)
Definition: serial.cc:124
serial::Serial::SerialImpl::getBaudrate
unsigned long getBaudrate() const
Definition: unix.cc:748
serial::Timeout
Definition: serial.h:98
serial::eightbits
@ eightbits
Definition: serial.h:60


serial
Author(s): William Woodall , John Harrison
autogenerated on Wed Mar 9 2022 03:10:03