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