00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
00048 typedef typename reactive_descriptor_service<Reactor>::native_type
00049 native_type;
00050
00051
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
00064 void shutdown_service()
00065 {
00066 }
00067
00068
00069 void construct(implementation_type& impl)
00070 {
00071 descriptor_service_.construct(impl);
00072 }
00073
00074
00075 void destroy(implementation_type& impl)
00076 {
00077 descriptor_service_.destroy(impl);
00078 }
00079
00080
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
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
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
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
00151 bool is_open(const implementation_type& impl) const
00152 {
00153 return descriptor_service_.is_open(impl);
00154 }
00155
00156
00157 asio::error_code close(implementation_type& impl,
00158 asio::error_code& ec)
00159 {
00160 return descriptor_service_.close(impl, ec);
00161 }
00162
00163
00164 native_type native(implementation_type& impl)
00165 {
00166 return descriptor_service_.native(impl);
00167 }
00168
00169
00170 asio::error_code cancel(implementation_type& impl,
00171 asio::error_code& ec)
00172 {
00173 return descriptor_service_.cancel(impl, ec);
00174 }
00175
00176
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
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
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
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
00231
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
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
00248
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
00258 reactive_descriptor_service<Reactor>& descriptor_service_;
00259 };
00260
00261 }
00262 }
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