From 6f547cf05ddd1a27c8ec4e107ac227f7f9520ba6 Mon Sep 17 00:00:00 2001 From: kbleeke Date: Thu, 2 Mar 2023 15:34:08 +0100 Subject: asyncify outgoing events --- src/ioctl.rs | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 src/ioctl.rs (limited to 'src/ioctl.rs') diff --git a/src/ioctl.rs b/src/ioctl.rs new file mode 100644 index 000000000..2d4cdb871 --- /dev/null +++ b/src/ioctl.rs @@ -0,0 +1,111 @@ +use core::cell::{Cell, RefCell}; +use core::future::poll_fn; +use core::task::{Poll, Waker}; + +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::blocking_mutex::Mutex; +use embassy_sync::waitqueue::WakerRegistration; + +#[derive(Clone, Copy)] +pub enum IoctlType { + Get = 0, + Set = 2, +} + +#[derive(Clone, Copy)] +pub struct PendingIoctl { + pub buf: *mut [u8], + pub kind: IoctlType, + pub cmd: u32, + pub iface: u32, +} + +#[derive(Clone, Copy)] +enum IoctlStateInner { + Pending(PendingIoctl), + Sent { buf: *mut [u8] }, + Done { resp_len: usize }, +} + +pub struct IoctlState { + state: Cell, + wakers: Mutex>, +} + +impl IoctlState { + pub fn new() -> Self { + Self { + state: Cell::new(IoctlStateInner::Done { resp_len: 0 }), + wakers: Mutex::new(RefCell::default()), + } + } + + fn wake_control(&self) { + self.wakers.lock(|f| { + f.borrow_mut().0.wake(); + }) + } + + fn register_control(&self, waker: &Waker) { + self.wakers.lock(|f| f.borrow_mut().0.register(waker)); + } + + fn wake_runner(&self) { + self.wakers.lock(|f| { + f.borrow_mut().1.wake(); + }) + } + + fn register_runner(&self, waker: &Waker) { + self.wakers.lock(|f| f.borrow_mut().1.register(waker)); + } + + pub async fn wait_complete(&self) -> usize { + poll_fn(|cx| { + if let IoctlStateInner::Done { resp_len } = self.state.get() { + Poll::Ready(resp_len) + } else { + self.register_control(cx.waker()); + Poll::Pending + } + }) + .await + } + + pub async fn wait_pending(&self) -> PendingIoctl { + let pending = poll_fn(|cx| { + if let IoctlStateInner::Pending(pending) = self.state.get() { + warn!("found pending ioctl"); + Poll::Ready(pending) + } else { + self.register_runner(cx.waker()); + Poll::Pending + } + }) + .await; + + self.state.set(IoctlStateInner::Sent { buf: pending.buf }); + pending + } + + pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { + warn!("doing ioctl"); + self.state + .set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface })); + self.wake_runner(); + self.wait_complete().await + } + + pub fn ioctl_done(&self, response: &[u8]) { + if let IoctlStateInner::Sent { buf } = self.state.get() { + warn!("ioctl complete"); + // TODO fix this + (unsafe { &mut *buf }[..response.len()]).copy_from_slice(response); + + self.state.set(IoctlStateInner::Done { + resp_len: response.len(), + }); + self.wake_control(); + } + } +} -- cgit From 4c521044131279aa36f7e21dbc6ec566703a57c6 Mon Sep 17 00:00:00 2001 From: kbleeke Date: Mon, 27 Mar 2023 12:40:27 +0200 Subject: simplify ioctl waker code --- src/ioctl.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/ioctl.rs') diff --git a/src/ioctl.rs b/src/ioctl.rs index 2d4cdb871..6a7465593 100644 --- a/src/ioctl.rs +++ b/src/ioctl.rs @@ -2,8 +2,6 @@ use core::cell::{Cell, RefCell}; use core::future::poll_fn; use core::task::{Poll, Waker}; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; -use embassy_sync::blocking_mutex::Mutex; use embassy_sync::waitqueue::WakerRegistration; #[derive(Clone, Copy)] @@ -27,37 +25,39 @@ enum IoctlStateInner { Done { resp_len: usize }, } +#[derive(Default)] +struct Wakers { + control: WakerRegistration, + runner: WakerRegistration, +} + pub struct IoctlState { state: Cell, - wakers: Mutex>, + wakers: RefCell, } impl IoctlState { pub fn new() -> Self { Self { state: Cell::new(IoctlStateInner::Done { resp_len: 0 }), - wakers: Mutex::new(RefCell::default()), + wakers: Default::default(), } } fn wake_control(&self) { - self.wakers.lock(|f| { - f.borrow_mut().0.wake(); - }) + self.wakers.borrow_mut().control.wake(); } fn register_control(&self, waker: &Waker) { - self.wakers.lock(|f| f.borrow_mut().0.register(waker)); + self.wakers.borrow_mut().control.register(waker); } fn wake_runner(&self) { - self.wakers.lock(|f| { - f.borrow_mut().1.wake(); - }) + self.wakers.borrow_mut().runner.wake(); } fn register_runner(&self, waker: &Waker) { - self.wakers.lock(|f| f.borrow_mut().1.register(waker)); + self.wakers.borrow_mut().runner.register(waker); } pub async fn wait_complete(&self) -> usize { -- cgit