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