rdif-pinctrl 0.1.0

Driver Interface pin control definition.
Documentation
use alloc::{boxed::Box, string::String};
use core::fmt;

use crate::{FirmwareKind, FunctionId, GpioLineId, GroupId, PinId, io};

#[derive(thiserror::Error, Debug)]
pub enum PinctrlError {
    #[error("operation not supported")]
    NotSupported,
    #[error("firmware source is not supported: {0:?}")]
    UnsupportedFirmware(FirmwareKind),
    #[error("device is not available")]
    NotAvailable,
    #[error("invalid pin: {0:?}")]
    InvalidPin(PinId),
    #[error("invalid group: {0:?}")]
    InvalidGroup(GroupId),
    #[error("invalid function: {0:?}")]
    InvalidFunction(FunctionId),
    #[error("function {function:?} cannot mux group {group:?}")]
    InvalidMux {
        group: GroupId,
        function: FunctionId,
    },
    #[error("invalid GPIO line: {0:?}")]
    InvalidLine(GpioLineId),
    #[error("GPIO line is already requested: {0:?}")]
    LineBusy(GpioLineId),
    #[error("GPIO line is not requested: {0:?}")]
    LineNotRequested(GpioLineId),
    #[error("invalid pin configuration")]
    InvalidConfig,
    #[error("IRQ event overflow")]
    IrqEventOverflow,
    #[error("other error: {0}")]
    Other(Box<dyn core::error::Error>),
}

impl PartialEq for PinctrlError {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::NotSupported, Self::NotSupported)
            | (Self::NotAvailable, Self::NotAvailable)
            | (Self::InvalidConfig, Self::InvalidConfig)
            | (Self::IrqEventOverflow, Self::IrqEventOverflow) => true,
            (Self::UnsupportedFirmware(a), Self::UnsupportedFirmware(b)) => a == b,
            (Self::InvalidPin(a), Self::InvalidPin(b)) => a == b,
            (Self::InvalidGroup(a), Self::InvalidGroup(b)) => a == b,
            (Self::InvalidFunction(a), Self::InvalidFunction(b)) => a == b,
            (
                Self::InvalidMux {
                    group: a_group,
                    function: a_function,
                },
                Self::InvalidMux {
                    group: b_group,
                    function: b_function,
                },
            ) => a_group == b_group && a_function == b_function,
            (Self::InvalidLine(a), Self::InvalidLine(b))
            | (Self::LineBusy(a), Self::LineBusy(b))
            | (Self::LineNotRequested(a), Self::LineNotRequested(b)) => a == b,
            (Self::Other(_), Self::Other(_)) => false,
            _ => false,
        }
    }
}

impl Eq for PinctrlError {}

#[derive(Debug)]
struct PinctrlMessageError(String);

impl fmt::Display for PinctrlMessageError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(&self.0)
    }
}

impl core::error::Error for PinctrlMessageError {}

impl PinctrlError {
    pub fn other(message: impl Into<String>) -> Self {
        Self::Other(Box::new(PinctrlMessageError(message.into())))
    }
}

impl From<PinctrlError> for io::ErrorKind {
    fn from(value: PinctrlError) -> Self {
        match value {
            PinctrlError::NotSupported | PinctrlError::UnsupportedFirmware(_) => {
                io::ErrorKind::Unsupported
            }
            PinctrlError::NotAvailable => io::ErrorKind::NotAvailable,
            PinctrlError::InvalidPin(_)
            | PinctrlError::InvalidGroup(_)
            | PinctrlError::InvalidFunction(_)
            | PinctrlError::InvalidMux { .. }
            | PinctrlError::InvalidLine(_)
            | PinctrlError::InvalidConfig => io::ErrorKind::InvalidData,
            PinctrlError::LineBusy(_) => io::ErrorKind::Interrupted,
            PinctrlError::LineNotRequested(_) | PinctrlError::IrqEventOverflow => {
                io::ErrorKind::Other(Box::new(value))
            }
            PinctrlError::Other(error) => io::ErrorKind::Other(error),
        }
    }
}