| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- // SPDX-License-Identifier: GPL-2.0
- //! Rust configfs sample.
- use kernel::alloc::flags;
- use kernel::configfs;
- use kernel::configfs::configfs_attrs;
- use kernel::new_mutex;
- use kernel::page::PAGE_SIZE;
- use kernel::prelude::*;
- use kernel::sync::Mutex;
- module! {
- type: RustConfigfs,
- name: "rust_configfs",
- authors: ["Rust for Linux Contributors"],
- description: "Rust configfs sample",
- license: "GPL",
- }
- #[pin_data]
- struct RustConfigfs {
- #[pin]
- config: configfs::Subsystem<Configuration>,
- }
- #[pin_data]
- struct Configuration {
- message: &'static CStr,
- #[pin]
- bar: Mutex<(KBox<[u8; PAGE_SIZE]>, usize)>,
- }
- impl Configuration {
- fn new() -> impl PinInit<Self, Error> {
- try_pin_init!(Self {
- message: c"Hello World\n",
- bar <- new_mutex!((KBox::new([0; PAGE_SIZE], flags::GFP_KERNEL)?, 0)),
- })
- }
- }
- impl kernel::InPlaceModule for RustConfigfs {
- fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
- pr_info!("Rust configfs sample (init)\n");
- // Define a subsystem with the data type `Configuration`, two
- // attributes, `message` and `bar` and child group type `Child`. `mkdir`
- // in the directory representing this subsystem will create directories
- // backed by the `Child` type.
- let item_type = configfs_attrs! {
- container: configfs::Subsystem<Configuration>,
- data: Configuration,
- child: Child,
- attributes: [
- message: 0,
- bar: 1,
- ],
- };
- try_pin_init!(Self {
- config <- configfs::Subsystem::new(
- c"rust_configfs", item_type, Configuration::new()
- ),
- })
- }
- }
- #[vtable]
- impl configfs::GroupOperations for Configuration {
- type Child = Child;
- fn make_group(&self, name: &CStr) -> Result<impl PinInit<configfs::Group<Child>, Error>> {
- // Define a group with data type `Child`, one attribute `baz` and child
- // group type `GrandChild`. `mkdir` in the directory representing this
- // group will create directories backed by the `GrandChild` type.
- let tpe = configfs_attrs! {
- container: configfs::Group<Child>,
- data: Child,
- child: GrandChild,
- attributes: [
- baz: 0,
- ],
- };
- Ok(configfs::Group::new(name.try_into()?, tpe, Child::new()))
- }
- }
- #[vtable]
- impl configfs::AttributeOperations<0> for Configuration {
- type Data = Configuration;
- fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
- pr_info!("Show message\n");
- let data = container.message.to_bytes();
- page[0..data.len()].copy_from_slice(data);
- Ok(data.len())
- }
- }
- #[vtable]
- impl configfs::AttributeOperations<1> for Configuration {
- type Data = Configuration;
- fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
- pr_info!("Show bar\n");
- let guard = container.bar.lock();
- let data = guard.0.as_slice();
- let len = guard.1;
- page[0..len].copy_from_slice(&data[0..len]);
- Ok(len)
- }
- fn store(container: &Configuration, page: &[u8]) -> Result {
- pr_info!("Store bar\n");
- let mut guard = container.bar.lock();
- guard.0[0..page.len()].copy_from_slice(page);
- guard.1 = page.len();
- Ok(())
- }
- }
- // `pin_data` cannot handle structs without braces.
- #[pin_data]
- struct Child {}
- impl Child {
- fn new() -> impl PinInit<Self, Error> {
- try_pin_init!(Self {})
- }
- }
- #[vtable]
- impl configfs::GroupOperations for Child {
- type Child = GrandChild;
- fn make_group(&self, name: &CStr) -> Result<impl PinInit<configfs::Group<GrandChild>, Error>> {
- // Define a group with data type `GrandChild`, one attribute `gc`. As no
- // child type is specified, it will not be possible to create subgroups
- // in this group, and `mkdir`in the directory representing this group
- // will return an error.
- let tpe = configfs_attrs! {
- container: configfs::Group<GrandChild>,
- data: GrandChild,
- attributes: [
- gc: 0,
- ],
- };
- Ok(configfs::Group::new(
- name.try_into()?,
- tpe,
- GrandChild::new(),
- ))
- }
- }
- #[vtable]
- impl configfs::AttributeOperations<0> for Child {
- type Data = Child;
- fn show(_container: &Child, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
- pr_info!("Show baz\n");
- let data = c"Hello Baz\n".to_bytes();
- page[0..data.len()].copy_from_slice(data);
- Ok(data.len())
- }
- }
- // `pin_data` cannot handle structs without braces.
- #[pin_data]
- struct GrandChild {}
- impl GrandChild {
- fn new() -> impl PinInit<Self, Error> {
- try_pin_init!(Self {})
- }
- }
- #[vtable]
- impl configfs::AttributeOperations<0> for GrandChild {
- type Data = GrandChild;
- fn show(_container: &GrandChild, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
- pr_info!("Show grand child\n");
- let data = c"Hello GC\n".to_bytes();
- page[0..data.len()].copy_from_slice(data);
- Ok(data.len())
- }
- }
|