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