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