1 // 2 // basic_serial_port.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) 7 // 8 // Distributed under the Boost Software License, Version 1.0. (See accompanying 9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 10 // 11 12 #ifndef BOOST_ASIO_BASIC_SERIAL_PORT_HPP 13 #define BOOST_ASIO_BASIC_SERIAL_PORT_HPP 14 15 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 16 # pragma once 17 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 18 19 #include <boost/asio/detail/config.hpp> 20 21 #if defined(BOOST_ASIO_HAS_SERIAL_PORT) \ 22 || defined(GENERATING_DOCUMENTATION) 23 24 #include <string> 25 #include <boost/asio/any_io_executor.hpp> 26 #include <boost/asio/async_result.hpp> 27 #include <boost/asio/detail/handler_type_requirements.hpp> 28 #include <boost/asio/detail/io_object_impl.hpp> 29 #include <boost/asio/detail/non_const_lvalue.hpp> 30 #include <boost/asio/detail/throw_error.hpp> 31 #include <boost/asio/detail/type_traits.hpp> 32 #include <boost/asio/error.hpp> 33 #include <boost/asio/execution_context.hpp> 34 #include <boost/asio/serial_port_base.hpp> 35 #if defined(BOOST_ASIO_HAS_IOCP) 36 # include <boost/asio/detail/win_iocp_serial_port_service.hpp> 37 #else 38 # include <boost/asio/detail/reactive_serial_port_service.hpp> 39 #endif 40 41 #if defined(BOOST_ASIO_HAS_MOVE) 42 # include <utility> 43 #endif // defined(BOOST_ASIO_HAS_MOVE) 44 45 #include <boost/asio/detail/push_options.hpp> 46 47 namespace boost { 48 namespace asio { 49 50 /// Provides serial port functionality. 51 /** 52 * The basic_serial_port class provides a wrapper over serial port 53 * functionality. 54 * 55 * @par Thread Safety 56 * @e Distinct @e objects: Safe.@n 57 * @e Shared @e objects: Unsafe. 58 */ 59 template <typename Executor = any_io_executor> 60 class basic_serial_port 61 : public serial_port_base 62 { 63 public: 64 /// The type of the executor associated with the object. 65 typedef Executor executor_type; 66 67 /// Rebinds the serial port type to another executor. 68 template <typename Executor1> 69 struct rebind_executor 70 { 71 /// The serial port type when rebound to the specified executor. 72 typedef basic_serial_port<Executor1> other; 73 }; 74 75 /// The native representation of a serial port. 76 #if defined(GENERATING_DOCUMENTATION) 77 typedef implementation_defined native_handle_type; 78 #elif defined(BOOST_ASIO_HAS_IOCP) 79 typedef detail::win_iocp_serial_port_service::native_handle_type 80 native_handle_type; 81 #else 82 typedef detail::reactive_serial_port_service::native_handle_type 83 native_handle_type; 84 #endif 85 86 /// A basic_basic_serial_port is always the lowest layer. 87 typedef basic_serial_port lowest_layer_type; 88 89 /// Construct a basic_serial_port without opening it. 90 /** 91 * This constructor creates a serial port without opening it. 92 * 93 * @param ex The I/O executor that the serial port will use, by default, to 94 * dispatch handlers for any asynchronous operations performed on the 95 * serial port. 96 */ basic_serial_port(const executor_type & ex)97 explicit basic_serial_port(const executor_type& ex) 98 : impl_(ex) 99 { 100 } 101 102 /// Construct a basic_serial_port without opening it. 103 /** 104 * This constructor creates a serial port without opening it. 105 * 106 * @param context An execution context which provides the I/O executor that 107 * the serial port will use, by default, to dispatch handlers for any 108 * asynchronous operations performed on the serial port. 109 */ 110 template <typename ExecutionContext> basic_serial_port(ExecutionContext & context,typename enable_if<is_convertible<ExecutionContext &,execution_context &>::value,basic_serial_port>::type * =0)111 explicit basic_serial_port(ExecutionContext& context, 112 typename enable_if< 113 is_convertible<ExecutionContext&, execution_context&>::value, 114 basic_serial_port 115 >::type* = 0) 116 : impl_(context) 117 { 118 } 119 120 /// Construct and open a basic_serial_port. 121 /** 122 * This constructor creates and opens a serial port for the specified device 123 * name. 124 * 125 * @param ex The I/O executor that the serial port will use, by default, to 126 * dispatch handlers for any asynchronous operations performed on the 127 * serial port. 128 * 129 * @param device The platform-specific device name for this serial 130 * port. 131 */ basic_serial_port(const executor_type & ex,const char * device)132 basic_serial_port(const executor_type& ex, const char* device) 133 : impl_(ex) 134 { 135 boost::system::error_code ec; 136 impl_.get_service().open(impl_.get_implementation(), device, ec); 137 boost::asio::detail::throw_error(ec, "open"); 138 } 139 140 /// Construct and open a basic_serial_port. 141 /** 142 * This constructor creates and opens a serial port for the specified device 143 * name. 144 * 145 * @param context An execution context which provides the I/O executor that 146 * the serial port will use, by default, to dispatch handlers for any 147 * asynchronous operations performed on the serial port. 148 * 149 * @param device The platform-specific device name for this serial 150 * port. 151 */ 152 template <typename ExecutionContext> basic_serial_port(ExecutionContext & context,const char * device,typename enable_if<is_convertible<ExecutionContext &,execution_context &>::value>::type * =0)153 basic_serial_port(ExecutionContext& context, const char* device, 154 typename enable_if< 155 is_convertible<ExecutionContext&, execution_context&>::value 156 >::type* = 0) 157 : impl_(context) 158 { 159 boost::system::error_code ec; 160 impl_.get_service().open(impl_.get_implementation(), device, ec); 161 boost::asio::detail::throw_error(ec, "open"); 162 } 163 164 /// Construct and open a basic_serial_port. 165 /** 166 * This constructor creates and opens a serial port for the specified device 167 * name. 168 * 169 * @param ex The I/O executor that the serial port will use, by default, to 170 * dispatch handlers for any asynchronous operations performed on the 171 * serial port. 172 * 173 * @param device The platform-specific device name for this serial 174 * port. 175 */ basic_serial_port(const executor_type & ex,const std::string & device)176 basic_serial_port(const executor_type& ex, const std::string& device) 177 : impl_(ex) 178 { 179 boost::system::error_code ec; 180 impl_.get_service().open(impl_.get_implementation(), device, ec); 181 boost::asio::detail::throw_error(ec, "open"); 182 } 183 184 /// Construct and open a basic_serial_port. 185 /** 186 * This constructor creates and opens a serial port for the specified device 187 * name. 188 * 189 * @param context An execution context which provides the I/O executor that 190 * the serial port will use, by default, to dispatch handlers for any 191 * asynchronous operations performed on the serial port. 192 * 193 * @param device The platform-specific device name for this serial 194 * port. 195 */ 196 template <typename ExecutionContext> basic_serial_port(ExecutionContext & context,const std::string & device,typename enable_if<is_convertible<ExecutionContext &,execution_context &>::value>::type * =0)197 basic_serial_port(ExecutionContext& context, const std::string& device, 198 typename enable_if< 199 is_convertible<ExecutionContext&, execution_context&>::value 200 >::type* = 0) 201 : impl_(context) 202 { 203 boost::system::error_code ec; 204 impl_.get_service().open(impl_.get_implementation(), device, ec); 205 boost::asio::detail::throw_error(ec, "open"); 206 } 207 208 /// Construct a basic_serial_port on an existing native serial port. 209 /** 210 * This constructor creates a serial port object to hold an existing native 211 * serial port. 212 * 213 * @param ex The I/O executor that the serial port will use, by default, to 214 * dispatch handlers for any asynchronous operations performed on the 215 * serial port. 216 * 217 * @param native_serial_port A native serial port. 218 * 219 * @throws boost::system::system_error Thrown on failure. 220 */ basic_serial_port(const executor_type & ex,const native_handle_type & native_serial_port)221 basic_serial_port(const executor_type& ex, 222 const native_handle_type& native_serial_port) 223 : impl_(ex) 224 { 225 boost::system::error_code ec; 226 impl_.get_service().assign(impl_.get_implementation(), 227 native_serial_port, ec); 228 boost::asio::detail::throw_error(ec, "assign"); 229 } 230 231 /// Construct a basic_serial_port on an existing native serial port. 232 /** 233 * This constructor creates a serial port object to hold an existing native 234 * serial port. 235 * 236 * @param context An execution context which provides the I/O executor that 237 * the serial port will use, by default, to dispatch handlers for any 238 * asynchronous operations performed on the serial port. 239 * 240 * @param native_serial_port A native serial port. 241 * 242 * @throws boost::system::system_error Thrown on failure. 243 */ 244 template <typename ExecutionContext> basic_serial_port(ExecutionContext & context,const native_handle_type & native_serial_port,typename enable_if<is_convertible<ExecutionContext &,execution_context &>::value>::type * =0)245 basic_serial_port(ExecutionContext& context, 246 const native_handle_type& native_serial_port, 247 typename enable_if< 248 is_convertible<ExecutionContext&, execution_context&>::value 249 >::type* = 0) 250 : impl_(context) 251 { 252 boost::system::error_code ec; 253 impl_.get_service().assign(impl_.get_implementation(), 254 native_serial_port, ec); 255 boost::asio::detail::throw_error(ec, "assign"); 256 } 257 258 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 259 /// Move-construct a basic_serial_port from another. 260 /** 261 * This constructor moves a serial port from one object to another. 262 * 263 * @param other The other basic_serial_port object from which the move will 264 * occur. 265 * 266 * @note Following the move, the moved-from object is in the same state as if 267 * constructed using the @c basic_serial_port(const executor_type&) 268 * constructor. 269 */ basic_serial_port(basic_serial_port && other)270 basic_serial_port(basic_serial_port&& other) 271 : impl_(std::move(other.impl_)) 272 { 273 } 274 275 /// Move-assign a basic_serial_port from another. 276 /** 277 * This assignment operator moves a serial port from one object to another. 278 * 279 * @param other The other basic_serial_port object from which the move will 280 * occur. 281 * 282 * @note Following the move, the moved-from object is in the same state as if 283 * constructed using the @c basic_serial_port(const executor_type&) 284 * constructor. 285 */ operator =(basic_serial_port && other)286 basic_serial_port& operator=(basic_serial_port&& other) 287 { 288 impl_ = std::move(other.impl_); 289 return *this; 290 } 291 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 292 293 /// Destroys the serial port. 294 /** 295 * This function destroys the serial port, cancelling any outstanding 296 * asynchronous wait operations associated with the serial port as if by 297 * calling @c cancel. 298 */ ~basic_serial_port()299 ~basic_serial_port() 300 { 301 } 302 303 /// Get the executor associated with the object. get_executor()304 executor_type get_executor() BOOST_ASIO_NOEXCEPT 305 { 306 return impl_.get_executor(); 307 } 308 309 /// Get a reference to the lowest layer. 310 /** 311 * This function returns a reference to the lowest layer in a stack of 312 * layers. Since a basic_serial_port cannot contain any further layers, it 313 * simply returns a reference to itself. 314 * 315 * @return A reference to the lowest layer in the stack of layers. Ownership 316 * is not transferred to the caller. 317 */ lowest_layer()318 lowest_layer_type& lowest_layer() 319 { 320 return *this; 321 } 322 323 /// Get a const reference to the lowest layer. 324 /** 325 * This function returns a const reference to the lowest layer in a stack of 326 * layers. Since a basic_serial_port cannot contain any further layers, it 327 * simply returns a reference to itself. 328 * 329 * @return A const reference to the lowest layer in the stack of layers. 330 * Ownership is not transferred to the caller. 331 */ lowest_layer() const332 const lowest_layer_type& lowest_layer() const 333 { 334 return *this; 335 } 336 337 /// Open the serial port using the specified device name. 338 /** 339 * This function opens the serial port for the specified device name. 340 * 341 * @param device The platform-specific device name. 342 * 343 * @throws boost::system::system_error Thrown on failure. 344 */ open(const std::string & device)345 void open(const std::string& device) 346 { 347 boost::system::error_code ec; 348 impl_.get_service().open(impl_.get_implementation(), device, ec); 349 boost::asio::detail::throw_error(ec, "open"); 350 } 351 352 /// Open the serial port using the specified device name. 353 /** 354 * This function opens the serial port using the given platform-specific 355 * device name. 356 * 357 * @param device The platform-specific device name. 358 * 359 * @param ec Set the indicate what error occurred, if any. 360 */ open(const std::string & device,boost::system::error_code & ec)361 BOOST_ASIO_SYNC_OP_VOID open(const std::string& device, 362 boost::system::error_code& ec) 363 { 364 impl_.get_service().open(impl_.get_implementation(), device, ec); 365 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 366 } 367 368 /// Assign an existing native serial port to the serial port. 369 /* 370 * This function opens the serial port to hold an existing native serial port. 371 * 372 * @param native_serial_port A native serial port. 373 * 374 * @throws boost::system::system_error Thrown on failure. 375 */ assign(const native_handle_type & native_serial_port)376 void assign(const native_handle_type& native_serial_port) 377 { 378 boost::system::error_code ec; 379 impl_.get_service().assign(impl_.get_implementation(), 380 native_serial_port, ec); 381 boost::asio::detail::throw_error(ec, "assign"); 382 } 383 384 /// Assign an existing native serial port to the serial port. 385 /* 386 * This function opens the serial port to hold an existing native serial port. 387 * 388 * @param native_serial_port A native serial port. 389 * 390 * @param ec Set to indicate what error occurred, if any. 391 */ assign(const native_handle_type & native_serial_port,boost::system::error_code & ec)392 BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_serial_port, 393 boost::system::error_code& ec) 394 { 395 impl_.get_service().assign(impl_.get_implementation(), 396 native_serial_port, ec); 397 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 398 } 399 400 /// Determine whether the serial port is open. is_open() const401 bool is_open() const 402 { 403 return impl_.get_service().is_open(impl_.get_implementation()); 404 } 405 406 /// Close the serial port. 407 /** 408 * This function is used to close the serial port. Any asynchronous read or 409 * write operations will be cancelled immediately, and will complete with the 410 * boost::asio::error::operation_aborted error. 411 * 412 * @throws boost::system::system_error Thrown on failure. 413 */ close()414 void close() 415 { 416 boost::system::error_code ec; 417 impl_.get_service().close(impl_.get_implementation(), ec); 418 boost::asio::detail::throw_error(ec, "close"); 419 } 420 421 /// Close the serial port. 422 /** 423 * This function is used to close the serial port. Any asynchronous read or 424 * write operations will be cancelled immediately, and will complete with the 425 * boost::asio::error::operation_aborted error. 426 * 427 * @param ec Set to indicate what error occurred, if any. 428 */ close(boost::system::error_code & ec)429 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) 430 { 431 impl_.get_service().close(impl_.get_implementation(), ec); 432 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 433 } 434 435 /// Get the native serial port representation. 436 /** 437 * This function may be used to obtain the underlying representation of the 438 * serial port. This is intended to allow access to native serial port 439 * functionality that is not otherwise provided. 440 */ native_handle()441 native_handle_type native_handle() 442 { 443 return impl_.get_service().native_handle(impl_.get_implementation()); 444 } 445 446 /// Cancel all asynchronous operations associated with the serial port. 447 /** 448 * This function causes all outstanding asynchronous read or write operations 449 * to finish immediately, and the handlers for cancelled operations will be 450 * passed the boost::asio::error::operation_aborted error. 451 * 452 * @throws boost::system::system_error Thrown on failure. 453 */ cancel()454 void cancel() 455 { 456 boost::system::error_code ec; 457 impl_.get_service().cancel(impl_.get_implementation(), ec); 458 boost::asio::detail::throw_error(ec, "cancel"); 459 } 460 461 /// Cancel all asynchronous operations associated with the serial port. 462 /** 463 * This function causes all outstanding asynchronous read or write operations 464 * to finish immediately, and the handlers for cancelled operations will be 465 * passed the boost::asio::error::operation_aborted error. 466 * 467 * @param ec Set to indicate what error occurred, if any. 468 */ cancel(boost::system::error_code & ec)469 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) 470 { 471 impl_.get_service().cancel(impl_.get_implementation(), ec); 472 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 473 } 474 475 /// Send a break sequence to the serial port. 476 /** 477 * This function causes a break sequence of platform-specific duration to be 478 * sent out the serial port. 479 * 480 * @throws boost::system::system_error Thrown on failure. 481 */ send_break()482 void send_break() 483 { 484 boost::system::error_code ec; 485 impl_.get_service().send_break(impl_.get_implementation(), ec); 486 boost::asio::detail::throw_error(ec, "send_break"); 487 } 488 489 /// Send a break sequence to the serial port. 490 /** 491 * This function causes a break sequence of platform-specific duration to be 492 * sent out the serial port. 493 * 494 * @param ec Set to indicate what error occurred, if any. 495 */ send_break(boost::system::error_code & ec)496 BOOST_ASIO_SYNC_OP_VOID send_break(boost::system::error_code& ec) 497 { 498 impl_.get_service().send_break(impl_.get_implementation(), ec); 499 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 500 } 501 502 /// Set an option on the serial port. 503 /** 504 * This function is used to set an option on the serial port. 505 * 506 * @param option The option value to be set on the serial port. 507 * 508 * @throws boost::system::system_error Thrown on failure. 509 * 510 * @sa SettableSerialPortOption @n 511 * boost::asio::serial_port_base::baud_rate @n 512 * boost::asio::serial_port_base::flow_control @n 513 * boost::asio::serial_port_base::parity @n 514 * boost::asio::serial_port_base::stop_bits @n 515 * boost::asio::serial_port_base::character_size 516 */ 517 template <typename SettableSerialPortOption> set_option(const SettableSerialPortOption & option)518 void set_option(const SettableSerialPortOption& option) 519 { 520 boost::system::error_code ec; 521 impl_.get_service().set_option(impl_.get_implementation(), option, ec); 522 boost::asio::detail::throw_error(ec, "set_option"); 523 } 524 525 /// Set an option on the serial port. 526 /** 527 * This function is used to set an option on the serial port. 528 * 529 * @param option The option value to be set on the serial port. 530 * 531 * @param ec Set to indicate what error occurred, if any. 532 * 533 * @sa SettableSerialPortOption @n 534 * boost::asio::serial_port_base::baud_rate @n 535 * boost::asio::serial_port_base::flow_control @n 536 * boost::asio::serial_port_base::parity @n 537 * boost::asio::serial_port_base::stop_bits @n 538 * boost::asio::serial_port_base::character_size 539 */ 540 template <typename SettableSerialPortOption> set_option(const SettableSerialPortOption & option,boost::system::error_code & ec)541 BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSerialPortOption& option, 542 boost::system::error_code& ec) 543 { 544 impl_.get_service().set_option(impl_.get_implementation(), option, ec); 545 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 546 } 547 548 /// Get an option from the serial port. 549 /** 550 * This function is used to get the current value of an option on the serial 551 * port. 552 * 553 * @param option The option value to be obtained from the serial port. 554 * 555 * @throws boost::system::system_error Thrown on failure. 556 * 557 * @sa GettableSerialPortOption @n 558 * boost::asio::serial_port_base::baud_rate @n 559 * boost::asio::serial_port_base::flow_control @n 560 * boost::asio::serial_port_base::parity @n 561 * boost::asio::serial_port_base::stop_bits @n 562 * boost::asio::serial_port_base::character_size 563 */ 564 template <typename GettableSerialPortOption> get_option(GettableSerialPortOption & option) const565 void get_option(GettableSerialPortOption& option) const 566 { 567 boost::system::error_code ec; 568 impl_.get_service().get_option(impl_.get_implementation(), option, ec); 569 boost::asio::detail::throw_error(ec, "get_option"); 570 } 571 572 /// Get an option from the serial port. 573 /** 574 * This function is used to get the current value of an option on the serial 575 * port. 576 * 577 * @param option The option value to be obtained from the serial port. 578 * 579 * @param ec Set to indicate what error occurred, if any. 580 * 581 * @sa GettableSerialPortOption @n 582 * boost::asio::serial_port_base::baud_rate @n 583 * boost::asio::serial_port_base::flow_control @n 584 * boost::asio::serial_port_base::parity @n 585 * boost::asio::serial_port_base::stop_bits @n 586 * boost::asio::serial_port_base::character_size 587 */ 588 template <typename GettableSerialPortOption> get_option(GettableSerialPortOption & option,boost::system::error_code & ec) const589 BOOST_ASIO_SYNC_OP_VOID get_option(GettableSerialPortOption& option, 590 boost::system::error_code& ec) const 591 { 592 impl_.get_service().get_option(impl_.get_implementation(), option, ec); 593 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 594 } 595 596 /// Write some data to the serial port. 597 /** 598 * This function is used to write data to the serial port. The function call 599 * will block until one or more bytes of the data has been written 600 * successfully, or until an error occurs. 601 * 602 * @param buffers One or more data buffers to be written to the serial port. 603 * 604 * @returns The number of bytes written. 605 * 606 * @throws boost::system::system_error Thrown on failure. An error code of 607 * boost::asio::error::eof indicates that the connection was closed by the 608 * peer. 609 * 610 * @note The write_some operation may not transmit all of the data to the 611 * peer. Consider using the @ref write function if you need to ensure that 612 * all data is written before the blocking operation completes. 613 * 614 * @par Example 615 * To write a single data buffer use the @ref buffer function as follows: 616 * @code 617 * basic_serial_port.write_some(boost::asio::buffer(data, size)); 618 * @endcode 619 * See the @ref buffer documentation for information on writing multiple 620 * buffers in one go, and how to use it with arrays, boost::array or 621 * std::vector. 622 */ 623 template <typename ConstBufferSequence> write_some(const ConstBufferSequence & buffers)624 std::size_t write_some(const ConstBufferSequence& buffers) 625 { 626 boost::system::error_code ec; 627 std::size_t s = impl_.get_service().write_some( 628 impl_.get_implementation(), buffers, ec); 629 boost::asio::detail::throw_error(ec, "write_some"); 630 return s; 631 } 632 633 /// Write some data to the serial port. 634 /** 635 * This function is used to write data to the serial port. The function call 636 * will block until one or more bytes of the data has been written 637 * successfully, or until an error occurs. 638 * 639 * @param buffers One or more data buffers to be written to the serial port. 640 * 641 * @param ec Set to indicate what error occurred, if any. 642 * 643 * @returns The number of bytes written. Returns 0 if an error occurred. 644 * 645 * @note The write_some operation may not transmit all of the data to the 646 * peer. Consider using the @ref write function if you need to ensure that 647 * all data is written before the blocking operation completes. 648 */ 649 template <typename ConstBufferSequence> write_some(const ConstBufferSequence & buffers,boost::system::error_code & ec)650 std::size_t write_some(const ConstBufferSequence& buffers, 651 boost::system::error_code& ec) 652 { 653 return impl_.get_service().write_some( 654 impl_.get_implementation(), buffers, ec); 655 } 656 657 /// Start an asynchronous write. 658 /** 659 * This function is used to asynchronously write data to the serial port. 660 * The function call always returns immediately. 661 * 662 * @param buffers One or more data buffers to be written to the serial port. 663 * Although the buffers object may be copied as necessary, ownership of the 664 * underlying memory blocks is retained by the caller, which must guarantee 665 * that they remain valid until the handler is called. 666 * 667 * @param handler The handler to be called when the write operation completes. 668 * Copies will be made of the handler as required. The function signature of 669 * the handler must be: 670 * @code void handler( 671 * const boost::system::error_code& error, // Result of operation. 672 * std::size_t bytes_transferred // Number of bytes written. 673 * ); @endcode 674 * Regardless of whether the asynchronous operation completes immediately or 675 * not, the handler will not be invoked from within this function. On 676 * immediate completion, invocation of the handler will be performed in a 677 * manner equivalent to using boost::asio::post(). 678 * 679 * @note The write operation may not transmit all of the data to the peer. 680 * Consider using the @ref async_write function if you need to ensure that all 681 * data is written before the asynchronous operation completes. 682 * 683 * @par Example 684 * To write a single data buffer use the @ref buffer function as follows: 685 * @code 686 * basic_serial_port.async_write_some( 687 * boost::asio::buffer(data, size), handler); 688 * @endcode 689 * See the @ref buffer documentation for information on writing multiple 690 * buffers in one go, and how to use it with arrays, boost::array or 691 * std::vector. 692 */ 693 template <typename ConstBufferSequence, 694 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 695 std::size_t)) WriteHandler 696 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,void (boost::system::error_code,std::size_t))697 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, 698 void (boost::system::error_code, std::size_t)) 699 async_write_some(const ConstBufferSequence& buffers, 700 BOOST_ASIO_MOVE_ARG(WriteHandler) handler 701 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 702 { 703 return async_initiate<WriteHandler, 704 void (boost::system::error_code, std::size_t)>( 705 initiate_async_write_some(this), handler, buffers); 706 } 707 708 /// Read some data from the serial port. 709 /** 710 * This function is used to read data from the serial port. The function 711 * call will block until one or more bytes of data has been read successfully, 712 * or until an error occurs. 713 * 714 * @param buffers One or more buffers into which the data will be read. 715 * 716 * @returns The number of bytes read. 717 * 718 * @throws boost::system::system_error Thrown on failure. An error code of 719 * boost::asio::error::eof indicates that the connection was closed by the 720 * peer. 721 * 722 * @note The read_some operation may not read all of the requested number of 723 * bytes. Consider using the @ref read function if you need to ensure that 724 * the requested amount of data is read before the blocking operation 725 * completes. 726 * 727 * @par Example 728 * To read into a single data buffer use the @ref buffer function as follows: 729 * @code 730 * basic_serial_port.read_some(boost::asio::buffer(data, size)); 731 * @endcode 732 * See the @ref buffer documentation for information on reading into multiple 733 * buffers in one go, and how to use it with arrays, boost::array or 734 * std::vector. 735 */ 736 template <typename MutableBufferSequence> read_some(const MutableBufferSequence & buffers)737 std::size_t read_some(const MutableBufferSequence& buffers) 738 { 739 boost::system::error_code ec; 740 std::size_t s = impl_.get_service().read_some( 741 impl_.get_implementation(), buffers, ec); 742 boost::asio::detail::throw_error(ec, "read_some"); 743 return s; 744 } 745 746 /// Read some data from the serial port. 747 /** 748 * This function is used to read data from the serial port. The function 749 * call will block until one or more bytes of data has been read successfully, 750 * or until an error occurs. 751 * 752 * @param buffers One or more buffers into which the data will be read. 753 * 754 * @param ec Set to indicate what error occurred, if any. 755 * 756 * @returns The number of bytes read. Returns 0 if an error occurred. 757 * 758 * @note The read_some operation may not read all of the requested number of 759 * bytes. Consider using the @ref read function if you need to ensure that 760 * the requested amount of data is read before the blocking operation 761 * completes. 762 */ 763 template <typename MutableBufferSequence> read_some(const MutableBufferSequence & buffers,boost::system::error_code & ec)764 std::size_t read_some(const MutableBufferSequence& buffers, 765 boost::system::error_code& ec) 766 { 767 return impl_.get_service().read_some( 768 impl_.get_implementation(), buffers, ec); 769 } 770 771 /// Start an asynchronous read. 772 /** 773 * This function is used to asynchronously read data from the serial port. 774 * The function call always returns immediately. 775 * 776 * @param buffers One or more buffers into which the data will be read. 777 * Although the buffers object may be copied as necessary, ownership of the 778 * underlying memory blocks is retained by the caller, which must guarantee 779 * that they remain valid until the handler is called. 780 * 781 * @param handler The handler to be called when the read operation completes. 782 * Copies will be made of the handler as required. The function signature of 783 * the handler must be: 784 * @code void handler( 785 * const boost::system::error_code& error, // Result of operation. 786 * std::size_t bytes_transferred // Number of bytes read. 787 * ); @endcode 788 * Regardless of whether the asynchronous operation completes immediately or 789 * not, the handler will not be invoked from within this function. On 790 * immediate completion, invocation of the handler will be performed in a 791 * manner equivalent to using boost::asio::post(). 792 * 793 * @note The read operation may not read all of the requested number of bytes. 794 * Consider using the @ref async_read function if you need to ensure that the 795 * requested amount of data is read before the asynchronous operation 796 * completes. 797 * 798 * @par Example 799 * To read into a single data buffer use the @ref buffer function as follows: 800 * @code 801 * basic_serial_port.async_read_some( 802 * boost::asio::buffer(data, size), handler); 803 * @endcode 804 * See the @ref buffer documentation for information on reading into multiple 805 * buffers in one go, and how to use it with arrays, boost::array or 806 * std::vector. 807 */ 808 template <typename MutableBufferSequence, 809 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 810 std::size_t)) ReadHandler 811 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))812 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, 813 void (boost::system::error_code, std::size_t)) 814 async_read_some(const MutableBufferSequence& buffers, 815 BOOST_ASIO_MOVE_ARG(ReadHandler) handler 816 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 817 { 818 return async_initiate<ReadHandler, 819 void (boost::system::error_code, std::size_t)>( 820 initiate_async_read_some(this), handler, buffers); 821 } 822 823 private: 824 // Disallow copying and assignment. 825 basic_serial_port(const basic_serial_port&) BOOST_ASIO_DELETED; 826 basic_serial_port& operator=(const basic_serial_port&) BOOST_ASIO_DELETED; 827 828 class initiate_async_write_some 829 { 830 public: 831 typedef Executor executor_type; 832 initiate_async_write_some(basic_serial_port * self)833 explicit initiate_async_write_some(basic_serial_port* self) 834 : self_(self) 835 { 836 } 837 get_executor() const838 executor_type get_executor() const BOOST_ASIO_NOEXCEPT 839 { 840 return self_->get_executor(); 841 } 842 843 template <typename WriteHandler, typename ConstBufferSequence> operator ()(BOOST_ASIO_MOVE_ARG (WriteHandler)handler,const ConstBufferSequence & buffers) const844 void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, 845 const ConstBufferSequence& buffers) const 846 { 847 // If you get an error on the following line it means that your handler 848 // does not meet the documented type requirements for a WriteHandler. 849 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; 850 851 detail::non_const_lvalue<WriteHandler> handler2(handler); 852 self_->impl_.get_service().async_write_some( 853 self_->impl_.get_implementation(), buffers, 854 handler2.value, self_->impl_.get_executor()); 855 } 856 857 private: 858 basic_serial_port* self_; 859 }; 860 861 class initiate_async_read_some 862 { 863 public: 864 typedef Executor executor_type; 865 initiate_async_read_some(basic_serial_port * self)866 explicit initiate_async_read_some(basic_serial_port* self) 867 : self_(self) 868 { 869 } 870 get_executor() const871 executor_type get_executor() const BOOST_ASIO_NOEXCEPT 872 { 873 return self_->get_executor(); 874 } 875 876 template <typename ReadHandler, typename MutableBufferSequence> operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,const MutableBufferSequence & buffers) const877 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, 878 const MutableBufferSequence& buffers) const 879 { 880 // If you get an error on the following line it means that your handler 881 // does not meet the documented type requirements for a ReadHandler. 882 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; 883 884 detail::non_const_lvalue<ReadHandler> handler2(handler); 885 self_->impl_.get_service().async_read_some( 886 self_->impl_.get_implementation(), buffers, 887 handler2.value, self_->impl_.get_executor()); 888 } 889 890 private: 891 basic_serial_port* self_; 892 }; 893 894 #if defined(BOOST_ASIO_HAS_IOCP) 895 detail::io_object_impl<detail::win_iocp_serial_port_service, Executor> impl_; 896 #else 897 detail::io_object_impl<detail::reactive_serial_port_service, Executor> impl_; 898 #endif 899 }; 900 901 } // namespace asio 902 } // namespace boost 903 904 #include <boost/asio/detail/pop_options.hpp> 905 906 #endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) 907 // || defined(GENERATING_DOCUMENTATION) 908 909 #endif // BOOST_ASIO_BASIC_SERIAL_PORT_HPP 910