--- a/drivers/hwd/src/backend/acpi.rs +++ b/drivers/hwd/src/backend/acpi.rs @@ -1,26 +1,30 @@ use amlserde::{AmlSerde, AmlSerdeValue}; -use std::{error::Error, fs, process::Command}; +use std::{error::Error, fs}; use super::Backend; pub struct AcpiBackend { - rxsdt: Vec, + _rxsdt: Vec, } impl Backend for AcpiBackend { fn new() -> Result> { let rxsdt = fs::read("/scheme/kernel.acpi/rxsdt")?; - // Spawn acpid - //TODO: pass rxsdt data to acpid? - #[allow(deprecated, reason = "we can't yet move this to init")] - daemon::Daemon::spawn(Command::new("acpid")); - - Ok(Self { rxsdt }) + Ok(Self { _rxsdt: rxsdt }) } fn probe(&mut self) -> Result<(), Box> { + let mut boot_critical_input_candidates = 0usize; + let mut thc_candidates = 0usize; + let mut non_hid_i2c_candidates = 0usize; + // Read symbols from acpi scheme - let entries = fs::read_dir("/scheme/acpi/symbols")?; + let entries = match fs::read_dir("/scheme/acpi/symbols") { + Ok(entries) => entries, + Err(err) if err.kind() == std::io::ErrorKind::WouldBlock || err.raw_os_error() == Some(11) => { + log::debug!("hwd: ACPI symbols are not ready yet"); + return Ok(()); + } + Err(err) => return Err(Box::new(err)), + }; // TODO: Reimplement with getdents? let symbols_fd = libredox::Fd::open( "/scheme/acpi/symbols", @@ -83,6 +87,7 @@ impl Backend for AcpiBackend { "PNP0C0F" => "PCI interrupt link", "PNP0C50" => "I2C HID", "PNP0F13" => "PS/2 port for PS/2-style mouse", + "80860F41" | "808622C1" => "DesignWare I2C controller", + "AMDI0010" | "AMDI0019" | "AMDI0510" => "AMD laptop I2C controller", + "INT33C2" | "INT33C3" | "INT3432" | "INT3433" | "INTC10EF" => { + "Intel LPSS/SerialIO I2C controller" + } + "INT34C5" | "INTC1055" => "Intel GPIO controller", + "INTC1050" | "INTC1051" | "INTC1080" | "INTC1081" | "INTC1082" => { + "Intel THC companion (QuickI2C/QuickSPI path)" + } + _ if is_elan_touchpad_id(&id) => "ELAN touchpad (I2C/SMBus path)", + _ if is_cypress_touchpad_id(&id) => "Cypress/Trackpad (non-HID I2C path)", + _ if is_synaptics_rmi_id(&id) => "Synaptics RMI touchpad (I2C/SMBus path)", _ => "?", }; log::debug!("{}: {} ({})", name, id, what); + if is_boot_critical_i2c_surface(&id) { + boot_critical_input_candidates += 1; + log::info!("{}: {} is boot-critical for laptop input path", name, id); + } + if is_thc_companion(&id) { + thc_candidates += 1; + log::warn!( + "{}: {} indicates Intel THC path; DMA/report fast-path is not complete yet", + name, + id + ); + } + if is_non_hid_i2c_input_id(&id) { + non_hid_i2c_candidates += 1; + } } } } + + if boot_critical_input_candidates == 0 { + log::warn!( + "hwd: no ACPI boot-critical I2C input candidates found; built-in laptop input may require additional controller/device support" + ); + } else { + log::info!( + "hwd: ACPI input candidates: total={} thc={} non_hid_i2c={}", + boot_critical_input_candidates, + thc_candidates, + non_hid_i2c_candidates + ); + } + Ok(()) } } + +fn is_boot_critical_i2c_surface(id: &str) -> bool { + matches!( + id, + "PNP0C50" + | "ACPI0C50" + | "80860F41" + | "808622C1" + | "AMDI0010" + | "AMDI0019" + | "AMDI0510" + | "INT33C2" + | "INT33C3" + | "INT3432" + | "INT3433" + | "INTC10EF" + | "INT34C5" + | "INTC1055" + | "INTC1050" + | "INTC1051" + | "INT1080" + | "INTC1081" + | "INT1082" + ) || is_elan_touchpad_id(id) + || is_cypress_touchpad_id(id) + || is_synaptics_rmi_id(id) +} + +fn is_thc_companion(id: &str) -> bool { + matches!( + id, + "INTC1050" | "INTC1051" | "INTC1080" | "INTC1081" | "INTC1082" + ) +} + +fn is_elan_touchpad_id(id: &str) -> bool { + id.starts_with("ELAN") +} + +fn is_cypress_touchpad_id(id: &str) -> bool { + id.starts_with("CYAP") +} + +fn is_synaptics_rmi_id(id: &str) -> bool { + id.starts_with("SYNA") +} + +fn is_non_hid_i2c_input_id(id: &str) -> bool { + is_elan_touchpad_id(id) || is_cypress_touchpad_id(id) || is_synaptics_rmi_id(id) +}