# serial: serial::serial::Serial::SerialImpl Class Reference

serial 1.0.1 Cross-platform serial port library written in C++

- Main Page
- Namespaces
- Data Structures
- Files

- Data Structures
- Data Structure Index
- Data Fields

All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Defines
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 ()
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 ()
| 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 ()
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 ()
void | reconfigurePort ()

## Constructor & Destructor Documentation

serial::serial::Serial::SerialImpl::SerialImpl | ( | const string & | port,
|  | unsigned long | baudrate,
|  | bytesize_t | bytesize,
|  | parity_t | parity,
|  | stopbits_t | stopbits,
|  | flowcontrol_t | flowcontrol
| ) |  |

virtual serial::serial::Serial::SerialImpl::~SerialImpl | ( |  | ) | `[virtual]`

Serial::SerialImpl::SerialImpl | ( | const string & | port,
|  | unsigned long | baudrate,
|  | bytesize_t | bytesize,
|  | parity_t | parity,
|  | stopbits_t | stopbits,
|  | flowcontrol_t | flowcontrol
| ) |  |

      : port_ (port), fd_ (-1), is_open_ (false), xonxoff_ (false), rtscts_ (false),
        baudrate_ (baudrate), parity_ (parity),
        bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol)
    {
      pthread_mutex_init(&this->read_mutex, NULL);
      pthread_mutex_init(&this->write_mutex, NULL);
      if (port_.empty () == false)
        open ();
    }

Serial::SerialImpl::~SerialImpl | ( |  | ) | `[virtual]`

    {
      close();
      pthread_mutex_destroy(&this->read_mutex);
      pthread_mutex_destroy(&this->write_mutex);
    }

## Member Function Documentation

size_t Serial::SerialImpl::available | ( |  | ) |

    {
      if (!is_open_) {
        return 0;
      }
      int count = 0;
      int result = ioctl (fd_, TIOCINQ, &count);
      if (result == 0) {
        return static_cast<size_t> (count);
      } else {
        THROW (IOException, errno);
      }
    }

size_t serial::serial::Serial::SerialImpl::available | ( |  | ) |

void Serial::SerialImpl::close | ( |  | ) |

    {
      if (is_open_ == true) {
        if (fd_ != -1) {
          ::close (fd_); // Ignoring the outcome
          fd_ = -1;
        }
        is_open_ = false;
      }
    }

void serial::serial::Serial::SerialImpl::close | ( |  | ) |

void Serial::SerialImpl::flush | ( |  | ) |

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::flush");
      }
      tcdrain (fd_);
    }

void serial::serial::Serial::SerialImpl::flush | ( |  | ) |

void Serial::SerialImpl::flushInput | ( |  | ) |

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::flushInput");
      }
      tcflush (fd_, TCIFLUSH);
    }

void serial::serial::Serial::SerialImpl::flushInput | ( |  | ) |

void Serial::SerialImpl::flushOutput | ( |  | ) |

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::flushOutput");
      }
      tcflush (fd_, TCOFLUSH);
    }

void serial::serial::Serial::SerialImpl::flushOutput | ( |  | ) |

unsigned long serial::serial::Serial::SerialImpl::getBaudrate | ( |  | ) | const

unsigned long serial::serial::Serial::SerialImpl::getBaudrate | ( |  | ) | const

bytesize_t serial::serial::Serial::SerialImpl::getBytesize | ( |  | ) | const

bytesize_t serial::serial::Serial::SerialImpl::getBytesize | ( |  | ) | const

bool Serial::SerialImpl::getCD | ( |  | ) |

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::getCD");
      }
      int s = ioctl (fd_, TIOCMGET, 0);
      return (s & TIOCM_CD) != 0;
    }

bool serial::serial::Serial::SerialImpl::getCD | ( |  | ) |

bool Serial::SerialImpl::getCTS | ( |  | ) |

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::getCTS");
      }
      int s = ioctl (fd_, TIOCMGET, 0);
      return (s & TIOCM_CTS) != 0;
    }

