hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
#[derive(Copy, Clone, PartialEq)]
pub enum SensorKind {
    Accelerometer,
    Gyroscope,
    Magnetometer,
    Barometer,
    Proximity,
    Light,
    Imu,
    Temperature,
    Humidity,
    Gravity,
    Unknown,
}

#[derive(Copy, Clone)]
pub struct SensorDevice {
    pub kind: SensorKind,
    pub reg_base: u64,
    pub irq: u32,
    pub compat: [u8; 64],
    pub compat_len: usize,
}

pub fn detect(out: &mut [SensorDevice]) -> usize {
    if out.is_empty() {
        return 0;
    }
    scan_dt(out)
}

fn scan_dt(out: &mut [SensorDevice]) -> usize {
    let mut blob = [0u8; 4096];
    let blen = crate::firmware::devicetree::load_fdt_blob(&mut blob);
    if blen < 40 {
        return 0;
    }
    let mut entries = [crate::firmware::devicetree::DtDeviceEntry {
        name: [0u8; 64],
        name_len: 0,
        reg_base: 0,
        reg_size: 0,
        irq: 0,
        compatible: [0u8; 128],
        compatible_len: 0,
    }; 64];
    let count = crate::firmware::devicetree::enumerate_devices(&blob[..blen], &mut entries);
    let mut found = 0usize;
    let mut i = 0usize;
    while i < count && found < out.len() {
        let compat = &entries[i].compatible[..entries[i].compatible_len];
        let kind = classify_sensor(compat, &entries[i].name[..entries[i].name_len]);
        if !matches!(kind, SensorKind::Unknown) {
            let mut compat_buf = [0u8; 64];
            let clen = copy_min(compat, &mut compat_buf);
            out[found] = SensorDevice {
                kind,
                reg_base: entries[i].reg_base,
                irq: entries[i].irq,
                compat: compat_buf,
                compat_len: clen,
            };
            found += 1;
        }
        i += 1;
    }
    found
}

fn classify_sensor(compat: &[u8], name: &[u8]) -> SensorKind {
    if contains(compat, b"mpu6050")
        || contains(compat, b"mpu6500")
        || contains(compat, b"mpu9250")
        || contains(compat, b"icm20")
        || contains(compat, b"bmi160")
        || contains(compat, b"bmi270")
        || contains(compat, b"lsm6ds")
        || contains(name, b"imu")
    {
        return SensorKind::Imu;
    }
    if contains(compat, b"bma")
        || contains(compat, b"lis3dh")
        || contains(compat, b"lis2dh")
        || contains(compat, b"kxtj")
        || contains(compat, b"adxl")
        || contains(compat, b"mc3")
        || contains(name, b"accel")
    {
        return SensorKind::Accelerometer;
    }
    if contains(compat, b"l3g") || contains(compat, b"bmg") || contains(name, b"gyro") {
        return SensorKind::Gyroscope;
    }
    if contains(compat, b"ak8963")
        || contains(compat, b"ak09911")
        || contains(compat, b"mmc5603")
        || contains(compat, b"hmc5883")
        || contains(compat, b"bmm150")
        || contains(name, b"magn")
    {
        return SensorKind::Magnetometer;
    }
    if contains(compat, b"bmp")
        || contains(compat, b"ms5611")
        || contains(compat, b"lps22")
        || contains(compat, b"hp206c")
        || contains(name, b"baro")
    {
        return SensorKind::Barometer;
    }
    if contains(compat, b"stk3")
        || contains(compat, b"apds9")
        || contains(compat, b"vcnl4")
        || contains(name, b"prox")
    {
        return SensorKind::Proximity;
    }
    if contains(compat, b"tsl2")
        || contains(compat, b"bh1750")
        || contains(compat, b"veml")
        || contains(compat, b"ltr5")
        || contains(name, b"light")
        || contains(name, b"als")
    {
        return SensorKind::Light;
    }
    if contains(compat, b"tmp1")
        || contains(compat, b"lm75")
        || contains(compat, b"aht")
        || contains(name, b"temp")
    {
        return SensorKind::Temperature;
    }
    if contains(compat, b"hdc1")
        || contains(compat, b"sht")
        || contains(compat, b"si7021")
        || contains(name, b"humid")
    {
        return SensorKind::Humidity;
    }
    SensorKind::Unknown
}

fn copy_min(src: &[u8], dst: &mut [u8; 64]) -> usize {
    let n = if src.len() < 64 { src.len() } else { 64 };
    let mut i = 0usize;
    while i < n {
        dst[i] = src[i];
        i += 1;
    }
    n
}

fn contains(haystack: &[u8], needle: &[u8]) -> bool {
    if needle.len() > haystack.len() {
        return false;
    }
    let mut i = 0usize;
    while i + needle.len() <= haystack.len() {
        let mut ok = true;
        let mut j = 0usize;
        while j < needle.len() {
            if haystack[i + j] != needle[j] {
                ok = false;
                break;
            }
            j += 1;
        }
        if ok {
            return true;
        }
        i += 1;
    }
    false
}