45 lines
1.3 KiB
Rust
45 lines
1.3 KiB
Rust
use core::sync::atomic::{AtomicU64, Ordering};
|
|
|
|
use alloc::{boxed::Box, collections::BTreeMap};
|
|
|
|
use device_api::gpio::PinHandle;
|
|
use libk_util::{ring::LossyRingQueue, sync::spin_rwlock::IrqSafeRwLock};
|
|
use yggdrasil_abi::error::Error;
|
|
|
|
static GPIO_EVENT_QUEUE: LossyRingQueue<u64> = LossyRingQueue::with_capacity(64);
|
|
static GPIO_EVENT_MAP: IrqSafeRwLock<BTreeMap<u64, Box<dyn Fn() + Send>>> =
|
|
IrqSafeRwLock::new(BTreeMap::new());
|
|
static GPIO_EVENT_ID: AtomicU64 = AtomicU64::new(1);
|
|
|
|
pub trait GpioEvent {
|
|
fn configure_with_interrupt(&self, handler: Box<dyn Fn() + Send>) -> Result<(), Error>;
|
|
}
|
|
|
|
impl GpioEvent for PinHandle {
|
|
fn configure_with_interrupt(&self, handler: Box<dyn Fn() + Send>) -> Result<(), Error> {
|
|
let ev = bind_gpio_event(handler);
|
|
self.parent.setup_gpio(self, Some(ev))
|
|
}
|
|
}
|
|
|
|
pub async fn gpio_event_handler_task() {
|
|
loop {
|
|
let id = GPIO_EVENT_QUEUE.read().await;
|
|
|
|
let lock = GPIO_EVENT_MAP.read();
|
|
if let Some(handler) = lock.get(&id) {
|
|
handler();
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn bind_gpio_event(handler: Box<dyn Fn() + Send>) -> u64 {
|
|
let id = GPIO_EVENT_ID.fetch_add(1, Ordering::Acquire);
|
|
GPIO_EVENT_MAP.write().insert(id, handler);
|
|
id
|
|
}
|
|
|
|
pub fn signal_gpio_event(ev: u64) {
|
|
GPIO_EVENT_QUEUE.write(ev);
|
|
}
|