Files
RedBear-OS/drivers/input/i2c-hidd/src/quirks.rs
T
Red Bear OS bd595851e2 base: apply Red Bear patches on latest upstream/main
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
2026-07-11 11:39:24 +03:00

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)
}