// SPDX-License-Identifier: GPL-2.0-only12//! Abstractions for the faux bus.3//!4//! This module provides bindings for working with faux devices in kernel modules.5//!6//! C header: [`include/linux/device/faux.h`](srctree/include/linux/device/faux.h)78use crate::{bindings, device, error::code::*, prelude::*};9use core::ptr::{addr_of_mut, null, null_mut, NonNull};1011/// The registration of a faux device.12///13/// This type represents the registration of a [`struct faux_device`]. When an instance of this type14/// is dropped, its respective faux device will be unregistered from the system.15///16/// # Invariants17///18/// `self.0` always holds a valid pointer to an initialized and registered [`struct faux_device`].19///20/// [`struct faux_device`]: srctree/include/linux/device/faux.h21pub struct Registration(NonNull<bindings::faux_device>);2223impl Registration {24/// Create and register a new faux device with the given name.25#[inline]26pub fn new(name: &CStr, parent: Option<&device::Device>) -> Result<Self> {27// SAFETY:28// - `name` is copied by this function into its own storage29// - `faux_ops` is safe to leave NULL according to the C API30// - `parent` can be either NULL or a pointer to a `struct device`, and `faux_device_create`31// will take a reference to `parent` using `device_add` - ensuring that it remains valid32// for the lifetime of the faux device.33let dev = unsafe {34bindings::faux_device_create(35name.as_char_ptr(),36parent.map_or(null_mut(), |p| p.as_raw()),37null(),38)39};4041// The above function will return either a valid device, or NULL on failure42// INVARIANT: The device will remain registered until faux_device_destroy() is called, which43// happens in our Drop implementation.44Ok(Self(NonNull::new(dev).ok_or(ENODEV)?))45}4647fn as_raw(&self) -> *mut bindings::faux_device {48self.0.as_ptr()49}50}5152impl AsRef<device::Device> for Registration {53fn as_ref(&self) -> &device::Device {54// SAFETY: The underlying `device` in `faux_device` is guaranteed by the C API to be55// a valid initialized `device`.56unsafe { device::Device::from_raw(addr_of_mut!((*self.as_raw()).dev)) }57}58}5960impl Drop for Registration {61#[inline]62fn drop(&mut self) {63// SAFETY: `self.0` is a valid registered faux_device via our type invariants.64unsafe { bindings::faux_device_destroy(self.as_raw()) }65}66}6768// SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as69// faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not70// having Copy/Clone.71unsafe impl Send for Registration {}7273// SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as74// faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not75// having Copy/Clone.76unsafe impl Sync for Registration {}777879