xref: /linux-6.15/rust/kernel/faux.rs (revision 10b20f2d)
178418f30SLyude Paul // SPDX-License-Identifier: GPL-2.0-only
278418f30SLyude Paul 
378418f30SLyude Paul //! Abstractions for the faux bus.
478418f30SLyude Paul //!
578418f30SLyude Paul //! This module provides bindings for working with faux devices in kernel modules.
678418f30SLyude Paul //!
778418f30SLyude Paul //! C header: [`include/linux/device/faux.h`]
878418f30SLyude Paul 
978418f30SLyude Paul use crate::{bindings, device, error::code::*, prelude::*};
1078418f30SLyude Paul use core::ptr::{addr_of_mut, null, null_mut, NonNull};
1178418f30SLyude Paul 
1278418f30SLyude Paul /// The registration of a faux device.
1378418f30SLyude Paul ///
1478418f30SLyude Paul /// This type represents the registration of a [`struct faux_device`]. When an instance of this type
1578418f30SLyude Paul /// is dropped, its respective faux device will be unregistered from the system.
1678418f30SLyude Paul ///
1778418f30SLyude Paul /// # Invariants
1878418f30SLyude Paul ///
1978418f30SLyude Paul /// `self.0` always holds a valid pointer to an initialized and registered [`struct faux_device`].
2078418f30SLyude Paul ///
2178418f30SLyude Paul /// [`struct faux_device`]: srctree/include/linux/device/faux.h
2278418f30SLyude Paul pub struct Registration(NonNull<bindings::faux_device>);
2378418f30SLyude Paul 
2478418f30SLyude Paul impl Registration {
2578418f30SLyude Paul     /// Create and register a new faux device with the given name.
26*10b20f2dSEthan Carter Edwards     #[inline]
new(name: &CStr, parent: Option<&device::Device>) -> Result<Self>2795cb0cb5SLyude Paul     pub fn new(name: &CStr, parent: Option<&device::Device>) -> Result<Self> {
2878418f30SLyude Paul         // SAFETY:
2978418f30SLyude Paul         // - `name` is copied by this function into its own storage
3078418f30SLyude Paul         // - `faux_ops` is safe to leave NULL according to the C API
3195cb0cb5SLyude Paul         // - `parent` can be either NULL or a pointer to a `struct device`, and `faux_device_create`
3295cb0cb5SLyude Paul         //   will take a reference to `parent` using `device_add` - ensuring that it remains valid
3395cb0cb5SLyude Paul         //   for the lifetime of the faux device.
3495cb0cb5SLyude Paul         let dev = unsafe {
3595cb0cb5SLyude Paul             bindings::faux_device_create(
3695cb0cb5SLyude Paul                 name.as_char_ptr(),
3795cb0cb5SLyude Paul                 parent.map_or(null_mut(), |p| p.as_raw()),
3895cb0cb5SLyude Paul                 null(),
3995cb0cb5SLyude Paul             )
4095cb0cb5SLyude Paul         };
4178418f30SLyude Paul 
4278418f30SLyude Paul         // The above function will return either a valid device, or NULL on failure
4378418f30SLyude Paul         // INVARIANT: The device will remain registered until faux_device_destroy() is called, which
4478418f30SLyude Paul         // happens in our Drop implementation.
4578418f30SLyude Paul         Ok(Self(NonNull::new(dev).ok_or(ENODEV)?))
4678418f30SLyude Paul     }
4778418f30SLyude Paul 
as_raw(&self) -> *mut bindings::faux_device4878418f30SLyude Paul     fn as_raw(&self) -> *mut bindings::faux_device {
4978418f30SLyude Paul         self.0.as_ptr()
5078418f30SLyude Paul     }
5178418f30SLyude Paul }
5278418f30SLyude Paul 
5378418f30SLyude Paul impl AsRef<device::Device> for Registration {
as_ref(&self) -> &device::Device5478418f30SLyude Paul     fn as_ref(&self) -> &device::Device {
5578418f30SLyude Paul         // SAFETY: The underlying `device` in `faux_device` is guaranteed by the C API to be
5678418f30SLyude Paul         // a valid initialized `device`.
5778418f30SLyude Paul         unsafe { device::Device::as_ref(addr_of_mut!((*self.as_raw()).dev)) }
5878418f30SLyude Paul     }
5978418f30SLyude Paul }
6078418f30SLyude Paul 
6178418f30SLyude Paul impl Drop for Registration {
62*10b20f2dSEthan Carter Edwards     #[inline]
drop(&mut self)6378418f30SLyude Paul     fn drop(&mut self) {
6478418f30SLyude Paul         // SAFETY: `self.0` is a valid registered faux_device via our type invariants.
6578418f30SLyude Paul         unsafe { bindings::faux_device_destroy(self.as_raw()) }
6678418f30SLyude Paul     }
6778418f30SLyude Paul }
6878418f30SLyude Paul 
6978418f30SLyude Paul // SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as
7078418f30SLyude Paul // faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not
7178418f30SLyude Paul // having Copy/Clone.
7278418f30SLyude Paul unsafe impl Send for Registration {}
7378418f30SLyude Paul 
7478418f30SLyude Paul // SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as
7578418f30SLyude Paul // faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not
7678418f30SLyude Paul // having Copy/Clone.
7778418f30SLyude Paul unsafe impl Sync for Registration {}
78