bool serial::serial::Serial::SerialImpl::getCTS | ( |  | ) |

bool Serial::SerialImpl::getDSR | ( |  | ) |

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::getDSR");
      }
      int s = ioctl (fd_, TIOCMGET, 0);
      return (s & TIOCM_DSR) != 0;
    }

bool serial::serial::Serial::SerialImpl::getDSR | ( |  | ) |

flowcontrol_t serial::serial::Serial::SerialImpl::getFlowcontrol | ( |  | ) | const

flowcontrol_t serial::serial::Serial::SerialImpl::getFlowcontrol | ( |  | ) | const

parity_t serial::serial::Serial::SerialImpl::getParity | ( |  | ) | const

parity_t serial::serial::Serial::SerialImpl::getParity | ( |  | ) | const

string serial::serial::Serial::SerialImpl::getPort | ( |  | ) | const

string serial::serial::Serial::SerialImpl::getPort | ( |  | ) | const

bool Serial::SerialImpl::getRI | ( |  | ) |

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::getRI");
      }
      int s = ioctl (fd_, TIOCMGET, 0);
      return (s & TIOCM_RI) != 0;
    }

bool serial::serial::Serial::SerialImpl::getRI | ( |  | ) |

stopbits_t serial::serial::Serial::SerialImpl::getStopbits | ( |  | ) | const

stopbits_t serial::serial::Serial::SerialImpl::getStopbits | ( |  | ) | const

Timeout serial::serial::Serial::SerialImpl::getTimeout | ( |  | ) | const

Timeout serial::serial::Serial::SerialImpl::getTimeout | ( |  | ) | const

bool serial::serial::Serial::SerialImpl::isOpen | ( |  | ) | const

bool serial::serial::Serial::SerialImpl::isOpen | ( |  | ) | const

void Serial::SerialImpl::open | ( |  | ) |

    {
      if (port_.empty ()) {
        throw invalid_argument ("Empty port is invalid.");
      }
      if (is_open_ == true) {
        throw SerialExecption ("Serial port already open.");
      }

      fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);

      if (fd_ == -1) {
        switch (errno) {
        case EINTR:
          // Recurse because this is a recoverable error.
          open ();
          return;
        case ENFILE:
        case EMFILE:
          THROW (IOException, "Too many file handles open.");
        default:
          THROW (IOException, errno);
        }
      }

      reconfigurePort();
      is_open_ = true;
    }

void serial::serial::Serial::SerialImpl::open | ( |  | ) |

size_t serial::serial::Serial::SerialImpl::read | ( | uint8_t * | buf,
|  | size_t | size = `1`
| ) |  |

size_t serial::serial::Serial::SerialImpl::read | ( | uint8_t * | buf,
|  | size_t | size = `1`
| ) |  |

void Serial::SerialImpl::readLock | ( |  | ) |

    {
      int result = pthread_mutex_lock(&this->read_mutex);
      if (result) {
        THROW (IOException, result);
      }
    }

void serial::serial::Serial::SerialImpl::readLock | ( |  | ) |

void Serial::SerialImpl::readUnlock | ( |  | ) |

    {
      int result = pthread_mutex_unlock(&this->read_mutex);
      if (result) {
        THROW (IOException, result);
      }
    }

void serial::serial::Serial::SerialImpl::readUnlock | ( |  | ) |

