xref: /linux-6.15/rust/kernel/faux.rs (revision 78418f30)
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