win_iocp_serial_port_service.hpp
Go to the documentation of this file.
00001 //
00002 // win_iocp_serial_port_service.hpp
00003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00004 //
00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
00006 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
00007 //
00008 // Distributed under the Boost Software License, Version 1.0. (See accompanying
00009 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
00010 //
00011 
00012 #ifndef ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
00013 #define ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
00014 
00015 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00016 # pragma once
00017 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00018 
00019 #include "asio/detail/push_options.hpp"
00020 
00021 #include "asio/detail/push_options.hpp"
00022 #include <cstring>
00023 #include <string>
00024 #include "asio/detail/pop_options.hpp"
00025 
00026 #include "asio/detail/win_iocp_io_service_fwd.hpp"
00027 
00028 #if defined(ASIO_HAS_IOCP)
00029 
00030 #include "asio/error.hpp"
00031 #include "asio/io_service.hpp"
00032 #include "asio/detail/win_iocp_handle_service.hpp"
00033 
00034 namespace asio {
00035 namespace detail {
00036 
00037 // Extend win_iocp_handle_service to provide serial port support.
00038 class win_iocp_serial_port_service
00039   : public asio::detail::service_base<win_iocp_serial_port_service>
00040 {
00041 public:
00042   // The native type of a stream handle.
00043   typedef win_iocp_handle_service::native_type native_type;
00044 
00045   // The implementation type of the stream handle.
00046   typedef win_iocp_handle_service::implementation_type implementation_type;
00047 
00048   win_iocp_serial_port_service(asio::io_service& io_service)
00049     : asio::detail::service_base<
00050         win_iocp_serial_port_service>(io_service),
00051       handle_service_(
00052           asio::use_service<win_iocp_handle_service>(io_service))
00053   {
00054   }
00055 
00056   // Destroy all user-defined handler objects owned by the service.
00057   void shutdown_service()
00058   {
00059   }
00060 
00061   // Construct a new handle implementation.
00062   void construct(implementation_type& impl)
00063   {
00064     handle_service_.construct(impl);
00065   }
00066 
00067   // Destroy a handle implementation.
00068   void destroy(implementation_type& impl)
00069   {
00070     handle_service_.destroy(impl);
00071   }
00072 
00073   // Open the serial port using the specified device name.
00074   asio::error_code open(implementation_type& impl,
00075       const std::string& device, asio::error_code& ec)
00076   {
00077     if (is_open(impl))
00078     {
00079       ec = asio::error::already_open;
00080       return ec;
00081     }
00082 
00083     // For convenience, add a leading \\.\ sequence if not already present.
00084     std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device;
00085 
00086     // Open a handle to the serial port.
00087     ::HANDLE handle = ::CreateFileA(name.c_str(),
00088         GENERIC_READ | GENERIC_WRITE, 0, 0,
00089         OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
00090     if (handle == INVALID_HANDLE_VALUE)
00091     {
00092       DWORD last_error = ::GetLastError();
00093       ec = asio::error_code(last_error,
00094           asio::error::get_system_category());
00095       return ec;
00096     }
00097 
00098     // Determine the initial serial port parameters.
00099     using namespace std; // For memcpy.
00100     ::DCB dcb;
00101     memset(&dcb, 0, sizeof(DCB));
00102     dcb.DCBlength = sizeof(DCB);
00103     if (!::GetCommState(handle, &dcb))
00104     {
00105       DWORD last_error = ::GetLastError();
00106       ::CloseHandle(handle);
00107       ec = asio::error_code(last_error,
00108           asio::error::get_system_category());
00109       return ec;
00110     }
00111 
00112     // Set some default serial port parameters. This implementation does not
00113     // support changing these, so they might as well be in a known state.
00114     dcb.fBinary = TRUE; // Win32 only supports binary mode.
00115     dcb.fDsrSensitivity = FALSE;
00116     dcb.fNull = FALSE; // Do not ignore NULL characters.
00117     dcb.fAbortOnError = FALSE; // Ignore serial framing errors.
00118     if (!::SetCommState(handle, &dcb))
00119     {
00120       DWORD last_error = ::GetLastError();
00121       ::CloseHandle(handle);
00122       ec = asio::error_code(last_error,
00123           asio::error::get_system_category());
00124       return ec;
00125     }
00126 
00127     // Set up timeouts so that the serial port will behave similarly to a
00128     // network socket. Reads wait for at least one byte, then return with
00129     // whatever they have. Writes return once everything is out the door.
00130     ::COMMTIMEOUTS timeouts;
00131     timeouts.ReadIntervalTimeout = 1;
00132     timeouts.ReadTotalTimeoutMultiplier = 0;
00133     timeouts.ReadTotalTimeoutConstant = 0;
00134     timeouts.WriteTotalTimeoutMultiplier = 0;
00135     timeouts.WriteTotalTimeoutConstant = 0;
00136     if (!::SetCommTimeouts(handle, &timeouts))
00137     {
00138       DWORD last_error = ::GetLastError();
00139       ::CloseHandle(handle);
00140       ec = asio::error_code(last_error,
00141           asio::error::get_system_category());
00142       return ec;
00143     }
00144 
00145     // We're done. Take ownership of the serial port handle.
00146     if (handle_service_.assign(impl, handle, ec))
00147       ::CloseHandle(handle);
00148     return ec;
00149   }
00150 
00151   // Assign a native handle to a handle implementation.
00152   asio::error_code assign(implementation_type& impl,
00153       const native_type& native_handle, asio::error_code& ec)
00154   {
00155     return handle_service_.assign(impl, native_handle, ec);
00156   }
00157 
00158   // Determine whether the handle is open.
00159   bool is_open(const implementation_type& impl) const
00160   {
00161     return handle_service_.is_open(impl);
00162   }
00163 
00164   // Destroy a handle implementation.
00165   asio::error_code close(implementation_type& impl,
00166       asio::error_code& ec)
00167   {
00168     return handle_service_.close(impl, ec);
00169   }
00170 
00171   // Get the native handle representation.
00172   native_type native(implementation_type& impl)
00173   {
00174     return handle_service_.native(impl);
00175   }
00176 
00177   // Cancel all operations associated with the handle.
00178   asio::error_code cancel(implementation_type& impl,
00179       asio::error_code& ec)
00180   {
00181     return handle_service_.cancel(impl, ec);
00182   }
00183 
00184   // Set an option on the serial port.
00185   template <typename SettableSerialPortOption>
00186   asio::error_code set_option(implementation_type& impl,
00187       const SettableSerialPortOption& option, asio::error_code& ec)
00188   {
00189     using namespace std; // For memcpy.
00190 
00191     ::DCB dcb;
00192     memset(&dcb, 0, sizeof(DCB));
00193     dcb.DCBlength = sizeof(DCB);
00194     if (!::GetCommState(handle_service_.native(impl), &dcb))
00195     {
00196       DWORD last_error = ::GetLastError();
00197       ec = asio::error_code(last_error,
00198           asio::error::get_system_category());
00199       return ec;
00200     }
00201 
00202     if (option.store(dcb, ec))
00203       return ec;
00204 
00205     if (!::SetCommState(handle_service_.native(impl), &dcb))
00206     {
00207       DWORD last_error = ::GetLastError();
00208       ec = asio::error_code(last_error,
00209           asio::error::get_system_category());
00210       return ec;
00211     }
00212 
00213     ec = asio::error_code();
00214     return ec;
00215   }
00216 
00217   // Get an option from the serial port.
00218   template <typename GettableSerialPortOption>
00219   asio::error_code get_option(const implementation_type& impl,
00220       GettableSerialPortOption& option, asio::error_code& ec) const
00221   {
00222     using namespace std; // For memcpy.
00223 
00224     ::DCB dcb;
00225     memset(&dcb, 0, sizeof(DCB));
00226     dcb.DCBlength = sizeof(DCB);
00227     if (!::GetCommState(handle_service_.native(impl), &dcb))
00228     {
00229       DWORD last_error = ::GetLastError();
00230       ec = asio::error_code(last_error,
00231           asio::error::get_system_category());
00232       return ec;
00233     }
00234 
00235     return option.load(dcb, ec);
00236   }
00237 
00238   // Send a break sequence to the serial port.
00239   asio::error_code send_break(implementation_type& impl,
00240       asio::error_code& ec)
00241   {
00242     ec = asio::error::operation_not_supported;
00243     return ec;
00244   }
00245 
00246   // Write the given data. Returns the number of bytes sent.
00247   template <typename ConstBufferSequence>
00248   size_t write_some(implementation_type& impl,
00249       const ConstBufferSequence& buffers, asio::error_code& ec)
00250   {
00251     return handle_service_.write_some(impl, buffers, ec);
00252   }
00253 
00254   // Start an asynchronous write. The data being written must be valid for the
00255   // lifetime of the asynchronous operation.
00256   template <typename ConstBufferSequence, typename Handler>
00257   void async_write_some(implementation_type& impl,
00258       const ConstBufferSequence& buffers, Handler handler)
00259   {
00260     handle_service_.async_write_some(impl, buffers, handler);
00261   }
00262 
00263   // Read some data. Returns the number of bytes received.
00264   template <typename MutableBufferSequence>
00265   size_t read_some(implementation_type& impl,
00266       const MutableBufferSequence& buffers, asio::error_code& ec)
00267   {
00268     return handle_service_.read_some(impl, buffers, ec);
00269   }
00270 
00271   // Start an asynchronous read. The buffer for the data being received must be
00272   // valid for the lifetime of the asynchronous operation.
00273   template <typename MutableBufferSequence, typename Handler>
00274   void async_read_some(implementation_type& impl,
00275       const MutableBufferSequence& buffers, Handler handler)
00276   {
00277     handle_service_.async_read_some(impl, buffers, handler);
00278   }
00279 
00280 private:
00281   // The handle service used for initiating asynchronous operations.
00282   win_iocp_handle_service& handle_service_;
00283 };
00284 
00285 } // namespace detail
00286 } // namespace asio
00287 
00288 #endif // defined(ASIO_HAS_IOCP)
00289 
00290 #include "asio/detail/pop_options.hpp"
00291 
00292 #endif // ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39