ra_hal/usb/
control_pipe.rs1use core::{marker::PhantomData, sync::atomic::Ordering, task::Poll};
4
5use embassy_usb_driver::{ControlPipe as DriverControlPipe, EndpointError};
6
7use crate::{
8 pac::usbfs::vals::{CfifoselCurpipe, DcpctrPid},
9 usb::{Instance, STATE},
10};
11
12pub struct ControlPipe<'a, I: Instance> {
14 pub(crate) _phantom: PhantomData<&'a I>,
15 pub(crate) max_packet_size: u16,
16}
17
18impl<'a, I: Instance> DriverControlPipe for ControlPipe<'a, I> {
19 fn max_packet_size(&self) -> usize {
20 self.max_packet_size as _
21 }
22
23 async fn setup(&mut self) -> [u8; 8] {
24 let pkt = core::future::poll_fn(|cx| {
25 STATE.ep_wakers[0].register(cx.waker());
26
27 if STATE.setup_ready.load(Ordering::Acquire) {
28 STATE.setup_ready.store(false, Ordering::Release);
29 let lo = STATE.setup_lo.load(Ordering::Acquire);
30 let hi = STATE.setup_hi.load(Ordering::Acquire);
31 let pkt = [
32 lo as _,
33 (lo >> 8) as _,
34 (lo >> 16) as _,
35 (lo >> 24) as _,
36 hi as _,
37 (hi >> 8) as _,
38 (hi >> 16) as _,
39 (hi >> 24) as _,
40 ];
41 Poll::Ready(pkt)
42 } else {
43 Poll::Pending
44 }
45 })
46 .await;
47
48 debug!(
49 "USB: setup [{:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}]",
50 pkt[0], pkt[1], pkt[2], pkt[3], pkt[4], pkt[5], pkt[6], pkt[7]
51 );
52 pkt
53 }
54
55 async fn data_out(
56 &mut self,
57 buf: &mut [u8],
58 _first: bool,
59 _last: bool,
60 ) -> Result<usize, EndpointError> {
61 trace!("USB: ctrl data_out waiting (buf={})", buf.len());
62 let r = I::regs();
63
64 r.cfifosel().modify(|r| {
66 r.set_curpipe(CfifoselCurpipe::Default);
67 r.set_isel(false);
69 });
70
71 r.dcpctr().modify(|r| r.set_pid(DcpctrPid::Buffer));
74
75 core::future::poll_fn(|cx| {
77 STATE.ep_wakers[0].register(cx.waker());
78 if STATE.pipe_brdy.load(Ordering::Acquire) & 1 != 0 {
79 STATE.pipe_brdy.fetch_and(!1, Ordering::AcqRel);
80 Poll::Ready(())
81 } else {
82 Poll::Pending
83 }
84 })
85 .await;
86
87 while !r.cfifoctr().read().frdy() {
89 cortex_m::asm::nop();
90 }
91
92 let data_len = r.cfifoctr().read().dtln() as usize;
93 let read_len = data_len.min(buf.len());
94 if data_len > read_len {
95 r.cfifoctr().modify(|r| r.set_bclr(true));
97 return Err(EndpointError::BufferOverflow);
98 }
99
100 for byte in buf[..read_len].iter_mut() {
101 *byte = r.cfifol().read().fifoport();
102 }
103
104 if data_len > read_len {
106 r.cfifoctr().modify(|r| r.set_bclr(true));
107 }
108
109 trace!("USB: ctrl data_out read {} bytes", read_len);
110 Ok(read_len)
111 }
112
113 async fn data_in(
114 &mut self,
115 data: &[u8],
116 _first: bool,
117 last: bool,
118 ) -> Result<(), EndpointError> {
119 trace!("USB: ctrl data_in {} bytes, last={}", data.len(), last);
120 let r = I::regs();
121
122 if data.is_empty() && last {
123 r.dcpctr().modify(|r| {
125 r.set_pid(DcpctrPid::Buffer);
126 r.set_ccpl(true);
127 });
128 return Ok(());
129 }
130
131 STATE.pipe_bemp.fetch_and(!1, Ordering::AcqRel);
136
137 r.cfifosel().modify(|r| {
139 r.set_curpipe(CfifoselCurpipe::Default);
140 r.set_isel(true);
141 });
142
143 while !r.cfifoctr().read().frdy() {
145 cortex_m::asm::nop();
146 }
147
148 for &byte in data {
149 r.cfifol().write(|w| w.set_fifoport(byte));
150 }
151
152 r.cfifoctr().modify(|r| r.set_bval(true));
154
155 if last {
157 r.dcpctr().modify(|r| r.set_ccpl(true));
158 }
159
160 r.dcpctr().modify(|r| r.set_pid(DcpctrPid::Buffer));
162
163 core::future::poll_fn(|cx| {
164 STATE.ep_wakers[0].register(cx.waker());
165 if STATE.pipe_bemp.load(Ordering::Acquire) & 1 != 0 {
166 STATE.pipe_bemp.fetch_and(!1, Ordering::AcqRel);
167 return Poll::Ready(());
168 } else {
169 Poll::Pending
170 }
171 })
172 .await;
173
174 Ok(())
175 }
176
177 async fn accept(&mut self) {
178 debug!("USB: ctrl accept");
179 let r = I::regs();
180 r.dcpctr().modify(|r| {
181 r.set_pid(DcpctrPid::Buffer);
182 r.set_ccpl(true);
187 })
188 }
189
190 async fn reject(&mut self) {
191 debug!("USB: ctrl reject");
192 let r = I::regs();
193 r.dcpctr().modify(|r| r.set_pid(DcpctrPid::Stall2));
194 }
195
196 async fn accept_set_address(&mut self, addr: u8) {
197 debug!("USB: ctrl accept_set_address={}", addr);
198 self.accept().await;
203 }
204}