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