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