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