xref: /linux/samples/rust/rust_configfs.rs (revision a3a7d09ab8bf881ea64aa8f33c76554ab9b5f6d6)
11bfb1050SAndreas Hindborg // SPDX-License-Identifier: GPL-2.0
21bfb1050SAndreas Hindborg 
31bfb1050SAndreas Hindborg //! Rust configfs sample.
41bfb1050SAndreas Hindborg 
51bfb1050SAndreas Hindborg use kernel::alloc::flags;
61bfb1050SAndreas Hindborg use kernel::c_str;
71bfb1050SAndreas Hindborg use kernel::configfs;
81bfb1050SAndreas Hindborg use kernel::configfs_attrs;
91bfb1050SAndreas Hindborg use kernel::new_mutex;
101bfb1050SAndreas Hindborg use kernel::page::PAGE_SIZE;
111bfb1050SAndreas Hindborg use kernel::prelude::*;
121bfb1050SAndreas Hindborg use kernel::sync::Mutex;
131bfb1050SAndreas Hindborg 
141bfb1050SAndreas Hindborg module! {
151bfb1050SAndreas Hindborg     type: RustConfigfs,
161bfb1050SAndreas Hindborg     name: "rust_configfs",
17bfb9e46bSGuilherme Giacomo Simoes     authors: ["Rust for Linux Contributors"],
181bfb1050SAndreas Hindborg     description: "Rust configfs sample",
191bfb1050SAndreas Hindborg     license: "GPL",
201bfb1050SAndreas Hindborg }
211bfb1050SAndreas Hindborg 
221bfb1050SAndreas Hindborg #[pin_data]
231bfb1050SAndreas Hindborg struct RustConfigfs {
241bfb1050SAndreas Hindborg     #[pin]
251bfb1050SAndreas Hindborg     config: configfs::Subsystem<Configuration>,
261bfb1050SAndreas Hindborg }
271bfb1050SAndreas Hindborg 
281bfb1050SAndreas Hindborg #[pin_data]
291bfb1050SAndreas Hindborg struct Configuration {
301bfb1050SAndreas Hindborg     message: &'static CStr,
311bfb1050SAndreas Hindborg     #[pin]
321bfb1050SAndreas Hindborg     bar: Mutex<(KBox<[u8; PAGE_SIZE]>, usize)>,
331bfb1050SAndreas Hindborg }
341bfb1050SAndreas Hindborg 
351bfb1050SAndreas Hindborg impl Configuration {
361bfb1050SAndreas Hindborg     fn new() -> impl PinInit<Self, Error> {
371bfb1050SAndreas Hindborg         try_pin_init!(Self {
381bfb1050SAndreas Hindborg             message: c_str!("Hello World\n"),
391bfb1050SAndreas Hindborg             bar <- new_mutex!((KBox::new([0; PAGE_SIZE], flags::GFP_KERNEL)?, 0)),
401bfb1050SAndreas Hindborg         })
411bfb1050SAndreas Hindborg     }
421bfb1050SAndreas Hindborg }
431bfb1050SAndreas Hindborg 
441bfb1050SAndreas Hindborg impl kernel::InPlaceModule for RustConfigfs {
451bfb1050SAndreas Hindborg     fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
461bfb1050SAndreas Hindborg         pr_info!("Rust configfs sample (init)\n");
471bfb1050SAndreas Hindborg 
481bfb1050SAndreas Hindborg         // Define a subsystem with the data type `Configuration`, two
491bfb1050SAndreas Hindborg         // attributes, `message` and `bar` and child group type `Child`. `mkdir`
501bfb1050SAndreas Hindborg         // in the directory representing this subsystem will create directories
511bfb1050SAndreas Hindborg         // backed by the `Child` type.
521bfb1050SAndreas Hindborg         let item_type = configfs_attrs! {
531bfb1050SAndreas Hindborg             container: configfs::Subsystem<Configuration>,
541bfb1050SAndreas Hindborg             data: Configuration,
551bfb1050SAndreas Hindborg             child: Child,
561bfb1050SAndreas Hindborg             attributes: [
571bfb1050SAndreas Hindborg                 message: 0,
581bfb1050SAndreas Hindborg                 bar: 1,
591bfb1050SAndreas Hindborg             ],
601bfb1050SAndreas Hindborg         };
611bfb1050SAndreas Hindborg 
621bfb1050SAndreas Hindborg         try_pin_init!(Self {
631bfb1050SAndreas Hindborg             config <- configfs::Subsystem::new(
641bfb1050SAndreas Hindborg                 c_str!("rust_configfs"), item_type, Configuration::new()
651bfb1050SAndreas Hindborg             ),
661bfb1050SAndreas Hindborg         })
671bfb1050SAndreas Hindborg     }
681bfb1050SAndreas Hindborg }
691bfb1050SAndreas Hindborg 
701bfb1050SAndreas Hindborg #[vtable]
711bfb1050SAndreas Hindborg impl configfs::GroupOperations for Configuration {
721bfb1050SAndreas Hindborg     type Child = Child;
731bfb1050SAndreas Hindborg 
741bfb1050SAndreas Hindborg     fn make_group(&self, name: &CStr) -> Result<impl PinInit<configfs::Group<Child>, Error>> {
751bfb1050SAndreas Hindborg         // Define a group with data type `Child`, one attribute `baz` and child
761bfb1050SAndreas Hindborg         // group type `GrandChild`. `mkdir` in the directory representing this
771bfb1050SAndreas Hindborg         // group will create directories backed by the `GrandChild` type.
781bfb1050SAndreas Hindborg         let tpe = configfs_attrs! {
791bfb1050SAndreas Hindborg             container: configfs::Group<Child>,
801bfb1050SAndreas Hindborg             data: Child,
811bfb1050SAndreas Hindborg             child: GrandChild,
821bfb1050SAndreas Hindborg             attributes: [
831bfb1050SAndreas Hindborg                 baz: 0,
841bfb1050SAndreas Hindborg             ],
851bfb1050SAndreas Hindborg         };
861bfb1050SAndreas Hindborg 
871bfb1050SAndreas Hindborg         Ok(configfs::Group::new(name.try_into()?, tpe, Child::new()))
881bfb1050SAndreas Hindborg     }
891bfb1050SAndreas Hindborg }
901bfb1050SAndreas Hindborg 
911bfb1050SAndreas Hindborg #[vtable]
921bfb1050SAndreas Hindborg impl configfs::AttributeOperations<0> for Configuration {
931bfb1050SAndreas Hindborg     type Data = Configuration;
941bfb1050SAndreas Hindborg 
951bfb1050SAndreas Hindborg     fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
961bfb1050SAndreas Hindborg         pr_info!("Show message\n");
97*a3a7d09aSTamir Duberstein         let data = container.message.to_bytes();
981bfb1050SAndreas Hindborg         page[0..data.len()].copy_from_slice(data);
991bfb1050SAndreas Hindborg         Ok(data.len())
1001bfb1050SAndreas Hindborg     }
1011bfb1050SAndreas Hindborg }
1021bfb1050SAndreas Hindborg 
1031bfb1050SAndreas Hindborg #[vtable]
1041bfb1050SAndreas Hindborg impl configfs::AttributeOperations<1> for Configuration {
1051bfb1050SAndreas Hindborg     type Data = Configuration;
1061bfb1050SAndreas Hindborg 
1071bfb1050SAndreas Hindborg     fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
1081bfb1050SAndreas Hindborg         pr_info!("Show bar\n");
1091bfb1050SAndreas Hindborg         let guard = container.bar.lock();
1101bfb1050SAndreas Hindborg         let data = guard.0.as_slice();
1111bfb1050SAndreas Hindborg         let len = guard.1;
1121bfb1050SAndreas Hindborg         page[0..len].copy_from_slice(&data[0..len]);
1131bfb1050SAndreas Hindborg         Ok(len)
1141bfb1050SAndreas Hindborg     }
1151bfb1050SAndreas Hindborg 
1161bfb1050SAndreas Hindborg     fn store(container: &Configuration, page: &[u8]) -> Result {
1171bfb1050SAndreas Hindborg         pr_info!("Store bar\n");
1181bfb1050SAndreas Hindborg         let mut guard = container.bar.lock();
1191bfb1050SAndreas Hindborg         guard.0[0..page.len()].copy_from_slice(page);
1201bfb1050SAndreas Hindborg         guard.1 = page.len();
1211bfb1050SAndreas Hindborg         Ok(())
1221bfb1050SAndreas Hindborg     }
1231bfb1050SAndreas Hindborg }
1241bfb1050SAndreas Hindborg 
1251bfb1050SAndreas Hindborg // `pin_data` cannot handle structs without braces.
1261bfb1050SAndreas Hindborg #[pin_data]
1271bfb1050SAndreas Hindborg struct Child {}
1281bfb1050SAndreas Hindborg 
1291bfb1050SAndreas Hindborg impl Child {
1301bfb1050SAndreas Hindborg     fn new() -> impl PinInit<Self, Error> {
1311bfb1050SAndreas Hindborg         try_pin_init!(Self {})
1321bfb1050SAndreas Hindborg     }
1331bfb1050SAndreas Hindborg }
1341bfb1050SAndreas Hindborg 
1351bfb1050SAndreas Hindborg #[vtable]
1361bfb1050SAndreas Hindborg impl configfs::GroupOperations for Child {
1371bfb1050SAndreas Hindborg     type Child = GrandChild;
1381bfb1050SAndreas Hindborg 
1391bfb1050SAndreas Hindborg     fn make_group(&self, name: &CStr) -> Result<impl PinInit<configfs::Group<GrandChild>, Error>> {
1401bfb1050SAndreas Hindborg         // Define a group with data type `GrandChild`, one attribute `gc`. As no
1411bfb1050SAndreas Hindborg         // child type is specified, it will not be possible to create subgroups
1421bfb1050SAndreas Hindborg         // in this group, and `mkdir`in the directory representing this group
1431bfb1050SAndreas Hindborg         // will return an error.
1441bfb1050SAndreas Hindborg         let tpe = configfs_attrs! {
1451bfb1050SAndreas Hindborg             container: configfs::Group<GrandChild>,
1461bfb1050SAndreas Hindborg             data: GrandChild,
1471bfb1050SAndreas Hindborg             attributes: [
1481bfb1050SAndreas Hindborg                 gc: 0,
1491bfb1050SAndreas Hindborg             ],
1501bfb1050SAndreas Hindborg         };
1511bfb1050SAndreas Hindborg 
1521bfb1050SAndreas Hindborg         Ok(configfs::Group::new(
1531bfb1050SAndreas Hindborg             name.try_into()?,
1541bfb1050SAndreas Hindborg             tpe,
1551bfb1050SAndreas Hindborg             GrandChild::new(),
1561bfb1050SAndreas Hindborg         ))
1571bfb1050SAndreas Hindborg     }
1581bfb1050SAndreas Hindborg }
1591bfb1050SAndreas Hindborg 
1601bfb1050SAndreas Hindborg #[vtable]
1611bfb1050SAndreas Hindborg impl configfs::AttributeOperations<0> for Child {
1621bfb1050SAndreas Hindborg     type Data = Child;
1631bfb1050SAndreas Hindborg 
1641bfb1050SAndreas Hindborg     fn show(_container: &Child, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
1651bfb1050SAndreas Hindborg         pr_info!("Show baz\n");
1661bfb1050SAndreas Hindborg         let data = c"Hello Baz\n".to_bytes();
1671bfb1050SAndreas Hindborg         page[0..data.len()].copy_from_slice(data);
1681bfb1050SAndreas Hindborg         Ok(data.len())
1691bfb1050SAndreas Hindborg     }
1701bfb1050SAndreas Hindborg }
1711bfb1050SAndreas Hindborg 
1721bfb1050SAndreas Hindborg // `pin_data` cannot handle structs without braces.
1731bfb1050SAndreas Hindborg #[pin_data]
1741bfb1050SAndreas Hindborg struct GrandChild {}
1751bfb1050SAndreas Hindborg 
1761bfb1050SAndreas Hindborg impl GrandChild {
1771bfb1050SAndreas Hindborg     fn new() -> impl PinInit<Self, Error> {
1781bfb1050SAndreas Hindborg         try_pin_init!(Self {})
1791bfb1050SAndreas Hindborg     }
1801bfb1050SAndreas Hindborg }
1811bfb1050SAndreas Hindborg 
1821bfb1050SAndreas Hindborg #[vtable]
1831bfb1050SAndreas Hindborg impl configfs::AttributeOperations<0> for GrandChild {
1841bfb1050SAndreas Hindborg     type Data = GrandChild;
1851bfb1050SAndreas Hindborg 
1861bfb1050SAndreas Hindborg     fn show(_container: &GrandChild, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
1871bfb1050SAndreas Hindborg         pr_info!("Show grand child\n");
1881bfb1050SAndreas Hindborg         let data = c"Hello GC\n".to_bytes();
1891bfb1050SAndreas Hindborg         page[0..data.len()].copy_from_slice(data);
1901bfb1050SAndreas Hindborg         Ok(data.len())
1911bfb1050SAndreas Hindborg     }
1921bfb1050SAndreas Hindborg }
193