1 // Copyright 2019 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::cmp; 6 use std::sync::Arc; 7 8 use base::debug; 9 use base::error; 10 use usb_util::EndpointDirection; 11 use usb_util::EndpointType; 12 use usb_util::TransferBuffer; 13 use usb_util::TransferStatus; 14 use usb_util::ENDPOINT_DIRECTION_OFFSET; 15 16 use crate::usb::backend::device::BackendDevice; 17 use crate::usb::backend::device::BackendDeviceType; 18 use crate::usb::backend::error::Error; 19 use crate::usb::backend::error::Result; 20 use crate::usb::backend::transfer::BackendTransfer; 21 use crate::usb::backend::transfer::BackendTransferType; 22 use crate::usb::backend::utils::update_transfer_state; 23 use crate::usb::xhci::scatter_gather_buffer::ScatterGatherBuffer; 24 use crate::usb::xhci::xhci_transfer::TransferDirection; 25 use crate::usb::xhci::xhci_transfer::XhciTransfer; 26 use crate::usb::xhci::xhci_transfer::XhciTransferState; 27 use crate::usb::xhci::xhci_transfer::XhciTransferType; 28 use crate::utils::AsyncJobQueue; 29 use crate::utils::FailHandle; 30 31 #[derive(Copy, Clone, PartialEq, Eq)] 32 pub enum ControlEndpointState { 33 /// Control endpoint should receive setup stage next. 34 SetupStage, 35 /// Control endpoint should receive data stage next. 36 DataStage, 37 /// Control endpoint should receive status stage next. 38 StatusStage, 39 } 40 41 /// Isochronous, Bulk or Interrupt endpoint. 42 pub 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 50 impl UsbEndpoint { 51 /// Create new endpoint. This function will panic if endpoint type is control. new( fail_handle: Arc<dyn FailHandle>, job_queue: Arc<AsyncJobQueue>, endpoint_number: u8, direction: EndpointDirection, ty: EndpointType, ) -> UsbEndpoint52 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 ep_addr(&self) -> u869 fn ep_addr(&self) -> u8 { 70 self.endpoint_number | ((self.direction as u8) << ENDPOINT_DIRECTION_OFFSET) 71 } 72 73 /// Returns true is this endpoint matches number and direction. match_ep(&self, endpoint_number: u8, dir: TransferDirection) -> bool74 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 /// Handle a xhci transfer. handle_transfer( &self, device: &mut BackendDeviceType, transfer: XhciTransfer, ) -> Result<()>83 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 get_transfer_buffer( &self, buffer: &ScatterGatherBuffer, device: &mut BackendDeviceType, ) -> Result<TransferBuffer>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 // Read data from ScatterGatherBuffer to a continuous memory. 131 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 handle_bulk_transfer( &self, device: &mut BackendDeviceType, xhci_transfer: XhciTransfer, buffer: ScatterGatherBuffer, ) -> Result<()>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 handle_interrupt_transfer( &self, device: &mut BackendDeviceType, xhci_transfer: XhciTransfer, buffer: ScatterGatherBuffer, ) -> Result<()>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 do_handle_transfer( &self, device: &mut BackendDeviceType, xhci_transfer: XhciTransfer, mut usb_transfer: BackendTransferType, buffer: ScatterGatherBuffer, ) -> Result<()>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 // update state is already invoked. This match should not be in any 276 // other state. 277 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 } 303