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