1*a74931ebSIgor Korotin // SPDX-License-Identifier: GPL-2.0 2*a74931ebSIgor Korotin 3*a74931ebSIgor Korotin //! Advanced Configuration and Power Interface abstractions. 4*a74931ebSIgor Korotin 5*a74931ebSIgor Korotin use crate::{bindings, device_id::RawDeviceId, prelude::*}; 6*a74931ebSIgor Korotin 7*a74931ebSIgor Korotin /// IdTable type for ACPI drivers. 8*a74931ebSIgor Korotin pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>; 9*a74931ebSIgor Korotin 10*a74931ebSIgor Korotin /// An ACPI device id. 11*a74931ebSIgor Korotin #[repr(transparent)] 12*a74931ebSIgor Korotin #[derive(Clone, Copy)] 13*a74931ebSIgor Korotin pub struct DeviceId(bindings::acpi_device_id); 14*a74931ebSIgor Korotin 15*a74931ebSIgor Korotin // SAFETY: 16*a74931ebSIgor Korotin // * `DeviceId` is a `#[repr(transparent)` wrapper of `struct acpi_device_id` and does not add 17*a74931ebSIgor Korotin // additional invariants, so it's safe to transmute to `RawType`. 18*a74931ebSIgor Korotin // * `DRIVER_DATA_OFFSET` is the offset to the `data` field. 19*a74931ebSIgor Korotin unsafe impl RawDeviceId for DeviceId { 20*a74931ebSIgor Korotin type RawType = bindings::acpi_device_id; 21*a74931ebSIgor Korotin 22*a74931ebSIgor Korotin const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::acpi_device_id, driver_data); 23*a74931ebSIgor Korotin 24*a74931ebSIgor Korotin fn index(&self) -> usize { 25*a74931ebSIgor Korotin self.0.driver_data as _ 26*a74931ebSIgor Korotin } 27*a74931ebSIgor Korotin } 28*a74931ebSIgor Korotin 29*a74931ebSIgor Korotin impl DeviceId { 30*a74931ebSIgor Korotin const ACPI_ID_LEN: usize = 16; 31*a74931ebSIgor Korotin 32*a74931ebSIgor Korotin /// Create a new device id from an ACPI 'id' string. 33*a74931ebSIgor Korotin #[inline(always)] 34*a74931ebSIgor Korotin pub const fn new(id: &'static CStr) -> Self { 35*a74931ebSIgor Korotin build_assert!( 36*a74931ebSIgor Korotin id.len_with_nul() <= Self::ACPI_ID_LEN, 37*a74931ebSIgor Korotin "ID exceeds 16 bytes" 38*a74931ebSIgor Korotin ); 39*a74931ebSIgor Korotin let src = id.as_bytes_with_nul(); 40*a74931ebSIgor Korotin // Replace with `bindings::acpi_device_id::default()` once stabilized for `const`. 41*a74931ebSIgor Korotin // SAFETY: FFI type is valid to be zero-initialized. 42*a74931ebSIgor Korotin let mut acpi: bindings::acpi_device_id = unsafe { core::mem::zeroed() }; 43*a74931ebSIgor Korotin let mut i = 0; 44*a74931ebSIgor Korotin while i < src.len() { 45*a74931ebSIgor Korotin acpi.id[i] = src[i]; 46*a74931ebSIgor Korotin i += 1; 47*a74931ebSIgor Korotin } 48*a74931ebSIgor Korotin 49*a74931ebSIgor Korotin Self(acpi) 50*a74931ebSIgor Korotin } 51*a74931ebSIgor Korotin } 52*a74931ebSIgor Korotin 53*a74931ebSIgor Korotin /// Create an ACPI `IdTable` with an "alias" for modpost. 54*a74931ebSIgor Korotin #[macro_export] 55*a74931ebSIgor Korotin macro_rules! acpi_device_table { 56*a74931ebSIgor Korotin ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => { 57*a74931ebSIgor Korotin const $table_name: $crate::device_id::IdArray< 58*a74931ebSIgor Korotin $crate::acpi::DeviceId, 59*a74931ebSIgor Korotin $id_info_type, 60*a74931ebSIgor Korotin { $table_data.len() }, 61*a74931ebSIgor Korotin > = $crate::device_id::IdArray::new($table_data); 62*a74931ebSIgor Korotin 63*a74931ebSIgor Korotin $crate::module_device_table!("acpi", $module_table_name, $table_name); 64*a74931ebSIgor Korotin }; 65*a74931ebSIgor Korotin } 66