void Serial::SerialImpl::reconfigurePort | ( |  | ) | `[protected]`

    {
      if (fd_ == -1) {
        // Can only operate on a valid file descriptor
        THROW (IOException, "Invalid file descriptor, is the serial port open?");
      }

      struct termios options; // The options for the file descriptor

      if (tcgetattr(fd_, &options) == -1) {
        THROW (IOException, "::tcgetattr");
      }

      // set up raw mode / no echo / binary
      options.c_cflag |= (tcflag_t)  (CLOCAL | CREAD);
      options.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL |
                                           ISIG | IEXTEN); //|ECHOPRT

      options.c_oflag &= (tcflag_t) ~(OPOST);
      options.c_iflag &= (tcflag_t) ~(INLCR | IGNCR | ICRNL | IGNBRK);
    #ifdef IUCLC
      options.c_iflag &= (tcflag_t) ~IUCLC;
    #endif
    #ifdef PARMRK
      options.c_iflag &= (tcflag_t) ~PARMRK;
    #endif

      // setup baud rate
      bool custom_baud = false;
      speed_t baud;
      switch (baudrate_) {
    #ifdef B0
      case 0: baud = B0; break;
    #endif
    #ifdef B50
      case 50: baud = B50; break;
    #endif
    #ifdef B75
      case 75: baud = B75; break;
    #endif
    #ifdef B110
      case 110: baud = B110; break;
    #endif
    #ifdef B134
      case 134: baud = B134; break;
    #endif
    #ifdef B150
      case 150: baud = B150; break;
    #endif
    #ifdef B200
      case 200: baud = B200; break;
    #endif
    #ifdef B300
      case 300: baud = B300; break;
    #endif
    #ifdef B600
      case 600: baud = B600; break;
    #endif
    #ifdef B1200
      case 1200: baud = B1200; break;
    #endif
    #ifdef B1800
      case 1800: baud = B1800; break;
    #endif
    #ifdef B2400
      case 2400: baud = B2400; break;
    #endif
    #ifdef B4800
      case 4800: baud = B4800; break;
    #endif
    #ifdef B7200
      case 7200: baud = B7200; break;
    #endif
    #ifdef B9600
      case 9600: baud = B9600; break;
    #endif
    #ifdef B14400
      case 14400: baud = B14400; break;
    #endif
    #ifdef B19200
      case 19200: baud = B19200; break;
    #endif
    #ifdef B28800
      case 28800: baud = B28800; break;
    #endif
    #ifdef B57600
      case 57600: baud = B57600; break;
    #endif
    #ifdef B76800
      case 76800: baud = B76800; break;
    #endif
    #ifdef B38400
      case 38400: baud = B38400; break;
    #endif
    #ifdef B115200
      case 115200: baud = B115200; break;
    #endif
    #ifdef B128000
      case 128000: baud = B128000; break;
    #endif
    #ifdef B153600
      case 153600: baud = B153600; break;
    #endif
    #ifdef B230400
      case 230400: baud = B230400; break;
    #endif
    #ifdef B256000
      case 256000: baud = B256000; break;
    #endif
    #ifdef B460800
      case 460800: baud = B460800; break;
    #endif
    #ifdef B921600
      case 921600: baud = B921600; break;
    #endif
    #ifdef B1000000
      case 1000000: baud = B1000000; break;
    #endif
    #ifdef B1152000
      case 1152000: baud = B1152000; break;
    #endif
    #ifdef B1500000
      case 1500000: baud = B1500000; break;
    #endif
    #ifdef B2000000
      case 2000000: baud = B2000000; break;
    #endif
    #ifdef B2500000
      case 2500000: baud = B2500000; break;
    #endif
    #ifdef B3000000
      case 3000000: baud = B3000000; break;
    #endif
    #ifdef B3500000
      case 3500000: baud = B3500000; break;
    #endif
    #ifdef B4000000
      case 4000000: baud = B4000000; break;
    #endif
      default:
        custom_baud = true;
        // Mac OS X 10.x Support
    #if defined(__APPLE__) && defined(__MACH__)
    #define IOSSIOSPEED _IOW('T', 2, speed_t)
        int new_baud = static_cast<int> (baudrate_);
        if (ioctl (fd_, IOSSIOSPEED, &new_baud, 1) < 0) {
          THROW (IOException, errno);
        }
        // Linux Support
    #elif defined(__linux__) && defined (TIOCSSERIAL)
        struct serial_struct ser;
        ioctl (fd_, TIOCGSERIAL, &ser);
        // set custom divisor
        ser.custom_divisor = ser.baud_base / (int) baudrate_;
        // update flags
        ser.flags &= ~ASYNC_SPD_MASK;
        ser.flags |= ASYNC_SPD_CUST;

        if (ioctl (fd_, TIOCSSERIAL, &ser) < 0) {
          THROW (IOException, errno);
        }
    #else
        throw invalid_argument ("OS does not currently support custom bauds");
    #endif
      }
      if (custom_baud == false) {
    #ifdef _BSD_SOURCE
        ::cfsetspeed(&options, baud);
    #else
        ::cfsetispeed(&options, baud);
        ::cfsetospeed(&options, baud);
    #endif
      }

      // setup char len
      options.c_cflag &= (tcflag_t) ~CSIZE;
      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
        throw invalid_argument ("invalid char len");
      // setup stopbits
      if (stopbits_ == stopbits_one)
        options.c_cflag &= (tcflag_t) ~(CSTOPB);
      else if (stopbits_ == stopbits_one_point_five)
        // ONE POINT FIVE same as TWO.. there is no POSIX support for 1.5
        options.c_cflag |=  (CSTOPB);
      else if (stopbits_ == stopbits_two)
        options.c_cflag |=  (CSTOPB);
      else
        throw invalid_argument ("invalid stop bit");
      // setup parity
      options.c_iflag &= (tcflag_t) ~(INPCK | ISTRIP);
      if (parity_ == parity_none) {
        options.c_cflag &= (tcflag_t) ~(PARENB | PARODD);
      } else if (parity_ == parity_even) {
        options.c_cflag &= (tcflag_t) ~(PARODD);
        options.c_cflag |=  (PARENB);
      } else if (parity_ == parity_odd) {
        options.c_cflag |=  (PARENB | PARODD);
      } else {
        throw invalid_argument ("invalid parity");
      }
      // setup flow control
      if (flowcontrol_ == flowcontrol_none) {
        xonxoff_ = false;
        rtscts_ = false;
      }
      if (flowcontrol_ == flowcontrol_software) {
        xonxoff_ = true;
        rtscts_ = false;
      }
      if (flowcontrol_ == flowcontrol_hardware) {
        xonxoff_ = false;
        rtscts_ = true;
      }
      // xonxoff
    #ifdef IXANY
      if (xonxoff_)
        options.c_iflag |=  (IXON | IXOFF); //|IXANY)
      else
        options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY);
    #else
      if (xonxoff_)
        options.c_iflag |=  (IXON | IXOFF);
      else
        options.c_iflag &= (tcflag_t) ~(IXON | IXOFF);
    #endif
      // rtscts
    #ifdef CRTSCTS
      if (rtscts_)
        options.c_cflag |=  (CRTSCTS);
      else
        options.c_cflag &= (unsigned long) ~(CRTSCTS);
    #elif defined CNEW_RTSCTS
      if (rtscts_)
        options.c_cflag |=  (CNEW_RTSCTS);
      else
        options.c_cflag &= (unsigned long) ~(CNEW_RTSCTS);
    #else
    #error "OS Support seems wrong."
    #endif

      // http://www.unixwiz.net/techtips/termios-vmin-vtime.html
      // this basically sets the read call up to be a polling read,
      // but we are using select to ensure there is data available
      // to read before each call, so we should never needlessly poll
      options.c_cc[VMIN] = 0;
      options.c_cc[VTIME] = 0;

      // activate settings
      ::tcsetattr (fd_, TCSANOW, &options);
    }

