summary refs log tree commit diff
path: root/devices/src/usb
diff options
context:
space:
mode:
Diffstat (limited to 'devices/src/usb')
-rw-r--r--devices/src/usb/host_backend/context.rs145
-rw-r--r--devices/src/usb/host_backend/error.rs6
-rw-r--r--devices/src/usb/host_backend/host_backend_device_provider.rs281
-rw-r--r--devices/src/usb/host_backend/host_device.rs207
-rw-r--r--devices/src/usb/host_backend/hotplug.rs45
-rw-r--r--devices/src/usb/host_backend/mod.rs2
-rw-r--r--devices/src/usb/host_backend/usb_endpoint.rs88
-rw-r--r--devices/src/usb/host_backend/utils.rs27
-rw-r--r--devices/src/usb/xhci/usb_hub.rs35
-rw-r--r--devices/src/usb/xhci/xhci_backend_device.rs4
-rw-r--r--devices/src/usb/xhci/xhci_transfer.rs9
11 files changed, 289 insertions, 560 deletions
diff --git a/devices/src/usb/host_backend/context.rs b/devices/src/usb/host_backend/context.rs
deleted file mode 100644
index 76ad4a4..0000000
--- a/devices/src/usb/host_backend/context.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2019 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use super::error::*;
-use crate::utils::{EventHandler, EventLoop};
-use std::os::raw::c_short;
-use std::os::unix::io::RawFd;
-use std::sync::{Arc, Weak};
-use sys_util::{error, WatchingEvents};
-#[cfg(feature = "sandboxed-libusb")]
-use usb_util::device_handle::DeviceHandle;
-use usb_util::hotplug::UsbHotplugHandler;
-use usb_util::libusb_context::{LibUsbContext, LibUsbPollfdChangeHandler};
-#[cfg(not(feature = "sandboxed-libusb"))]
-use usb_util::libusb_device::LibUsbDevice;
-use vm_control::MaybeOwnedFd;
-
-/// Context wraps libusb context with libusb event handling.
-pub struct Context {
-    context: LibUsbContext,
-    event_loop: Arc<EventLoop>,
-    event_handler: Arc<dyn EventHandler>,
-}
-
-impl Context {
-    /// Create a new context.
-    pub fn new(event_loop: Arc<EventLoop>) -> Result<Context> {
-        let context = LibUsbContext::new().map_err(Error::CreateLibUsbContext)?;
-        let ctx = Context {
-            context: context.clone(),
-            event_loop,
-            event_handler: Arc::new(LibUsbEventHandler {
-                context: context.clone(),
-            }),
-        };
-        ctx.init_event_handler()?;
-        Ok(ctx)
-    }
-
-    pub fn set_hotplug_handler<H: UsbHotplugHandler + Sized>(&self, handler: H) {
-        if let Err(e) = self.context.set_hotplug_cb(handler) {
-            error!("cannot set hotplug handler: {:?}", e);
-        }
-    }
-
-    fn init_event_handler(&self) -> Result<()> {
-        for pollfd in self.context.get_pollfd_iter() {
-            usb_debug!("event loop add event {} events handler", pollfd.fd);
-            self.event_loop
-                .add_event(
-                    &MaybeOwnedFd::Borrowed(pollfd.fd),
-                    WatchingEvents::new(pollfd.events as u32),
-                    Arc::downgrade(&self.event_handler),
-                )
-                .map_err(Error::AddToEventLoop)?;
-        }
-
-        self.context
-            .set_pollfd_notifiers(Box::new(PollfdChangeHandler {
-                event_loop: self.event_loop.clone(),
-                event_handler: Arc::downgrade(&self.event_handler),
-            }));
-        Ok(())
-    }
-
-    /// Get libusb device with matching bus, addr, vid and pid.
-    #[cfg(not(feature = "sandboxed-libusb"))]
-    pub fn get_device(&self, bus: u8, addr: u8, vid: u16, pid: u16) -> Option<LibUsbDevice> {
-        let device_iter = match self.context.get_device_iter() {
-            Ok(iter) => iter,
-            Err(e) => {
-                error!("could not get libusb device iterator: {:?}", e);
-                return None;
-            }
-        };
-        for device in device_iter {
-            if device.get_bus_number() == bus && device.get_address() == addr {
-                if let Ok(descriptor) = device.get_device_descriptor() {
-                    if descriptor.idProduct == pid && descriptor.idVendor == vid {
-                        return Some(device);
-                    }
-                }
-            }
-        }
-        error!("device not found bus {}, addr {}", bus, addr);
-        None
-    }
-
-    #[cfg(feature = "sandboxed-libusb")]
-    pub fn get_device_handle(&self, fd: std::fs::File) -> Option<DeviceHandle> {
-        match self.context.handle_from_file(fd) {
-            Ok(handle) => Some(handle),
-            Err(e) => {
-                error!("could not build device from fd: {:?}", e);
-                None
-            }
-        }
-    }
-}
-
-struct LibUsbEventHandler {
-    context: LibUsbContext,
-}
-
-impl EventHandler for LibUsbEventHandler {
-    fn on_event(&self) -> std::result::Result<(), ()> {
-        self.context.handle_events_nonblock();
-        Ok(())
-    }
-}
-
-struct PollfdChangeHandler {
-    event_loop: Arc<EventLoop>,
-    event_handler: Weak<dyn EventHandler>,
-}
-
-impl LibUsbPollfdChangeHandler for PollfdChangeHandler {
-    fn add_poll_fd(&self, fd: RawFd, events: c_short) {
-        if let Err(e) = self.event_loop.add_event(
-            &MaybeOwnedFd::Borrowed(fd),
-            WatchingEvents::new(events as u32),
-            self.event_handler.clone(),
-        ) {
-            error!("cannot add event to event loop: {}", e);
-        }
-    }
-
-    fn remove_poll_fd(&self, fd: RawFd) {
-        if let Some(h) = self.event_handler.upgrade() {
-            if let Err(e) = h.on_event() {
-                error!("cannot handle event: {:?}", e);
-            }
-        }
-        if let Err(e) = self
-            .event_loop
-            .remove_event_for_fd(&MaybeOwnedFd::Borrowed(fd))
-        {
-            error!(
-                "failed to remove poll change handler from event loop: {}",
-                e
-            );
-        }
-    }
-}
diff --git a/devices/src/usb/host_backend/error.rs b/devices/src/usb/host_backend/error.rs
index ef097f9..3f1fed4 100644
--- a/devices/src/usb/host_backend/error.rs
+++ b/devices/src/usb/host_backend/error.rs
@@ -7,7 +7,7 @@ use crate::usb::xhci::xhci_transfer::Error as XhciTransferError;
 use crate::utils::Error as UtilsError;
 use msg_socket::MsgError;
 use std::fmt::{self, Display};
