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 | XhciTransferType::Isochronous => {
102 transfer.create_buffer().map_err(Error::CreateBuffer)?
103 }
104 XhciTransferType::Noop => {
105 return transfer
106 .on_transfer_complete(&TransferStatus::Completed, 0)
107 .map_err(Error::TransferComplete);
108 }
109 _ => {
110 error!("unhandled xhci transfer type by usb endpoint");
111 return transfer
112 .on_transfer_complete(&TransferStatus::Error, 0)
113 .map_err(Error::TransferComplete);
114 }
115 };
116
117 match self.ty {
118 EndpointType::Bulk => {
119 self.handle_bulk_transfer(device, transfer, buffer)?;
120 }
121 EndpointType::Interrupt => {
122 self.handle_interrupt_transfer(device, transfer, buffer)?;
123 }
124 EndpointType::Isochronous => {
125 self.handle_isochronous_transfer(device, transfer, buffer)?;
126 }
127 _ => {
128 return transfer
129 .on_transfer_complete(&TransferStatus::Error, 0)
130 .map_err(Error::TransferComplete);
131 }
132 }
133 Ok(())
134 }
135
136 fn get_transfer_buffer(
137 &self,
138 buffer: &ScatterGatherBuffer,
139 device: &mut BackendDeviceType,
140 ) -> Result<TransferBuffer> {
141 let len = buffer.len().map_err(Error::BufferLen)?;
142 let mut buf = device.request_transfer_buffer(len);
143 if self.direction == EndpointDirection::HostToDevice {
144 match &mut buf {
146 TransferBuffer::Dma(dmabuf) => {
147 if let Some(buf) = dmabuf.upgrade() {
148 buffer
149 .read(buf.lock().as_mut_slice())
150 .map_err(Error::ReadBuffer)?;
151 } else {
152 return Err(Error::GetDmaBuffer);
153 }
154 }
155 TransferBuffer::Vector(v) => {
156 buffer.read(v.as_mut_slice()).map_err(Error::ReadBuffer)?;
157 }
158 }
159 }
160 Ok(buf)
161 }
162
163 fn handle_bulk_transfer(
164 &self,
165 device: &mut BackendDeviceType,
166 xhci_transfer: XhciTransfer,
167 buffer: ScatterGatherBuffer,
168 ) -> Result<()> {
169 let transfer_buffer = self.get_transfer_buffer(&buffer, device)?;
170 let usb_transfer = device.build_bulk_transfer(
171 self.ep_addr(),
172 transfer_buffer,
173 xhci_transfer.get_stream_id(),
174 )?;
175 self.do_handle_transfer(device, xhci_transfer, usb_transfer, buffer)
176 }
177
178 fn handle_interrupt_transfer(
179 &self,
180 device: &mut BackendDeviceType,
181 xhci_transfer: XhciTransfer,
182 buffer: ScatterGatherBuffer,
183 ) -> Result<()> {
184 let transfer_buffer = self.get_transfer_buffer(&buffer, device)?;
185 let usb_transfer = device.build_interrupt_transfer(self.ep_addr(), transfer_buffer)?;
186 self.do_handle_transfer(device, xhci_transfer, usb_transfer, buffer)
187 }
188
189 fn handle_isochronous_transfer(
190 &self,
191 device: &mut BackendDeviceType,
192 xhci_transfer: XhciTransfer,
193 buffer: ScatterGatherBuffer,
194 ) -> Result<()> {
195 if self.direction == EndpointDirection::HostToDevice {
197 return xhci_transfer
198 .on_transfer_complete(&TransferStatus::Error, 0)
199 .map_err(Error::TransferComplete);
200 }
201
202 let max_payload = xhci_transfer
203 .get_max_payload()
204 .map_err(Error::TransferGetMaxPayload)?;
205 let transfer_buffer = self.get_transfer_buffer(&buffer, device)?;
206 let usb_transfer =
207 device.build_isochronous_transfer(self.ep_addr(), transfer_buffer, max_payload)?;
208 self.do_handle_transfer(device, xhci_transfer, usb_transfer, buffer)
209 }
210
211 fn do_handle_transfer(
212 &self,
213 device: &mut BackendDeviceType,
214 xhci_transfer: XhciTransfer,
215 mut usb_transfer: BackendTransferType,
216 buffer: ScatterGatherBuffer,
217 ) -> Result<()> {
218 let xhci_transfer = Arc::new(xhci_transfer);
219 let tmp_transfer = xhci_transfer.clone();
220 match self.direction {
221 EndpointDirection::HostToDevice => {
222 let _trace = cros_tracing::trace_event!(
223 USB,
224 "Endpoint out transfer",
225 self.ep_addr(),
226 buffer.len()
227 );
228 let callback = move |t: BackendTransferType| {
229 let mut state = xhci_transfer.state().lock();
230 update_transfer_state(&mut state, t.status())?;
231 match *state {
232 XhciTransferState::Cancelled => {
233 debug!("Xhci transfer has been cancelled");
234 drop(state);
235 xhci_transfer
236 .on_transfer_complete(&TransferStatus::Cancelled, 0)
237 .map_err(Error::TransferComplete)
238 }
239 XhciTransferState::Completed => {
240 let status = t.status();
241 let actual_length = t.actual_length();
242 drop(state);
243 xhci_transfer
244 .on_transfer_complete(&status, actual_length as u32)
245 .map_err(Error::TransferComplete)
246 }
247 _ => {
248 error!("xhci trasfer state (host to device) is invalid");
249 Err(Error::BadXhciTransferState)
250 }
251 }
252 };
253 let fail_handle = self.fail_handle.clone();
254 usb_transfer.set_callback(move |t: BackendTransferType| match callback(t) {
255 Ok(_) => {}
256 Err(e) => {
257 error!("bulk transfer callback failed: {:?}", e);
258 fail_handle.fail();
259 }
260 });
261 device.submit_transfer(
262 self.fail_handle.clone(),
263 &self.job_queue,
264 tmp_transfer,
265 usb_transfer,
266 )?;
267 }
268 EndpointDirection::DeviceToHost => {
269 let _trace = cros_tracing::trace_event!(
270 USB,
271 "Endpoint in transfer",
272 self.ep_addr(),
273 buffer.len()
274 );
275 let _addr = self.ep_addr();
276 let callback = move |t: BackendTransferType| {
277 let mut state = xhci_transfer.state().lock();
278 update_transfer_state(&mut state, t.status())?;
279 match *state {
280 XhciTransferState::Cancelled => {
281 debug!("Xhci transfer has been cancelled");
282 drop(state);
283 xhci_transfer
284 .on_transfer_complete(&TransferStatus::Cancelled, 0)
285 .map_err(Error::TransferComplete)
286 }
287 XhciTransferState::Completed => {
288 let status = t.status();
289 let actual_length = t.actual_length();
290 let copied_length = match t.buffer() {
291 TransferBuffer::Vector(v) => {
292 buffer.write(v.as_slice()).map_err(Error::WriteBuffer)?
293 }
294 TransferBuffer::Dma(buf) => {
295 if let Some(buf) = buf.upgrade() {
296 buffer
297 .write(buf.lock().as_slice())
298 .map_err(Error::WriteBuffer)?
299 } else {
300 return Err(Error::GetDmaBuffer);
301 }
302 }
303 };
304 let actual_length = cmp::min(actual_length, copied_length);
305 drop(state);
306 xhci_transfer
307 .on_transfer_complete(&status, actual_length as u32)
308 .map_err(Error::TransferComplete)
309 }
310 _ => {
311 error!("xhci trasfer state (device to host) is invalid");
314 Err(Error::BadXhciTransferState)
315 }
316 }
317 };
318 let fail_handle = self.fail_handle.clone();
319
320 usb_transfer.set_callback(move |t: BackendTransferType| match callback(t) {
321 Ok(_) => {}
322 Err(e) => {
323 error!("bulk transfer callback {:?}", e);
324 fail_handle.fail();
325 }
326 });
327
328 device.submit_transfer(
329 self.fail_handle.clone(),
330 &self.job_queue,
331 tmp_transfer,
332 usb_transfer,
333 )?;
334 }
335 }
336 Ok(())
337 }
338}