1 // Copyright 2019 The Chromium OS Authors. All rights reserved. 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 super::error::*; 9 use super::utils::{submit_transfer, update_transfer_state}; 10 use crate::usb::xhci::scatter_gather_buffer::ScatterGatherBuffer; 11 use crate::usb::xhci::xhci_transfer::{ 12 TransferDirection, XhciTransfer, XhciTransferState, XhciTransferType, 13 }; 14 use crate::utils::AsyncJobQueue; 15 use crate::utils::FailHandle; 16 use base::error; 17 use sync::Mutex; 18 use usb_util::{ 19 Device, EndpointDirection, EndpointType, Transfer, TransferStatus, ENDPOINT_DIRECTION_OFFSET, 20 }; 21 22 /// Isochronous, Bulk or Interrupt endpoint. 23 pub struct UsbEndpoint { 24 fail_handle: Arc<dyn FailHandle>, 25 job_queue: Arc<AsyncJobQueue>, 26 device: Arc<Mutex<Device>>, 27 endpoint_number: u8, 28 direction: EndpointDirection, 29 ty: EndpointType, 30 } 31 32 impl UsbEndpoint { 33 /// Create new endpoint. This function will panic if endpoint type is control. new( fail_handle: Arc<dyn FailHandle>, job_queue: Arc<AsyncJobQueue>, device: Arc<Mutex<Device>>, endpoint_number: u8, direction: EndpointDirection, ty: EndpointType, ) -> UsbEndpoint34 pub fn new( 35 fail_handle: Arc<dyn FailHandle>, 36 job_queue: Arc<AsyncJobQueue>, 37 device: Arc<Mutex<Device>>, 38 endpoint_number: u8, 39 direction: EndpointDirection, 40 ty: EndpointType, 41 ) -> UsbEndpoint { 42 assert!(ty != EndpointType::Control); 43 UsbEndpoint { 44 fail_handle, 45 job_queue, 46 device, 47 endpoint_number, 48 direction, 49 ty, 50 } 51 } 52 ep_addr(&self) -> u853 fn ep_addr(&self) -> u8 { 54 self.endpoint_number | ((self.direction as u8) << ENDPOINT_DIRECTION_OFFSET) 55 } 56 57 /// Returns true is this endpoint matches number and direction. match_ep(&self, endpoint_number: u8, dir: TransferDirection) -> bool58 pub fn match_ep(&self, endpoint_number: u8, dir: TransferDirection) -> bool { 59 let self_dir = match self.direction { 60 EndpointDirection::HostToDevice => TransferDirection::Out, 61 EndpointDirection::DeviceToHost => TransferDirection::In, 62 }; 63 self.endpoint_number == endpoint_number && self_dir == dir 64 } 65 66 /// Handle a xhci transfer. handle_transfer(&self, transfer: XhciTransfer) -> Result<()>67 pub fn handle_transfer(&self, transfer: XhciTransfer) -> Result<()> { 68 let buffer = match transfer 69 .get_transfer_type() 70 .map_err(Error::GetXhciTransferType)? 71 { 72 XhciTransferType::Normal(buffer) => buffer, 73 XhciTransferType::Noop => { 74 return transfer 75 .on_transfer_complete(&TransferStatus::Completed, 0) 76 .map_err(Error::TransferComplete); 77 } 78 _ => { 79 error!("unhandled xhci transfer type by usb endpoint"); 80 return transfer 81 .on_transfer_complete(&TransferStatus::Error, 0) 82 .map_err(Error::TransferComplete); 83 } 84 }; 85 86 match self.ty { 87 EndpointType::Bulk => { 88 self.handle_bulk_transfer(transfer, buffer)?; 89 } 90 EndpointType::Interrupt => { 91 self.handle_interrupt_transfer(transfer, buffer)?; 92 } 93 _ => { 94 return transfer 95 .on_transfer_complete(&TransferStatus::Error, 0) 96 .map_err(Error::TransferComplete); 97 } 98 } 99 Ok(()) 100 } 101 get_transfer_buffer(&self, buffer: &ScatterGatherBuffer) -> Result<Vec<u8>>102 fn get_transfer_buffer(&self, buffer: &ScatterGatherBuffer) -> Result<Vec<u8>> { 103 let mut v = vec![0u8; buffer.len().map_err(Error::BufferLen)?]; 104 if self.direction == EndpointDirection::HostToDevice { 105 // Read data from ScatterGatherBuffer to a continuous memory. 106 buffer.read(v.as_mut_slice()).map_err(Error::ReadBuffer)?; 107 } 108 Ok(v) 109 } 110 handle_bulk_transfer( &self, xhci_transfer: XhciTransfer, buffer: ScatterGatherBuffer, ) -> Result<()>111 fn handle_bulk_transfer( 112 &self, 113 xhci_transfer: XhciTransfer, 114 buffer: ScatterGatherBuffer, 115 ) -> Result<()> { 116 let transfer_buffer = self.get_transfer_buffer(&buffer)?; 117 let usb_transfer = 118 Transfer::new_bulk(self.ep_addr(), transfer_buffer).map_err(Error::CreateTransfer)?; 119 self.do_handle_transfer(xhci_transfer, usb_transfer, buffer) 120 } 121 handle_interrupt_transfer( &self, xhci_transfer: XhciTransfer, buffer: ScatterGatherBuffer, ) -> Result<()>122 fn handle_interrupt_transfer( 123 &self, 124 xhci_transfer: XhciTransfer, 125 buffer: ScatterGatherBuffer, 126 ) -> Result<()> { 127 let transfer_buffer = self.get_transfer_buffer(&buffer)?; 128 let usb_transfer = Transfer::new_interrupt(self.ep_addr(), transfer_buffer) 129 .map_err(Error::CreateTransfer)?; 130 self.do_handle_transfer(xhci_transfer, usb_transfer, buffer) 131 } 132 do_handle_transfer( &self, xhci_transfer: XhciTransfer, mut usb_transfer: Transfer, buffer: ScatterGatherBuffer, ) -> Result<()>133 fn do_handle_transfer( 134 &self, 135 xhci_transfer: XhciTransfer, 136 mut usb_transfer: Transfer, 137 buffer: ScatterGatherBuffer, 138 ) -> Result<()> { 139 let xhci_transfer = Arc::new(xhci_transfer); 140 let tmp_transfer = xhci_transfer.clone(); 141 match self.direction { 142 EndpointDirection::HostToDevice => { 143 usb_debug!( 144 "out transfer ep_addr {:#x}, buffer len {:?}", 145 self.ep_addr(), 146 buffer.len(), 147 ); 148 let callback = move |t: Transfer| { 149 usb_debug!("out transfer callback"); 150 update_transfer_state(&xhci_transfer, &t)?; 151 let state = xhci_transfer.state().lock(); 152 match *state { 153 XhciTransferState::Cancelled => { 154 usb_debug!("transfer has been cancelled"); 155 drop(state); 156 xhci_transfer 157 .on_transfer_complete(&TransferStatus::Cancelled, 0) 158 .map_err(Error::TransferComplete) 159 } 160 XhciTransferState::Completed => { 161 let status = t.status(); 162 let actual_length = t.actual_length(); 163 drop(state); 164 xhci_transfer 165 .on_transfer_complete(&status, actual_length as u32) 166 .map_err(Error::TransferComplete) 167 } 168 _ => { 169 error!("xhci trasfer state (host to device) is invalid"); 170 Err(Error::BadXhciTransferState) 171 } 172 } 173 }; 174 let fail_handle = self.fail_handle.clone(); 175 usb_transfer.set_callback(move |t: Transfer| match callback(t) { 176 Ok(_) => {} 177 Err(e) => { 178 error!("bulk transfer callback failed: {:?}", e); 179 fail_handle.fail(); 180 } 181 }); 182 submit_transfer( 183 self.fail_handle.clone(), 184 &self.job_queue, 185 tmp_transfer, 186 &mut self.device.lock(), 187 usb_transfer, 188 )?; 189 } 190 EndpointDirection::DeviceToHost => { 191 usb_debug!( 192 "in transfer ep_addr {:#x}, buffer len {:?}", 193 self.ep_addr(), 194 buffer.len() 195 ); 196 let _addr = self.ep_addr(); 197 let callback = move |t: Transfer| { 198 usb_debug!("ep {:#x} in transfer data {:?}", _addr, t.buffer.as_slice()); 199 update_transfer_state(&xhci_transfer, &t)?; 200 let state = xhci_transfer.state().lock(); 201 match *state { 202 XhciTransferState::Cancelled => { 203 usb_debug!("transfer has been cancelled"); 204 drop(state); 205 xhci_transfer 206 .on_transfer_complete(&TransferStatus::Cancelled, 0) 207 .map_err(Error::TransferComplete) 208 } 209 XhciTransferState::Completed => { 210 let status = t.status(); 211 let actual_length = t.actual_length() as usize; 212 let copied_length = buffer 213 .write(t.buffer.as_slice()) 214 .map_err(Error::WriteBuffer)?; 215 let actual_length = cmp::min(actual_length, copied_length); 216 drop(state); 217 xhci_transfer 218 .on_transfer_complete(&status, actual_length as u32) 219 .map_err(Error::TransferComplete) 220 } 221 _ => { 222 // update state is already invoked. This match should not be in any 223 // other state. 224 error!("xhci trasfer state (device to host) is invalid"); 225 Err(Error::BadXhciTransferState) 226 } 227 } 228 }; 229 let fail_handle = self.fail_handle.clone(); 230 231 usb_transfer.set_callback(move |t: Transfer| match callback(t) { 232 Ok(_) => {} 233 Err(e) => { 234 error!("bulk transfer callback {:?}", e); 235 fail_handle.fail(); 236 } 237 }); 238 239 submit_transfer( 240 self.fail_handle.clone(), 241 &self.job_queue, 242 tmp_transfer, 243 &mut self.device.lock(), 244 usb_transfer, 245 )?; 246 } 247 } 248 Ok(()) 249 } 250 } 251