};
#define to_driver(obj) container_of(obj, struct driver_private, kobj)
-#ifdef CONFIG_RUST
-/**
- * struct driver_type - Representation of a Rust driver type.
- */
-struct driver_type {
- /**
- * @id: Representation of core::any::TypeId.
- */
- u8 id[16];
-} __packed;
-#endif
-
/**
* struct device_private - structure to hold the private to the driver core
* portions of the device structure.
* dev_err_probe() for later retrieval via debugfs
* @device: pointer back to the struct device that this structure is
* associated with.
- * @driver_type: The type of the bound Rust driver.
* @dead: This device is currently either in the process of or has been
* removed from the system. Any asynchronous events scheduled for this
* device should exit without taking any action.
const struct device_driver *async_driver;
char *deferred_probe_reason;
struct device *device;
-#ifdef CONFIG_RUST
- struct driver_type driver_type;
-#endif
u8 dead:1;
};
#define to_device_private_parent(obj) \
}, //
};
use core::{
- any::TypeId,
marker::PhantomData,
ptr, //
};
pub mod property;
-// Assert that we can `read()` / `write()` a `TypeId` instance from / into `struct driver_type`.
-static_assert!(core::mem::size_of::<bindings::driver_type>() >= core::mem::size_of::<TypeId>());
-
/// 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
}
impl Device<CoreInternal> {
- fn set_type_id<T: 'static>(&self) {
- // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
- let private = unsafe { (*self.as_raw()).p };
-
- // SAFETY: For a bound device (implied by the `CoreInternal` device context), `private` is
- // guaranteed to be a valid pointer to a `struct device_private`.
- let driver_type = unsafe { &raw mut (*private).driver_type };
-
- // SAFETY: `driver_type` is valid for (unaligned) writes of a `TypeId`.
- unsafe {
- driver_type
- .cast::<TypeId>()
- .write_unaligned(TypeId::of::<T>())
- };
- }
-
/// Store a pointer to the bound driver's private data.
pub fn set_drvdata<T: 'static>(&self, data: impl PinInit<T, Error>) -> Result {
let data = KBox::pin_init(data, GFP_KERNEL)?;
// SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
unsafe { bindings::dev_set_drvdata(self.as_raw(), data.into_foreign().cast()) };
- self.set_type_id::<T>();
Ok(())
}
// in `into_foreign()`.
unsafe { Pin::<KBox<T>>::borrow(ptr.cast()) }
}
-
- fn match_type_id<T: 'static>(&self) -> Result {
- // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
- let private = unsafe { (*self.as_raw()).p };
-
- // SAFETY: For a bound device, `private` is guaranteed to be a valid pointer to a
- // `struct device_private`.
- let driver_type = unsafe { &raw mut (*private).driver_type };
-
- // SAFETY:
- // - `driver_type` is valid for (unaligned) reads of a `TypeId`.
- // - A bound device guarantees that `driver_type` contains a valid `TypeId` value.
- let type_id = unsafe { driver_type.cast::<TypeId>().read_unaligned() };
-
- if type_id != TypeId::of::<T>() {
- return Err(EINVAL);
- }
-
- Ok(())
- }
-
- /// Access a driver's private data.
- ///
- /// Returns a pinned reference to the driver's private data or [`EINVAL`] if it doesn't match
- /// the asserted type `T`.
- pub fn drvdata<T: 'static>(&self) -> Result<Pin<&T>> {
- // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
- if unsafe { bindings::dev_get_drvdata(self.as_raw()) }.is_null() {
- return Err(ENOENT);
- }
-
- self.match_type_id::<T>()?;
-
- // SAFETY:
- // - The above check of `dev_get_drvdata()` guarantees that we are called after
- // `set_drvdata()`.
- // - We've just checked that the type of the driver's private data is in fact `T`.
- Ok(unsafe { self.drvdata_unchecked() })
- }
}
impl<Ctx: DeviceContext> Device<Ctx> {