use alloc::sync::Arc;
use ax_errno::{AxError, AxResult};
use axvm_types::{InterruptTriggerMode, IrqLineId};
pub trait IrqSink: Send + Sync {
fn set_level(&self, line: IrqLineId, asserted: bool) -> AxResult;
fn pulse(&self, line: IrqLineId) -> AxResult;
}
#[derive(Clone)]
pub struct IrqLine(Arc<IrqLineInner>);
struct IrqLineInner {
id: IrqLineId,
trigger: InterruptTriggerMode,
sink: Arc<dyn IrqSink>,
}
impl IrqLine {
pub fn new(id: IrqLineId, trigger: InterruptTriggerMode, sink: Arc<dyn IrqSink>) -> Self {
Self(Arc::new(IrqLineInner { id, trigger, sink }))
}
pub fn raise(&self) -> AxResult {
if self.0.trigger != InterruptTriggerMode::LevelTriggered {
return Err(AxError::InvalidInput);
}
self.0.sink.set_level(self.0.id, true)
}
pub fn lower(&self) -> AxResult {
if self.0.trigger != InterruptTriggerMode::LevelTriggered {
return Err(AxError::InvalidInput);
}
self.0.sink.set_level(self.0.id, false)
}
pub fn pulse(&self) -> AxResult {
if self.0.trigger != InterruptTriggerMode::EdgeTriggered {
return Err(AxError::InvalidInput);
}
self.0.sink.pulse(self.0.id)
}
}