Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:57

0001 //
0002 // impl/serial_port_base.ipp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
0007 //
0008 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0009 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 
0012 #ifndef BOOST_ASIO_IMPL_SERIAL_PORT_BASE_IPP
0013 #define BOOST_ASIO_IMPL_SERIAL_PORT_BASE_IPP
0014 
0015 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0016 # pragma once
0017 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0018 
0019 #include <boost/asio/detail/config.hpp>
0020 
0021 #if defined(BOOST_ASIO_HAS_SERIAL_PORT)
0022 
0023 #include <stdexcept>
0024 #include <boost/asio/error.hpp>
0025 #include <boost/asio/serial_port_base.hpp>
0026 #include <boost/asio/detail/throw_exception.hpp>
0027 
0028 #if defined(GENERATING_DOCUMENTATION)
0029 # define BOOST_ASIO_OPTION_STORAGE implementation_defined
0030 #elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0031 # define BOOST_ASIO_OPTION_STORAGE DCB
0032 #else
0033 # define BOOST_ASIO_OPTION_STORAGE termios
0034 #endif
0035 
0036 #include <boost/asio/detail/push_options.hpp>
0037 
0038 namespace boost {
0039 namespace asio {
0040 
0041 BOOST_ASIO_SYNC_OP_VOID serial_port_base::baud_rate::store(
0042     BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
0043 {
0044 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0045   storage.BaudRate = value_;
0046 #else
0047   speed_t baud;
0048   switch (value_)
0049   {
0050   // Do POSIX-specified rates first.
0051   case 0: baud = B0; break;
0052   case 50: baud = B50; break;
0053   case 75: baud = B75; break;
0054   case 110: baud = B110; break;
0055   case 134: baud = B134; break;
0056   case 150: baud = B150; break;
0057   case 200: baud = B200; break;
0058   case 300: baud = B300; break;
0059   case 600: baud = B600; break;
0060   case 1200: baud = B1200; break;
0061   case 1800: baud = B1800; break;
0062   case 2400: baud = B2400; break;
0063   case 4800: baud = B4800; break;
0064   case 9600: baud = B9600; break;
0065   case 19200: baud = B19200; break;
0066   case 38400: baud = B38400; break;
0067   // And now the extended ones conditionally.
0068 # ifdef B7200
0069   case 7200: baud = B7200; break;
0070 # endif
0071 # ifdef B14400
0072   case 14400: baud = B14400; break;
0073 # endif
0074 # ifdef B57600
0075   case 57600: baud = B57600; break;
0076 # endif
0077 # ifdef B115200
0078   case 115200: baud = B115200; break;
0079 # endif
0080 # ifdef B230400
0081   case 230400: baud = B230400; break;
0082 # endif
0083 # ifdef B460800
0084   case 460800: baud = B460800; break;
0085 # endif
0086 # ifdef B500000
0087   case 500000: baud = B500000; break;
0088 # endif
0089 # ifdef B576000
0090   case 576000: baud = B576000; break;
0091 # endif
0092 # ifdef B921600
0093   case 921600: baud = B921600; break;
0094 # endif
0095 # ifdef B1000000
0096   case 1000000: baud = B1000000; break;
0097 # endif
0098 # ifdef B1152000
0099   case 1152000: baud = B1152000; break;
0100 # endif
0101 # ifdef B2000000
0102   case 2000000: baud = B2000000; break;
0103 # endif
0104 # ifdef B3000000
0105   case 3000000: baud = B3000000; break;
0106 # endif
0107 # ifdef B3500000
0108   case 3500000: baud = B3500000; break;
0109 # endif
0110 # ifdef B4000000
0111   case 4000000: baud = B4000000; break;
0112 # endif
0113   default:
0114     ec = boost::asio::error::invalid_argument;
0115     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0116   }
0117 # if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
0118   ::cfsetspeed(&storage, baud);
0119 # else
0120   ::cfsetispeed(&storage, baud);
0121   ::cfsetospeed(&storage, baud);
0122 # endif
0123 #endif
0124   ec = boost::system::error_code();
0125   BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0126 }
0127 
0128 BOOST_ASIO_SYNC_OP_VOID serial_port_base::baud_rate::load(
0129     const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
0130 {
0131 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0132   value_ = storage.BaudRate;
0133 #else
0134   speed_t baud = ::cfgetospeed(&storage);
0135   switch (baud)
0136   {
0137   // First do those specified by POSIX.
0138   case B0: value_ = 0; break;
0139   case B50: value_ = 50; break;
0140   case B75: value_ = 75; break;
0141   case B110: value_ = 110; break;
0142   case B134: value_ = 134; break;
0143   case B150: value_ = 150; break;
0144   case B200: value_ = 200; break;
0145   case B300: value_ = 300; break;
0146   case B600: value_ = 600; break;
0147   case B1200: value_ = 1200; break;
0148   case B1800: value_ = 1800; break;
0149   case B2400: value_ = 2400; break;
0150   case B4800: value_ = 4800; break;
0151   case B9600: value_ = 9600; break;
0152   case B19200: value_ = 19200; break;
0153   case B38400: value_ = 38400; break;
0154   // Now conditionally handle a bunch of extended rates.
0155 # ifdef B7200
0156   case B7200: value_ = 7200; break;
0157 # endif
0158 # ifdef B14400
0159   case B14400: value_ = 14400; break;
0160 # endif
0161 # ifdef B57600
0162   case B57600: value_ = 57600; break;
0163 # endif
0164 # ifdef B115200
0165   case B115200: value_ = 115200; break;
0166 # endif
0167 # ifdef B230400
0168   case B230400: value_ = 230400; break;
0169 # endif
0170 # ifdef B460800
0171   case B460800: value_ = 460800; break;
0172 # endif
0173 # ifdef B500000
0174   case B500000: value_ = 500000; break;
0175 # endif
0176 # ifdef B576000
0177   case B576000: value_ = 576000; break;
0178 # endif
0179 # ifdef B921600
0180   case B921600: value_ = 921600; break;
0181 # endif
0182 # ifdef B1000000
0183   case B1000000: value_ = 1000000; break;
0184 # endif
0185 # ifdef B1152000
0186   case B1152000: value_ = 1152000; break;
0187 # endif
0188 # ifdef B2000000
0189   case B2000000: value_ = 2000000; break;
0190 # endif
0191 # ifdef B3000000
0192   case B3000000: value_ = 3000000; break;
0193 # endif
0194 # ifdef B3500000
0195   case B3500000: value_ = 3500000; break;
0196 # endif
0197 # ifdef B4000000
0198   case B4000000: value_ = 4000000; break;
0199 # endif
0200   default:
0201     value_ = 0;
0202     ec = boost::asio::error::invalid_argument;
0203     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0204   }
0205 #endif
0206   ec = boost::system::error_code();
0207   BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0208 }
0209 
0210 serial_port_base::flow_control::flow_control(
0211     serial_port_base::flow_control::type t)
0212   : value_(t)
0213 {
0214   if (t != none && t != software && t != hardware)
0215   {
0216     std::out_of_range ex("invalid flow_control value");
0217     boost::asio::detail::throw_exception(ex);
0218   }
0219 }
0220 
0221 BOOST_ASIO_SYNC_OP_VOID serial_port_base::flow_control::store(
0222     BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
0223 {
0224 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0225   storage.fOutxCtsFlow = FALSE;
0226   storage.fOutxDsrFlow = FALSE;
0227   storage.fTXContinueOnXoff = TRUE;
0228   storage.fDtrControl = DTR_CONTROL_ENABLE;
0229   storage.fDsrSensitivity = FALSE;
0230   storage.fOutX = FALSE;
0231   storage.fInX = FALSE;
0232   storage.fRtsControl = RTS_CONTROL_ENABLE;
0233   switch (value_)
0234   {
0235   case none:
0236     break;
0237   case software:
0238     storage.fOutX = TRUE;
0239     storage.fInX = TRUE;
0240     break;
0241   case hardware:
0242     storage.fOutxCtsFlow = TRUE;
0243     storage.fRtsControl = RTS_CONTROL_HANDSHAKE;
0244     break;
0245   default:
0246     break;
0247   }
0248 #else
0249   switch (value_)
0250   {
0251   case none:
0252     storage.c_iflag &= ~(IXOFF | IXON);
0253 # if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
0254     storage.c_cflag &= ~CRTSCTS;
0255 # elif defined(__QNXNTO__)
0256     storage.c_cflag &= ~(IHFLOW | OHFLOW);
0257 # endif
0258     break;
0259   case software:
0260     storage.c_iflag |= IXOFF | IXON;
0261 # if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
0262     storage.c_cflag &= ~CRTSCTS;
0263 # elif defined(__QNXNTO__)
0264     storage.c_cflag &= ~(IHFLOW | OHFLOW);
0265 # endif
0266     break;
0267   case hardware:
0268 # if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
0269     storage.c_iflag &= ~(IXOFF | IXON);
0270     storage.c_cflag |= CRTSCTS;
0271     break;
0272 # elif defined(__QNXNTO__)
0273     storage.c_iflag &= ~(IXOFF | IXON);
0274     storage.c_cflag |= (IHFLOW | OHFLOW);
0275     break;
0276 # else
0277     ec = boost::asio::error::operation_not_supported;
0278     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0279 # endif
0280   default:
0281     break;
0282   }
0283 #endif
0284   ec = boost::system::error_code();
0285   BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0286 }
0287 
0288 BOOST_ASIO_SYNC_OP_VOID serial_port_base::flow_control::load(
0289     const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
0290 {
0291 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0292   if (storage.fOutX && storage.fInX)
0293   {
0294     value_ = software;
0295   }
0296   else if (storage.fOutxCtsFlow && storage.fRtsControl == RTS_CONTROL_HANDSHAKE)
0297   {
0298     value_ = hardware;
0299   }
0300   else
0301   {
0302     value_ = none;
0303   }
0304 #else
0305   if (storage.c_iflag & (IXOFF | IXON))
0306   {
0307     value_ = software;
0308   }
0309 # if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
0310   else if (storage.c_cflag & CRTSCTS)
0311   {
0312     value_ = hardware;
0313   }
0314 # elif defined(__QNXNTO__)
0315   else if (storage.c_cflag & IHFLOW && storage.c_cflag & OHFLOW)
0316   {
0317     value_ = hardware;
0318   }
0319 # endif
0320   else
0321   {
0322     value_ = none;
0323   }
0324 #endif
0325   ec = boost::system::error_code();
0326   BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0327 }
0328 
0329 serial_port_base::parity::parity(serial_port_base::parity::type t)
0330   : value_(t)
0331 {
0332   if (t != none && t != odd && t != even)
0333   {
0334     std::out_of_range ex("invalid parity value");
0335     boost::asio::detail::throw_exception(ex);
0336   }
0337 }
0338 
0339 BOOST_ASIO_SYNC_OP_VOID serial_port_base::parity::store(
0340     BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
0341 {
0342 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0343   switch (value_)
0344   {
0345   case none:
0346     storage.fParity = FALSE;
0347     storage.Parity = NOPARITY;
0348     break;
0349   case odd:
0350     storage.fParity = TRUE;
0351     storage.Parity = ODDPARITY;
0352     break;
0353   case even:
0354     storage.fParity = TRUE;
0355     storage.Parity = EVENPARITY;
0356     break;
0357   default:
0358     break;
0359   }
0360 #else
0361   switch (value_)
0362   {
0363   case none:
0364     storage.c_iflag |= IGNPAR;
0365     storage.c_cflag &= ~(PARENB | PARODD);
0366     break;
0367   case even:
0368     storage.c_iflag &= ~(IGNPAR | PARMRK);
0369     storage.c_iflag |= INPCK;
0370     storage.c_cflag |= PARENB;
0371     storage.c_cflag &= ~PARODD;
0372     break;
0373   case odd:
0374     storage.c_iflag &= ~(IGNPAR | PARMRK);
0375     storage.c_iflag |= INPCK;
0376     storage.c_cflag |= (PARENB | PARODD);
0377     break;
0378   default:
0379     break;
0380   }
0381 #endif
0382   ec = boost::system::error_code();
0383   BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0384 }
0385 
0386 BOOST_ASIO_SYNC_OP_VOID serial_port_base::parity::load(
0387     const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
0388 {
0389 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0390   if (storage.Parity == EVENPARITY)
0391   {
0392     value_ = even;
0393   }
0394   else if (storage.Parity == ODDPARITY)
0395   {
0396     value_ = odd;
0397   }
0398   else
0399   {
0400     value_ = none;
0401   }
0402 #else
0403   if (storage.c_cflag & PARENB)
0404   {
0405     if (storage.c_cflag & PARODD)
0406     {
0407       value_ = odd;
0408     }
0409     else
0410     {
0411       value_ = even;
0412     }
0413   }
0414   else
0415   {
0416     value_ = none;
0417   }
0418 #endif
0419   ec = boost::system::error_code();
0420   BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0421 }
0422 
0423 serial_port_base::stop_bits::stop_bits(
0424     serial_port_base::stop_bits::type t)
0425   : value_(t)
0426 {
0427   if (t != one && t != onepointfive && t != two)
0428   {
0429     std::out_of_range ex("invalid stop_bits value");
0430     boost::asio::detail::throw_exception(ex);
0431   }
0432 }
0433 
0434 BOOST_ASIO_SYNC_OP_VOID serial_port_base::stop_bits::store(
0435     BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
0436 {
0437 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0438   switch (value_)
0439   {
0440   case one:
0441     storage.StopBits = ONESTOPBIT;
0442     break;
0443   case onepointfive:
0444     storage.StopBits = ONE5STOPBITS;
0445     break;
0446   case two:
0447     storage.StopBits = TWOSTOPBITS;
0448     break;
0449   default:
0450     break;
0451   }
0452 #else
0453   switch (value_)
0454   {
0455   case one:
0456     storage.c_cflag &= ~CSTOPB;
0457     break;
0458   case two:
0459     storage.c_cflag |= CSTOPB;
0460     break;
0461   default:
0462     ec = boost::asio::error::operation_not_supported;
0463     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0464   }
0465 #endif
0466   ec = boost::system::error_code();
0467   BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0468 }
0469 
0470 BOOST_ASIO_SYNC_OP_VOID serial_port_base::stop_bits::load(
0471     const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
0472 {
0473 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0474   if (storage.StopBits == ONESTOPBIT)
0475   {
0476     value_ = one;
0477   }
0478   else if (storage.StopBits == ONE5STOPBITS)
0479   {
0480     value_ = onepointfive;
0481   }
0482   else if (storage.StopBits == TWOSTOPBITS)
0483   {
0484     value_ = two;
0485   }
0486   else
0487   {
0488     value_ = one;
0489   }
0490 #else
0491   value_ = (storage.c_cflag & CSTOPB) ? two : one;
0492 #endif
0493   ec = boost::system::error_code();
0494   BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0495 }
0496 
0497 serial_port_base::character_size::character_size(unsigned int t)
0498   : value_(t)
0499 {
0500   if (t < 5 || t > 8)
0501   {
0502     std::out_of_range ex("invalid character_size value");
0503     boost::asio::detail::throw_exception(ex);
0504   }
0505 }
0506 
0507 BOOST_ASIO_SYNC_OP_VOID serial_port_base::character_size::store(
0508     BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
0509 {
0510 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0511   storage.ByteSize = value_;
0512 #else
0513   storage.c_cflag &= ~CSIZE;
0514   switch (value_)
0515   {
0516   case 5: storage.c_cflag |= CS5; break;
0517   case 6: storage.c_cflag |= CS6; break;
0518   case 7: storage.c_cflag |= CS7; break;
0519   case 8: storage.c_cflag |= CS8; break;
0520   default: break;
0521   }
0522 #endif
0523   ec = boost::system::error_code();
0524   BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0525 }
0526 
0527 BOOST_ASIO_SYNC_OP_VOID serial_port_base::character_size::load(
0528     const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
0529 {
0530 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0531   value_ = storage.ByteSize;
0532 #else
0533   if ((storage.c_cflag & CSIZE) == CS5) { value_ = 5; }
0534   else if ((storage.c_cflag & CSIZE) == CS6) { value_ = 6; }
0535   else if ((storage.c_cflag & CSIZE) == CS7) { value_ = 7; }
0536   else if ((storage.c_cflag & CSIZE) == CS8) { value_ = 8; }
0537   else
0538   {
0539     // Hmmm, use 8 for now.
0540     value_ = 8;
0541   }
0542 #endif
0543   ec = boost::system::error_code();
0544   BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0545 }
0546 
0547 } // namespace asio
0548 } // namespace boost
0549 
0550 #include <boost/asio/detail/pop_options.hpp>
0551 
0552 #undef BOOST_ASIO_OPTION_STORAGE
0553 
0554 #endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
0555 
0556 #endif // BOOST_ASIO_IMPL_SERIAL_PORT_BASE_IPP