esp_synopsys_usb_otg/
endpoint_memory.rs1#![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 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}