serialport/lib.rs
1//! serialport-rs is a cross-platform serial port library.
2//!
3//! The goal of this library is to expose a cross-platform and platform-specific API for enumerating
4//! and using blocking I/O with serial ports. This library exposes a similar API to that provided
5//! by [Qt's `QSerialPort` library](https://doc.qt.io/qt-5/qserialport.html).
6//!
7//! # Feature Overview
8//!
9//! The library has been organized such that there is a high-level `SerialPort` trait that provides
10//! a cross-platform API for accessing serial ports. This is the preferred method of interacting
11//! with ports. The `SerialPort::new().open*()` and `available_ports()` functions in the root
12//! provide cross-platform functionality.
13//!
14//! For platform-specific functionality, this crate is split into a `posix` and `windows` API with
15//! corresponding `TTYPort` and `COMPort` structs (that both implement the `SerialPort` trait).
16//! Using the platform-specific `SerialPort::new().open*()` functions will return the
17//! platform-specific port object which allows access to platform-specific functionality.
18
19#![deny(
20 clippy::dbg_macro,
21 missing_docs,
22 missing_debug_implementations,
23 missing_copy_implementations
24)]
25// Document feature-gated elements on docs.rs. See
26// https://doc.rust-lang.org/rustdoc/unstable-features.html?highlight=doc(cfg#doccfg-recording-what-platforms-or-features-are-required-for-code-to-be-present
27// and
28// https://doc.rust-lang.org/rustdoc/unstable-features.html#doc_auto_cfg-automatically-generate-doccfg
29// for details.
30#![cfg_attr(docsrs, feature(doc_auto_cfg))]
31// Don't worry about needing to `unwrap()` or otherwise handle some results in
32// doc tests.
33#![doc(test(attr(allow(unused_must_use))))]
34
35use std::error::Error as StdError;
36use std::fmt;
37use std::io;
38use std::str::FromStr;
39use std::time::Duration;
40
41#[cfg(unix)]
42mod posix;
43#[cfg(unix)]
44pub use posix::{BreakDuration, TTYPort};
45
46#[cfg(windows)]
47mod windows;
48#[cfg(windows)]
49pub use windows::COMPort;
50
51#[cfg(test)]
52pub(crate) mod tests;
53
54/// A type for results generated by interacting with serial ports
55///
56/// The `Err` type is hard-wired to [`serialport::Error`](struct.Error.html).
57pub type Result<T> = std::result::Result<T, Error>;
58
59/// Categories of errors that can occur when interacting with serial ports
60///
61/// This list is intended to grow over time and it is not recommended to
62/// exhaustively match against it.
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum ErrorKind {
65 /// The device is not available.
66 ///
67 /// This could indicate that the device is in use by another process or was
68 /// disconnected while performing I/O.
69 NoDevice,
70
71 /// A parameter was incorrect.
72 InvalidInput,
73
74 /// An unknown error occurred.
75 Unknown,
76
77 /// An I/O error occurred.
78 ///
79 /// The type of I/O error is determined by the inner `io::ErrorKind`.
80 Io(io::ErrorKind),
81}
82
83/// An error type for serial port operations
84#[derive(Debug, Clone)]
85pub struct Error {
86 /// The kind of error this is
87 pub kind: ErrorKind,
88 /// A description of the error suitable for end-users
89 pub description: String,
90}
91
92impl Error {
93 /// Instantiates a new error
94 pub fn new<T: Into<String>>(kind: ErrorKind, description: T) -> Self {
95 Error {
96 kind,
97 description: description.into(),
98 }
99 }
100
101 /// Returns the corresponding `ErrorKind` for this error.
102 pub fn kind(&self) -> ErrorKind {
103 self.kind
104 }
105}
106
107impl fmt::Display for Error {
108 fn fmt(&self, fmt: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
109 fmt.write_str(&self.description)
110 }
111}
112
113impl StdError for Error {
114 fn description(&self) -> &str {
115 &self.description
116 }
117}
118
119impl From<io::Error> for Error {
120 fn from(io_error: io::Error) -> Error {
121 Error::new(ErrorKind::Io(io_error.kind()), format!("{}", io_error))
122 }
123}
124
125impl From<Error> for io::Error {
126 fn from(error: Error) -> io::Error {
127 let kind = match error.kind {
128 ErrorKind::NoDevice => io::ErrorKind::NotFound,
129 ErrorKind::InvalidInput => io::ErrorKind::InvalidInput,
130 ErrorKind::Unknown => io::ErrorKind::Other,
131 ErrorKind::Io(kind) => kind,
132 };
133
134 io::Error::new(kind, error.description)
135 }
136}
137
138/// Number of bits per character
139#[derive(Debug, Copy, Clone, PartialEq, Eq)]
140#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
141pub enum DataBits {
142 /// 5 bits per character
143 Five,
144
145 /// 6 bits per character
146 Six,
147
148 /// 7 bits per character
149 Seven,
150
151 /// 8 bits per character
152 Eight,
153}
154
155impl fmt::Display for DataBits {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 match *self {
158 DataBits::Five => write!(f, "Five"),
159 DataBits::Six => write!(f, "Six"),
160 DataBits::Seven => write!(f, "Seven"),
161 DataBits::Eight => write!(f, "Eight"),
162 }
163 }
164}
165
166impl From<DataBits> for u8 {
167 fn from(value: DataBits) -> Self {
168 match value {
169 DataBits::Five => 5,
170 DataBits::Six => 6,
171 DataBits::Seven => 7,
172 DataBits::Eight => 8,
173 }
174 }
175}
176
177impl TryFrom<u8> for DataBits {
178 type Error = ();
179
180 fn try_from(value: u8) -> core::result::Result<Self, Self::Error> {
181 match value {
182 5 => Ok(Self::Five),
183 6 => Ok(Self::Six),
184 7 => Ok(Self::Seven),
185 8 => Ok(Self::Eight),
186 _ => Err(()),
187 }
188 }
189}
190
191/// Parity checking modes
192///
193/// When parity checking is enabled (`Odd` or `Even`) an extra bit is transmitted with
194/// each character. The value of the parity bit is arranged so that the number of 1 bits in the
195/// character (including the parity bit) is an even number (`Even`) or an odd number
196/// (`Odd`).
197///
198/// Parity checking is disabled by setting `None`, in which case parity bits are not
199/// transmitted.
200#[derive(Debug, Copy, Clone, PartialEq, Eq)]
201#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
202pub enum Parity {
203 /// No parity bit.
204 None,
205
206 /// Parity bit sets odd number of 1 bits.
207 Odd,
208
209 /// Parity bit sets even number of 1 bits.
210 Even,
211}
212
213impl fmt::Display for Parity {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 match *self {
216 Parity::None => write!(f, "None"),
217 Parity::Odd => write!(f, "Odd"),
218 Parity::Even => write!(f, "Even"),
219 }
220 }
221}
222
223/// Number of stop bits
224///
225/// Stop bits are transmitted after every character.
226#[derive(Debug, Copy, Clone, PartialEq, Eq)]
227#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
228pub enum StopBits {
229 /// One stop bit.
230 One,
231
232 /// Two stop bits.
233 Two,
234}
235
236impl fmt::Display for StopBits {
237 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
238 match *self {
239 StopBits::One => write!(f, "One"),
240 StopBits::Two => write!(f, "Two"),
241 }
242 }
243}
244
245impl From<StopBits> for u8 {
246 fn from(value: StopBits) -> Self {
247 match value {
248 StopBits::One => 1,
249 StopBits::Two => 2,
250 }
251 }
252}
253
254impl TryFrom<u8> for StopBits {
255 type Error = ();
256
257 fn try_from(value: u8) -> core::result::Result<Self, Self::Error> {
258 match value {
259 1 => Ok(Self::One),
260 2 => Ok(Self::Two),
261 _ => Err(()),
262 }
263 }
264}
265
266/// Flow control modes
267#[derive(Debug, Copy, Clone, PartialEq, Eq)]
268#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
269pub enum FlowControl {
270 /// No flow control.
271 None,
272
273 /// Flow control using XON/XOFF bytes.
274 Software,
275
276 /// Flow control using RTS/CTS signals.
277 Hardware,
278}
279
280impl fmt::Display for FlowControl {
281 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
282 match *self {
283 FlowControl::None => write!(f, "None"),
284 FlowControl::Software => write!(f, "Software"),
285 FlowControl::Hardware => write!(f, "Hardware"),
286 }
287 }
288}
289
290impl FromStr for FlowControl {
291 type Err = ();
292
293 fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
294 match s {
295 "None" | "none" | "n" => Ok(FlowControl::None),
296 "Software" | "software" | "SW" | "sw" | "s" => Ok(FlowControl::Software),
297 "Hardware" | "hardware" | "HW" | "hw" | "h" => Ok(FlowControl::Hardware),
298 _ => Err(()),
299 }
300 }
301}
302
303/// Specifies which buffer or buffers to purge when calling [`clear`]
304///
305/// [`clear`]: trait.SerialPort.html#tymethod.clear
306#[derive(Debug, Copy, Clone, PartialEq, Eq)]
307#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
308pub enum ClearBuffer {
309 /// Specify to clear data received but not read
310 Input,
311 /// Specify to clear data written but not yet transmitted
312 Output,
313 /// Specify to clear both data received and data not yet transmitted
314 All,
315}
316
317/// A struct containing all serial port settings
318#[derive(Debug, Clone, PartialEq, Eq)]
319pub struct SerialPortBuilder {
320 /// The port name, usually the device path
321 path: String,
322 /// The baud rate in symbols-per-second
323 baud_rate: u32,
324 /// Number of bits used to represent a character sent on the line
325 data_bits: DataBits,
326 /// The type of signalling to use for controlling data transfer
327 flow_control: FlowControl,
328 /// The type of parity to use for error checking
329 parity: Parity,
330 /// Number of bits to use to signal the end of a character
331 stop_bits: StopBits,
332 /// Amount of time to wait to receive data before timing out
333 timeout: Duration,
334}
335
336impl SerialPortBuilder {
337 /// Set the path to the serial port
338 // TODO: Switch to `clone_into` when bumping our MSRV past 1.63 and remove this exemption.
339 #[allow(clippy::assigning_clones)]
340 #[must_use]
341 pub fn path<'a>(mut self, path: impl Into<std::borrow::Cow<'a, str>>) -> Self {
342 self.path = path.into().as_ref().to_owned();
343 self
344 }
345
346 /// Set the baud rate in symbols-per-second
347 #[must_use]
348 pub fn baud_rate(mut self, baud_rate: u32) -> Self {
349 self.baud_rate = baud_rate;
350 self
351 }
352
353 /// Set the number of bits used to represent a character sent on the line
354 #[must_use]
355 pub fn data_bits(mut self, data_bits: DataBits) -> Self {
356 self.data_bits = data_bits;
357 self
358 }
359
360 /// Set the type of signalling to use for controlling data transfer
361 #[must_use]
362 pub fn flow_control(mut self, flow_control: FlowControl) -> Self {
363 self.flow_control = flow_control;
364 self
365 }
366
367 /// Set the type of parity to use for error checking
368 #[must_use]
369 pub fn parity(mut self, parity: Parity) -> Self {
370 self.parity = parity;
371 self
372 }
373
374 /// Set the number of bits to use to signal the end of a character
375 #[must_use]
376 pub fn stop_bits(mut self, stop_bits: StopBits) -> Self {
377 self.stop_bits = stop_bits;
378 self
379 }
380
381 /// Set the amount of time to wait to receive data before timing out
382 ///
383 /// <div class="warning">
384 ///
385 /// The accuracy is limited by the underlying platform's capabilities. Longer timeouts will be
386 /// clamped to the maximum supported value which is expected to be in the magnitude of a few
387 /// days.
388 ///
389 /// </div>
390 #[must_use]
391 pub fn timeout(mut self, timeout: Duration) -> Self {
392 self.timeout = timeout;
393 self
394 }
395
396 /// Open a cross-platform interface to the port with the specified settings
397 pub fn open(self) -> Result<Box<dyn SerialPort>> {
398 #[cfg(unix)]
399 return posix::TTYPort::open(&self).map(|p| Box::new(p) as Box<dyn SerialPort>);
400
401 #[cfg(windows)]
402 return windows::COMPort::open(&self).map(|p| Box::new(p) as Box<dyn SerialPort>);
403
404 #[cfg(not(any(unix, windows)))]
405 Err(Error::new(
406 ErrorKind::Unknown,
407 "open() not implemented for platform",
408 ))
409 }
410
411 /// Open a platform-specific interface to the port with the specified settings
412 #[cfg(unix)]
413 pub fn open_native(self) -> Result<TTYPort> {
414 posix::TTYPort::open(&self)
415 }
416
417 /// Open a platform-specific interface to the port with the specified settings
418 #[cfg(windows)]
419 pub fn open_native(self) -> Result<COMPort> {
420 windows::COMPort::open(&self)
421 }
422}
423
424/// A trait for serial port devices
425///
426/// This trait is all that's necessary to implement a new serial port driver
427/// for a new platform.
428pub trait SerialPort: Send + io::Read + io::Write {
429 // Port settings getters
430
431 /// Returns the name of this port if it exists.
432 ///
433 /// This name may not be the canonical device name and instead be shorthand.
434 /// Additionally it may not exist for virtual ports.
435 fn name(&self) -> Option<String>;
436
437 /// Returns the current baud rate.
438 ///
439 /// This may return a value different from the last specified baud rate depending on the
440 /// platform as some will return the actual device baud rate rather than the last specified
441 /// baud rate.
442 fn baud_rate(&self) -> Result<u32>;
443
444 /// Returns the character size.
445 ///
446 /// This function returns `None` if the character size could not be determined. This may occur
447 /// if the hardware is in an uninitialized state or is using a non-standard character size.
448 /// Setting a baud rate with `set_char_size()` should initialize the character size to a
449 /// supported value.
450 fn data_bits(&self) -> Result<DataBits>;
451
452 /// Returns the flow control mode.
453 ///
454 /// This function returns `None` if the flow control mode could not be determined. This may
455 /// occur if the hardware is in an uninitialized state or is using an unsupported flow control
456 /// mode. Setting a flow control mode with `set_flow_control()` should initialize the flow
457 /// control mode to a supported value.
458 fn flow_control(&self) -> Result<FlowControl>;
459
460 /// Returns the parity-checking mode.
461 ///
462 /// This function returns `None` if the parity mode could not be determined. This may occur if
463 /// the hardware is in an uninitialized state or is using a non-standard parity mode. Setting
464 /// a parity mode with `set_parity()` should initialize the parity mode to a supported value.
465 fn parity(&self) -> Result<Parity>;
466
467 /// Returns the number of stop bits.
468 ///
469 /// This function returns `None` if the number of stop bits could not be determined. This may
470 /// occur if the hardware is in an uninitialized state or is using an unsupported stop bit
471 /// configuration. Setting the number of stop bits with `set_stop-bits()` should initialize the
472 /// stop bits to a supported value.
473 fn stop_bits(&self) -> Result<StopBits>;
474
475 /// Returns the current timeout.
476 fn timeout(&self) -> Duration;
477
478 // Port settings setters
479
480 /// Sets the baud rate.
481 ///
482 /// ## Errors
483 ///
484 /// If the implementation does not support the requested baud rate, this function may return an
485 /// `InvalidInput` error. Even if the baud rate is accepted by `set_baud_rate()`, it may not be
486 /// supported by the underlying hardware.
487 fn set_baud_rate(&mut self, baud_rate: u32) -> Result<()>;
488
489 /// Sets the character size.
490 fn set_data_bits(&mut self, data_bits: DataBits) -> Result<()>;
491
492 /// Sets the flow control mode.
493 fn set_flow_control(&mut self, flow_control: FlowControl) -> Result<()>;
494
495 /// Sets the parity-checking mode.
496 fn set_parity(&mut self, parity: Parity) -> Result<()>;
497
498 /// Sets the number of stop bits.
499 fn set_stop_bits(&mut self, stop_bits: StopBits) -> Result<()>;
500
501 /// Sets the timeout for future I/O operations.
502 ///
503 /// <div class="warning">
504 ///
505 /// The accuracy is limited by the underlying platform's capabilities. Longer timeouts will be
506 /// clamped to the maximum supported value which is expected to be in the magnitude of a few
507 /// days.
508 ///
509 /// </div>
510 fn set_timeout(&mut self, timeout: Duration) -> Result<()>;
511
512 // Functions for setting non-data control signal pins
513
514 /// Sets the state of the RTS (Request To Send) control signal.
515 ///
516 /// Setting a value of `true` asserts the RTS control signal. `false` clears the signal.
517 ///
518 /// ## Errors
519 ///
520 /// This function returns an error if the RTS control signal could not be set to the desired
521 /// state on the underlying hardware:
522 ///
523 /// * `NoDevice` if the device was disconnected.
524 /// * `Io` for any other type of I/O error.
525 fn write_request_to_send(&mut self, level: bool) -> Result<()>;
526
527 /// Writes to the Data Terminal Ready pin
528 ///
529 /// Setting a value of `true` asserts the DTR control signal. `false` clears the signal.
530 ///
531 /// ## Errors
532 ///
533 /// This function returns an error if the DTR control signal could not be set to the desired
534 /// state on the underlying hardware:
535 ///
536 /// * `NoDevice` if the device was disconnected.
537 /// * `Io` for any other type of I/O error.
538 fn write_data_terminal_ready(&mut self, level: bool) -> Result<()>;
539
540 // Functions for reading additional pins
541
542 /// Reads the state of the CTS (Clear To Send) control signal.
543 ///
544 /// This function returns a boolean that indicates whether the CTS control signal is asserted.
545 ///
546 /// ## Errors
547 ///
548 /// This function returns an error if the state of the CTS control signal could not be read
549 /// from the underlying hardware:
550 ///
551 /// * `NoDevice` if the device was disconnected.
552 /// * `Io` for any other type of I/O error.
553 fn read_clear_to_send(&mut self) -> Result<bool>;
554
555 /// Reads the state of the Data Set Ready control signal.
556 ///
557 /// This function returns a boolean that indicates whether the DSR control signal is asserted.
558 ///
559 /// ## Errors
560 ///
561 /// This function returns an error if the state of the DSR control signal could not be read
562 /// from the underlying hardware:
563 ///
564 /// * `NoDevice` if the device was disconnected.
565 /// * `Io` for any other type of I/O error.
566 fn read_data_set_ready(&mut self) -> Result<bool>;
567
568 /// Reads the state of the Ring Indicator control signal.
569 ///
570 /// This function returns a boolean that indicates whether the RI control signal is asserted.
571 ///
572 /// ## Errors
573 ///
574 /// This function returns an error if the state of the RI control signal could not be read from
575 /// the underlying hardware:
576 ///
577 /// * `NoDevice` if the device was disconnected.
578 /// * `Io` for any other type of I/O error.
579 fn read_ring_indicator(&mut self) -> Result<bool>;
580
581 /// Reads the state of the Carrier Detect control signal.
582 ///
583 /// This function returns a boolean that indicates whether the CD control signal is asserted.
584 ///
585 /// ## Errors
586 ///
587 /// This function returns an error if the state of the CD control signal could not be read from
588 /// the underlying hardware:
589 ///
590 /// * `NoDevice` if the device was disconnected.
591 /// * `Io` for any other type of I/O error.
592 fn read_carrier_detect(&mut self) -> Result<bool>;
593
594 /// Gets the number of bytes available to be read from the input buffer.
595 ///
596 /// # Errors
597 ///
598 /// This function may return the following errors:
599 ///
600 /// * `NoDevice` if the device was disconnected.
601 /// * `Io` for any other type of I/O error.
602 fn bytes_to_read(&self) -> Result<u32>;
603
604 /// Get the number of bytes written to the output buffer, awaiting transmission.
605 ///
606 /// # Errors
607 ///
608 /// This function may return the following errors:
609 ///
610 /// * `NoDevice` if the device was disconnected.
611 /// * `Io` for any other type of I/O error.
612 fn bytes_to_write(&self) -> Result<u32>;
613
614 /// Discards all bytes from the serial driver's input buffer and/or output buffer.
615 ///
616 /// # Errors
617 ///
618 /// This function may return the following errors:
619 ///
620 /// * `NoDevice` if the device was disconnected.
621 /// * `Io` for any other type of I/O error.
622 fn clear(&self, buffer_to_clear: ClearBuffer) -> Result<()>;
623
624 // Misc methods
625
626 /// Attempts to clone the `SerialPort`. This allow you to write and read simultaneously from the
627 /// same serial connection. Please note that if you want a real asynchronous serial port you
628 /// should look at [mio-serial](https://crates.io/crates/mio-serial) or
629 /// [tokio-serial](https://crates.io/crates/tokio-serial).
630 ///
631 /// Also, you must be very careful when changing the settings of a cloned `SerialPort` : since
632 /// the settings are cached on a per object basis, trying to modify them from two different
633 /// objects can cause some nasty behavior.
634 ///
635 /// # Errors
636 ///
637 /// This function returns an error if the serial port couldn't be cloned.
638 fn try_clone(&self) -> Result<Box<dyn SerialPort>>;
639
640 /// Start transmitting a break
641 fn set_break(&self) -> Result<()>;
642
643 /// Stop transmitting a break
644 fn clear_break(&self) -> Result<()>;
645}
646
647impl<T: SerialPort> SerialPort for &mut T {
648 fn name(&self) -> Option<String> {
649 (**self).name()
650 }
651
652 fn baud_rate(&self) -> Result<u32> {
653 (**self).baud_rate()
654 }
655
656 fn data_bits(&self) -> Result<DataBits> {
657 (**self).data_bits()
658 }
659
660 fn flow_control(&self) -> Result<FlowControl> {
661 (**self).flow_control()
662 }
663
664 fn parity(&self) -> Result<Parity> {
665 (**self).parity()
666 }
667
668 fn stop_bits(&self) -> Result<StopBits> {
669 (**self).stop_bits()
670 }
671
672 fn timeout(&self) -> Duration {
673 (**self).timeout()
674 }
675
676 fn set_baud_rate(&mut self, baud_rate: u32) -> Result<()> {
677 (**self).set_baud_rate(baud_rate)
678 }
679
680 fn set_data_bits(&mut self, data_bits: DataBits) -> Result<()> {
681 (**self).set_data_bits(data_bits)
682 }
683
684 fn set_flow_control(&mut self, flow_control: FlowControl) -> Result<()> {
685 (**self).set_flow_control(flow_control)
686 }
687
688 fn set_parity(&mut self, parity: Parity) -> Result<()> {
689 (**self).set_parity(parity)
690 }
691
692 fn set_stop_bits(&mut self, stop_bits: StopBits) -> Result<()> {
693 (**self).set_stop_bits(stop_bits)
694 }
695
696 fn set_timeout(&mut self, timeout: Duration) -> Result<()> {
697 (**self).set_timeout(timeout)
698 }
699
700 fn write_request_to_send(&mut self, level: bool) -> Result<()> {
701 (**self).write_request_to_send(level)
702 }
703
704 fn write_data_terminal_ready(&mut self, level: bool) -> Result<()> {
705 (**self).write_data_terminal_ready(level)
706 }
707
708 fn read_clear_to_send(&mut self) -> Result<bool> {
709 (**self).read_clear_to_send()
710 }
711
712 fn read_data_set_ready(&mut self) -> Result<bool> {
713 (**self).read_data_set_ready()
714 }
715
716 fn read_ring_indicator(&mut self) -> Result<bool> {
717 (**self).read_ring_indicator()
718 }
719
720 fn read_carrier_detect(&mut self) -> Result<bool> {
721 (**self).read_carrier_detect()
722 }
723
724 fn bytes_to_read(&self) -> Result<u32> {
725 (**self).bytes_to_read()
726 }
727
728 fn bytes_to_write(&self) -> Result<u32> {
729 (**self).bytes_to_write()
730 }
731
732 fn clear(&self, buffer_to_clear: ClearBuffer) -> Result<()> {
733 (**self).clear(buffer_to_clear)
734 }
735
736 fn try_clone(&self) -> Result<Box<dyn SerialPort>> {
737 (**self).try_clone()
738 }
739
740 fn set_break(&self) -> Result<()> {
741 (**self).set_break()
742 }
743
744 fn clear_break(&self) -> Result<()> {
745 (**self).clear_break()
746 }
747}
748
749impl fmt::Debug for dyn SerialPort {
750 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
751 write!(f, "SerialPort ( ")?;
752
753 if let Some(n) = self.name().as_ref() {
754 write!(f, "name: {} ", n)?;
755 };
756 if let Ok(b) = self.baud_rate().as_ref() {
757 write!(f, "baud_rate: {} ", b)?;
758 };
759 if let Ok(b) = self.data_bits().as_ref() {
760 write!(f, "data_bits: {} ", b)?;
761 };
762 if let Ok(c) = self.flow_control().as_ref() {
763 write!(f, "flow_control: {} ", c)?;
764 }
765 if let Ok(p) = self.parity().as_ref() {
766 write!(f, "parity: {} ", p)?;
767 }
768 if let Ok(s) = self.stop_bits().as_ref() {
769 write!(f, "stop_bits: {} ", s)?;
770 }
771
772 write!(f, ")")
773 }
774}
775
776/// Contains all possible USB information about a `SerialPort`
777#[derive(Debug, Clone, PartialEq, Eq)]
778#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
779pub struct UsbPortInfo {
780 /// Vendor ID
781 pub vid: u16,
782 /// Product ID
783 pub pid: u16,
784 /// Serial number (arbitrary string)
785 pub serial_number: Option<String>,
786 /// Manufacturer (arbitrary string)
787 pub manufacturer: Option<String>,
788 /// Product name (arbitrary string)
789 pub product: Option<String>,
790 /// The interface index of the USB serial port. This can be either the interface number of
791 /// the communication interface (as is the case on Windows and Linux) or the data
792 /// interface (as is the case on macOS), so you should recognize both interface numbers.
793 #[cfg(feature = "usbportinfo-interface")]
794 pub interface: Option<u8>,
795}
796
797/// The physical type of a `SerialPort`
798#[derive(Debug, Clone, PartialEq, Eq)]
799#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
800pub enum SerialPortType {
801 /// The serial port is connected via USB
802 UsbPort(UsbPortInfo),
803 /// The serial port is connected via PCI (permanent port)
804 PciPort,
805 /// The serial port is connected via Bluetooth
806 BluetoothPort,
807 /// It can't be determined how the serial port is connected
808 Unknown,
809}
810
811/// A device-independent implementation of serial port information
812#[derive(Debug, Clone, PartialEq, Eq)]
813#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
814pub struct SerialPortInfo {
815 /// The short name of the serial port
816 pub port_name: String,
817 /// The hardware device type that exposes this port
818 pub port_type: SerialPortType,
819}
820
821/// Construct a builder of `SerialPort` objects
822///
823/// `SerialPort` objects are built using the Builder pattern through the `new` function. The
824/// resultant `SerialPortBuilder` object can be copied, reconfigured, and saved making working with
825/// multiple serial ports a little easier.
826///
827/// To open a new serial port:
828/// ```no_run
829/// serialport::new("/dev/ttyUSB0", 9600).open().expect("Failed to open port");
830/// ```
831pub fn new<'a>(path: impl Into<std::borrow::Cow<'a, str>>, baud_rate: u32) -> SerialPortBuilder {
832 SerialPortBuilder {
833 path: path.into().into_owned(),
834 baud_rate,
835 data_bits: DataBits::Eight,
836 flow_control: FlowControl::None,
837 parity: Parity::None,
838 stop_bits: StopBits::One,
839 timeout: Duration::from_millis(0),
840 }
841}
842
843/// Returns a list of all serial ports on system
844///
845/// It is not guaranteed that these ports exist or are available even if they're
846/// returned by this function.
847pub fn available_ports() -> Result<Vec<SerialPortInfo>> {
848 #[cfg(unix)]
849 return crate::posix::available_ports();
850
851 #[cfg(windows)]
852 return crate::windows::available_ports();
853
854 #[cfg(not(any(unix, windows)))]
855 Err(Error::new(
856 ErrorKind::Unknown,
857 "available_ports() not implemented for platform",
858 ))
859}