mirror of
https://github.com/boostorg/asio.git
synced 2026-02-25 14:32:08 +00:00
Add support for serial ports.
[SVN r46272]
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include <boost/asio/basic_deadline_timer.hpp>
|
||||
#include <boost/asio/basic_io_object.hpp>
|
||||
#include <boost/asio/basic_raw_socket.hpp>
|
||||
#include <boost/asio/basic_serial_port.hpp>
|
||||
#include <boost/asio/basic_socket_acceptor.hpp>
|
||||
#include <boost/asio/basic_socket_iostream.hpp>
|
||||
#include <boost/asio/basic_socket_streambuf.hpp>
|
||||
@@ -73,6 +74,9 @@
|
||||
#include <boost/asio/raw_socket_service.hpp>
|
||||
#include <boost/asio/read.hpp>
|
||||
#include <boost/asio/read_until.hpp>
|
||||
#include <boost/asio/serial_port.hpp>
|
||||
#include <boost/asio/serial_port_base.hpp>
|
||||
#include <boost/asio/serial_port_service.hpp>
|
||||
#include <boost/asio/socket_acceptor_service.hpp>
|
||||
#include <boost/asio/socket_base.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
|
||||
610
include/boost/asio/basic_serial_port.hpp
Normal file
610
include/boost/asio/basic_serial_port.hpp
Normal file
@@ -0,0 +1,610 @@
|
||||
//
|
||||
// basic_serial_port.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_BASIC_SERIAL_PORT_HPP
|
||||
#define BOOST_ASIO_BASIC_SERIAL_PORT_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
#include <string>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#include <boost/asio/basic_io_object.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/serial_port_base.hpp>
|
||||
#include <boost/asio/serial_port_service.hpp>
|
||||
#include <boost/asio/detail/throw_error.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \
|
||||
|| defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
/// Provides serial port functionality.
|
||||
/**
|
||||
* The basic_serial_port class template provides functionality that is common
|
||||
* to all serial ports.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*/
|
||||
template <typename SerialPortService = serial_port_service>
|
||||
class basic_serial_port
|
||||
: public basic_io_object<SerialPortService>,
|
||||
public serial_port_base
|
||||
{
|
||||
public:
|
||||
/// The native representation of a serial port.
|
||||
typedef typename SerialPortService::native_type native_type;
|
||||
|
||||
/// A basic_serial_port is always the lowest layer.
|
||||
typedef basic_serial_port<SerialPortService> lowest_layer_type;
|
||||
|
||||
/// Construct a basic_serial_port without opening it.
|
||||
/**
|
||||
* This constructor creates a serial port without opening it.
|
||||
*
|
||||
* @param io_service The io_service object that the serial port will use to
|
||||
* dispatch handlers for any asynchronous operations performed on the port.
|
||||
*/
|
||||
explicit basic_serial_port(boost::asio::io_service& io_service)
|
||||
: basic_io_object<SerialPortService>(io_service)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct and open a basic_serial_port.
|
||||
/**
|
||||
* This constructor creates and opens a serial port for the specified device
|
||||
* name.
|
||||
*
|
||||
* @param io_service The io_service object that the serial port will use to
|
||||
* dispatch handlers for any asynchronous operations performed on the port.
|
||||
*
|
||||
* @param device The platform-specific device name for this serial
|
||||
* port.
|
||||
*/
|
||||
explicit basic_serial_port(boost::asio::io_service& io_service,
|
||||
const char* device)
|
||||
: basic_io_object<SerialPortService>(io_service)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
this->service.open(this->implementation, device, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
}
|
||||
|
||||
/// Construct and open a basic_serial_port.
|
||||
/**
|
||||
* This constructor creates and opens a serial port for the specified device
|
||||
* name.
|
||||
*
|
||||
* @param io_service The io_service object that the serial port will use to
|
||||
* dispatch handlers for any asynchronous operations performed on the port.
|
||||
*
|
||||
* @param device The platform-specific device name for this serial
|
||||
* port.
|
||||
*/
|
||||
explicit basic_serial_port(boost::asio::io_service& io_service,
|
||||
const std::string& device)
|
||||
: basic_io_object<SerialPortService>(io_service)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
this->service.open(this->implementation, device, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
}
|
||||
|
||||
/// Construct a basic_serial_port on an existing native serial port.
|
||||
/**
|
||||
* This constructor creates a serial port object to hold an existing native
|
||||
* serial port.
|
||||
*
|
||||
* @param io_service The io_service object that the serial port will use to
|
||||
* dispatch handlers for any asynchronous operations performed on the port.
|
||||
*
|
||||
* @param native_serial_port A native serial port.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
basic_serial_port(boost::asio::io_service& io_service,
|
||||
const native_type& native_serial_port)
|
||||
: basic_io_object<SerialPortService>(io_service)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
this->service.assign(this->implementation, native_serial_port, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
}
|
||||
|
||||
/// Get a reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a reference to the lowest layer in a stack of
|
||||
* layers. Since a basic_serial_port cannot contain any further layers, it
|
||||
* simply returns a reference to itself.
|
||||
*
|
||||
* @return A reference to the lowest layer in the stack of layers. Ownership
|
||||
* is not transferred to the caller.
|
||||
*/
|
||||
lowest_layer_type& lowest_layer()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Open the serial port using the specified device name.
|
||||
/**
|
||||
* This function opens the serial port for the specified device name.
|
||||
*
|
||||
* @param device The platform-specific device name.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
void open(const std::string& device)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
this->service.open(this->implementation, device, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
}
|
||||
|
||||
/// Open the serial port using the specified device name.
|
||||
/**
|
||||
* This function opens the serial port using the given platform-specific
|
||||
* device name.
|
||||
*
|
||||
* @param device The platform-specific device name.
|
||||
*
|
||||
* @param ec Set the indicate what error occurred, if any.
|
||||
*/
|
||||
boost::system::error_code open(const std::string& device,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return this->service.open(this->implementation, device, ec);
|
||||
}
|
||||
|
||||
/// Assign an existing native serial port to the serial port.
|
||||
/*
|
||||
* This function opens the serial port to hold an existing native serial port.
|
||||
*
|
||||
* @param native_serial_port A native serial port.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
void assign(const native_type& native_serial_port)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
this->service.assign(this->implementation, native_serial_port, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
}
|
||||
|
||||
/// Assign an existing native serial port to the serial port.
|
||||
/*
|
||||
* This function opens the serial port to hold an existing native serial port.
|
||||
*
|
||||
* @param native_serial_port A native serial port.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
boost::system::error_code assign(const native_type& native_serial_port,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return this->service.assign(this->implementation, native_serial_port, ec);
|
||||
}
|
||||
|
||||
/// Determine whether the serial port is open.
|
||||
bool is_open() const
|
||||
{
|
||||
return this->service.is_open(this->implementation);
|
||||
}
|
||||
|
||||
/// Close the serial port.
|
||||
/**
|
||||
* This function is used to close the serial port. Any asynchronous read or
|
||||
* write operations will be cancelled immediately, and will complete with the
|
||||
* boost::asio::error::operation_aborted error.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
this->service.close(this->implementation, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
}
|
||||
|
||||
/// Close the serial port.
|
||||
/**
|
||||
* This function is used to close the serial port. Any asynchronous read or
|
||||
* write operations will be cancelled immediately, and will complete with the
|
||||
* boost::asio::error::operation_aborted error.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
boost::system::error_code close(boost::system::error_code& ec)
|
||||
{
|
||||
return this->service.close(this->implementation, ec);
|
||||
}
|
||||
|
||||
/// Get the native serial port representation.
|
||||
/**
|
||||
* This function may be used to obtain the underlying representation of the
|
||||
* serial port. This is intended to allow access to native serial port
|
||||
* functionality that is not otherwise provided.
|
||||
*/
|
||||
native_type native()
|
||||
{
|
||||
return this->service.native(this->implementation);
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the serial port.
|
||||
/**
|
||||
* This function causes all outstanding asynchronous read or write operations
|
||||
* to finish immediately, and the handlers for cancelled operations will be
|
||||
* passed the boost::asio::error::operation_aborted error.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
void cancel()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
this->service.cancel(this->implementation, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the serial port.
|
||||
/**
|
||||
* This function causes all outstanding asynchronous read or write operations
|
||||
* to finish immediately, and the handlers for cancelled operations will be
|
||||
* passed the boost::asio::error::operation_aborted error.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
boost::system::error_code cancel(boost::system::error_code& ec)
|
||||
{
|
||||
return this->service.cancel(this->implementation, ec);
|
||||
}
|
||||
|
||||
/// Send a break sequence to the serial port.
|
||||
/**
|
||||
* This function causes a break sequence of platform-specific duration to be
|
||||
* sent out the serial port.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
void send_break()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
this->service.send_break(this->implementation, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
}
|
||||
|
||||
/// Send a break sequence to the serial port.
|
||||
/**
|
||||
* This function causes a break sequence of platform-specific duration to be
|
||||
* sent out the serial port.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
boost::system::error_code send_break(boost::system::error_code& ec)
|
||||
{
|
||||
return this->service.send_break(this->implementation, ec);
|
||||
}
|
||||
|
||||
/// Set an option on the serial port.
|
||||
/**
|
||||
* This function is used to set an option on the serial port.
|
||||
*
|
||||
* @param option The option value to be set on the serial port.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*
|
||||
* @sa SettableSerialPortOption @n
|
||||
* boost::asio::serial_port_base::baud_rate @n
|
||||
* boost::asio::serial_port_base::flow_control @n
|
||||
* boost::asio::serial_port_base::parity @n
|
||||
* boost::asio::serial_port_base::stop_bits @n
|
||||
* boost::asio::serial_port_base::character_size
|
||||
*/
|
||||
template <typename SettableSerialPortOption>
|
||||
void set_option(const SettableSerialPortOption& option)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
this->service.set_option(this->implementation, option, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
}
|
||||
|
||||
/// Set an option on the serial port.
|
||||
/**
|
||||
* This function is used to set an option on the serial port.
|
||||
*
|
||||
* @param option The option value to be set on the serial port.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @sa SettableSerialPortOption @n
|
||||
* boost::asio::serial_port_base::baud_rate @n
|
||||
* boost::asio::serial_port_base::flow_control @n
|
||||
* boost::asio::serial_port_base::parity @n
|
||||
* boost::asio::serial_port_base::stop_bits @n
|
||||
* boost::asio::serial_port_base::character_size
|
||||
*/
|
||||
template <typename SettableSerialPortOption>
|
||||
boost::system::error_code set_option(const SettableSerialPortOption& option,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return this->service.set_option(this->implementation, option, ec);
|
||||
}
|
||||
|
||||
/// Get an option from the serial port.
|
||||
/**
|
||||
* This function is used to get the current value of an option on the serial
|
||||
* port.
|
||||
*
|
||||
* @param option The option value to be obtained from the serial port.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*
|
||||
* @sa GettableSerialPortOption @n
|
||||
* boost::asio::serial_port_base::baud_rate @n
|
||||
* boost::asio::serial_port_base::flow_control @n
|
||||
* boost::asio::serial_port_base::parity @n
|
||||
* boost::asio::serial_port_base::stop_bits @n
|
||||
* boost::asio::serial_port_base::character_size
|
||||
*/
|
||||
template <typename GettableSerialPortOption>
|
||||
void get_option(GettableSerialPortOption& option)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
this->service.get_option(this->implementation, option, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
}
|
||||
|
||||
/// Get an option from the serial port.
|
||||
/**
|
||||
* This function is used to get the current value of an option on the serial
|
||||
* port.
|
||||
*
|
||||
* @param option The option value to be obtained from the serial port.
|
||||
*
|
||||
* @param ec Set to indicate what error occured, if any.
|
||||
*
|
||||
* @sa GettableSerialPortOption @n
|
||||
* boost::asio::serial_port_base::baud_rate @n
|
||||
* boost::asio::serial_port_base::flow_control @n
|
||||
* boost::asio::serial_port_base::parity @n
|
||||
* boost::asio::serial_port_base::stop_bits @n
|
||||
* boost::asio::serial_port_base::character_size
|
||||
*/
|
||||
template <typename GettableSerialPortOption>
|
||||
boost::system::error_code get_option(GettableSerialPortOption& option,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return this->service.get_option(this->implementation, option, ec);
|
||||
}
|
||||
|
||||
/// Write some data to the serial port.
|
||||
/**
|
||||
* This function is used to write data to the serial port. The function call
|
||||
* will block until one or more bytes of the data has been written
|
||||
* successfully, or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the serial port.
|
||||
*
|
||||
* @returns The number of bytes written.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure. An error code of
|
||||
* boost::asio::error::eof indicates that the connection was closed by the
|
||||
* peer.
|
||||
*
|
||||
* @note The write_some operation may not transmit all of the data to the
|
||||
* peer. Consider using the @ref write function if you need to ensure that
|
||||
* all data is written before the blocking operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To write a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* serial_port.write_some(boost::asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on writing multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some(const ConstBufferSequence& buffers)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
std::size_t s = this->service.write_some(this->implementation, buffers, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Write some data to the serial port.
|
||||
/**
|
||||
* This function is used to write data to the serial port. The function call
|
||||
* will block until one or more bytes of the data has been written
|
||||
* successfully, or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the serial port.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes written. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The write_some operation may not transmit all of the data to the
|
||||
* peer. Consider using the @ref write function if you need to ensure that
|
||||
* all data is written before the blocking operation completes.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return this->service.write_some(this->implementation, buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous write.
|
||||
/**
|
||||
* This function is used to asynchronously write data to the serial port.
|
||||
* The function call always returns immediately.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the serial port.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the handler is called.
|
||||
*
|
||||
* @param handler The handler to be called when the write operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code void handler(
|
||||
* const boost::system::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes written.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* boost::asio::io_service::post().
|
||||
*
|
||||
* @note The write operation may not transmit all of the data to the peer.
|
||||
* Consider using the @ref async_write function if you need to ensure that all
|
||||
* data is written before the asynchronous operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To write a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* serial_port.async_write_some(boost::asio::buffer(data, size), handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on writing multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence, typename WriteHandler>
|
||||
void async_write_some(const ConstBufferSequence& buffers,
|
||||
WriteHandler handler)
|
||||
{
|
||||
this->service.async_write_some(this->implementation, buffers, handler);
|
||||
}
|
||||
|
||||
/// Read some data from the serial port.
|
||||
/**
|
||||
* This function is used to read data from the serial port. The function
|
||||
* call will block until one or more bytes of data has been read successfully,
|
||||
* or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
*
|
||||
* @returns The number of bytes read.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure. An error code of
|
||||
* boost::asio::error::eof indicates that the connection was closed by the
|
||||
* peer.
|
||||
*
|
||||
* @note The read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that
|
||||
* the requested amount of data is read before the blocking operation
|
||||
* completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* serial_port.read_some(boost::asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on reading into multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
std::size_t s = this->service.read_some(this->implementation, buffers, ec);
|
||||
boost::asio::detail::throw_error(ec);
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Read some data from the serial port.
|
||||
/**
|
||||
* This function is used to read data from the serial port. The function
|
||||
* call will block until one or more bytes of data has been read successfully,
|
||||
* or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes read. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that
|
||||
* the requested amount of data is read before the blocking operation
|
||||
* completes.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return this->service.read_some(this->implementation, buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous read.
|
||||
/**
|
||||
* This function is used to asynchronously read data from the serial port.
|
||||
* The function call always returns immediately.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the handler is called.
|
||||
*
|
||||
* @param handler The handler to be called when the read operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code void handler(
|
||||
* const boost::system::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes read.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* boost::asio::io_service::post().
|
||||
*
|
||||
* @note The read operation may not read all of the requested number of bytes.
|
||||
* Consider using the @ref async_read function if you need to ensure that the
|
||||
* requested amount of data is read before the asynchronous operation
|
||||
* completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* serial_port.async_read_some(boost::asio::buffer(data, size), handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on reading into multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
void async_read_some(const MutableBufferSequence& buffers,
|
||||
ReadHandler handler)
|
||||
{
|
||||
this->service.async_read_some(this->implementation, buffers, handler);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
|
||||
// || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_BASIC_SERIAL_PORT_HPP
|
||||
@@ -47,6 +47,12 @@ inline ReturnType error_wrapper(ReturnType return_value,
|
||||
return return_value;
|
||||
}
|
||||
|
||||
inline int open(const char* path, int flags, boost::system::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::open(path, flags), ec);
|
||||
}
|
||||
|
||||
inline int close(int d, boost::system::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
@@ -88,6 +94,18 @@ inline int ioctl(int d, long cmd, ioctl_arg_type* arg,
|
||||
return error_wrapper(::ioctl(d, cmd, arg), ec);
|
||||
}
|
||||
|
||||
inline int fcntl(int d, long cmd, boost::system::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::fcntl(d, cmd), ec);
|
||||
}
|
||||
|
||||
inline int fcntl(int d, long cmd, long arg, boost::system::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::fcntl(d, cmd, arg), ec);
|
||||
}
|
||||
|
||||
inline int poll_read(int d, boost::system::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
|
||||
@@ -177,7 +177,7 @@ public:
|
||||
}
|
||||
|
||||
// Get the native descriptor representation.
|
||||
native_type native(implementation_type& impl)
|
||||
native_type native(const implementation_type& impl) const
|
||||
{
|
||||
return impl.descriptor_;
|
||||
}
|
||||
|
||||
260
include/boost/asio/detail/reactive_serial_port_service.hpp
Normal file
260
include/boost/asio/detail/reactive_serial_port_service.hpp
Normal file
@@ -0,0 +1,260 @@
|
||||
//
|
||||
// reactive_serial_port_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP
|
||||
#define BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
#include <termios.h>
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/detail/descriptor_ops.hpp>
|
||||
#include <boost/asio/detail/reactive_descriptor_service.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
// Extend reactive_descriptor_service to provide serial port support.
|
||||
template <typename Reactor>
|
||||
class reactive_serial_port_service
|
||||
: public boost::asio::detail::service_base<
|
||||
reactive_serial_port_service<Reactor> >
|
||||
{
|
||||
public:
|
||||
// The native type of a stream handle.
|
||||
typedef typename reactive_descriptor_service<Reactor>::native_type
|
||||
native_type;
|
||||
|
||||
// The implementation type of the stream handle.
|
||||
typedef typename reactive_descriptor_service<Reactor>::implementation_type
|
||||
implementation_type;
|
||||
|
||||
reactive_serial_port_service(boost::asio::io_service& io_service)
|
||||
: boost::asio::detail::service_base<
|
||||
reactive_serial_port_service>(io_service),
|
||||
descriptor_service_(boost::asio::use_service<
|
||||
reactive_descriptor_service<Reactor> >(io_service))
|
||||
{
|
||||
}
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
void shutdown_service()
|
||||
{
|
||||
}
|
||||
|
||||
// Construct a new handle implementation.
|
||||
void construct(implementation_type& impl)
|
||||
{
|
||||
descriptor_service_.construct(impl);
|
||||
}
|
||||
|
||||
// Destroy a handle implementation.
|
||||
void destroy(implementation_type& impl)
|
||||
{
|
||||
descriptor_service_.destroy(impl);
|
||||
}
|
||||
|
||||
// Open the serial port using the specified device name.
|
||||
boost::system::error_code open(implementation_type& impl,
|
||||
const std::string& device, boost::system::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
int fd = descriptor_ops::open(device.c_str(),
|
||||
O_RDWR | O_NONBLOCK | O_NOCTTY, ec);
|
||||
if (fd < 0)
|
||||
return ec;
|
||||
|
||||
int s = descriptor_ops::fcntl(fd, F_GETFL, ec);
|
||||
if (s >= 0)
|
||||
s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec);
|
||||
if (s < 0)
|
||||
{
|
||||
boost::system::error_code ignored_ec;
|
||||
descriptor_ops::close(fd, ignored_ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Set up default serial port options.
|
||||
termios ios;
|
||||
descriptor_ops::clear_error(ec);
|
||||
s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec);
|
||||
if (s >= 0)
|
||||
{
|
||||
::cfmakeraw(&ios);
|
||||
ios.c_iflag |= IGNPAR;
|
||||
descriptor_ops::clear_error(ec);
|
||||
s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec);
|
||||
}
|
||||
if (s < 0)
|
||||
{
|
||||
boost::system::error_code ignored_ec;
|
||||
descriptor_ops::close(fd, ignored_ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
// We're done. Take ownership of the serial port descriptor.
|
||||
if (descriptor_service_.assign(impl, fd, ec))
|
||||
{
|
||||
boost::system::error_code ignored_ec;
|
||||
descriptor_ops::close(fd, ignored_ec);
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Assign a native handle to a handle implementation.
|
||||
boost::system::error_code assign(implementation_type& impl,
|
||||
const native_type& native_descriptor, boost::system::error_code& ec)
|
||||
{
|
||||
return descriptor_service_.assign(impl, native_descriptor, ec);
|
||||
}
|
||||
|
||||
// Determine whether the handle is open.
|
||||
bool is_open(const implementation_type& impl) const
|
||||
{
|
||||
return descriptor_service_.is_open(impl);
|
||||
}
|
||||
|
||||
// Destroy a handle implementation.
|
||||
boost::system::error_code close(implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return descriptor_service_.close(impl, ec);
|
||||
}
|
||||
|
||||
// Get the native handle representation.
|
||||
native_type native(implementation_type& impl)
|
||||
{
|
||||
return descriptor_service_.native(impl);
|
||||
}
|
||||
|
||||
// Cancel all operations associated with the handle.
|
||||
boost::system::error_code cancel(implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return descriptor_service_.cancel(impl, ec);
|
||||
}
|
||||
|
||||
// Set an option on the serial port.
|
||||
template <typename SettableSerialPortOption>
|
||||
boost::system::error_code set_option(implementation_type& impl,
|
||||
const SettableSerialPortOption& option, boost::system::error_code& ec)
|
||||
{
|
||||
termios ios;
|
||||
descriptor_ops::clear_error(ec);
|
||||
descriptor_ops::error_wrapper(::tcgetattr(
|
||||
descriptor_service_.native(impl), &ios), ec);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
if (option.store(ios, ec))
|
||||
return ec;
|
||||
|
||||
descriptor_ops::clear_error(ec);
|
||||
descriptor_ops::error_wrapper(::tcsetattr(
|
||||
descriptor_service_.native(impl), TCSANOW, &ios), ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Get an option from the serial port.
|
||||
template <typename GettableSerialPortOption>
|
||||
boost::system::error_code get_option(const implementation_type& impl,
|
||||
GettableSerialPortOption& option, boost::system::error_code& ec) const
|
||||
{
|
||||
termios ios;
|
||||
descriptor_ops::clear_error(ec);
|
||||
descriptor_ops::error_wrapper(::tcgetattr(
|
||||
descriptor_service_.native(impl), &ios), ec);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
return option.load(ios, ec);
|
||||
}
|
||||
|
||||
// Send a break sequence to the serial port.
|
||||
boost::system::error_code send_break(implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
descriptor_ops::clear_error(ec);
|
||||
descriptor_ops::error_wrapper(::tcsendbreak(
|
||||
descriptor_service_.native(impl), 0), ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Write the given data. Returns the number of bytes sent.
|
||||
template <typename ConstBufferSequence>
|
||||
size_t write_some(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers, boost::system::error_code& ec)
|
||||
{
|
||||
return descriptor_service_.write_some(impl, buffers, ec);
|
||||
}
|
||||
|
||||
// Start an asynchronous write. The data being written must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
void async_write_some(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers, Handler handler)
|
||||
{
|
||||
descriptor_service_.async_write_some(impl, buffers, handler);
|
||||
}
|
||||
|
||||
// Read some data. Returns the number of bytes received.
|
||||
template <typename MutableBufferSequence>
|
||||
size_t read_some(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, boost::system::error_code& ec)
|
||||
{
|
||||
return descriptor_service_.read_some(impl, buffers, ec);
|
||||
}
|
||||
|
||||
// Start an asynchronous read. The buffer for the data being received must be
|
||||
// valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
void async_read_some(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, Handler handler)
|
||||
{
|
||||
descriptor_service_.async_read_some(impl, buffers, handler);
|
||||
}
|
||||
|
||||
private:
|
||||
// The handle service used for initiating asynchronous operations.
|
||||
reactive_descriptor_service<Reactor>& descriptor_service_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP
|
||||
@@ -155,7 +155,7 @@ public:
|
||||
|
||||
// Destroy a handle implementation.
|
||||
boost::system::error_code close(implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
@@ -176,7 +176,7 @@ public:
|
||||
}
|
||||
|
||||
// Get the native handle representation.
|
||||
native_type native(implementation_type& impl)
|
||||
native_type native(const implementation_type& impl) const
|
||||
{
|
||||
return impl.handle_;
|
||||
}
|
||||
|
||||
294
include/boost/asio/detail/win_iocp_serial_port_service.hpp
Normal file
294
include/boost/asio/detail/win_iocp_serial_port_service.hpp
Normal file
@@ -0,0 +1,294 @@
|
||||
//
|
||||
// win_iocp_serial_port_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
|
||||
#define BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/detail/win_iocp_handle_service.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
// Extend win_iocp_handle_service to provide serial port support.
|
||||
class win_iocp_serial_port_service
|
||||
: public boost::asio::detail::service_base<win_iocp_serial_port_service>
|
||||
{
|
||||
public:
|
||||
// The native type of a stream handle.
|
||||
typedef win_iocp_handle_service::native_type native_type;
|
||||
|
||||
// The implementation type of the stream handle.
|
||||
typedef win_iocp_handle_service::implementation_type implementation_type;
|
||||
|
||||
win_iocp_serial_port_service(boost::asio::io_service& io_service)
|
||||
: boost::asio::detail::service_base<
|
||||
win_iocp_serial_port_service>(io_service),
|
||||
handle_service_(
|
||||
boost::asio::use_service<win_iocp_handle_service>(io_service))
|
||||
{
|
||||
}
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
void shutdown_service()
|
||||
{
|
||||
}
|
||||
|
||||
// Construct a new handle implementation.
|
||||
void construct(implementation_type& impl)
|
||||
{
|
||||
handle_service_.construct(impl);
|
||||
}
|
||||
|
||||
// Destroy a handle implementation.
|
||||
void destroy(implementation_type& impl)
|
||||
{
|
||||
handle_service_.destroy(impl);
|
||||
}
|
||||
|
||||
// Open the serial port using the specified device name.
|
||||
boost::system::error_code open(implementation_type& impl,
|
||||
const std::string& device, boost::system::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
// For convenience, add a leading \\.\ sequence if not already present.
|
||||
std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device;
|
||||
|
||||
// Open a handle to the serial port.
|
||||
::HANDLE handle = ::CreateFile(name.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE, 0, 0,
|
||||
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Determine the initial serial port parameters.
|
||||
using namespace std; // For memcpy.
|
||||
::DCB dcb;
|
||||
memset(&dcb, 0, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!::GetCommState(handle, &dcb))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
::CloseHandle(handle);
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Set some default serial port parameters. This implementation does not
|
||||
// support changing these, so they might as well be in a known state.
|
||||
dcb.fBinary = TRUE; // Win32 only supports binary mode.
|
||||
dcb.fDsrSensitivity = FALSE;
|
||||
dcb.fNull = FALSE; // Do not ignore NULL characters.
|
||||
dcb.fAbortOnError = FALSE; // Ignore serial framing errors.
|
||||
if (!::SetCommState(handle, &dcb))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
::CloseHandle(handle);
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Set up timeouts so that the serial port will behave similarly to a
|
||||
// network socket. Reads wait for at least one byte, then return with
|
||||
// whatever they have. Writes return once everything is out the door.
|
||||
::COMMTIMEOUTS timeouts;
|
||||
timeouts.ReadIntervalTimeout = 1;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
timeouts.ReadTotalTimeoutConstant = 0;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
timeouts.WriteTotalTimeoutConstant = 0;
|
||||
if (!::SetCommTimeouts(handle, &timeouts))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
::CloseHandle(handle);
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
// We're done. Take ownership of the serial port handle.
|
||||
if (handle_service_.assign(impl, handle, ec))
|
||||
::CloseHandle(handle);
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Assign a native handle to a handle implementation.
|
||||
boost::system::error_code assign(implementation_type& impl,
|
||||
const native_type& native_handle, boost::system::error_code& ec)
|
||||
{
|
||||
return handle_service_.assign(impl, native_handle, ec);
|
||||
}
|
||||
|
||||
// Determine whether the handle is open.
|
||||
bool is_open(const implementation_type& impl) const
|
||||
{
|
||||
return handle_service_.is_open(impl);
|
||||
}
|
||||
|
||||
// Destroy a handle implementation.
|
||||
boost::system::error_code close(implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return handle_service_.close(impl, ec);
|
||||
}
|
||||
|
||||
// Get the native handle representation.
|
||||
native_type native(implementation_type& impl)
|
||||
{
|
||||
return handle_service_.native(impl);
|
||||
}
|
||||
|
||||
// Cancel all operations associated with the handle.
|
||||
boost::system::error_code cancel(implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return handle_service_.cancel(impl, ec);
|
||||
}
|
||||
|
||||
// Set an option on the serial port.
|
||||
template <typename SettableSerialPortOption>
|
||||
boost::system::error_code set_option(implementation_type& impl,
|
||||
const SettableSerialPortOption& option, boost::system::error_code& ec)
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
|
||||
::DCB dcb;
|
||||
memset(&dcb, 0, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!::GetCommState(handle_service_.native(impl), &dcb))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
if (option.store(dcb, ec))
|
||||
return ec;
|
||||
|
||||
if (!::SetCommState(handle_service_.native(impl), &dcb))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Get an option from the serial port.
|
||||
template <typename GettableSerialPortOption>
|
||||
boost::system::error_code get_option(const implementation_type& impl,
|
||||
GettableSerialPortOption& option, boost::system::error_code& ec) const
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
|
||||
::DCB dcb;
|
||||
memset(&dcb, 0, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!::GetCommState(handle_service_.native(impl), &dcb))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
return option.load(dcb, ec);
|
||||
}
|
||||
|
||||
// Send a break sequence to the serial port.
|
||||
boost::system::error_code send_break(implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
ec = boost::asio::error::operation_not_supported;
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Write the given data. Returns the number of bytes sent.
|
||||
template <typename ConstBufferSequence>
|
||||
size_t write_some(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers, boost::system::error_code& ec)
|
||||
{
|
||||
return handle_service_.write_some(impl, buffers, ec);
|
||||
}
|
||||
|
||||
// Start an asynchronous write. The data being written must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
void async_write_some(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers, Handler handler)
|
||||
{
|
||||
handle_service_.async_write_some(impl, buffers, handler);
|
||||
}
|
||||
|
||||
// Read some data. Returns the number of bytes received.
|
||||
template <typename MutableBufferSequence>
|
||||
size_t read_some(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, boost::system::error_code& ec)
|
||||
{
|
||||
return handle_service_.read_some(impl, buffers, ec);
|
||||
}
|
||||
|
||||
// Start an asynchronous read. The buffer for the data being received must be
|
||||
// valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
void async_read_some(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, Handler handler)
|
||||
{
|
||||
handle_service_.async_read_some(impl, buffers, handler);
|
||||
}
|
||||
|
||||
private:
|
||||
// The handle service used for initiating asynchronous operations.
|
||||
win_iocp_handle_service& handle_service_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
|
||||
527
include/boost/asio/impl/serial_port_base.ipp
Normal file
527
include/boost/asio/impl/serial_port_base.ipp
Normal file
@@ -0,0 +1,527 @@
|
||||
//
|
||||
// serial_port_base.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_SERIAL_PORT_BASE_IPP
|
||||
#define BOOST_ASIO_SERIAL_PORT_BASE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
inline serial_port_base::baud_rate::baud_rate(unsigned int rate)
|
||||
: value_(rate)
|
||||
{
|
||||
}
|
||||
|
||||
inline unsigned int serial_port_base::baud_rate::value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
inline boost::system::error_code serial_port_base::baud_rate::store(
|
||||
BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
storage.BaudRate = value_;
|
||||
#else
|
||||
speed_t baud;
|
||||
switch (value_)
|
||||
{
|
||||
// Do POSIX-specified rates first.
|
||||
case 0: baud = B0; break;
|
||||
case 50: baud = B50; break;
|
||||
case 75: baud = B75; break;
|
||||
case 110: baud = B110; break;
|
||||
case 134: baud = B134; break;
|
||||
case 150: baud = B150; break;
|
||||
case 200: baud = B200; break;
|
||||
case 300: baud = B300; break;
|
||||
case 600: baud = B600; break;
|
||||
case 1200: baud = B1200; break;
|
||||
case 1800: baud = B1800; break;
|
||||
case 2400: baud = B2400; break;
|
||||
case 4800: baud = B4800; break;
|
||||
case 9600: baud = B9600; break;
|
||||
case 19200: baud = B19200; break;
|
||||
case 38400: baud = B38400; break;
|
||||
// And now the extended ones conditionally.
|
||||
# ifdef B7200
|
||||
case 7200: baud = B7200; break;
|
||||
# endif
|
||||
# ifdef B14400
|
||||
case 14400: baud = B14400; break;
|
||||
# endif
|
||||
# ifdef B57600
|
||||
case 57600: baud = B57600; break;
|
||||
# endif
|
||||
# ifdef B115200
|
||||
case 115200: baud = B115200; break;
|
||||
# endif
|
||||
# ifdef B230400
|
||||
case 230400: baud = B230400; break;
|
||||
# endif
|
||||
# ifdef B460800
|
||||
case 460800: baud = B460800; break;
|
||||
# endif
|
||||
# ifdef B500000
|
||||
case 500000: baud = B500000; break;
|
||||
# endif
|
||||
# ifdef B576000
|
||||
case 576000: baud = B576000; break;
|
||||
# endif
|
||||
# ifdef B921600
|
||||
case 921600: baud = B921600; break;
|
||||
# endif
|
||||
# ifdef B1000000
|
||||
case 1000000: baud = B1000000; break;
|
||||
# endif
|
||||
# ifdef B1152000
|
||||
case 1152000: baud = B1152000; break;
|
||||
# endif
|
||||
# ifdef B2000000
|
||||
case 2000000: baud = B2000000; break;
|
||||
# endif
|
||||
# ifdef B3000000
|
||||
case 3000000: baud = B3000000; break;
|
||||
# endif
|
||||
# ifdef B3500000
|
||||
case 3500000: baud = B3500000; break;
|
||||
# endif
|
||||
# ifdef B4000000
|
||||
case 4000000: baud = B4000000; break;
|
||||
# endif
|
||||
default:
|
||||
baud = B0;
|
||||
ec = boost::asio::error::invalid_argument;
|
||||
return ec;
|
||||
}
|
||||
::cfsetspeed(&storage, baud);
|
||||
#endif
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
inline boost::system::error_code serial_port_base::baud_rate::load(
|
||||
const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
value_ = storage.BaudRate;
|
||||
#else
|
||||
speed_t baud = ::cfgetospeed(&storage);
|
||||
switch (baud)
|
||||
{
|
||||
// First do those specified by POSIX.
|
||||
case B0: value_ = 0; break;
|
||||
case B50: value_ = 50; break;
|
||||
case B75: value_ = 75; break;
|
||||
case B110: value_ = 110; break;
|
||||
case B134: value_ = 134; break;
|
||||
case B150: value_ = 150; break;
|
||||
case B200: value_ = 200; break;
|
||||
case B300: value_ = 300; break;
|
||||
case B600: value_ = 600; break;
|
||||
case B1200: value_ = 1200; break;
|
||||
case B1800: value_ = 1800; break;
|
||||
case B2400: value_ = 2400; break;
|
||||
case B4800: value_ = 4800; break;
|
||||
case B9600: value_ = 9600; break;
|
||||
case B19200: value_ = 19200; break;
|
||||
case B38400: value_ = 38400; break;
|
||||
// Now conditionally handle a bunch of extended rates.
|
||||
# ifdef B7200
|
||||
case B7200: value_ = 7200; break;
|
||||
# endif
|
||||
# ifdef B14400
|
||||
case B14400: value_ = 14400; break;
|
||||
# endif
|
||||
# ifdef B57600
|
||||
case B57600: value_ = 57600; break;
|
||||
# endif
|
||||
# ifdef B115200
|
||||
case B115200: value_ = 115200; break;
|
||||
# endif
|
||||
# ifdef B230400
|
||||
case B230400: value_ = 230400; break;
|
||||
# endif
|
||||
# ifdef B460800
|
||||
case B460800: value_ = 460800; break;
|
||||
# endif
|
||||
# ifdef B500000
|
||||
case B500000: value_ = 500000; break;
|
||||
# endif
|
||||
# ifdef B576000
|
||||
case B576000: value_ = 576000; break;
|
||||
# endif
|
||||
# ifdef B921600
|
||||
case B921600: value_ = 921600; break;
|
||||
# endif
|
||||
# ifdef B1000000
|
||||
case B1000000: value_ = 1000000; break;
|
||||
# endif
|
||||
# ifdef B1152000
|
||||
case B1152000: value_ = 1152000; break;
|
||||
# endif
|
||||
# ifdef B2000000
|
||||
case B2000000: value_ = 2000000; break;
|
||||
# endif
|
||||
# ifdef B3000000
|
||||
case B3000000: value_ = 3000000; break;
|
||||
# endif
|
||||
# ifdef B3500000
|
||||
case B3500000: value_ = 3500000; break;
|
||||
# endif
|
||||
# ifdef B4000000
|
||||
case B4000000: value_ = 4000000; break;
|
||||
# endif
|
||||
default:
|
||||
value_ = 0;
|
||||
ec = boost::asio::error::invalid_argument;
|
||||
return ec;
|
||||
}
|
||||
#endif
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
inline serial_port_base::flow_control::flow_control(
|
||||
serial_port_base::flow_control::type t)
|
||||
: value_(t)
|
||||
{
|
||||
if (t != none && t != software && t != hardware)
|
||||
throw std::out_of_range("invalid flow_control value");
|
||||
}
|
||||
|
||||
inline serial_port_base::flow_control::type
|
||||
serial_port_base::flow_control::value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
inline boost::system::error_code serial_port_base::flow_control::store(
|
||||
BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
storage.fOutxCtsFlow = FALSE;
|
||||
storage.fOutxDsrFlow = FALSE;
|
||||
storage.fTXContinueOnXoff = TRUE;
|
||||
storage.fDtrControl = DTR_CONTROL_ENABLE;
|
||||
storage.fDsrSensitivity = FALSE;
|
||||
storage.fOutX = FALSE;
|
||||
storage.fInX = FALSE;
|
||||
storage.fRtsControl = RTS_CONTROL_ENABLE;
|
||||
switch (value_)
|
||||
{
|
||||
case none:
|
||||
break;
|
||||
case software:
|
||||
storage.fOutX = TRUE;
|
||||
storage.fInX = TRUE;
|
||||
break;
|
||||
case hardware:
|
||||
storage.fOutxCtsFlow = TRUE;
|
||||
storage.fRtsControl = RTS_CONTROL_HANDSHAKE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (value_)
|
||||
{
|
||||
case none:
|
||||
storage.c_iflag &= ~(IXOFF | IXON);
|
||||
storage.c_cflag &= ~CRTSCTS;
|
||||
break;
|
||||
case software:
|
||||
storage.c_iflag |= IXOFF | IXON;
|
||||
storage.c_cflag &= ~CRTSCTS;
|
||||
break;
|
||||
case hardware:
|
||||
storage.c_iflag &= ~(IXOFF | IXON);
|
||||
storage.c_cflag |= CRTSCTS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
inline boost::system::error_code serial_port_base::flow_control::load(
|
||||
const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
if (storage.fOutX && storage.fInX)
|
||||
{
|
||||
value_ = software;
|
||||
}
|
||||
else if (storage.fOutxCtsFlow && storage.fRtsControl == RTS_CONTROL_HANDSHAKE)
|
||||
{
|
||||
value_ = hardware;
|
||||
}
|
||||
else
|
||||
{
|
||||
value_ = none;
|
||||
}
|
||||
#else
|
||||
if (storage.c_iflag & (IXOFF | IXON))
|
||||
{
|
||||
value_ = software;
|
||||
}
|
||||
else if (storage.c_cflag & CRTSCTS)
|
||||
{
|
||||
value_ = hardware;
|
||||
}
|
||||
else
|
||||
{
|
||||
value_ = none;
|
||||
}
|
||||
#endif
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
inline serial_port_base::parity::parity(serial_port_base::parity::type t)
|
||||
: value_(t)
|
||||
{
|
||||
if (t != none && t != odd && t != even)
|
||||
throw std::out_of_range("invalid parity value");
|
||||
}
|
||||
|
||||
inline serial_port_base::parity::type serial_port_base::parity::value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
inline boost::system::error_code serial_port_base::parity::store(
|
||||
BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
switch (value_)
|
||||
{
|
||||
case none:
|
||||
storage.fParity = FALSE;
|
||||
storage.Parity = NOPARITY;
|
||||
break;
|
||||
case odd:
|
||||
storage.fParity = TRUE;
|
||||
storage.Parity = ODDPARITY;
|
||||
break;
|
||||
case even:
|
||||
storage.fParity = TRUE;
|
||||
storage.Parity = EVENPARITY;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (value_)
|
||||
{
|
||||
case none:
|
||||
storage.c_iflag |= IGNPAR;
|
||||
storage.c_cflag &= ~(PARENB | PARODD);
|
||||
break;
|
||||
case even:
|
||||
storage.c_iflag &= ~(IGNPAR | PARMRK);
|
||||
storage.c_iflag |= INPCK;
|
||||
storage.c_cflag |= PARENB;
|
||||
storage.c_cflag &= ~PARODD;
|
||||
break;
|
||||
case odd:
|
||||
storage.c_iflag &= ~(IGNPAR | PARMRK);
|
||||
storage.c_iflag |= INPCK;
|
||||
storage.c_cflag |= (PARENB | PARODD);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
inline boost::system::error_code serial_port_base::parity::load(
|
||||
const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
if (storage.Parity == EVENPARITY)
|
||||
{
|
||||
value_ = even;
|
||||
}
|
||||
else if (storage.Parity == ODDPARITY)
|
||||
{
|
||||
value_ = odd;
|
||||
}
|
||||
else
|
||||
{
|
||||
value_ = none;
|
||||
}
|
||||
#else
|
||||
if (storage.c_cflag & PARENB)
|
||||
{
|
||||
if (storage.c_cflag & PARODD)
|
||||
{
|
||||
value_ = odd;
|
||||
}
|
||||
else
|
||||
{
|
||||
value_ = even;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value_ = none;
|
||||
}
|
||||
#endif
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
inline serial_port_base::stop_bits::stop_bits(
|
||||
serial_port_base::stop_bits::type t)
|
||||
: value_(t)
|
||||
{
|
||||
if (t != one && t != onepointfive && t != two)
|
||||
throw std::out_of_range("invalid stop_bits value");
|
||||
}
|
||||
|
||||
inline serial_port_base::stop_bits::type
|
||||
serial_port_base::stop_bits::value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
inline boost::system::error_code serial_port_base::stop_bits::store(
|
||||
BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
switch (value_)
|
||||
{
|
||||
case one:
|
||||
storage.StopBits = ONESTOPBIT;
|
||||
break;
|
||||
case onepointfive:
|
||||
storage.StopBits = ONE5STOPBITS;
|
||||
break;
|
||||
case two:
|
||||
storage.StopBits = TWOSTOPBITS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (value_)
|
||||
{
|
||||
case one:
|
||||
storage.c_cflag &= ~CSTOPB;
|
||||
break;
|
||||
case two:
|
||||
storage.c_cflag |= CSTOPB;
|
||||
break;
|
||||
default:
|
||||
ec = boost::asio::error::operation_not_supported;
|
||||
return ec;
|
||||
}
|
||||
#endif
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
inline boost::system::error_code serial_port_base::stop_bits::load(
|
||||
const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
if (storage.StopBits == ONESTOPBIT)
|
||||
{
|
||||
value_ = one;
|
||||
}
|
||||
else if (storage.StopBits == ONE5STOPBITS)
|
||||
{
|
||||
value_ = onepointfive;
|
||||
}
|
||||
else if (storage.StopBits == TWOSTOPBITS)
|
||||
{
|
||||
value_ = two;
|
||||
}
|
||||
else
|
||||
{
|
||||
value_ = one;
|
||||
}
|
||||
#else
|
||||
value_ = (storage.c_cflag & CSTOPB) ? two : one;
|
||||
#endif
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
inline serial_port_base::character_size::character_size(unsigned int t)
|
||||
: value_(t)
|
||||
{
|
||||
if (t < 5 || t > 8)
|
||||
throw std::out_of_range("invalid character_size value");
|
||||
}
|
||||
|
||||
inline unsigned int serial_port_base::character_size::value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
inline boost::system::error_code serial_port_base::character_size::store(
|
||||
BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
storage.ByteSize = value_;
|
||||
#else
|
||||
storage.c_cflag &= ~CSIZE;
|
||||
switch (value_)
|
||||
{
|
||||
case 5: storage.c_cflag |= CS5; break;
|
||||
case 6: storage.c_cflag |= CS6; break;
|
||||
case 7: storage.c_cflag |= CS7; break;
|
||||
case 8: storage.c_cflag |= CS8; break;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
inline boost::system::error_code serial_port_base::character_size::load(
|
||||
const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
value_ = storage.ByteSize;
|
||||
#else
|
||||
if ((storage.c_cflag & CSIZE) == CS5) { value_ = 5; }
|
||||
else if ((storage.c_cflag & CSIZE) == CS6) { value_ = 6; }
|
||||
else if ((storage.c_cflag & CSIZE) == CS7) { value_ = 7; }
|
||||
else if ((storage.c_cflag & CSIZE) == CS8) { value_ = 8; }
|
||||
else
|
||||
{
|
||||
// Hmmm, use 8 for now.
|
||||
value_ = 8;
|
||||
}
|
||||
#endif
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_SERIAL_PORT_BASE_IPP
|
||||
40
include/boost/asio/serial_port.hpp
Normal file
40
include/boost/asio/serial_port.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// serial_port.hpp
|
||||
// ~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_SERIAL_PORT_HPP
|
||||
#define BOOST_ASIO_SERIAL_PORT_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
#include <boost/asio/basic_serial_port.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \
|
||||
|| defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
/// Typedef for the typical usage of a serial port.
|
||||
typedef basic_serial_port<> serial_port;
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
|
||||
// || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_SERIAL_PORT_HPP
|
||||
159
include/boost/asio/serial_port_base.hpp
Normal file
159
include/boost/asio/serial_port_base.hpp
Normal file
@@ -0,0 +1,159 @@
|
||||
//
|
||||
// serial_port_base.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_SERIAL_PORT_BASE_HPP
|
||||
#define BOOST_ASIO_SERIAL_PORT_BASE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
#include <stdexcept>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
# include <termios.h>
|
||||
#endif
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#include <boost/asio/detail/socket_types.hpp>
|
||||
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
# define BOOST_ASIO_OPTION_STORAGE implementation_defined
|
||||
#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
# define BOOST_ASIO_OPTION_STORAGE DCB
|
||||
#else
|
||||
# define BOOST_ASIO_OPTION_STORAGE termios
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
/// The serial_port_base class is used as a base for the basic_serial_port class
|
||||
/// template so that we have a common place to define the serial port options.
|
||||
class serial_port_base
|
||||
{
|
||||
public:
|
||||
/// Serial port option to permit changing the baud rate.
|
||||
/**
|
||||
* Implements changing the baud rate for a given serial port.
|
||||
*/
|
||||
class baud_rate
|
||||
{
|
||||
public:
|
||||
explicit baud_rate(unsigned int rate = 0);
|
||||
unsigned int value() const;
|
||||
boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage,
|
||||
boost::system::error_code& ec) const;
|
||||
boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage,
|
||||
boost::system::error_code& ec);
|
||||
private:
|
||||
unsigned int value_;
|
||||
};
|
||||
|
||||
/// Serial port option to permit changing the flow control.
|
||||
/**
|
||||
* Implements changing the flow control for a given serial port.
|
||||
*/
|
||||
class flow_control
|
||||
{
|
||||
public:
|
||||
enum type { none, software, hardware };
|
||||
explicit flow_control(type t = none);
|
||||
type value() const;
|
||||
boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage,
|
||||
boost::system::error_code& ec) const;
|
||||
boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage,
|
||||
boost::system::error_code& ec);
|
||||
private:
|
||||
type value_;
|
||||
};
|
||||
|
||||
/// Serial port option to permit changing the parity.
|
||||
/**
|
||||
* Implements changing the parity for a given serial port.
|
||||
*/
|
||||
class parity
|
||||
{
|
||||
public:
|
||||
enum type { none, odd, even };
|
||||
explicit parity(type t = none);
|
||||
type value() const;
|
||||
boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage,
|
||||
boost::system::error_code& ec) const;
|
||||
boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage,
|
||||
boost::system::error_code& ec);
|
||||
private:
|
||||
type value_;
|
||||
};
|
||||
|
||||
/// Serial port option to permit changing the number of stop bits.
|
||||
/**
|
||||
* Implements changing the number of stop bits for a given serial port.
|
||||
*/
|
||||
class stop_bits
|
||||
{
|
||||
public:
|
||||
enum type { one, onepointfive, two };
|
||||
explicit stop_bits(type t = one);
|
||||
type value() const;
|
||||
boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage,
|
||||
boost::system::error_code& ec) const;
|
||||
boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage,
|
||||
boost::system::error_code& ec);
|
||||
private:
|
||||
type value_;
|
||||
};
|
||||
|
||||
/// Serial port option to permit changing the character size.
|
||||
/**
|
||||
* Implements changing the character size for a given serial port.
|
||||
*/
|
||||
class character_size
|
||||
{
|
||||
public:
|
||||
explicit character_size(unsigned int t = 8);
|
||||
unsigned int value() const;
|
||||
boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage,
|
||||
boost::system::error_code& ec) const;
|
||||
boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage,
|
||||
boost::system::error_code& ec);
|
||||
private:
|
||||
unsigned int value_;
|
||||
};
|
||||
|
||||
protected:
|
||||
/// Protected destructor to prevent deletion through this type.
|
||||
~serial_port_base()
|
||||
{
|
||||
}
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
private:
|
||||
// Workaround to enable the empty base optimisation with Borland C++.
|
||||
char dummy_;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/impl/serial_port_base.ipp>
|
||||
|
||||
#undef BOOST_ASIO_OPTION_STORAGE
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_SERIAL_PORT_BASE_HPP
|
||||
224
include/boost/asio/serial_port_service.hpp
Normal file
224
include/boost/asio/serial_port_service.hpp
Normal file
@@ -0,0 +1,224 @@
|
||||
//
|
||||
// serial_port_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_SERIAL_PORT_SERVICE_HPP
|
||||
#define BOOST_ASIO_SERIAL_PORT_SERVICE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
#include <cstddef>
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/detail/service_base.hpp>
|
||||
#include <boost/asio/detail/reactive_serial_port_service.hpp>
|
||||
#include <boost/asio/detail/win_iocp_serial_port_service.hpp>
|
||||
|
||||
#if !defined(BOOST_ASIO_DISABLE_SERIAL_PORT)
|
||||
# if defined(BOOST_ASIO_HAS_IOCP) \
|
||||
|| !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
# define BOOST_ASIO_HAS_SERIAL_PORT 1
|
||||
# endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
#endif // !defined(BOOST_ASIO_DISABLE_STREAM_HANDLE)
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \
|
||||
|| defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
/// Default service implementation for a serial port.
|
||||
class serial_port_service
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
: public boost::asio::io_service::service
|
||||
#else
|
||||
: public boost::asio::detail::service_base<serial_port_service>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
/// The unique service identifier.
|
||||
static boost::asio::io_service::id id;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// The type of the platform-specific implementation.
|
||||
#if defined(BOOST_ASIO_HAS_IOCP)
|
||||
typedef detail::win_iocp_serial_port_service service_impl_type;
|
||||
#elif defined(BOOST_ASIO_HAS_EPOLL)
|
||||
typedef detail::reactive_serial_port_service<
|
||||
detail::epoll_reactor<false> > service_impl_type;
|
||||
#elif defined(BOOST_ASIO_HAS_KQUEUE)
|
||||
typedef detail::reactive_serial_port_service<
|
||||
detail::kqueue_reactor<false> > service_impl_type;
|
||||
#elif defined(BOOST_ASIO_HAS_DEV_POLL)
|
||||
typedef detail::reactive_serial_port_service<
|
||||
detail::dev_poll_reactor<false> > service_impl_type;
|
||||
#else
|
||||
typedef detail::reactive_serial_port_service<
|
||||
detail::select_reactor<false> > service_impl_type;
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// The type of a serial port implementation.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined implementation_type;
|
||||
#else
|
||||
typedef service_impl_type::implementation_type implementation_type;
|
||||
#endif
|
||||
|
||||
/// The native handle type.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined native_type;
|
||||
#else
|
||||
typedef service_impl_type::native_type native_type;
|
||||
#endif
|
||||
|
||||
/// Construct a new serial port service for the specified io_service.
|
||||
explicit serial_port_service(boost::asio::io_service& io_service)
|
||||
: boost::asio::detail::service_base<serial_port_service>(io_service),
|
||||
service_impl_(boost::asio::use_service<service_impl_type>(io_service))
|
||||
{
|
||||
}
|
||||
|
||||
/// Destroy all user-defined handler objects owned by the service.
|
||||
void shutdown_service()
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a new serial port implementation.
|
||||
void construct(implementation_type& impl)
|
||||
{
|
||||
service_impl_.construct(impl);
|
||||
}
|
||||
|
||||
/// Destroy a serial port implementation.
|
||||
void destroy(implementation_type& impl)
|
||||
{
|
||||
service_impl_.destroy(impl);
|
||||
}
|
||||
|
||||
/// Open a serial port.
|
||||
boost::system::error_code open(implementation_type& impl,
|
||||
const std::string& device, boost::system::error_code& ec)
|
||||
{
|
||||
return service_impl_.open(impl, device, ec);
|
||||
}
|
||||
|
||||
/// Assign an existing native handle to a serial port.
|
||||
boost::system::error_code assign(implementation_type& impl,
|
||||
const native_type& native_handle, boost::system::error_code& ec)
|
||||
{
|
||||
return service_impl_.assign(impl, native_handle, ec);
|
||||
}
|
||||
|
||||
/// Determine whether the handle is open.
|
||||
bool is_open(const implementation_type& impl) const
|
||||
{
|
||||
return service_impl_.is_open(impl);
|
||||
}
|
||||
|
||||
/// Close a serial port implementation.
|
||||
boost::system::error_code close(implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return service_impl_.close(impl, ec);
|
||||
}
|
||||
|
||||
/// Get the native handle implementation.
|
||||
native_type native(implementation_type& impl)
|
||||
{
|
||||
return service_impl_.native(impl);
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the handle.
|
||||
boost::system::error_code cancel(implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return service_impl_.cancel(impl, ec);
|
||||
}
|
||||
|
||||
/// Set a serial port option.
|
||||
template <typename SettableSerialPortOption>
|
||||
boost::system::error_code set_option(implementation_type& impl,
|
||||
const SettableSerialPortOption& option, boost::system::error_code& ec)
|
||||
{
|
||||
return service_impl_.set_option(impl, option, ec);
|
||||
}
|
||||
|
||||
/// Get a serial port option.
|
||||
template <typename GettableSerialPortOption>
|
||||
boost::system::error_code get_option(const implementation_type& impl,
|
||||
GettableSerialPortOption& option, boost::system::error_code& ec) const
|
||||
{
|
||||
return service_impl_.get_option(impl, option, ec);
|
||||
}
|
||||
|
||||
/// Send a break sequence to the serial port.
|
||||
boost::system::error_code send_break(implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return service_impl_.send_break(impl, ec);
|
||||
}
|
||||
|
||||
/// Write the given data to the stream.
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers, boost::system::error_code& ec)
|
||||
{
|
||||
return service_impl_.write_some(impl, buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous write.
|
||||
template <typename ConstBufferSequence, typename WriteHandler>
|
||||
void async_write_some(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers, WriteHandler handler)
|
||||
{
|
||||
service_impl_.async_write_some(impl, buffers, handler);
|
||||
}
|
||||
|
||||
/// Read some data from the stream.
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, boost::system::error_code& ec)
|
||||
{
|
||||
return service_impl_.read_some(impl, buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous read.
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
void async_read_some(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, ReadHandler handler)
|
||||
{
|
||||
service_impl_.async_read_some(impl, buffers, handler);
|
||||
}
|
||||
|
||||
private:
|
||||
// The service that provides the platform-specific implementation.
|
||||
service_impl_type& service_impl_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
|
||||
// || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_SERIAL_PORT_SERVICE_HPP
|
||||
Reference in New Issue
Block a user