summary refs log tree commit diff
path: root/usb_util/src/error.rs
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2019-07-09 17:21:54 -0700
committerCommit Bot <commit-bot@chromium.org>2019-10-17 00:20:24 +0000
commit6494117e1766337f5d688b98bfc3df999932c3ac (patch)
tree0c8b6fd24a615ae146bb0a2d6f4d8ce332f5cc42 /usb_util/src/error.rs
parentbed8b0017d2cb283c20dc50241adb4f5b2668489 (diff)
downloadcrosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar.gz
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar.bz2
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar.lz
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar.xz
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar.zst
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.zip
usb: replace libusb with Rust usb_util library
Drop the dependency on libusb and reimplement the host USB backend using
usb_sys to wrap the Linux usbdevfs ioctls.

This allows sandboxing to work without any dependency on libusb patches,
and it gives us the flexibility to modify and update the USB backend
without depending on an external third-party library.

BUG=chromium:987833
TEST=`adb logcat` on nami with Nexus 5 attached
TEST=deploy app to phone with Android Studio
TEST=Run EdgeTPU USB accelerator demo (including DFU mode transition)

Cq-Depend: chromium:1773695
Change-Id: I4321c2b6142caac15f48f197795a37d59d268831
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1783601
Reviewed-by: Zach Reizner <zachr@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'usb_util/src/error.rs')
-rw-r--r--usb_util/src/error.rs103
1 files changed, 35 insertions, 68 deletions
diff --git a/usb_util/src/error.rs b/usb_util/src/error.rs
index b6dd91e..24d8036 100644
--- a/usb_util/src/error.rs
+++ b/usb_util/src/error.rs
@@ -1,85 +1,52 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// 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 libc::c_ulong;
+use remain::sorted;
 use std;
-use std::fmt;
+use std::fmt::{self, Display};
+use std::io;
+use std::num;
 
-use crate::bindings;
-
-/// Error type for libusb.
+#[sorted]
+#[derive(Debug)]
 pub enum Error {
-    Success(i32),
-    IO,
-    InvalidParam,
-    Access,
+    DescriptorParse,
+    DescriptorRead(io::Error),
+    FdCloneFailed(io::Error),
+    InvalidActualLength(num::TryFromIntError),
+    InvalidBufferLength(num::TryFromIntError),
+    IoctlFailed(c_ulong, sys_util::Error),
     NoDevice,
-    NotFound,
-    Busy,
-    Timeout,
-    Overflow,
-    Pipe,
-    Interrupted,
-    NoMem,
-    NotSupported,
-    Other,
+    NoSuchDescriptor,
+    RcGetMutFailed,
+    RcUnwrapFailed,
+    TransferAlreadyCompleted,
 }
 
-impl fmt::Debug for Error {
+impl Display for Error {
+    #[remain::check]
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Error::Success(_v) => write!(f, "Success (no error)"),
-            Error::IO => write!(f, "Input/output error"),
-            Error::InvalidParam => write!(f, "Invalid parameter"),
-            Error::Access => write!(f, "Access denied (insufficient permissions)"),
-            Error::NoDevice => write!(f, "No such device (it may have been disconnected)"),
-            Error::NotFound => write!(f, "Entity not found"),
-            Error::Busy => write!(f, "Resource busy"),
-            Error::Timeout => write!(f, "Operation timed out"),
-            Error::Overflow => write!(f, "Overflow"),
-            Error::Pipe => write!(f, "Pipe error"),
-            Error::Interrupted => write!(f, "System call interrupted (perhaps due to signal)"),
-            Error::NoMem => write!(f, "Insufficient memory"),
-            Error::NotSupported => write!(
-                f,
-                "Operation not supported or unimplemented on this platform"
-            ),
-            Error::Other => write!(f, "Other error"),
-        }
-    }
-}
+        use self::Error::*;
 
-impl From<bindings::libusb_error> for Error {
-    fn from(e: bindings::libusb_error) -> Self {
-        match e {
-            bindings::LIBUSB_ERROR_IO => Error::IO,
-            bindings::LIBUSB_ERROR_INVALID_PARAM => Error::InvalidParam,
-            bindings::LIBUSB_ERROR_ACCESS => Error::Access,
-            bindings::LIBUSB_ERROR_NO_DEVICE => Error::NoDevice,
-            bindings::LIBUSB_ERROR_NOT_FOUND => Error::NotFound,
-            bindings::LIBUSB_ERROR_BUSY => Error::Busy,
-            bindings::LIBUSB_ERROR_TIMEOUT => Error::Timeout,
-            bindings::LIBUSB_ERROR_OVERFLOW => Error::Overflow,
-            bindings::LIBUSB_ERROR_PIPE => Error::Pipe,
-            bindings::LIBUSB_ERROR_INTERRUPTED => Error::Interrupted,
-            bindings::LIBUSB_ERROR_NO_MEM => Error::NoMem,
-            bindings::LIBUSB_ERROR_NOT_SUPPORTED => Error::NotSupported,
-            bindings::LIBUSB_ERROR_OTHER => Error::Other,
-            // All possible errors are defined above, other values mean success,
-            // see libusb_get_device_list for example.
-            _ => Error::Success(e),
+        #[sorted]
+        match self {
+            DescriptorParse => write!(f, "parsing descriptors failed"),
+            DescriptorRead(e) => write!(f, "reading descriptors from device failed: {}", e),
+            FdCloneFailed(e) => write!(f, "File::try_clone() failed: {}", e),
+            InvalidActualLength(e) => write!(f, "invalid actual_length in URB: {}", e),
+            InvalidBufferLength(e) => write!(f, "invalid transfer buffer length: {}", e),
+            IoctlFailed(nr, e) => write!(f, "USB ioctl 0x{:x} failed: {}", nr, e),
+            NoDevice => write!(f, "Device has been removed"),
+            NoSuchDescriptor => write!(f, "Requested descriptor not found"),
+            RcGetMutFailed => write!(f, "Rc::get_mut failed"),
+            RcUnwrapFailed => write!(f, "Rc::try_unwrap failed"),
+            TransferAlreadyCompleted => write!(f, "attempted to cancel already-completed transfer"),
         }
     }
 }
 
 pub type Result<T> = std::result::Result<T, Error>;
 
-#[macro_export]
-macro_rules! try_libusb {
-    ($x:expr) => {
-        match Error::from($x as i32) {
-            Error::Success(e) => e,
-            err => return Err(err),
-        }
-    };
-}
+impl std::error::Error for Error {}