1use core::mem::{self, MaybeUninit};
4use cortex_m::interrupt::{self, Mutex};
5use usb_device::bus::{PollResult, UsbBusAllocator};
6use usb_device::endpoint::{EndpointAddress, EndpointType};
7use usb_device::{Result, UsbDirection, UsbError};
8
9use crate::endpoint::{calculate_count_rx, Endpoint, EndpointStatus, NUM_ENDPOINTS};
10use crate::endpoint_memory::EndpointMemoryAllocator;
11use crate::registers::UsbRegisters;
12use crate::UsbPeripheral;
13
14pub struct UsbBus<USB> {
16 peripheral: USB,
17 regs: Mutex<UsbRegisters<USB>>,
18 endpoints: [Endpoint<USB>; NUM_ENDPOINTS],
19 ep_allocator: EndpointMemoryAllocator<USB>,
20 max_endpoint: usize,
21}
22
23impl<USB: UsbPeripheral> UsbBus<USB> {
24 pub fn new(peripheral: USB) -> UsbBusAllocator<Self> {
26 USB::enable();
27
28 let bus = UsbBus {
29 peripheral,
30 regs: Mutex::new(UsbRegisters::new()),
31 ep_allocator: EndpointMemoryAllocator::new(),
32 max_endpoint: 0,
33 endpoints: {
34 let mut endpoints: [MaybeUninit<Endpoint<USB>>; NUM_ENDPOINTS] =
35 unsafe { MaybeUninit::uninit().assume_init() };
36
37 for i in 0..NUM_ENDPOINTS {
38 endpoints[i] = MaybeUninit::new(Endpoint::new(i as u8));
39 }
40
41 unsafe { mem::transmute::<_, [Endpoint<USB>; NUM_ENDPOINTS]>(endpoints) }
42 },
43 };
44
45 UsbBusAllocator::new(bus)
46 }
47
48 pub fn free(self) -> USB {
49 self.peripheral
50 }
51
52 pub fn force_reenumeration<F: FnOnce()>(&self, disconnect: F) {
63 interrupt::free(|cs| {
64 let regs = self.regs.borrow(cs);
65
66 let pdwn = regs.cntr.read().pdwn().bit_is_set();
67 regs.cntr.modify(|_, w| w.pdwn().set_bit());
68
69 disconnect();
70
71 regs.cntr.modify(|_, w| w.pdwn().bit(pdwn));
72 });
73 }
74
75 pub fn suspend_low_power_mode(&self) -> bool {
85 interrupt::free(|cs| {
86 let regs = self.regs.borrow(cs);
87 if regs.cntr.read().fsusp().is_suspend() {
88 regs.cntr.modify(|_, w| w.lpmode().set_bit());
89 true
90 } else {
91 false
92 }
93 })
94 }
95
96 pub fn remote_wakeup(&self, resume: bool) {
107 interrupt::free(|cs| {
108 self.regs
109 .borrow(cs)
110 .cntr
111 .modify(|r, w| w.resume().bit(resume && r.fsusp().is_suspend()));
112 })
113 }
114}
115
116impl<USB: UsbPeripheral> usb_device::bus::UsbBus for UsbBus<USB> {
117 fn alloc_ep(
118 &mut self,
119 ep_dir: UsbDirection,
120 ep_addr: Option<EndpointAddress>,
121 ep_type: EndpointType,
122 max_packet_size: u16,
123 _interval: u8,
124 ) -> Result<EndpointAddress> {
125 for index in ep_addr.map(|a| a.index()..a.index() + 1).unwrap_or(1..NUM_ENDPOINTS) {
126 let ep = &mut self.endpoints[index];
127
128 match ep.ep_type() {
129 None => {
130 ep.set_ep_type(ep_type);
131 }
132 Some(t) if t != ep_type => {
133 continue;
134 }
135 _ => {}
136 };
137
138 match ep_dir {
139 UsbDirection::Out if !ep.is_out_buf_set() => {
140 let (out_size, size_bits) = calculate_count_rx(max_packet_size as usize)?;
141
142 let buffer = self.ep_allocator.allocate_buffer(out_size)?;
143
144 ep.set_out_buf(buffer, size_bits);
145
146 return Ok(EndpointAddress::from_parts(index, ep_dir));
147 }
148 UsbDirection::In if !ep.is_in_buf_set() => {
149 let size = (max_packet_size as usize + 1) & !0x01;
150
151 let buffer = self.ep_allocator.allocate_buffer(size)?;
152
153 ep.set_in_buf(buffer);
154
155 return Ok(EndpointAddress::from_parts(index, ep_dir));
156 }
157 _ => {}
158 }
159 }
160
161 Err(match ep_addr {
162 Some(_) => UsbError::InvalidEndpoint,
163 None => UsbError::EndpointOverflow,
164 })
165 }
166
167 fn enable(&mut self) {
168 let mut max = 0;
169 for (index, ep) in self.endpoints.iter().enumerate() {
170 if ep.is_out_buf_set() || ep.is_in_buf_set() {
171 max = index;
172 }
173 }
174
175 self.max_endpoint = max;
176
177 interrupt::free(|cs| {
178 let regs = self.regs.borrow(cs);
179
180 regs.cntr.modify(|_, w| w.pdwn().clear_bit());
181
182 USB::startup_delay();
183
184 regs.btable.modify(|_, w| w.btable().bits(0));
185 regs.cntr.modify(|_, w| {
186 w.fres().clear_bit();
187 w.resetm().set_bit();
188 w.suspm().set_bit();
189 w.wkupm().set_bit();
190 w.ctrm().set_bit()
191 });
192 regs.istr.modify(|_, w| unsafe { w.bits(0) });
193
194 if USB::DP_PULL_UP_FEATURE {
195 regs.bcdr.modify(|_, w| w.dppu().set_bit());
196 }
197 });
198 }
199
200 fn reset(&self) {
201 interrupt::free(|cs| {
202 let regs = self.regs.borrow(cs);
203
204 regs.istr.modify(|_, w| unsafe { w.bits(0) });
205 regs.daddr.modify(|_, w| w.ef().set_bit().add().bits(0));
206
207 for ep in self.endpoints.iter() {
208 ep.configure(cs);
209 }
210 });
211 }
212
213 fn set_device_address(&self, addr: u8) {
214 interrupt::free(|cs| {
215 self.regs.borrow(cs).daddr.modify(|_, w| w.add().bits(addr as u8));
216 });
217 }
218
219 fn poll(&self) -> PollResult {
220 interrupt::free(|cs| {
221 let regs = self.regs.borrow(cs);
222
223 let istr = regs.istr.read();
224
225 if istr.wkup().bit_is_set() {
226 regs.istr.write(|w| unsafe { w.bits(0xffff) }.wkup().clear_bit());
229
230 regs.cntr.modify(|_, w| w.fsusp().clear_bit());
232
233 PollResult::Resume
234 } else if istr.reset().bit_is_set() {
235 regs.istr.write(|w| unsafe { w.bits(0xffff) }.reset().clear_bit());
236
237 PollResult::Reset
238 } else if istr.susp().bit_is_set() {
239 regs.istr.write(|w| unsafe { w.bits(0xffff) }.susp().clear_bit());
240
241 PollResult::Suspend
242 } else if istr.ctr().bit_is_set() {
243 let mut ep_out = 0;
244 let mut ep_in_complete = 0;
245 let mut ep_setup = 0;
246 let mut bit = 1;
247
248 for ep in &self.endpoints[0..=self.max_endpoint] {
249 let v = ep.read_reg();
250
251 if v.ctr_rx().bit_is_set() {
252 ep_out |= bit;
253
254 if v.setup().bit_is_set() {
255 ep_setup |= bit;
256 }
257 }
258
259 if v.ctr_tx().bit_is_set() {
260 ep_in_complete |= bit;
261 ep.clear_ctr_tx(cs);
262 }
263
264 bit <<= 1;
265 }
266
267 PollResult::Data {
268 ep_out,
269 ep_in_complete,
270 ep_setup,
271 }
272 } else {
273 PollResult::None
274 }
275 })
276 }
277
278 fn write(&self, ep_addr: EndpointAddress, buf: &[u8]) -> Result<usize> {
279 if !ep_addr.is_in() {
280 return Err(UsbError::InvalidEndpoint);
281 }
282
283 self.endpoints[ep_addr.index()].write(buf)
284 }
285
286 fn read(&self, ep_addr: EndpointAddress, buf: &mut [u8]) -> Result<usize> {
287 if !ep_addr.is_out() {
288 return Err(UsbError::InvalidEndpoint);
289 }
290
291 self.endpoints[ep_addr.index()].read(buf)
292 }
293
294 fn set_stalled(&self, ep_addr: EndpointAddress, stalled: bool) {
295 interrupt::free(|cs| {
296 if self.is_stalled(ep_addr) == stalled {
297 return;
298 }
299
300 let ep = &self.endpoints[ep_addr.index()];
301
302 match (stalled, ep_addr.direction()) {
303 (true, UsbDirection::In) => ep.set_stat_tx(cs, EndpointStatus::Stall),
304 (true, UsbDirection::Out) => ep.set_stat_rx(cs, EndpointStatus::Stall),
305 (false, UsbDirection::In) => ep.set_stat_tx(cs, EndpointStatus::Nak),
306 (false, UsbDirection::Out) => ep.set_stat_rx(cs, EndpointStatus::Valid),
307 };
308 });
309 }
310
311 fn is_stalled(&self, ep_addr: EndpointAddress) -> bool {
312 let ep = &self.endpoints[ep_addr.index()];
313 let reg_v = ep.read_reg();
314
315 let status = match ep_addr.direction() {
316 UsbDirection::In => reg_v.stat_tx().bits(),
317 UsbDirection::Out => reg_v.stat_rx().bits(),
318 };
319
320 status == (EndpointStatus::Stall as u8)
321 }
322
323 fn suspend(&self) {
324 interrupt::free(|cs| {
325 self.regs.borrow(cs).cntr.modify(|_, w| w.fsusp().set_bit());
326 });
327 }
328
329 fn resume(&self) {
330 interrupt::free(|cs| {
331 self.regs
332 .borrow(cs)
333 .cntr
334 .modify(|_, w| w.fsusp().clear_bit().lpmode().clear_bit());
335 });
336 }
337}