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 = LossyRingQueue::with_capacity(64); static GPIO_EVENT_MAP: IrqSafeRwLock>> = IrqSafeRwLock::new(BTreeMap::new()); static GPIO_EVENT_ID: AtomicU64 = AtomicU64::new(1); pub trait GpioEvent { fn configure_with_interrupt(&self, handler: Box) -> Result<(), Error>; } impl GpioEvent for PinHandle { fn configure_with_interrupt(&self, handler: Box) -> 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) -> 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); }