basic_serial_port.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. //
  2. // basic_serial_port.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2011 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 "asio/basic_io_object.hpp"
  21. #include "asio/detail/throw_error.hpp"
  22. #include "asio/error.hpp"
  23. #include "asio/serial_port_base.hpp"
  24. #include "asio/serial_port_service.hpp"
  25. #include "asio/detail/push_options.hpp"
  26. namespace asio {
  27. /// Provides serial port functionality.
  28. /**
  29. * The basic_serial_port class template provides functionality that is common
  30. * to all serial ports.
  31. *
  32. * @par Thread Safety
  33. * @e Distinct @e objects: Safe.@n
  34. * @e Shared @e objects: Unsafe.
  35. */
  36. template <typename SerialPortService = serial_port_service>
  37. class basic_serial_port
  38. : public basic_io_object<SerialPortService>,
  39. public serial_port_base
  40. {
  41. public:
  42. /// The native representation of a serial port.
  43. typedef typename SerialPortService::native_type native_type;
  44. /// A basic_serial_port is always the lowest layer.
  45. typedef basic_serial_port<SerialPortService> lowest_layer_type;
  46. /// Construct a basic_serial_port without opening it.
  47. /**
  48. * This constructor creates a serial port without opening it.
  49. *
  50. * @param io_service The io_service object that the serial port will use to
  51. * dispatch handlers for any asynchronous operations performed on the port.
  52. */
  53. explicit basic_serial_port(asio::io_service& io_service)
  54. : basic_io_object<SerialPortService>(io_service)
  55. {
  56. }
  57. /// Construct and open a basic_serial_port.
  58. /**
  59. * This constructor creates and opens a serial port for the specified device
  60. * name.
  61. *
  62. * @param io_service The io_service object that the serial port will use to
  63. * dispatch handlers for any asynchronous operations performed on the port.
  64. *
  65. * @param device The platform-specific device name for this serial
  66. * port.
  67. */
  68. explicit basic_serial_port(asio::io_service& io_service,
  69. const char* device)
  70. : basic_io_object<SerialPortService>(io_service)
  71. {
  72. asio::error_code ec;
  73. this->service.open(this->implementation, device, ec);
  74. asio::detail::throw_error(ec);
  75. }
  76. /// Construct and open a basic_serial_port.
  77. /**
  78. * This constructor creates and opens a serial port for the specified device
  79. * name.
  80. *
  81. * @param io_service The io_service object that the serial port will use to
  82. * dispatch handlers for any asynchronous operations performed on the port.
  83. *
  84. * @param device The platform-specific device name for this serial
  85. * port.
  86. */
  87. explicit basic_serial_port(asio::io_service& io_service,
  88. const std::string& device)
  89. : basic_io_object<SerialPortService>(io_service)
  90. {
  91. asio::error_code ec;
  92. this->service.open(this->implementation, device, ec);
  93. asio::detail::throw_error(ec);
  94. }
  95. /// Construct a basic_serial_port on an existing native serial port.
  96. /**
  97. * This constructor creates a serial port object to hold an existing native
  98. * serial port.
  99. *
  100. * @param io_service The io_service object that the serial port will use to
  101. * dispatch handlers for any asynchronous operations performed on the port.
  102. *
  103. * @param native_serial_port A native serial port.
  104. *
  105. * @throws asio::system_error Thrown on failure.
  106. */
  107. basic_serial_port(asio::io_service& io_service,
  108. const native_type& native_serial_port)
  109. : basic_io_object<SerialPortService>(io_service)
  110. {
  111. asio::error_code ec;
  112. this->service.assign(this->implementation, native_serial_port, ec);
  113. asio::detail::throw_error(ec);
  114. }
  115. /// Get a reference to the lowest layer.
  116. /**
  117. * This function returns a reference to the lowest layer in a stack of
  118. * layers. Since a basic_serial_port cannot contain any further layers, it
  119. * simply returns a reference to itself.
  120. *
  121. * @return A reference to the lowest layer in the stack of layers. Ownership
  122. * is not transferred to the caller.
  123. */
  124. lowest_layer_type& lowest_layer()
  125. {
  126. return *this;
  127. }
  128. /// Get a const reference to the lowest layer.
  129. /**
  130. * This function returns a const reference to the lowest layer in a stack of
  131. * layers. Since a basic_serial_port cannot contain any further layers, it
  132. * simply returns a reference to itself.
  133. *
  134. * @return A const reference to the lowest layer in the stack of layers.
  135. * Ownership is not transferred to the caller.
  136. */
  137. const lowest_layer_type& lowest_layer() const
  138. {
  139. return *this;
  140. }
  141. /// Open the serial port using the specified device name.
  142. /**
  143. * This function opens the serial port for the specified device name.
  144. *
  145. * @param device The platform-specific device name.
  146. *
  147. * @throws asio::system_error Thrown on failure.
  148. */
  149. void open(const std::string& device)
  150. {
  151. asio::error_code ec;
  152. this->service.open(this->implementation, device, ec);
  153. asio::detail::throw_error(ec);
  154. }
  155. /// Open the serial port using the specified device name.
  156. /**
  157. * This function opens the serial port using the given platform-specific
  158. * device name.
  159. *
  160. * @param device The platform-specific device name.
  161. *
  162. * @param ec Set the indicate what error occurred, if any.
  163. */
  164. asio::error_code open(const std::string& device,
  165. asio::error_code& ec)
  166. {
  167. return this->service.open(this->implementation, device, ec);
  168. }
  169. /// Assign an existing native serial port to the serial port.
  170. /*
  171. * This function opens the serial port to hold an existing native serial port.
  172. *
  173. * @param native_serial_port A native serial port.
  174. *
  175. * @throws asio::system_error Thrown on failure.
  176. */
  177. void assign(const native_type& native_serial_port)
  178. {
  179. asio::error_code ec;
  180. this->service.assign(this->implementation, native_serial_port, ec);
  181. asio::detail::throw_error(ec);
  182. }
  183. /// Assign an existing native serial port to the serial port.
  184. /*
  185. * This function opens the serial port to hold an existing native serial port.
  186. *
  187. * @param native_serial_port A native serial port.
  188. *
  189. * @param ec Set to indicate what error occurred, if any.
  190. */
  191. asio::error_code assign(const native_type& native_serial_port,
  192. asio::error_code& ec)
  193. {
  194. return this->service.assign(this->implementation, native_serial_port, ec);
  195. }
  196. /// Determine whether the serial port is open.
  197. bool is_open() const
  198. {
  199. return this->service.is_open(this->implementation);
  200. }
  201. /// Close the serial port.
  202. /**
  203. * This function is used to close the serial port. Any asynchronous read or
  204. * write operations will be cancelled immediately, and will complete with the
  205. * asio::error::operation_aborted error.
  206. *
  207. * @throws asio::system_error Thrown on failure.
  208. */
  209. void close()
  210. {
  211. asio::error_code ec;
  212. this->service.close(this->implementation, ec);
  213. asio::detail::throw_error(ec);
  214. }
  215. /// Close the serial port.
  216. /**
  217. * This function is used to close the serial port. Any asynchronous read or
  218. * write operations will be cancelled immediately, and will complete with the
  219. * asio::error::operation_aborted error.
  220. *
  221. * @param ec Set to indicate what error occurred, if any.
  222. */
  223. asio::error_code close(asio::error_code& ec)
  224. {
  225. return this->service.close(this->implementation, ec);
  226. }
  227. /// Get the native serial port representation.
  228. /**
  229. * This function may be used to obtain the underlying representation of the
  230. * serial port. This is intended to allow access to native serial port
  231. * functionality that is not otherwise provided.
  232. */
  233. native_type native()
  234. {
  235. return this->service.native(this->implementation);
  236. }
  237. /// Cancel all asynchronous operations associated with the serial port.
  238. /**
  239. * This function causes all outstanding asynchronous read or write operations
  240. * to finish immediately, and the handlers for cancelled operations will be
  241. * passed the asio::error::operation_aborted error.
  242. *
  243. * @throws asio::system_error Thrown on failure.
  244. */
  245. void cancel()
  246. {
  247. asio::error_code ec;
  248. this->service.cancel(this->implementation, ec);
  249. asio::detail::throw_error(ec);
  250. }
  251. /// Cancel all asynchronous operations associated with the serial port.
  252. /**
  253. * This function causes all outstanding asynchronous read or write operations
  254. * to finish immediately, and the handlers for cancelled operations will be
  255. * passed the asio::error::operation_aborted error.
  256. *
  257. * @param ec Set to indicate what error occurred, if any.
  258. */
  259. asio::error_code cancel(asio::error_code& ec)
  260. {
  261. return this->service.cancel(this->implementation, ec);
  262. }
  263. /// Send a break sequence to the serial port.
  264. /**
  265. * This function causes a break sequence of platform-specific duration to be
  266. * sent out the serial port.
  267. *
  268. * @throws asio::system_error Thrown on failure.
  269. */
  270. void send_break()
  271. {
  272. asio::error_code ec;
  273. this->service.send_break(this->implementation, ec);
  274. asio::detail::throw_error(ec);
  275. }
  276. /// Send a break sequence to the serial port.
  277. /**
  278. * This function causes a break sequence of platform-specific duration to be
  279. * sent out the serial port.
  280. *
  281. * @param ec Set to indicate what error occurred, if any.
  282. */
  283. asio::error_code send_break(asio::error_code& ec)
  284. {
  285. return this->service.send_break(this->implementation, ec);
  286. }
  287. /// Set an option on the serial port.
  288. /**
  289. * This function is used to set an option on the serial port.
  290. *
  291. * @param option The option value to be set on the serial port.
  292. *
  293. * @throws asio::system_error Thrown on failure.
  294. *
  295. * @sa SettableSerialPortOption @n
  296. * asio::serial_port_base::baud_rate @n
  297. * asio::serial_port_base::flow_control @n
  298. * asio::serial_port_base::parity @n
  299. * asio::serial_port_base::stop_bits @n
  300. * asio::serial_port_base::character_size
  301. */
  302. template <typename SettableSerialPortOption>
  303. void set_option(const SettableSerialPortOption& option)
  304. {
  305. asio::error_code ec;
  306. this->service.set_option(this->implementation, option, ec);
  307. asio::detail::throw_error(ec);
  308. }
  309. /// Set an option on the serial port.
  310. /**
  311. * This function is used to set an option on the serial port.
  312. *
  313. * @param option The option value to be set on the serial port.
  314. *
  315. * @param ec Set to indicate what error occurred, if any.
  316. *
  317. * @sa SettableSerialPortOption @n
  318. * asio::serial_port_base::baud_rate @n
  319. * asio::serial_port_base::flow_control @n
  320. * asio::serial_port_base::parity @n
  321. * asio::serial_port_base::stop_bits @n
  322. * asio::serial_port_base::character_size
  323. */
  324. template <typename SettableSerialPortOption>
  325. asio::error_code set_option(const SettableSerialPortOption& option,
  326. asio::error_code& ec)
  327. {
  328. return this->service.set_option(this->implementation, option, ec);
  329. }
  330. /// Get an option from the serial port.
  331. /**
  332. * This function is used to get the current value of an option on the serial
  333. * port.
  334. *
  335. * @param option The option value to be obtained from the serial port.
  336. *
  337. * @throws asio::system_error Thrown on failure.
  338. *
  339. * @sa GettableSerialPortOption @n
  340. * asio::serial_port_base::baud_rate @n
  341. * asio::serial_port_base::flow_control @n
  342. * asio::serial_port_base::parity @n
  343. * asio::serial_port_base::stop_bits @n
  344. * asio::serial_port_base::character_size
  345. */
  346. template <typename GettableSerialPortOption>
  347. void get_option(GettableSerialPortOption& option)
  348. {
  349. asio::error_code ec;
  350. this->service.get_option(this->implementation, option, ec);
  351. asio::detail::throw_error(ec);
  352. }
  353. /// Get an option from the serial port.
  354. /**
  355. * This function is used to get the current value of an option on the serial
  356. * port.
  357. *
  358. * @param option The option value to be obtained from the serial port.
  359. *
  360. * @param ec Set to indicate what error occured, if any.
  361. *
  362. * @sa GettableSerialPortOption @n
  363. * asio::serial_port_base::baud_rate @n
  364. * asio::serial_port_base::flow_control @n
  365. * asio::serial_port_base::parity @n
  366. * asio::serial_port_base::stop_bits @n
  367. * asio::serial_port_base::character_size
  368. */
  369. template <typename GettableSerialPortOption>
  370. asio::error_code get_option(GettableSerialPortOption& option,
  371. asio::error_code& ec)
  372. {
  373. return this->service.get_option(this->implementation, option, ec);
  374. }
  375. /// Write some data to the serial port.
  376. /**
  377. * This function is used to write data to the serial port. The function call
  378. * will block until one or more bytes of the data has been written
  379. * successfully, or until an error occurs.
  380. *
  381. * @param buffers One or more data buffers to be written to the serial port.
  382. *
  383. * @returns The number of bytes written.
  384. *
  385. * @throws asio::system_error Thrown on failure. An error code of
  386. * asio::error::eof indicates that the connection was closed by the
  387. * peer.
  388. *
  389. * @note The write_some operation may not transmit all of the data to the
  390. * peer. Consider using the @ref write function if you need to ensure that
  391. * all data is written before the blocking operation completes.
  392. *
  393. * @par Example
  394. * To write a single data buffer use the @ref buffer function as follows:
  395. * @code
  396. * serial_port.write_some(asio::buffer(data, size));
  397. * @endcode
  398. * See the @ref buffer documentation for information on writing multiple
  399. * buffers in one go, and how to use it with arrays, boost::array or
  400. * std::vector.
  401. */
  402. template <typename ConstBufferSequence>
  403. std::size_t write_some(const ConstBufferSequence& buffers)
  404. {
  405. asio::error_code ec;
  406. std::size_t s = this->service.write_some(this->implementation, buffers, ec);
  407. asio::detail::throw_error(ec);
  408. return s;
  409. }
  410. /// Write some data to the serial port.
  411. /**
  412. * This function is used to write data to the serial port. The function call
  413. * will block until one or more bytes of the data has been written
  414. * successfully, or until an error occurs.
  415. *
  416. * @param buffers One or more data buffers to be written to the serial port.
  417. *
  418. * @param ec Set to indicate what error occurred, if any.
  419. *
  420. * @returns The number of bytes written. Returns 0 if an error occurred.
  421. *
  422. * @note The write_some operation may not transmit all of the data to the
  423. * peer. Consider using the @ref write function if you need to ensure that
  424. * all data is written before the blocking operation completes.
  425. */
  426. template <typename ConstBufferSequence>
  427. std::size_t write_some(const ConstBufferSequence& buffers,
  428. asio::error_code& ec)
  429. {
  430. return this->service.write_some(this->implementation, buffers, ec);
  431. }
  432. /// Start an asynchronous write.
  433. /**
  434. * This function is used to asynchronously write data to the serial port.
  435. * The function call always returns immediately.
  436. *
  437. * @param buffers One or more data buffers to be written to the serial port.
  438. * Although the buffers object may be copied as necessary, ownership of the
  439. * underlying memory blocks is retained by the caller, which must guarantee
  440. * that they remain valid until the handler is called.
  441. *
  442. * @param handler The handler to be called when the write operation completes.
  443. * Copies will be made of the handler as required. The function signature of
  444. * the handler must be:
  445. * @code void handler(
  446. * const asio::error_code& error, // Result of operation.
  447. * std::size_t bytes_transferred // Number of bytes written.
  448. * ); @endcode
  449. * Regardless of whether the asynchronous operation completes immediately or
  450. * not, the handler will not be invoked from within this function. Invocation
  451. * of the handler will be performed in a manner equivalent to using
  452. * asio::io_service::post().
  453. *
  454. * @note The write operation may not transmit all of the data to the peer.
  455. * Consider using the @ref async_write function if you need to ensure that all
  456. * data is written before the asynchronous operation completes.
  457. *
  458. * @par Example
  459. * To write a single data buffer use the @ref buffer function as follows:
  460. * @code
  461. * serial_port.async_write_some(asio::buffer(data, size), handler);
  462. * @endcode
  463. * See the @ref buffer documentation for information on writing multiple
  464. * buffers in one go, and how to use it with arrays, boost::array or
  465. * std::vector.
  466. */
  467. template <typename ConstBufferSequence, typename WriteHandler>
  468. void async_write_some(const ConstBufferSequence& buffers,
  469. WriteHandler handler)
  470. {
  471. this->service.async_write_some(this->implementation, buffers, handler);
  472. }
  473. /// Read some data from the serial port.
  474. /**
  475. * This function is used to read data from the serial port. The function
  476. * call will block until one or more bytes of data has been read successfully,
  477. * or until an error occurs.
  478. *
  479. * @param buffers One or more buffers into which the data will be read.
  480. *
  481. * @returns The number of bytes read.
  482. *
  483. * @throws asio::system_error Thrown on failure. An error code of
  484. * asio::error::eof indicates that the connection was closed by the
  485. * peer.
  486. *
  487. * @note The read_some operation may not read all of the requested number of
  488. * bytes. Consider using the @ref read function if you need to ensure that
  489. * the requested amount of data is read before the blocking operation
  490. * completes.
  491. *
  492. * @par Example
  493. * To read into a single data buffer use the @ref buffer function as follows:
  494. * @code
  495. * serial_port.read_some(asio::buffer(data, size));
  496. * @endcode
  497. * See the @ref buffer documentation for information on reading into multiple
  498. * buffers in one go, and how to use it with arrays, boost::array or
  499. * std::vector.
  500. */
  501. template <typename MutableBufferSequence>
  502. std::size_t read_some(const MutableBufferSequence& buffers)
  503. {
  504. asio::error_code ec;
  505. std::size_t s = this->service.read_some(this->implementation, buffers, ec);
  506. asio::detail::throw_error(ec);
  507. return s;
  508. }
  509. /// Read some data from the serial port.
  510. /**
  511. * This function is used to read data from the serial port. The function
  512. * call will block until one or more bytes of data has been read successfully,
  513. * or until an error occurs.
  514. *
  515. * @param buffers One or more buffers into which the data will be read.
  516. *
  517. * @param ec Set to indicate what error occurred, if any.
  518. *
  519. * @returns The number of bytes read. Returns 0 if an error occurred.
  520. *
  521. * @note The read_some operation may not read all of the requested number of
  522. * bytes. Consider using the @ref read function if you need to ensure that
  523. * the requested amount of data is read before the blocking operation
  524. * completes.
  525. */
  526. template <typename MutableBufferSequence>
  527. std::size_t read_some(const MutableBufferSequence& buffers,
  528. asio::error_code& ec)
  529. {
  530. return this->service.read_some(this->implementation, buffers, ec);
  531. }
  532. /// Start an asynchronous read.
  533. /**
  534. * This function is used to asynchronously read data from the serial port.
  535. * The function call always returns immediately.
  536. *
  537. * @param buffers One or more buffers into which the data will be read.
  538. * Although the buffers object may be copied as necessary, ownership of the
  539. * underlying memory blocks is retained by the caller, which must guarantee
  540. * that they remain valid until the handler is called.
  541. *
  542. * @param handler The handler to be called when the read operation completes.
  543. * Copies will be made of the handler as required. The function signature of
  544. * the handler must be:
  545. * @code void handler(
  546. * const asio::error_code& error, // Result of operation.
  547. * std::size_t bytes_transferred // Number of bytes read.
  548. * ); @endcode
  549. * Regardless of whether the asynchronous operation completes immediately or
  550. * not, the handler will not be invoked from within this function. Invocation
  551. * of the handler will be performed in a manner equivalent to using
  552. * asio::io_service::post().
  553. *
  554. * @note The read operation may not read all of the requested number of bytes.
  555. * Consider using the @ref async_read function if you need to ensure that the
  556. * requested amount of data is read before the asynchronous operation
  557. * completes.
  558. *
  559. * @par Example
  560. * To read into a single data buffer use the @ref buffer function as follows:
  561. * @code
  562. * serial_port.async_read_some(asio::buffer(data, size), handler);
  563. * @endcode
  564. * See the @ref buffer documentation for information on reading into multiple
  565. * buffers in one go, and how to use it with arrays, boost::array or
  566. * std::vector.
  567. */
  568. template <typename MutableBufferSequence, typename ReadHandler>
  569. void async_read_some(const MutableBufferSequence& buffers,
  570. ReadHandler handler)
  571. {
  572. this->service.async_read_some(this->implementation, buffers, handler);
  573. }
  574. };
  575. } // namespace asio
  576. #include "asio/detail/pop_options.hpp"
  577. #endif // defined(ASIO_HAS_SERIAL_PORT)
  578. // || defined(GENERATING_DOCUMENTATION)
  579. #endif // ASIO_BASIC_SERIAL_PORT_HPP