bd595851e2
251 files: init, acpid, ipcd, netcfg, ihdgd, virtio-gpud, scheme-utils, inputd, block driver, ptyd, ramfs, randd, initfs bootstrap, path deps, version +rb0.3.1, author attribution
89 lines
2.6 KiB
Rust
89 lines
2.6 KiB
Rust
use std::fs;
|
|
|
|
use anyhow::{Context, Result};
|
|
use serde::Deserialize;
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct ProbeFailureQuirk {
|
|
pub name: String,
|
|
pub system_vendor: Option<String>,
|
|
pub product_name: Option<String>,
|
|
pub board_name: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Deserialize)]
|
|
struct ProbeFailureQuirkFile {
|
|
quirks: Vec<ProbeFailureQuirkEntry>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize)]
|
|
struct ProbeFailureQuirkEntry {
|
|
name: String,
|
|
system_vendor: Option<String>,
|
|
product_name: Option<String>,
|
|
board_name: Option<String>,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct DmiSnapshot {
|
|
system_vendor: String,
|
|
product_name: String,
|
|
board_name: String,
|
|
}
|
|
|
|
pub fn match_probe_failure_quirk() -> Result<Option<ProbeFailureQuirk>> {
|
|
let snapshot = read_dmi_snapshot()?;
|
|
for entry in load_quirks()? {
|
|
if field_matches(&entry.system_vendor, &snapshot.system_vendor)
|
|
&& field_matches(&entry.product_name, &snapshot.product_name)
|
|
&& field_matches(&entry.board_name, &snapshot.board_name)
|
|
{
|
|
return Ok(Some(ProbeFailureQuirk {
|
|
name: entry.name,
|
|
system_vendor: entry.system_vendor,
|
|
product_name: entry.product_name,
|
|
board_name: entry.board_name,
|
|
}));
|
|
}
|
|
}
|
|
|
|
Ok(None)
|
|
}
|
|
|
|
fn load_quirks() -> Result<Vec<ProbeFailureQuirkEntry>> {
|
|
let path = "/etc/i2c-hidd-quirks.ron";
|
|
let text = match fs::read_to_string(path) {
|
|
Ok(text) => text,
|
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(Vec::new()),
|
|
Err(err) => return Err(err).with_context(|| format!("failed to read {path}")),
|
|
};
|
|
|
|
let file: ProbeFailureQuirkFile =
|
|
ron::from_str(&text).with_context(|| format!("failed to decode {path}"))?;
|
|
Ok(file.quirks)
|
|
}
|
|
|
|
fn read_dmi_snapshot() -> Result<DmiSnapshot> {
|
|
Ok(DmiSnapshot {
|
|
system_vendor: read_dmi_field("system_vendor")?,
|
|
product_name: read_dmi_field("product_name")?,
|
|
board_name: read_dmi_field("board_name")?,
|
|
})
|
|
}
|
|
|
|
fn read_dmi_field(field: &str) -> Result<String> {
|
|
let path = format!("/scheme/acpi/dmi/{field}");
|
|
match fs::read_to_string(&path) {
|
|
Ok(value) => Ok(value.trim().to_string()),
|
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(String::new()),
|
|
Err(err) => Err(err).with_context(|| format!("failed to read {path}")),
|
|
}
|
|
}
|
|
|
|
fn field_matches(expected: &Option<String>, actual: &str) -> bool {
|
|
expected
|
|
.as_deref()
|
|
.map(|expected| actual.eq_ignore_ascii_case(expected))
|
|
.unwrap_or(true)
|
|
}
|