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::fs::File; 6 use std::sync::Arc; 7 8 use super::error::*; 9 use super::host_device::HostDevice; 10 use crate::usb::xhci::usb_hub::UsbHub; 11 use crate::usb::xhci::xhci_backend_device_provider::XhciBackendDeviceProvider; 12 use crate::utils::AsyncJobQueue; 13 use crate::utils::{EventHandler, EventLoop, FailHandle}; 14 15 use anyhow::Context; 16 use base::{error, AsRawDescriptor, Descriptor, RawDescriptor, Tube, WatchingEvents}; 17 use std::collections::HashMap; 18 use std::mem; 19 use std::time::Duration; 20 use sync::Mutex; 21 use usb_util::Device; 22 use vm_control::{ 23 UsbControlAttachedDevice, UsbControlCommand, UsbControlResult, USB_CONTROL_MAX_PORTS, 24 }; 25 26 const SOCKET_TIMEOUT_MS: u64 = 2000; 27 28 /// Host backend device provider is a xhci backend device provider that would provide pass through 29 /// devices. 30 pub enum HostBackendDeviceProvider { 31 // The provider is created but not yet started. 32 Created { control_tube: Mutex<Tube> }, 33 // The provider is started on an event loop. 34 Started { inner: Arc<ProviderInner> }, 35 // The provider has failed. 36 Failed, 37 } 38 39 impl HostBackendDeviceProvider { new() -> Result<(Tube, HostBackendDeviceProvider)>40 pub fn new() -> Result<(Tube, HostBackendDeviceProvider)> { 41 let (child_tube, control_tube) = Tube::pair().map_err(Error::CreateControlTube)?; 42 control_tube 43 .set_send_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS))) 44 .map_err(Error::SetupControlTube)?; 45 control_tube 46 .set_recv_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS))) 47 .map_err(Error::SetupControlTube)?; 48 49 let provider = HostBackendDeviceProvider::Created { 50 control_tube: Mutex::new(child_tube), 51 }; 52 Ok((control_tube, provider)) 53 } 54 start_helper( &mut self, fail_handle: Arc<dyn FailHandle>, event_loop: Arc<EventLoop>, hub: Arc<UsbHub>, ) -> Result<()>55 fn start_helper( 56 &mut self, 57 fail_handle: Arc<dyn FailHandle>, 58 event_loop: Arc<EventLoop>, 59 hub: Arc<UsbHub>, 60 ) -> Result<()> { 61 match mem::replace(self, HostBackendDeviceProvider::Failed) { 62 HostBackendDeviceProvider::Created { control_tube } => { 63 let job_queue = 64 AsyncJobQueue::init(&event_loop).map_err(Error::StartAsyncJobQueue)?; 65 let inner = Arc::new(ProviderInner::new( 66 fail_handle, 67 job_queue, 68 event_loop.clone(), 69 control_tube, 70 hub, 71 )); 72 let handler: Arc<dyn EventHandler> = inner.clone(); 73 event_loop 74 .add_event( 75 &*inner.control_tube.lock(), 76 WatchingEvents::empty().set_read(), 77 Arc::downgrade(&handler), 78 ) 79 .map_err(Error::AddToEventLoop)?; 80 *self = HostBackendDeviceProvider::Started { inner }; 81 Ok(()) 82 } 83 HostBackendDeviceProvider::Started { .. } => { 84 error!("Host backend provider has already started"); 85 Err(Error::BadBackendProviderState) 86 } 87 HostBackendDeviceProvider::Failed => { 88 error!("Host backend provider has already failed"); 89 Err(Error::BadBackendProviderState) 90 } 91 } 92 } 93 } 94 95 impl XhciBackendDeviceProvider for HostBackendDeviceProvider { start( &mut self, fail_handle: Arc<dyn FailHandle>, event_loop: Arc<EventLoop>, hub: Arc<UsbHub>, ) -> Result<()>96 fn start( 97 &mut self, 98 fail_handle: Arc<dyn FailHandle>, 99 event_loop: Arc<EventLoop>, 100 hub: Arc<UsbHub>, 101 ) -> Result<()> { 102 self.start_helper(fail_handle, event_loop, hub) 103 } 104 keep_rds(&self) -> Vec<RawDescriptor>105 fn keep_rds(&self) -> Vec<RawDescriptor> { 106 match self { 107 HostBackendDeviceProvider::Created { control_tube } => { 108 vec![control_tube.lock().as_raw_descriptor()] 109 } 110 _ => { 111 error!( 112 "Trying to get keepfds when HostBackendDeviceProvider is not in created state" 113 ); 114 vec![] 115 } 116 } 117 } 118 } 119 120 /// ProviderInner listens to control socket. 121 pub struct ProviderInner { 122 fail_handle: Arc<dyn FailHandle>, 123 job_queue: Arc<AsyncJobQueue>, 124 event_loop: Arc<EventLoop>, 125 control_tube: Mutex<Tube>, 126 usb_hub: Arc<UsbHub>, 127 128 // Map of USB hub port number to per-device context. 129 devices: Mutex<HashMap<u8, HostDeviceContext>>, 130 } 131 132 struct HostDeviceContext { 133 event_handler: Arc<dyn EventHandler>, 134 device: Arc<Mutex<Device>>, 135 } 136 137 impl ProviderInner { new( fail_handle: Arc<dyn FailHandle>, job_queue: Arc<AsyncJobQueue>, event_loop: Arc<EventLoop>, control_tube: Mutex<Tube>, usb_hub: Arc<UsbHub>, ) -> ProviderInner138 fn new( 139 fail_handle: Arc<dyn FailHandle>, 140 job_queue: Arc<AsyncJobQueue>, 141 event_loop: Arc<EventLoop>, 142 control_tube: Mutex<Tube>, 143 usb_hub: Arc<UsbHub>, 144 ) -> ProviderInner { 145 ProviderInner { 146 fail_handle, 147 job_queue, 148 event_loop, 149 control_tube, 150 usb_hub, 151 devices: Mutex::new(HashMap::new()), 152 } 153 } 154 155 /// Open a usbdevfs file to create a host USB device object. 156 /// `fd` should be an open file descriptor for a file in `/dev/bus/usb`. handle_attach_device(&self, usb_file: File) -> UsbControlResult157 fn handle_attach_device(&self, usb_file: File) -> UsbControlResult { 158 let device = match Device::new(usb_file) { 159 Ok(d) => d, 160 Err(e) => { 161 error!("could not construct USB device from fd: {}", e); 162 return UsbControlResult::NoSuchDevice; 163 } 164 }; 165 166 let device_descriptor = Descriptor(device.as_raw_descriptor()); 167 168 let arc_mutex_device = Arc::new(Mutex::new(device)); 169 170 let event_handler: Arc<dyn EventHandler> = Arc::new(UsbUtilEventHandler { 171 device: arc_mutex_device.clone(), 172 }); 173 174 if let Err(e) = self.event_loop.add_event( 175 &device_descriptor, 176 WatchingEvents::empty().set_read().set_write(), 177 Arc::downgrade(&event_handler), 178 ) { 179 error!("failed to add USB device fd to event handler: {}", e); 180 return UsbControlResult::FailedToOpenDevice; 181 } 182 183 let device_ctx = HostDeviceContext { 184 event_handler, 185 device: arc_mutex_device.clone(), 186 }; 187 188 // Resetting the device is used to make sure it is in a known state, but it may 189 // still function if the reset fails. 190 if let Err(e) = arc_mutex_device.lock().reset() { 191 error!("failed to reset device after attach: {:?}", e); 192 } 193 194 let host_device = match HostDevice::new( 195 self.fail_handle.clone(), 196 self.job_queue.clone(), 197 arc_mutex_device, 198 ) { 199 Ok(host_device) => Box::new(host_device), 200 Err(e) => { 201 error!("failed to initialize HostDevice: {}", e); 202 return UsbControlResult::FailedToInitHostDevice; 203 } 204 }; 205 206 let port = self.usb_hub.connect_backend(host_device); 207 match port { 208 Ok(port) => { 209 self.devices.lock().insert(port, device_ctx); 210 UsbControlResult::Ok { port } 211 } 212 Err(e) => { 213 error!("failed to connect device to hub: {}", e); 214 UsbControlResult::NoAvailablePort 215 } 216 } 217 } 218 handle_detach_device(&self, port: u8) -> UsbControlResult219 fn handle_detach_device(&self, port: u8) -> UsbControlResult { 220 match self.usb_hub.disconnect_port(port) { 221 Ok(()) => { 222 if let Some(device_ctx) = self.devices.lock().remove(&port) { 223 let _ = device_ctx.event_handler.on_event(); 224 let device = device_ctx.device.lock(); 225 let fd = device.fd(); 226 227 if let Err(e) = self.event_loop.remove_event_for_fd(&*fd) { 228 error!( 229 "failed to remove poll change handler from event loop: {}", 230 e 231 ); 232 } 233 } 234 UsbControlResult::Ok { port } 235 } 236 Err(e) => { 237 error!("failed to disconnect device from port {}: {}", port, e); 238 UsbControlResult::NoSuchDevice 239 } 240 } 241 } 242 handle_list_devices(&self, ports: [u8; USB_CONTROL_MAX_PORTS]) -> UsbControlResult243 fn handle_list_devices(&self, ports: [u8; USB_CONTROL_MAX_PORTS]) -> UsbControlResult { 244 let mut devices: [UsbControlAttachedDevice; USB_CONTROL_MAX_PORTS] = Default::default(); 245 for (result_index, &port_id) in ports.iter().enumerate() { 246 match self.usb_hub.get_port(port_id).and_then(|p| { 247 p.get_backend_device() 248 .as_ref() 249 .map(|d| (d.get_vid(), d.get_pid())) 250 }) { 251 Some((vendor_id, product_id)) => { 252 devices[result_index] = UsbControlAttachedDevice { 253 port: port_id, 254 vendor_id, 255 product_id, 256 } 257 } 258 None => continue, 259 } 260 } 261 UsbControlResult::Devices(devices) 262 } 263 on_event_helper(&self) -> Result<()>264 fn on_event_helper(&self) -> Result<()> { 265 let tube = self.control_tube.lock(); 266 let cmd = tube.recv().map_err(Error::ReadControlTube)?; 267 let result = match cmd { 268 UsbControlCommand::AttachDevice { file, .. } => self.handle_attach_device(file), 269 UsbControlCommand::DetachDevice { port } => self.handle_detach_device(port), 270 UsbControlCommand::ListDevice { ports } => self.handle_list_devices(ports), 271 }; 272 tube.send(&result).map_err(Error::WriteControlTube)?; 273 Ok(()) 274 } 275 } 276 277 impl EventHandler for ProviderInner { on_event(&self) -> anyhow::Result<()>278 fn on_event(&self) -> anyhow::Result<()> { 279 self.on_event_helper() 280 .context("host backend device provider failed") 281 } 282 } 283 284 struct UsbUtilEventHandler { 285 device: Arc<Mutex<Device>>, 286 } 287 288 impl EventHandler for UsbUtilEventHandler { on_event(&self) -> anyhow::Result<()>289 fn on_event(&self) -> anyhow::Result<()> { 290 self.device 291 .lock() 292 .poll_transfers() 293 .context("UsbUtilEventHandler poll_transfers failed") 294 } 295 } 296