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    /// The state to set DTR to when opening the device
335    dtr_on_open: Option<bool>,
336}
337
338impl SerialPortBuilder {
339    /// Set the path to the serial port
340    // TODO: Switch to `clone_into` when bumping our MSRV past 1.63 and remove this exemption.
341    #[allow(clippy::assigning_clones)]
342    #[must_use]
343    pub fn path<'a>(mut self, path: impl Into<std::borrow::Cow<'a, str>>) -> Self {
344        self.path = path.into().as_ref().to_owned();
345        self
346    }
347
348    /// Set the baud rate in symbols-per-second
349    #[must_use]
350    pub fn baud_rate(mut self, baud_rate: u32) -> Self {
351        self.baud_rate = baud_rate;
352        self
353    }
354
355    /// Set the number of bits used to represent a character sent on the line
356    #[must_use]
357    pub fn data_bits(mut self, data_bits: DataBits) -> Self {
358        self.data_bits = data_bits;
359        self
360    }
361
362    /// Set the type of signalling to use for controlling data transfer
363    #[must_use]
364    pub fn flow_control(mut self, flow_control: FlowControl) -> Self {
365        self.flow_control = flow_control;
366        self
367    }
368
369    /// Set the type of parity to use for error checking
370    #[must_use]
371    pub fn parity(mut self, parity: Parity) -> Self {
372        self.parity = parity;
373        self
374    }
375
376    /// Set the number of bits to use to signal the end of a character
377    #[must_use]
378    pub fn stop_bits(mut self, stop_bits: StopBits) -> Self {
379        self.stop_bits = stop_bits;
380        self
381    }
382
383    /// Set the amount of time to wait to receive data before timing out
384    ///
385    /// <div class="warning">
386    ///
387    /// The accuracy is limited by the underlying platform's capabilities. Longer timeouts will be
388    /// clamped to the maximum supported value which is expected to be in the magnitude of a few
389    /// days.
390    ///
391    /// </div>
392    #[must_use]
393    pub fn timeout(mut self, timeout: Duration) -> Self {
394        self.timeout = timeout;
395        self
396    }
397
398    /// Set data terminal ready (DTR) to the given state when opening the device
399    ///
400    /// Note: On Linux, DTR is automatically set on open. Even if you set `dtr_on_open` to false,
401    /// DTR will be asserted for a short moment when opening the port. This can't be prevented
402    /// without kernel modifications.
403    #[must_use]
404    pub fn dtr_on_open(mut self, state: bool) -> Self {
405        self.dtr_on_open = Some(state);
406        self
407    }
408
409    /// Preserve the state of data terminal ready (DTR) when opening the device. Your outcome may
410    /// vary depending on the operation system. For example, Linux sets DTR by default and Windows
411    /// doesn't.
412    #[must_use]
413    pub fn preserve_dtr_on_open(mut self) -> Self {
414        self.dtr_on_open = None;
415        self
416    }
417
418    /// Open a cross-platform interface to the port with the specified settings
419    pub fn open(self) -> Result<Box<dyn SerialPort>> {
420        #[cfg(unix)]
421        return posix::TTYPort::open(&self).map(|p| Box::new(p) as Box<dyn SerialPort>);
422
423        #[cfg(windows)]
424        return windows::COMPort::open(&self).map(|p| Box::new(p) as Box<dyn SerialPort>);
425
426        #[cfg(not(any(unix, windows)))]
427        Err(Error::new(
428            ErrorKind::Unknown,
429            "open() not implemented for platform",
430        ))
431    }
432
433    /// Open a platform-specific interface to the port with the specified settings
434    #[cfg(unix)]
435    pub fn open_native(self) -> Result<TTYPort> {
436        posix::TTYPort::open(&self)
437    }
438
439    /// Open a platform-specific interface to the port with the specified settings
440    #[cfg(windows)]
441    pub fn open_native(self) -> Result<COMPort> {
442        windows::COMPort::open(&self)
443    }
444}
445
446/// A trait for serial port devices
447///
448/// This trait is all that's necessary to implement a new serial port driver
449/// for a new platform.
450pub trait SerialPort: Send + io::Read + io::Write {
451    // Port settings getters
452
453    /// Returns the name of this port if it exists.
454    ///
455    /// This name may not be the canonical device name and instead be shorthand.
456    /// Additionally it may not exist for virtual ports.
457    fn name(&self) -> Option<String>;
458
459    /// Returns the current baud rate.
460    ///
461    /// This may return a value different from the last specified baud rate depending on the
462    /// platform as some will return the actual device baud rate rather than the last specified
463    /// baud rate.
464    fn baud_rate(&self) -> Result<u32>;
465
466    /// Returns the character size.
467    ///
468    /// This function returns `None` if the character size could not be determined. This may occur
469    /// if the hardware is in an uninitialized state or is using a non-standard character size.
470    /// Setting a baud rate with `set_char_size()` should initialize the character size to a
471    /// supported value.
472    fn data_bits(&self) -> Result<DataBits>;
473
474    /// Returns the flow control mode.
475    ///
476    /// This function returns `None` if the flow control mode could not be determined. This may
477    /// occur if the hardware is in an uninitialized state or is using an unsupported flow control
478    /// mode. Setting a flow control mode with `set_flow_control()` should initialize the flow
479    /// control mode to a supported value.
480    fn flow_control(&self) -> Result<FlowControl>;
481
482    /// Returns the parity-checking mode.
483    ///
484    /// This function returns `None` if the parity mode could not be determined. This may occur if
485    /// the hardware is in an uninitialized state or is using a non-standard parity mode. Setting
486    /// a parity mode with `set_parity()` should initialize the parity mode to a supported value.
487    fn parity(&self) -> Result<Parity>;
488
489    /// Returns the number of stop bits.
490    ///
491    /// This function returns `None` if the number of stop bits could not be determined. This may
492    /// occur if the hardware is in an uninitialized state or is using an unsupported stop bit
493    /// configuration. Setting the number of stop bits with `set_stop-bits()` should initialize the
494    /// stop bits to a supported value.
495    fn stop_bits(&self) -> Result<StopBits>;
496
497    /// Returns the current timeout.
498    fn timeout(&self) -> Duration;
499
500    // Port settings setters
501
502    /// Sets the baud rate.
503    ///
504    /// ## Errors
505    ///
506    /// If the implementation does not support the requested baud rate, this function may return an
507    /// `InvalidInput` error. Even if the baud rate is accepted by `set_baud_rate()`, it may not be
508    /// supported by the underlying hardware.
509    fn set_baud_rate(&mut self, baud_rate: u32) -> Result<()>;
510
511    /// Sets the character size.
512    fn set_data_bits(&mut self, data_bits: DataBits) -> Result<()>;
513
514    /// Sets the flow control mode.
515    fn set_flow_control(&mut self, flow_control: FlowControl) -> Result<()>;
516
517    /// Sets the parity-checking mode.
518    fn set_parity(&mut self, parity: Parity) -> Result<()>;
519
520    /// Sets the number of stop bits.
521    fn set_stop_bits(&mut self, stop_bits: StopBits) -> Result<()>;
522
523    /// Sets the timeout for future I/O operations.
524    ///
525    /// <div class="warning">
526    ///
527    /// The accuracy is limited by the underlying platform's capabilities. Longer timeouts will be
528    /// clamped to the maximum supported value which is expected to be in the magnitude of a few
529    /// days.
530    ///
531    /// </div>
532    fn set_timeout(&mut self, timeout: Duration) -> Result<()>;
533
534    // Functions for setting non-data control signal pins
535
536    /// Sets the state of the RTS (Request To Send) control signal.
537    ///
538    /// Setting a value of `true` asserts the RTS control signal. `false` clears the signal.
539    ///
540    /// ## Errors
541    ///
542    /// This function returns an error if the RTS control signal could not be set to the desired
543    /// state on the underlying hardware:
544    ///
545    /// * `NoDevice` if the device was disconnected.
546    /// * `Io` for any other type of I/O error.
547    fn write_request_to_send(&mut self, level: bool) -> Result<()>;
548
549    /// Writes to the Data Terminal Ready pin
550    ///
551    /// Setting a value of `true` asserts the DTR control signal. `false` clears the signal.
552    ///
553    /// ## Errors
554    ///
555    /// This function returns an error if the DTR control signal could not be set to the desired
556    /// state on the underlying hardware:
557    ///
558    /// * `NoDevice` if the device was disconnected.
559    /// * `Io` for any other type of I/O error.
560    fn write_data_terminal_ready(&mut self, level: bool) -> Result<()>;
561
562    // Functions for reading additional pins
563
564    /// Reads the state of the CTS (Clear To Send) control signal.
565    ///
566    /// This function returns a boolean that indicates whether the CTS control signal is asserted.
567    ///
568    /// ## Errors
569    ///
570    /// This function returns an error if the state of the CTS control signal could not be read
571    /// from the underlying hardware:
572    ///
573    /// * `NoDevice` if the device was disconnected.
574    /// * `Io` for any other type of I/O error.
575    fn read_clear_to_send(&mut self) -> Result<bool>;
576
577    /// Reads the state of the Data Set Ready control signal.
578    ///
579    /// This function returns a boolean that indicates whether the DSR control signal is asserted.
580    ///
581    /// ## Errors
582    ///
583    /// This function returns an error if the state of the DSR control signal could not be read
584    /// from the underlying hardware:
585    ///
586    /// * `NoDevice` if the device was disconnected.
587    /// * `Io` for any other type of I/O error.
588    fn read_data_set_ready(&mut self) -> Result<bool>;
589
590    /// Reads the state of the Ring Indicator control signal.
591    ///
592    /// This function returns a boolean that indicates whether the RI control signal is asserted.
593    ///
594    /// ## Errors
595    ///
596    /// This function returns an error if the state of the RI control signal could not be read from
597    /// the underlying hardware:
598    ///
599    /// * `NoDevice` if the device was disconnected.
600    /// * `Io` for any other type of I/O error.
601    fn read_ring_indicator(&mut self) -> Result<bool>;
602
603    /// Reads the state of the Carrier Detect control signal.
604    ///
605    /// This function returns a boolean that indicates whether the CD control signal is asserted.
606    ///
607    /// ## Errors
608    ///
609    /// This function returns an error if the state of the CD control signal could not be read from
610    /// the underlying hardware:
611    ///
612    /// * `NoDevice` if the device was disconnected.
613    /// * `Io` for any other type of I/O error.
614    fn read_carrier_detect(&mut self) -> Result<bool>;
615
616    /// Gets the number of bytes available to be read from the input buffer.
617    ///
618    /// # Errors
619    ///
620    /// This function may return the following errors:
621    ///
622    /// * `NoDevice` if the device was disconnected.
623    /// * `Io` for any other type of I/O error.
624    fn bytes_to_read(&self) -> Result<u32>;
625
626    /// Get the number of bytes written to the output buffer, awaiting transmission.
627    ///
628    /// # Errors
629    ///
630    /// This function may return the following errors:
631    ///
632    /// * `NoDevice` if the device was disconnected.
633    /// * `Io` for any other type of I/O error.
634    fn bytes_to_write(&self) -> Result<u32>;
635
636    /// Discards all bytes from the serial driver's input buffer and/or output buffer.
637    ///
638    /// # Errors
639    ///
640    /// This function may return the following errors:
641    ///
642    /// * `NoDevice` if the device was disconnected.
643    /// * `Io` for any other type of I/O error.
644    fn clear(&self, buffer_to_clear: ClearBuffer) -> Result<()>;
645
646    // Misc methods
647
648    /// Attempts to clone the `SerialPort`. This allow you to write and read simultaneously from the
649    /// same serial connection. Please note that if you want a real asynchronous serial port you
650    /// should look at [mio-serial](https://crates.io/crates/mio-serial) or
651    /// [tokio-serial](https://crates.io/crates/tokio-serial).
652    ///
653    /// Also, you must be very careful when changing the settings of a cloned `SerialPort` : since
654    /// the settings are cached on a per object basis, trying to modify them from two different
655    /// objects can cause some nasty behavior.
656    ///
657    /// # Errors
658    ///
659    /// This function returns an error if the serial port couldn't be cloned.
660    fn try_clone(&self) -> Result<Box<dyn SerialPort>>;
661
662    /// Start transmitting a break
663    fn set_break(&self) -> Result<()>;
664
665    /// Stop transmitting a break
666    fn clear_break(&self) -> Result<()>;
667}
668
669impl<T: SerialPort> SerialPort for &mut T {
670    fn name(&self) -> Option<String> {
671        (**self).name()
672    }
673
674    fn baud_rate(&self) -> Result<u32> {
675        (**self).baud_rate()
676    }
677
678    fn data_bits(&self) -> Result<DataBits> {
679        (**self).data_bits()
680    }
681
682    fn flow_control(&self) -> Result<FlowControl> {
683        (**self).flow_control()
684    }
685
686    fn parity(&self) -> Result<Parity> {
687        (**self).parity()
688    }
689
690    fn stop_bits(&self) -> Result<StopBits> {
691        (**self).stop_bits()
692    }
693
694    fn timeout(&self) -> Duration {
695        (**self).timeout()
696    }
697
698    fn set_baud_rate(&mut self, baud_rate: u32) -> Result<()> {
699        (**self).set_baud_rate(baud_rate)
700    }
701
702    fn set_data_bits(&mut self, data_bits: DataBits) -> Result<()> {
703        (**self).set_data_bits(data_bits)
704    }
705
706    fn set_flow_control(&mut self, flow_control: FlowControl) -> Result<()> {
707        (**self).set_flow_control(flow_control)
708    }
709
710    fn set_parity(&mut self, parity: Parity) -> Result<()> {
711        (**self).set_parity(parity)
712    }
713
714    fn set_stop_bits(&mut self, stop_bits: StopBits) -> Result<()> {
715        (**self).set_stop_bits(stop_bits)
716    }
717
718    fn set_timeout(&mut self, timeout: Duration) -> Result<()> {
719        (**self).set_timeout(timeout)
720    }
721
722    fn write_request_to_send(&mut self, level: bool) -> Result<()> {
723        (**self).write_request_to_send(level)
724    }
725
726    fn write_data_terminal_ready(&mut self, level: bool) -> Result<()> {
727        (**self).write_data_terminal_ready(level)
728    }
729
730    fn read_clear_to_send(&mut self) -> Result<bool> {
731        (**self).read_clear_to_send()
732    }
733
734    fn read_data_set_ready(&mut self) -> Result<bool> {
735        (**self).read_data_set_ready()
736    }
737
738    fn read_ring_indicator(&mut self) -> Result<bool> {
739        (**self).read_ring_indicator()
740    }
741
742    fn read_carrier_detect(&mut self) -> Result<bool> {
743        (**self).read_carrier_detect()
744    }
745
746    fn bytes_to_read(&self) -> Result<u32> {
747        (**self).bytes_to_read()
748    }
749
750    fn bytes_to_write(&self) -> Result<u32> {
751        (**self).bytes_to_write()
752    }
753
754    fn clear(&self, buffer_to_clear: ClearBuffer) -> Result<()> {
755        (**self).clear(buffer_to_clear)
756    }
757
758    fn try_clone(&self) -> Result<Box<dyn SerialPort>> {
759        (**self).try_clone()
760    }
761
762    fn set_break(&self) -> Result<()> {
763        (**self).set_break()
764    }
765
766    fn clear_break(&self) -> Result<()> {
767        (**self).clear_break()
768    }
769}
770
771impl fmt::Debug for dyn SerialPort {
772    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
773        write!(f, "SerialPort ( ")?;
774
775        if let Some(n) = self.name().as_ref() {
776            write!(f, "name: {} ", n)?;
777        };
778        if let Ok(b) = self.baud_rate().as_ref() {
779            write!(f, "baud_rate: {} ", b)?;
780        };
781        if let Ok(b) = self.data_bits().as_ref() {
782            write!(f, "data_bits: {} ", b)?;
783        };
784        if let Ok(c) = self.flow_control().as_ref() {
785            write!(f, "flow_control: {} ", c)?;
786        }
787        if let Ok(p) = self.parity().as_ref() {
788            write!(f, "parity: {} ", p)?;
789        }
790        if let Ok(s) = self.stop_bits().as_ref() {
791            write!(f, "stop_bits: {} ", s)?;
792        }
793
794        write!(f, ")")
795    }
796}
797
798/// Contains all possible USB information about a `SerialPort`
799#[derive(Debug, Clone, PartialEq, Eq)]
800#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
801pub struct UsbPortInfo {
802    /// Vendor ID
803    pub vid: u16,
804    /// Product ID
805    pub pid: u16,
806    /// Serial number (arbitrary string)
807    pub serial_number: Option<String>,
808    /// Manufacturer (arbitrary string)
809    pub manufacturer: Option<String>,
810    /// Product name (arbitrary string)
811    pub product: Option<String>,
812    /// The interface index of the USB serial port. This can be either the interface number of
813    /// the communication interface (as is the case on Windows and Linux) or the data
814    /// interface (as is the case on macOS), so you should recognize both interface numbers.
815    #[cfg(feature = "usbportinfo-interface")]
816    pub interface: Option<u8>,
817}
818
819/// The physical type of a `SerialPort`
820#[derive(Debug, Clone, PartialEq, Eq)]
821#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
822pub enum SerialPortType {
823    /// The serial port is connected via USB
824    UsbPort(UsbPortInfo),
825    /// The serial port is connected via PCI (permanent port)
826    PciPort,
827    /// The serial port is connected via Bluetooth
828    BluetoothPort,
829    /// It can't be determined how the serial port is connected
830    Unknown,
831}
832
833/// A device-independent implementation of serial port information
834#[derive(Debug, Clone, PartialEq, Eq)]
835#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
836pub struct SerialPortInfo {
837    /// The short name of the serial port
838    pub port_name: String,
839    /// The hardware device type that exposes this port
840    pub port_type: SerialPortType,
841}
842
843/// Construct a builder of `SerialPort` objects
844///
845/// `SerialPort` objects are built using the Builder pattern through the `new` function. The
846/// resultant `SerialPortBuilder` object can be copied, reconfigured, and saved making working with
847/// multiple serial ports a little easier.
848///
849/// To open a new serial port:
850/// ```no_run
851/// serialport::new("/dev/ttyUSB0", 9600).open().expect("Failed to open port");
852/// ```
853pub fn new<'a>(path: impl Into<std::borrow::Cow<'a, str>>, baud_rate: u32) -> SerialPortBuilder {
854    SerialPortBuilder {
855        path: path.into().into_owned(),
856        baud_rate,
857        data_bits: DataBits::Eight,
858        flow_control: FlowControl::None,
859        parity: Parity::None,
860        stop_bits: StopBits::One,
861        timeout: Duration::from_millis(0),
862        // By default, set DTR when opening the device. There are USB devices performing "wait for
863        // DTR" before sending any data and users stumbled over this multiple times (see issues #29
864        // and #204). We are expecting little to no negative consequences from setting DTR by
865        // default but less hassle for users.
866        dtr_on_open: Some(true),
867    }
868}
869
870/// Returns a list of all serial ports on system
871///
872/// It is not guaranteed that these ports exist or are available even if they're
873/// returned by this function.
874pub fn available_ports() -> Result<Vec<SerialPortInfo>> {
875    #[cfg(unix)]
876    return crate::posix::available_ports();
877
878    #[cfg(windows)]
879    return crate::windows::available_ports();
880
881    #[cfg(not(any(unix, windows)))]
882    Err(Error::new(
883        ErrorKind::Unknown,
884        "available_ports() not implemented for platform",
885    ))
886}