pub struct Device<Ctx: DeviceContext = Normal>(/* private fields */);
Expand description
The core representation of a device in the kernel’s driver model.
This structure represents the Rust abstraction for a C struct device
. A Device
can either
exist as temporary reference (see also Device::from_raw
), which is only valid within a
certain scope or as ARef<Device>
, owning a dedicated reference count.
§Device Types
A Device
can represent either a bus device or a class device.
§Bus Devices
A bus device is a Device
that is associated with a physical or virtual bus. Examples of
buses include PCI, USB, I2C, and SPI. Devices attached to a bus are registered with a specific
bus type, which facilitates matching devices with appropriate drivers based on IDs or other
identifying information. Bus devices are visible in sysfs under /sys/bus/<bus-name>/devices/
.
§Class Devices
A class device is a Device
that is associated with a logical category of functionality
rather than a physical bus. Examples of classes include block devices, network interfaces, sound
cards, and input devices. Class devices are grouped under a common class and exposed to
userspace via entries in /sys/class/<class-name>/
.
§Device Context
Device
references are generic over a DeviceContext
, which represents the type state of
a Device
.
As the name indicates, this type state represents the context of the scope the Device
reference is valid in. For instance, the Bound
context guarantees that the Device
is
bound to a driver for the entire duration of the existence of a Device<Bound>
reference.
Other DeviceContext
types besides Bound
are Normal
, Core
and CoreInternal
.
Unless selected otherwise Device
defaults to the Normal
DeviceContext
, which by
itself has no additional requirements.
It is always up to the caller of Device::from_raw
to select the correct DeviceContext
type for the corresponding scope the Device
reference is created in.
All DeviceContext
types other than Normal
are intended to be used with
bus devices only.
§Implementing Bus Devices
This section provides a guideline to implement bus specific devices, such as pci::Device
or
platform::Device
.
A bus specific device should be defined as follows.
#[repr(transparent)]
pub struct Device<Ctx: device::DeviceContext = device::Normal>(
Opaque<bindings::bus_device_type>,
PhantomData<Ctx>,
);
Since devices are reference counted, AlwaysRefCounted
should be implemented for Device
(i.e. Device<Normal>
). Note that AlwaysRefCounted
must not be implemented for any other
DeviceContext
, since all other device context types are only valid within a certain scope.
In order to be able to implement the DeviceContext
dereference hierarchy, bus device
implementations should call the impl_device_context_deref
macro as shown below.
// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s
// generic argument.
kernel::impl_device_context_deref!(unsafe { Device });
In order to convert from a any Device<Ctx>
to ARef<Device>
, bus devices can implement
the following macro call.
kernel::impl_device_context_into_aref!(Device);
Bus devices should also implement the following AsRef
implementation, such that users can
easily derive a generic Device
reference.
impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
fn as_ref(&self) -> &device::Device<Ctx> {
...
}
}
§Implementing Class Devices
Class device implementations require less infrastructure and depend slightly more on the specific subsystem.
An example implementation for a class device could look like this.
#[repr(C)]
pub struct Device<T: class::Driver> {
dev: Opaque<bindings::class_device_type>,
data: T::Data,
}
This class device uses the sub-classing pattern to embed the driver’s private data within the
allocation of the class device. For this to be possible the class device is generic over the
class specific Driver
trait implementation.
Just like any device, class devices are reference counted and should hence implement
AlwaysRefCounted
for Device
.
Class devices should also implement the following AsRef
implementation, such that users can
easily derive a generic Device
reference.
impl<T: class::Driver> AsRef<device::Device> for Device<T> {
fn as_ref(&self) -> &device::Device {
...
}
}
An example for a class device implementation is drm::Device
.
§Invariants
A Device
instance represents a valid struct device
created by the C portion of the kernel.
Instances of this type are always reference-counted, that is, a call to get_device
ensures
that the allocation remains valid at least until the matching call to put_device
.
bindings::device::release
is valid to be called from any thread, hence ARef<Device>
can be
dropped from any thread.
Implementations§
Source§impl Device
impl Device
Sourcepub unsafe fn get_device(ptr: *mut device) -> ARef<Self>
pub unsafe fn get_device(ptr: *mut device) -> ARef<Self>
Creates a new reference-counted abstraction instance of an existing struct device
pointer.
§Safety
Callers must ensure that ptr
is valid, non-null, and has a non-zero reference count,
i.e. it must be ensured that the reference count of the C struct device
ptr
points to
can’t drop to zero, for the duration of this function call.
It must also be ensured that bindings::device::release
can be called from any thread.
While not officially documented, this should be the case for any struct device
.
Sourcepub unsafe fn as_bound(&self) -> &Device<Bound>
pub unsafe fn as_bound(&self) -> &Device<Bound>
Convert a &Device
into a &Device<Bound>
.
§Safety
The caller is responsible to ensure that the returned &Device<Bound>
only lives as long as it can be guaranteed that the Device
is actually bound.
Source§impl Device<CoreInternal>
impl Device<CoreInternal>
Sourcepub fn set_drvdata(&self, data: impl ForeignOwnable)
pub fn set_drvdata(&self, data: impl ForeignOwnable)
Store a pointer to the bound driver’s private data.
Sourcepub unsafe fn drvdata_obtain<T: ForeignOwnable>(&self) -> T
pub unsafe fn drvdata_obtain<T: ForeignOwnable>(&self) -> T
Take ownership of the private data stored in this Device
.
§Safety
- Must only be called once after a preceding call to
Device::set_drvdata
. - The type
T
must match the type of theForeignOwnable
previously stored byDevice::set_drvdata
.
Sourcepub unsafe fn drvdata_borrow<T: ForeignOwnable>(&self) -> T::Borrowed<'_>
pub unsafe fn drvdata_borrow<T: ForeignOwnable>(&self) -> T::Borrowed<'_>
Borrow the driver’s private data bound to this Device
.
§Safety
- Must only be called after a preceding call to
Device::set_drvdata
and beforeDevice::drvdata_obtain
. - The type
T
must match the type of theForeignOwnable
previously stored byDevice::set_drvdata
.
Source§impl<Ctx: DeviceContext> Device<Ctx>
impl<Ctx: DeviceContext> Device<Ctx>
Sourcepub unsafe fn from_raw<'a>(ptr: *mut device) -> &'a Self
pub unsafe fn from_raw<'a>(ptr: *mut device) -> &'a Self
Convert a raw C struct device
pointer to a &'a Device
.
§Safety
Callers must ensure that ptr
is valid, non-null, and has a non-zero reference count,
i.e. it must be ensured that the reference count of the C struct device
ptr
points to
can’t drop to zero, for the duration of this function call and the entire duration when the
returned reference exists.
Sourcepub fn pr_emerg(&self, args: Arguments<'_>)
pub fn pr_emerg(&self, args: Arguments<'_>)
Prints an emergency-level message (level 0) prefixed with device information.
More details are available from dev_emerg
.
Sourcepub fn pr_alert(&self, args: Arguments<'_>)
pub fn pr_alert(&self, args: Arguments<'_>)
Prints an alert-level message (level 1) prefixed with device information.
More details are available from dev_alert
.
Sourcepub fn pr_crit(&self, args: Arguments<'_>)
pub fn pr_crit(&self, args: Arguments<'_>)
Prints a critical-level message (level 2) prefixed with device information.
More details are available from dev_crit
.
Sourcepub fn pr_err(&self, args: Arguments<'_>)
pub fn pr_err(&self, args: Arguments<'_>)
Prints an error-level message (level 3) prefixed with device information.
More details are available from dev_err
.
Sourcepub fn pr_warn(&self, args: Arguments<'_>)
pub fn pr_warn(&self, args: Arguments<'_>)
Prints a warning-level message (level 4) prefixed with device information.
More details are available from dev_warn
.
Sourcepub fn pr_notice(&self, args: Arguments<'_>)
pub fn pr_notice(&self, args: Arguments<'_>)
Prints a notice-level message (level 5) prefixed with device information.
More details are available from dev_notice
.
Sourcepub fn pr_info(&self, args: Arguments<'_>)
pub fn pr_info(&self, args: Arguments<'_>)
Prints an info-level message (level 6) prefixed with device information.
More details are available from dev_info
.
Trait Implementations§
Source§impl AlwaysRefCounted for Device
impl AlwaysRefCounted for Device
Source§impl AsRef<Device> for Registration
impl AsRef<Device> for Registration
Source§impl Deref for Device<CoreInternal>
impl Deref for Device<CoreInternal>
Source§impl From<&Device<CoreInternal>> for ARef<Device>
impl From<&Device<CoreInternal>> for ARef<Device>
Source§fn from(dev: &Device<CoreInternal>) -> Self
fn from(dev: &Device<CoreInternal>) -> Self
impl Send for Device
impl Sync for Device
Auto Trait Implementations§
impl<Ctx = Normal> !Freeze for Device<Ctx>
impl<Ctx = Normal> !RefUnwindSafe for Device<Ctx>
impl<Ctx = Normal> !Send for Device<Ctx>
impl<Ctx = Normal> !Sync for Device<Ctx>
impl<Ctx = Normal> !Unpin for Device<Ctx>
impl<Ctx> UnwindSafe for Device<Ctx>where
Ctx: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> PinInit<T> for T
impl<T> PinInit<T> for T
Source§unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible>
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible>
slot
. Read more