@@ -15,23 +15,130 @@ use crate::c_str;
15
15
16
16
pub mod property;
17
17
18
- /// A reference-counted device.
18
+ /// The core representation of a device in the kernel's driver model .
19
19
///
20
- /// This structure represents the Rust abstraction for a C `struct device`. This implementation
21
- /// abstracts the usage of an already existing C `struct device` within Rust code that we get
22
- /// passed from the C side .
20
+ /// This structure represents the Rust abstraction for a C `struct device`. A [`Device`] can either
21
+ /// exist as temporary reference (see also [`Device::from_raw`]), which is only valid within a
22
+ /// certain scope or as [`ARef<Device>`], owning a dedicated reference count .
23
23
///
24
- /// An instance of this abstraction can be obtained temporarily or permanent.
24
+ /// # Device Types
25
25
///
26
- /// A temporary one is bound to the lifetime of the C `struct device` pointer used for creation.
27
- /// A permanent instance is always reference-counted and hence not restricted by any lifetime
28
- /// boundaries.
26
+ /// A [`Device`] can represent either a bus device or a class device.
29
27
///
30
- /// For subsystems it is recommended to create a permanent instance to wrap into a subsystem
31
- /// specific device structure (e.g. `pci::Device`). This is useful for passing it to drivers in
32
- /// `T::probe()`, such that a driver can store the `ARef<Device>` (equivalent to storing a
33
- /// `struct device` pointer in a C driver) for arbitrary purposes, e.g. allocating DMA coherent
34
- /// memory.
28
+ /// ## Bus Devices
29
+ ///
30
+ /// A bus device is a [`Device`] that is associated with a physical or virtual bus. Examples of
31
+ /// buses include PCI, USB, I2C, and SPI. Devices attached to a bus are registered with a specific
32
+ /// bus type, which facilitates matching devices with appropriate drivers based on IDs or other
33
+ /// identifying information. Bus devices are visible in sysfs under `/sys/bus/<bus-name>/devices/`.
34
+ ///
35
+ /// ## Class Devices
36
+ ///
37
+ /// A class device is a [`Device`] that is associated with a logical category of functionality
38
+ /// rather than a physical bus. Examples of classes include block devices, network interfaces, sound
39
+ /// cards, and input devices. Class devices are grouped under a common class and exposed to
40
+ /// userspace via entries in `/sys/class/<class-name>/`.
41
+ ///
42
+ /// # Device Context
43
+ ///
44
+ /// [`Device`] references are generic over a [`DeviceContext`], which represents the type state of
45
+ /// a [`Device`].
46
+ ///
47
+ /// As the name indicates, this type state represents the context of the scope the [`Device`]
48
+ /// reference is valid in. For instance, the [`Bound`] context guarantees that the [`Device`] is
49
+ /// bound to a driver for the entire duration of the existence of a [`Device<Bound>`] reference.
50
+ ///
51
+ /// Other [`DeviceContext`] types besides [`Bound`] are [`Normal`], [`Core`] and [`CoreInternal`].
52
+ ///
53
+ /// Unless selected otherwise [`Device`] defaults to the [`Normal`] [`DeviceContext`], which by
54
+ /// itself has no additional requirements.
55
+ ///
56
+ /// It is always up to the caller of [`Device::from_raw`] to select the correct [`DeviceContext`]
57
+ /// type for the corresponding scope the [`Device`] reference is created in.
58
+ ///
59
+ /// All [`DeviceContext`] types other than [`Normal`] are intended to be used with
60
+ /// [bus devices](#bus-devices) only.
61
+ ///
62
+ /// # Implementing Bus Devices
63
+ ///
64
+ /// This section provides a guideline to implement bus specific devices, such as [`pci::Device`] or
65
+ /// [`platform::Device`].
66
+ ///
67
+ /// A bus specific device should be defined as follows.
68
+ ///
69
+ /// ```ignore
70
+ /// #[repr(transparent)]
71
+ /// pub struct Device<Ctx: device::DeviceContext = device::Normal>(
72
+ /// Opaque<bindings::bus_device_type>,
73
+ /// PhantomData<Ctx>,
74
+ /// );
75
+ /// ```
76
+ ///
77
+ /// Since devices are reference counted, [`AlwaysRefCounted`] should be implemented for `Device`
78
+ /// (i.e. `Device<Normal>`). Note that [`AlwaysRefCounted`] must not be implemented for any other
79
+ /// [`DeviceContext`], since all other device context types are only valid within a certain scope.
80
+ ///
81
+ /// In order to be able to implement the [`DeviceContext`] dereference hierarchy, bus device
82
+ /// implementations should call the [`impl_device_context_deref`] macro as shown below.
83
+ ///
84
+ /// ```ignore
85
+ /// // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s
86
+ /// // generic argument.
87
+ /// kernel::impl_device_context_deref!(unsafe { Device });
88
+ /// ```
89
+ ///
90
+ /// In order to convert from a any [`Device<Ctx>`] to [`ARef<Device>`], bus devices can implement
91
+ /// the following macro call.
92
+ ///
93
+ /// ```ignore
94
+ /// kernel::impl_device_context_into_aref!(Device);
95
+ /// ```
96
+ ///
97
+ /// Bus devices should also implement the following [`AsRef`] implementation, such that users can
98
+ /// easily derive a generic [`Device`] reference.
99
+ ///
100
+ /// ```ignore
101
+ /// impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
102
+ /// fn as_ref(&self) -> &device::Device<Ctx> {
103
+ /// ...
104
+ /// }
105
+ /// }
106
+ /// ```
107
+ ///
108
+ /// # Implementing Class Devices
109
+ ///
110
+ /// Class device implementations require less infrastructure and depend slightly more on the
111
+ /// specific subsystem.
112
+ ///
113
+ /// An example implementation for a class device could look like this.
114
+ ///
115
+ /// ```ignore
116
+ /// #[repr(C)]
117
+ /// pub struct Device<T: class::Driver> {
118
+ /// dev: Opaque<bindings::class_device_type>,
119
+ /// data: T::Data,
120
+ /// }
121
+ /// ```
122
+ ///
123
+ /// This class device uses the sub-classing pattern to embed the driver's private data within the
124
+ /// allocation of the class device. For this to be possible the class device is generic over the
125
+ /// class specific `Driver` trait implementation.
126
+ ///
127
+ /// Just like any device, class devices are reference counted and should hence implement
128
+ /// [`AlwaysRefCounted`] for `Device`.
129
+ ///
130
+ /// Class devices should also implement the following [`AsRef`] implementation, such that users can
131
+ /// easily derive a generic [`Device`] reference.
132
+ ///
133
+ /// ```ignore
134
+ /// impl<T: class::Driver> AsRef<device::Device> for Device<T> {
135
+ /// fn as_ref(&self) -> &device::Device {
136
+ /// ...
137
+ /// }
138
+ /// }
139
+ /// ```
140
+ ///
141
+ /// An example for a class device implementation is [`drm::Device`].
35
142
///
36
143
/// # Invariants
37
144
///
@@ -42,6 +149,12 @@ pub mod property;
42
149
///
43
150
/// `bindings::device::release` is valid to be called from any thread, hence `ARef<Device>` can be
44
151
/// dropped from any thread.
152
+ ///
153
+ /// [`AlwaysRefCounted`]: kernel::types::AlwaysRefCounted
154
+ /// [`drm::Device`]: kernel::drm::Device
155
+ /// [`impl_device_context_deref`]: kernel::impl_device_context_deref
156
+ /// [`pci::Device`]: kernel::pci::Device
157
+ /// [`platform::Device`]: kernel::platform::Device
45
158
#[ repr( transparent) ]
46
159
pub struct Device < Ctx : DeviceContext = Normal > ( Opaque < bindings:: device > , PhantomData < Ctx > ) ;
47
160
0 commit comments