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