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