use std::io;
use std::path::PathBuf;
#[non_exhaustive]
#[derive(Debug)]
pub enum I2cDevError {
ConnectorNotFound {
connector: String,
},
ConnectorHasNoDdcAdapter {
connector: String,
},
DdcAdapterIndexUnparseable {
symlink_target: PathBuf,
},
DeviceOpenFailed {
path: PathBuf,
source: io::Error,
},
Transaction(I2cTransactionError),
}
#[non_exhaustive]
#[derive(Debug)]
pub struct I2cTransactionError {
pub phase: MessagePhase,
pub kind: I2cErrorKind,
}
#[non_exhaustive]
#[derive(Debug)]
pub enum MessagePhase {
Write {
register: u8,
},
Read {
register: u8,
},
}
#[non_exhaustive]
#[derive(Debug)]
pub enum I2cErrorKind {
AddressNack,
DataNack,
ArbitrationLost,
ClockStretchTimeout,
BusBusy,
BusProtocolError,
AdapterGone,
Unknown {
errno: i32,
},
}
impl std::fmt::Display for I2cDevError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ConnectorNotFound { connector } => {
write!(f, "DRM connector not found in sysfs: {connector}")
}
Self::ConnectorHasNoDdcAdapter { connector } => {
write!(
f,
"connector {connector} has no DDC adapter (no sink attached, or not an HDMI port)"
)
}
Self::DdcAdapterIndexUnparseable { symlink_target } => {
write!(
f,
"DDC symlink target does not contain a recognizable adapter index: {}",
symlink_target.display()
)
}
Self::DeviceOpenFailed { path, .. } => {
write!(f, "failed to open I²C device: {}", path.display())
}
Self::Transaction(e) => write!(f, "I²C transaction failed: {e}"),
}
}
}
impl std::error::Error for I2cDevError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::DeviceOpenFailed { source, .. } => Some(source),
Self::Transaction(e) => Some(e),
_ => None,
}
}
}
impl std::fmt::Display for I2cTransactionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let phase = match &self.phase {
MessagePhase::Write { register } => format!("write phase (register 0x{register:02x})"),
MessagePhase::Read { register } => format!("read phase (register 0x{register:02x})"),
};
write!(f, "{phase}: {:?}", self.kind)
}
}
impl std::error::Error for I2cTransactionError {}
#[cfg(test)]
#[path = "error_tests.rs"]
mod tests;