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