Skip to main content

rpi_pal/
uart.rs

1//! Interface for the UART peripherals and any USB to serial adapters.
2//!
3//! rpi-pal controls the Raspberry Pi's UART peripherals through the `ttyAMA0`
4//! (PL011) and `ttyS0` (mini UART) character devices. USB to serial adapters
5//! are controlled using the `ttyUSBx` and `ttyACMx` character devices.
6//!
7//! ## UART peripherals
8//!
9//! The Raspberry Pi's BCM283x SoC features two UART peripherals.
10//! `/dev/ttyAMA0` represents the PL011 UART, which offers a full set of
11//! features. `/dev/ttyS0` represents an auxiliary peripheral that's referred
12//! to as mini UART, with limited capabilities. More details on the differences
13//! between the PL011 and mini UART can be found in the official Raspberry Pi
14//! [documentation].
15//!
16//! On earlier Raspberry Pi models without Bluetooth, `/dev/ttyAMA0` is
17//! configured as a Linux serial console. On more recent models with Bluetooth,
18//! `/dev/ttyAMA0` is connected to the Bluetooth
19//! module, and `/dev/ttyS0` is used as a serial console instead. Due to the
20//! limitations of `/dev/ttyS0` and the requirement for a fixed core frequency,
21//! in most cases you'll want to use `/dev/ttyAMA0` for serial communication.
22//!
23//! By default, TX (outgoing data) is tied to BCM GPIO 14 (physical pin 8) and
24//! RX (incoming data) is tied to BCM GPIO 15 (physical pin 10). You can move
25//! these lines to different GPIO pins using the `uart0` and `uart1` overlays,
26//! but the alternative pin options aren't exposed through the GPIO header on
27//! any of the current Raspberry Pi models. They are only available on the
28//! Compute Module's SO-DIMM pads.
29//!
30//! ## Configure `/dev/ttyAMA0` for serial communication (recommended)
31//!
32//! Disable the Linux serial console by either deactivating it through
33//! `sudo raspi-config`, or manually removing the parameter
34//! `console=serial0,115200` from `/boot/firmware/cmdline.txt`.
35//!
36//! Remove any lines containing `enable_uart=0` or `enable_uart=1` from
37//! `/boot/firmware/config.txt`.
38//!
39//! On Raspberry Pi models with a Bluetooth module, an extra step is required
40//! to either disable Bluetooth or move it to `/dev/ttyS0`, so `/dev/ttyAMA0`
41//! becomes available for serial communication.
42//!
43//! To disable Bluetooth, add `dtoverlay=pi3-disable-bt` to `/boot/firmware/config.txt`.
44//! You'll also need to disable the service that initializes Bluetooth with
45//! `sudo systemctl disable hciuart`.
46//!
47//! To move the Bluetooth module to `/dev/ttyS0`, instead of disabling it with
48//! the above-mentioned steps, add `dtoverlay=pi3-miniuart-bt` and
49//! `core_freq=250` to `/boot/firmware/config.txt`.
50//!
51//! Remember to reboot the Raspberry Pi after making any changes.
52//!
53//! ## Configure `/dev/ttyS0` for serial communication
54//!
55//! If you prefer to leave the Bluetooth module connected to `/dev/ttyAMA0`,
56//! you can configure `/dev/ttyS0` for serial communication instead.
57//!
58//! Disable the Linux serial console by either deactivating it through
59//! `sudo raspi-config`, or manually removing the parameter
60//! `console=serial0,115200` from `/boot/firmware/cmdline.txt`.
61//!
62//! Add the line `enable_uart=1` to `/boot/firmware/config.txt` to enable serial
63//! communication on `/dev/ttyS0`, which also sets a fixed core frequency.
64//!
65//! Remember to reboot the Raspberry Pi after making any changes.
66//!
67//! ## USB to serial adapters
68//!
69//! In addition to controlling the hardware UART peripherals, [`Uart`] can
70//! also be used for USB to serial adapters. Depending on the type of
71//! device, these can be accessed either through `/dev/ttyUSBx` or
72//! `/dev/ttyACMx`, where `x` is an index starting at `0`. The numbering is
73//! based on the order in which the devices are discovered by the kernel.
74//!
75//! When you have multiple USB to serial adapters connected at the same time,
76//! you can uniquely identify a specific device by searching for the relevant
77//! symlink in the `/dev/serial/by-id` directory, or by adding your own
78//! `udev` rules.
79//!
80//! Support for automatic software (XON/XOFF) and hardware (RTS/CTS) flow
81//! control for USB to serial adapters depends on the USB interface IC on the
82//! device, and the relevant Linux driver. Some ICs use an older,
83//! incompatible RTS/CTS implementation, sometimes referred to as legacy or
84//! simplex mode, where RTS is used to indicate data is about to be
85//! transmitted, rather than to request the external device to resume its
86//! transmission.
87//!
88//! ## Hardware flow control
89//!
90//! The RTS/CTS hardware flow control implementation supported by [`Uart`]
91//! and used by the Raspberry Pi's UART peripherals requires RTS on one
92//! device to be connected to CTS on the other device. The RTS signal is
93//! used to request the other device to pause or resume its transmission.
94//!
95//! Some devices use an older, incompatible RTS/CTS implementation, sometimes
96//! referred to as legacy or simplex mode, where RTS is connected to RTS, and
97//! CTS to CTS. The RTS signal is used to indicate data is about to be
98//! transmitted. [`Uart`] is not compatible with this implementation.
99//! Connecting the Raspberry Pi's RTS and CTS pins incorrectly could damage
100//! the Pi or the external device.
101//!
102//! When [`Uart`] is controlling a UART peripheral, enabling hardware flow
103//! control will also configure the RTS and CTS pins. On Raspberry Pi models
104//! with a 40-pin GPIO header, RTS is tied to BCM GPIO 17 (physical pin 11)
105//! and CTS is tied to BCM GPIO 16 (physical pin 36). RTS and CTS aren't
106//! available on models with a 26-pin header, except for the Raspberry Pi B
107//! Rev 2, which exposes RTS and CTS through its unpopulated P5 header with
108//! RTS on BCM GPIO 31 (physical pin 6) and CTS on BCM GPIO 30 (physical pin
109//! 5).
110//!
111//! The RTS and CTS pins are reset to their original state when [`Uart`] goes
112//! out of scope. Note that `drop` methods aren't called when a process is
113//! abnormally terminated, for instance when a user presses <kbd>Ctrl</kbd> +
114//! <kbd>C</kbd> and the `SIGINT` signal isn't caught, which prevents [`Uart`]
115//! from resetting the pins. You can catch those using crates such as
116//! [`simple_signal`].
117//!
118//! ## Troubleshooting
119//!
120//! ### Permission denied
121//!
122//! If [`new`] or [`with_path`] returns an `io::ErrorKind::PermissionDenied`
123//! error, make sure the file permissions for the specified device are correct,
124//! and the current user is a member of the group that owns the device, which is
125//! usually either `dialout` or `tty`.
126//!
127//! [documentation]: https://www.raspberrypi.org/documentation/configuration/uart.md
128//! [`simple_signal`]: https://crates.io/crates/simple-signal
129//! [`Uart`]: struct.Uart.html
130//! [`new`]: struct.Uart.html#method.new
131//! [`with_path`]: struct.Uart.html#method.with_path
132
133use std::error;
134use std::fmt;
135use std::fs::{self, File, OpenOptions};
136use std::io;
137use std::io::{Read, Write};
138use std::os::unix::fs::OpenOptionsExt;
139use std::os::unix::io::{AsRawFd, RawFd};
140use std::path::Path;
141use std::result;
142use std::time::Duration;
143
144use libc::{c_int, O_NOCTTY, O_NONBLOCK};
145use libc::{TIOCM_CAR, TIOCM_CTS, TIOCM_DSR, TIOCM_DTR, TIOCM_RNG, TIOCM_RTS};
146
147use crate::gpio::{self, Gpio, IoPin, Mode};
148use crate::system::{self, DeviceInfo, Model, SoC};
149
150#[cfg(any(
151    feature = "embedded-hal-0",
152    feature = "embedded-hal",
153    feature = "embedded-hal-nb"
154))]
155mod hal;
156mod termios;
157
158const GPIO_RTS: u8 = 17;
159const GPIO_CTS: u8 = 16;
160
161const GPIO_RTS_BREV2: u8 = 31;
162const GPIO_CTS_BREV2: u8 = 30;
163
164const GPIO_RTS_MODE_UART0: Mode = Mode::Alt3;
165const GPIO_CTS_MODE_UART0: Mode = Mode::Alt3;
166
167const GPIO_RTS_MODE_UART1: Mode = Mode::Alt5;
168const GPIO_CTS_MODE_UART1: Mode = Mode::Alt5;
169
170/// Errors that can occur when accessing the UART peripheral.
171#[derive(Debug)]
172pub enum Error {
173    /// I/O error.
174    Io(io::Error),
175    /// GPIO error.
176    Gpio(gpio::Error),
177    /// Invalid or unsupported value.
178    InvalidValue,
179}
180
181impl fmt::Display for Error {
182    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183        match *self {
184            Error::Io(ref err) => write!(f, "I/O error: {}", err),
185            Error::Gpio(ref err) => write!(f, "GPIO error: {}", err),
186            Error::InvalidValue => write!(f, "Invalid or unsupported value"),
187        }
188    }
189}
190
191impl error::Error for Error {}
192
193impl From<io::Error> for Error {
194    fn from(err: io::Error) -> Error {
195        Error::Io(err)
196    }
197}
198
199impl From<gpio::Error> for Error {
200    fn from(err: gpio::Error) -> Error {
201        Error::Gpio(err)
202    }
203}
204
205impl From<system::Error> for Error {
206    fn from(_err: system::Error) -> Error {
207        Error::Gpio(gpio::Error::UnknownModel)
208    }
209}
210
211/// Result type returned from methods that can have `uart::Error`s.
212pub type Result<T> = result::Result<T, Error>;
213
214/// Parity bit modes.
215///
216/// The parity bit mode determines how the parity bit is calculated.
217///
218/// `None` omits the parity bit. `Even` and `Odd` count the total number of
219/// 1-bits in the data bits. `Mark` and `Space` always set the parity
220/// bit to `1` or `0` respectively.
221#[derive(Debug, PartialEq, Eq, Copy, Clone)]
222pub enum Parity {
223    /// No parity bit.
224    None,
225    /// Even parity.
226    Even,
227    /// Odd parity.
228    Odd,
229    /// Sets parity bit to `1`.
230    Mark,
231    /// Sets parity bit to `0`.
232    Space,
233}
234
235impl fmt::Display for Parity {
236    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237        match *self {
238            Parity::None => write!(f, "None"),
239            Parity::Even => write!(f, "Even"),
240            Parity::Odd => write!(f, "Odd"),
241            Parity::Mark => write!(f, "Mark"),
242            Parity::Space => write!(f, "Space"),
243        }
244    }
245}
246
247/// Parity check modes.
248///
249/// The parity check mode determines how parity errors are handled.
250#[derive(Debug, PartialEq, Eq, Copy, Clone)]
251pub enum ParityCheck {
252    /// Ignores parity errors.
253    None,
254    /// Removes bytes with parity errors from the input queue.
255    Strip,
256    /// Replaces bytes with parity errors with a `0` byte.
257    Replace,
258    /// Marks bytes with parity errors with a preceding `255` and `0` byte.
259    ///
260    /// Actual `255` bytes are replaced with two `255` bytes to avoid confusion
261    /// with parity errors.
262    Mark,
263}
264
265impl fmt::Display for ParityCheck {
266    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267        match *self {
268            ParityCheck::None => write!(f, "None"),
269            ParityCheck::Strip => write!(f, "Strip"),
270            ParityCheck::Replace => write!(f, "Replace"),
271            ParityCheck::Mark => write!(f, "Mark"),
272        }
273    }
274}
275
276/// Queue types.
277#[derive(Debug, PartialEq, Eq, Copy, Clone)]
278pub enum Queue {
279    /// Input queue.
280    Input,
281    /// Output queue.
282    Output,
283    /// Both queues.
284    Both,
285}
286
287impl fmt::Display for Queue {
288    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
289        match *self {
290            Queue::Input => write!(f, "Input"),
291            Queue::Output => write!(f, "Output"),
292            Queue::Both => write!(f, "Both"),
293        }
294    }
295}
296
297/// Control signal status.
298pub struct Status {
299    tiocm: c_int,
300}
301
302impl Status {
303    /// Returns `true` if RTS is active.
304    ///
305    /// RTS (active low) is controlled by [`Uart`]. An active signal indicates
306    /// [`Uart`] is ready to receive more data.
307    ///
308    /// [`Uart`]: struct.Uart.html
309    pub fn rts(&self) -> bool {
310        self.tiocm & TIOCM_RTS > 0
311    }
312
313    /// Returns `true` if CTS is active.
314    ///
315    /// CTS (active low) is controlled by the external device. An active signal
316    /// indicates the external device is ready to receive more data.
317    pub fn cts(&self) -> bool {
318        self.tiocm & TIOCM_CTS > 0
319    }
320
321    /// Returns `true` if DTR is active.
322    ///
323    /// DTR (active low) is controlled by [`Uart`]. When communicating with a
324    /// modem, an active signal is used to place or accept a call. An inactive
325    /// signal causes the modem to hang up. Other devices may use DTR and DSR
326    /// for flow control.
327    ///
328    /// DTR is not supported by the Raspberry Pi's UART peripherals,
329    /// but may be available on some USB to serial adapters.
330    ///
331    /// [`Uart`]: struct.Uart.html
332    pub fn dtr(&self) -> bool {
333        self.tiocm & TIOCM_DTR > 0
334    }
335
336    /// Returns `true` if DSR is active.
337    ///
338    /// DSR (active low) is controlled by the external device. When
339    /// communicating with a modem, an active signal indicates the modem is
340    /// ready for data transmission. Other devices may use DTR and DSR for flow
341    /// control.
342    ///
343    /// DSR is not supported by the Raspberry Pi's UART peripherals,
344    /// but may be available on some USB to serial adapters.
345    pub fn dsr(&self) -> bool {
346        self.tiocm & TIOCM_DSR > 0
347    }
348
349    /// Returns `true` if DCD is active.
350    ///
351    /// DCD (active low) is controlled by the external device. When
352    /// communicating with a modem, an active signal indicates a connection is
353    /// established.
354    ///
355    /// DCD is not supported by the Raspberry Pi's UART peripherals,
356    /// but may be available on some USB to serial adapters.
357    pub fn dcd(&self) -> bool {
358        self.tiocm & TIOCM_CAR > 0
359    }
360
361    /// Returns `true` if RI is active.
362    ///
363    /// RI (active low) is controlled by the external device. When
364    /// communicating with a modem, an active signal indicates an incoming
365    /// call.
366    ///
367    /// RI is not supported by the Raspberry Pi's UART peripherals,
368    /// but may be available on some USB to serial adapters.
369    pub fn ri(&self) -> bool {
370        self.tiocm & TIOCM_RNG > 0
371    }
372}
373
374impl fmt::Debug for Status {
375    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376        f.debug_struct("Status")
377            .field("rts", &self.rts())
378            .field("cts", &self.cts())
379            .field("dtr", &self.dtr())
380            .field("dsr", &self.dsr())
381            .field("dcd", &self.dcd())
382            .field("ri", &self.ri())
383            .finish()
384    }
385}
386
387#[derive(Debug)]
388struct UartInner {
389    device: File,
390    fd: RawFd,
391    rtscts_mode: Option<(Mode, Mode)>,
392    rtscts_pins: Option<(IoPin, IoPin)>,
393    blocking_read: bool,
394    blocking_write: bool,
395    baud_rate: u32,
396    parity: Parity,
397    parity_check: ParityCheck,
398    data_bits: u8,
399    stop_bits: u8,
400    software_flow_control: bool,
401    hardware_flow_control: bool,
402}
403
404/// Provides access to the Raspberry Pi's UART peripherals and any USB to
405/// serial adapters.
406///
407/// The `embedded-hal` trait implementations for `Uart` can be enabled by specifying
408/// the optional `hal` feature in the dependency declaration for the `rpi_pal` crate.
409#[derive(Debug)]
410pub struct Uart {
411    inner: UartInner,
412}
413
414impl Uart {
415    /// Constructs a new `Uart`.
416    ///
417    /// `new` attempts to identify the UART peripheral tied to BCM GPIO 14 and
418    /// 15, and then calls [`with_path`] with the appropriate device path.
419    ///
420    /// [`with_path`]: #method.with_path
421    pub fn new(baud_rate: u32, parity: Parity, data_bits: u8, stop_bits: u8) -> Result<Uart> {
422        // On the Raspberry Pi 5, by default /dev/serial0 will point to the UART on the debug header,
423        // which is /dev/ttyAMA10. Check if /dev/ttyAMA0 exists first, which would mean the user
424        // enabled UART on GPIO14/15 and likely wants to use that one instead.
425        let path = match DeviceInfo::new()?.soc() {
426            SoC::Bcm2712 => {
427                if Path::new("/dev/ttyAMA0").exists() {
428                    "/dev/ttyAMA0"
429                } else {
430                    "/dev/serial0"
431                }
432            }
433            // Older models should use whatever /dev/serial0 points to.
434            _ => "/dev/serial0",
435        };
436
437        Self::with_path(path, baud_rate, parity, data_bits, stop_bits)
438    }
439
440    /// Constructs a new `Uart` connected to the serial character device
441    /// specified by `path`.
442    ///
443    /// `with_path` can be used to connect to either a UART peripheral or a USB
444    /// to serial adapter.
445    ///
446    /// When a new `Uart` is constructed, the specified device is configured
447    /// for non-canonical mode which processes input per character, ignores any
448    /// special terminal input or output characters and disables local echo. DCD
449    /// is ignored, all flow control is disabled, and the input and output queues
450    /// are flushed.
451    pub fn with_path<P: AsRef<Path>>(
452        path: P,
453        baud_rate: u32,
454        parity: Parity,
455        data_bits: u8,
456        stop_bits: u8,
457    ) -> Result<Uart> {
458        // Follow symbolic links
459        let path = fs::canonicalize(path)?;
460
461        // Check if we're using /dev/ttyAMA0 or /dev/ttyS0 so we can set the
462        // correct RTS/CTS pin modes when needed.
463        let rtscts_mode = if let Some(path_str) = path.to_str() {
464            match path_str {
465                "/dev/ttyAMA0" => Some((GPIO_RTS_MODE_UART0, GPIO_CTS_MODE_UART0)),
466                "/dev/ttyS0" => Some((GPIO_RTS_MODE_UART1, GPIO_CTS_MODE_UART1)),
467                _ => None,
468            }
469        } else {
470            None
471        };
472
473        let device = OpenOptions::new()
474            .read(true)
475            .write(true)
476            .custom_flags(O_NOCTTY | O_NONBLOCK)
477            .open(path)?;
478
479        let fd = device.as_raw_fd();
480
481        // Enables character input mode, disables echoing and any special
482        // processing
483        termios::set_raw_mode(fd)?;
484
485        // Non-blocking reads
486        termios::set_read_mode(fd, 0, Duration::default())?;
487
488        // Ignore modem control lines (CLOCAL)
489        termios::ignore_carrier_detect(fd)?;
490
491        // Enable receiver (CREAD)
492        termios::enable_read(fd)?;
493
494        // Disable software flow control (XON/XOFF)
495        termios::set_software_flow_control(fd, false, false)?;
496
497        // Disable hardware flow control (RTS/CTS)
498        termios::set_hardware_flow_control(fd, false)?;
499
500        termios::set_line_speed(fd, baud_rate)?;
501        termios::set_parity(fd, parity)?;
502        termios::set_data_bits(fd, data_bits)?;
503        termios::set_stop_bits(fd, stop_bits)?;
504
505        // Pass through parity errors unfiltered
506        termios::set_parity_check(fd, ParityCheck::None)?;
507
508        // Flush the input and output queue
509        termios::flush(fd, Queue::Both)?;
510
511        Ok(Uart {
512            inner: UartInner {
513                device,
514                fd,
515                rtscts_mode,
516                rtscts_pins: None,
517                blocking_read: false,
518                blocking_write: false,
519                baud_rate,
520                parity,
521                parity_check: ParityCheck::None,
522                data_bits,
523                stop_bits,
524                software_flow_control: false,
525                hardware_flow_control: false,
526            },
527        })
528    }
529
530    /// Returns the line speed in baud (Bd).
531    pub fn baud_rate(&self) -> u32 {
532        self.inner.baud_rate
533    }
534
535    /// Sets the line speed in baud (Bd).
536    ///
537    /// On the Raspberry Pi, baud rate is equivalent to bit rate in bits per
538    /// second (bit/s).
539    ///
540    /// Accepted values:
541    /// `0`, `50`, `75`, `110`, `134`, `150`, `200`, `300`, `600`, `1_200`,
542    /// `1_800`, `2_400`, `4_800`, `9_600`, `19_200`, `38_400`, `57_600`,
543    /// `115_200`, `230_400`, `460_800`, `500_000`, `576_000`, `921_600`,
544    /// `1_000_000`, `1_152_000`, `1_500_000`, `2_000_000`, `2_500_000`,
545    /// `3_000_000`, `3_500_000`, `4_000_000`.
546    ///
547    /// Support for some values may be device-dependent.
548    pub fn set_baud_rate(&mut self, baud_rate: u32) -> Result<()> {
549        termios::set_line_speed(self.inner.fd, baud_rate)?;
550
551        self.inner.baud_rate = baud_rate;
552
553        Ok(())
554    }
555
556    /// Returns the parity bit mode.
557    pub fn parity(&self) -> Parity {
558        self.inner.parity
559    }
560
561    /// Sets the parity bit mode.
562    ///
563    /// The parity bit mode determines how the parity bit is calculated.
564    ///
565    /// Support for some modes may be device-dependent.
566    pub fn set_parity(&mut self, parity: Parity) -> Result<()> {
567        termios::set_parity(self.inner.fd, parity)?;
568
569        self.inner.parity = parity;
570
571        Ok(())
572    }
573
574    /// Returns the parity check mode for incoming data.
575    pub fn parity_check(&self) -> ParityCheck {
576        self.inner.parity_check
577    }
578
579    /// Configures parity checking for incoming data.
580    ///
581    /// The parity check mode determines how parity errors are handled.
582    ///
583    /// By default, `parity_check` is set to [`None`].
584    ///
585    /// Support for some modes may be device-dependent.
586    ///
587    /// [`None`]: enum.ParityCheck.html#variant.None
588    pub fn set_parity_check(&mut self, parity_check: ParityCheck) -> Result<()> {
589        termios::set_parity_check(self.inner.fd, parity_check)?;
590
591        self.inner.parity_check = parity_check;
592
593        Ok(())
594    }
595
596    /// Returns the number of data bits.
597    pub fn data_bits(&self) -> u8 {
598        self.inner.data_bits
599    }
600
601    /// Sets the number of data bits.
602    ///
603    /// Accepted values: `5`, `6`, `7`, `8`.
604    ///
605    /// Support for some values may be device-dependent.
606    pub fn set_data_bits(&mut self, data_bits: u8) -> Result<()> {
607        termios::set_data_bits(self.inner.fd, data_bits)?;
608
609        self.inner.data_bits = data_bits;
610
611        Ok(())
612    }
613
614    /// Returns the number of stop bits.
615    pub fn stop_bits(&self) -> u8 {
616        self.inner.stop_bits
617    }
618
619    /// Sets the number of stop bits.
620    ///
621    /// Accepted values: `1`, `2`.
622    ///
623    /// Support for some values may be device-dependent.
624    pub fn set_stop_bits(&mut self, stop_bits: u8) -> Result<()> {
625        termios::set_stop_bits(self.inner.fd, stop_bits)?;
626
627        self.inner.stop_bits = stop_bits;
628
629        Ok(())
630    }
631
632    /// Returns the status of the control signals.
633    pub fn status(&self) -> Result<Status> {
634        let tiocm = termios::status(self.inner.fd)?;
635
636        Ok(Status { tiocm })
637    }
638
639    /// Sets DTR to active (`true`) or inactive (`false`).
640    ///
641    /// DTR is not supported by the Raspberry Pi's UART peripherals,
642    /// but may be available on some USB to serial adapters.
643    pub fn set_dtr(&mut self, dtr: bool) -> Result<()> {
644        termios::set_dtr(self.inner.fd, dtr)
645    }
646
647    /// Sets RTS to active (`true`) or inactive (`false`).
648    pub fn set_rts(&mut self, rts: bool) -> Result<()> {
649        termios::set_rts(self.inner.fd, rts)
650    }
651
652    /// Returns `true` if XON/XOFF software flow control is enabled.
653    pub fn software_flow_control(&self) -> bool {
654        self.inner.software_flow_control
655    }
656
657    /// Enables or disables XON/XOFF software flow control.
658    ///
659    /// When software flow control is enabled, incoming XON (decimal 17) and
660    /// XOFF (decimal 19) control characters are filtered from the input queue.
661    /// When XOFF is received, the transmission of data in the output queue is
662    /// paused until the external device sends XON. XOFF is automatically sent
663    /// to the external device to prevent the input queue from overflowing.
664    /// XON is sent when the input queue is ready for more data. You can also
665    /// manually send these control characters by calling [`send_stop`] and
666    /// [`send_start`].
667    ///
668    /// By default, software flow control is disabled.
669    ///
670    /// Support for XON/XOFF software flow control is
671    /// device-dependent. You can manually implement XON/XOFF by disabling
672    /// software flow control, parsing incoming XON/XOFF control characters
673    /// received with [`read`], and sending XON/XOFF when needed using
674    /// [`write`].
675    ///
676    /// [`send_start`]: #method.send_start
677    /// [`send_stop`]: #method.send_stop
678    /// [`read`]: #method.read
679    /// [`write`]: #method.write
680    pub fn set_software_flow_control(&mut self, software_flow_control: bool) -> Result<()> {
681        termios::set_software_flow_control(
682            self.inner.fd,
683            software_flow_control,
684            software_flow_control,
685        )?;
686
687        self.inner.software_flow_control = software_flow_control;
688
689        Ok(())
690    }
691
692    /// Returns `true` if RTS/CTS hardware flow control is enabled.
693    pub fn hardware_flow_control(&self) -> bool {
694        self.inner.hardware_flow_control
695    }
696
697    /// Enables or disables RTS/CTS hardware flow control.
698    ///
699    /// When hardware flow control is enabled, the RTS line (active low) is
700    /// automatically driven high to prevent the input queue from overflowing,
701    /// and driven low when the input queue is ready for more data. When the
702    /// CTS line (active low) is driven high by the external device, all data
703    /// in the output queue is held until CTS is driven low. You can also
704    /// manually change the active state of RTS by calling [`send_stop`] and
705    /// [`send_start`].
706    ///
707    /// When `Uart` is controlling a UART peripheral, enabling hardware flow
708    /// control will also configure the RTS and CTS pins.
709    ///
710    /// More information on hardware flow control can be found [here].
711    ///
712    /// By default, hardware flow control is disabled.
713    ///
714    /// Support for RTS/CTS hardware flow control is device-dependent. You can
715    /// manually implement RTS/CTS using [`cts`], [`send_stop`] and
716    /// [`send_start`], or by disabling hardware flow control and configuring
717    /// an [`OutputPin`] for RTS and an [`InputPin`] for CTS.
718    ///
719    /// [here]: index.html#hardware-flow-control
720    /// [`cts`]: struct.Status.html#method.cts
721    /// [`send_start`]: #method.send_start
722    /// [`send_stop`]: #method.send_stop
723    /// [`OutputPin`]: ../gpio/struct.OutputPin.html
724    /// [`InputPin`]: ../gpio/struct.InputPin.html
725    pub fn set_hardware_flow_control(&mut self, hardware_flow_control: bool) -> Result<()> {
726        if hardware_flow_control && self.inner.rtscts_pins.is_none() {
727            // Configure and store RTS/CTS GPIO pins for UART0/UART1, so their
728            // mode is automatically reset when Uart goes out of scope.
729            if let Some((rts_mode, cts_mode)) = self.inner.rtscts_mode {
730                let gpio = Gpio::new()?;
731
732                let (gpio_rts, gpio_cts) = if DeviceInfo::new()?.model() == Model::RaspberryPiBRev2
733                {
734                    // The Pi B Rev 2 exposes RTS/CTS through its (unpopulated) P5 header
735                    (GPIO_RTS_BREV2, GPIO_CTS_BREV2)
736                } else {
737                    // All other models with a 40-pin header use these GPIO pins
738                    (GPIO_RTS, GPIO_CTS)
739                };
740
741                let pin_rts = gpio.get(gpio_rts)?.into_io(rts_mode);
742                let pin_cts = gpio.get(gpio_cts)?.into_io(cts_mode);
743
744                self.inner.rtscts_pins = Some((pin_rts, pin_cts));
745            }
746        } else if !hardware_flow_control {
747            self.inner.rtscts_pins = None;
748        }
749
750        termios::set_hardware_flow_control(self.inner.fd, hardware_flow_control)?;
751
752        self.inner.hardware_flow_control = hardware_flow_control;
753
754        Ok(())
755    }
756
757    /// Requests the external device to pause its transmission using flow control.
758    ///
759    /// If software flow control is enabled, `send_stop`
760    /// sends the XOFF control character.
761    ///
762    /// If hardware flow control is enabled, `send_stop` sets RTS to its
763    /// inactive state.
764    pub fn send_stop(&self) -> Result<()> {
765        if self.inner.software_flow_control {
766            termios::send_stop(self.inner.fd)?;
767        }
768
769        if self.inner.hardware_flow_control {
770            termios::set_rts(self.inner.fd, false)?;
771        }
772
773        Ok(())
774    }
775
776    /// Requests the external device to resume its transmission using flow control.
777    ///
778    /// If software flow control is enabled, `send_start`
779    /// sends the XON control character.
780    ///
781    /// If hardware flow control is enabled, `send_start` sets RTS to its
782    /// active state.
783    pub fn send_start(&self) -> Result<()> {
784        if self.inner.software_flow_control {
785            termios::send_start(self.inner.fd)?;
786        }
787
788        if self.inner.hardware_flow_control {
789            termios::set_rts(self.inner.fd, true)?;
790        }
791
792        Ok(())
793    }
794
795    /// Returns `true` if [`read`] is configured to block when needed.
796    ///
797    /// [`read`]: #method.write
798    pub fn is_read_blocking(&self) -> bool {
799        self.inner.blocking_read
800    }
801
802    /// Returns `true` if [`write`] is configured to block when needed.
803    ///
804    /// [`write`]: #method.write
805    pub fn is_write_blocking(&self) -> bool {
806        self.inner.blocking_write
807    }
808
809    /// Sets the blocking mode for subsequent calls to [`read`].
810    ///
811    /// `min_length` indicates the minimum number of requested bytes. This
812    /// value may differ from the actual buffer length. Maximum value: 255
813    /// bytes.
814    ///
815    /// `timeout` indicates how long [`read`] blocks while waiting for
816    /// incoming data. `timeout` uses a 0.1 second resolution. Maximum
817    /// value: 25.5 seconds.
818    ///
819    /// [`read`] operates in one of four modes, depending on the specified
820    /// `min_length` and `timeout` values:
821    ///
822    /// * **Non-blocking read** (`min_length` = 0, `timeout` = 0). [`read`]
823    ///   retrieves any available data and returns immediately.
824    /// * **Blocking read** (`min_length` > 0, `timeout` = 0). [`read`] blocks
825    ///   until at least `min_length` bytes are available, or the provided buffer
826    ///   is full.
827    /// * **Read with timeout** (`min_length` = 0, `timeout` > 0). [`read`]
828    ///   blocks until at least one byte is available, or the `timeout` duration
829    ///   elapses.
830    /// * **Read with inter-byte timeout** (`min_length` > 0, `timeout` > 0).
831    ///   [`read`] blocks until at least `min_length` bytes are available, the
832    ///   provided buffer is full, or the `timeout` duration elapses
833    ///   after receiving one or more bytes. The timer is started after an
834    ///   initial byte becomes available, and is restarted after each additional
835    ///   byte. That means [`read`] will block indefinitely until at least one
836    ///   byte has been received.
837    ///
838    /// By default, [`read`] is configured as non-blocking.
839    ///
840    /// [`read`]: #method.read
841    pub fn set_read_mode(&mut self, min_length: u8, timeout: Duration) -> Result<()> {
842        termios::set_read_mode(self.inner.fd, min_length, timeout)?;
843
844        self.inner.blocking_read = min_length > 0 || timeout.as_millis() > 0;
845
846        // If both read() and write() are non-blocking, we can safely set
847        // O_NONBLOCK once instead of toggling it for every write. We can't
848        // leave it set when read() should block, because it ignores the
849        // VMIN and VTIME settings.
850        if self.inner.blocking_read || self.inner.blocking_write {
851            unsafe {
852                libc::fcntl(self.inner.fd, libc::F_SETFL, 0);
853            }
854        } else {
855            unsafe {
856                libc::fcntl(self.inner.fd, libc::F_SETFL, libc::O_NONBLOCK);
857            }
858        }
859
860        Ok(())
861    }
862
863    /// Sets the blocking mode for subsequent calls to [`write`].
864    ///
865    /// [`write`] operates in one of two modes, depending on the specified
866    /// `blocking` value:
867    ///
868    /// * **Non-blocking write**. [`write`] returns immediately after
869    ///   copying as much of the contents of the provided buffer to the output queue
870    ///   as it's able to fit.
871    /// * **Blocking write**. [`write`] blocks until the entire contents of the provided buffer
872    ///   can be copied to the output queue. If flow control is enabled and the
873    ///   external device has sent a stop request, the transmission of any waiting data
874    ///   in the output queue is paused until a start request has been received.
875    ///
876    /// By default, [`write`] is configured as non-blocking.
877    ///
878    /// [`write`]: #method.write
879    pub fn set_write_mode(&mut self, blocking: bool) -> Result<()> {
880        self.inner.blocking_write = blocking;
881
882        // If both read() and write() are non-blocking, we can safely set
883        // O_NONBLOCK once instead of toggling it for every write. We can't
884        // leave it set when read() should block, because it ignores the
885        // VMIN and VTIME settings.
886        if self.inner.blocking_read || self.inner.blocking_write {
887            unsafe {
888                libc::fcntl(self.inner.fd, libc::F_SETFL, 0);
889            }
890        } else {
891            unsafe {
892                libc::fcntl(self.inner.fd, libc::F_SETFL, libc::O_NONBLOCK);
893            }
894        }
895
896        Ok(())
897    }
898
899    /// Returns the number of bytes waiting in the input queue.
900    pub fn input_len(&self) -> Result<usize> {
901        termios::input_len(self.inner.fd)
902    }
903
904    /// Returns the number of bytes waiting in the output queue.
905    pub fn output_len(&self) -> Result<usize> {
906        termios::output_len(self.inner.fd)
907    }
908
909    /// Receives incoming data from the external device and stores it in
910    /// `buffer`.
911    ///
912    /// `read` operates in one of four (non)blocking modes, depending on the
913    /// settings configured by [`set_read_mode`]. By default, `read` is configured
914    /// as non-blocking.
915    ///
916    /// Returns how many bytes were read.
917    ///
918    /// [`set_read_mode`]: #method.set_read_mode
919    pub fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
920        self.inner.device.read(buffer).or_else(|e| {
921            if e.kind() == io::ErrorKind::WouldBlock {
922                Ok(0)
923            } else {
924                Err(Error::Io(e))
925            }
926        })
927    }
928
929    /// Sends the contents of `buffer` to the external device.
930    ///
931    /// `write` operates in either blocking or non-blocking mode, depending on the
932    /// settings configured by [`set_write_mode`]. By default, `write` is configured
933    /// as non-blocking.
934    ///
935    /// Returns how many bytes were written.
936    ///
937    /// [`set_write_mode`]: #method.set_write_mode
938    pub fn write(&mut self, buffer: &[u8]) -> Result<usize> {
939        // We only need to toggle O_NONBLOCK when read() is configured as
940        // blocking. If read() is non-blocking, either with_path() or
941        // set_read_mode() will have already enabled O_NONBLOCK.
942        if self.inner.blocking_read && !self.inner.blocking_write {
943            unsafe {
944                libc::fcntl(self.inner.fd, libc::F_SETFL, libc::O_NONBLOCK);
945            }
946        }
947
948        let result = self.inner.device.write(buffer).or_else(|e| {
949            if e.kind() == io::ErrorKind::WouldBlock {
950                Ok(0)
951            } else {
952                Err(Error::Io(e))
953            }
954        });
955
956        if self.inner.blocking_read && !self.inner.blocking_write {
957            unsafe {
958                libc::fcntl(self.inner.fd, libc::F_SETFL, 0);
959            }
960        }
961
962        result
963    }
964
965    /// Blocks until all data in the output queue has been transmitted.
966    pub fn drain(&self) -> Result<()> {
967        termios::drain(self.inner.fd)
968    }
969
970    /// Discards all data in the input and/or output queue.
971    pub fn flush(&self, queue_type: Queue) -> Result<()> {
972        termios::flush(self.inner.fd, queue_type)
973    }
974}