1 //! Abstraction over byte stream devices, also known as serial I/O devices.
2 
3 use crate::proto::unsafe_protocol;
4 use crate::{Result, StatusExt};
5 use core::fmt::Write;
6 use uefi_raw::protocol::console::serial::SerialIoProtocol;
7 
8 pub use uefi_raw::protocol::console::serial::{
9     ControlBits, Parity, SerialIoMode as IoMode, StopBits,
10 };
11 
12 /// Provides access to a serial I/O device.
13 ///
14 /// This can include standard UART devices, serial ports over a USB interface,
15 /// or any other character-based communication device.
16 ///
17 /// Since UEFI drivers are implemented through polling, if you fail to regularly
18 /// check for input/output, some data might be lost.
19 #[derive(Debug)]
20 #[repr(transparent)]
21 #[unsafe_protocol(SerialIoProtocol::GUID)]
22 pub struct Serial(SerialIoProtocol);
23 
24 impl Serial {
25     /// Reset the device.
reset(&mut self) -> Result26     pub fn reset(&mut self) -> Result {
27         unsafe { (self.0.reset)(&mut self.0) }.to_result()
28     }
29 
30     /// Returns the current I/O mode.
31     #[must_use]
io_mode(&self) -> &IoMode32     pub const fn io_mode(&self) -> &IoMode {
33         unsafe { &*self.0.mode }
34     }
35 
36     /// Sets the device's new attributes.
37     ///
38     /// The given `IoMode` will become the device's new `IoMode`,
39     /// with some exceptions:
40     ///
41     /// - `control_mask` is ignored, since it's a read-only field;
42     ///
43     /// - values set to `0` / `Default` will be filled with the device's
44     ///   default parameters
45     ///
46     /// - if either `baud_rate` or `receive_fifo_depth` is less than
47     ///   the device's minimum, an error will be returned;
48     ///   this value will be rounded down to the nearest value supported by the device;
set_attributes(&mut self, mode: &IoMode) -> Result49     pub fn set_attributes(&mut self, mode: &IoMode) -> Result {
50         unsafe {
51             (self.0.set_attributes)(
52                 &mut self.0,
53                 mode.baud_rate,
54                 mode.receive_fifo_depth,
55                 mode.timeout,
56                 mode.parity,
57                 mode.data_bits as u8,
58                 mode.stop_bits,
59             )
60         }
61         .to_result()
62     }
63 
64     /// Retrieve the device's current control bits.
get_control_bits(&self) -> Result<ControlBits>65     pub fn get_control_bits(&self) -> Result<ControlBits> {
66         let mut bits = ControlBits::empty();
67         unsafe { (self.0.get_control_bits)(&self.0, &mut bits) }.to_result_with_val(|| bits)
68     }
69 
70     /// Sets the device's new control bits.
71     ///
72     /// Not all bits can be modified with this function. A mask of the allowed
73     /// bits is stored in the [`ControlBits::SETTABLE`] constant.
set_control_bits(&mut self, bits: ControlBits) -> Result74     pub fn set_control_bits(&mut self, bits: ControlBits) -> Result {
75         unsafe { (self.0.set_control_bits)(&mut self.0, bits) }.to_result()
76     }
77 
78     /// Reads data from this device.
79     ///
80     /// This operation will block until the buffer has been filled with data or
81     /// an error occurs. In the latter case, the error will indicate how many
82     /// bytes were actually read from the device.
read(&mut self, data: &mut [u8]) -> Result<(), usize>83     pub fn read(&mut self, data: &mut [u8]) -> Result<(), usize> {
84         let mut buffer_size = data.len();
85         unsafe { (self.0.read)(&mut self.0, &mut buffer_size, data.as_mut_ptr()) }.to_result_with(
86             || debug_assert_eq!(buffer_size, data.len()),
87             |_| buffer_size,
88         )
89     }
90 
91     /// Writes data to this device.
92     ///
93     /// This operation will block until the data has been fully written or an
94     /// error occurs. In the latter case, the error will indicate how many bytes
95     /// were actually written to the device.
write(&mut self, data: &[u8]) -> Result<(), usize>96     pub fn write(&mut self, data: &[u8]) -> Result<(), usize> {
97         let mut buffer_size = data.len();
98         unsafe { (self.0.write)(&mut self.0, &mut buffer_size, data.as_ptr()) }.to_result_with(
99             || debug_assert_eq!(buffer_size, data.len()),
100             |_| buffer_size,
101         )
102     }
103 }
104 
105 impl Write for Serial {
write_str(&mut self, s: &str) -> core::fmt::Result106     fn write_str(&mut self, s: &str) -> core::fmt::Result {
107         self.write(s.as_bytes()).map_err(|_| core::fmt::Error)
108     }
109 }
110