serial_io/unix/
tokio.rs

1//! Async interface to serial-io via tokio.
2//! You need to enable the `tokio` feature to use this.
3//!
4
5use crate::{ClearBuffer, DataBits, FlowControl, Parity, Serial, SerialPort, StopBits};
6
7use futures::ready;
8use serialport::SerialPortBuilder;
9use std::io::{self, Read, Write};
10use std::pin::Pin;
11use std::task::{Context, Poll};
12use std::time::Duration;
13use tokio::io::unix::AsyncFd;
14use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
15
16/// Serial port I/O struct.
17pub struct AsyncSerial {
18    io: AsyncFd<Serial>,
19}
20
21impl AsyncSerial {
22    /// Open a non-blocking tokio-compatible serial port from the provided port.
23    pub fn from_builder(builder: &SerialPortBuilder) -> io::Result<AsyncSerial> {
24        let serial = Serial::from_builder(builder)?;
25        let io = AsyncFd::new(serial)?;
26
27        Ok(AsyncSerial { io })
28    }
29
30    /// Create a pair of pseudo serial terminals using the default reactor
31    ///
32    /// ## Returns
33    /// Two connected, unnamed `Serial` objects.
34    ///
35    /// ## Errors
36    /// Attempting any IO or parameter settings on the slave tty after the master
37    /// tty is closed will return errors.
38    ///
39    pub fn pair() -> crate::Result<(Self, Self)> {
40        let (master, slave) = Serial::pair()?;
41
42        let master = AsyncSerial {
43            io: AsyncFd::new(master)?,
44        };
45        let slave = AsyncSerial {
46            io: AsyncFd::new(slave)?,
47        };
48        Ok((master, slave))
49    }
50
51    /// Sets the exclusivity of the port
52    ///
53    /// If a port is exclusive, then trying to open the same device path again
54    /// will fail.
55    ///
56    /// See the man pages for the tiocexcl and tiocnxcl ioctl's for more details.
57    ///
58    /// ## Errors
59    ///
60    /// * `Io` for any error while setting exclusivity for the port.
61    pub fn set_exclusive(&mut self, exclusive: bool) -> crate::Result<()> {
62        self.io.get_mut().set_exclusive(exclusive)
63    }
64
65    /// Returns the exclusivity of the port
66    ///
67    /// If a port is exclusive, then trying to open the same device path again
68    /// will fail.
69    pub fn exclusive(&self) -> bool {
70        self.io.get_ref().exclusive()
71    }
72}
73
74impl SerialPort for AsyncSerial {
75    fn name(&self) -> Option<String> {
76        self.io.get_ref().name()
77    }
78
79    fn baud_rate(&self) -> crate::Result<u32> {
80        self.io.get_ref().baud_rate()
81    }
82
83    fn data_bits(&self) -> crate::Result<DataBits> {
84        self.io.get_ref().data_bits()
85    }
86
87    fn flow_control(&self) -> crate::Result<FlowControl> {
88        self.io.get_ref().flow_control()
89    }
90
91    fn parity(&self) -> crate::Result<Parity> {
92        self.io.get_ref().parity()
93    }
94
95    fn stop_bits(&self) -> crate::Result<StopBits> {
96        self.io.get_ref().stop_bits()
97    }
98
99    fn timeout(&self) -> Duration {
100        Duration::from_secs(0)
101    }
102
103    fn set_baud_rate(&mut self, baud_rate: u32) -> crate::Result<()> {
104        self.io.get_mut().set_baud_rate(baud_rate)
105    }
106
107    fn set_data_bits(&mut self, data_bits: DataBits) -> crate::Result<()> {
108        self.io.get_mut().set_data_bits(data_bits)
109    }
110
111    fn set_flow_control(&mut self, flow_control: FlowControl) -> crate::Result<()> {
112        self.io.get_mut().set_flow_control(flow_control)
113    }
114
115    fn set_parity(&mut self, parity: Parity) -> crate::Result<()> {
116        self.io.get_mut().set_parity(parity)
117    }
118
119    fn set_stop_bits(&mut self, stop_bits: StopBits) -> crate::Result<()> {
120        self.io.get_mut().set_stop_bits(stop_bits)
121    }
122
123    fn set_timeout(&mut self, _: Duration) -> crate::Result<()> {
124        Ok(())
125    }
126
127    fn write_request_to_send(&mut self, level: bool) -> crate::Result<()> {
128        self.io.get_mut().write_request_to_send(level)
129    }
130
131    fn write_data_terminal_ready(&mut self, level: bool) -> crate::Result<()> {
132        self.io.get_mut().write_data_terminal_ready(level)
133    }
134
135    fn read_clear_to_send(&mut self) -> crate::Result<bool> {
136        self.io.get_mut().read_clear_to_send()
137    }
138
139    fn read_data_set_ready(&mut self) -> crate::Result<bool> {
140        self.io.get_mut().read_data_set_ready()
141    }
142
143    fn read_ring_indicator(&mut self) -> crate::Result<bool> {
144        self.io.get_mut().read_ring_indicator()
145    }
146
147    fn read_carrier_detect(&mut self) -> crate::Result<bool> {
148        self.io.get_mut().read_carrier_detect()
149    }
150
151    fn bytes_to_read(&self) -> crate::Result<u32> {
152        self.io.get_ref().bytes_to_read()
153    }
154
155    fn bytes_to_write(&self) -> crate::Result<u32> {
156        self.io.get_ref().bytes_to_write()
157    }
158
159    fn clear(&self, buffer_to_clear: ClearBuffer) -> crate::Result<()> {
160        self.io.get_ref().clear(buffer_to_clear)
161    }
162
163    fn try_clone(&self) -> crate::Result<Box<dyn SerialPort>> {
164        self.io.get_ref().try_clone()
165    }
166
167    /// Start transmitting a break
168    fn set_break(&self) -> crate::Result<()> {
169        self.io.get_ref().set_break()
170    }
171
172    /// Stop transmitting a break
173    fn clear_break(&self) -> crate::Result<()> {
174        self.io.get_ref().clear_break()
175    }
176}
177
178impl Read for AsyncSerial {
179    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
180        self.io.get_mut().read(buf)
181    }
182}
183
184impl Write for AsyncSerial {
185    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
186        self.io.get_mut().write(buf)
187    }
188
189    fn flush(&mut self) -> io::Result<()> {
190        self.io.get_mut().flush()
191    }
192}
193
194use std::os::unix::io::{AsRawFd, RawFd};
195impl AsRawFd for AsyncSerial {
196    fn as_raw_fd(&self) -> RawFd {
197        self.io.as_raw_fd()
198    }
199}
200
201impl AsyncRead for AsyncSerial {
202    fn poll_read(
203        self: Pin<&mut Self>,
204        cx: &mut Context<'_>,
205        buf: &mut ReadBuf<'_>,
206    ) -> Poll<io::Result<()>> {
207        loop {
208            let mut guard = ready!(self.io.poll_read_ready(cx))?;
209            match guard.try_io(|_| {
210                let read = self.io.get_ref().read(buf.initialize_unfilled())?;
211                buf.advance(read);
212                Ok(())
213            }) {
214                Ok(result) => return Poll::Ready(result),
215                Err(_would_block) => continue,
216            }
217        }
218    }
219}
220
221impl AsyncWrite for AsyncSerial {
222    fn poll_write(
223        self: Pin<&mut Self>,
224        cx: &mut Context<'_>,
225        buf: &[u8],
226    ) -> Poll<io::Result<usize>> {
227        loop {
228            let mut guard = ready!(self.io.poll_write_ready(cx))?;
229            match guard.try_io(|_| self.io.get_ref().write(buf)) {
230                Ok(x) => return Poll::Ready(x),
231                Err(_would_block) => continue,
232            }
233        }
234    }
235
236    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
237        loop {
238            let mut guard = ready!(self.io.poll_write_ready(cx))?;
239            match guard.try_io(|_| self.io.get_ref().flush()) {
240                Ok(x) => return Poll::Ready(x),
241                Err(_would_block) => continue,
242            }
243        }
244    }
245
246    fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
247        Poll::Ready(Ok(()))
248    }
249}