use crate::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Model {
ASM2464PD,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Command {
ConfigRead = 0xe0,
ConfigWrite = 0xe1,
FlashRead = 0xe2,
FlashWrite = 0xe3,
Read = 0xe4,
Write = 0xe5,
Reload = 0xe8,
}
pub trait Backend {
fn model(&self) -> Model;
fn transfer(&mut self, cdb: &[u8]) -> Result<(), Error>;
fn transfer_to_device(&mut self, cdb: &[u8], data: &[u8]) -> Result<(), Error>;
fn transfer_from_device(&mut self, cdb: &[u8], data: &mut [u8]) -> Result<(), Error>;
}
pub struct Device {
backend: Box<dyn Backend>,
}
pub struct FWVersion {
day: u8,
month: u8,
year: u8,
major: u8,
minor: u8,
patch: u8,
}
impl Display for FWVersion {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{:02x}{:02x}{:02x}_{:02x}_{:02x}_{:02x}",
self.year, self.month, self.day, self.major, self.minor, self.patch
)
}
}
impl Device {
pub fn new(backend: Box<dyn Backend>) -> Self {
Self { backend }
}
pub fn read(&mut self, mut addr: u32, bfr: &mut [u8]) -> Result<(), Error> {
let mut cdb = [0_u8; 6];
addr &= 0x01ffff;
addr |= 0x500000;
cdb[0] = Command::Read as u8;
cdb[1] = bfr.len() as u8;
cdb[2] = (addr >> 16) as u8;
cdb[3] = (addr >> 8) as u8;
cdb[4] = addr as u8;
cdb[5] = 0x00;
self.backend.transfer_from_device(&cdb, bfr)
}
pub fn write(&mut self, mut addr: u32, value: u8) -> Result<(), Error> {
let mut cdb = [0_u8; 6];
addr &= 0x01ffff;
addr |= 0x500000;
cdb[0] = Command::Write as u8;
cdb[1] = value;
cdb[2] = (addr >> 16) as u8;
cdb[3] = (addr >> 8) as u8;
cdb[4] = addr as u8;
cdb[5] = 0x00;
self.backend.transfer(&cdb)
}
pub fn read_fw_version(&mut self) -> Result<FWVersion, Error> {
let mut bfr = [0_u8; 6];
self.read(0x07f0, &mut bfr)?;
Ok(FWVersion {
year: bfr[0],
month: bfr[1],
day: bfr[2],
major: bfr[3],
minor: bfr[4],
patch: bfr[5],
})
}
pub fn read_config(&mut self) -> Result<[u8; 0x80], Error> {
let cdb = [Command::ConfigRead as u8, 0x50, 0x00, 0x00, 0x00, 0x00];
let mut bfr = [0_u8; 0x80];
self.backend.transfer_from_device(&cdb, &mut bfr)?;
Ok(bfr)
}
pub fn read_firmware(&mut self, bfr: &mut [u8]) -> Result<(), Error> {
let mut cdb = [Command::FlashRead as u8, 0x50, 0x00, 0x00, 0x00, 0x00];
cdb[2] = (bfr.len() >> 16) as u8;
cdb[3] = (bfr.len() >> 8) as u8;
cdb[4] = bfr.len() as u8;
self.backend.transfer_from_device(&cdb, bfr)?;
Ok(())
}
}