• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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