esp_synopsys_usb_otg/
endpoint_memory.rs

1#![allow(dead_code)]
2use crate::target::{fifo_read_into, UsbRegisters};
3use crate::UsbPeripheral;
4use core::marker::PhantomData;
5use core::slice;
6use usb_device::{Result, UsbError};
7use vcell::VolatileCell;
8
9#[derive(Eq, PartialEq)]
10pub enum EndpointBufferState {
11    Empty,
12    DataOut,
13    DataSetup,
14}
15
16pub struct EndpointBuffer {
17    buffer: &'static mut [VolatileCell<u32>],
18    data_size: u16,
19    has_data: bool,
20    is_setup: bool,
21}
22
23impl EndpointBuffer {
24    pub fn new(buffer: &'static mut [u32]) -> Self {
25        Self {
26            buffer: unsafe { &mut *(buffer as *mut [u32] as *mut [VolatileCell<u32>]) },
27            data_size: 0,
28            has_data: false,
29            is_setup: false,
30        }
31    }
32
33    pub fn read_packet(&mut self, mut buf: &mut [u8]) -> Result<usize> {
34        if !self.has_data {
35            return Err(UsbError::WouldBlock);
36        }
37
38        let data_size = self.data_size as usize;
39
40        if buf.len() < data_size {
41            return Err(UsbError::BufferOverflow);
42        }
43
44        let mut index = 0;
45        let mut current_size = data_size;
46        while current_size >= 4 {
47            let word = self.buffer[index].get();
48            index += 1;
49
50            let bytes = word.to_ne_bytes();
51            buf[..4].copy_from_slice(&bytes);
52            buf = &mut buf[4..];
53
54            current_size -= 4;
55        }
56        if current_size > 0 {
57            let word = self.buffer[index].get();
58            let bytes = word.to_ne_bytes();
59            buf[..current_size].copy_from_slice(&bytes[..current_size]);
60        }
61
62        self.has_data = false;
63
64        Ok(data_size)
65    }
66
67    pub fn fill_from_fifo(
68        &mut self,
69        usb: UsbRegisters,
70        data_size: u16,
71        is_setup: bool,
72    ) -> Result<()> {
73        if self.has_data {
74            return Err(UsbError::WouldBlock);
75        }
76
77        if data_size as usize > self.capacity() {
78            return Err(UsbError::BufferOverflow);
79        }
80
81        let words = (data_size as usize + 3) / 4;
82        fifo_read_into(usb, &self.buffer[..words]);
83
84        self.is_setup = is_setup;
85        self.data_size = data_size;
86        self.has_data = true;
87
88        Ok(())
89    }
90
91    pub fn state(&self) -> EndpointBufferState {
92        if self.has_data {
93            if self.is_setup {
94                EndpointBufferState::DataSetup
95            } else {
96                EndpointBufferState::DataOut
97            }
98        } else {
99            EndpointBufferState::Empty
100        }
101    }
102
103    pub fn capacity(&self) -> usize {
104        self.buffer.len() * 4
105    }
106}
107
108impl Default for EndpointBuffer {
109    fn default() -> Self {
110        EndpointBuffer::new(&mut [])
111    }
112}
113
114pub struct EndpointMemoryAllocator<USB> {
115    next_free_offset: usize,
116    max_size_words: usize,
117    memory: &'static mut [u32],
118    tx_fifo_size_words: [u16; 9],
119    _marker: PhantomData<USB>,
120}
121
122impl<USB: UsbPeripheral> EndpointMemoryAllocator<USB> {
123    pub fn new(memory: &'static mut [u32]) -> Self {
124        Self {
125            next_free_offset: 0,
126            max_size_words: 0,
127            memory,
128            tx_fifo_size_words: [0; 9],
129            _marker: PhantomData,
130        }
131    }
132
133    pub fn allocate_rx_buffer(&mut self, size: usize) -> Result<EndpointBuffer> {
134        let size_words = (size + 3) / 4;
135
136        let offset = self.next_free_offset;
137        if offset + size_words > self.memory.len() {
138            return Err(UsbError::EndpointMemoryOverflow);
139        }
140
141        self.next_free_offset += size_words;
142        self.max_size_words = core::cmp::max(self.max_size_words, size_words);
143
144        let buffer = unsafe {
145            let ptr = self.memory.as_mut_ptr().add(offset);
146            slice::from_raw_parts_mut(ptr, size_words)
147        };
148        Ok(EndpointBuffer::new(buffer))
149    }
150
151    pub fn allocate_tx_buffer(&mut self, ep_number: u8, size: usize) -> Result<()> {
152        let ep_number = ep_number as usize;
153        assert!(ep_number < self.tx_fifo_size_words.len());
154
155        if self.tx_fifo_size_words[ep_number] != 0 {
156            return Err(UsbError::InvalidEndpoint);
157        }
158
159        let used = 30
160            + self.total_rx_buffer_size_words() as usize
161            + self.tx_fifo_size_words.iter().sum::<u16>() as usize;
162
163        let size_words = core::cmp::max((size + 3) / 4, 16);
164        if (used + size_words) > USB::FIFO_DEPTH_WORDS {
165            return Err(UsbError::EndpointMemoryOverflow);
166        }
167
168        self.tx_fifo_size_words[ep_number] = size_words as u16;
169
170        Ok(())
171    }
172
173    /// Returns the size of memory allocated for OUT endpoints in words
174    pub fn total_rx_buffer_size_words(&self) -> u16 {
175        self.next_free_offset as u16
176    }
177
178    pub fn tx_fifo_size_words(&self, ep_number: usize) -> u16 {
179        self.tx_fifo_size_words[ep_number]
180    }
181
182    pub fn max_buffer_size_words(&self) -> usize {
183        self.max_size_words
184    }
185}