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