Skip to content

Commit

Permalink
Merge pull request #301 from TheSven73/rust-for-linux-pdev-pr3
Browse files Browse the repository at this point in the history
Simple Rust driver that touches real hardware: PR 3/6
  • Loading branch information
alex authored May 27, 2021
2 parents ed19a55 + fa6f1ba commit 698569d
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 13 deletions.
17 changes: 16 additions & 1 deletion drivers/char/hw_random/bcm2835_rng_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use alloc::boxed::Box;
use core::pin::Pin;
use kernel::of::OfMatchTable;
use kernel::platdev::PlatformDriver;
use kernel::prelude::*;
use kernel::{c_str, platdev};

Expand All @@ -19,6 +20,20 @@ module! {
license: b"GPL v2",
}

struct RngDriver;

impl PlatformDriver for RngDriver {
fn probe(device_id: i32) -> Result {
pr_info!("probing discovered hwrng with id {}\n", device_id);
Ok(())
}

fn remove(device_id: i32) -> Result {
pr_info!("removing hwrng with id {}\n", device_id);
Ok(())
}
}

struct RngModule {
_pdev: Pin<Box<platdev::Registration>>,
}
Expand All @@ -27,7 +42,7 @@ impl KernelModule for RngModule {
fn init() -> Result<Self> {
let of_match_tbl = OfMatchTable::new(&c_str!("brcm,bcm2835-rng"))?;

let pdev = platdev::Registration::new_pinned(
let pdev = platdev::Registration::new_pinned::<RngDriver>(
c_str!("bcm2835-rng-rust"),
Some(of_match_tbl),
&THIS_MODULE,
Expand Down
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 698569d

Please sign in to comment.