basic_serial_port.hpp 33 KB

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