blob: 083fde6e155fcba34c2e4acf9ba0e0d8c6252170 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use thiserror::Error;
use super::Capability;
/// Contains all the errors that any method on the `Transport` trait could generate. This
/// struct is serializable, such that it can be transmitted across a network for instance as
/// part of the session proxy functionality.
#[derive(Error, Debug, Serialize, Deserialize)]
pub enum TransportError {
#[error("USB device did not match")]
NoMatch,
#[error("Found no USB device")]
NoDevice,
#[error("Found multiple USB devices, use --serial")]
MultipleDevices,
#[error("USB error: {0}")]
UsbGenericError(String),
#[error("Error opening USB device: {0}")]
UsbOpenError(String),
#[error("Transport does not support {0:?}")]
InvalidInterface(TransportInterfaceType),
#[error("Transport does not support {0:?} instance {1}")]
InvalidInstance(TransportInterfaceType, String),
#[error("Encountered non-unicode device path")]
UnicodePathError,
#[error("Error opening {0}: {1}")]
OpenError(String, String),
#[error("Error reading from {0}: {1}")]
ReadError(String, String),
#[error("FPGA programming failed: {0}")]
FpgaProgramFailed(String),
#[error("Invalid pin strapping name \"{0}\"")]
InvalidStrappingName(String),
#[error("Transport does not support the requested operation")]
UnsupportedOperation,
#[error("Error communicating with FTDI: {0}")]
FtdiError(String),
#[error("Error communicating with debugger: {0}")]
CommunicationError(String),
#[error("Proxy unable to resolve `{0}`: {1}")]
ProxyLookupError(String, String),
#[error("Proxy unable to connect to `{0}`: {1}")]
ProxyConnectError(String, String),
#[error("Proxy communication error: {0}")]
ProxyCommunicationError(#[from] crate::transport::proxy::ProxyError),
#[error("Requested capabilities {0:?}, but capabilities {1:?} are supplied")]
MissingCapabilities(Capability, Capability),
// Include sub-enums for the various sub-traits of Tranport.
#[error("GPIO error: {0}")]
GpioError(#[from] crate::io::gpio::GpioError),
#[error("UART error: {0}")]
UartError(#[from] crate::io::uart::UartError),
#[error("SPI error: {0}")]
SpiError(#[from] crate::io::spi::SpiError),
#[error("SPI error: {0}")]
I2cError(#[from] crate::io::i2c::I2cError),
}
/// Enum value used by `TransportError::InvalidInstance`.
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub enum TransportInterfaceType {
Gpio,
Uart,
Spi,
I2c,
}
/// Return type to be used in `Transport` methods.
pub type Result<T> = anyhow::Result<T, TransportError>;
/// Convenience macro to be used in implementations of `Transport`.
#[macro_export]
macro_rules! bail {
($err:expr $(,)?) => {
return Err($err.into())
};
}
/// Convenience macro to be used in implementations of `Transport`.
#[macro_export]
macro_rules! ensure {
($cond:expr, $err:expr $(,)?) => {
if !$cond {
return Err($err.into());
}
};
}
/// Function for conveniently wrapping (the flat string representation of) an anyhow::Error in a
/// TransportError.
///
/// Example usage:
/// serialport::available_ports().wrap(UartError::EnumerationError)?;
pub trait WrapInTransportError<T> {
fn wrap<S: Into<TransportError>>(self, kind: impl FnOnce(String) -> S) -> Result<T>;
}
impl<T, E: ToString> WrapInTransportError<T> for anyhow::Result<T, E> {
fn wrap<S: Into<TransportError>>(self, kind: impl FnOnce(String) -> S) -> Result<T> {
self.map_err(|e| kind(e.to_string()).into())
}
}