Struct vm_superio::serial::Serial

source ·
pub struct Serial<T: Trigger, EV: SerialEvents, W: Write> { /* private fields */ }
Expand description

The serial console emulation is done by emulating a serial COM port.

Each serial COM port (COM1-4) has an associated Port I/O address base and 12 registers mapped into 8 consecutive Port I/O locations (with the first one being the base). This structure emulates the registers that make sense for UART 16550 (and below) and helps in the interaction between the driver and device by using a Trigger object for notifications. It also writes the guest’s output to an out Write object.

§Example


struct EventFdTrigger(EventFd);
impl Trigger for EventFdTrigger {
    type E = Error;

    fn trigger(&self) -> Result<()> {
        self.write(1)
    }
}
impl Deref for EventFdTrigger {
    type Target = EventFd;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl EventFdTrigger {
    pub fn new(flag: i32) -> Self {
        EventFdTrigger(EventFd::new(flag).unwrap())
    }
    pub fn try_clone(&self) -> Self {
        EventFdTrigger((**self).try_clone().unwrap())
    }
}

let intr_evt = EventFdTrigger::new(libc::EFD_NONBLOCK);
let mut serial = Serial::new(intr_evt.try_clone(), Vec::new());
// std::io::Sink can be used if user is not interested in guest's output.
let serial_with_sink = Serial::new(intr_evt, sink());

// Write 0x01 to THR register.
serial.write(0, 0x01).unwrap();
// Read from RBR register.
let value = serial.read(0);

// Send more bytes to the guest in one shot.
let input = &[b'a', b'b', b'c'];
// Before enqueuing bytes we first check if there is enough free space
// in the FIFO.
if serial.fifo_capacity() >= input.len() {
    serial.enqueue_raw_bytes(input).unwrap();
}

Implementations§

source§

impl<T: Trigger, W: Write> Serial<T, NoEvents, W>

source

pub fn new(trigger: T, out: W) -> Serial<T, NoEvents, W>

Creates a new Serial instance which writes the guest’s output to out and uses trigger object to notify the driver about new events.

§Arguments
  • trigger - The Trigger object that will be used to notify the driver about events.
  • out - An object for writing guest’s output to. In case the output is not of interest, std::io::Sink can be used here.
§Example

You can see an example of how to use this function in the Example section from Serial.

source§

impl<T: Trigger, EV: SerialEvents, W: Write> Serial<T, EV, W>

source

pub fn from_state( state: &SerialState, trigger: T, serial_evts: EV, out: W ) -> Result<Self, Error<T::E>>

Creates a new Serial instance from a given state, which writes the guest’s output to out, uses trigger object to notify the driver about new events, and invokes the serial_evts implementation of SerialEvents during operation. For creating the instance from a default state, with_events method can be used.

§Arguments
  • state - A reference to the state from which the Serial is constructed.
  • trigger - The Trigger object that will be used to notify the driver about events.
  • serial_evts - The SerialEvents implementation used to track the occurrence of significant events in the serial operation logic.
  • out - An object for writing guest’s output to. In case the output is not of interest, std::io::Sink can be used here.
source

pub fn with_events(trigger: T, serial_evts: EV, out: W) -> Self

Creates a new Serial instance from the default state, which writes the guest’s output to out, uses trigger object to notify the driver about new events, and invokes the serial_evts implementation of SerialEvents during operation.

§Arguments
  • trigger - The Trigger object that will be used to notify the driver about events.
  • serial_evts - The SerialEvents implementation used to track the occurrence of significant events in the serial operation logic.
  • out - An object for writing guest’s output to. In case the output is not of interest, std::io::Sink can be used here.
source

pub fn state(&self) -> SerialState

Returns the state of the Serial.

source

pub fn writer(&self) -> &W

Gets a reference to the output Write object

const DATA_OFFSET: u8 = 0;

let output = Vec::new();
let mut serial = Serial::new(DummyTrigger, output);
serial.write(DATA_OFFSET, 0x66).unwrap();
assert_eq!(serial.writer().first().copied(), Some(0x66));
source

pub fn writer_mut(&mut self) -> &mut W

Gets a mutable reference to the output Write object

const DATA_OFFSET: u8 = 0;

let output = Vec::new();
let mut serial = Serial::new(DummyTrigger, output);
serial.write(DATA_OFFSET, 0x66).unwrap();
serial.writer_mut().clear();
assert_eq!(serial.writer().first(), None);
source

pub fn into_writer(self) -> W

Consumes the device and retrieves the inner writer. This can be useful when restoring a copy of the device.

const DATA_OFFSET: u8 = 0;

// Create a device with some state
let output = Vec::new();
let mut serial = Serial::new(DummyTrigger, output);
serial.write(DATA_OFFSET, 0x66).unwrap();

// Save the state
let state = serial.state();
let output = serial.into_writer();

// Restore the device
let restored_serial = Serial::from_state(&state, DummyTrigger, NoEvents, output).unwrap();
assert_eq!(restored_serial.writer().first().copied(), Some(0x66));
source

pub fn interrupt_evt(&self) -> &T

Provides a reference to the interrupt event object.

source

pub fn events(&self) -> &EV

Provides a reference to the serial events object.

source

pub fn write(&mut self, offset: u8, value: u8) -> Result<(), Error<T::E>>

Handles a write request from the driver at offset offset from the base Port I/O address.

§Arguments
  • offset - The offset that will be added to the base PIO address for writing to a specific register.
  • value - The byte that should be written.
§Example

You can see an example of how to use this function in the Example section from Serial.

source

pub fn read(&mut self, offset: u8) -> u8

Handles a read request from the driver at offset offset from the base Port I/O address.

Returns the read value.

§Arguments
  • offset - The offset that will be added to the base PIO address for reading from a specific register.
§Example

You can see an example of how to use this function in the Example section from Serial.

source

pub fn fifo_capacity(&self) -> usize

Returns how much space is still available in the FIFO.

§Example

You can see an example of how to use this function in the Example section from Serial.

source

pub fn enqueue_raw_bytes(&mut self, input: &[u8]) -> Result<usize, Error<T::E>>

Helps in sending more bytes to the guest in one shot, by storing input bytes in UART buffer and letting the driver know there is some pending data to be read by setting RDA bit and its corresponding interrupt when not already triggered.

§Arguments
  • input - The data to be sent to the guest.
§Returns

The function returns the number of bytes it was able to write to the fifo, or FullFifo error when the fifo is full. Users can use fifo_capacity before calling this function to check the available space.

§Example

You can see an example of how to use this function in the Example section from Serial.

Trait Implementations§

source§

impl<T: Debug + Trigger, EV: Debug + SerialEvents, W: Debug + Write> Debug for Serial<T, EV, W>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T, EV, W> Freeze for Serial<T, EV, W>
where T: Freeze, EV: Freeze, W: Freeze,

§

impl<T, EV, W> RefUnwindSafe for Serial<T, EV, W>

§

impl<T, EV, W> Send for Serial<T, EV, W>
where T: Send, EV: Send, W: Send,

§

impl<T, EV, W> Sync for Serial<T, EV, W>
where T: Sync, EV: Sync, W: Sync,

§

impl<T, EV, W> Unpin for Serial<T, EV, W>
where T: Unpin, EV: Unpin, W: Unpin,

§

impl<T, EV, W> UnwindSafe for Serial<T, EV, W>
where T: UnwindSafe, EV: UnwindSafe, W: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.