Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //
0002 // detail/impl/win_iocp_serial_port_service.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_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP
0013 #define BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_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_IOCP) && defined(BOOST_ASIO_HAS_SERIAL_PORT)
0022 
0023 #include <cstring>
0024 #include <boost/asio/detail/win_iocp_serial_port_service.hpp>
0025 
0026 #include <boost/asio/detail/push_options.hpp>
0027 
0028 namespace boost {
0029 namespace asio {
0030 namespace detail {
0031 
0032 win_iocp_serial_port_service::win_iocp_serial_port_service(
0033     execution_context& context)
0034   : execution_context_service_base<win_iocp_serial_port_service>(context),
0035     handle_service_(context)
0036 {
0037 }
0038 
0039 void win_iocp_serial_port_service::shutdown()
0040 {
0041 }
0042 
0043 boost::system::error_code win_iocp_serial_port_service::open(
0044     win_iocp_serial_port_service::implementation_type& impl,
0045     const std::string& device, boost::system::error_code& ec)
0046 {
0047   if (is_open(impl))
0048   {
0049     ec = boost::asio::error::already_open;
0050     BOOST_ASIO_ERROR_LOCATION(ec);
0051     return ec;
0052   }
0053 
0054   // For convenience, add a leading \\.\ sequence if not already present.
0055   std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device;
0056 
0057   // Open a handle to the serial port.
0058   ::HANDLE handle = ::CreateFileA(name.c_str(),
0059       GENERIC_READ | GENERIC_WRITE, 0, 0,
0060       OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
0061   if (handle == INVALID_HANDLE_VALUE)
0062   {
0063     DWORD last_error = ::GetLastError();
0064     ec = boost::system::error_code(last_error,
0065         boost::asio::error::get_system_category());
0066     BOOST_ASIO_ERROR_LOCATION(ec);
0067     return ec;
0068   }
0069 
0070   // Determine the initial serial port parameters.
0071   using namespace std; // For memset.
0072   ::DCB dcb;
0073   memset(&dcb, 0, sizeof(DCB));
0074   dcb.DCBlength = sizeof(DCB);
0075   if (!::GetCommState(handle, &dcb))
0076   {
0077     DWORD last_error = ::GetLastError();
0078     ::CloseHandle(handle);
0079     ec = boost::system::error_code(last_error,
0080         boost::asio::error::get_system_category());
0081     BOOST_ASIO_ERROR_LOCATION(ec);
0082     return ec;
0083   }
0084 
0085   // Set some default serial port parameters. This implementation does not
0086   // support changing all of these, so they might as well be in a known state.
0087   dcb.fBinary = TRUE; // Win32 only supports binary mode.
0088   dcb.fNull = FALSE; // Do not ignore NULL characters.
0089   dcb.fAbortOnError = FALSE; // Ignore serial framing errors.
0090   dcb.BaudRate = CBR_9600; // 9600 baud by default
0091   dcb.ByteSize = 8; // 8 bit bytes
0092   dcb.fOutxCtsFlow = FALSE; // No flow control
0093   dcb.fOutxDsrFlow = FALSE;
0094   dcb.fDtrControl = DTR_CONTROL_DISABLE;
0095   dcb.fDsrSensitivity = FALSE;
0096   dcb.fOutX = FALSE;
0097   dcb.fInX = FALSE;
0098   dcb.fRtsControl = RTS_CONTROL_DISABLE;
0099   dcb.fParity = FALSE; // No parity
0100   dcb.Parity = NOPARITY;
0101   dcb.StopBits = ONESTOPBIT; // One stop bit
0102   if (!::SetCommState(handle, &dcb))
0103   {
0104     DWORD last_error = ::GetLastError();
0105     ::CloseHandle(handle);
0106     ec = boost::system::error_code(last_error,
0107         boost::asio::error::get_system_category());
0108     BOOST_ASIO_ERROR_LOCATION(ec);
0109     return ec;
0110   }
0111 
0112   // Set up timeouts so that the serial port will behave similarly to a
0113   // network socket. Reads wait for at least one byte, then return with
0114   // whatever they have. Writes return once everything is out the door.
0115   ::COMMTIMEOUTS timeouts;
0116   timeouts.ReadIntervalTimeout = 1;
0117   timeouts.ReadTotalTimeoutMultiplier = 0;
0118   timeouts.ReadTotalTimeoutConstant = 0;
0119   timeouts.WriteTotalTimeoutMultiplier = 0;
0120   timeouts.WriteTotalTimeoutConstant = 0;
0121   if (!::SetCommTimeouts(handle, &timeouts))
0122   {
0123     DWORD last_error = ::GetLastError();
0124     ::CloseHandle(handle);
0125     ec = boost::system::error_code(last_error,
0126         boost::asio::error::get_system_category());
0127     BOOST_ASIO_ERROR_LOCATION(ec);
0128     return ec;
0129   }
0130 
0131   // We're done. Take ownership of the serial port handle.
0132   if (handle_service_.assign(impl, handle, ec))
0133     ::CloseHandle(handle);
0134   return ec;
0135 }
0136 
0137 boost::system::error_code win_iocp_serial_port_service::do_set_option(
0138     win_iocp_serial_port_service::implementation_type& impl,
0139     win_iocp_serial_port_service::store_function_type store,
0140     const void* option, boost::system::error_code& ec)
0141 {
0142   using namespace std; // For memcpy.
0143 
0144   ::DCB dcb;
0145   memset(&dcb, 0, sizeof(DCB));
0146   dcb.DCBlength = sizeof(DCB);
0147   if (!::GetCommState(handle_service_.native_handle(impl), &dcb))
0148   {
0149     DWORD last_error = ::GetLastError();
0150     ec = boost::system::error_code(last_error,
0151         boost::asio::error::get_system_category());
0152     BOOST_ASIO_ERROR_LOCATION(ec);
0153     return ec;
0154   }
0155 
0156   if (store(option, dcb, ec))
0157     return ec;
0158 
0159   if (!::SetCommState(handle_service_.native_handle(impl), &dcb))
0160   {
0161     DWORD last_error = ::GetLastError();
0162     ec = boost::system::error_code(last_error,
0163         boost::asio::error::get_system_category());
0164     BOOST_ASIO_ERROR_LOCATION(ec);
0165     return ec;
0166   }
0167 
0168   ec = boost::system::error_code();
0169   return ec;
0170 }
0171 
0172 boost::system::error_code win_iocp_serial_port_service::do_get_option(
0173     const win_iocp_serial_port_service::implementation_type& impl,
0174     win_iocp_serial_port_service::load_function_type load,
0175     void* option, boost::system::error_code& ec) const
0176 {
0177   using namespace std; // For memset.
0178 
0179   ::DCB dcb;
0180   memset(&dcb, 0, sizeof(DCB));
0181   dcb.DCBlength = sizeof(DCB);
0182   if (!::GetCommState(handle_service_.native_handle(impl), &dcb))
0183   {
0184     DWORD last_error = ::GetLastError();
0185     ec = boost::system::error_code(last_error,
0186         boost::asio::error::get_system_category());
0187     BOOST_ASIO_ERROR_LOCATION(ec);
0188     return ec;
0189   }
0190 
0191   return load(option, dcb, ec);
0192 }
0193 
0194 } // namespace detail
0195 } // namespace asio
0196 } // namespace boost
0197 
0198 #include <boost/asio/detail/pop_options.hpp>
0199 
0200 #endif // defined(BOOST_ASIO_HAS_IOCP) && defined(BOOST_ASIO_HAS_SERIAL_PORT)
0201 
0202 #endif // BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP