Path: blob/main/devices/src/usb/backend/host_backend/host_device.rs
5394 views
// Copyright 2019 The ChromiumOS Authors1// Use of this source code is governed by a BSD-style license that can be2// found in the LICENSE file.34use std::collections::HashMap;5use std::mem;6use std::sync::Arc;7use std::sync::RwLock;89use base::debug;10use base::error;11use base::AsRawDescriptor;12use base::RawDescriptor;13use sync::Mutex;14use usb_util::ConfigDescriptorTree;15use usb_util::DescriptorHeader;16use usb_util::Device;17use usb_util::DeviceDescriptorTree;18use usb_util::DeviceSpeed;19use usb_util::InterfaceDescriptor;20use usb_util::Transfer;21use usb_util::TransferBuffer;22use usb_util::TransferHandle;23use usb_util::TransferStatus;24use usb_util::UsbRequestSetup;25use zerocopy::IntoBytes;2627use crate::usb::backend::device::BackendDevice;28use crate::usb::backend::device::DeviceState;29use crate::usb::backend::endpoint::ControlEndpointState;30use crate::usb::backend::endpoint::UsbEndpoint;31use crate::usb::backend::error::Error;32use crate::usb::backend::error::Result;33use crate::usb::backend::transfer::BackendTransfer;34use crate::usb::backend::transfer::BackendTransferHandle;35use crate::usb::backend::transfer::BackendTransferType;36use crate::usb::backend::transfer::ControlTransferState;37use crate::usb::backend::transfer::GenericTransferHandle;38use crate::usb::xhci::scatter_gather_buffer::ScatterGatherBuffer;39use crate::usb::xhci::xhci_backend_device::BackendType;40use crate::usb::xhci::xhci_backend_device::UsbDeviceAddress;41use crate::usb::xhci::xhci_backend_device::XhciBackendDevice;42use crate::utils::EventLoop;4344/// Host device is a device connected to host.45pub struct HostDevice {46pub device: Arc<Mutex<Device>>,47alt_settings: HashMap<u8, u8>,48claimed_interfaces: Vec<u8>,49state: Arc<RwLock<DeviceState>>,50control_transfer_state: Arc<RwLock<ControlTransferState>>,51}5253impl HostDevice {54/// Create a new host device.55pub fn new(device: Arc<Mutex<Device>>, state: DeviceState) -> Result<HostDevice> {56let control_transfer_state = ControlTransferState {57ctl_ep_state: ControlEndpointState::SetupStage,58control_request_setup: UsbRequestSetup::new(0, 0, 0, 0, 0),59executed: false,60};61let mut host_device = HostDevice {62device,63alt_settings: HashMap::new(),64claimed_interfaces: vec![],65state: Arc::new(RwLock::new(state)),66control_transfer_state: Arc::new(RwLock::new(control_transfer_state)),67};6869let config_descriptor = host_device.get_active_config_descriptor()?;70host_device.claim_interfaces(&config_descriptor);7172Ok(host_device)73}7475// Execute a Get Descriptor control request with type Configuration.76// This function is used to return a filtered version of the host device's configuration77// descriptor that only includes the interfaces in `self.claimed_interfaces`.78pub fn get_config_descriptor_filtered(79&mut self,80buffer: &ScatterGatherBuffer,81descriptor_index: u8,82) -> Result<(TransferStatus, u32)> {83let _trace = cros_tracing::trace_event!(84USB,85"host_device get_config_descriptor_filtered",86descriptor_index87);8889let config_descriptor = self.get_config_descriptor_by_index(descriptor_index)?;9091let device_descriptor = self.get_device_descriptor_tree()?;92let config_start = config_descriptor.offset();93let config_end = config_start + config_descriptor.wTotalLength as usize;94let mut descriptor_data = device_descriptor.raw()[config_start..config_end].to_vec();9596if config_descriptor.bConfigurationValue == self.get_active_configuration()? {97for i in 0..config_descriptor.bNumInterfaces {98if !self.claimed_interfaces.contains(&i) {99// Rewrite descriptors for unclaimed interfaces to vendor-specific class.100// This prevents them from being recognized by the guest drivers.101let alt_setting = self.alt_settings.get(&i).unwrap_or(&0);102let interface = config_descriptor103.get_interface_descriptor(i, *alt_setting)104.ok_or(Error::GetInterfaceDescriptor(i, *alt_setting))?;105let mut interface_data: InterfaceDescriptor = **interface;106interface_data.bInterfaceClass = 0xFF;107interface_data.bInterfaceSubClass = 0xFF;108interface_data.bInterfaceProtocol = 0xFF;109110let interface_start =111interface.offset() + mem::size_of::<DescriptorHeader>() - config_start;112let interface_end = interface_start + mem::size_of::<InterfaceDescriptor>();113descriptor_data[interface_start..interface_end]114.copy_from_slice(interface_data.as_bytes());115}116}117}118119let bytes_transferred = buffer.write(&descriptor_data).map_err(Error::WriteBuffer)?;120Ok((TransferStatus::Completed, bytes_transferred as u32))121}122123pub fn set_interface(&mut self, interface: u8, alt_setting: u8) -> Result<TransferStatus> {124let _trace = cros_tracing::trace_event!(USB, "host_device set_interface");125// It's a standard, set_interface, interface request.126self.device127.lock()128.set_interface_alt_setting(interface, alt_setting)129.map_err(Error::SetInterfaceAltSetting)?;130self.alt_settings.insert(interface, alt_setting);131let config = self.get_active_configuration()?;132let config_descriptor = self.get_config_descriptor(config)?;133self.create_endpoints(&config_descriptor)?;134Ok(TransferStatus::Completed)135}136137pub fn claim_interfaces(&mut self, config_descriptor: &ConfigDescriptorTree) {138for i in 0..config_descriptor.num_interfaces() {139match self.device.lock().claim_interface(i) {140Ok(()) => {141debug!("usb: claimed interface {}", i);142self.claimed_interfaces.push(i);143}144Err(e) => {145error!("unable to claim interface {}: {:?}", i, e);146}147}148}149}150151pub fn release_interfaces(&mut self) {152let device_locked = self.device.lock();153for i in &self.claimed_interfaces {154if let Err(e) = device_locked.release_interface(*i) {155error!("could not release interface: {:?}", e);156}157}158self.claimed_interfaces = Vec::new();159}160}161162impl Drop for HostDevice {163fn drop(&mut self) {164self.release_interfaces();165}166}167168impl AsRawDescriptor for HostDevice {169fn as_raw_descriptor(&self) -> RawDescriptor {170self.device.lock().as_raw_descriptor()171}172}173174impl GenericTransferHandle for TransferHandle {175fn cancel(&self) -> Result<()> {176TransferHandle::cancel(self).map_err(Error::TransferHandle)177}178}179180impl BackendDevice for HostDevice {181fn submit_backend_transfer(182&mut self,183transfer: BackendTransferType,184) -> Result<BackendTransferHandle> {185match transfer {186BackendTransferType::HostDevice(transfer) => self187.device188.lock()189.submit_transfer(transfer)190.map_err(Error::CreateTransfer)191.map(BackendTransferHandle::new),192_ => Err(Error::MalformedBackendTransfer),193}194}195196fn detach_event_handler(&self, event_loop: &Arc<EventLoop>) -> Result<()> {197event_loop198.remove_event_for_descriptor(self)199.map_err(Error::RemoveFromEventLoop)200}201202fn request_transfer_buffer(&mut self, size: usize) -> TransferBuffer {203match self.device.lock().reserve_dma_buffer(size) {204Ok(dmabuf) => TransferBuffer::Dma(dmabuf),205Err(_) => TransferBuffer::Vector(vec![0u8; size]),206}207}208209fn build_bulk_transfer(210&mut self,211ep_addr: u8,212transfer_buffer: TransferBuffer,213stream_id: Option<u16>,214) -> Result<BackendTransferType> {215Ok(BackendTransferType::HostDevice(216Transfer::new_bulk(ep_addr, transfer_buffer, stream_id)217.map_err(Error::CreateTransfer)?,218))219}220221fn build_interrupt_transfer(222&mut self,223ep_addr: u8,224transfer_buffer: TransferBuffer,225) -> Result<BackendTransferType> {226Ok(BackendTransferType::HostDevice(227Transfer::new_interrupt(ep_addr, transfer_buffer).map_err(Error::CreateTransfer)?,228))229}230231fn get_control_transfer_state(&mut self) -> Arc<RwLock<ControlTransferState>> {232self.control_transfer_state.clone()233}234235fn get_device_state(&mut self) -> Arc<RwLock<DeviceState>> {236self.state.clone()237}238239fn get_active_config_descriptor(&mut self) -> Result<ConfigDescriptorTree> {240let cur_config = self.get_active_configuration()?;241self.get_config_descriptor(cur_config)242}243244fn get_config_descriptor(&mut self, config: u8) -> Result<ConfigDescriptorTree> {245self.device246.lock()247.get_config_descriptor(config)248.map_err(Error::GetActiveConfig)249}250251fn get_config_descriptor_by_index(&mut self, config_index: u8) -> Result<ConfigDescriptorTree> {252self.device253.lock()254.get_config_descriptor_by_index(config_index)255.map_err(Error::GetConfigDescriptor)256}257258fn get_device_descriptor_tree(&mut self) -> Result<DeviceDescriptorTree> {259Ok(self.device.lock().get_device_descriptor_tree().clone())260}261262fn get_active_configuration(&mut self) -> Result<u8> {263self.device264.lock()265.get_active_configuration()266.map_err(Error::GetActiveConfig)267}268269fn set_active_configuration(&mut self, config: u8) -> Result<()> {270self.device271.lock()272.set_active_configuration(config)273.map_err(Error::SetActiveConfig)274}275276fn clear_feature(&mut self, value: u16, index: u16) -> Result<TransferStatus> {277// It's a standard, clear_feature, endpoint request.278const STD_FEATURE_ENDPOINT_HALT: u16 = 0;279if value == STD_FEATURE_ENDPOINT_HALT {280self.device281.lock()282.clear_halt(index as u8)283.map_err(Error::ClearHalt)?;284}285Ok(TransferStatus::Completed)286}287288fn create_endpoints(&mut self, config_descriptor: &ConfigDescriptorTree) -> Result<()> {289let mut endpoints = Vec::new();290let device_state = self.get_device_state();291for i in &self.claimed_interfaces {292let alt_setting = self.alt_settings.get(i).unwrap_or(&0);293let interface = config_descriptor294.get_interface_descriptor(*i, *alt_setting)295.ok_or(Error::GetInterfaceDescriptor(*i, *alt_setting))?;296for ep_idx in 0..interface.bNumEndpoints {297let ep_dp = interface298.get_endpoint_descriptor(ep_idx)299.ok_or(Error::GetEndpointDescriptor(ep_idx))?;300let ep_num = ep_dp.get_endpoint_number();301if ep_num == 0 {302continue;303}304let direction = ep_dp.get_direction();305let ty = ep_dp.get_endpoint_type().ok_or(Error::GetEndpointType)?;306endpoints.push(UsbEndpoint::new(307device_state.read().unwrap().fail_handle.clone(),308device_state.read().unwrap().job_queue.clone(),309ep_num,310direction,311ty,312));313}314}315device_state.write().unwrap().endpoints = endpoints;316Ok(())317}318}319320impl XhciBackendDevice for HostDevice {321fn get_backend_type(&self) -> BackendType {322let d = match self.device.lock().get_device_descriptor() {323Ok(d) => d,324Err(_) => return BackendType::Usb2,325};326327// See definition of bcdUsb.328const USB3_MASK: u16 = 0x0300;329match d.bcdUSB & USB3_MASK {330USB3_MASK => BackendType::Usb3,331_ => BackendType::Usb2,332}333}334335fn get_vid(&self) -> u16 {336match self.device.lock().get_device_descriptor() {337Ok(d) => d.idVendor,338Err(e) => {339error!("cannot get device descriptor: {:?}", e);3400341}342}343}344345fn get_pid(&self) -> u16 {346match self.device.lock().get_device_descriptor() {347Ok(d) => d.idProduct,348Err(e) => {349error!("cannot get device descriptor: {:?}", e);3500351}352}353}354355fn set_address(&mut self, _address: UsbDeviceAddress) {356// It's a standard, set_address, device request. We do nothing here. As described in XHCI357// spec. See set address command ring trb.358debug!(359"usb set address control transfer is received with address: {}",360_address361);362}363364fn reset(&mut self) -> Result<()> {365self.device.lock().reset().map_err(Error::Reset)366}367368fn get_speed(&self) -> Option<DeviceSpeed> {369self.device.lock().get_speed().unwrap_or(None)370}371372fn alloc_streams(&self, ep: u8, num_streams: u16) -> Result<()> {373self.device374.lock()375.alloc_streams(ep, num_streams)376.map_err(Error::AllocStreams)377}378379fn free_streams(&self, ep: u8) -> Result<()> {380self.device381.lock()382.free_streams(ep)383.map_err(Error::FreeStreams)384}385386fn stop(&mut self) {387// NOOP, nothing to do388}389}390391impl BackendTransfer for Transfer {392fn status(&self) -> TransferStatus {393Transfer::status(self)394}395396fn actual_length(&self) -> usize {397Transfer::actual_length(self)398}399400fn buffer(&self) -> &TransferBuffer {401&self.buffer402}403404fn set_callback<C: 'static + Fn(BackendTransferType) + Send + Sync>(&mut self, cb: C) {405Transfer::set_callback(self, move |t| cb(BackendTransferType::HostDevice(t)));406}407}408409410