void serial::serial::Serial::SerialImpl::reconfigurePort | ( |  | ) | `[protected]`

void Serial::SerialImpl::sendBreak | ( | int | duration | ) |

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::sendBreak");
      }
      tcsendbreak (fd_, static_cast<int> (duration / 4));
    }

void serial::serial::Serial::SerialImpl::sendBreak | ( | int | duration | ) |

void Serial::SerialImpl::setBaudrate | ( | unsigned long | baudrate | ) |

    {
      baudrate_ = baudrate;
      if (is_open_)
        reconfigurePort ();
    }

void serial::serial::Serial::SerialImpl::setBaudrate | ( | unsigned long | baudrate | ) |

void Serial::SerialImpl::setBreak | ( | bool | level | ) |

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::setBreak");
      }
      if (level) {
        ioctl (fd_, TIOCSBRK);
      } else {
        ioctl (fd_, TIOCCBRK);
      }
    }

void serial::serial::Serial::SerialImpl::setBreak | ( | bool | level | ) |

void serial::serial::Serial::SerialImpl::setBytesize | ( | bytesize_t | bytesize | ) |

void serial::serial::Serial::SerialImpl::setBytesize | ( | bytesize_t | bytesize | ) |

void Serial::SerialImpl::setDTR | ( | bool | level | ) |

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::setDTR");
      }
      if (level) {
        ioctl (fd_, TIOCMBIS, TIOCM_DTR);
      } else {
        ioctl (fd_, TIOCMBIC, TIOCM_DTR);
      }
    }

