Provide an initial sample LED driver that just prints the current requested LED state. This is not intended to be merged, but as a placeholder until the abstactions for hardware access are written. Signed-off-by: Fiona Behrens <me@xxxxxxxxxx> --- samples/rust/Kconfig | 10 ++++ samples/rust/Makefile | 1 + samples/rust/rust_led.rs | 103 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 samples/rust/rust_led.rs diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index b0f74a81c8f9..910f15ef6951 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -30,6 +30,16 @@ config SAMPLE_RUST_PRINT If unsure, say N. +config SAMPLE_RUST_LED + tristate "Led subsystem" + help + This option builds the Rust LED subsystem sample. + + To compile this as a module, choose M here: + the module will be called rust_led. + + If unsure, say N. + config SAMPLE_RUST_HOSTPROGS bool "Host programs" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 03086dabbea4..1299ca1e9ebb 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -2,5 +2,6 @@ obj-$(CONFIG_SAMPLE_RUST_MINIMAL) += rust_minimal.o obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o +obj-$(CONFIG_SAMPLE_RUST_LED) += rust_led.o subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs diff --git a/samples/rust/rust_led.rs b/samples/rust/rust_led.rs new file mode 100644 index 000000000000..0085f7484ea1 --- /dev/null +++ b/samples/rust/rust_led.rs @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +//! Rust LED sample. + +use core::time::Duration; + +use kernel::c_str; +use kernel::leds::{Brightness, Color, Led, LedConfig, Operations}; +use kernel::prelude::*; + +module! { + type: RustLed, + name: "rust_led", + author: "Rust for Linux Contributors", + description: "Rust led sample", + license: "GPL", +} + +/// Rust LED sample driver +// Hold references in scope as droping would unregister the LED +#[allow(dead_code)] +struct RustLed { + /// LED which just supports on/off. + on_off: Pin<Box<Led<LedOnOff>>>, + /// LED which supports brightness levels and blinking. + blink: Pin<Box<Led<LedBlinking>>>, +} + +impl kernel::Module for RustLed { + fn init(_module: &'static ThisModule) -> Result<Self> { + pr_info!("registering on_off led\n"); + let on_off = Box::pin_init( + Led::register_with_name( + c_str!("sample:red:on_off"), + None, + &LedConfig { color: Color::Red }, + LedOnOff, + ), + GFP_KERNEL, + )?; + + let blink = Box::pin_init( + Led::register_with_name( + c_str!("sample:green:blink"), + None, + &LedConfig { + color: Color::Green, + }, + LedBlinking, + ), + GFP_KERNEL, + )?; + + Ok(Self { on_off, blink }) + } +} + +struct LedOnOff; + +#[vtable] +impl Operations for LedOnOff { + const MAX_BRIGHTNESS: u8 = 1; + + fn brightness_set(_this: &mut Led<Self>, brightness: Brightness) { + match brightness { + Brightness::Off => pr_info!("Switching led off\n"), + Brightness::On(v) => pr_info!("Switching led on: {}\n", v.get()), + } + } +} + +struct LedBlinking; + +impl LedBlinking { + const HW_DURATION: Duration = Duration::from_millis(1000); +} + +#[vtable] +impl Operations for LedBlinking { + const MAX_BRIGHTNESS: u8 = 255; + + fn brightness_set(_this: &mut Led<Self>, brightness: Brightness) { + match brightness { + Brightness::Off => pr_info!("blinking: off\n"), + Brightness::On(v) => pr_info!("blinking: on at {}\n", v.get()), + } + } + + fn blink_set( + _this: &mut Led<Self>, + delay_on: Duration, + delay_off: Duration, + ) -> Result<(Duration, Duration)> { + pr_info!("blinking: try delay {delay_on:?} {delay_off:?}\n"); + if !(delay_on.is_zero() && delay_off.is_zero()) + && !(delay_on == Self::HW_DURATION && delay_off == Self::HW_DURATION) + { + return Err(EINVAL); + } + + pr_info!("blinking: setting dealy\n"); + Ok((Self::HW_DURATION, Self::HW_DURATION)) + } +} -- 2.46.0