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