Skip to content

Commit

Permalink
rust-core/platdev: add simple PlatformDriver trait
Browse files Browse the repository at this point in the history
Add the `PlatformDriver` trait, which driver writers may implement
in order to define a platform driver in the kernel.

For sake of simplicity and ease of review, `PlatformDriver` consists
of two functions for now - `probe()` and `remove()`.

Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
  • Loading branch information
Sven Van Asbroeck committed May 26, 2021
1 parent 7fde08b commit 22fe6d2
Showing 1 changed file with 41 additions and 12 deletions.
53 changes: 41 additions & 12 deletions rust/kernel/platdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use crate::{
bindings, c_types,
error::{Error, Result},
from_kernel_result,
of::OfMatchTable,
pr_info,
str::CStr,
types::PointerWrapper,
};
Expand All @@ -30,18 +30,30 @@ pub struct Registration {
// (it is fine for multiple threads to have a shared reference to it).
unsafe impl Sync for Registration {}

extern "C" fn probe_callback(_pdev: *mut bindings::platform_device) -> c_types::c_int {
pr_info!("Rust platform_device probed\n");
0
extern "C" fn probe_callback<P: PlatformDriver>(
pdev: *mut bindings::platform_device,
) -> c_types::c_int {
from_kernel_result! {
// SAFETY: `pdev` is guaranteed to be a valid, non-null pointer.
let device_id = unsafe { (*pdev).id };
P::probe(device_id)?;
Ok(0)
}
}

extern "C" fn remove_callback(_pdev: *mut bindings::platform_device) -> c_types::c_int {
pr_info!("Rust platform_device removed\n");
0
extern "C" fn remove_callback<P: PlatformDriver>(
pdev: *mut bindings::platform_device,
) -> c_types::c_int {
from_kernel_result! {
// SAFETY: `pdev` is guaranteed to be a valid, non-null pointer.
let device_id = unsafe { (*pdev).id };
P::remove(device_id)?;
Ok(0)
}
}

impl Registration {
fn register(
fn register<P: PlatformDriver>(
self: Pin<&mut Self>,
name: &'static CStr,
of_match_table: Option<OfMatchTable>,
Expand All @@ -59,8 +71,8 @@ impl Registration {
this.of_table = Some(ptr);
this.pdrv.driver.of_match_table = ptr.cast();
}
this.pdrv.probe = Some(probe_callback);
this.pdrv.remove = Some(remove_callback);
this.pdrv.probe = Some(probe_callback::<P>);
this.pdrv.remove = Some(remove_callback::<P>);
// SAFETY:
// - `this.pdrv` lives at least until the call to `platform_driver_unregister()` returns.
// - `name` pointer has static lifetime.
Expand All @@ -81,13 +93,13 @@ impl Registration {
/// Registers a platform device.
///
/// Returns a pinned heap-allocated representation of the registration.
pub fn new_pinned(
pub fn new_pinned<P: PlatformDriver>(
name: &'static CStr,
of_match_tbl: Option<OfMatchTable>,
module: &'static crate::ThisModule,
) -> Result<Pin<Box<Self>>> {
let mut r = Pin::from(Box::try_new(Self::default())?);
r.as_mut().register(name, of_match_tbl, module)?;
r.as_mut().register::<P>(name, of_match_tbl, module)?;
Ok(r)
}
}
Expand All @@ -107,3 +119,20 @@ impl Drop for Registration {
}
}
}

/// Trait for implementers of platform drivers.
///
/// Implement this trait whenever you create a platform driver.
pub trait PlatformDriver {
/// Platform driver probe.
///
/// Called when a new platform device is added or discovered.
/// Implementers should attempt to initialize the device here.
fn probe(device_id: i32) -> Result;

/// Platform driver remove.
///
/// Called when a platform device is removed.
/// Implementers should prepare the device for complete removal here.
fn remove(device_id: i32) -> Result;
}

0 comments on commit 22fe6d2

Please sign in to comment.