void serial::serial::Serial::SerialImpl::setDTR | ( | bool | level | ) |

void serial::serial::Serial::SerialImpl::setFlowcontrol | ( | flowcontrol_t | flowcontrol | ) |

void serial::serial::Serial::SerialImpl::setFlowcontrol | ( | flowcontrol_t | flowcontrol | ) |

void serial::serial::Serial::SerialImpl::setParity | ( | parity_t | parity | ) |

void serial::serial::Serial::SerialImpl::setParity | ( | parity_t | parity | ) |

void Serial::SerialImpl::setPort | ( | const string & | port | ) |

    {
      port_ = port;
    }

void serial::serial::Serial::SerialImpl::setPort | ( | const string & | port | ) |

void Serial::SerialImpl::setRTS | ( | bool | level | ) |

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::setRTS");
      }
      if (level) {
        ioctl (fd_, TIOCMBIS, TIOCM_RTS);
      } else {
        ioctl (fd_, TIOCMBIC, TIOCM_RTS);
      }
    }

void serial::serial::Serial::SerialImpl::setRTS | ( | bool | level | ) |

void serial::serial::Serial::SerialImpl::setStopbits | ( | stopbits_t | stopbits | ) |

void serial::serial::Serial::SerialImpl::setStopbits | ( | stopbits_t | stopbits | ) |

void serial::serial::Serial::SerialImpl::setTimeout | ( | Timeout & | timeout | ) |

void serial::serial::Serial::SerialImpl::setTimeout | ( | Timeout & | timeout | ) |

bool Serial::SerialImpl::waitForChange | ( |  | ) |

    {
    #ifndef TIOCMIWAIT
      while (is_open_ == true) {
        int s = ioctl (fd_, TIOCMGET, 0);
        if ((s & TIOCM_CTS) != 0) return true;
        if ((s & TIOCM_DSR) != 0) return true;
        if ((s & TIOCM_RI) != 0) return true;
        if ((s & TIOCM_CD) != 0) return true;
        usleep(1000);
      }
      return false;
    #else
      if (ioctl(fd_, TIOCMIWAIT, (TIOCM_CD|TIOCM_DSR|TIOCM_RI|TIOCM_CTS)) != 0) {
        stringstream ss;
        ss << "waitForDSR failed on a call to ioctl(TIOCMIWAIT): "
           << errno << " " << strerror(errno);
        throw(SerialExecption(ss.str().c_str()));
      }
      return true;
    #endif
    }

bool serial::serial::Serial::SerialImpl::waitForChange | ( |  | ) |

size_t Serial::SerialImpl::write | ( | const uint8_t * | data,
|  | size_t | length
| ) |  |

Error

Timeout

