Struct Device

Source
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

Source

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.

Source

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>

Source

pub fn set_drvdata(&self, data: impl ForeignOwnable)

Store a pointer to the bound driver’s private data.

Source

pub unsafe fn drvdata_obtain<T: ForeignOwnable>(&self) -> T

Take ownership of the private data stored in this Device.

§Safety
Source

pub unsafe fn drvdata_borrow<T: ForeignOwnable>(&self) -> T::Borrowed<'_>

Borrow the driver’s private data bound to this Device.

§Safety
Source§

impl<Ctx: DeviceContext> Device<Ctx>

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn pr_dbg(&self, args: Arguments<'_>)

Prints a debug-level message (level 7) prefixed with device information.

More details are available from dev_dbg.

Source

pub fn fwnode(&self) -> Option<&FwNode>

Obtain the FwNode corresponding to this Device.

Trait Implementations§

Source§

impl AlwaysRefCounted for Device

Source§

fn inc_ref(&self)

Increments the reference count on the object.
Source§

unsafe fn dec_ref(obj: NonNull<Self>)

Decrements the reference count on the object. Read more
Source§

impl<Ctx: DeviceContext> AsRef<Device<Ctx>> for Device<Ctx>

Source§

fn as_ref(&self) -> &Device<Ctx>

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl<Ctx: DeviceContext> AsRef<Device<Ctx>> for Device<Ctx>

Source§

fn as_ref(&self) -> &Device<Ctx>

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl<Ctx: DeviceContext> AsRef<Device<Ctx>> for Device<Ctx>

Source§

fn as_ref(&self) -> &Device<Ctx>

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl AsRef<Device> for Device

Source§

fn as_ref(&self) -> &Device

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl<T: Driver> AsRef<Device> for Device<T>

Source§

fn as_ref(&self) -> &Device

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl AsRef<Device> for Registration

Source§

fn as_ref(&self) -> &Device

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl Deref for Device<Bound>

Source§

type Target = Device

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl Deref for Device<Core>

Source§

type Target = Device<Bound>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl Deref for Device<CoreInternal>

Source§

type Target = Device<Core>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl From<&Device<Bound>> for ARef<Device>

Source§

fn from(dev: &Device<Bound>) -> Self

Converts to this type from the input type.
Source§

impl From<&Device<Core>> for ARef<Device>

Source§

fn from(dev: &Device<Core>) -> Self

Converts to this type from the input type.
Source§

impl From<&Device<CoreInternal>> for ARef<Device>

Source§

fn from(dev: &Device<CoreInternal>) -> Self

Converts to this type from the input type.
Source§

impl<Ctx: DeviceContext> TryFrom<&Device<Ctx>> for &Device<Ctx>

Source§

type Error = Error

The type returned in the event of a conversion error.
Source§

fn try_from(dev: &Device<Ctx>) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<Ctx: DeviceContext> TryFrom<&Device<Ctx>> for &Device<Ctx>

Source§

type Error = Error

The type returned in the event of a conversion error.
Source§

fn try_from(dev: &Device<Ctx>) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl Send for Device

Source§

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Init<T> for T

Source§

unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible>

Initializes slot. Read more
Source§

fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
where F: FnOnce(&mut T) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PinInit<T> for T

Source§

unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible>

Initializes slot. Read more
Source§

fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
where F: FnOnce(Pin<&mut T>) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. Read more
Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.