@@ -15,23 +15,130 @@ use crate::c_str;
1515
1616pub mod property;
1717
18- /// A reference-counted device.
18+ /// The core representation of a device in the kernel's driver model .
1919///
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 .
2323///
24- /// An instance of this abstraction can be obtained temporarily or permanent.
24+ /// # Device Types
2525///
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.
2927///
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`].
35142///
36143/// # Invariants
37144///
@@ -42,6 +149,12 @@ pub mod property;
42149///
43150/// `bindings::device::release` is valid to be called from any thread, hence `ARef<Device>` can be
44151/// 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
45158#[ repr( transparent) ]
46159pub struct Device < Ctx : DeviceContext = Normal > ( Opaque < bindings:: device > , PhantomData < Ctx > ) ;
47160
0 commit comments