1use std::cmp;
6use std::sync::Arc;
7
8use base::debug;
9use base::error;
10use usb_util::EndpointDirection;
11use usb_util::EndpointType;
12use usb_util::TransferBuffer;
13use usb_util::TransferStatus;
14use usb_util::ENDPOINT_DIRECTION_OFFSET;
15
16use crate::usb::backend::device::BackendDevice;
17use crate::usb::backend::device::BackendDeviceType;
18use crate::usb::backend::error::Error;
19use crate::usb::backend::error::Result;
20use crate::usb::backend::transfer::BackendTransfer;
21use crate::usb::backend::transfer::BackendTransferType;
22use crate::usb::backend::utils::update_transfer_state;
23use crate::usb::xhci::scatter_gather_buffer::ScatterGatherBuffer;
24use crate::usb::xhci::xhci_transfer::TransferDirection;
25use crate::usb::xhci::xhci_transfer::XhciTransfer;
26use crate::usb::xhci::xhci_transfer::XhciTransferState;
27use crate::usb::xhci::xhci_transfer::XhciTransferType;
28use crate::utils::AsyncJobQueue;
29use crate::utils::FailHandle;
30
31#[derive(Copy, Clone, PartialEq, Eq)]
32pub enum ControlEndpointState {
33 SetupStage,
35 DataStage,
37 StatusStage,
39}
40
41pub struct UsbEndpoint {
43 fail_handle: Arc<dyn FailHandle>,
44 job_queue: Arc<AsyncJobQueue>,
45 endpoint_number: u8,
46 direction: EndpointDirection,
47 ty: EndpointType,
48}
49
50impl UsbEndpoint {
51 pub fn new(
53 fail_handle: Arc<dyn FailHandle>,
54 job_queue: Arc<AsyncJobQueue>,
55 endpoint_number: u8,
56 direction: EndpointDirection,
57 ty: EndpointType,
58 ) -> UsbEndpoint {
59 assert!(ty != EndpointType::Control);
60 UsbEndpoint {
61 fail_handle,
62 job_queue,
63 endpoint_number,
64 direction,
65 ty,
66 }
67 }
68
69 fn ep_addr(&self) -> u8 {
70 self.endpoint_number | ((self.direction as u8) << ENDPOINT_DIRECTION_OFFSET)
71 }
72
73 pub fn match_ep(&self, endpoint_number: u8, dir: TransferDirection) -> bool {
75 let self_dir = match self.direction {
76 EndpointDirection::HostToDevice => TransferDirection::Out,
77 EndpointDirection::DeviceToHost => TransferDirection::In,
78 };
79 self.endpoint_number == endpoint_number && self_dir == dir
80 }
81
82 pub fn handle_transfer(
87 &self,
88 device: &mut BackendDeviceType,
89 transfer: XhciTransfer,
90 ) -> Result<()> {
91 let transfer_type = match transfer.get_transfer_type() {
92 Ok(ty) => ty,
93 Err(e) => {
94 error!("failed to get transfer type: {}", e);
95 return transfer
96 .on_transfer_complete(&TransferStatus::Error, 0)
97 .map_err(Error::TransferComplete);
98 }
99 };
100 let buffer = match transfer_type {
101 XhciTransferType::Normal => transfer.create_buffer().map_err(Error::CreateBuffer)?,
102 XhciTransferType::Noop => {
103 return transfer
104 .on_transfer_complete(&TransferStatus::Completed, 0)
105 .map_err(Error::TransferComplete);
106 }
107 _ => {
108 error!("unhandled xhci transfer type by usb endpoint");
109 return transfer
110 .on_transfer_complete(&TransferStatus::Error, 0)
111 .map_err(Error::TransferComplete);
112 }
113 };
114
115 match self.ty {
116 EndpointType::Bulk => {
117 self.handle_bulk_transfer(device, transfer, buffer)?;
118 }
119 EndpointType::Interrupt => {
120 self.handle_interrupt_transfer(device, transfer, buffer)?;
121 }
122 _ => {
123 return transfer
124 .on_transfer_complete(&TransferStatus::Error, 0)
125 .map_err(Error::TransferComplete);
126 }
127 }
128 Ok(())
129 }
130
131 fn get_transfer_buffer(
132 &self,
133 buffer: &ScatterGatherBuffer,
134 device: &mut BackendDeviceType,
135 ) -> Result<TransferBuffer> {
136 let len = buffer.len().map_err(Error::BufferLen)?;
137 let mut buf = device.request_transfer_buffer(len);
138 if self.direction == EndpointDirection::HostToDevice {
139 match &mut buf {
141 TransferBuffer::Dma(dmabuf) => {
142 if let Some(buf) = dmabuf.upgrade() {
143 buffer
144 .read(buf.lock().as_mut_slice())
145 .map_err(Error::ReadBuffer)?;
146 } else {
147 return Err(Error::GetDmaBuffer);
148 }
149 }
150 TransferBuffer::Vector(v) => {
151 buffer.read(v.as_mut_slice()).map_err(Error::ReadBuffer)?;
152 }
153 }
154 }
155 Ok(buf)
156 }
157
158 fn handle_bulk_transfer(
159 &self,
160 device: &mut BackendDeviceType,
161 xhci_transfer: XhciTransfer,
162 buffer: ScatterGatherBuffer,
163 ) -> Result<()> {
164 let transfer_buffer = self.get_transfer_buffer(&buffer, device)?;
165 let usb_transfer = device.build_bulk_transfer(
166 self.ep_addr(),
167 transfer_buffer,
168 xhci_transfer.get_stream_id(),
169 )?;
170 self.do_handle_transfer(device, xhci_transfer, usb_transfer, buffer)
171 }
172
173 fn handle_interrupt_transfer(
174 &self,
175 device: &mut BackendDeviceType,
176 xhci_transfer: XhciTransfer,
177 buffer: ScatterGatherBuffer,
178 ) -> Result<()> {
179 let transfer_buffer = self.get_transfer_buffer(&buffer, device)?;
180 let usb_transfer = device.build_interrupt_transfer(self.ep_addr(), transfer_buffer)?;
181 self.do_handle_transfer(device, xhci_transfer, usb_transfer, buffer)
182 }
183
184 fn do_handle_transfer(
185 &self,
186 device: &mut BackendDeviceType,
187 xhci_transfer: XhciTransfer,
188 mut usb_transfer: BackendTransferType,
189 buffer: ScatterGatherBuffer,
190 ) -> Result<()> {
191 let xhci_transfer = Arc::new(xhci_transfer);
192 let tmp_transfer = xhci_transfer.clone();
193 match self.direction {
194 EndpointDirection::HostToDevice => {
195 let _trace = cros_tracing::trace_event!(
196 USB,
197 "Endpoint out transfer",
198 self.ep_addr(),
199 buffer.len()
200 );
201 let callback = move |t: BackendTransferType| {
202 let mut state = xhci_transfer.state().lock();
203 update_transfer_state(&mut state, t.status())?;
204 match *state {
205 XhciTransferState::Cancelled => {
206 debug!("Xhci transfer has been cancelled");
207 drop(state);
208 xhci_transfer
209 .on_transfer_complete(&TransferStatus::Cancelled, 0)
210 .map_err(Error::TransferComplete)
211 }
212 XhciTransferState::Completed => {
213 let status = t.status();
214 let actual_length = t.actual_length();
215 drop(state);
216 xhci_transfer
217 .on_transfer_complete(&status, actual_length as u32)
218 .map_err(Error::TransferComplete)
219 }
220 _ => {
221 error!("xhci trasfer state (host to device) is invalid");
222 Err(Error::BadXhciTransferState)
223 }
224 }
225 };
226 let fail_handle = self.fail_handle.clone();
227 usb_transfer.set_callback(move |t: BackendTransferType| match callback(t) {
228 Ok(_) => {}
229 Err(e) => {
230 error!("bulk transfer callback failed: {:?}", e);
231 fail_handle.fail();
232 }
233 });
234 device.submit_transfer(
235 self.fail_handle.clone(),
236 &self.job_queue,
237 tmp_transfer,
238 usb_transfer,
239 )?;
240 }
241 EndpointDirection::DeviceToHost => {
242 let _trace = cros_tracing::trace_event!(
243 USB,
244 "Endpoint in transfer",
245 self.ep_addr(),
246 buffer.len()
247 );
248 let _addr = self.ep_addr();
249 let callback = move |t: BackendTransferType| {
250 let mut state = xhci_transfer.state().lock();
251 update_transfer_state(&mut state, t.status())?;
252 match *state {
253 XhciTransferState::Cancelled => {
254 debug!("Xhci transfer has been cancelled");
255 drop(state);
256 xhci_transfer
257 .on_transfer_complete(&TransferStatus::Cancelled, 0)
258 .map_err(Error::TransferComplete)
259 }
260 XhciTransferState::Completed => {
261 let status = t.status();
262 let actual_length = t.actual_length();
263 let copied_length = match t.buffer() {
264 TransferBuffer::Vector(v) => {
265 buffer.write(v.as_slice()).map_err(Error::WriteBuffer)?
266 }
267 TransferBuffer::Dma(buf) => {
268 if let Some(buf) = buf.upgrade() {
269 buffer
270 .write(buf.lock().as_slice())
271 .map_err(Error::WriteBuffer)?
272 } else {
273 return Err(Error::GetDmaBuffer);
274 }
275 }
276 };
277 let actual_length = cmp::min(actual_length, copied_length);
278 drop(state);
279 xhci_transfer
280 .on_transfer_complete(&status, actual_length as u32)
281 .map_err(Error::TransferComplete)
282 }
283 _ => {
284 error!("xhci trasfer state (device to host) is invalid");
287 Err(Error::BadXhciTransferState)
288 }
289 }
290 };
291 let fail_handle = self.fail_handle.clone();
292
293 usb_transfer.set_callback(move |t: BackendTransferType| match callback(t) {
294 Ok(_) => {}
295 Err(e) => {
296 error!("bulk transfer callback {:?}", e);
297 fail_handle.fail();
298 }
299 });
300
301 device.submit_transfer(
302 self.fail_handle.clone(),
303 &self.job_queue,
304 tmp_transfer,
305 usb_transfer,
306 )?;
307 }
308 }
309 Ok(())
310 }
311}