ch347_rs 0.2.1

ch347 for rust
Documentation
mod eon_silicon;
mod macronix;
mod winbond;

use std::fmt;

use super::{RegReadRet, Register, RegisterAccess, RegisterItem, SpiDrive, SpiFlash};

type JedecIdParser = fn(vendor: &'static Vendor, data: (u8, u8)) -> Option<Chip>;

// #[derive(Debug)]
pub struct Vendor {
    pub name: &'static str,
    pub id: u8,
    pub parser: JedecIdParser,
    pub reg_defines: Option<&'static [Register]>,
}

impl Vendor {
    pub fn check_support_uid(&self) -> Result<&'static Register, &'static str> {
        if let None = self.reg_defines {
            return Err("Not define Registers");
        }

        let result = self
            .reg_defines
            .unwrap()
            .iter()
            .find(|item| item.name.eq("unique_id"));

        let result = match result {
            None => return Err("Not support UniqueID"),
            Some(a) => a,
        };

        Ok(result)
    }

    pub fn read_uid(&self, spi_flash: &SpiFlash<dyn SpiDrive>) -> Result<Vec<u8>, &'static str> {
        let uid_reg = self.check_support_uid()?;

        let result = (uid_reg.reader)(spi_flash)?;

        if let RegReadRet::Muti(buf) = result {
            return Ok(buf);
        }

        panic!();
    }
}

#[derive(Debug, PartialEq, Eq)]
pub enum Capacity {
    C05,
    C10,
    C20,
    C40,
    C80,
    C16,
    C32,
    C64,
    C128,
    C256,
}

impl Into<usize> for Capacity {
    fn into(self) -> usize {
        match self {
            Capacity::C05 => 1024 * 64,
            Capacity::C10 => 1024 * 128,
            Capacity::C20 => 1024 * 256,
            Capacity::C40 => 1024 * 512,
            Capacity::C80 => 1024 * 1024 * 1,
            Capacity::C16 => 1024 * 1024 * 2,
            Capacity::C32 => 1024 * 1024 * 4,
            Capacity::C64 => 1024 * 1024 * 8,
            Capacity::C128 => 1024 * 1024 * 16,
            Capacity::C256 => 1024 * 1024 * 32,
        }
    }
}

impl fmt::Display for Capacity {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{}",
            match self {
                Capacity::C05 => "64 KB",
                Capacity::C10 => "128 KB",
                Capacity::C20 => "256 KB",
                Capacity::C40 => "512 KB",
                Capacity::C80 => "1 MB",
                Capacity::C16 => "2 MB",
                Capacity::C32 => "4 MB",
                Capacity::C64 => "8 MB",
                Capacity::C128 => "16 MB",
                Capacity::C256 => "32 MB",
            }
        )
    }
}

// #[derive(Debug)]
pub struct Chip {
    pub name: String,
    pub vendor: &'static Vendor,
    pub capacity: Capacity,
}

const JEDEC_ID_LIST: [Vendor; 3] = [
    Vendor {
        name: "Eon Silicon",
        id: 0x1C,
        parser: eon_silicon::parse_jedec_id,
        reg_defines: Some(&eon_silicon::REGISTER_DEFINES),
    },
    Vendor {
        name: "Macronix (MX)",
        id: 0xC2,
        parser: macronix::parse_jedec_id,
        reg_defines: Some(&macronix::REGISTER_DEFINES),
    },
    Vendor {
        name: "Winbond (ex Nexcom)",
        id: 0xEF,
        parser: winbond::parse_jedec_id,
        reg_defines: Some(&winbond::REGISTER_DEFINES),
    },
];

#[test]
pub fn test_parse_jedec_id() {
    assert!(parse_jedec_id(&[0xFF, 0xFF, 0xFF]).is_none());
    assert!(parse_jedec_id(&[0x00, 0x00, 0x00]).is_none());
    assert!(parse_jedec_id(&[]).is_none());
}

pub fn parse_jedec_id(buf: &[u8]) -> Option<Chip> {
    if buf.len() < 3 {
        return None;
    }

    let vendor = JEDEC_ID_LIST.iter().find(|&i| i.id == buf[0])?;

    (vendor.parser)(vendor, (buf[1], buf[2]))
}