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

serial 1.0 Cross-platformserialportlibraryforC++

- Main Page
- Namespaces
- Data Structures
- Files

- Data Structures
- Data Structure Index
- Data Fields

All Data Structures Namespaces Files Functions 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, long timeout, 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 (unsigned char *buf, size_t size=1)
size_t | write (const string &data)
void | flush ()
void | flushInput ()
void | flushOutput ()
void | sendBreak (int duration)
void | setBreak (bool level)
void | setRTS (bool level)
void | setDTR (bool level)
bool | getCTS ()
bool | getDSR ()
bool | getRI ()
bool | getCD ()
void | setPort (const string &port)
string | getPort () const
void | setTimeout (long timeout)
long | 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, long timeout, 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 (char *buf, size_t size=1)
size_t | write (const string &data)
void | flush ()
void | flushInput ()
void | flushOutput ()
void | sendBreak (int duration)
void | setBreak (bool level)
void | setRTS (bool level)
void | setDTR (bool level)
bool | getCTS ()
bool | getDSR ()
bool | getRI ()
bool | getCD ()
void | setPort (const string &port)
string | getPort () const
void | setTimeout (long timeout)
long | 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

## Protected Member Functions

void | reconfigurePort ()
void | reconfigurePort ()

## Constructor & Destructor Documentation

serial::serial::Serial::SerialImpl::SerialImpl | ( | const string & | port,
|  | unsigned long | baudrate,
|  | long | timeout,
|  | 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,
|  | long | timeout,
|  | bytesize_t | bytesize,
|  | parity_t | parity,
|  | stopbits_t | stopbits,
|  | flowcontrol_t | flowcontrol
| ) |  |

    : port_ (port), fd_ (-1), is_open_ (false), xonxoff_ (true), rtscts_ (false),
      timeout_ (timeout), 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

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

long 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 | ( | char * | buf,
|  | size_t | size = `1`
| ) |  |

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

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

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

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

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

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 |= (unsigned long)  (CLOCAL|CREAD);
      options.c_lflag &= (unsigned long) ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|
                                           ISIG|IEXTEN); //|ECHOPRT

      options.c_oflag &= (unsigned long) ~(OPOST);
      options.c_iflag &= (unsigned long) ~(INLCR|IGNCR|ICRNL|IGNBRK);
    #ifdef IUCLC
      options.c_iflag &= (unsigned long) ~IUCLC;
    #endif
    #ifdef PARMRK
      options.c_iflag &= (unsigned long) ~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
        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__)
          struct serial_struct ser;
          ioctl (fd_, TIOCGSERIAL, &ser);
          // set custom divisor
          ser.custom_divisor = ser.baud_base / 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 &= (unsigned long) ~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 &= (unsigned long) ~(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 &= (unsigned long) ~(INPCK|ISTRIP);
      if (parity_ == parity_none)
      {
        options.c_cflag &= (unsigned long) ~(PARENB|PARODD);
      }
      else if (parity_ == parity_even)
      {
        options.c_cflag &= (unsigned long) ~(PARODD);
        options.c_cflag |=  (PARENB);
      }
      else if (parity_ == parity_odd)
      {
        options.c_cflag |=  (PARENB|PARODD);
      }
      else
      {
        throw invalid_argument ("invalid parity");
      }
      // setup flow control
      // xonxoff
    #ifdef IXANY
      if (xonxoff_)
        options.c_iflag |=  (IXON|IXOFF); //|IXANY)
      else
        options.c_iflag &= (unsigned long) ~(IXON|IXOFF|IXANY);
    #else
      if (xonxoff_)
        options.c_iflag |=  (IXON|IXOFF);
      else
        options.c_iflag &= (unsigned long) ~(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::SerialImpl::setTimeout | ( | long | timeout | ) |

    {
      timeout_ = timeout;
    }

void serial::serial::Serial::SerialImpl::setTimeout | ( | long | timeout | ) |

size_t Serial::SerialImpl::write | ( | const string & | data | ) |

    {
      if (is_open_ == false)
      {
        throw PortNotOpenedException ("Serial::write");
      }

      return static_cast<size_t> (::write (fd_, data.c_str (), data.length ()));
    }

size_t serial::serial::Serial::SerialImpl::write | ( | const string & | data | ) |

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

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

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

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

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

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