diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-05-30 22:42:49 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-05-30 22:42:49 +0200 |
| commit | c327c6cd6fc3c11cfaf83cf64591940d401c5f6b (patch) | |
| tree | 1e9f693a74b01ae930caa145ae282c24276510e3 /cyw43/src/ioctl.rs | |
| parent | 3cc0ec654a1e46fe7b8fa168942452303343cd84 (diff) | |
cyw43: move crate to subdir.
Diffstat (limited to 'cyw43/src/ioctl.rs')
| -rw-r--r-- | cyw43/src/ioctl.rs | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/cyw43/src/ioctl.rs b/cyw43/src/ioctl.rs new file mode 100644 index 000000000..61524c274 --- /dev/null +++ b/cyw43/src/ioctl.rs | |||
| @@ -0,0 +1,126 @@ | |||
| 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 | use crate::fmt::Bytes; | ||
| 8 | |||
| 9 | #[derive(Clone, Copy)] | ||
| 10 | pub enum IoctlType { | ||
| 11 | Get = 0, | ||
| 12 | Set = 2, | ||
| 13 | } | ||
| 14 | |||
| 15 | #[derive(Clone, Copy)] | ||
| 16 | pub struct PendingIoctl { | ||
| 17 | pub buf: *mut [u8], | ||
| 18 | pub kind: IoctlType, | ||
| 19 | pub cmd: u32, | ||
| 20 | pub iface: u32, | ||
| 21 | } | ||
| 22 | |||
| 23 | #[derive(Clone, Copy)] | ||
| 24 | enum IoctlStateInner { | ||
| 25 | Pending(PendingIoctl), | ||
| 26 | Sent { buf: *mut [u8] }, | ||
| 27 | Done { resp_len: usize }, | ||
| 28 | } | ||
| 29 | |||
| 30 | struct Wakers { | ||
| 31 | control: WakerRegistration, | ||
| 32 | runner: WakerRegistration, | ||
| 33 | } | ||
| 34 | |||
| 35 | impl Default for Wakers { | ||
| 36 | fn default() -> Self { | ||
| 37 | Self { | ||
| 38 | control: WakerRegistration::new(), | ||
| 39 | runner: WakerRegistration::new(), | ||
| 40 | } | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | pub struct IoctlState { | ||
| 45 | state: Cell<IoctlStateInner>, | ||
| 46 | wakers: RefCell<Wakers>, | ||
| 47 | } | ||
| 48 | |||
| 49 | impl IoctlState { | ||
| 50 | pub fn new() -> Self { | ||
| 51 | Self { | ||
| 52 | state: Cell::new(IoctlStateInner::Done { resp_len: 0 }), | ||
| 53 | wakers: Default::default(), | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | fn wake_control(&self) { | ||
| 58 | self.wakers.borrow_mut().control.wake(); | ||
| 59 | } | ||
| 60 | |||
| 61 | fn register_control(&self, waker: &Waker) { | ||
| 62 | self.wakers.borrow_mut().control.register(waker); | ||
| 63 | } | ||
| 64 | |||
| 65 | fn wake_runner(&self) { | ||
| 66 | self.wakers.borrow_mut().runner.wake(); | ||
| 67 | } | ||
| 68 | |||
| 69 | fn register_runner(&self, waker: &Waker) { | ||
| 70 | self.wakers.borrow_mut().runner.register(waker); | ||
| 71 | } | ||
| 72 | |||
| 73 | pub async fn wait_complete(&self) -> usize { | ||
| 74 | poll_fn(|cx| { | ||
| 75 | if let IoctlStateInner::Done { resp_len } = self.state.get() { | ||
| 76 | Poll::Ready(resp_len) | ||
| 77 | } else { | ||
| 78 | self.register_control(cx.waker()); | ||
| 79 | Poll::Pending | ||
| 80 | } | ||
| 81 | }) | ||
| 82 | .await | ||
| 83 | } | ||
| 84 | |||
| 85 | pub async fn wait_pending(&self) -> PendingIoctl { | ||
| 86 | let pending = poll_fn(|cx| { | ||
| 87 | if let IoctlStateInner::Pending(pending) = self.state.get() { | ||
| 88 | Poll::Ready(pending) | ||
| 89 | } else { | ||
| 90 | self.register_runner(cx.waker()); | ||
| 91 | Poll::Pending | ||
| 92 | } | ||
| 93 | }) | ||
| 94 | .await; | ||
| 95 | |||
| 96 | self.state.set(IoctlStateInner::Sent { buf: pending.buf }); | ||
| 97 | pending | ||
| 98 | } | ||
| 99 | |||
| 100 | pub fn cancel_ioctl(&self) { | ||
| 101 | self.state.set(IoctlStateInner::Done { resp_len: 0 }); | ||
| 102 | } | ||
| 103 | |||
| 104 | pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { | ||
| 105 | self.state | ||
| 106 | .set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface })); | ||
| 107 | self.wake_runner(); | ||
| 108 | self.wait_complete().await | ||
| 109 | } | ||
| 110 | |||
| 111 | pub fn ioctl_done(&self, response: &[u8]) { | ||
| 112 | if let IoctlStateInner::Sent { buf } = self.state.get() { | ||
| 113 | trace!("IOCTL Response: {:02x}", Bytes(response)); | ||
| 114 | |||
| 115 | // TODO fix this | ||
| 116 | (unsafe { &mut *buf }[..response.len()]).copy_from_slice(response); | ||
| 117 | |||
| 118 | self.state.set(IoctlStateInner::Done { | ||
| 119 | resp_len: response.len(), | ||
| 120 | }); | ||
| 121 | self.wake_control(); | ||
| 122 | } else { | ||
| 123 | warn!("IOCTL Response but no pending Ioctl"); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | } | ||