Port ready to write

    {
      if (is_open_ == false) {
        throw PortNotOpenedException ("Serial::write");
      }
      fd_set writefds;
      size_t bytes_written = 0;
      struct timeval timeout;
      timeout.tv_sec =                    timeout_.write_timeout_constant / 1000;
      timeout.tv_usec = static_cast<int> (timeout_.write_timeout_multiplier % 1000);
      timeout.tv_usec *= 1000; // To convert to micro seconds
      while (bytes_written < length) {
        FD_ZERO (&writefds);
        FD_SET (fd_, &writefds);
        // On Linux the timeout struct is updated by select to contain the time
        // left on the timeout to make looping easier, but on other platforms this
        // does not occur.
    #if !defined(__linux__)
        // Begin timing select
        struct timespec start, end;
        get_time_now(start);
    #endif
        // Do the select
        int r = select (fd_ + 1, NULL, &writefds, NULL, &timeout);
    #if !defined(__linux__)
        // Calculate difference and update the structure
        get_time_now(end);
        // Calculate the time select took
        struct timeval diff;
        diff.tv_sec = end.tv_sec - start.tv_sec;
        diff.tv_usec = static_cast<int> ((end.tv_nsec - start.tv_nsec) / 1000);
        // Update the timeout
        if (timeout.tv_sec <= diff.tv_sec) {
          timeout.tv_sec = 0;
        } else {
          timeout.tv_sec -= diff.tv_sec;
        }
        if (timeout.tv_usec <= diff.tv_usec) {
          timeout.tv_usec = 0;
        } else {
          timeout.tv_usec -= diff.tv_usec;
        }
    #endif

        // Figure out what happened by looking at select's response 'r'
        if (r < 0) {
          // Select was interrupted, try again
          if (errno == EINTR) {
            continue;
          }
          // Otherwise there was some error
          THROW (IOException, errno);
        }
        if (r == 0) {
          break;
        }
        if (r > 0) {
          // Make sure our file descriptor is in the ready to write list
          if (FD_ISSET (fd_, &writefds)) {
            // This will write some
            ssize_t bytes_written_now =
              ::write (fd_, data + bytes_written, length - bytes_written);
            // write should always return some data as select reported it was
            // ready to write when we get to this point.
            if (bytes_written_now < 1) {
              // Disconnected devices, at least on Linux, show the
              // behavior that they are always ready to write immediately
              // but writing returns nothing.
              throw SerialExecption ("device reports readiness to write but "
                                     "returned no data (device disconnected?)");
            }
            // Update bytes_written
            bytes_written += static_cast<size_t> (bytes_written_now);
            // If bytes_written == size then we have written everything we need to
            if (bytes_written == length) {
              break;
            }
            // If bytes_written < size then we have more to write
            if (bytes_written < length) {
              continue;
            }
            // If bytes_written > size then we have over written, which shouldn't happen
            if (bytes_written > length) {
              throw SerialExecption ("write over wrote, too many bytes where "
                                     "written, this shouldn't happen, might be "
                                     "a logical error!");
            }
          }
          // This shouldn't happen, if r > 0 our fd has to be in the list!
          THROW (IOException, "select reports ready to write, but our fd isn't"
                              " in the list, this shouldn't happen!");
        }
      }
      return bytes_written;
    }

size_t serial::serial::Serial::SerialImpl::write | ( | const uint8_t * | data,
|  | size_t | length
| ) |  |

void Serial::SerialImpl::writeLock | ( |  | ) |

    {
      int result = pthread_mutex_lock(&this->write_mutex);
      if (result) {
        THROW (IOException, result);
      }
    }

void serial::serial::Serial::SerialImpl::writeLock | ( |  | ) |

void Serial::SerialImpl::writeUnlock | ( |  | ) |

    {
      int result = pthread_mutex_unlock(&this->write_mutex);
      if (result) {
        THROW (IOException, result);
      }
    }

void serial::serial::Serial::SerialImpl::writeUnlock | ( |  | ) |

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

- include/serial/impl/unix.h
- include/serial/impl/win.h
- src/impl/unix.cc
- src/impl/win.cc