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