use core::mem::MaybeUninit;
use moa_uapi::{
channel::ChanHandle,
device::{DeviceInfo, IrqHandle},
error::{
ERR_BUSY, ERR_FAULT, ERR_INVAL, ERR_NO_RESOURCE, ERR_NOT_FOUND, ERR_NOT_SUPPORTED, ERR_PERM,
},
mem::MemHandle,
sysnr::{
SYSNR_DEVICE_ACQUIRE, SYSNR_DEVICE_COUNT, SYSNR_DEVICE_GET_PROP, SYSNR_DEVICE_QUERY,
SYSNR_DEVICE_RELEASE, SYSNR_IRQ_ACK, SYSNR_IRQ_BIND, SYSNR_IRQ_UNBIND,
},
};
pub type Result<T> = core::result::Result<T, DeviceError>;
define_syscall_error! {
pub enum DeviceError {
Perm = ERR_PERM,
NotFound = ERR_NOT_FOUND,
Inval = ERR_INVAL,
NoResource = ERR_NO_RESOURCE,
Fault = ERR_FAULT,
Busy = ERR_BUSY,
NotSupported = ERR_NOT_SUPPORTED,
}
}
pub fn device_count() -> Result<u32> {
let ret = unsafe { super::arch::syscall0(SYSNR_DEVICE_COUNT) };
if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(ret as u32) }
}
pub fn device_query(index: u32) -> Result<DeviceInfo> {
let mut info = MaybeUninit::<DeviceInfo>::uninit();
let ret = unsafe {
super::arch::syscall2(SYSNR_DEVICE_QUERY, index as usize, info.as_mut_ptr() as usize)
};
if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(unsafe { info.assume_init() }) }
}
pub fn device_get_prop(index: u32, name: &str, buf: &mut [u8]) -> Result<usize> {
let ret = unsafe {
super::arch::syscall5(
SYSNR_DEVICE_GET_PROP,
index as usize,
name.as_ptr() as usize,
name.len(),
buf.as_mut_ptr() as usize,
buf.len(),
)
};
if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(ret as usize) }
}
pub fn device_acquire(index: u32, mems: &mut [MemHandle], irqs: &mut [IrqHandle]) -> Result<()> {
let ret = unsafe {
super::arch::syscall5(
SYSNR_DEVICE_ACQUIRE,
index as usize,
mems.as_mut_ptr() as usize,
mems.len(),
irqs.as_mut_ptr() as usize,
irqs.len(),
)
};
if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(()) }
}
pub fn device_release(index: u32) -> Result<()> {
let ret = unsafe { super::arch::syscall1(SYSNR_DEVICE_RELEASE, index as usize) };
if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(()) }
}
pub fn irq_bind(irq: IrqHandle, chan: ChanHandle) -> Result<()> {
let ret =
unsafe { super::arch::syscall2(SYSNR_IRQ_BIND, irq.raw() as usize, chan.raw() as usize) };
if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(()) }
}
pub fn irq_unbind(irq: IrqHandle) -> Result<()> {
let ret = unsafe { super::arch::syscall1(SYSNR_IRQ_UNBIND, irq.raw() as usize) };
if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(()) }
}
pub fn irq_ack(irq: IrqHandle) -> Result<()> {
let ret = unsafe { super::arch::syscall1(SYSNR_IRQ_ACK, irq.raw() as usize) };
if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(()) }
}