Files
yggdrasil/kernel/libk/src/event.rs
T

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);
}