reactive_serial_port_service.hpp
Go to the documentation of this file.
00001 //
00002 // reactive_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_REACTIVE_SERIAL_PORT_SERVICE_HPP
00013 #define ASIO_DETAIL_REACTIVE_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 #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
00027 
00028 #include "asio/detail/push_options.hpp"
00029 #include <termios.h>
00030 #include "asio/detail/pop_options.hpp"
00031 
00032 #include "asio/error.hpp"
00033 #include "asio/io_service.hpp"
00034 #include "asio/detail/descriptor_ops.hpp"
00035 #include "asio/detail/reactive_descriptor_service.hpp"
00036 
00037 namespace asio {
00038 namespace detail {
00039 
00040 // Extend reactive_descriptor_service to provide serial port support.
00041 template <typename Reactor>
00042 class reactive_serial_port_service
00043   : public asio::detail::service_base<
00044       reactive_serial_port_service<Reactor> >
00045 {
00046 public:
00047   // The native type of a stream handle.
00048   typedef typename reactive_descriptor_service<Reactor>::native_type
00049     native_type;
00050 
00051   // The implementation type of the stream handle.
00052   typedef typename reactive_descriptor_service<Reactor>::implementation_type
00053     implementation_type;
00054 
00055   reactive_serial_port_service(asio::io_service& io_service)
00056     : asio::detail::service_base<
00057         reactive_serial_port_service>(io_service),
00058       descriptor_service_(asio::use_service<
00059           reactive_descriptor_service<Reactor> >(io_service))
00060   {
00061   }
00062 
00063   // Destroy all user-defined handler objects owned by the service.
00064   void shutdown_service()
00065   {
00066   }
00067 
00068   // Construct a new handle implementation.
00069   void construct(implementation_type& impl)
00070   {
00071     descriptor_service_.construct(impl);
00072   }
00073 
00074   // Destroy a handle implementation.
00075   void destroy(implementation_type& impl)
00076   {
00077     descriptor_service_.destroy(impl);
00078   }
00079 
00080   // Open the serial port using the specified device name.
00081   asio::error_code open(implementation_type& impl,
00082       const std::string& device, asio::error_code& ec)
00083   {
00084     if (is_open(impl))
00085     {
00086       ec = asio::error::already_open;
00087       return ec;
00088     }
00089 
00090     int fd = descriptor_ops::open(device.c_str(),
00091         O_RDWR | O_NONBLOCK | O_NOCTTY, ec);
00092     if (fd < 0)
00093       return ec;
00094 
00095     int s = descriptor_ops::fcntl(fd, F_GETFL, ec);
00096     if (s >= 0)
00097       s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec);
00098     if (s < 0)
00099     {
00100       asio::error_code ignored_ec;
00101       descriptor_ops::close(fd, ignored_ec);
00102       return ec;
00103     }
00104   
00105     // Set up default serial port options.
00106     termios ios;
00107     descriptor_ops::clear_error(ec);
00108     s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec);
00109     if (s >= 0)
00110     {
00111 #if defined(_BSD_SOURCE)
00112       ::cfmakeraw(&ios);
00113 #else
00114       ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK
00115           | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
00116       ios.c_oflag &= ~OPOST;
00117       ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
00118       ios.c_cflag &= ~(CSIZE | PARENB);
00119       ios.c_cflag |= CS8;
00120 #endif
00121       ios.c_iflag |= IGNPAR;
00122       ios.c_cflag |= CREAD | CLOCAL;
00123       descriptor_ops::clear_error(ec);
00124       s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec);
00125     }
00126     if (s < 0)
00127     {
00128       asio::error_code ignored_ec;
00129       descriptor_ops::close(fd, ignored_ec);
00130       return ec;
00131     }
00132   
00133     // We're done. Take ownership of the serial port descriptor.
00134     if (descriptor_service_.assign(impl, fd, ec))
00135     {
00136       asio::error_code ignored_ec;
00137       descriptor_ops::close(fd, ignored_ec);
00138     }
00139 
00140     return ec;
00141   }
00142 
00143   // Assign a native handle to a handle implementation.
00144   asio::error_code assign(implementation_type& impl,
00145       const native_type& native_descriptor, asio::error_code& ec)
00146   {
00147     return descriptor_service_.assign(impl, native_descriptor, ec);
00148   }
00149 
00150   // Determine whether the handle is open.
00151   bool is_open(const implementation_type& impl) const
00152   {
00153     return descriptor_service_.is_open(impl);
00154   }
00155 
00156   // Destroy a handle implementation.
00157   asio::error_code close(implementation_type& impl,
00158       asio::error_code& ec)
00159   {
00160     return descriptor_service_.close(impl, ec);
00161   }
00162 
00163   // Get the native handle representation.
00164   native_type native(implementation_type& impl)
00165   {
00166     return descriptor_service_.native(impl);
00167   }
00168 
00169   // Cancel all operations associated with the handle.
00170   asio::error_code cancel(implementation_type& impl,
00171       asio::error_code& ec)
00172   {
00173     return descriptor_service_.cancel(impl, ec);
00174   }
00175 
00176   // Set an option on the serial port.
00177   template <typename SettableSerialPortOption>
00178   asio::error_code set_option(implementation_type& impl,
00179       const SettableSerialPortOption& option, asio::error_code& ec)
00180   {
00181     termios ios;
00182     descriptor_ops::clear_error(ec);
00183     descriptor_ops::error_wrapper(::tcgetattr(
00184           descriptor_service_.native(impl), &ios), ec);
00185     if (ec)
00186       return ec;
00187 
00188     if (option.store(ios, ec))
00189       return ec;
00190 
00191     descriptor_ops::clear_error(ec);
00192     descriptor_ops::error_wrapper(::tcsetattr(
00193           descriptor_service_.native(impl), TCSANOW, &ios), ec);
00194     return ec;
00195   }
00196 
00197   // Get an option from the serial port.
00198   template <typename GettableSerialPortOption>
00199   asio::error_code get_option(const implementation_type& impl,
00200       GettableSerialPortOption& option, asio::error_code& ec) const
00201   {
00202     termios ios;
00203     descriptor_ops::clear_error(ec);
00204     descriptor_ops::error_wrapper(::tcgetattr(
00205           descriptor_service_.native(impl), &ios), ec);
00206     if (ec)
00207       return ec;
00208 
00209     return option.load(ios, ec);
00210   }
00211 
00212   // Send a break sequence to the serial port.
00213   asio::error_code send_break(implementation_type& impl,
00214       asio::error_code& ec)
00215   {
00216     descriptor_ops::clear_error(ec);
00217     descriptor_ops::error_wrapper(::tcsendbreak(
00218           descriptor_service_.native(impl), 0), ec);
00219     return ec;
00220   }
00221 
00222   // Write the given data. Returns the number of bytes sent.
00223   template <typename ConstBufferSequence>
00224   size_t write_some(implementation_type& impl,
00225       const ConstBufferSequence& buffers, asio::error_code& ec)
00226   {
00227     return descriptor_service_.write_some(impl, buffers, ec);
00228   }
00229 
00230   // Start an asynchronous write. The data being written must be valid for the
00231   // lifetime of the asynchronous operation.
00232   template <typename ConstBufferSequence, typename Handler>
00233   void async_write_some(implementation_type& impl,
00234       const ConstBufferSequence& buffers, Handler handler)
00235   {
00236     descriptor_service_.async_write_some(impl, buffers, handler);
00237   }
00238 
00239   // Read some data. Returns the number of bytes received.
00240   template <typename MutableBufferSequence>
00241   size_t read_some(implementation_type& impl,
00242       const MutableBufferSequence& buffers, asio::error_code& ec)
00243   {
00244     return descriptor_service_.read_some(impl, buffers, ec);
00245   }
00246 
00247   // Start an asynchronous read. The buffer for the data being received must be
00248   // valid for the lifetime of the asynchronous operation.
00249   template <typename MutableBufferSequence, typename Handler>
00250   void async_read_some(implementation_type& impl,
00251       const MutableBufferSequence& buffers, Handler handler)
00252   {
00253     descriptor_service_.async_read_some(impl, buffers, handler);
00254   }
00255 
00256 private:
00257   // The handle service used for initiating asynchronous operations.
00258   reactive_descriptor_service<Reactor>& descriptor_service_;
00259 };
00260 
00261 } // namespace detail
00262 } // namespace asio
00263 
00264 #endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
00265 
00266 #include "asio/detail/pop_options.hpp"
00267 
00268 #endif // ASIO_DETAIL_REACTIVE_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