Chris@16: // Chris@16: // impl/serial_port_base.ipp Chris@16: // ~~~~~~~~~~~~~~~~~~~~~~~~~ Chris@16: // Chris@101: // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) Chris@16: // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: Chris@16: #ifndef BOOST_ASIO_IMPL_SERIAL_PORT_BASE_IPP Chris@16: #define BOOST_ASIO_IMPL_SERIAL_PORT_BASE_IPP Chris@16: Chris@16: #if defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: # pragma once Chris@16: #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: Chris@16: #include Chris@16: Chris@16: #if defined(BOOST_ASIO_HAS_SERIAL_PORT) Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #if defined(GENERATING_DOCUMENTATION) Chris@16: # define BOOST_ASIO_OPTION_STORAGE implementation_defined Chris@16: #elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: # define BOOST_ASIO_OPTION_STORAGE DCB Chris@16: #else Chris@16: # define BOOST_ASIO_OPTION_STORAGE termios Chris@16: #endif Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace asio { Chris@16: Chris@16: boost::system::error_code serial_port_base::baud_rate::store( Chris@16: BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const Chris@16: { Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: storage.BaudRate = value_; Chris@16: #else Chris@16: speed_t baud; Chris@16: switch (value_) Chris@16: { Chris@16: // Do POSIX-specified rates first. Chris@16: case 0: baud = B0; break; Chris@16: case 50: baud = B50; break; Chris@16: case 75: baud = B75; break; Chris@16: case 110: baud = B110; break; Chris@16: case 134: baud = B134; break; Chris@16: case 150: baud = B150; break; Chris@16: case 200: baud = B200; break; Chris@16: case 300: baud = B300; break; Chris@16: case 600: baud = B600; break; Chris@16: case 1200: baud = B1200; break; Chris@16: case 1800: baud = B1800; break; Chris@16: case 2400: baud = B2400; break; Chris@16: case 4800: baud = B4800; break; Chris@16: case 9600: baud = B9600; break; Chris@16: case 19200: baud = B19200; break; Chris@16: case 38400: baud = B38400; break; Chris@16: // And now the extended ones conditionally. Chris@16: # ifdef B7200 Chris@16: case 7200: baud = B7200; break; Chris@16: # endif Chris@16: # ifdef B14400 Chris@16: case 14400: baud = B14400; break; Chris@16: # endif Chris@16: # ifdef B57600 Chris@16: case 57600: baud = B57600; break; Chris@16: # endif Chris@16: # ifdef B115200 Chris@16: case 115200: baud = B115200; break; Chris@16: # endif Chris@16: # ifdef B230400 Chris@16: case 230400: baud = B230400; break; Chris@16: # endif Chris@16: # ifdef B460800 Chris@16: case 460800: baud = B460800; break; Chris@16: # endif Chris@16: # ifdef B500000 Chris@16: case 500000: baud = B500000; break; Chris@16: # endif Chris@16: # ifdef B576000 Chris@16: case 576000: baud = B576000; break; Chris@16: # endif Chris@16: # ifdef B921600 Chris@16: case 921600: baud = B921600; break; Chris@16: # endif Chris@16: # ifdef B1000000 Chris@16: case 1000000: baud = B1000000; break; Chris@16: # endif Chris@16: # ifdef B1152000 Chris@16: case 1152000: baud = B1152000; break; Chris@16: # endif Chris@16: # ifdef B2000000 Chris@16: case 2000000: baud = B2000000; break; Chris@16: # endif Chris@16: # ifdef B3000000 Chris@16: case 3000000: baud = B3000000; break; Chris@16: # endif Chris@16: # ifdef B3500000 Chris@16: case 3500000: baud = B3500000; break; Chris@16: # endif Chris@16: # ifdef B4000000 Chris@16: case 4000000: baud = B4000000; break; Chris@16: # endif Chris@16: default: Chris@16: ec = boost::asio::error::invalid_argument; Chris@16: return ec; Chris@16: } Chris@16: # if defined(_BSD_SOURCE) Chris@16: ::cfsetspeed(&storage, baud); Chris@16: # else Chris@16: ::cfsetispeed(&storage, baud); Chris@16: ::cfsetospeed(&storage, baud); Chris@16: # endif Chris@16: #endif Chris@16: ec = boost::system::error_code(); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: boost::system::error_code serial_port_base::baud_rate::load( Chris@16: const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) Chris@16: { Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: value_ = storage.BaudRate; Chris@16: #else Chris@16: speed_t baud = ::cfgetospeed(&storage); Chris@16: switch (baud) Chris@16: { Chris@16: // First do those specified by POSIX. Chris@16: case B0: value_ = 0; break; Chris@16: case B50: value_ = 50; break; Chris@16: case B75: value_ = 75; break; Chris@16: case B110: value_ = 110; break; Chris@16: case B134: value_ = 134; break; Chris@16: case B150: value_ = 150; break; Chris@16: case B200: value_ = 200; break; Chris@16: case B300: value_ = 300; break; Chris@16: case B600: value_ = 600; break; Chris@16: case B1200: value_ = 1200; break; Chris@16: case B1800: value_ = 1800; break; Chris@16: case B2400: value_ = 2400; break; Chris@16: case B4800: value_ = 4800; break; Chris@16: case B9600: value_ = 9600; break; Chris@16: case B19200: value_ = 19200; break; Chris@16: case B38400: value_ = 38400; break; Chris@16: // Now conditionally handle a bunch of extended rates. Chris@16: # ifdef B7200 Chris@16: case B7200: value_ = 7200; break; Chris@16: # endif Chris@16: # ifdef B14400 Chris@16: case B14400: value_ = 14400; break; Chris@16: # endif Chris@16: # ifdef B57600 Chris@16: case B57600: value_ = 57600; break; Chris@16: # endif Chris@16: # ifdef B115200 Chris@16: case B115200: value_ = 115200; break; Chris@16: # endif Chris@16: # ifdef B230400 Chris@16: case B230400: value_ = 230400; break; Chris@16: # endif Chris@16: # ifdef B460800 Chris@16: case B460800: value_ = 460800; break; Chris@16: # endif Chris@16: # ifdef B500000 Chris@16: case B500000: value_ = 500000; break; Chris@16: # endif Chris@16: # ifdef B576000 Chris@16: case B576000: value_ = 576000; break; Chris@16: # endif Chris@16: # ifdef B921600 Chris@16: case B921600: value_ = 921600; break; Chris@16: # endif Chris@16: # ifdef B1000000 Chris@16: case B1000000: value_ = 1000000; break; Chris@16: # endif Chris@16: # ifdef B1152000 Chris@16: case B1152000: value_ = 1152000; break; Chris@16: # endif Chris@16: # ifdef B2000000 Chris@16: case B2000000: value_ = 2000000; break; Chris@16: # endif Chris@16: # ifdef B3000000 Chris@16: case B3000000: value_ = 3000000; break; Chris@16: # endif Chris@16: # ifdef B3500000 Chris@16: case B3500000: value_ = 3500000; break; Chris@16: # endif Chris@16: # ifdef B4000000 Chris@16: case B4000000: value_ = 4000000; break; Chris@16: # endif Chris@16: default: Chris@16: value_ = 0; Chris@16: ec = boost::asio::error::invalid_argument; Chris@16: return ec; Chris@16: } Chris@16: #endif Chris@16: ec = boost::system::error_code(); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: serial_port_base::flow_control::flow_control( Chris@16: serial_port_base::flow_control::type t) Chris@16: : value_(t) Chris@16: { Chris@16: if (t != none && t != software && t != hardware) Chris@16: { Chris@16: std::out_of_range ex("invalid flow_control value"); Chris@16: boost::asio::detail::throw_exception(ex); Chris@16: } Chris@16: } Chris@16: Chris@16: boost::system::error_code serial_port_base::flow_control::store( Chris@16: BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const Chris@16: { Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: storage.fOutxCtsFlow = FALSE; Chris@16: storage.fOutxDsrFlow = FALSE; Chris@16: storage.fTXContinueOnXoff = TRUE; Chris@16: storage.fDtrControl = DTR_CONTROL_ENABLE; Chris@16: storage.fDsrSensitivity = FALSE; Chris@16: storage.fOutX = FALSE; Chris@16: storage.fInX = FALSE; Chris@16: storage.fRtsControl = RTS_CONTROL_ENABLE; Chris@16: switch (value_) Chris@16: { Chris@16: case none: Chris@16: break; Chris@16: case software: Chris@16: storage.fOutX = TRUE; Chris@16: storage.fInX = TRUE; Chris@16: break; Chris@16: case hardware: Chris@16: storage.fOutxCtsFlow = TRUE; Chris@16: storage.fRtsControl = RTS_CONTROL_HANDSHAKE; Chris@16: break; Chris@16: default: Chris@16: break; Chris@16: } Chris@16: #else Chris@16: switch (value_) Chris@16: { Chris@16: case none: Chris@16: storage.c_iflag &= ~(IXOFF | IXON); Chris@16: # if defined(_BSD_SOURCE) Chris@16: storage.c_cflag &= ~CRTSCTS; Chris@16: # elif defined(__QNXNTO__) Chris@16: storage.c_cflag &= ~(IHFLOW | OHFLOW); Chris@16: # endif Chris@16: break; Chris@16: case software: Chris@16: storage.c_iflag |= IXOFF | IXON; Chris@16: # if defined(_BSD_SOURCE) Chris@16: storage.c_cflag &= ~CRTSCTS; Chris@16: # elif defined(__QNXNTO__) Chris@16: storage.c_cflag &= ~(IHFLOW | OHFLOW); Chris@16: # endif Chris@16: break; Chris@16: case hardware: Chris@16: # if defined(_BSD_SOURCE) Chris@16: storage.c_iflag &= ~(IXOFF | IXON); Chris@16: storage.c_cflag |= CRTSCTS; Chris@16: break; Chris@16: # elif defined(__QNXNTO__) Chris@16: storage.c_iflag &= ~(IXOFF | IXON); Chris@16: storage.c_cflag |= (IHFLOW | OHFLOW); Chris@16: break; Chris@16: # else Chris@16: ec = boost::asio::error::operation_not_supported; Chris@16: return ec; Chris@16: # endif Chris@16: default: Chris@16: break; Chris@16: } Chris@16: #endif Chris@16: ec = boost::system::error_code(); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: boost::system::error_code serial_port_base::flow_control::load( Chris@16: const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) Chris@16: { Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: if (storage.fOutX && storage.fInX) Chris@16: { Chris@16: value_ = software; Chris@16: } Chris@16: else if (storage.fOutxCtsFlow && storage.fRtsControl == RTS_CONTROL_HANDSHAKE) Chris@16: { Chris@16: value_ = hardware; Chris@16: } Chris@16: else Chris@16: { Chris@16: value_ = none; Chris@16: } Chris@16: #else Chris@16: if (storage.c_iflag & (IXOFF | IXON)) Chris@16: { Chris@16: value_ = software; Chris@16: } Chris@16: # if defined(_BSD_SOURCE) Chris@16: else if (storage.c_cflag & CRTSCTS) Chris@16: { Chris@16: value_ = hardware; Chris@16: } Chris@16: # elif defined(__QNXNTO__) Chris@16: else if (storage.c_cflag & IHFLOW && storage.c_cflag & OHFLOW) Chris@16: { Chris@16: value_ = hardware; Chris@16: } Chris@16: # endif Chris@16: else Chris@16: { Chris@16: value_ = none; Chris@16: } Chris@16: #endif Chris@16: ec = boost::system::error_code(); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: serial_port_base::parity::parity(serial_port_base::parity::type t) Chris@16: : value_(t) Chris@16: { Chris@16: if (t != none && t != odd && t != even) Chris@16: { Chris@16: std::out_of_range ex("invalid parity value"); Chris@16: boost::asio::detail::throw_exception(ex); Chris@16: } Chris@16: } Chris@16: Chris@16: boost::system::error_code serial_port_base::parity::store( Chris@16: BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const Chris@16: { Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: switch (value_) Chris@16: { Chris@16: case none: Chris@16: storage.fParity = FALSE; Chris@16: storage.Parity = NOPARITY; Chris@16: break; Chris@16: case odd: Chris@16: storage.fParity = TRUE; Chris@16: storage.Parity = ODDPARITY; Chris@16: break; Chris@16: case even: Chris@16: storage.fParity = TRUE; Chris@16: storage.Parity = EVENPARITY; Chris@16: break; Chris@16: default: Chris@16: break; Chris@16: } Chris@16: #else Chris@16: switch (value_) Chris@16: { Chris@16: case none: Chris@16: storage.c_iflag |= IGNPAR; Chris@16: storage.c_cflag &= ~(PARENB | PARODD); Chris@16: break; Chris@16: case even: Chris@16: storage.c_iflag &= ~(IGNPAR | PARMRK); Chris@16: storage.c_iflag |= INPCK; Chris@16: storage.c_cflag |= PARENB; Chris@16: storage.c_cflag &= ~PARODD; Chris@16: break; Chris@16: case odd: Chris@16: storage.c_iflag &= ~(IGNPAR | PARMRK); Chris@16: storage.c_iflag |= INPCK; Chris@16: storage.c_cflag |= (PARENB | PARODD); Chris@16: break; Chris@16: default: Chris@16: break; Chris@16: } Chris@16: #endif Chris@16: ec = boost::system::error_code(); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: boost::system::error_code serial_port_base::parity::load( Chris@16: const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) Chris@16: { Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: if (storage.Parity == EVENPARITY) Chris@16: { Chris@16: value_ = even; Chris@16: } Chris@16: else if (storage.Parity == ODDPARITY) Chris@16: { Chris@16: value_ = odd; Chris@16: } Chris@16: else Chris@16: { Chris@16: value_ = none; Chris@16: } Chris@16: #else Chris@16: if (storage.c_cflag & PARENB) Chris@16: { Chris@16: if (storage.c_cflag & PARODD) Chris@16: { Chris@16: value_ = odd; Chris@16: } Chris@16: else Chris@16: { Chris@16: value_ = even; Chris@16: } Chris@16: } Chris@16: else Chris@16: { Chris@16: value_ = none; Chris@16: } Chris@16: #endif Chris@16: ec = boost::system::error_code(); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: serial_port_base::stop_bits::stop_bits( Chris@16: serial_port_base::stop_bits::type t) Chris@16: : value_(t) Chris@16: { Chris@16: if (t != one && t != onepointfive && t != two) Chris@16: { Chris@16: std::out_of_range ex("invalid stop_bits value"); Chris@16: boost::asio::detail::throw_exception(ex); Chris@16: } Chris@16: } Chris@16: Chris@16: boost::system::error_code serial_port_base::stop_bits::store( Chris@16: BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const Chris@16: { Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: switch (value_) Chris@16: { Chris@16: case one: Chris@16: storage.StopBits = ONESTOPBIT; Chris@16: break; Chris@16: case onepointfive: Chris@16: storage.StopBits = ONE5STOPBITS; Chris@16: break; Chris@16: case two: Chris@16: storage.StopBits = TWOSTOPBITS; Chris@16: break; Chris@16: default: Chris@16: break; Chris@16: } Chris@16: #else Chris@16: switch (value_) Chris@16: { Chris@16: case one: Chris@16: storage.c_cflag &= ~CSTOPB; Chris@16: break; Chris@16: case two: Chris@16: storage.c_cflag |= CSTOPB; Chris@16: break; Chris@16: default: Chris@16: ec = boost::asio::error::operation_not_supported; Chris@16: return ec; Chris@16: } Chris@16: #endif Chris@16: ec = boost::system::error_code(); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: boost::system::error_code serial_port_base::stop_bits::load( Chris@16: const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) Chris@16: { Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: if (storage.StopBits == ONESTOPBIT) Chris@16: { Chris@16: value_ = one; Chris@16: } Chris@16: else if (storage.StopBits == ONE5STOPBITS) Chris@16: { Chris@16: value_ = onepointfive; Chris@16: } Chris@16: else if (storage.StopBits == TWOSTOPBITS) Chris@16: { Chris@16: value_ = two; Chris@16: } Chris@16: else Chris@16: { Chris@16: value_ = one; Chris@16: } Chris@16: #else Chris@16: value_ = (storage.c_cflag & CSTOPB) ? two : one; Chris@16: #endif Chris@16: ec = boost::system::error_code(); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: serial_port_base::character_size::character_size(unsigned int t) Chris@16: : value_(t) Chris@16: { Chris@16: if (t < 5 || t > 8) Chris@16: { Chris@16: std::out_of_range ex("invalid character_size value"); Chris@16: boost::asio::detail::throw_exception(ex); Chris@16: } Chris@16: } Chris@16: Chris@16: boost::system::error_code serial_port_base::character_size::store( Chris@16: BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const Chris@16: { Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: storage.ByteSize = value_; Chris@16: #else Chris@16: storage.c_cflag &= ~CSIZE; Chris@16: switch (value_) Chris@16: { Chris@16: case 5: storage.c_cflag |= CS5; break; Chris@16: case 6: storage.c_cflag |= CS6; break; Chris@16: case 7: storage.c_cflag |= CS7; break; Chris@16: case 8: storage.c_cflag |= CS8; break; Chris@16: default: break; Chris@16: } Chris@16: #endif Chris@16: ec = boost::system::error_code(); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: boost::system::error_code serial_port_base::character_size::load( Chris@16: const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) Chris@16: { Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: value_ = storage.ByteSize; Chris@16: #else Chris@16: if ((storage.c_cflag & CSIZE) == CS5) { value_ = 5; } Chris@16: else if ((storage.c_cflag & CSIZE) == CS6) { value_ = 6; } Chris@16: else if ((storage.c_cflag & CSIZE) == CS7) { value_ = 7; } Chris@16: else if ((storage.c_cflag & CSIZE) == CS8) { value_ = 8; } Chris@16: else Chris@16: { Chris@16: // Hmmm, use 8 for now. Chris@16: value_ = 8; Chris@16: } Chris@16: #endif Chris@16: ec = boost::system::error_code(); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: } // namespace asio Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #undef BOOST_ASIO_OPTION_STORAGE Chris@16: Chris@16: #endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) Chris@16: Chris@16: #endif // BOOST_ASIO_IMPL_SERIAL_PORT_BASE_IPP