fix doc example typo
[boost.git] / boost / asio / detail / win_iocp_serial_port_service.hpp
blob57d56cf63358f4d8312db6a60b2a678fb1fcd524
1 //
2 // win_iocp_serial_port_service.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
7 //
8 // Distributed under the Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12 #ifndef BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
13 #define BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 # pragma once
17 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
19 #include <boost/asio/detail/push_options.hpp>
21 #include <boost/asio/detail/push_options.hpp>
22 #include <cstring>
23 #include <string>
24 #include <boost/asio/detail/pop_options.hpp>
26 #include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
28 #if defined(BOOST_ASIO_HAS_IOCP)
30 #include <boost/asio/error.hpp>
31 #include <boost/asio/io_service.hpp>
32 #include <boost/asio/detail/win_iocp_handle_service.hpp>
34 namespace boost {
35 namespace asio {
36 namespace detail {
38 // Extend win_iocp_handle_service to provide serial port support.
39 class win_iocp_serial_port_service
40 : public boost::asio::detail::service_base<win_iocp_serial_port_service>
42 public:
43 // The native type of a stream handle.
44 typedef win_iocp_handle_service::native_type native_type;
46 // The implementation type of the stream handle.
47 typedef win_iocp_handle_service::implementation_type implementation_type;
49 win_iocp_serial_port_service(boost::asio::io_service& io_service)
50 : boost::asio::detail::service_base<
51 win_iocp_serial_port_service>(io_service),
52 handle_service_(
53 boost::asio::use_service<win_iocp_handle_service>(io_service))
57 // Destroy all user-defined handler objects owned by the service.
58 void shutdown_service()
62 // Construct a new handle implementation.
63 void construct(implementation_type& impl)
65 handle_service_.construct(impl);
68 // Destroy a handle implementation.
69 void destroy(implementation_type& impl)
71 handle_service_.destroy(impl);
74 // Open the serial port using the specified device name.
75 boost::system::error_code open(implementation_type& impl,
76 const std::string& device, boost::system::error_code& ec)
78 if (is_open(impl))
80 ec = boost::asio::error::already_open;
81 return ec;
84 // For convenience, add a leading \\.\ sequence if not already present.
85 std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device;
87 // Open a handle to the serial port.
88 ::HANDLE handle = ::CreateFileA(name.c_str(),
89 GENERIC_READ | GENERIC_WRITE, 0, 0,
90 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
91 if (handle == INVALID_HANDLE_VALUE)
93 DWORD last_error = ::GetLastError();
94 ec = boost::system::error_code(last_error,
95 boost::asio::error::get_system_category());
96 return ec;
99 // Determine the initial serial port parameters.
100 using namespace std; // For memcpy.
101 ::DCB dcb;
102 memset(&dcb, 0, sizeof(DCB));
103 dcb.DCBlength = sizeof(DCB);
104 if (!::GetCommState(handle, &dcb))
106 DWORD last_error = ::GetLastError();
107 ::CloseHandle(handle);
108 ec = boost::system::error_code(last_error,
109 boost::asio::error::get_system_category());
110 return ec;
113 // Set some default serial port parameters. This implementation does not
114 // support changing these, so they might as well be in a known state.
115 dcb.fBinary = TRUE; // Win32 only supports binary mode.
116 dcb.fDsrSensitivity = FALSE;
117 dcb.fNull = FALSE; // Do not ignore NULL characters.
118 dcb.fAbortOnError = FALSE; // Ignore serial framing errors.
119 if (!::SetCommState(handle, &dcb))
121 DWORD last_error = ::GetLastError();
122 ::CloseHandle(handle);
123 ec = boost::system::error_code(last_error,
124 boost::asio::error::get_system_category());
125 return ec;
128 // Set up timeouts so that the serial port will behave similarly to a
129 // network socket. Reads wait for at least one byte, then return with
130 // whatever they have. Writes return once everything is out the door.
131 ::COMMTIMEOUTS timeouts;
132 timeouts.ReadIntervalTimeout = 1;
133 timeouts.ReadTotalTimeoutMultiplier = 0;
134 timeouts.ReadTotalTimeoutConstant = 0;
135 timeouts.WriteTotalTimeoutMultiplier = 0;
136 timeouts.WriteTotalTimeoutConstant = 0;
137 if (!::SetCommTimeouts(handle, &timeouts))
139 DWORD last_error = ::GetLastError();
140 ::CloseHandle(handle);
141 ec = boost::system::error_code(last_error,
142 boost::asio::error::get_system_category());
143 return ec;
146 // We're done. Take ownership of the serial port handle.
147 if (handle_service_.assign(impl, handle, ec))
148 ::CloseHandle(handle);
149 return ec;
152 // Assign a native handle to a handle implementation.
153 boost::system::error_code assign(implementation_type& impl,
154 const native_type& native_handle, boost::system::error_code& ec)
156 return handle_service_.assign(impl, native_handle, ec);
159 // Determine whether the handle is open.
160 bool is_open(const implementation_type& impl) const
162 return handle_service_.is_open(impl);
165 // Destroy a handle implementation.
166 boost::system::error_code close(implementation_type& impl,
167 boost::system::error_code& ec)
169 return handle_service_.close(impl, ec);
172 // Get the native handle representation.
173 native_type native(implementation_type& impl)
175 return handle_service_.native(impl);
178 // Cancel all operations associated with the handle.
179 boost::system::error_code cancel(implementation_type& impl,
180 boost::system::error_code& ec)
182 return handle_service_.cancel(impl, ec);
185 // Set an option on the serial port.
186 template <typename SettableSerialPortOption>
187 boost::system::error_code set_option(implementation_type& impl,
188 const SettableSerialPortOption& option, boost::system::error_code& ec)
190 using namespace std; // For memcpy.
192 ::DCB dcb;
193 memset(&dcb, 0, sizeof(DCB));
194 dcb.DCBlength = sizeof(DCB);
195 if (!::GetCommState(handle_service_.native(impl), &dcb))
197 DWORD last_error = ::GetLastError();
198 ec = boost::system::error_code(last_error,
199 boost::asio::error::get_system_category());
200 return ec;
203 if (option.store(dcb, ec))
204 return ec;
206 if (!::SetCommState(handle_service_.native(impl), &dcb))
208 DWORD last_error = ::GetLastError();
209 ec = boost::system::error_code(last_error,
210 boost::asio::error::get_system_category());
211 return ec;
214 ec = boost::system::error_code();
215 return ec;
218 // Get an option from the serial port.
219 template <typename GettableSerialPortOption>
220 boost::system::error_code get_option(const implementation_type& impl,
221 GettableSerialPortOption& option, boost::system::error_code& ec) const
223 using namespace std; // For memcpy.
225 ::DCB dcb;
226 memset(&dcb, 0, sizeof(DCB));
227 dcb.DCBlength = sizeof(DCB);
228 if (!::GetCommState(handle_service_.native(impl), &dcb))
230 DWORD last_error = ::GetLastError();
231 ec = boost::system::error_code(last_error,
232 boost::asio::error::get_system_category());
233 return ec;
236 return option.load(dcb, ec);
239 // Send a break sequence to the serial port.
240 boost::system::error_code send_break(implementation_type&,
241 boost::system::error_code& ec)
243 ec = boost::asio::error::operation_not_supported;
244 return ec;
247 // Write the given data. Returns the number of bytes sent.
248 template <typename ConstBufferSequence>
249 size_t write_some(implementation_type& impl,
250 const ConstBufferSequence& buffers, boost::system::error_code& ec)
252 return handle_service_.write_some(impl, buffers, ec);
255 // Start an asynchronous write. The data being written must be valid for the
256 // lifetime of the asynchronous operation.
257 template <typename ConstBufferSequence, typename Handler>
258 void async_write_some(implementation_type& impl,
259 const ConstBufferSequence& buffers, Handler handler)
261 handle_service_.async_write_some(impl, buffers, handler);
264 // Read some data. Returns the number of bytes received.
265 template <typename MutableBufferSequence>
266 size_t read_some(implementation_type& impl,
267 const MutableBufferSequence& buffers, boost::system::error_code& ec)
269 return handle_service_.read_some(impl, buffers, ec);
272 // Start an asynchronous read. The buffer for the data being received must be
273 // valid for the lifetime of the asynchronous operation.
274 template <typename MutableBufferSequence, typename Handler>
275 void async_read_some(implementation_type& impl,
276 const MutableBufferSequence& buffers, Handler handler)
278 handle_service_.async_read_some(impl, buffers, handler);
281 private:
282 // The handle service used for initiating asynchronous operations.
283 win_iocp_handle_service& handle_service_;
286 } // namespace detail
287 } // namespace asio
288 } // namespace boost
290 #endif // defined(BOOST_ASIO_HAS_IOCP)
292 #include <boost/asio/detail/pop_options.hpp>
294 #endif // BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP