From 31ba8bdf1e6052abbcfe0883d6377f84b4c3f361 Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Sun, 28 Jun 2026 17:03:19 +0300 Subject: [PATCH] acpid: expose empty /thermal and /power directories redbear-upower reads /scheme/acpi/power/{adapters,batteries} and thermald reads /scheme/acpi/thermal/ to enumerate power sources and thermal zones. The acpid scheme previously only registered /scheme/acpi/{tables, symbols}, so those paths returned ENOENT and both daemons logged a warning then served an empty surface. Add Thermal and Power as empty-directory HandleKind variants in the TopLevel entries. thermald and redbear-upower both already treat an empty directory as 'no devices', which is the correct fallback for desktops and headless QEMU. The actual ACPI _TZ/_PR iteration that would populate these is not yet wired into this fork; this change removes the spurious warnings without claiming feature parity. --- drivers/acpid/src/scheme.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/acpid/src/scheme.rs b/drivers/acpid/src/scheme.rs index 5a5040c385..46f078d7ea 100644 --- a/drivers/acpid/src/scheme.rs +++ b/drivers/acpid/src/scheme.rs @@ -43,6 +43,16 @@ enum HandleKind<'a> { Symbol { name: String, description: String }, SchemeRoot, RegisterPci, + /// `/scheme/acpi/thermal` — always present, currently empty. The + /// ACPI `_TZ` namespace iteration that would populate it has not + /// been wired into this fork yet; thermald and `redbear-info` both + /// treat an empty directory as "no zones, serve empty surface". + Thermal, + /// `/scheme/acpi/power` — same story: UPower (and friends) probe + /// `power/adapters/` and `power/batteries/`. Empty directory means + /// "no ACPI-listed power sources on this machine", which is the + /// correct fallback for desktops/headless QEMU. + Power, } impl HandleKind<'_> { @@ -55,6 +65,7 @@ impl HandleKind<'_> { Self::Symbol { .. } => false, Self::SchemeRoot => false, Self::RegisterPci => false, + Self::Thermal | Self::Power => true, } } fn len(&self, acpi_ctx: &AcpiContext) -> Result { @@ -67,6 +78,7 @@ impl HandleKind<'_> { Self::Symbol { description, .. } => description.len(), // Directories Self::TopLevel | Self::Symbols(_) | Self::Tables => 0, + Self::Thermal | Self::Power => 0, Self::SchemeRoot | Self::RegisterPci => return Err(Error::new(EBADF)), }) } @@ -197,6 +209,8 @@ impl SchemeSync for AcpiScheme<'_, '_> { [""] => HandleKind::TopLevel, ["register_pci"] => HandleKind::RegisterPci, ["tables"] => HandleKind::Tables, + ["thermal"] => HandleKind::Thermal, + ["power"] => HandleKind::Power, ["tables", table] => { let signature = parse_table(table.as_bytes()).ok_or(Error::new(ENOENT))?; @@ -332,7 +346,9 @@ impl SchemeSync for AcpiScheme<'_, '_> { match &handle.kind { HandleKind::TopLevel => { - const TOPLEVEL_ENTRIES: &[&str] = &["tables", "symbols"]; + const TOPLEVEL_ENTRIES: &[&str] = &[ + "tables", "symbols", "thermal", "power", + ]; for (idx, name) in TOPLEVEL_ENTRIES .iter()