use crate::proto::Protocol;
use crate::{unsafe_guid, Result, Status};
use bitflags::bitflags;
#[repr(C)]
#[unsafe_guid("bb25cf6f-f1d4-11d2-9a0c-0090273fc1fd")]
#[derive(Protocol)]
pub struct Serial<'boot> {
revision: u32,
reset: extern "efiapi" fn(&mut Serial) -> Status,
set_attributes: extern "efiapi" fn(
&Serial,
baud_rate: u64,
receive_fifo_depth: u32,
timeout: u32,
parity: Parity,
data_bits: u8,
stop_bits_type: StopBits,
) -> Status,
set_control_bits: extern "efiapi" fn(&mut Serial, ControlBits) -> Status,
get_control_bits: extern "efiapi" fn(&Serial, &mut ControlBits) -> Status,
write: unsafe extern "efiapi" fn(&mut Serial, &mut usize, *const u8) -> Status,
read: unsafe extern "efiapi" fn(&mut Serial, &mut usize, *mut u8) -> Status,
io_mode: &'boot IoMode,
}
impl<'boot> Serial<'boot> {
pub fn reset(&mut self) -> Result {
(self.reset)(self).into()
}
pub fn io_mode(&self) -> &IoMode {
self.io_mode
}
pub fn set_attributes(&mut self, mode: &IoMode) -> Result {
(self.set_attributes)(
self,
mode.baud_rate,
mode.receive_fifo_depth,
mode.timeout,
mode.parity,
mode.data_bits as u8,
mode.stop_bits,
)
.into()
}
pub fn get_control_bits(&self) -> Result<ControlBits> {
let mut bits = ControlBits::empty();
(self.get_control_bits)(self, &mut bits).into_with_val(|| bits)
}
pub fn set_control_bits(&mut self, bits: ControlBits) -> Result {
(self.set_control_bits)(self, bits).into()
}
pub fn read(&mut self, data: &mut [u8]) -> Result<(), usize> {
let mut buffer_size = data.len();
unsafe { (self.read)(self, &mut buffer_size, data.as_mut_ptr()) }.into_with(
|| debug_assert_eq!(buffer_size, data.len()),
|_| buffer_size,
)
}
pub fn write(&mut self, data: &[u8]) -> Result<(), usize> {
let mut buffer_size = data.len();
unsafe { (self.write)(self, &mut buffer_size, data.as_ptr()) }.into_with(
|| debug_assert_eq!(buffer_size, data.len()),
|_| buffer_size,
)
}
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct IoMode {
pub control_mask: ControlBits,
pub timeout: u32,
pub baud_rate: u64,
pub receive_fifo_depth: u32,
pub data_bits: u32,
pub parity: Parity,
pub stop_bits: StopBits,
}
bitflags! {
pub struct ControlBits: u32 {
const CLEAR_TO_SEND = 0x10;
const DATA_SET_READY = 0x20;
const RING_INDICATE = 0x40;
const CARRIER_DETECT = 0x80;
const INPUT_BUFFER_EMPTY = 0x100;
const OUTPUT_BUFFER_EMPTY = 0x200;
const DATA_TERMINAL_READY = 0x1;
const REQUEST_TO_SEND = 0x2;
const HARDWARE_LOOPBACK_ENABLE = 0x1000;
const SOFTWARE_LOOPBACK_ENABLE = 0x2000;
const HARDWARE_FLOW_CONTROL_ENABLE = 0x4000;
const SETTABLE =
ControlBits::DATA_TERMINAL_READY.bits
| ControlBits::REQUEST_TO_SEND.bits
| ControlBits::HARDWARE_LOOPBACK_ENABLE.bits
| ControlBits::SOFTWARE_LOOPBACK_ENABLE.bits
| ControlBits::HARDWARE_FLOW_CONTROL_ENABLE.bits;
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(u32)]
pub enum Parity {
Default = 0,
None,
Even,
Odd,
Mark,
Space,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(u32)]
pub enum StopBits {
Default = 0,
One,
OneFive,
Two,
}