From fa1e44af1aca236d5f251a28d1195f3fff0b1471 Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Thu, 27 May 2021 14:42:55 -0400 Subject: [PATCH] bcm2835_rng_rust: add support for `DrvData` To demonstrate device driver data in a non-trivial way, create a `miscdev` for each discovered device. This `miscdev` can only be opened and read. When read from userspace, it returns four zero bytes at a time. Note that `DrvData` consists of a `Pin>`, which is a pinned structure. This demonstrates that pinned or self- referential structures may be used in `DrvData`. Signed-off-by: Sven Van Asbroeck --- drivers/char/hw_random/bcm2835_rng_rust.rs | 46 ++++++++++++++++++---- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/drivers/char/hw_random/bcm2835_rng_rust.rs b/drivers/char/hw_random/bcm2835_rng_rust.rs index 4c586c8bac838e..ade4ee95950d24 100644 --- a/drivers/char/hw_random/bcm2835_rng_rust.rs +++ b/drivers/char/hw_random/bcm2835_rng_rust.rs @@ -7,10 +7,16 @@ use alloc::boxed::Box; use core::pin::Pin; -use kernel::of::OfMatchTable; -use kernel::platdev::PlatformDriver; -use kernel::prelude::*; -use kernel::{c_str, platdev}; +use kernel::{ + file::File, + file_operations::{FileOpener, FileOperations}, + io_buffer::IoBufferWriter, + miscdev, + of::OfMatchTable, + platdev::PlatformDriver, + prelude::*, + {c_str, platdev}, +}; module! { type: RngModule, @@ -20,15 +26,41 @@ module! { license: b"GPL v2", } +struct RngDevice; + +impl FileOpener<()> for RngDevice { + fn open(_state: &()) -> Result { + Ok(Box::try_new(RngDevice)?) + } +} + +impl FileOperations for RngDevice { + kernel::declare_file_operations!(read); + + fn read(&self, _: &File, data: &mut T, offset: u64) -> Result { + // Succeed if the caller doesn't provide a buffer or if not at the start. + if data.is_empty() || offset != 0 { + return Ok(0); + } + + data.write(&0_u32)?; + Ok(4) + } +} + struct RngDriver; impl PlatformDriver for RngDriver { - fn probe(device_id: i32) -> Result { + type DrvData = Pin>>; + + fn probe(device_id: i32) -> Result { pr_info!("probing discovered hwrng with id {}\n", device_id); - Ok(()) + let drv_data = + miscdev::Registration::new_pinned::(c_str!("rust_hwrng"), None, ())?; + Ok(drv_data) } - fn remove(device_id: i32) -> Result { + fn remove(device_id: i32, _drv_data: Self::DrvData) -> Result { pr_info!("removing hwrng with id {}\n", device_id); Ok(()) }