Add kwin full source tree, greeter login, zsh, pcid service, and build system improvements
This commit is contained in:
@@ -280,11 +280,19 @@ index 9e776232..8cecf423 100644
|
||||
@@ -63,6 +74,7 @@ members = [
|
||||
"drivers/storage/usbscsid",
|
||||
"drivers/storage/virtio-blkd",
|
||||
|
||||
|
||||
+ "drivers/usb/ucsid",
|
||||
"drivers/usb/xhcid",
|
||||
"drivers/usb/usbctl",
|
||||
"drivers/usb/usbhubd",
|
||||
@@ -82,6 +93,7 @@ fdt = "0.1.5"
|
||||
edid = "0.3.0" #TODO: edid is abandoned, fork it and maintain?
|
||||
fdt = "0.1.5"
|
||||
+nom = "3.2.0" # transitive dep via edid; needed to match on IResult variants
|
||||
libc = "0.2.181"
|
||||
log = "0.4"
|
||||
libredox = "0.1.16"
|
||||
parking_lot = "0.12"
|
||||
diff --git a/drivers/acpi-resource/Cargo.toml b/drivers/acpi-resource/Cargo.toml
|
||||
new file mode 100644
|
||||
index 00000000..f30c6d02
|
||||
@@ -998,79 +1006,6 @@ index 00000000..57ae4b4b
|
||||
+ assert!(matches!(&resources[0], ResourceDescriptor::GpioInt(_)));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/drivers/acpid/Cargo.toml b/drivers/acpid/Cargo.toml
|
||||
index f03a4ccb..712b6d6e 100644
|
||||
--- a/drivers/acpid/Cargo.toml
|
||||
+++ b/drivers/acpid/Cargo.toml
|
||||
@@ -8,6 +8,7 @@ edition = "2018"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
+acpi-resource = { path = "../acpi-resource" }
|
||||
acpi = { git = "https://github.com/jackpot51/acpi.git" }
|
||||
arrayvec = "0.7.6"
|
||||
log.workspace = true
|
||||
diff --git a/drivers/acpid/src/main.rs b/drivers/acpid/src/main.rs
|
||||
index e388cd46..3b0deeab 100644
|
||||
--- a/drivers/acpid/src/main.rs
|
||||
+++ b/drivers/acpid/src/main.rs
|
||||
@@ -15,8 +15,9 @@ mod aml_physmem;
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
mod ec;
|
||||
|
||||
-mod sleep;
|
||||
+mod resources;
|
||||
mod scheme;
|
||||
+mod sleep;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum StartupError {
|
||||
@@ -179,15 +180,18 @@ fn run_acpid(daemon: daemon::Daemon) -> Result<(), StartupError> {
|
||||
while mounted {
|
||||
let Some(event) = event_queue.next().transpose().map_err(|error| {
|
||||
StartupError::runtime("failed to read event file", error.to_string())
|
||||
- })? else {
|
||||
+ })?
|
||||
+ else {
|
||||
break;
|
||||
};
|
||||
|
||||
if event.fd == socket.inner().raw() {
|
||||
loop {
|
||||
- match handler.process_requests_nonblocking(&mut scheme).map_err(|error| {
|
||||
- StartupError::runtime("failed to process requests", error.to_string())
|
||||
- })? {
|
||||
+ match handler
|
||||
+ .process_requests_nonblocking(&mut scheme)
|
||||
+ .map_err(|error| {
|
||||
+ StartupError::runtime("failed to process requests", error.to_string())
|
||||
+ })? {
|
||||
ControlFlow::Continue(()) => {}
|
||||
ControlFlow::Break(()) => break,
|
||||
}
|
||||
@@ -204,7 +208,10 @@ fn run_acpid(daemon: daemon::Daemon) -> Result<(), StartupError> {
|
||||
drop(event_queue);
|
||||
|
||||
acpi_context.set_global_s_state(5).map_err(|error| {
|
||||
- StartupError::runtime("failed to shut down after kernel request", error.to_string())
|
||||
+ StartupError::runtime(
|
||||
+ "failed to shut down after kernel request",
|
||||
+ error.to_string(),
|
||||
+ )
|
||||
})
|
||||
}
|
||||
|
||||
@@ -289,8 +296,8 @@ mod tests {
|
||||
#[test]
|
||||
fn xsdt_physaddrs_parse_without_panic() {
|
||||
let payload = [
|
||||
- 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
|
||||
- 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99,
|
||||
+ 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB,
|
||||
+ 0xAA, 0x99,
|
||||
];
|
||||
let sdt = parse_root_sdt(make_sdt(*b"XSDT", &payload))
|
||||
.unwrap()
|
||||
diff --git a/drivers/acpid/src/resources.rs b/drivers/acpid/src/resources.rs
|
||||
new file mode 100644
|
||||
index 00000000..86bcfd1e
|
||||
@@ -1078,416 +1013,6 @@ index 00000000..86bcfd1e
|
||||
+++ b/drivers/acpid/src/resources.rs
|
||||
@@ -0,0 +1 @@
|
||||
+pub use acpi_resource::{decode_resource_template, ResourceDescriptor};
|
||||
diff --git a/drivers/acpid/src/scheme.rs b/drivers/acpid/src/scheme.rs
|
||||
index 7070e8b9..4fe3b8d8 100644
|
||||
--- a/drivers/acpid/src/scheme.rs
|
||||
+++ b/drivers/acpid/src/scheme.rs
|
||||
@@ -15,7 +15,9 @@ use syscall::FobtainFdFlags;
|
||||
|
||||
use syscall::data::Stat;
|
||||
use syscall::error::{Error, Result};
|
||||
-use syscall::error::{EACCES, EAGAIN, EBADF, EBADFD, EINVAL, EIO, EISDIR, ENOENT, ENOTDIR, EOPNOTSUPP};
|
||||
+use syscall::error::{
|
||||
+ EACCES, EAGAIN, EBADF, EBADFD, EINVAL, EIO, EISDIR, ENOENT, ENOTDIR, EOPNOTSUPP,
|
||||
+};
|
||||
use syscall::flag::{MODE_DIR, MODE_FILE};
|
||||
use syscall::flag::{O_ACCMODE, O_DIRECTORY, O_RDONLY, O_STAT, O_SYMLINK};
|
||||
use syscall::{EOVERFLOW, EPERM};
|
||||
@@ -24,6 +26,7 @@ use crate::acpi::{
|
||||
AcpiBattery, AcpiContext, AcpiPowerAdapter, AcpiPowerSnapshot, AmlSymbols, DmiInfo,
|
||||
SdtSignature,
|
||||
};
|
||||
+use crate::resources::{decode_resource_template, ResourceDescriptor};
|
||||
|
||||
pub struct AcpiScheme<'acpi, 'sock> {
|
||||
ctx: &'acpi AcpiContext,
|
||||
@@ -42,6 +45,8 @@ enum HandleKind<'a> {
|
||||
Table(SdtSignature),
|
||||
Symbols(RwLockReadGuard<'a, AmlSymbols>),
|
||||
Symbol { name: String, description: String },
|
||||
+ ResourcesDir,
|
||||
+ Resources(String),
|
||||
Reboot,
|
||||
DmiDir,
|
||||
Dmi(String),
|
||||
@@ -197,6 +202,7 @@ fn top_level_entries(power_available: bool) -> Vec<(&'static str, DirentKind)> {
|
||||
let mut entries = vec![
|
||||
("tables", DirentKind::Directory),
|
||||
("symbols", DirentKind::Directory),
|
||||
+ ("resources", DirentKind::Directory),
|
||||
("dmi", DirentKind::Directory),
|
||||
("reboot", DirentKind::Regular),
|
||||
];
|
||||
@@ -206,6 +212,37 @@ fn top_level_entries(power_available: bool) -> Vec<(&'static str, DirentKind)> {
|
||||
entries
|
||||
}
|
||||
|
||||
+fn resource_symbol_path(path: &str) -> Option<String> {
|
||||
+ let normalized = path.trim_matches('/').trim_start_matches('\\');
|
||||
+ if normalized.is_empty() {
|
||||
+ return None;
|
||||
+ }
|
||||
+
|
||||
+ let normalized = normalized.replace('/', ".");
|
||||
+ if normalized.is_empty() {
|
||||
+ None
|
||||
+ } else {
|
||||
+ Some(format!("{normalized}._CRS"))
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+fn resource_entry_name(symbol: &str) -> Option<String> {
|
||||
+ symbol
|
||||
+ .strip_suffix("._CRS")
|
||||
+ .map(str::to_string)
|
||||
+ .filter(|path| !path.is_empty())
|
||||
+}
|
||||
+
|
||||
+fn resource_dir_entries<'a>(symbols: impl IntoIterator<Item = &'a str>) -> Vec<String> {
|
||||
+ let mut entries = symbols
|
||||
+ .into_iter()
|
||||
+ .filter_map(resource_entry_name)
|
||||
+ .collect::<Vec<_>>();
|
||||
+ entries.sort_unstable();
|
||||
+ entries.dedup();
|
||||
+ entries
|
||||
+}
|
||||
+
|
||||
impl HandleKind<'_> {
|
||||
fn is_dir(&self) -> bool {
|
||||
match self {
|
||||
@@ -214,6 +251,8 @@ impl HandleKind<'_> {
|
||||
Self::Table(_) => false,
|
||||
Self::Symbols(_) => true,
|
||||
Self::Symbol { .. } => false,
|
||||
+ Self::ResourcesDir => true,
|
||||
+ Self::Resources(_) => false,
|
||||
Self::Reboot => false,
|
||||
Self::DmiDir => true,
|
||||
Self::Dmi(_) => false,
|
||||
@@ -235,12 +274,14 @@ impl HandleKind<'_> {
|
||||
.ok_or(Error::new(EBADFD))?
|
||||
.length(),
|
||||
Self::Symbol { description, .. } => description.len(),
|
||||
+ Self::Resources(contents) => contents.len(),
|
||||
Self::Reboot => 0,
|
||||
Self::Dmi(contents) => contents.len(),
|
||||
Self::PowerFile(contents) => contents.len(),
|
||||
// Directories
|
||||
Self::TopLevel
|
||||
| Self::Symbols(_)
|
||||
+ | Self::ResourcesDir
|
||||
| Self::Tables
|
||||
| Self::DmiDir
|
||||
| Self::PowerDir
|
||||
@@ -280,6 +321,58 @@ impl<'acpi, 'sock> AcpiScheme<'acpi, 'sock> {
|
||||
matches!(self.ctx.power_snapshot(), Ok(_))
|
||||
}
|
||||
|
||||
+ fn resources_handle(&self, path: &str) -> Result<HandleKind<'acpi>> {
|
||||
+ if !self.ctx.pci_ready() {
|
||||
+ let display_path = if path.is_empty() { "resources" } else { path };
|
||||
+ log::warn!(
|
||||
+ "Deferring ACPI resource lookup for {display_path} until PCI registration is ready"
|
||||
+ );
|
||||
+ return Err(Error::new(EAGAIN));
|
||||
+ }
|
||||
+
|
||||
+ let normalized = path.trim_matches('/');
|
||||
+ if normalized.is_empty() {
|
||||
+ return Ok(HandleKind::ResourcesDir);
|
||||
+ }
|
||||
+
|
||||
+ let symbol_path = resource_symbol_path(normalized).ok_or(Error::new(ENOENT))?;
|
||||
+ if self.ctx.aml_lookup(&symbol_path).is_none() {
|
||||
+ return Err(Error::new(ENOENT));
|
||||
+ }
|
||||
+
|
||||
+ let aml_name =
|
||||
+ AmlName::from_str(&format!("\\{symbol_path}")).map_err(|_| Error::new(ENOENT))?;
|
||||
+ let buffer = match self.ctx.aml_eval(aml_name, Vec::new()) {
|
||||
+ Ok(AmlSerdeValue::Buffer(bytes)) => bytes,
|
||||
+ Ok(other) => {
|
||||
+ log::debug!(
|
||||
+ "Skipping ACPI resources for {normalized} due to unexpected _CRS value: {:?}",
|
||||
+ other
|
||||
+ );
|
||||
+ return Err(Error::new(ENOENT));
|
||||
+ }
|
||||
+ Err(error) => {
|
||||
+ log::debug!(
|
||||
+ "Failed to evaluate ACPI resources for {symbol_path}: {:?}",
|
||||
+ error
|
||||
+ );
|
||||
+ return Err(Error::new(ENOENT));
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ let descriptors: Vec<ResourceDescriptor> =
|
||||
+ decode_resource_template(&buffer).map_err(|error| {
|
||||
+ log::warn!("Failed to decode ACPI _CRS for {symbol_path}: {error}");
|
||||
+ Error::new(EIO)
|
||||
+ })?;
|
||||
+ let serialized = ron::ser::to_string(&descriptors).map_err(|error| {
|
||||
+ log::warn!("Failed to serialize decoded ACPI resources for {symbol_path}: {error}");
|
||||
+ Error::new(EIO)
|
||||
+ })?;
|
||||
+
|
||||
+ Ok(HandleKind::Resources(serialized))
|
||||
+ }
|
||||
+
|
||||
fn power_handle(&self, path: &str) -> Result<HandleKind<'acpi>> {
|
||||
let normalized = path.trim_matches('/');
|
||||
self.power_snapshot()?;
|
||||
@@ -464,76 +557,85 @@ impl SchemeSync for AcpiScheme<'_, '_> {
|
||||
|
||||
let kind = match handle.kind {
|
||||
HandleKind::SchemeRoot => {
|
||||
- // TODO: arrayvec
|
||||
- let components = {
|
||||
- let mut v = arrayvec::ArrayVec::<&str, 4>::new();
|
||||
- let it = path.split('/');
|
||||
- for component in it.take(4) {
|
||||
- v.push(component);
|
||||
- }
|
||||
-
|
||||
- v
|
||||
- };
|
||||
-
|
||||
- match &*components {
|
||||
- [""] => HandleKind::TopLevel,
|
||||
- ["reboot"] => HandleKind::Reboot,
|
||||
- ["dmi"] => {
|
||||
- if flag_dir || flag_stat || path.ends_with('/') {
|
||||
- HandleKind::DmiDir
|
||||
- } else {
|
||||
- HandleKind::Dmi(
|
||||
- dmi_contents(self.ctx.dmi_info(), "match_all")
|
||||
- .expect("match_all should always resolve"),
|
||||
- )
|
||||
+ if path == "resources" || path == "resources/" {
|
||||
+ self.resources_handle("")?
|
||||
+ } else if let Some(rest) = path.strip_prefix("resources/") {
|
||||
+ self.resources_handle(rest)?
|
||||
+ } else {
|
||||
+ // TODO: arrayvec
|
||||
+ let components = {
|
||||
+ let mut v = arrayvec::ArrayVec::<&str, 4>::new();
|
||||
+ let it = path.split('/');
|
||||
+ for component in it.take(4) {
|
||||
+ v.push(component);
|
||||
}
|
||||
- }
|
||||
- ["dmi", ""] => HandleKind::DmiDir,
|
||||
- ["dmi", field] => HandleKind::Dmi(
|
||||
- dmi_contents(self.ctx.dmi_info(), field).ok_or(Error::new(ENOENT))?,
|
||||
- ),
|
||||
- ["power"] => self.power_handle("")?,
|
||||
- ["power", tail] => self.power_handle(tail)?,
|
||||
- ["power", a, b] => self.power_handle(&format!("{a}/{b}"))?,
|
||||
- ["power", a, b, c] => self.power_handle(&format!("{a}/{b}/{c}"))?,
|
||||
- ["register_pci"] => HandleKind::RegisterPci,
|
||||
- ["tables"] => HandleKind::Tables,
|
||||
-
|
||||
- ["tables", table] => {
|
||||
- let signature = parse_table(table.as_bytes()).ok_or(Error::new(ENOENT))?;
|
||||
- HandleKind::Table(signature)
|
||||
- }
|
||||
|
||||
- ["symbols"] => {
|
||||
- if !self.ctx.pci_ready() {
|
||||
- log::warn!("Deferring AML symbol scan until PCI registration is ready");
|
||||
- return Err(Error::new(EAGAIN));
|
||||
+ v
|
||||
+ };
|
||||
+
|
||||
+ match &*components {
|
||||
+ [""] => HandleKind::TopLevel,
|
||||
+ ["reboot"] => HandleKind::Reboot,
|
||||
+ ["dmi"] => {
|
||||
+ if flag_dir || flag_stat || path.ends_with('/') {
|
||||
+ HandleKind::DmiDir
|
||||
+ } else {
|
||||
+ HandleKind::Dmi(
|
||||
+ dmi_contents(self.ctx.dmi_info(), "match_all")
|
||||
+ .expect("match_all should always resolve"),
|
||||
+ )
|
||||
+ }
|
||||
}
|
||||
- if let Ok(aml_symbols) = self.ctx.aml_symbols() {
|
||||
- HandleKind::Symbols(aml_symbols)
|
||||
- } else {
|
||||
- return Err(Error::new(EIO));
|
||||
+ ["dmi", ""] => HandleKind::DmiDir,
|
||||
+ ["dmi", field] => HandleKind::Dmi(
|
||||
+ dmi_contents(self.ctx.dmi_info(), field).ok_or(Error::new(ENOENT))?,
|
||||
+ ),
|
||||
+ ["power"] => self.power_handle("")?,
|
||||
+ ["power", tail] => self.power_handle(tail)?,
|
||||
+ ["power", a, b] => self.power_handle(&format!("{a}/{b}"))?,
|
||||
+ ["power", a, b, c] => self.power_handle(&format!("{a}/{b}/{c}"))?,
|
||||
+ ["register_pci"] => HandleKind::RegisterPci,
|
||||
+ ["tables"] => HandleKind::Tables,
|
||||
+
|
||||
+ ["tables", table] => {
|
||||
+ let signature =
|
||||
+ parse_table(table.as_bytes()).ok_or(Error::new(ENOENT))?;
|
||||
+ HandleKind::Table(signature)
|
||||
}
|
||||
- }
|
||||
|
||||
- ["symbols", symbol] => {
|
||||
- if !self.ctx.pci_ready() {
|
||||
- log::warn!(
|
||||
- "Deferring AML symbol lookup for {symbol} until PCI registration is ready"
|
||||
- );
|
||||
- return Err(Error::new(EAGAIN));
|
||||
+ ["symbols"] => {
|
||||
+ if !self.ctx.pci_ready() {
|
||||
+ log::warn!(
|
||||
+ "Deferring AML symbol scan until PCI registration is ready"
|
||||
+ );
|
||||
+ return Err(Error::new(EAGAIN));
|
||||
+ }
|
||||
+ if let Ok(aml_symbols) = self.ctx.aml_symbols() {
|
||||
+ HandleKind::Symbols(aml_symbols)
|
||||
+ } else {
|
||||
+ return Err(Error::new(EIO));
|
||||
+ }
|
||||
}
|
||||
- if let Some(description) = self.ctx.aml_lookup(symbol) {
|
||||
- HandleKind::Symbol {
|
||||
- name: (*symbol).to_owned(),
|
||||
- description,
|
||||
+
|
||||
+ ["symbols", symbol] => {
|
||||
+ if !self.ctx.pci_ready() {
|
||||
+ log::warn!(
|
||||
+ "Deferring AML symbol lookup for {symbol} until PCI registration is ready"
|
||||
+ );
|
||||
+ return Err(Error::new(EAGAIN));
|
||||
+ }
|
||||
+ if let Some(description) = self.ctx.aml_lookup(symbol) {
|
||||
+ HandleKind::Symbol {
|
||||
+ name: (*symbol).to_owned(),
|
||||
+ description,
|
||||
+ }
|
||||
+ } else {
|
||||
+ return Err(Error::new(ENOENT));
|
||||
}
|
||||
- } else {
|
||||
- return Err(Error::new(ENOENT));
|
||||
}
|
||||
- }
|
||||
|
||||
- _ => return Err(Error::new(ENOENT)),
|
||||
+ _ => return Err(Error::new(ENOENT)),
|
||||
+ }
|
||||
}
|
||||
}
|
||||
HandleKind::DmiDir => {
|
||||
@@ -545,6 +647,7 @@ impl SchemeSync for AcpiScheme<'_, '_> {
|
||||
)
|
||||
}
|
||||
}
|
||||
+ HandleKind::ResourcesDir => self.resources_handle(path)?,
|
||||
HandleKind::Symbols(ref aml_symbols) => {
|
||||
if let Some(description) = aml_symbols.lookup(path) {
|
||||
HandleKind::Symbol {
|
||||
@@ -646,6 +749,7 @@ impl SchemeSync for AcpiScheme<'_, '_> {
|
||||
.ok_or(Error::new(EBADFD))?
|
||||
.as_slice(),
|
||||
HandleKind::Symbol { description, .. } => description.as_bytes(),
|
||||
+ HandleKind::Resources(contents) => contents.as_bytes(),
|
||||
HandleKind::Dmi(contents) => contents.as_bytes(),
|
||||
HandleKind::PowerFile(contents) => contents.as_bytes(),
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
@@ -698,6 +802,19 @@ impl SchemeSync for AcpiScheme<'_, '_> {
|
||||
})?;
|
||||
}
|
||||
}
|
||||
+ HandleKind::ResourcesDir => {
|
||||
+ let aml_symbols = self.ctx.aml_symbols().map_err(|_| Error::new(EIO))?;
|
||||
+ let entries =
|
||||
+ resource_dir_entries(aml_symbols.symbols_cache().keys().map(String::as_str));
|
||||
+ for (idx, name) in entries.iter().enumerate().skip(opaque_offset as usize) {
|
||||
+ buf.entry(DirEntry {
|
||||
+ inode: 0,
|
||||
+ next_opaque_id: idx as u64 + 1,
|
||||
+ name,
|
||||
+ kind: DirentKind::Regular,
|
||||
+ })?;
|
||||
+ }
|
||||
+ }
|
||||
HandleKind::PowerDir => {
|
||||
const POWER_ROOT_ENTRIES: &[(&str, DirentKind)] = &[
|
||||
("on_battery", DirentKind::Regular),
|
||||
@@ -958,7 +1075,7 @@ impl SchemeSync for AcpiScheme<'_, '_> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
- use super::{dmi_contents, top_level_entries};
|
||||
+ use super::{dmi_contents, resource_dir_entries, resource_symbol_path, top_level_entries};
|
||||
use crate::acpi::DmiInfo;
|
||||
use syscall::dirent::DirentKind;
|
||||
|
||||
@@ -994,9 +1111,9 @@ mod tests {
|
||||
#[test]
|
||||
fn top_level_entries_always_include_reboot() {
|
||||
let entries = top_level_entries(false);
|
||||
- assert!(entries.iter().any(|(name, kind)| {
|
||||
- *name == "reboot" && matches!(kind, DirentKind::Regular)
|
||||
- }));
|
||||
+ assert!(entries
|
||||
+ .iter()
|
||||
+ .any(|(name, kind)| { *name == "reboot" && matches!(kind, DirentKind::Regular) }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1005,8 +1122,40 @@ mod tests {
|
||||
let visible = top_level_entries(true);
|
||||
|
||||
assert!(!hidden.iter().any(|(name, _)| *name == "power"));
|
||||
- assert!(visible.iter().any(|(name, kind)| {
|
||||
- *name == "power" && matches!(kind, DirentKind::Directory)
|
||||
- }));
|
||||
+ assert!(visible
|
||||
+ .iter()
|
||||
+ .any(|(name, kind)| { *name == "power" && matches!(kind, DirentKind::Directory) }));
|
||||
+ }
|
||||
+
|
||||
+ #[test]
|
||||
+ fn top_level_entries_always_include_resources() {
|
||||
+ let entries = top_level_entries(false);
|
||||
+ assert!(entries
|
||||
+ .iter()
|
||||
+ .any(|(name, kind)| { *name == "resources" && matches!(kind, DirentKind::Directory) }));
|
||||
+ }
|
||||
+
|
||||
+ #[test]
|
||||
+ fn resource_symbol_path_accepts_dotted_and_slash_paths() {
|
||||
+ assert_eq!(
|
||||
+ resource_symbol_path("_SB.PCI0.I2C0.TPD0").as_deref(),
|
||||
+ Some("_SB.PCI0.I2C0.TPD0._CRS")
|
||||
+ );
|
||||
+ assert_eq!(
|
||||
+ resource_symbol_path("\\_SB/PCI0/I2C0/TPD0").as_deref(),
|
||||
+ Some("_SB.PCI0.I2C0.TPD0._CRS")
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ #[test]
|
||||
+ fn resource_dir_entries_list_devices_with_crs_suffix() {
|
||||
+ assert_eq!(
|
||||
+ resource_dir_entries([
|
||||
+ "_SB.PCI0.I2C0.TPD0._CRS",
|
||||
+ "_SB.PCI0.I2C1.TPD1._HID",
|
||||
+ "_SB.PCI0.I2C0.TPD0._CRS",
|
||||
+ ]),
|
||||
+ vec!["_SB.PCI0.I2C0.TPD0".to_string()]
|
||||
+ );
|
||||
}
|
||||
}
|
||||
diff --git a/drivers/acpid/src/sleep.rs b/drivers/acpid/src/sleep.rs
|
||||
new file mode 100644
|
||||
index 00000000..e5d6ab22
|
||||
|
||||
Reference in New Issue
Block a user