diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-03-27 10:43:53 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-03-27 10:43:53 +0000 |
| commit | cde6f0f8628b50008df8cdeb52e80c186f63863a (patch) | |
| tree | f4d0304ac729d9e4234f26b49b43f7e093c7f300 /src/ioctl.rs | |
| parent | fd3de78b43e1c3607c68a2e12987a28bf60888e2 (diff) | |
| parent | c7646eb699e194a7c692b95b49adc76d6d3295ea (diff) | |
Merge pull request #50 from kbleeke/async-ioctls
Rework Ioctls to an async state machine
Diffstat (limited to 'src/ioctl.rs')
| -rw-r--r-- | src/ioctl.rs | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/ioctl.rs b/src/ioctl.rs new file mode 100644 index 000000000..6a7465593 --- /dev/null +++ b/src/ioctl.rs | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | use core::cell::{Cell, RefCell}; | ||
| 2 | use core::future::poll_fn; | ||
| 3 | use core::task::{Poll, Waker}; | ||
| 4 | |||
| 5 | use embassy_sync::waitqueue::WakerRegistration; | ||
| 6 | |||
| 7 | #[derive(Clone, Copy)] | ||
| 8 | pub enum IoctlType { | ||
| 9 | Get = 0, | ||
| 10 | Set = 2, | ||
| 11 | } | ||
| 12 | |||
| 13 | #[derive(Clone, Copy)] | ||
| 14 | pub struct PendingIoctl { | ||
| 15 | pub buf: *mut [u8], | ||
| 16 | pub kind: IoctlType, | ||
| 17 | pub cmd: u32, | ||
| 18 | pub iface: u32, | ||
| 19 | } | ||
| 20 | |||
| 21 | #[derive(Clone, Copy)] | ||
| 22 | enum IoctlStateInner { | ||
| 23 | Pending(PendingIoctl), | ||
| 24 | Sent { buf: *mut [u8] }, | ||
| 25 | Done { resp_len: usize }, | ||
| 26 | } | ||
| 27 | |||
| 28 | #[derive(Default)] | ||
| 29 | struct Wakers { | ||
| 30 | control: WakerRegistration, | ||
| 31 | runner: WakerRegistration, | ||
| 32 | } | ||
| 33 | |||
| 34 | pub struct IoctlState { | ||
| 35 | state: Cell<IoctlStateInner>, | ||
| 36 | wakers: RefCell<Wakers>, | ||
| 37 | } | ||
| 38 | |||
| 39 | impl IoctlState { | ||
| 40 | pub fn new() -> Self { | ||
| 41 | Self { | ||
| 42 | state: Cell::new(IoctlStateInner::Done { resp_len: 0 }), | ||
| 43 | wakers: Default::default(), | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | fn wake_control(&self) { | ||
| 48 | self.wakers.borrow_mut().control.wake(); | ||
| 49 | } | ||
| 50 | |||
| 51 | fn register_control(&self, waker: &Waker) { | ||
| 52 | self.wakers.borrow_mut().control.register(waker); | ||
| 53 | } | ||
| 54 | |||
| 55 | fn wake_runner(&self) { | ||
| 56 | self.wakers.borrow_mut().runner.wake(); | ||
| 57 | } | ||
| 58 | |||
| 59 | fn register_runner(&self, waker: &Waker) { | ||
| 60 | self.wakers.borrow_mut().runner.register(waker); | ||
| 61 | } | ||
| 62 | |||
| 63 | pub async fn wait_complete(&self) -> usize { | ||
| 64 | poll_fn(|cx| { | ||
| 65 | if let IoctlStateInner::Done { resp_len } = self.state.get() { | ||
| 66 | Poll::Ready(resp_len) | ||
| 67 | } else { | ||
| 68 | self.register_control(cx.waker()); | ||
| 69 | Poll::Pending | ||
| 70 | } | ||
| 71 | }) | ||
| 72 | .await | ||
| 73 | } | ||
| 74 | |||
| 75 | pub async fn wait_pending(&self) -> PendingIoctl { | ||
| 76 | let pending = poll_fn(|cx| { | ||
| 77 | if let IoctlStateInner::Pending(pending) = self.state.get() { | ||
| 78 | warn!("found pending ioctl"); | ||
| 79 | Poll::Ready(pending) | ||
| 80 | } else { | ||
| 81 | self.register_runner(cx.waker()); | ||
| 82 | Poll::Pending | ||
| 83 | } | ||
| 84 | }) | ||
| 85 | .await; | ||
| 86 | |||
| 87 | self.state.set(IoctlStateInner::Sent { buf: pending.buf }); | ||
| 88 | pending | ||
| 89 | } | ||
| 90 | |||
| 91 | pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { | ||
| 92 | warn!("doing ioctl"); | ||
| 93 | self.state | ||
| 94 | .set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface })); | ||
| 95 | self.wake_runner(); | ||
| 96 | self.wait_complete().await | ||
| 97 | } | ||
| 98 | |||
| 99 | pub fn ioctl_done(&self, response: &[u8]) { | ||
| 100 | if let IoctlStateInner::Sent { buf } = self.state.get() { | ||
| 101 | warn!("ioctl complete"); | ||
| 102 | // TODO fix this | ||
| 103 | (unsafe { &mut *buf }[..response.len()]).copy_from_slice(response); | ||
| 104 | |||
| 105 | self.state.set(IoctlStateInner::Done { | ||
| 106 | resp_len: response.len(), | ||
| 107 | }); | ||
| 108 | self.wake_control(); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | } | ||
