mod dpdu;
pub mod passthru;
#[cfg(unix)]
pub mod socketcan;
use std::sync::{Arc, Mutex};
use crate::channel::{CanChannel, IsoTPChannel};
pub type HardwareResult<T> = Result<T, HardwareError>;
pub trait Hardware {
fn create_iso_tp_channel(this: Arc<Mutex<Self>>) -> HardwareResult<Box<dyn IsoTPChannel>>;
fn create_can_channel(this: Arc<Mutex<Self>>) -> HardwareResult<Box<dyn CanChannel>>;
fn is_iso_tp_channel_open(&self) -> bool;
fn is_can_channel_open(&self) -> bool;
fn read_battery_voltage(&mut self) -> Option<f32>;
fn read_ignition_voltage(&mut self) -> Option<f32>;
fn get_info(&self) -> &HardwareInfo;
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct HardwareInfo {
pub name: String,
pub vendor: Option<String>,
pub device_fw_version: Option<String>,
pub api_version: Option<String>,
pub library_version: Option<String>,
pub library_location: Option<String>,
pub capabilities: HardwareCapabilities,
}
pub trait HardwareScanner<T: Hardware> {
fn list_devices(&self) -> Vec<HardwareInfo>;
fn open_device_by_index(&self, idx: usize) -> HardwareResult<Arc<Mutex<T>>>;
fn open_device_by_name(&self, name: &str) -> HardwareResult<Arc<Mutex<T>>>;
}
#[derive(Debug)]
pub enum HardwareError {
APIError {
code: u32,
desc: String,
},
ConflictingChannel,
ChannelNotSupported,
DeviceNotFound,
DeviceNotOpen,
LibLoadError(libloading::Error),
}
impl From<libloading::Error> for HardwareError {
fn from(err: libloading::Error) -> Self {
Self::LibLoadError(err)
}
}
impl std::fmt::Display for HardwareError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self {
HardwareError::APIError { code, desc } => write!(
f,
"Hardware API Error. Code {}, Description: {}",
code, desc
),
HardwareError::ConflictingChannel => {
write!(f, "Conflicting communication channel already open")
}
HardwareError::ChannelNotSupported => {
write!(f, "Channel type is not supported by hardware")
}
HardwareError::DeviceNotFound => write!(f, "Device not found"),
HardwareError::DeviceNotOpen => write!(f, "Hardware device not open"),
HardwareError::LibLoadError(e) => write!(f, "LibLoading error: {}", e),
}
}
}
impl std::error::Error for HardwareError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match &self {
HardwareError::LibLoadError(l) => Some(l),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct HardwareCapabilities {
pub iso_tp: bool,
pub can: bool,
pub kline: bool,
pub kline_kwp: bool,
pub sae_j1850: bool,
pub sci: bool,
pub ip: bool,
}