aboutsummaryrefslogtreecommitdiff
path: root/embassy-net-esp-hosted/src/ioctl.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-06-09 03:36:48 +0200
committerDario Nieuwenhuis <[email protected]>2023-06-22 21:12:10 +0200
commit6c123596b7d48ee66ea93e8b1515e91231e9bced (patch)
tree7f657d78d2fac5a24982d74b909789d60a2dfee7 /embassy-net-esp-hosted/src/ioctl.rs
parent1f2be2dac5eeed739d2866b9b63ca06fdd84c276 (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.rs119
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 @@
1use core::cell::{Cell, RefCell};
2use core::future::poll_fn;
3use core::task::{Poll, Waker};
4
5use embassy_sync::waitqueue::WakerRegistration;
6
7use crate::fmt::Bytes;
8
9#[derive(Clone, Copy)]
10pub struct PendingIoctl {
11 pub buf: *mut [u8],
12 pub req_len: usize,
13}
14
15#[derive(Clone, Copy)]
16enum IoctlStateInner {
17 Pending(PendingIoctl),
18 Sent { buf: *mut [u8] },
19 Done { resp_len: usize },
20}
21
22struct Wakers {
23 control: WakerRegistration,
24 runner: WakerRegistration,
25}
26
27impl Default for Wakers {
28 fn default() -> Self {
29 Self {
30 control: WakerRegistration::new(),
31 runner: WakerRegistration::new(),
32 }
33 }
34}
35
36pub struct IoctlState {
37 state: Cell<IoctlStateInner>,
38 wakers: RefCell<Wakers>,
39}
40
41impl 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}