use std::{
borrow::BorrowMut,
sync::{Arc, Mutex},
};
use crate::hardware::HardwareError;
pub type ChannelResult<T> = Result<T, ChannelError>;
#[derive(Debug)]
pub enum ChannelError {
IOError(std::io::Error),
WriteTimeout,
ReadTimeout,
BufferEmpty,
BufferFull,
UnsupportedRequest,
InterfaceNotOpen,
HardwareError(HardwareError),
NotOpen,
ConfigurationError,
}
impl std::fmt::Display for ChannelError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ChannelError::IOError(e) => write!(f, "IO error: {}", e),
ChannelError::UnsupportedRequest => write!(f, "unsupported channel request"),
ChannelError::ReadTimeout => write!(f, "timeout reading from channel"),
ChannelError::WriteTimeout => write!(f, "timeout writing to channel"),
ChannelError::BufferFull => write!(f, "channel's Transmit buffer is full"),
ChannelError::BufferEmpty => write!(f, "channel's Receive buffer is empty"),
ChannelError::InterfaceNotOpen => write!(f, "channel's interface is not open"),
ChannelError::HardwareError(err) => write!(f, "Channel hardware error: {}", err),
ChannelError::NotOpen => write!(f, "Channel has not been opened"),
ChannelError::ConfigurationError => {
write!(f, "Channel opened prior to being configured")
}
}
}
}
impl From<HardwareError> for ChannelError {
fn from(err: HardwareError) -> Self {
Self::HardwareError(err)
}
}
impl std::error::Error for ChannelError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
if let Self::IOError(io_err) = self {
Some(io_err)
} else if let Self::HardwareError(err) = self {
Some(err)
} else {
None
}
}
}
pub trait PayloadChannel: Send + Sync {
fn open(&mut self) -> ChannelResult<()>;
fn close(&mut self) -> ChannelResult<()>;
fn set_ids(&mut self, send: u32, recv: u32) -> ChannelResult<()>;
fn read_bytes(&mut self, timeout_ms: u32) -> ChannelResult<Vec<u8>>;
fn write_bytes(&mut self, addr: u32, buffer: &[u8], timeout_ms: u32) -> ChannelResult<()>;
fn read_write_bytes(
&mut self,
addr: u32,
buffer: &[u8],
write_timeout_ms: u32,
read_timeout_ms: u32,
) -> ChannelResult<Vec<u8>> {
self.write_bytes(addr, buffer, write_timeout_ms)?;
self.read_bytes(read_timeout_ms)
}
fn clear_rx_buffer(&mut self) -> ChannelResult<()>;
fn clear_tx_buffer(&mut self) -> ChannelResult<()>;
}
pub trait IsoTPChannel: PayloadChannel {
fn set_iso_tp_cfg(&mut self, cfg: IsoTPSettings) -> ChannelResult<()>;
}
pub trait PacketChannel<T: Packet>: Send + Sync {
fn open(&mut self) -> ChannelResult<()>;
fn close(&mut self) -> ChannelResult<()>;
fn write_packets(&mut self, packets: Vec<T>, timeout_ms: u32) -> ChannelResult<()>;
fn read_packets(&mut self, max: usize, timeout_ms: u32) -> ChannelResult<Vec<T>>;
fn clear_rx_buffer(&mut self) -> ChannelResult<()>;
fn clear_tx_buffer(&mut self) -> ChannelResult<()>;
}
pub trait CanChannel: PacketChannel<CanFrame> {
fn set_can_cfg(&mut self, baud: u32, use_extended: bool) -> ChannelResult<()>;
}
impl<T: PayloadChannel + ?Sized> PayloadChannel for Box<T> {
fn open(&mut self) -> ChannelResult<()> {
T::open(self)
}
fn close(&mut self) -> ChannelResult<()> {
T::close(self)
}
fn set_ids(&mut self, send: u32, recv: u32) -> ChannelResult<()> {
T::set_ids(self, send, recv)
}
fn read_bytes(&mut self, timeout_ms: u32) -> ChannelResult<Vec<u8>> {
T::read_bytes(self, timeout_ms)
}
fn write_bytes(&mut self, addr: u32, buffer: &[u8], timeout_ms: u32) -> ChannelResult<()> {
T::write_bytes(self, addr, buffer, timeout_ms)
}
fn clear_rx_buffer(&mut self) -> ChannelResult<()> {
T::clear_rx_buffer(self)
}
fn clear_tx_buffer(&mut self) -> ChannelResult<()> {
T::clear_tx_buffer(self)
}
}
impl<T: IsoTPChannel + ?Sized> IsoTPChannel for Box<T> {
fn set_iso_tp_cfg(&mut self, cfg: IsoTPSettings) -> ChannelResult<()> {
T::set_iso_tp_cfg(self, cfg)
}
}
impl<X: Packet, T: PacketChannel<X> + ?Sized> PacketChannel<X> for Box<T> {
fn open(&mut self) -> ChannelResult<()> {
T::open(self)
}
fn close(&mut self) -> ChannelResult<()> {
T::close(self)
}
fn write_packets(&mut self, packets: Vec<X>, timeout_ms: u32) -> ChannelResult<()> {
T::write_packets(self, packets, timeout_ms)
}
fn read_packets(&mut self, max: usize, timeout_ms: u32) -> ChannelResult<Vec<X>> {
T::read_packets(self, max, timeout_ms)
}
fn clear_rx_buffer(&mut self) -> ChannelResult<()> {
T::clear_rx_buffer(self)
}
fn clear_tx_buffer(&mut self) -> ChannelResult<()> {
T::clear_tx_buffer(self)
}
}
impl<T: CanChannel + ?Sized> CanChannel for Box<T> {
fn set_can_cfg(&mut self, baud: u32, use_extended: bool) -> ChannelResult<()> {
T::set_can_cfg(self, baud, use_extended)
}
}
impl<T: PayloadChannel + ?Sized> PayloadChannel for Arc<Mutex<T>> {
fn open(&mut self) -> ChannelResult<()> {
T::open(self.lock()?.borrow_mut())
}
fn close(&mut self) -> ChannelResult<()> {
T::close(self.lock()?.borrow_mut())
}
fn set_ids(&mut self, send: u32, recv: u32) -> ChannelResult<()> {
T::set_ids(self.lock()?.borrow_mut(), send, recv)
}
fn read_bytes(&mut self, timeout_ms: u32) -> ChannelResult<Vec<u8>> {
T::read_bytes(self.lock()?.borrow_mut(), timeout_ms)
}
fn write_bytes(&mut self, addr: u32, buffer: &[u8], timeout_ms: u32) -> ChannelResult<()> {
T::write_bytes(self.lock()?.borrow_mut(), addr, buffer, timeout_ms)
}
fn clear_rx_buffer(&mut self) -> ChannelResult<()> {
T::clear_rx_buffer(self.lock()?.borrow_mut())
}
fn clear_tx_buffer(&mut self) -> ChannelResult<()> {
T::clear_tx_buffer(self.lock()?.borrow_mut())
}
}
impl<T: IsoTPChannel + ?Sized> IsoTPChannel for Arc<Mutex<T>> {
fn set_iso_tp_cfg(&mut self, cfg: IsoTPSettings) -> ChannelResult<()> {
T::set_iso_tp_cfg(self.lock()?.borrow_mut(), cfg)
}
}
impl<X: Packet, T: PacketChannel<X> + ?Sized> PacketChannel<X> for Arc<Mutex<T>> {
fn open(&mut self) -> ChannelResult<()> {
T::open(self.lock()?.borrow_mut())
}
fn close(&mut self) -> ChannelResult<()> {
T::close(self.lock()?.borrow_mut())
}
fn write_packets(&mut self, packets: Vec<X>, timeout_ms: u32) -> ChannelResult<()> {
T::write_packets(self.lock()?.borrow_mut(), packets, timeout_ms)
}
fn read_packets(&mut self, max: usize, timeout_ms: u32) -> ChannelResult<Vec<X>> {
T::read_packets(self.lock()?.borrow_mut(), max, timeout_ms)
}
fn clear_rx_buffer(&mut self) -> ChannelResult<()> {
T::clear_rx_buffer(self.lock()?.borrow_mut())
}
fn clear_tx_buffer(&mut self) -> ChannelResult<()> {
T::clear_tx_buffer(self.lock()?.borrow_mut())
}
}
impl<T: CanChannel + ?Sized> CanChannel for Arc<Mutex<T>> {
fn set_can_cfg(&mut self, baud: u32, use_extended: bool) -> ChannelResult<()> {
T::set_can_cfg(self.lock()?.borrow_mut(), baud, use_extended)
}
}
pub trait Packet: Send + Sync + Sized {
fn get_address(&self) -> u32;
fn get_data(&self) -> &[u8];
fn set_address(&mut self, address: u32);
fn set_data(&mut self, data: &[u8]);
}
#[derive(Debug, Copy, Clone)]
pub struct CanFrame {
id: u32,
dlc: u8,
data: [u8; 8],
ext: bool,
}
impl CanFrame {
pub fn new(id: u32, data: &[u8], is_ext: bool) -> Self {
let max = std::cmp::min(8, data.len());
let mut tmp = [0u8; 8];
tmp[0..max].copy_from_slice(&data[0..max]);
Self {
id,
dlc: max as u8,
data: tmp,
ext: is_ext,
}
}
pub fn is_extended(&self) -> bool {
self.ext
}
}
impl Packet for CanFrame {
fn get_address(&self) -> u32 {
self.id
}
fn get_data(&self) -> &[u8] {
&self.data[0..self.dlc as usize]
}
fn set_address(&mut self, address: u32) {
self.id = address
}
fn set_data(&mut self, data: &[u8]) {
let max = std::cmp::min(8, data.len());
self.data[0..max].copy_from_slice(&data[0..max]);
self.dlc = max as u8;
}
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct IsoTPSettings {
pub block_size: u8,
pub st_min: u8,
pub extended_addressing: bool,
pub pad_frame: bool,
pub can_speed: u32,
pub can_use_ext_addr: bool,
}
impl Default for IsoTPSettings {
fn default() -> Self {
Self {
block_size: 8,
st_min: 20,
extended_addressing: false,
pad_frame: true,
can_speed: 500_000,
can_use_ext_addr: false,
}
}
}