aboutsummaryrefslogtreecommitdiff
path: root/cyw43/src/ioctl.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-05-30 22:42:49 +0200
committerDario Nieuwenhuis <[email protected]>2023-05-30 22:42:49 +0200
commitc327c6cd6fc3c11cfaf83cf64591940d401c5f6b (patch)
tree1e9f693a74b01ae930caa145ae282c24276510e3 /cyw43/src/ioctl.rs
parent3cc0ec654a1e46fe7b8fa168942452303343cd84 (diff)
cyw43: move crate to subdir.
Diffstat (limited to 'cyw43/src/ioctl.rs')
-rw-r--r--cyw43/src/ioctl.rs126
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 @@
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 enum IoctlType {
11 Get = 0,
12 Set = 2,
13}
14
15#[derive(Clone, Copy)]
16pub 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)]
24enum IoctlStateInner {
25 Pending(PendingIoctl),
26 Sent { buf: *mut [u8] },
27 Done { resp_len: usize },
28}
29
30struct Wakers {
31 control: WakerRegistration,
32 runner: WakerRegistration,
33}
34
35impl Default for Wakers {
36 fn default() -> Self {
37 Self {
38 control: WakerRegistration::new(),
39 runner: WakerRegistration::new(),
40 }
41 }
42}
43
44pub struct IoctlState {
45 state: Cell<IoctlStateInner>,
46 wakers: RefCell<Wakers>,
47}
48
49impl 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}