-use usb_util::error::Error as UsbUtilError;
+use usb_util::Error as UsbUtilError;
 
 #[derive(Debug)]
 pub enum Error {
@@ -19,6 +19,7 @@ pub enum Error {
     SetActiveConfig(UsbUtilError),
     SetInterfaceAltSetting(UsbUtilError),
     ClearHalt(UsbUtilError),
+    CreateTransfer(UsbUtilError),
     GetEndpointType,
     CreateControlSock(std::io::Error),
     SetupControlSock(std::io::Error),
@@ -30,7 +31,7 @@ pub enum Error {
     WriteBuffer(BufferError),
     BufferLen(BufferError),
     /// Cannot get interface descriptor for (interface, altsetting).
-    GetInterfaceDescriptor((i32, u16)),
+    GetInterfaceDescriptor((u8, u8)),
     GetEndpointDescriptor(u8),
     BadXhciTransferState,
     BadBackendProviderState,
@@ -49,6 +50,7 @@ impl Display for Error {
             SetActiveConfig(e) => write!(f, "failed to set active config: {:?}", e),
             SetInterfaceAltSetting(e) => write!(f, "failed to set interface alt setting: {:?}", e),
             ClearHalt(e) => write!(f, "failed to clear halt: {:?}", e),
+            CreateTransfer(e) => write!(f, "failed to create transfer: {:?}", e),
             GetEndpointType => write!(f, "failed to get endpoint type"),
             CreateControlSock(e) => write!(f, "failed to create contro sock: {}", e),
             SetupControlSock(e) => write!(f, "failed to setup control sock: {}", e),
diff --git a/devices/src/usb/host_backend/host_backend_device_provider.rs b/devices/src/usb/host_backend/host_backend_device_provider.rs
index f479bcb..f60983f 100644
--- a/devices/src/usb/host_backend/host_backend_device_provider.rs
+++ b/devices/src/usb/host_backend/host_backend_device_provider.rs
@@ -4,22 +4,23 @@
 
 use std::sync::Arc;
 
-use super::context::Context;
 use super::error::*;
 use super::host_device::HostDevice;
-use super::hotplug::HotplugHandler;
 use crate::usb::xhci::usb_hub::UsbHub;
 use crate::usb::xhci::xhci_backend_device_provider::XhciBackendDeviceProvider;
 use crate::utils::AsyncJobQueue;
 use crate::utils::{EventHandler, EventLoop, FailHandle};
 use msg_socket::{MsgReceiver, MsgSender, MsgSocket};
+use std::collections::HashMap;
 use std::mem;
 use std::os::unix::io::{AsRawFd, RawFd};
 use std::time::Duration;
+use sync::Mutex;
 use sys_util::net::UnixSeqpacket;
 use sys_util::{error, WatchingEvents};
+use usb_util::Device;
 use vm_control::{
-    UsbControlAttachedDevice, UsbControlCommand, UsbControlResult, UsbControlSocket,
+    MaybeOwnedFd, UsbControlAttachedDevice, UsbControlCommand, UsbControlResult, UsbControlSocket,
     USB_CONTROL_MAX_PORTS,
 };
 
@@ -64,12 +65,15 @@ impl HostBackendDeviceProvider {
     ) -> Result<()> {
         match mem::replace(self, HostBackendDeviceProvider::Failed) {
             HostBackendDeviceProvider::Created { sock } => {
-                let ctx = Context::new(event_loop.clone())?;
-                let hotplug_handler = HotplugHandler::new(hub.clone());
-                ctx.set_hotplug_handler(hotplug_handler);
                 let job_queue =
                     AsyncJobQueue::init(&event_loop).map_err(Error::StartAsyncJobQueue)?;
-                let inner = Arc::new(ProviderInner::new(fail_handle, job_queue, ctx, sock, hub));
+                let inner = Arc::new(ProviderInner::new(
+                    fail_handle,
+                    job_queue,
+                    event_loop.clone(),
+                    sock,
+                    hub,
+                ));
                 let handler: Arc<dyn EventHandler> = inner.clone();
                 event_loop
                     .add_event(
@@ -123,25 +127,125 @@ impl XhciBackendDeviceProvider for HostBackendDeviceProvider {
 pub struct ProviderInner {
     fail_handle: Arc<dyn FailHandle>,
     job_queue: Arc<AsyncJobQueue>,
-    ctx: Context,
+    event_loop: Arc<EventLoop>,
     sock: MsgSocket<UsbControlResult, UsbControlCommand>,
     usb_hub: Arc<UsbHub>,
+
+    // Map of USB hub port number to per-device context.
+    devices: Mutex<HashMap<u8, HostDeviceContext>>,
+}
+
+struct HostDeviceContext {
+    event_handler: Arc<dyn EventHandler>,
+    device: Arc<Mutex<Device>>,
 }
 
 impl ProviderInner {
     fn new(
         fail_handle: Arc<dyn FailHandle>,
         job_queue: Arc<AsyncJobQueue>,
-        ctx: Context,
+        event_loop: Arc<EventLoop>,
         sock: MsgSocket<UsbControlResult, UsbControlCommand>,
         usb_hub: Arc<UsbHub>,
     ) -> ProviderInner {
         ProviderInner {
             fail_handle,
             job_queue,
-            ctx,
+            event_loop,
             sock,
             usb_hub,
+            devices: Mutex::new(HashMap::new()),
+        }
+    }
+
+    /// Open a usbdevfs file to create a host USB device object.
+    /// `fd` should be an open file descriptor for a file in `/dev/bus/usb`.
+    fn handle_attach_device(&self, fd: Option<MaybeOwnedFd>) -> UsbControlResult {
+        let usb_file = match fd {
+            Some(MaybeOwnedFd::Owned(file)) => file,
+            _ => {
+                error!("missing fd in UsbControlCommand::AttachDevice message");
+                return UsbControlResult::FailedToOpenDevice;
+            }
+        };
+
+        let raw_fd = usb_file.as_raw_fd();
+        let device = match Device::new(usb_file) {
+            Ok(d) => d,
+            Err(e) => {
+                error!("could not construct USB device from fd: {}", e);
+                return UsbControlResult::NoSuchDevice;
+            }
+        };
+
+        let arc_mutex_device = Arc::new(Mutex::new(device));
+
+        let event_handler: Arc<dyn EventHandler> = Arc::new(UsbUtilEventHandler {
+            device: arc_mutex_device.clone(),
+        });
+
+        if let Err(e) = self.event_loop.add_event(
+            &MaybeOwnedFd::Borrowed(raw_fd),
+            WatchingEvents::empty().set_read().set_write(),
+            Arc::downgrade(&event_handler),
+        ) {
+            error!("failed to add USB device fd to event handler: {}", e);
+            return UsbControlResult::FailedToOpenDevice;
+        }
+
+        let device_ctx = HostDeviceContext {
+            event_handler,
+            device: arc_mutex_device.clone(),
+        };
+
+        // Resetting the device is used to make sure it is in a known state, but it may
+        // still function if the reset fails.
+        if let Err(e) = arc_mutex_device.lock().reset() {
+            error!("failed to reset device after attach: {:?}", e);
+        }
+
+        let host_device = Box::new(HostDevice::new(
+            self.fail_handle.clone(),
+            self.job_queue.clone(),
+            arc_mutex_device,
+        ));
+        let port = self.usb_hub.connect_backend(host_device);
+        match port {
+            Ok(port) => {
+                self.devices.lock().insert(port, device_ctx);
+                UsbControlResult::Ok { port }
+            }
+            Err(e) => {
+                error!("failed to connect device to hub: {}", e);
+                UsbControlResult::NoAvailablePort
+            }
+        }
+    }
+
+    fn handle_detach_device(&self, port: u8) -> UsbControlResult {
+        match self.usb_hub.disconnect_port(port) {
+            Ok(()) => {
+                if let Some(device_ctx) = self.devices.lock().remove(&port) {
+                    let _ = device_ctx.event_handler.on_event();
+                    let device = device_ctx.device.lock();
+                    let fd = device.fd();
+
+                    if let Err(e) = self
+                        .event_loop
+                        .remove_event_for_fd(&MaybeOwnedFd::Borrowed(fd.as_raw_fd()))
+                    {
+                        error!(
+                            "failed to remove poll change handler from event loop: {}",
+                            e
+                        );
+                    }
+                }
+                UsbControlResult::Ok { port }
+            }
+            Err(e) => {
+                error!("failed to disconnect device from port {}: {}", port, e);
+                UsbControlResult::NoSuchDevice
+            }
         }
     }
 
@@ -168,146 +272,13 @@ impl ProviderInner {
 
     fn on_event_helper(&self) -> Result<()> {
         let cmd = self.sock.recv().map_err(Error::ReadControlSock)?;
-        match cmd {
-            UsbControlCommand::AttachDevice {
-                bus,
-                addr,
-                vid,
-                pid,
-                fd: usb_fd,
-            } => {
-                let _ = usb_fd;
-                #[cfg(not(feature = "sandboxed-libusb"))]
-                let device = match self.ctx.get_device(bus, addr, vid, pid) {
-                    Some(d) => d,
-                    None => {
-                        error!(
-                            "cannot get device bus: {}, addr: {}, vid: {}, pid: {}",
-                            bus, addr, vid, pid
-                        );
-                        // The send failure will be logged, but event loop still think the event is
-                        // handled.
-                        let _ = self
-                            .sock
-                            .send(&UsbControlResult::NoSuchDevice)
-                            .map_err(Error::WriteControlSock)?;
-                        return Ok(());
-                    }
-                };
-                #[cfg(feature = "sandboxed-libusb")]
-                let (device, device_handle) = {
-                    use vm_control::MaybeOwnedFd;
-
-                    let usb_file = match usb_fd {
-                        Some(MaybeOwnedFd::Owned(file)) => file,
-                        _ => {
-                            let _ = self
-                                .sock
-                                .send(&UsbControlResult::FailedToOpenDevice)
-                                .map_err(Error::WriteControlSock);
-                            return Ok(());
-                        }
-                    };
-
-                    let device_handle = match self.ctx.get_device_handle(usb_file) {
-                        Some(d) => d,
-                        None => {
-                            error!(
-                                "cannot get device bus: {}, addr: {}, vid: {}, pid: {}",
-                                bus, addr, vid, pid
-                            );
-                            // The send failure will be logged, but event loop still think the event
-                            // is handled.
-                            let _ = self
-                                .sock
-                                .send(&UsbControlResult::NoSuchDevice)
-                                .map_err(Error::WriteControlSock);
-                            return Ok(());
-                        }
-                    };
-
-                    let device = device_handle.get_device();
-
-                    // Resetting the device is used to make sure it is in a known state, but it may
-                    // still function if the reset fails.
-                    if let Err(e) = device_handle.reset() {
-                        error!("failed to reset device after attach: {:?}", e);
-                    }
-                    (device, device_handle)
-                };
-
-                #[cfg(not(feature = "sandboxed-libusb"))]
-                let device_handle = match device.open() {
-                    Ok(handle) => handle,
-                    Err(e) => {
-                        error!("fail to open device: {:?}", e);
-                        // The send failure will be logged, but event loop still think the event is
-                        // handled.
-                        let _ = self
-                            .sock
-                            .send(&UsbControlResult::FailedToOpenDevice)
-                            .map_err(Error::WriteControlSock);
-                        return Ok(());
-                    }
-                };
-                let device = Box::new(HostDevice::new(
-                    self.fail_handle.clone(),
-                    self.job_queue.clone(),
-                    device,
-                    device_handle,
-                ));
-                let port = self.usb_hub.connect_backend(device);
-                match port {
-                    Ok(port) => {
-                        // The send failure will be logged, but event loop still think the event is
-                        // handled.
-                        let _ = self
-                            .sock
-                            .send(&UsbControlResult::Ok { port })
-                            .map_err(Error::WriteControlSock);
-                    }
-                    Err(e) => {
-                        error!("failed to connect device to hub: {}", e);
-                        // The send failure will be logged, but event loop still think the event is
-                        // handled.
-                        let _ = self
-                            .sock
-                            .send(&UsbControlResult::NoAvailablePort)
-                            .map_err(Error::WriteControlSock);
-                    }
-                }
-                Ok(())
-            }
-            UsbControlCommand::DetachDevice { port } => {
-                match self.usb_hub.disconnect_port(port) {
-                    Ok(()) => {
-                        // The send failure will be logged, but event loop still think the event is
-                        // handled.
-                        let _ = self
-                            .sock
-                            .send(&UsbControlResult::Ok { port })
-                            .map_err(Error::WriteControlSock);
-                    }
-                    Err(e) => {
-                        error!("failed to disconnect device from port {}: {}", port, e);
-                        // The send failure will be logged, but event loop still think the event is
-                        // handled.
-                        let _ = self
-                            .sock
-                            .send(&UsbControlResult::NoSuchDevice)
-                            .map_err(Error::WriteControlSock);
-                    }
-                }
-                Ok(())
-            }
-            UsbControlCommand::ListDevice { ports } => {
-                let result = self.handle_list_devices(ports);
-                // The send failure will be logged, but event loop still think the event is
-                // handled.
-                let _ = self.sock.send(&result).map_err(Error::WriteControlSock);
-                Ok(())
-            }
-        }
+        let result = match cmd {
+            UsbControlCommand::AttachDevice { fd, .. } => self.handle_attach_device(fd),
+            UsbControlCommand::DetachDevice { port } => self.handle_detach_device(port),
+            UsbControlCommand::ListDevice { ports } => self.handle_list_devices(ports),
+        };
+        self.sock.send(&result).map_err(Error::WriteControlSock)?;
+        Ok(())
     }
 }
 
@@ -318,3 +289,13 @@ impl EventHandler for ProviderInner {
         })
     }
 }
+
+struct UsbUtilEventHandler {
+    device: Arc<Mutex<Device>>,
+}
+
+impl EventHandler for UsbUtilEventHandler {
+    fn on_event(&self) -> std::result::Result<(), ()> {
+        self.device.lock().poll_transfers().map_err(|_e| ())
+    }
+}
diff --git a/devices/src/usb/host_backend/host_device.rs b/devices/src/usb/host_backend/host_device.rs
index 8841f00..3b85ea2 100644
--- a/devices/src/usb/host_backend/host_device.rs
+++ b/devices/src/usb/host_backend/host_device.rs
@@ -4,7 +4,6 @@
 
 use std::mem::drop;
 use std::sync::Arc;
-use sync::Mutex;
 
 use super::error::*;
 use super::usb_endpoint::UsbEndpoint;
@@ -14,17 +13,14 @@ use crate::usb::xhci::xhci_backend_device::{BackendType, UsbDeviceAddress, XhciB
 use crate::usb::xhci::xhci_transfer::{XhciTransfer, XhciTransferState, XhciTransferType};
 use crate::utils::AsyncJobQueue;
 use crate::utils::FailHandle;
+use data_model::DataInit;
 use std::collections::HashMap;
+use std::mem;
+use sync::Mutex;
 use sys_util::{error, warn};
-use usb_util::device_handle::DeviceHandle;
-use usb_util::error::Error as LibUsbError;
-use usb_util::libusb_device::LibUsbDevice;
-use usb_util::types::{
-    ControlRequestDataPhaseTransferDirection, ControlRequestRecipient, StandardControlRequest,
-    UsbRequestSetup,
-};
-use usb_util::usb_transfer::{
-    control_transfer, ControlTransferBuffer, TransferStatus, UsbTransfer,
+use usb_util::{
+    ConfigDescriptorTree, ControlRequestDataPhaseTransferDirection, ControlRequestRecipient,
+    Device, StandardControlRequest, Transfer, TransferStatus, UsbRequestSetup,
 };
 
 #[derive(PartialEq)]
@@ -43,11 +39,10 @@ pub struct HostDevice {
     // Endpoints only contains data endpoints (1 to 30). Control transfers are handled at device
     // level.
     endpoints: Vec<UsbEndpoint>,
-    device: LibUsbDevice,
-    device_handle: Arc<Mutex<DeviceHandle>>,
+    device: Arc<Mutex<Device>>,
     ctl_ep_state: ControlEndpointState,
-    alt_settings: HashMap<u16, u16>,
-    claimed_interfaces: Vec<i32>,
+    alt_settings: HashMap<u8, u8>,
+    claimed_interfaces: Vec<u8>,
     control_request_setup: UsbRequestSetup,
     executed: bool,
     job_queue: Arc<AsyncJobQueue>,
@@ -64,14 +59,12 @@ impl HostDevice {
     pub fn new(
         fail_handle: Arc<dyn FailHandle>,
         job_queue: Arc<AsyncJobQueue>,
-        device: LibUsbDevice,
-        device_handle: DeviceHandle,
+        device: Arc<Mutex<Device>>,
     ) -> HostDevice {
         HostDevice {
             fail_handle,
             endpoints: vec![],
             device,
-            device_handle: Arc::new(Mutex::new(device_handle)),
             ctl_ep_state: ControlEndpointState::SetupStage,
             alt_settings: HashMap::new(),
             claimed_interfaces: vec![],
@@ -81,30 +74,6 @@ impl HostDevice {
         }
     }
 
-    fn get_interface_number_of_active_config(&self) -> i32 {
-        match self.device.get_active_config_descriptor() {
-            Err(LibUsbError::NotFound) => {
-                usb_debug!("device is in unconfigured state");
-                0
-            }
-            Err(e) => {
-                // device might be disconnected now.
-                error!("unexpected error: {:?}", e);
-                0
-            }
-            Ok(descriptor) => descriptor.bNumInterfaces as i32,
-        }
-    }
-
-    fn release_interfaces(&mut self) {
-        for i in &self.claimed_interfaces {
-            if let Err(e) = self.device_handle.lock().release_interface(*i) {
-                error!("could not release interface: {:?}", e);
-            }
-        }
-        self.claimed_interfaces = Vec::new();
-    }
-
     // Check for requests that should be intercepted and emulated using libusb
     // functions rather than passed directly to the device.
     // Returns true if the request has been intercepted or false if the request
@@ -167,20 +136,34 @@ impl HostDevice {
         xhci_transfer: Arc<XhciTransfer>,
         buffer: Option<ScatterGatherBuffer>,
     ) -> Result<()> {
-        let mut control_transfer = control_transfer(0);
-        control_transfer
-            .buffer_mut()
-            .set_request_setup(&self.control_request_setup);
-
         if self.intercepted_control_transfer(&xhci_transfer)? {
             return Ok(());
         }
 
+        // Default buffer size for control data transfer.
+        const CONTROL_DATA_BUFFER_SIZE: usize = 1024;
+
+        // Buffer type for control transfer. The first 8 bytes is a UsbRequestSetup struct.
+        #[derive(Copy, Clone)]
+        #[repr(C, packed)]
+        struct ControlTransferBuffer {
+            pub setup: UsbRequestSetup,
+            pub data: [u8; CONTROL_DATA_BUFFER_SIZE],
+        }
+
+        // Safe because it only has data and has no implicit padding.
+        unsafe impl DataInit for ControlTransferBuffer {}
+
+        let mut control_request = ControlTransferBuffer {
+            setup: self.control_request_setup,
+            data: [0; CONTROL_DATA_BUFFER_SIZE],
+        };
+
         let direction = self.control_request_setup.get_direction();
         let buffer = if direction == ControlRequestDataPhaseTransferDirection::HostToDevice {
             if let Some(buffer) = buffer {
                 buffer
-                    .read(&mut control_transfer.buffer_mut().data_buffer)
+                    .read(&mut control_request.data)
                     .map_err(Error::ReadBuffer)?;
             }
             // buffer is consumed here for HostToDevice transfers.
@@ -190,8 +173,13 @@ impl HostDevice {
             buffer
         };
 
+        let control_buffer = control_request.as_slice().to_vec();
+
+        let mut control_transfer =
+            Transfer::new_control(control_buffer).map_err(Error::CreateTransfer)?;
+
         let tmp_transfer = xhci_transfer.clone();
-        let callback = move |t: UsbTransfer<ControlTransferBuffer>| {
+        let callback = move |t: Transfer| {
             usb_debug!("setup token control transfer callback invoked");
             update_transfer_state(&xhci_transfer, &t)?;
             let state = xhci_transfer.state().lock();
@@ -207,10 +195,14 @@ impl HostDevice {
                     let status = t.status();
                     let actual_length = t.actual_length();
                     if direction == ControlRequestDataPhaseTransferDirection::DeviceToHost {
-                        if let Some(buffer) = &buffer {
-                            buffer
-                                .write(&t.buffer().data_buffer)
-                                .map_err(Error::WriteBuffer)?;
+                        if let Some(control_request_data) =
+                            t.buffer.get(mem::size_of::<UsbRequestSetup>()..)
+                        {
+                            if let Some(buffer) = &buffer {
+                                buffer
+                                    .write(&control_request_data)
+                                    .map_err(Error::WriteBuffer)?;
+                            }
                         }
                     }
                     drop(state);
@@ -231,20 +223,18 @@ impl HostDevice {
         };
 
         let fail_handle = self.fail_handle.clone();
-        control_transfer.set_callback(
-            move |t: UsbTransfer<ControlTransferBuffer>| match callback(t) {
-                Ok(_) => {}
-                Err(e) => {
-                    error!("control transfer callback failed {:?}", e);
-                    fail_handle.fail();
-                }
-            },
-        );
+        control_transfer.set_callback(move |t: Transfer| match callback(t) {
+            Ok(_) => {}
+            Err(e) => {
+                error!("control transfer callback failed {:?}", e);
+                fail_handle.fail();
+            }
+        });
         submit_transfer(
             self.fail_handle.clone(),
             &self.job_queue,
             tmp_transfer,
-            &self.device_handle,
+            &mut self.device.lock(),
             control_transfer,
         )
     }
@@ -309,40 +299,50 @@ impl HostDevice {
 
     fn set_config(&mut self) -> Result<TransferStatus> {
         // It's a standard, set_config, device request.
-        let config = (self.control_request_setup.value & 0xff) as i32;
+        let config = (self.control_request_setup.value & 0xff) as u8;
         usb_debug!(
             "Set config control transfer is received with config: {}",
             config
         );
         self.release_interfaces();
         let cur_config = self
-            .device_handle
+            .device
             .lock()
             .get_active_configuration()
             .map_err(Error::GetActiveConfig)?;
         usb_debug!("current config is: {}", cur_config);
         if config != cur_config {
-            self.device_handle
+            self.device
                 .lock()
                 .set_active_configuration(config)
                 .map_err(Error::SetActiveConfig)?;
         }
-        self.claim_interfaces();
-        self.create_endpoints()?;
+        let config_descriptor = self
+            .device
+            .lock()
+            .get_active_config_descriptor()
+            .map_err(Error::GetActiveConfig)?;
+        self.claim_interfaces(&config_descriptor);
+        self.create_endpoints(&config_descriptor)?;
         Ok(TransferStatus::Completed)
     }
 
     fn set_interface(&mut self) -> Result<TransferStatus> {
         usb_debug!("set interface");
         // It's a standard, set_interface, interface request.
-        let interface = self.control_request_setup.index;
-        let alt_setting = self.control_request_setup.value;
-        self.device_handle
+        let interface = self.control_request_setup.index as u8;
+        let alt_setting = self.control_request_setup.value as u8;
+        self.device
             .lock()
-            .set_interface_alt_setting(interface as i32, alt_setting as i32)
+            .set_interface_alt_setting(interface, alt_setting)
             .map_err(Error::SetInterfaceAltSetting)?;
         self.alt_settings.insert(interface, alt_setting);
-        self.create_endpoints()?;
+        let config_descriptor = self
+            .device
+            .lock()
+            .get_active_config_descriptor()
+            .map_err(Error::GetActiveConfig)?;
+        self.create_endpoints(&config_descriptor)?;
         Ok(TransferStatus::Completed)
     }
 
@@ -352,7 +352,7 @@ impl HostDevice {
         // It's a standard, clear_feature, endpoint request.
         const STD_FEATURE_ENDPOINT_HALT: u16 = 0;
         if request_setup.value == STD_FEATURE_ENDPOINT_HALT {
-            self.device_handle
+            self.device
                 .lock()
                 .clear_halt(request_setup.index as u8)
                 .map_err(Error::ClearHalt)?;
@@ -360,9 +360,9 @@ impl HostDevice {
         Ok(TransferStatus::Completed)
     }
 
-    fn claim_interfaces(&mut self) {
-        for i in 0..self.get_interface_number_of_active_config() {
-            match self.device_handle.lock().claim_interface(i) {
+    fn claim_interfaces(&mut self, config_descriptor: &ConfigDescriptorTree) {
+        for i in 0..config_descriptor.num_interfaces() {
+            match self.device.lock().claim_interface(i) {
                 Ok(()) => {
                     usb_debug!("claimed interface {}", i);
                     self.claimed_interfaces.push(i);
@@ -374,23 +374,16 @@ impl HostDevice {
         }
     }
 
-    fn create_endpoints(&mut self) -> Result<()> {
+    fn create_endpoints(&mut self, config_descriptor: &ConfigDescriptorTree) -> Result<()> {
         self.endpoints = Vec::new();
-        let config_descriptor = match self.device.get_active_config_descriptor() {
-            Err(e) => {
-                error!("device might be disconnected: {:?}", e);
-                return Ok(());
-            }
-            Ok(descriptor) => descriptor,
-        };
         for i in &self.claimed_interfaces {
-            let alt_setting = self.alt_settings.get(&(*i as u16)).unwrap_or(&0);
+            let alt_setting = self.alt_settings.get(i).unwrap_or(&0);
             let interface = config_descriptor
-                .get_interface_descriptor(*i as u8, *alt_setting as i32)
+                .get_interface_descriptor(*i, *alt_setting)
                 .ok_or(Error::GetInterfaceDescriptor((*i, *alt_setting)))?;
             for ep_idx in 0..interface.bNumEndpoints {
                 let ep_dp = interface
-                    .endpoint_descriptor(ep_idx)
+                    .get_endpoint_descriptor(ep_idx)
                     .ok_or(Error::GetEndpointDescriptor(ep_idx))?;
                 let ep_num = ep_dp.get_endpoint_number();
                 if ep_num == 0 {
@@ -402,7 +395,7 @@ impl HostDevice {
                 self.endpoints.push(UsbEndpoint::new(
                     self.fail_handle.clone(),
                     self.job_queue.clone(),
-                    self.device_handle.clone(),
+                    self.device.clone(),
                     ep_num,
                     direction,
                     ty,
@@ -412,6 +405,15 @@ impl HostDevice {
         Ok(())
     }
 
+    fn release_interfaces(&mut self) {
+        for i in &self.claimed_interfaces {
+            if let Err(e) = self.device.lock().release_interface(*i) {
+                error!("could not release interface: {:?}", e);
+            }
+        }
+        self.claimed_interfaces = Vec::new();
+    }
+
     fn submit_transfer_helper(&mut self, transfer: XhciTransfer) -> Result<()> {
         if transfer.get_endpoint_number() == 0 {
             return self.handle_control_transfer(transfer);
@@ -430,7 +432,7 @@ impl HostDevice {
 
 impl XhciBackendDevice for HostDevice {
     fn get_backend_type(&self) -> BackendType {
-        let d = match self.device.get_device_descriptor() {
+        let d = match self.device.lock().get_device_descriptor() {
             Ok(d) => d,
             Err(_) => return BackendType::Usb2,
         };
@@ -443,16 +445,8 @@ impl XhciBackendDevice for HostDevice {
         }
     }
 
-    fn host_bus(&self) -> u8 {
-        self.device.get_bus_number()
-    }
-
-    fn host_address(&self) -> u8 {
-        self.device.get_address()
-    }
-
     fn get_vid(&self) -> u16 {
-        match self.device.get_device_descriptor() {
+        match self.device.lock().get_device_descriptor() {
             Ok(d) => d.idVendor,
             Err(e) => {
                 error!("cannot get device descriptor: {:?}", e);
@@ -462,7 +456,7 @@ impl XhciBackendDevice for HostDevice {
     }
 
     fn get_pid(&self) -> u16 {
-        match self.device.get_device_descriptor() {
+        match self.device.lock().get_device_descriptor() {
             Ok(d) => d.idProduct,
             Err(e) => {
                 error!("cannot get device descriptor: {:?}", e);
@@ -488,16 +482,9 @@ impl XhciBackendDevice for HostDevice {
 
     fn reset(&mut self) -> std::result::Result<(), ()> {
         usb_debug!("resetting host device");
-        let result = self.device_handle.lock().reset();
-        match result {
-            Err(LibUsbError::NotFound) => {
-                // libusb will return NotFound if it fails to re-claim
-                // the interface after the reset.
-                Ok(())
-            }
-            _ => result.map_err(|e| {
-                error!("failed to reset device: {:?}", e);
-            }),
-        }
+        self.device
+            .lock()
+            .reset()
+            .map_err(|e| error!("failed to reset device: {:?}", e))
     }
 }
diff --git a/devices/src/usb/host_backend/hotplug.rs b/devices/src/usb/host_backend/hotplug.rs
deleted file mode 100644
index 0764660..0000000
--- a/devices/src/usb/host_backend/hotplug.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2019 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use std::sync::Arc;
-
-use crate::usb::xhci::usb_hub::UsbHub;
-use sys_util::error;
-use usb_util::hotplug::{HotplugEvent, UsbHotplugHandler};
-use usb_util::libusb_device::LibUsbDevice;
-
-pub struct HotplugHandler {
-    hub: Arc<UsbHub>,
-}
-
-impl HotplugHandler {
-    pub fn new(hub: Arc<UsbHub>) -> Self {
-        HotplugHandler { hub }
-    }
-}
-
-impl UsbHotplugHandler for HotplugHandler {
-    fn hotplug_event(&self, device: LibUsbDevice, event: HotplugEvent) {
-        if event != HotplugEvent::DeviceLeft {
-            return;
-        }
-
-        let bus = device.get_bus_number();
-        let address = device.get_address();
-        let descriptor = match device.get_device_descriptor() {
-            Ok(d) => d,
-            Err(e) => {
-                error!("cannot get device descriptor: {:?}", e);
-                return;
-            }
-        };
-        let vid = descriptor.idVendor;
-        let pid = descriptor.idProduct;
-
-        if let Err(e) = self.hub.try_detach(bus, address, vid, pid) {
-            error!("device left event triggered failed detach from hub: {}", e);
-            return;
-        }
-    }
-}
diff --git a/devices/src/usb/host_backend/mod.rs b/devices/src/usb/host_backend/mod.rs
index ea0f44c..aa0f568 100644
--- a/devices/src/usb/host_backend/mod.rs
+++ b/devices/src/usb/host_backend/mod.rs
@@ -2,10 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-pub mod context;
 pub mod error;
 pub mod host_backend_device_provider;
 pub mod host_device;
-mod hotplug;
 pub mod usb_endpoint;
 mod utils;
diff --git a/devices/src/usb/host_backend/usb_endpoint.rs b/devices/src/usb/host_backend/usb_endpoint.rs
index 329d6ff..f9f06ff 100644
--- a/devices/src/usb/host_backend/usb_endpoint.rs
+++ b/devices/src/usb/host_backend/usb_endpoint.rs
@@ -4,7 +4,6 @@
 
 use std::cmp;
 use std::sync::Arc;
-use sync::Mutex;
 
 use super::error::*;
 use super::utils::{submit_transfer, update_transfer_state};
@@ -14,18 +13,17 @@ use crate::usb::xhci::xhci_transfer::{
 };
 use crate::utils::AsyncJobQueue;
 use crate::utils::FailHandle;
+use sync::Mutex;
 use sys_util::error;
-use usb_util::device_handle::DeviceHandle;
-use usb_util::types::{EndpointDirection, EndpointType, ENDPOINT_DIRECTION_OFFSET};
-use usb_util::usb_transfer::{
-    bulk_transfer, interrupt_transfer, BulkTransferBuffer, TransferStatus, UsbTransfer,
+use usb_util::{
+    Device, EndpointDirection, EndpointType, Transfer, TransferStatus, ENDPOINT_DIRECTION_OFFSET,
 };
 
 /// Isochronous, Bulk or Interrupt endpoint.
 pub struct UsbEndpoint {
     fail_handle: Arc<dyn FailHandle>,
     job_queue: Arc<AsyncJobQueue>,
-    device_handle: Arc<Mutex<DeviceHandle>>,
+    device: Arc<Mutex<Device>>,
     endpoint_number: u8,
     direction: EndpointDirection,
     ty: EndpointType,
@@ -36,7 +34,7 @@ impl UsbEndpoint {
     pub fn new(
         fail_handle: Arc<dyn FailHandle>,
         job_queue: Arc<AsyncJobQueue>,
-        device_handle: Arc<Mutex<DeviceHandle>>,
+        device: Arc<Mutex<Device>>,
         endpoint_number: u8,
         direction: EndpointDirection,
         ty: EndpointType,
@@ -45,7 +43,7 @@ impl UsbEndpoint {
         UsbEndpoint {
             fail_handle,
             job_queue,
-            device_handle,
+            device,
             endpoint_number,
             direction,
             ty,
@@ -101,13 +99,23 @@ impl UsbEndpoint {
         Ok(())
     }
 
+    fn get_transfer_buffer(&self, buffer: &ScatterGatherBuffer) -> Result<Vec<u8>> {
+        let mut v = vec![0u8; buffer.len().map_err(Error::BufferLen)?];
+        if self.direction == EndpointDirection::HostToDevice {
+            // Read data from ScatterGatherBuffer to a continuous memory.
+            buffer.read(v.as_mut_slice()).map_err(Error::ReadBuffer)?;
+        }
+        Ok(v)
+    }
+
     fn handle_bulk_transfer(
         &self,
         xhci_transfer: XhciTransfer,
         buffer: ScatterGatherBuffer,
     ) -> Result<()> {
+        let transfer_buffer = self.get_transfer_buffer(&buffer)?;
         let usb_transfer =
-            bulk_transfer(self.ep_addr(), 0, buffer.len().map_err(Error::BufferLen)?);
+            Transfer::new_bulk(self.ep_addr(), transfer_buffer).map_err(Error::CreateTransfer)?;
         self.do_handle_transfer(xhci_transfer, usb_transfer, buffer)
     }
 
@@ -116,32 +124,28 @@ impl UsbEndpoint {
         xhci_transfer: XhciTransfer,
         buffer: ScatterGatherBuffer,
     ) -> Result<()> {
-        let usb_transfer =
-            interrupt_transfer(self.ep_addr(), 0, buffer.len().map_err(Error::BufferLen)?);
+        let transfer_buffer = self.get_transfer_buffer(&buffer)?;
+        let usb_transfer = Transfer::new_interrupt(self.ep_addr(), transfer_buffer)
+            .map_err(Error::CreateTransfer)?;
         self.do_handle_transfer(xhci_transfer, usb_transfer, buffer)
     }
 
     fn do_handle_transfer(
         &self,
         xhci_transfer: XhciTransfer,
-        mut usb_transfer: UsbTransfer<BulkTransferBuffer>,
+        mut usb_transfer: Transfer,
         buffer: ScatterGatherBuffer,
     ) -> Result<()> {
         let xhci_transfer = Arc::new(xhci_transfer);
         let tmp_transfer = xhci_transfer.clone();
         match self.direction {
             EndpointDirection::HostToDevice => {
-                // Read data from ScatterGatherBuffer to a continuous memory.
-                buffer
-                    .read(usb_transfer.buffer_mut().as_mut_slice())
-                    .map_err(Error::ReadBuffer)?;
                 usb_debug!(
-                    "out transfer ep_addr {:#x}, buffer len {:?}, data {:#x?}",
+                    "out transfer ep_addr {:#x}, buffer len {:?}",
                     self.ep_addr(),
                     buffer.len(),
-                    usb_transfer.buffer_mut().as_mut_slice()
                 );
-                let callback = move |t: UsbTransfer<BulkTransferBuffer>| {
+                let callback = move |t: Transfer| {
                     usb_debug!("out transfer callback");
                     update_transfer_state(&xhci_transfer, &t)?;
                     let state = xhci_transfer.state().lock();
@@ -168,20 +172,18 @@ impl UsbEndpoint {
                     }
                 };
                 let fail_handle = self.fail_handle.clone();
-                usb_transfer.set_callback(
-                    move |t: UsbTransfer<BulkTransferBuffer>| match callback(t) {
-                        Ok(_) => {}
-                        Err(e) => {
-                            error!("bulk transfer callback failed: {:?}", e);
-                            fail_handle.fail();
-                        }
-                    },
-                );
+                usb_transfer.set_callback(move |t: Transfer| match callback(t) {
+                    Ok(_) => {}
+                    Err(e) => {
+                        error!("bulk transfer callback failed: {:?}", e);
+                        fail_handle.fail();
+                    }
+                });
                 submit_transfer(
                     self.fail_handle.clone(),
                     &self.job_queue,
                     tmp_transfer,
-                    &self.device_handle,
+                    &mut self.device.lock(),
                     usb_transfer,
                 )?;
             }
@@ -192,12 +194,8 @@ impl UsbEndpoint {
                     buffer.len()
                 );
                 let _addr = self.ep_addr();
-                let callback = move |t: UsbTransfer<BulkTransferBuffer>| {
-                    usb_debug!(
-                        "ep {:#x} in transfer data {:?}",
-                        _addr,
-                        t.buffer().as_slice()
-                    );
+                let callback = move |t: Transfer| {
+                    usb_debug!("ep {:#x} in transfer data {:?}", _addr, t.buffer.as_slice());
                     update_transfer_state(&xhci_transfer, &t)?;
                     let state = xhci_transfer.state().lock();
                     match *state {
@@ -212,7 +210,7 @@ impl UsbEndpoint {
                             let status = t.status();
                             let actual_length = t.actual_length() as usize;
                             let copied_length = buffer
-                                .write(t.buffer().as_slice())
+                                .write(t.buffer.as_slice())
                                 .map_err(Error::WriteBuffer)?;
                             let actual_length = cmp::min(actual_length, copied_length);
                             drop(state);
@@ -230,21 +228,19 @@ impl UsbEndpoint {
                 };
                 let fail_handle = self.fail_handle.clone();
 
-                usb_transfer.set_callback(
-                    move |t: UsbTransfer<BulkTransferBuffer>| match callback(t) {
-                        Ok(_) => {}
-                        Err(e) => {
-                            error!("bulk transfer callback {:?}", e);
-                            fail_handle.fail();
-                        }
-                    },
-                );
+                usb_transfer.set_callback(move |t: Transfer| match callback(t) {
+                    Ok(_) => {}
+                    Err(e) => {
+                        error!("bulk transfer callback {:?}", e);
+                        fail_handle.fail();
+                    }
+                });
 
                 submit_transfer(
                     self.fail_handle.clone(),
                     &self.job_queue,
                     tmp_transfer,
-                    &self.device_handle,
+                    &mut self.device.lock(),
                     usb_transfer,
                 )?;
             }
diff --git a/devices/src/usb/host_backend/utils.rs b/devices/src/usb/host_backend/utils.rs
index bcbec20..ac506e7 100644
--- a/devices/src/usb/host_backend/utils.rs
+++ b/devices/src/usb/host_backend/utils.rs
@@ -4,20 +4,18 @@
 
 use std::mem;
 use std::sync::Arc;
-use sync::Mutex;
 
 use super::error::*;
 use crate::usb::xhci::xhci_transfer::{XhciTransfer, XhciTransferState};
 use crate::utils::AsyncJobQueue;
 use crate::utils::FailHandle;
 use sys_util::{error, warn};
-use usb_util::device_handle::DeviceHandle;
-use usb_util::usb_transfer::{TransferStatus, UsbTransfer, UsbTransferBuffer};
+use usb_util::{Device, Transfer, TransferStatus};
 
 /// Helper function to update xhci_transfer state.
-pub fn update_transfer_state<T: UsbTransferBuffer>(
+pub fn update_transfer_state(
     xhci_transfer: &Arc<XhciTransfer>,
-    usb_transfer: &UsbTransfer<T>,
+    usb_transfer: &Transfer,
 ) -> Result<()> {
     let status = usb_transfer.status();
     let mut state = xhci_transfer.state().lock();
@@ -44,12 +42,12 @@ pub fn update_transfer_state<T: UsbTransferBuffer>(
 }
 
 /// Helper function to submit usb_transfer to device handle.
-pub fn submit_transfer<T: UsbTransferBuffer>(
+pub fn submit_transfer(
     fail_handle: Arc<dyn FailHandle>,
     job_queue: &Arc<AsyncJobQueue>,
     xhci_transfer: Arc<XhciTransfer>,
-    device_handle: &Arc<Mutex<DeviceHandle>>,
-    usb_transfer: UsbTransfer<T>,
+    device: &mut Device,
+    usb_transfer: Transfer,
 ) -> Result<()> {
     let transfer_status = {
         // We need to hold the lock to avoid race condition.
@@ -58,7 +56,7 @@ pub fn submit_transfer<T: UsbTransferBuffer>(
         let mut state = xhci_transfer.state().lock();
         match mem::replace(&mut *state, XhciTransferState::Cancelled) {
             XhciTransferState::Created => {
-                match device_handle.lock().submit_async_transfer(usb_transfer) {
+                match device.submit_transfer(usb_transfer) {
                     Err(e) => {
                         error!("fail to submit transfer {:?}", e);
                         *state = XhciTransferState::Completed;
@@ -66,13 +64,12 @@ pub fn submit_transfer<T: UsbTransferBuffer>(
                     }
                     // If it's submitted, we don't need to send on_transfer_complete now.
                     Ok(canceller) => {
-                        // TODO(jkwang) refactor canceller to return Cancel::Ok or Cancel::Err.
-                        let cancel_callback = Box::new(move || match canceller.try_cancel() {
-                            true => {
-                                usb_debug!("cancel issued to libusb backend");
+                        let cancel_callback = Box::new(move || match canceller.cancel() {
+                            Ok(()) => {
+                                usb_debug!("cancel issued to kernel");
                             }
-                            false => {
-                                usb_debug!("fail to cancel");
+                            Err(e) => {
+                                usb_debug!("fail to cancel: {}", e);
                             }
                         });
                         *state = XhciTransferState::Submitted { cancel_callback };
diff --git a/devices/src/usb/xhci/usb_hub.rs b/devices/src/usb/xhci/usb_hub.rs
index 28c7f19..d54eaa9 100644
--- a/devices/src/usb/xhci/usb_hub.rs
+++ b/devices/src/usb/xhci/usb_hub.rs
@@ -205,41 +205,6 @@ impl UsbHub {
         UsbHub { ports }
     }
 
-    /// Try to detach device of bus, addr, vid, pid
-    pub fn try_detach(&self, bus: u8, addr: u8, vid: u16, pid: u16) -> Result<()> {
-        for port in &self.ports {
-            // This block exists so that we only hold the backend device
-            // lock while checking the address. It needs to be dropped before
-            // calling port.detach(), because that acquires the backend
-            // device lock again.
-            {
-                let backend_device = port.get_backend_device();
-
-                let d = match backend_device.as_ref() {
-                    None => continue,
-                    Some(d) => d,
-                };
-
-                if d.host_bus() != bus
-                    || d.host_address() != addr
-                    || d.get_vid() != vid
-                    || d.get_pid() != pid
-                {
-                    continue;
-                }
-            }
-
-            return port.detach();
-        }
-
-        Err(Error::NoSuchDevice {
-            bus,
-            addr,
-            vid,
-            pid,
-        })
-    }
-
     /// Reset all ports.
     pub fn reset(&self) -> Result<()> {
         usb_debug!("reseting usb hub");
diff --git a/devices/src/usb/xhci/xhci_backend_device.rs b/devices/src/usb/xhci/xhci_backend_device.rs
index e104cdc..a3d9e66 100644
--- a/devices/src/usb/xhci/xhci_backend_device.rs
+++ b/devices/src/usb/xhci/xhci_backend_device.rs
@@ -18,10 +18,6 @@ pub enum BackendType {
 pub trait XhciBackendDevice: Send {
     /// Returns the type of USB device provided by this device.
     fn get_backend_type(&self) -> BackendType;
-    /// Returns host bus number of this device.
-    fn host_bus(&self) -> u8;
-    /// Returns host address of this device.
-    fn host_address(&self) -> u8;
     /// Get vendor id of this device.
     fn get_vid(&self) -> u16;
     /// Get product id of this device.
diff --git a/devices/src/usb/xhci/xhci_transfer.rs b/devices/src/usb/xhci/xhci_transfer.rs
index fa6d5de..625f97e 100644
--- a/devices/src/usb/xhci/xhci_transfer.rs
+++ b/devices/src/usb/xhci/xhci_transfer.rs
@@ -17,8 +17,7 @@ use std::mem;
 use std::sync::{Arc, Weak};
 use sync::Mutex;
 use sys_util::{error, Error as SysError, EventFd, GuestMemory};
-use usb_util::types::UsbRequestSetup;
-use usb_util::usb_transfer::TransferStatus;
+use usb_util::{TransferStatus, UsbRequestSetup};
 
 #[derive(Debug)]
 pub enum Error {
@@ -67,7 +66,7 @@ pub enum XhciTransferState {
     /// When transfer is submitted, it will contain a transfer callback, which should be invoked
     /// when the transfer is cancelled.
     Submitted {
-        cancel_callback: Box<dyn FnMut() + Send>,
+        cancel_callback: Box<dyn FnOnce() + Send>,
     },
     Cancelling,
     Cancelled,
@@ -78,9 +77,7 @@ impl XhciTransferState {
     /// Try to cancel this transfer, if it's possible.
     pub fn try_cancel(&mut self) {
         match mem::replace(self, XhciTransferState::Created) {
-            XhciTransferState::Submitted {
-                mut cancel_callback,
-            } => {
+            XhciTransferState::Submitted { cancel_callback } => {
                 *self = XhciTransferState::Cancelling;
                 cancel_callback();
             }