use std::result::Result;
use crate::Trigger;
const COMMAND_OFFSET: u8 = 4;
const CMD_RESET_CPU: u8 = 0xFE;
#[derive(Debug)]
pub struct I8042Device<T: Trigger> {
reset_evt: T,
}
impl<T: Trigger> I8042Device<T> {
pub fn new(reset_evt: T) -> I8042Device<T> {
I8042Device { reset_evt }
}
pub fn read(&mut self, _offset: u8) -> u8 {
0x00
}
pub fn write(&mut self, offset: u8, value: u8) -> Result<(), T::E> {
match offset {
COMMAND_OFFSET if value == CMD_RESET_CPU => {
self.reset_evt.trigger()
}
_ => Ok(()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use vmm_sys_util::eventfd::EventFd;
#[test]
fn test_i8042_valid_ops() {
let reset_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap();
let mut i8042 = I8042Device::new(reset_evt.try_clone().unwrap());
assert_eq!(i8042.read(0), 0);
i8042.write(COMMAND_OFFSET, CMD_RESET_CPU).unwrap();
assert_eq!(reset_evt.read().unwrap(), 1);
}
#[test]
fn test_i8042_invalid_reset() {
let reset_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap();
let mut i8042 = I8042Device::new(reset_evt.try_clone().unwrap());
assert!(reset_evt.write(1).is_ok());
i8042.write(COMMAND_OFFSET, CMD_RESET_CPU + 1).unwrap();
assert_eq!(reset_evt.read().unwrap(), 1);
assert!(reset_evt.write(1).is_ok());
i8042.write(COMMAND_OFFSET + 1, CMD_RESET_CPU).unwrap();
assert_eq!(reset_evt.read().unwrap(), 1);
}
}