1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use std::fmt;
use std::error::Error as StdError;
use std::result::Result as StdResult;

use libc::c_int;
use libusb::*;

/// A result of a function that may return a `Error`.
pub type Result<T> = StdResult<T, Error>;


/// Errors returned by the `libusb` library.
#[derive(Debug)]
pub enum Error {
    /// Success (no error).
    Success,

    /// Input/output error.
    Io,

    /// Invalid parameter.
    InvalidParam,

    /// Access denied (insufficient permissions).
    Access,

    /// No such device (it may have been disconnected).
    NoDevice,

    /// Entity not found.
    NotFound,

    /// Resource busy.
    Busy,

    /// Operation timed out.
    Timeout,

    /// Overflow.
    Overflow,

    /// Pipe error.
    Pipe,

    /// System call interrupted (perhaps due to signal).
    Interrupted,

    /// Insufficient memory.
    NoMem,

    /// Operation not supported or unimplemented on this platform.
    NotSupported,

    /// Other error.
    Other
}

impl Error {
    /// Returns a description of an error suitable for display to an end user.
    pub fn strerror(&self) -> &'static str {
        match *self {
            Error::Success      => "Success",
            Error::Io           => "Input/Output Error",
            Error::InvalidParam => "Invalid parameter",
            Error::Access       => "Access denied (insufficient permissions)",
            Error::NoDevice     => "No such device (it may have been disconnected)",
            Error::NotFound     => "Entity not found",
            Error::Busy         => "Resource busy",
            Error::Timeout      => "Operation timed out",
            Error::Overflow     => "Overflow",
            Error::Pipe         => "Pipe error",
            Error::Interrupted  => "System call interrupted (perhaps due to signal)",
            Error::NoMem        => "Insufficient memory",
            Error::NotSupported => "Operation not supported or unimplemented on this platform",
            Error::Other        => "Other error",
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> StdResult<(), fmt::Error> {
        fmt.write_str(self.strerror())
    }
}

impl StdError for Error {
    fn description(&self) -> &'static str {
        self.strerror()
    }
}


#[doc(hidden)]
pub fn from_libusb(err: c_int) -> Error {
    match err {
        LIBUSB_SUCCESS             => Error::Success,
        LIBUSB_ERROR_IO            => Error::Io,
        LIBUSB_ERROR_INVALID_PARAM => Error::InvalidParam,
        LIBUSB_ERROR_ACCESS        => Error::Access,
        LIBUSB_ERROR_NO_DEVICE     => Error::NoDevice,
        LIBUSB_ERROR_NOT_FOUND     => Error::NotFound,
        LIBUSB_ERROR_BUSY          => Error::Busy,
        LIBUSB_ERROR_TIMEOUT       => Error::Timeout,
        LIBUSB_ERROR_OVERFLOW      => Error::Overflow,
        LIBUSB_ERROR_PIPE          => Error::Pipe,
        LIBUSB_ERROR_INTERRUPTED   => Error::Interrupted,
        LIBUSB_ERROR_NO_MEM        => Error::NoMem,
        LIBUSB_ERROR_NOT_SUPPORTED => Error::NotSupported,
        LIBUSB_ERROR_OTHER | _     => Error::Other,
    }
}

#[doc(hidden)]
macro_rules! try_unsafe {
    ($x:expr) => {
        match unsafe { $x } {
            0 => (),
            err => return Err($crate::error::from_libusb(err)),
        }
    }
}