555 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
		
		
			
		
	
	
			555 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
|  | // | ||
|  | // impl/serial_port_base.ipp | ||
|  | // ~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|  | // | ||
|  | // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) | ||
|  | // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) | ||
|  | // | ||
|  | // 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 ASIO_IMPL_SERIAL_PORT_BASE_IPP | ||
|  | #define ASIO_IMPL_SERIAL_PORT_BASE_IPP | ||
|  | 
 | ||
|  | #if defined(_MSC_VER) && (_MSC_VER >= 1200) | ||
|  | # pragma once | ||
|  | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | ||
|  | 
 | ||
|  | #include "asio/detail/config.hpp" | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_SERIAL_PORT) | ||
|  | 
 | ||
|  | #include <stdexcept> | ||
|  | #include "asio/error.hpp" | ||
|  | #include "asio/serial_port_base.hpp" | ||
|  | #include "asio/detail/throw_exception.hpp" | ||
|  | 
 | ||
|  | #if defined(GENERATING_DOCUMENTATION) | ||
|  | # define ASIO_OPTION_STORAGE implementation_defined | ||
|  | #elif defined(ASIO_WINDOWS) || defined(__CYGWIN__) | ||
|  | # define ASIO_OPTION_STORAGE DCB | ||
|  | #else | ||
|  | # define ASIO_OPTION_STORAGE termios | ||
|  | #endif | ||
|  | 
 | ||
|  | #include "asio/detail/push_options.hpp" | ||
|  | 
 | ||
|  | namespace asio { | ||
|  | 
 | ||
|  | ASIO_SYNC_OP_VOID serial_port_base::baud_rate::store( | ||
|  |     ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const | ||
|  | { | ||
|  | #if defined(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 = asio::error::invalid_argument; | ||
|  |     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 = asio::error_code(); | ||
|  |   ASIO_SYNC_OP_VOID_RETURN(ec); | ||
|  | } | ||
|  | 
 | ||
|  | ASIO_SYNC_OP_VOID serial_port_base::baud_rate::load( | ||
|  |     const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) | ||
|  | { | ||
|  | #if defined(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 = asio::error::invalid_argument; | ||
|  |     ASIO_SYNC_OP_VOID_RETURN(ec); | ||
|  |   } | ||
|  | #endif | ||
|  |   ec = asio::error_code(); | ||
|  |   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"); | ||
|  |     asio::detail::throw_exception(ex); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | ASIO_SYNC_OP_VOID serial_port_base::flow_control::store( | ||
|  |     ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const | ||
|  | { | ||
|  | #if defined(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 = asio::error::operation_not_supported; | ||
|  |     ASIO_SYNC_OP_VOID_RETURN(ec); | ||
|  | # endif | ||
|  |   default: | ||
|  |     break; | ||
|  |   } | ||
|  | #endif | ||
|  |   ec = asio::error_code(); | ||
|  |   ASIO_SYNC_OP_VOID_RETURN(ec); | ||
|  | } | ||
|  | 
 | ||
|  | ASIO_SYNC_OP_VOID serial_port_base::flow_control::load( | ||
|  |     const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) | ||
|  | { | ||
|  | #if defined(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 = asio::error_code(); | ||
|  |   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"); | ||
|  |     asio::detail::throw_exception(ex); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | ASIO_SYNC_OP_VOID serial_port_base::parity::store( | ||
|  |     ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const | ||
|  | { | ||
|  | #if defined(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 = asio::error_code(); | ||
|  |   ASIO_SYNC_OP_VOID_RETURN(ec); | ||
|  | } | ||
|  | 
 | ||
|  | ASIO_SYNC_OP_VOID serial_port_base::parity::load( | ||
|  |     const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) | ||
|  | { | ||
|  | #if defined(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 = asio::error_code(); | ||
|  |   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"); | ||
|  |     asio::detail::throw_exception(ex); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | ASIO_SYNC_OP_VOID serial_port_base::stop_bits::store( | ||
|  |     ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const | ||
|  | { | ||
|  | #if defined(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 = asio::error::operation_not_supported; | ||
|  |     ASIO_SYNC_OP_VOID_RETURN(ec); | ||
|  |   } | ||
|  | #endif | ||
|  |   ec = asio::error_code(); | ||
|  |   ASIO_SYNC_OP_VOID_RETURN(ec); | ||
|  | } | ||
|  | 
 | ||
|  | ASIO_SYNC_OP_VOID serial_port_base::stop_bits::load( | ||
|  |     const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) | ||
|  | { | ||
|  | #if defined(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 = asio::error_code(); | ||
|  |   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"); | ||
|  |     asio::detail::throw_exception(ex); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | ASIO_SYNC_OP_VOID serial_port_base::character_size::store( | ||
|  |     ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const | ||
|  | { | ||
|  | #if defined(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 = asio::error_code(); | ||
|  |   ASIO_SYNC_OP_VOID_RETURN(ec); | ||
|  | } | ||
|  | 
 | ||
|  | ASIO_SYNC_OP_VOID serial_port_base::character_size::load( | ||
|  |     const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) | ||
|  | { | ||
|  | #if defined(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 = asio::error_code(); | ||
|  |   ASIO_SYNC_OP_VOID_RETURN(ec); | ||
|  | } | ||
|  | 
 | ||
|  | } // namespace asio | ||
|  | 
 | ||
|  | #include "asio/detail/pop_options.hpp" | ||
|  | 
 | ||
|  | #undef ASIO_OPTION_STORAGE | ||
|  | 
 | ||
|  | #endif // defined(ASIO_HAS_SERIAL_PORT) | ||
|  | 
 | ||
|  | #endif // ASIO_IMPL_SERIAL_PORT_BASE_IPP |