serial_io/unix.rs
1//! Unix impl of mio-enabled serial ports.
2
3use std::io::{self, Read, Write};
4use std::os::unix::prelude::*;
5use std::time::Duration;
6
7use mio::event::Source;
8use mio::unix::SourceFd;
9use mio::{Interest, Registry, Token};
10
11use serialport::{
12 ClearBuffer, DataBits, Error, ErrorKind, FlowControl, Parity, SerialPort, SerialPortBuilder,
13 StopBits, TTYPort,
14};
15
16use nix::sys::termios::{self, SetArg, SpecialCharacterIndices};
17use nix::{self, libc};
18
19#[cfg(feature = "tokio")]
20pub mod tokio;
21
22/// *nix serial port using termios
23#[derive(Debug)]
24pub struct Serial {
25 inner: TTYPort,
26}
27
28fn map_nix_error(e: nix::Error) -> Error {
29 Error {
30 kind: ErrorKind::Io(io::ErrorKind::Other),
31 description: e.to_string(),
32 }
33}
34
35impl Serial {
36 /// Open a non-blocking serial port from the provided builder.
37 ///
38 /// ## Example
39 ///
40 /// ```ignore
41 /// use serial_io::{build, Serial, TTYPort};
42 ///
43 /// let builder = build(tty_path, 9600);
44 /// let serial = Serial::from_builder(&builder).unwrap();
45 /// # fn main() {}
46 /// ```
47 pub fn from_builder(builder: &SerialPortBuilder) -> crate::Result<Self> {
48 let port = TTYPort::open(builder).unwrap();
49 Self::from_serial(port)
50 }
51
52 fn from_serial(port: TTYPort) -> crate::Result<Self> {
53 // Get the termios structure
54 let mut t = termios::tcgetattr(port.as_raw_fd()).map_err(map_nix_error)?;
55
56 // Set VMIN = 1 to block until at least one character is received.
57 t.control_chars[SpecialCharacterIndices::VMIN as usize] = 1;
58 termios::tcsetattr(port.as_raw_fd(), SetArg::TCSANOW, &t).map_err(map_nix_error)?;
59
60 // Set the O_NONBLOCK flag.
61 let flags = unsafe { libc::fcntl(port.as_raw_fd(), libc::F_GETFL) };
62 if flags < 0 {
63 return Err(io::Error::last_os_error().into());
64 }
65
66 match unsafe { libc::fcntl(port.as_raw_fd(), libc::F_SETFL, flags | libc::O_NONBLOCK) } {
67 0 => Ok(Serial { inner: port }),
68 _ => Err(io::Error::last_os_error().into()),
69 }
70 }
71
72 /// Create a pair of pseudo serial terminals
73 ///
74 /// ## Returns
75 /// Two connected `Serial` objects: `(master, slave)`
76 ///
77 /// ## Errors
78 /// Attempting any IO or parameter settings on the slave tty after the master
79 /// tty is closed will return errors.
80 ///
81 /// ## Examples
82 ///
83 /// ```
84 /// use serial_io::Serial;
85 ///
86 /// let (master, slave) = Serial::pair().unwrap();
87 /// ```
88 pub fn pair() -> crate::Result<(Self, Self)> {
89 let (master, slave) = TTYPort::pair()?;
90
91 let master = Self::from_serial(master)?;
92 let slave = Self::from_serial(slave)?;
93
94 Ok((master, slave))
95 }
96
97 /// Sets the exclusivity of the port
98 ///
99 /// If a port is exclusive, then trying to open the same device path again
100 /// will fail.
101 ///
102 /// See the man pages for the tiocexcl and tiocnxcl ioctl's for more details.
103 ///
104 /// ## Errors
105 ///
106 /// * `Io` for any error while setting exclusivity for the port.
107 pub fn set_exclusive(&mut self, exclusive: bool) -> crate::Result<()> {
108 self.inner.set_exclusive(exclusive).map_err(|e| e)
109 }
110
111 /// Returns the exclusivity of the port
112 ///
113 /// If a port is exclusive, then trying to open the same device path again
114 /// will fail.
115 pub fn exclusive(&self) -> bool {
116 self.inner.exclusive()
117 }
118}
119
120impl SerialPort for Serial {
121 /// Return the name associated with the serial port, if known.
122 fn name(&self) -> Option<String> {
123 self.inner.name()
124 }
125
126 /// Returns the current baud rate.
127 ///
128 /// This function returns `None` if the baud rate could not be determined. This may occur if
129 /// the hardware is in an uninitialized state. Setting a baud rate with `set_baud_rate()`
130 /// should initialize the baud rate to a supported value.
131 fn baud_rate(&self) -> crate::Result<u32> {
132 self.inner.baud_rate()
133 }
134
135 /// Returns the character size.
136 ///
137 /// This function returns `None` if the character size could not be determined. This may occur
138 /// if the hardware is in an uninitialized state or is using a non-standard character size.
139 /// Setting a baud rate with `set_char_size()` should initialize the character size to a
140 /// supported value.
141 fn data_bits(&self) -> crate::Result<DataBits> {
142 self.inner.data_bits()
143 }
144
145 /// Returns the flow control mode.
146 ///
147 /// This function returns `None` if the flow control mode could not be determined. This may
148 /// occur if the hardware is in an uninitialized state or is using an unsupported flow control
149 /// mode. Setting a flow control mode with `set_flow_control()` should initialize the flow
150 /// control mode to a supported value.
151 fn flow_control(&self) -> crate::Result<FlowControl> {
152 self.inner.flow_control()
153 }
154
155 /// Returns the parity-checking mode.
156 ///
157 /// This function returns `None` if the parity mode could not be determined. This may occur if
158 /// the hardware is in an uninitialized state or is using a non-standard parity mode. Setting
159 /// a parity mode with `set_parity()` should initialize the parity mode to a supported value.
160 fn parity(&self) -> crate::Result<Parity> {
161 self.inner.parity()
162 }
163
164 /// Returns the number of stop bits.
165 ///
166 /// This function returns `None` if the number of stop bits could not be determined. This may
167 /// occur if the hardware is in an uninitialized state or is using an unsupported stop bit
168 /// configuration. Setting the number of stop bits with `set_stop-bits()` should initialize the
169 /// stop bits to a supported value.
170 fn stop_bits(&self) -> crate::Result<StopBits> {
171 self.inner.stop_bits()
172 }
173
174 /// Returns the current timeout. This parameter is const and equal to zero and implemented due
175 /// to required for trait completeness.
176 fn timeout(&self) -> Duration {
177 Duration::from_secs(0)
178 }
179
180 /// Sets the baud rate.
181 ///
182 /// ## Errors
183 ///
184 /// If the implementation does not support the requested baud rate, this function may return an
185 /// `InvalidInput` error. Even if the baud rate is accepted by `set_baud_rate()`, it may not be
186 /// supported by the underlying hardware.
187 fn set_baud_rate(&mut self, baud_rate: u32) -> crate::Result<()> {
188 self.inner.set_baud_rate(baud_rate)
189 }
190
191 /// Sets the character size.
192 fn set_data_bits(&mut self, data_bits: DataBits) -> crate::Result<()> {
193 self.inner.set_data_bits(data_bits)
194 }
195
196 /// Sets the flow control mode.
197 fn set_flow_control(&mut self, flow_control: FlowControl) -> crate::Result<()> {
198 self.inner.set_flow_control(flow_control)
199 }
200
201 /// Sets the parity-checking mode.
202 fn set_parity(&mut self, parity: Parity) -> crate::Result<()> {
203 self.inner.set_parity(parity)
204 }
205
206 /// Sets the number of stop bits.
207 fn set_stop_bits(&mut self, stop_bits: StopBits) -> crate::Result<()> {
208 self.inner.set_stop_bits(stop_bits)
209 }
210
211 /// Sets the timeout for future I/O operations. This parameter is ignored but
212 /// required for trait completeness.
213 fn set_timeout(&mut self, _: Duration) -> crate::Result<()> {
214 Ok(())
215 }
216
217 // Functions for setting non-data control signal pins
218
219 /// Sets the state of the RTS (Request To Send) control signal.
220 ///
221 /// Setting a value of `true` asserts the RTS control signal. `false` clears the signal.
222 ///
223 /// ## Errors
224 ///
225 /// This function returns an error if the RTS control signal could not be set to the desired
226 /// state on the underlying hardware:
227 ///
228 /// * `NoDevice` if the device was disconnected.
229 /// * `Io` for any other type of I/O error.
230 fn write_request_to_send(&mut self, level: bool) -> crate::Result<()> {
231 self.inner.write_request_to_send(level)
232 }
233
234 /// Writes to the Data Terminal Ready pin
235 ///
236 /// Setting a value of `true` asserts the DTR control signal. `false` clears the signal.
237 ///
238 /// ## Errors
239 ///
240 /// This function returns an error if the DTR control signal could not be set to the desired
241 /// state on the underlying hardware:
242 ///
243 /// * `NoDevice` if the device was disconnected.
244 /// * `Io` for any other type of I/O error.
245 fn write_data_terminal_ready(&mut self, level: bool) -> crate::Result<()> {
246 self.inner.write_data_terminal_ready(level)
247 }
248
249 // Functions for reading additional pins
250
251 /// Reads the state of the CTS (Clear To Send) control signal.
252 ///
253 /// This function returns a boolean that indicates whether the CTS control signal is asserted.
254 ///
255 /// ## Errors
256 ///
257 /// This function returns an error if the state of the CTS control signal could not be read
258 /// from the underlying hardware:
259 ///
260 /// * `NoDevice` if the device was disconnected.
261 /// * `Io` for any other type of I/O error.
262 fn read_clear_to_send(&mut self) -> crate::Result<bool> {
263 self.inner.read_clear_to_send()
264 }
265
266 /// Reads the state of the Data Set Ready control signal.
267 ///
268 /// This function returns a boolean that indicates whether the DSR control signal is asserted.
269 ///
270 /// ## Errors
271 ///
272 /// This function returns an error if the state of the DSR control signal could not be read
273 /// from the underlying hardware:
274 ///
275 /// * `NoDevice` if the device was disconnected.
276 /// * `Io` for any other type of I/O error.
277 fn read_data_set_ready(&mut self) -> crate::Result<bool> {
278 self.inner.read_data_set_ready()
279 }
280
281 /// Reads the state of the Ring Indicator control signal.
282 ///
283 /// This function returns a boolean that indicates whether the RI control signal is asserted.
284 ///
285 /// ## Errors
286 ///
287 /// This function returns an error if the state of the RI control signal could not be read from
288 /// the underlying hardware:
289 ///
290 /// * `NoDevice` if the device was disconnected.
291 /// * `Io` for any other type of I/O error.
292 fn read_ring_indicator(&mut self) -> crate::Result<bool> {
293 self.inner.read_ring_indicator()
294 }
295
296 /// Reads the state of the Carrier Detect control signal.
297 ///
298 /// This function returns a boolean that indicates whether the CD control signal is asserted.
299 ///
300 /// ## Errors
301 ///
302 /// This function returns an error if the state of the CD control signal could not be read from
303 /// the underlying hardware:
304 ///
305 /// * `NoDevice` if the device was disconnected.
306 /// * `Io` for any other type of I/O error.
307 fn read_carrier_detect(&mut self) -> crate::Result<bool> {
308 self.inner.read_carrier_detect()
309 }
310
311 /// Gets the number of bytes available to be read from the input buffer.
312 ///
313 /// # Errors
314 ///
315 /// This function may return the following errors:
316 ///
317 /// * `NoDevice` if the device was disconnected.
318 /// * `Io` for any other type of I/O error.
319 fn bytes_to_read(&self) -> crate::Result<u32> {
320 self.inner.bytes_to_read()
321 }
322
323 /// Get the number of bytes written to the output buffer, awaiting transmission.
324 ///
325 /// # Errors
326 ///
327 /// This function may return the following errors:
328 ///
329 /// * `NoDevice` if the device was disconnected.
330 /// * `Io` for any other type of I/O error.
331 fn bytes_to_write(&self) -> crate::Result<u32> {
332 self.inner.bytes_to_write()
333 }
334
335 /// Discards all bytes from the serial driver's input buffer and/or output buffer.
336 ///
337 /// # Errors
338 ///
339 /// This function may return the following errors:
340 ///
341 /// * `NoDevice` if the device was disconnected.
342 /// * `Io` for any other type of I/O error.
343 fn clear(&self, buffer_to_clear: ClearBuffer) -> crate::Result<()> {
344 self.inner.clear(buffer_to_clear)
345 }
346
347 /// Attempts to clone the `SerialPort`. This allow you to write and read simultaneously from the
348 /// same serial connection. Please note that if you want a real asynchronous serial port you
349 /// should look at [mio-serial](https://crates.io/crates/mio-serial) or
350 /// [tokio-serial](https://crates.io/crates/tokio-serial).
351 ///
352 /// Also, you must be very carefull when changing the settings of a cloned `SerialPort` : since
353 /// the settings are cached on a per object basis, trying to modify them from two different
354 /// objects can cause some nasty behavior.
355 ///
356 /// # Errors
357 ///
358 /// This function returns an error if the serial port couldn't be cloned.
359 fn try_clone(&self) -> crate::Result<Box<dyn SerialPort>> {
360 self.inner.try_clone()
361 }
362
363 /// Start transmitting a break
364 fn set_break(&self) -> crate::Result<()> {
365 self.inner.set_break()
366 }
367
368 /// Stop transmitting a break
369 fn clear_break(&self) -> crate::Result<()> {
370 self.inner.clear_break()
371 }
372}
373
374macro_rules! uninterruptibly {
375 ($e:expr) => {{
376 loop {
377 match $e {
378 Err(ref error) if error.kind() == io::ErrorKind::Interrupted => {}
379 res => break res,
380 }
381 }
382 }};
383}
384
385impl Read for Serial {
386 fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
387 uninterruptibly!(match unsafe {
388 libc::read(
389 self.as_raw_fd(),
390 bytes.as_ptr() as *mut libc::c_void,
391 bytes.len() as libc::size_t,
392 )
393 } {
394 x if x >= 0 => Ok(x as usize),
395 _ => Err(io::Error::last_os_error()),
396 })
397 }
398}
399
400impl Write for Serial {
401 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
402 uninterruptibly!(match unsafe {
403 libc::write(
404 self.as_raw_fd(),
405 bytes.as_ptr() as *const libc::c_void,
406 bytes.len() as libc::size_t,
407 )
408 } {
409 x if x >= 0 => Ok(x as usize),
410 _ => Err(io::Error::last_os_error()),
411 })
412 }
413
414 fn flush(&mut self) -> io::Result<()> {
415 uninterruptibly!(
416 termios::tcdrain(self.inner.as_raw_fd()).map_err(|error| match error {
417 nix::Error::Sys(errno) => io::Error::from(errno),
418 error => io::Error::new(io::ErrorKind::Other, error.to_string()),
419 })
420 )
421 }
422}
423
424impl<'a> Read for &'a Serial {
425 fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
426 uninterruptibly!(match unsafe {
427 libc::read(
428 self.as_raw_fd(),
429 bytes.as_ptr() as *mut libc::c_void,
430 bytes.len() as libc::size_t,
431 )
432 } {
433 x if x >= 0 => Ok(x as usize),
434 _ => Err(io::Error::last_os_error()),
435 })
436 }
437}
438
439impl<'a> Write for &'a Serial {
440 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
441 uninterruptibly!(match unsafe {
442 libc::write(
443 self.as_raw_fd(),
444 bytes.as_ptr() as *const libc::c_void,
445 bytes.len() as libc::size_t,
446 )
447 } {
448 x if x >= 0 => Ok(x as usize),
449 _ => Err(io::Error::last_os_error()),
450 })
451 }
452
453 fn flush(&mut self) -> io::Result<()> {
454 uninterruptibly!(
455 termios::tcdrain(self.inner.as_raw_fd()).map_err(|error| match error {
456 nix::Error::Sys(errno) => io::Error::from(errno),
457 error => io::Error::new(io::ErrorKind::Other, error.to_string()),
458 })
459 )
460 }
461}
462
463impl AsRawFd for Serial {
464 fn as_raw_fd(&self) -> RawFd {
465 self.inner.as_raw_fd()
466 }
467}
468
469impl IntoRawFd for Serial {
470 fn into_raw_fd(self) -> RawFd {
471 self.inner.into_raw_fd()
472 }
473}
474
475impl FromRawFd for Serial {
476 unsafe fn from_raw_fd(fd: RawFd) -> Self {
477 let port = TTYPort::from_raw_fd(fd);
478 Serial { inner: port }
479 }
480}
481
482impl Source for Serial {
483 fn register(
484 &mut self,
485 registry: &Registry,
486 token: Token,
487 interests: Interest,
488 ) -> io::Result<()> {
489 SourceFd(&self.as_raw_fd()).register(registry, token, interests)
490 }
491
492 fn reregister(
493 &mut self,
494 registry: &Registry,
495 token: Token,
496 interests: Interest,
497 ) -> io::Result<()> {
498 SourceFd(&self.as_raw_fd()).reregister(registry, token, interests)
499 }
500
501 fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
502 SourceFd(&self.as_raw_fd()).deregister(registry)
503 }
504}