esp_synopsys_usb_otg/
endpoint.rs

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
41/// Arbitrates access to the endpoint-specific registers and packet buffer memory.
42pub 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        // deactivating endpoint
110        modify_reg!(endpoint_in, regs, DIEPCTL, USBAEP: 0);
111
112        // TODO: flushing FIFO
113
114        // disabling endpoint
115        if read_reg!(endpoint_in, regs, DIEPCTL, EPENA) != 0 && self.index() != 0 {
116            modify_reg!(endpoint_in, regs, DIEPCTL, EPDIS: 1)
117        }
118
119        // clean EP interrupts
120        write_reg!(endpoint_in, regs, DIEPINT, 0xff);
121
122        // TODO: deconfiguring TX FIFO
123    }
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            // Check for FIFO free space
138            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            // Isochronous endpoints must set the correct even/odd frame bit to
148            // correspond with the next frame's number.
149            EndpointType::Isochronous { .. } => {
150                // Previous frame number is OTG_DSTS.FNSOF
151                let frame_number = read_reg!(otg_device, device, DSTS, FNSOF);
152                if frame_number & 0x1 == 1 {
153                    // Previous frame number is odd, so upcoming frame is even
154                    modify_reg!(endpoint_in, ep, DIEPCTL, SD0PID_SEVNFRM: 1);
155                } else {
156                    // Previous frame number is even, so upcoming frame is odd
157                    #[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        // deactivating endpoint
220        modify_reg!(endpoint_out, regs, DOEPCTL, USBAEP: 0);
221
222        // disabling endpoint
223        if read_reg!(endpoint_out, regs, DOEPCTL, EPENA) != 0 && self.index() != 0 {
224            modify_reg!(endpoint_out, regs, DOEPCTL, EPDIS: 1)
225        }
226
227        // clean EP interrupts
228        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            // Isochronous endpoints must set the correct even/odd frame bit to
237            // correspond with the next frame's number.
238            EndpointType::Isochronous { .. } => {
239                // Previous frame number is OTG_DSTS.FNSOF
240                let frame_number = read_reg!(otg_device, device, DSTS, FNSOF);
241                if frame_number & 0x1 == 1 {
242                    // Previous frame number is odd, so upcoming frame is even
243                    modify_reg!(endpoint_out, ep, DOEPCTL, SD0PID_SEVNFRM: 1);
244                } else {
245                    // Previous frame number is even, so upcoming frame is odd
246                    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}