tokio_serial/
lib.rs

1//! Bindings for serial port I/O and futures
2//!
3//! This crate provides bindings between `mio_serial`, a mio crate for
4//! serial port I/O, and `futures`.  The API is very similar to the
5//! bindings in `mio_serial`
6//!
7#![deny(missing_docs)]
8#![warn(rust_2018_idioms)]
9
10// Re-export serialport types and traits from mio_serial
11pub use mio_serial::{
12    available_ports, new, ClearBuffer, DataBits, Error, ErrorKind, FlowControl, Parity, SerialPort,
13    SerialPortBuilder, SerialPortInfo, SerialPortType, StopBits, UsbPortInfo,
14};
15
16use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
17
18#[cfg(unix)]
19use std::convert::TryFrom;
20use std::io::{Read, Result as IoResult, Write};
21use std::pin::Pin;
22use std::task::{Context, Poll};
23use std::time::Duration;
24
25#[cfg(feature = "codec")]
26pub mod frame;
27
28#[cfg(unix)]
29mod os_prelude {
30    pub use futures::ready;
31    pub use tokio::io::unix::AsyncFd;
32}
33
34#[cfg(windows)]
35mod os_prelude {
36    pub use std::mem;
37    pub use std::ops::{Deref, DerefMut};
38    pub use std::os::windows::prelude::*;
39    pub use tokio::net::windows::named_pipe;
40}
41
42use crate::os_prelude::*;
43
44/// A type for results generated by interacting with serial ports.
45pub type Result<T> = mio_serial::Result<T>;
46
47/// Async serial port I/O
48///
49/// Reading and writing to a `SerialStream` is usually done using the
50/// convenience methods found on the [`tokio::io::AsyncReadExt`] and [`tokio::io::AsyncWriteExt`]
51/// traits.
52///
53/// [`AsyncReadExt`]: trait@tokio::io::AsyncReadExt
54/// [`AsyncWriteExt`]: trait@tokio::io::AsyncWriteExt
55///
56#[derive(Debug)]
57pub struct SerialStream {
58    #[cfg(unix)]
59    inner: AsyncFd<mio_serial::SerialStream>,
60    // Named pipes and COM ports are actually two entirely different things that hardly have anything in common.
61    // The only thing they share is the opaque `HANDLE` type that can be fed into `CreateFileW`, `ReadFile`, `WriteFile`, etc.
62    //
63    // Both `mio` and `tokio` don't yet have any code to work on arbitrary HANDLEs.
64    // But they have code for dealing with named pipes, and we (ab)use that here to work on COM ports.
65    #[cfg(windows)]
66    inner: named_pipe::NamedPipeClient,
67    // The com port is kept around for serialport related methods
68    #[cfg(windows)]
69    com: mem::ManuallyDrop<mio_serial::SerialStream>,
70}
71
72impl SerialStream {
73    /// Open serial port from a provided path, using the default reactor.
74    pub fn open(builder: &crate::SerialPortBuilder) -> crate::Result<Self> {
75        let port = mio_serial::SerialStream::open(builder)?;
76
77        #[cfg(unix)]
78        {
79            Ok(Self {
80                inner: AsyncFd::new(port)?,
81            })
82        }
83
84        #[cfg(windows)]
85        {
86            let handle = port.as_raw_handle();
87            // Keep the com port around to use for serialport related things
88            let com = mem::ManuallyDrop::new(port);
89            Ok(Self {
90                inner: unsafe { named_pipe::NamedPipeClient::from_raw_handle(handle)? },
91                com,
92            })
93        }
94    }
95
96    /// Create a pair of pseudo serial terminals using the default reactor
97    ///
98    /// ## Returns
99    /// Two connected, unnamed `Serial` objects.
100    ///
101    /// ## Errors
102    /// Attempting any IO or parameter settings on the slave tty after the master
103    /// tty is closed will return errors.
104    ///
105    /// ## Examples
106    ///
107    /// ```no_run
108    /// use tokio_serial::SerialStream;
109    ///
110    /// #[tokio::main]
111    /// async fn main() {
112    ///     let (master, slave) = SerialStream::pair().unwrap();
113    /// }
114    /// ```
115    #[cfg(unix)]
116    pub fn pair() -> crate::Result<(Self, Self)> {
117        let (master, slave) = mio_serial::SerialStream::pair()?;
118
119        let master = SerialStream {
120            inner: AsyncFd::new(master)?,
121        };
122        let slave = SerialStream {
123            inner: AsyncFd::new(slave)?,
124        };
125        Ok((master, slave))
126    }
127
128    /// Sets the exclusivity of the port
129    ///
130    /// If a port is exclusive, then trying to open the same device path again
131    /// will fail.
132    ///
133    /// See the man pages for the tiocexcl and tiocnxcl ioctl's for more details.
134    ///
135    /// ## Errors
136    ///
137    /// * `Io` for any error while setting exclusivity for the port.
138    #[cfg(unix)]
139    pub fn set_exclusive(&mut self, exclusive: bool) -> crate::Result<()> {
140        self.inner.get_mut().set_exclusive(exclusive)
141    }
142
143    /// Returns the exclusivity of the port
144    ///
145    /// If a port is exclusive, then trying to open the same device path again
146    /// will fail.
147    #[cfg(unix)]
148    pub fn exclusive(&self) -> bool {
149        self.inner.get_ref().exclusive()
150    }
151
152    /// Borrow a reference to the underlying mio-serial::SerialStream object.
153    #[inline(always)]
154    fn borrow(&self) -> &mio_serial::SerialStream {
155        #[cfg(unix)]
156        {
157            self.inner.get_ref()
158        }
159        #[cfg(windows)]
160        {
161            self.com.deref()
162        }
163    }
164
165    /// Borrow a mutable reference to the underlying mio-serial::SerialStream object.
166    #[inline(always)]
167    fn borrow_mut(&mut self) -> &mut mio_serial::SerialStream {
168        #[cfg(unix)]
169        {
170            self.inner.get_mut()
171        }
172        #[cfg(windows)]
173        {
174            self.com.deref_mut()
175        }
176    }
177    /// Try to read bytes on the serial port.  On success returns the number of bytes read.
178    ///
179    /// The function must be called with valid byte array `buf` of sufficient
180    /// size to hold the message bytes. If a message is too long to fit in the
181    /// supplied buffer, excess bytes may be discarded.
182    ///
183    /// When there is no pending data, `Err(io::ErrorKind::WouldBlock)` is
184    /// returned. This function is usually paired with `readable()`.
185    pub fn try_read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
186        #[cfg(unix)]
187        {
188            self.inner.get_mut().read(buf)
189        }
190        #[cfg(windows)]
191        {
192            self.inner.try_read(buf)
193        }
194    }
195
196    /// Wait for the port to become readable.
197    ///
198    /// This function is usually paired with `try_read()`.
199    ///
200    /// The function may complete without the socket being readable. This is a
201    /// false-positive and attempting a `try_read()` will return with
202    /// `io::ErrorKind::WouldBlock`.
203    pub async fn readable(&self) -> IoResult<()> {
204        let _ = self.inner.readable().await?;
205        Ok(())
206    }
207
208    /// Try to write bytes on the serial port.  On success returns the number of bytes written.
209    ///
210    /// When the write would block, `Err(io::ErrorKind::WouldBlock)` is
211    /// returned. This function is usually paired with `writable()`.
212    pub fn try_write(&mut self, buf: &[u8]) -> IoResult<usize> {
213        #[cfg(unix)]
214        {
215            self.inner.get_mut().write(buf)
216        }
217        #[cfg(windows)]
218        {
219            self.inner.try_write(buf)
220        }
221    }
222
223    /// Wait for the port to become writable.
224    ///
225    /// This function is usually paired with `try_write()`.
226    ///
227    /// The function may complete without the socket being readable. This is a
228    /// false-positive and attempting a `try_write()` will return with
229    /// `io::ErrorKind::WouldBlock`.
230    pub async fn writable(&self) -> IoResult<()> {
231        let _ = self.inner.writable().await?;
232        Ok(())
233    }
234}
235
236#[cfg(unix)]
237impl AsyncRead for SerialStream {
238    /// Attempts to ready bytes on the serial port.
239    ///
240    /// Note that on multiple calls to a `poll_*` method in the read direction, only the
241    /// `Waker` from the `Context` passed to the most recent call will be scheduled to
242    /// receive a wakeup.
243    ///
244    /// # Return value
245    ///
246    /// The function returns:
247    ///
248    /// * `Poll::Pending` if the socket is not ready to read
249    /// * `Poll::Ready(Ok(()))` reads data `ReadBuf` if the socket is ready
250    /// * `Poll::Ready(Err(e))` if an error is encountered.
251    ///
252    /// # Errors
253    ///
254    /// This function may encounter any standard I/O error except `WouldBlock`.
255    fn poll_read(
256        self: Pin<&mut Self>,
257        cx: &mut Context<'_>,
258        buf: &mut ReadBuf<'_>,
259    ) -> Poll<IoResult<()>> {
260        loop {
261            let mut guard = ready!(self.inner.poll_read_ready(cx))?;
262
263            match guard.try_io(|inner| inner.get_ref().read(buf.initialize_unfilled())) {
264                Ok(Ok(bytes_read)) => {
265                    buf.advance(bytes_read);
266                    return Poll::Ready(Ok(()));
267                }
268                Ok(Err(err)) => {
269                    return Poll::Ready(Err(err));
270                }
271                Err(_would_block) => continue,
272            }
273        }
274    }
275}
276
277#[cfg(unix)]
278impl AsyncWrite for SerialStream {
279    /// Attempts to send data on the serial port
280    ///
281    /// Note that on multiple calls to a `poll_*` method in the send direction,
282    /// only the `Waker` from the `Context` passed to the most recent call will
283    /// be scheduled to receive a wakeup.
284    ///
285    /// # Return value
286    ///
287    /// The function returns:
288    ///
289    /// * `Poll::Pending` if the socket is not available to write
290    /// * `Poll::Ready(Ok(n))` `n` is the number of bytes sent
291    /// * `Poll::Ready(Err(e))` if an error is encountered.
292    ///
293    /// # Errors
294    ///
295    /// This function may encounter any standard I/O error except `WouldBlock`.
296    fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<IoResult<usize>> {
297        loop {
298            let mut guard = ready!(self.inner.poll_write_ready(cx))?;
299
300            match guard.try_io(|inner| inner.get_ref().write(buf)) {
301                Ok(result) => return Poll::Ready(result),
302                Err(_would_block) => continue,
303            }
304        }
305    }
306
307    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<IoResult<()>> {
308        loop {
309            let mut guard = ready!(self.inner.poll_write_ready(cx))?;
310            match guard.try_io(|inner| inner.get_ref().flush()) {
311                Ok(_) => return Poll::Ready(Ok(())),
312                Err(_would_block) => continue,
313            }
314        }
315    }
316
317    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<IoResult<()>> {
318        let _ = self.poll_flush(cx)?;
319        Ok(()).into()
320    }
321}
322
323#[cfg(windows)]
324impl AsyncRead for SerialStream {
325    fn poll_read(
326        self: Pin<&mut Self>,
327        cx: &mut Context<'_>,
328        buf: &mut ReadBuf<'_>,
329    ) -> Poll<IoResult<()>> {
330        let mut self_ = self;
331        Pin::new(&mut self_.inner).poll_read(cx, buf)
332    }
333}
334
335#[cfg(windows)]
336impl AsyncWrite for SerialStream {
337    fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<IoResult<usize>> {
338        let mut self_ = self;
339        Pin::new(&mut self_.inner).poll_write(cx, buf)
340    }
341
342    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<IoResult<()>> {
343        let mut self_ = self;
344        Pin::new(&mut self_.inner).poll_flush(cx)
345    }
346
347    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<IoResult<()>> {
348        let mut self_ = self;
349        Pin::new(&mut self_.inner).poll_shutdown(cx)
350    }
351}
352
353impl crate::SerialPort for SerialStream {
354    #[inline(always)]
355    fn name(&self) -> Option<String> {
356        self.borrow().name()
357    }
358
359    #[inline(always)]
360    fn baud_rate(&self) -> crate::Result<u32> {
361        self.borrow().baud_rate()
362    }
363
364    #[inline(always)]
365    fn data_bits(&self) -> crate::Result<crate::DataBits> {
366        self.borrow().data_bits()
367    }
368
369    #[inline(always)]
370    fn flow_control(&self) -> crate::Result<crate::FlowControl> {
371        self.borrow().flow_control()
372    }
373
374    #[inline(always)]
375    fn parity(&self) -> crate::Result<crate::Parity> {
376        self.borrow().parity()
377    }
378
379    #[inline(always)]
380    fn stop_bits(&self) -> crate::Result<crate::StopBits> {
381        self.borrow().stop_bits()
382    }
383
384    #[inline(always)]
385    fn timeout(&self) -> Duration {
386        Duration::from_secs(0)
387    }
388
389    #[inline(always)]
390    fn set_baud_rate(&mut self, baud_rate: u32) -> crate::Result<()> {
391        self.borrow_mut().set_baud_rate(baud_rate)
392    }
393
394    #[inline(always)]
395    fn set_data_bits(&mut self, data_bits: crate::DataBits) -> crate::Result<()> {
396        self.borrow_mut().set_data_bits(data_bits)
397    }
398
399    #[inline(always)]
400    fn set_flow_control(&mut self, flow_control: crate::FlowControl) -> crate::Result<()> {
401        self.borrow_mut().set_flow_control(flow_control)
402    }
403
404    #[inline(always)]
405    fn set_parity(&mut self, parity: crate::Parity) -> crate::Result<()> {
406        self.borrow_mut().set_parity(parity)
407    }
408
409    #[inline(always)]
410    fn set_stop_bits(&mut self, stop_bits: crate::StopBits) -> crate::Result<()> {
411        self.borrow_mut().set_stop_bits(stop_bits)
412    }
413
414    #[inline(always)]
415    fn set_timeout(&mut self, _: Duration) -> crate::Result<()> {
416        Ok(())
417    }
418
419    #[inline(always)]
420    fn write_request_to_send(&mut self, level: bool) -> crate::Result<()> {
421        self.borrow_mut().write_request_to_send(level)
422    }
423
424    #[inline(always)]
425    fn write_data_terminal_ready(&mut self, level: bool) -> crate::Result<()> {
426        self.borrow_mut().write_data_terminal_ready(level)
427    }
428
429    #[inline(always)]
430    fn read_clear_to_send(&mut self) -> crate::Result<bool> {
431        self.borrow_mut().read_clear_to_send()
432    }
433
434    #[inline(always)]
435    fn read_data_set_ready(&mut self) -> crate::Result<bool> {
436        self.borrow_mut().read_data_set_ready()
437    }
438
439    #[inline(always)]
440    fn read_ring_indicator(&mut self) -> crate::Result<bool> {
441        self.borrow_mut().read_ring_indicator()
442    }
443
444    #[inline(always)]
445    fn read_carrier_detect(&mut self) -> crate::Result<bool> {
446        self.borrow_mut().read_carrier_detect()
447    }
448
449    #[inline(always)]
450    fn bytes_to_read(&self) -> crate::Result<u32> {
451        self.borrow().bytes_to_read()
452    }
453
454    #[inline(always)]
455    fn bytes_to_write(&self) -> crate::Result<u32> {
456        self.borrow().bytes_to_write()
457    }
458
459    #[inline(always)]
460    fn clear(&self, buffer_to_clear: crate::ClearBuffer) -> crate::Result<()> {
461        self.borrow().clear(buffer_to_clear)
462    }
463
464    /// Cloning SerialStream is not supported.
465    ///
466    /// # Errors
467    /// Always returns `ErrorKind::Other` with a message.
468    #[inline(always)]
469    fn try_clone(&self) -> crate::Result<Box<dyn crate::SerialPort>> {
470        Err(crate::Error::new(
471            crate::ErrorKind::Io(std::io::ErrorKind::Other),
472            "Cannot clone Tokio handles",
473        ))
474    }
475
476    #[inline(always)]
477    fn set_break(&self) -> crate::Result<()> {
478        self.borrow().set_break()
479    }
480
481    #[inline(always)]
482    fn clear_break(&self) -> crate::Result<()> {
483        self.borrow().clear_break()
484    }
485}
486
487impl Read for SerialStream {
488    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
489        self.try_read(buf)
490    }
491}
492
493impl Write for SerialStream {
494    fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
495        self.try_write(buf)
496    }
497
498    fn flush(&mut self) -> IoResult<()> {
499        self.borrow_mut().flush()
500    }
501}
502
503#[cfg(unix)]
504impl TryFrom<serialport::TTYPort> for SerialStream {
505    type Error = Error;
506
507    fn try_from(value: serialport::TTYPort) -> std::result::Result<Self, Self::Error> {
508        let port = mio_serial::SerialStream::try_from(value)?;
509        Ok(Self {
510            inner: AsyncFd::new(port)?,
511        })
512    }
513}
514
515#[cfg(unix)]
516mod sys {
517    use super::SerialStream;
518    use std::os::unix::io::{AsRawFd, RawFd};
519    impl AsRawFd for SerialStream {
520        fn as_raw_fd(&self) -> RawFd {
521            self.inner.as_raw_fd()
522        }
523    }
524}
525
526#[cfg(windows)]
527mod io {
528    use super::SerialStream;
529    use std::os::windows::io::{AsRawHandle, RawHandle};
530    impl AsRawHandle for SerialStream {
531        fn as_raw_handle(&self) -> RawHandle {
532            self.inner.as_raw_handle()
533        }
534    }
535}
536
537/// An extension trait for serialport::SerialPortBuilder
538///
539/// This trait adds one method to SerialPortBuilder:
540///
541/// - open_native_async
542///
543/// This method mirrors the `open_native` method of SerialPortBuilder
544pub trait SerialPortBuilderExt {
545    /// Open a platform-specific interface to the port with the specified settings
546    fn open_native_async(self) -> Result<SerialStream>;
547}
548
549impl SerialPortBuilderExt for SerialPortBuilder {
550    /// Open a platform-specific interface to the port with the specified settings
551    fn open_native_async(self) -> Result<SerialStream> {
552        SerialStream::open(&self)
553    }
554}