xref: /linux/rust/kernel/faux.rs (revision eb3dad518e4da48ab6c6df16aa8895b8b0bd6ecf)
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 
9 use crate::{
10     bindings,
11     device,
12     prelude::*, //
13 };
14 use 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
31 pub struct Registration(NonNull<bindings::faux_device>);
32 
33 impl 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 
62 impl 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 
70 impl 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.
81 unsafe 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.
86 unsafe impl Sync for Registration {}
87