basic_serial_port.hpp 31 KB

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