extern crate alloc;
use alloc::{sync::Arc, vec};
use ax_errno::AxResult;
use axdevice_base::{
AccessWidth, BaseDeviceOps, BusAccess, BusKind, BusResponse, Device, EmuDeviceType,
MmioDeviceAdapter,
};
use axvm_types::{GuestPhysAddr, GuestPhysAddrRange};
const DEVICE_A_TEST_METHOD_ANSWER: usize = 42;
struct DeviceA;
impl BaseDeviceOps<GuestPhysAddrRange> for DeviceA {
fn emu_type(&self) -> EmuDeviceType {
EmuDeviceType::Dummy
}
fn address_range(&self) -> GuestPhysAddrRange {
(0x1000..0x2000).try_into().unwrap()
}
fn handle_read(&self, addr: GuestPhysAddr, _width: AccessWidth) -> AxResult<usize> {
Ok(addr.as_usize())
}
fn handle_write(&self, _addr: GuestPhysAddr, _width: AccessWidth, _val: usize) -> AxResult {
Ok(())
}
}
impl DeviceA {
pub fn test_method(&self) -> usize {
DEVICE_A_TEST_METHOD_ANSWER
}
}
struct DeviceB;
impl BaseDeviceOps<GuestPhysAddrRange> for DeviceB {
fn emu_type(&self) -> EmuDeviceType {
EmuDeviceType::Dummy
}
fn address_range(&self) -> GuestPhysAddrRange {
(0x2000..0x3000).try_into().unwrap()
}
fn handle_read(&self, addr: GuestPhysAddr, _width: AccessWidth) -> AxResult<usize> {
Ok(addr.as_usize())
}
fn handle_write(&self, _addr: GuestPhysAddr, _width: AccessWidth, _val: usize) -> AxResult {
Ok(())
}
}
#[test]
fn test_device_type_test() {
let devices: Vec<Arc<dyn Device>> = vec![
MmioDeviceAdapter::from_arc(Arc::new(DeviceA)),
MmioDeviceAdapter::from_arc(Arc::new(DeviceB)),
];
let mut device_a_found = false;
for device in &devices {
let resp = device
.handle(&BusAccess {
kind: BusKind::Mmio,
is_read: true,
addr: 0x2000,
width: AccessWidth::Byte,
data: 0,
})
.unwrap();
assert!(matches!(
resp,
BusResponse::Read { value } if value as usize == 0x2000
));
if let Some(a) = device.as_any().downcast_ref::<DeviceA>() {
assert_eq!(a.test_method(), DEVICE_A_TEST_METHOD_ANSWER);
device_a_found = true;
}
}
assert!(device_a_found, "DeviceA was not found");
}