basic_serial_port.hpp 34 KB

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