1use crate::endpoint_memory::{EndpointBuffer, EndpointBufferState};
2use crate::ral::{
3 endpoint0_out, endpoint_in, endpoint_out, modify_reg, otg_device, read_reg, write_reg,
4};
5use crate::target::{fifo_write, UsbRegisters};
6use crate::transition::EndpointDescriptor;
7use crate::UsbPeripheral;
8use core::cell::RefCell;
9use core::ops::{Deref, DerefMut};
10use critical_section::{CriticalSection, Mutex};
11use usb_device::endpoint::{EndpointAddress, EndpointType};
12use usb_device::{Result, UsbDirection, UsbError};
13
14pub fn set_stalled(usb: UsbRegisters, address: EndpointAddress, stalled: bool) {
15 critical_section::with(|_| match address.direction() {
16 UsbDirection::Out => {
17 let ep = usb.endpoint_out(address.index() as usize);
18 modify_reg!(endpoint_out, ep, DOEPCTL, STALL: stalled as u32);
19 }
20 UsbDirection::In => {
21 let ep = usb.endpoint_in(address.index() as usize);
22 modify_reg!(endpoint_in, ep, DIEPCTL, STALL: stalled as u32);
23 }
24 })
25}
26
27pub fn is_stalled(usb: UsbRegisters, address: EndpointAddress) -> bool {
28 let stall = match address.direction() {
29 UsbDirection::Out => {
30 let ep = usb.endpoint_out(address.index());
31 read_reg!(endpoint_out, ep, DOEPCTL, STALL)
32 }
33 UsbDirection::In => {
34 let ep = usb.endpoint_in(address.index());
35 read_reg!(endpoint_in, ep, DIEPCTL, STALL)
36 }
37 };
38 stall != 0
39}
40
41pub struct Endpoint {
43 descriptor: EndpointDescriptor,
44 usb: UsbRegisters,
45}
46
47impl Endpoint {
48 pub fn new<USB: UsbPeripheral>(descriptor: EndpointDescriptor) -> Endpoint {
49 Endpoint {
50 descriptor,
51 usb: UsbRegisters::new::<USB>(),
52 }
53 }
54
55 pub fn address(&self) -> EndpointAddress {
56 self.descriptor.address
57 }
58
59 #[inline(always)]
60 fn index(&self) -> u8 {
61 self.descriptor.address.index() as u8
62 }
63
64 pub fn ep_type(&self) -> EndpointType {
65 self.descriptor.ep_type
66 }
67}
68
69pub struct EndpointIn {
70 common: Endpoint,
71}
72
73impl EndpointIn {
74 pub fn new<USB: UsbPeripheral>(descriptor: EndpointDescriptor) -> EndpointIn {
75 EndpointIn {
76 common: Endpoint::new::<USB>(descriptor),
77 }
78 }
79
80 pub fn configure(&self, _cs: CriticalSection<'_>) {
81 if self.index() == 0 {
82 let mpsiz = match self.descriptor.max_packet_size {
83 8 => 0b11,
84 16 => 0b10,
85 32 => 0b01,
86 64 => 0b00,
87 other => panic!("Unsupported EP0 size: {}", other),
88 };
89
90 let regs = self.usb.endpoint_in(self.index() as usize);
91 write_reg!(endpoint_in, regs, DIEPCTL, MPSIZ: mpsiz as u32, SNAK: 1);
92 write_reg!(endpoint_in, regs, DIEPTSIZ, PKTCNT: 0, XFRSIZ: self.descriptor.max_packet_size as u32);
93 } else {
94 let regs = self.usb.endpoint_in(self.index() as usize);
95 write_reg!(endpoint_in, regs, DIEPCTL,
96 SNAK: 1,
97 USBAEP: 1,
98 EPTYP: self.descriptor.ep_type.to_bm_attributes() as u32,
99 SD0PID_SEVNFRM: 1,
100 TXFNUM: self.index() as u32,
101 MPSIZ: self.descriptor.max_packet_size as u32
102 );
103 }
104 }
105
106 pub fn deconfigure(&self, _cs: CriticalSection<'_>) {
107 let regs = self.usb.endpoint_in(self.index() as usize);
108
109 modify_reg!(endpoint_in, regs, DIEPCTL, USBAEP: 0);
111
112 if read_reg!(endpoint_in, regs, DIEPCTL, EPENA) != 0 && self.index() != 0 {
116 modify_reg!(endpoint_in, regs, DIEPCTL, EPDIS: 1)
117 }
118
119 write_reg!(endpoint_in, regs, DIEPINT, 0xff);
121
122 }
124
125 pub fn write(&self, buf: &[u8]) -> Result<()> {
126 let ep = self.usb.endpoint_in(self.index() as usize);
127 let device = self.usb.device();
128 if self.index() != 0 && read_reg!(endpoint_in, ep, DIEPCTL, EPENA) != 0 {
129 return Err(UsbError::WouldBlock);
130 }
131
132 if buf.len() > self.descriptor.max_packet_size as usize {
133 return Err(UsbError::BufferOverflow);
134 }
135
136 if !buf.is_empty() {
137 let size_words = (buf.len() + 3) / 4;
139 if size_words > read_reg!(endpoint_in, ep, DTXFSTS, INEPTFSAV) as usize {
140 return Err(UsbError::WouldBlock);
141 }
142 }
143
144 write_reg!(endpoint_in, ep, DIEPTSIZ, MCNT: 1, PKTCNT: 1, XFRSIZ: buf.len() as u32);
145
146 match self.descriptor.ep_type {
147 EndpointType::Isochronous { .. } => {
150 let frame_number = read_reg!(otg_device, device, DSTS, FNSOF);
152 if frame_number & 0x1 == 1 {
153 modify_reg!(endpoint_in, ep, DIEPCTL, SD0PID_SEVNFRM: 1);
155 } else {
156 #[cfg(feature = "fs")]
158 modify_reg!(endpoint_in, ep, DIEPCTL, SODDFRM_SD1PID: 1);
159 #[cfg(feature = "hs")]
160 modify_reg!(endpoint_in, ep, DIEPCTL, SODDFRM: 1);
161 }
162 }
163 _ => {}
164 }
165
166 modify_reg!(endpoint_in, ep, DIEPCTL, CNAK: 1, EPENA: 1);
167
168 fifo_write(self.usb, self.index(), buf);
169
170 Ok(())
171 }
172}
173
174pub struct EndpointOut {
175 common: Endpoint,
176 pub(crate) buffer: Mutex<RefCell<EndpointBuffer>>,
177}
178
179impl EndpointOut {
180 pub fn new<USB: UsbPeripheral>(
181 descriptor: EndpointDescriptor,
182 buffer: EndpointBuffer,
183 ) -> EndpointOut {
184 EndpointOut {
185 common: Endpoint::new::<USB>(descriptor),
186 buffer: Mutex::new(RefCell::new(buffer)),
187 }
188 }
189
190 pub fn configure(&self, _cs: CriticalSection<'_>) {
191 if self.index() == 0 {
192 let mpsiz = match self.descriptor.max_packet_size {
193 8 => 0b11,
194 16 => 0b10,
195 32 => 0b01,
196 64 => 0b00,
197 other => panic!("Unsupported EP0 size: {}", other),
198 };
199
200 let regs = self.usb.endpoint0_out();
201 write_reg!(endpoint0_out, regs, DOEPTSIZ0, STUPCNT: 1, PKTCNT: 1, XFRSIZ: self.descriptor.max_packet_size as u32);
202 modify_reg!(endpoint0_out, regs, DOEPCTL0, MPSIZ: mpsiz as u32, EPENA: 1, CNAK: 1);
203 } else {
204 let regs = self.usb.endpoint_out(self.index() as usize);
205 write_reg!(endpoint_out, regs, DOEPCTL,
206 SD0PID_SEVNFRM: 1,
207 CNAK: 1,
208 EPENA: 1,
209 USBAEP: 1,
210 EPTYP: self.descriptor.ep_type.to_bm_attributes() as u32,
211 MPSIZ: self.descriptor.max_packet_size as u32
212 );
213 }
214 }
215
216 pub fn deconfigure(&self, _cs: CriticalSection<'_>) {
217 let regs = self.usb.endpoint_out(self.index() as usize);
218
219 modify_reg!(endpoint_out, regs, DOEPCTL, USBAEP: 0);
221
222 if read_reg!(endpoint_out, regs, DOEPCTL, EPENA) != 0 && self.index() != 0 {
224 modify_reg!(endpoint_out, regs, DOEPCTL, EPDIS: 1)
225 }
226
227 write_reg!(endpoint_out, regs, DOEPINT, 0xff);
229 }
230
231 pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
232 let ep = self.usb.endpoint_out(self.index() as usize);
233 let device = self.usb.device();
234
235 match self.descriptor.ep_type {
236 EndpointType::Isochronous { .. } => {
239 let frame_number = read_reg!(otg_device, device, DSTS, FNSOF);
241 if frame_number & 0x1 == 1 {
242 modify_reg!(endpoint_out, ep, DOEPCTL, SD0PID_SEVNFRM: 1);
244 } else {
245 modify_reg!(endpoint_out, ep, DOEPCTL, SODDFRM: 1);
247 }
248 }
249 _ => {}
250 }
251
252 critical_section::with(|cs| self.buffer.borrow_ref_mut(cs).read_packet(buf))
253 }
254
255 pub fn buffer_state(&self) -> EndpointBufferState {
256 critical_section::with(|cs| self.buffer.borrow_ref(cs).state())
257 }
258}
259
260impl Deref for EndpointIn {
261 type Target = Endpoint;
262
263 fn deref(&self) -> &Self::Target {
264 &self.common
265 }
266}
267
268impl DerefMut for EndpointIn {
269 fn deref_mut(&mut self) -> &mut Self::Target {
270 &mut self.common
271 }
272}
273
274impl Deref for EndpointOut {
275 type Target = Endpoint;
276
277 fn deref(&self) -> &Self::Target {
278 &self.common
279 }
280}
281
282impl DerefMut for EndpointOut {
283 fn deref_mut(&mut self) -> &mut Self::Target {
284 &mut self.common
285 }
286}