Commit fdb1ac6c authored by Lee Jones's avatar Lee Jones Committed by Greg Kroah-Hartman
Browse files

samples: rust: Provide example using the new Rust MiscDevice abstraction



This sample driver demonstrates the following basic operations:

* Register a Misc Device
* Create /dev/rust-misc-device
* Provide open call-back for the aforementioned character device
* Operate on the character device via a simple ioctl()
* Provide close call-back for the character device

Signed-off-by: default avatarLee Jones <lee@kernel.org>
Reviewed-by: default avatarDanilo Krummrich <dakr@kernel.org>
Link: https://lore.kernel.org/r/20241213134715.601415-3-lee@kernel.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4a9ce188
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -20,6 +20,16 @@ config SAMPLE_RUST_MINIMAL

	  If unsure, say N.

config SAMPLE_RUST_MISC_DEVICE
	tristate "Misc device"
	help
	  This option builds the Rust misc device.

	  To compile this as a module, choose M here:
	  the module will be called rust_misc_device.

	  If unsure, say N.

config SAMPLE_RUST_PRINT
	tristate "Printing macros"
	help
+1 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
ccflags-y += -I$(src)				# needed for trace events

obj-$(CONFIG_SAMPLE_RUST_MINIMAL)		+= rust_minimal.o
obj-$(CONFIG_SAMPLE_RUST_MISC_DEVICE)		+= rust_misc_device.o
obj-$(CONFIG_SAMPLE_RUST_PRINT)			+= rust_print.o

rust_print-y := rust_print_main.o rust_print_events.o
+87 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0

// Copyright (C) 2024 Google LLC.

//! Rust misc device sample.

use kernel::{
    c_str,
    device::Device,
    fs::File,
    ioctl::_IO,
    miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration},
    prelude::*,
    types::ARef,
};

const RUST_MISC_DEV_HELLO: u32 = _IO('|' as u32, 0x80);

module! {
    type: RustMiscDeviceModule,
    name: "rust_misc_device",
    author: "Lee Jones",
    description: "Rust misc device sample",
    license: "GPL",
}

#[pin_data]
struct RustMiscDeviceModule {
    #[pin]
    _miscdev: MiscDeviceRegistration<RustMiscDevice>,
}

impl kernel::InPlaceModule for RustMiscDeviceModule {
    fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
        pr_info!("Initialising Rust Misc Device Sample\n");

        let options = MiscDeviceOptions {
            name: c_str!("rust-misc-device"),
        };

        try_pin_init!(Self {
            _miscdev <- MiscDeviceRegistration::register(options),
        })
    }
}

struct RustMiscDevice {
    dev: ARef<Device>,
}

#[vtable]
impl MiscDevice for RustMiscDevice {
    type Ptr = KBox<Self>;

    fn open(_file: &File, misc: &MiscDeviceRegistration<Self>) -> Result<KBox<Self>> {
        let dev = ARef::from(misc.device());

        dev_info!(dev, "Opening Rust Misc Device Sample\n");

        Ok(KBox::new(RustMiscDevice { dev }, GFP_KERNEL)?)
    }

    fn ioctl(
        me: <Self::Ptr as kernel::types::ForeignOwnable>::Borrowed<'_>,
        _file: &File,
        cmd: u32,
        _arg: usize,
    ) -> Result<isize> {
        dev_info!(me.dev, "IOCTLing Rust Misc Device Sample\n");

        match cmd {
            RUST_MISC_DEV_HELLO => dev_info!(me.dev, "Hello from the Rust Misc Device\n"),
            _ => {
                dev_err!(me.dev, "-> IOCTL not recognised: {}\n", cmd);
                return Err(ENOTTY);
            }
        }

        Ok(0)
    }
}

impl Drop for RustMiscDevice {
    fn drop(&mut self) {
        dev_info!(self.dev, "Exiting the Rust Misc Device Sample\n");
    }
}