basic_serial_port.hpp 30 KB

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