use std::fmt::{self, Debug, Display, Formatter};
use std::fs::File;
use std::io::{BufRead, BufReader};
use error::{Error, ErrorKind};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum Model {
Pi1A,
Pi1APlus,
Pi1B,
Pi1BPlus,
Pi2B,
Pi3B,
Pi3BPlus,
PiZero,
PiZeroW,
PiCm1,
PiCm3
}
impl Display for Model {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let model = match *self {
Model::Pi1A => "Raspberry Pi 1 Model A",
Model::Pi1APlus => "Raspberry Pi 1 Model A+",
Model::Pi1B => "Raspberry Pi 1 Model B",
Model::Pi1BPlus => "Raspberry Pi 1 Model B+",
Model::Pi2B => "Raspberry Pi 2 Model B",
Model::Pi3B => "Raspberry Pi 3 Model B",
Model::Pi3BPlus => "Raspberry Pi 3 Model B+",
Model::PiZero => "Raspberry Pi Zero",
Model::PiZeroW => "Raspberry Pi Zero W",
Model::PiCm1 => "Raspberry Pi Compute Module 1",
Model::PiCm3 => "Raspberry Pi Compute Module 3"
};
f.write_str(model)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum Mfg {
Unknown,
Sony,
Qisda,
Egoman,
Embest,
SonyJp
}
impl Display for Mfg {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Debug::fmt(self, f)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum Chip {
Bcm2835,
Bcm2836,
Bcm2837
}
impl Display for Chip {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Debug::fmt(self, f)
}
}
#[derive(Debug)]
pub struct System {
pub model: Model,
pub manufacturer: Mfg,
pub chip: Chip,
pub memory: usize
}
impl System {
pub fn detect() -> Result<System, Error> {
let f = BufReader::new(File::open("/proc/cpuinfo")?);
let revision = f.lines()
.collect::<Result<Vec<String>, _>>()?.into_iter()
.find(|s| s.starts_with("Revision"))
.ok_or(Error::new(ErrorKind::UnsupportedSystem))?
.split(": ").nth(1)
.ok_or(Error::new(ErrorKind::UnsupportedSystem))?
.to_string();
let revision = u64::from_str_radix(&revision, 16).unwrap();
let (model, manufacturer, chip, memory) = match revision {
0x000002 => (Model::Pi1B, Mfg::Unknown, Chip::Bcm2835, 256),
0x000003 => (Model::Pi1B, Mfg::Unknown, Chip::Bcm2835, 256),
0x000004 => (Model::Pi1B, Mfg::Sony, Chip::Bcm2835, 256),
0x000005 => (Model::Pi1B, Mfg::Qisda, Chip::Bcm2835, 256),
0x000006 => (Model::Pi1B, Mfg::Egoman, Chip::Bcm2835, 256),
0x000007 => (Model::Pi1A, Mfg::Egoman, Chip::Bcm2835, 256),
0x000008 => (Model::Pi1A, Mfg::Sony, Chip::Bcm2835, 256),
0x000009 => (Model::Pi1A, Mfg::Qisda, Chip::Bcm2835, 256),
0x00000d => (Model::Pi1B, Mfg::Egoman, Chip::Bcm2835, 512),
0x00000e => (Model::Pi1B, Mfg::Sony, Chip::Bcm2835, 512),
0x00000f => (Model::Pi1B, Mfg::Qisda, Chip::Bcm2835, 512),
0x000010 => (Model::Pi1BPlus, Mfg::Sony, Chip::Bcm2835, 512),
0x000011 => (Model::PiCm1, Mfg::Sony, Chip::Bcm2835, 512),
0x000012 => (Model::Pi1APlus, Mfg::Sony, Chip::Bcm2835, 256),
0x000013 => (Model::Pi1BPlus, Mfg::Embest, Chip::Bcm2835, 512),
0x000014 => (Model::PiCm1, Mfg::Embest, Chip::Bcm2835, 512),
0x000015 => (Model::Pi1APlus, Mfg::Embest, Chip::Bcm2835, 256),
0xa01040 => (Model::Pi2B, Mfg::Sony, Chip::Bcm2836, 1024),
0xa01041 => (Model::Pi2B, Mfg::Sony, Chip::Bcm2836, 1024),
0xa21041 => (Model::Pi2B, Mfg::Embest, Chip::Bcm2836, 1024),
0xa22042 => (Model::Pi2B, Mfg::Embest, Chip::Bcm2837, 1024),
0x900021 => (Model::Pi1APlus, Mfg::Sony, Chip::Bcm2835, 512),
0x900032 => (Model::Pi1BPlus, Mfg::Sony, Chip::Bcm2835, 512),
0x900092 => (Model::PiZero, Mfg::Sony, Chip::Bcm2835, 512),
0x900093 => (Model::PiZero, Mfg::Sony, Chip::Bcm2835, 512),
0x920093 => (Model::PiZero, Mfg::Embest, Chip::Bcm2835, 512),
0x9000c1 => (Model::PiZeroW, Mfg::Sony, Chip::Bcm2835, 512),
0xa02082 => (Model::Pi3B, Mfg::Sony, Chip::Bcm2837, 1024),
0xa020a0 => (Model::PiCm3, Mfg::Sony, Chip::Bcm2837, 1024),
0xa22082 => (Model::Pi3B, Mfg::Embest, Chip::Bcm2837, 1024),
0xa32082 => (Model::Pi3B, Mfg::SonyJp, Chip::Bcm2837, 1024),
0xa020d3 => (Model::Pi3BPlus, Mfg::Sony, Chip::Bcm2837, 1024),
_ => return Err(Error::new(ErrorKind::UnsupportedSystem)),
};
Ok(System {
model,
manufacturer,
chip,
memory
})
}
pub fn peripheral_offset(&self) -> usize {
match self.chip {
Chip::Bcm2835 => 0x2000_0000,
Chip::Bcm2836 => 0x3f00_0000,
Chip::Bcm2837 => 0x3f00_0000
}
}
}