1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2024 Google LLC. 4 5 //! Rust misc device sample. 6 7 use kernel::{ 8 c_str, 9 device::Device, 10 fs::File, 11 ioctl::_IO, 12 miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration}, 13 prelude::*, 14 types::ARef, 15 }; 16 17 const RUST_MISC_DEV_HELLO: u32 = _IO('|' as u32, 0x80); 18 19 module! { 20 type: RustMiscDeviceModule, 21 name: "rust_misc_device", 22 author: "Lee Jones", 23 description: "Rust misc device sample", 24 license: "GPL", 25 } 26 27 #[pin_data] 28 struct RustMiscDeviceModule { 29 #[pin] 30 _miscdev: MiscDeviceRegistration<RustMiscDevice>, 31 } 32 33 impl kernel::InPlaceModule for RustMiscDeviceModule { 34 fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> { 35 pr_info!("Initialising Rust Misc Device Sample\n"); 36 37 let options = MiscDeviceOptions { 38 name: c_str!("rust-misc-device"), 39 }; 40 41 try_pin_init!(Self { 42 _miscdev <- MiscDeviceRegistration::register(options), 43 }) 44 } 45 } 46 47 struct RustMiscDevice { 48 dev: ARef<Device>, 49 } 50 51 #[vtable] 52 impl MiscDevice for RustMiscDevice { 53 type Ptr = KBox<Self>; 54 55 fn open(_file: &File, misc: &MiscDeviceRegistration<Self>) -> Result<KBox<Self>> { 56 let dev = ARef::from(misc.device()); 57 58 dev_info!(dev, "Opening Rust Misc Device Sample\n"); 59 60 Ok(KBox::new(RustMiscDevice { dev }, GFP_KERNEL)?) 61 } 62 63 fn ioctl( 64 me: <Self::Ptr as kernel::types::ForeignOwnable>::Borrowed<'_>, 65 _file: &File, 66 cmd: u32, 67 _arg: usize, 68 ) -> Result<isize> { 69 dev_info!(me.dev, "IOCTLing Rust Misc Device Sample\n"); 70 71 match cmd { 72 RUST_MISC_DEV_HELLO => dev_info!(me.dev, "Hello from the Rust Misc Device\n"), 73 _ => { 74 dev_err!(me.dev, "-> IOCTL not recognised: {}\n", cmd); 75 return Err(ENOTTY); 76 } 77 } 78 79 Ok(0) 80 } 81 } 82 83 impl Drop for RustMiscDevice { 84 fn drop(&mut self) { 85 dev_info!(self.dev, "Exiting the Rust Misc Device Sample\n"); 86 } 87 } 88