1*78418f30SLyude Paul // SPDX-License-Identifier: GPL-2.0-only 2*78418f30SLyude Paul 3*78418f30SLyude Paul //! Abstractions for the faux bus. 4*78418f30SLyude Paul //! 5*78418f30SLyude Paul //! This module provides bindings for working with faux devices in kernel modules. 6*78418f30SLyude Paul //! 7*78418f30SLyude Paul //! C header: [`include/linux/device/faux.h`] 8*78418f30SLyude Paul 9*78418f30SLyude Paul use crate::{bindings, device, error::code::*, prelude::*}; 10*78418f30SLyude Paul use core::ptr::{addr_of_mut, null, null_mut, NonNull}; 11*78418f30SLyude Paul 12*78418f30SLyude Paul /// The registration of a faux device. 13*78418f30SLyude Paul /// 14*78418f30SLyude Paul /// This type represents the registration of a [`struct faux_device`]. When an instance of this type 15*78418f30SLyude Paul /// is dropped, its respective faux device will be unregistered from the system. 16*78418f30SLyude Paul /// 17*78418f30SLyude Paul /// # Invariants 18*78418f30SLyude Paul /// 19*78418f30SLyude Paul /// `self.0` always holds a valid pointer to an initialized and registered [`struct faux_device`]. 20*78418f30SLyude Paul /// 21*78418f30SLyude Paul /// [`struct faux_device`]: srctree/include/linux/device/faux.h 22*78418f30SLyude Paul #[repr(transparent)] 23*78418f30SLyude Paul pub struct Registration(NonNull<bindings::faux_device>); 24*78418f30SLyude Paul 25*78418f30SLyude Paul impl Registration { 26*78418f30SLyude Paul /// Create and register a new faux device with the given name. 27*78418f30SLyude Paul pub fn new(name: &CStr) -> Result<Self> { 28*78418f30SLyude Paul // SAFETY: 29*78418f30SLyude Paul // - `name` is copied by this function into its own storage 30*78418f30SLyude Paul // - `faux_ops` is safe to leave NULL according to the C API 31*78418f30SLyude Paul let dev = unsafe { bindings::faux_device_create(name.as_char_ptr(), null_mut(), null()) }; 32*78418f30SLyude Paul 33*78418f30SLyude Paul // The above function will return either a valid device, or NULL on failure 34*78418f30SLyude Paul // INVARIANT: The device will remain registered until faux_device_destroy() is called, which 35*78418f30SLyude Paul // happens in our Drop implementation. 36*78418f30SLyude Paul Ok(Self(NonNull::new(dev).ok_or(ENODEV)?)) 37*78418f30SLyude Paul } 38*78418f30SLyude Paul 39*78418f30SLyude Paul fn as_raw(&self) -> *mut bindings::faux_device { 40*78418f30SLyude Paul self.0.as_ptr() 41*78418f30SLyude Paul } 42*78418f30SLyude Paul } 43*78418f30SLyude Paul 44*78418f30SLyude Paul impl AsRef<device::Device> for Registration { 45*78418f30SLyude Paul fn as_ref(&self) -> &device::Device { 46*78418f30SLyude Paul // SAFETY: The underlying `device` in `faux_device` is guaranteed by the C API to be 47*78418f30SLyude Paul // a valid initialized `device`. 48*78418f30SLyude Paul unsafe { device::Device::as_ref(addr_of_mut!((*self.as_raw()).dev)) } 49*78418f30SLyude Paul } 50*78418f30SLyude Paul } 51*78418f30SLyude Paul 52*78418f30SLyude Paul impl Drop for Registration { 53*78418f30SLyude Paul fn drop(&mut self) { 54*78418f30SLyude Paul // SAFETY: `self.0` is a valid registered faux_device via our type invariants. 55*78418f30SLyude Paul unsafe { bindings::faux_device_destroy(self.as_raw()) } 56*78418f30SLyude Paul } 57*78418f30SLyude Paul } 58*78418f30SLyude Paul 59*78418f30SLyude Paul // SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as 60*78418f30SLyude Paul // faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not 61*78418f30SLyude Paul // having Copy/Clone. 62*78418f30SLyude Paul unsafe impl Send for Registration {} 63*78418f30SLyude Paul 64*78418f30SLyude Paul // SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as 65*78418f30SLyude Paul // faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not 66*78418f30SLyude Paul // having Copy/Clone. 67*78418f30SLyude Paul unsafe impl Sync for Registration {} 68