Skip to content

Commit 42523ce

Browse files
lag-linarogregkh
authored andcommitted
samples: rust_misc_device: Demonstrate additional get/set value functionality
Expand the complexity of the sample driver by providing the ability to get and set an integer. The value is protected by a mutex. Signed-off-by: Lee Jones <lee@kernel.org> Link: https://lore.kernel.org/r/20241213134715.601415-4-lee@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent fdb1ac6 commit 42523ce

File tree

1 file changed

+75
-14
lines changed

1 file changed

+75
-14
lines changed

samples/rust/rust_misc_device.rs

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,24 @@
44

55
//! Rust misc device sample.
66
7+
use core::pin::Pin;
8+
79
use kernel::{
810
c_str,
911
device::Device,
1012
fs::File,
11-
ioctl::_IO,
13+
ioctl::{_IO, _IOC_SIZE, _IOR, _IOW},
1214
miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration},
15+
new_mutex,
1316
prelude::*,
17+
sync::Mutex,
1418
types::ARef,
19+
uaccess::{UserSlice, UserSliceReader, UserSliceWriter},
1520
};
1621

1722
const RUST_MISC_DEV_HELLO: u32 = _IO('|' as u32, 0x80);
23+
const RUST_MISC_DEV_GET_VALUE: u32 = _IOR::<i32>('|' as u32, 0x81);
24+
const RUST_MISC_DEV_SET_VALUE: u32 = _IOW::<i32>('|' as u32, 0x82);
1825

1926
module! {
2027
type: RustMiscDeviceModule,
@@ -44,44 +51,98 @@ impl kernel::InPlaceModule for RustMiscDeviceModule {
4451
}
4552
}
4653

54+
struct Inner {
55+
value: i32,
56+
}
57+
58+
#[pin_data(PinnedDrop)]
4759
struct RustMiscDevice {
60+
#[pin]
61+
inner: Mutex<Inner>,
4862
dev: ARef<Device>,
4963
}
5064

5165
#[vtable]
5266
impl MiscDevice for RustMiscDevice {
53-
type Ptr = KBox<Self>;
67+
type Ptr = Pin<KBox<Self>>;
5468

55-
fn open(_file: &File, misc: &MiscDeviceRegistration<Self>) -> Result<KBox<Self>> {
69+
fn open(_file: &File, misc: &MiscDeviceRegistration<Self>) -> Result<Pin<KBox<Self>>> {
5670
let dev = ARef::from(misc.device());
5771

5872
dev_info!(dev, "Opening Rust Misc Device Sample\n");
5973

60-
Ok(KBox::new(RustMiscDevice { dev }, GFP_KERNEL)?)
74+
KBox::try_pin_init(
75+
try_pin_init! {
76+
RustMiscDevice {
77+
inner <- new_mutex!( Inner{ value: 0_i32 } ),
78+
dev: dev,
79+
}
80+
},
81+
GFP_KERNEL,
82+
)
6183
}
6284

63-
fn ioctl(
64-
me: <Self::Ptr as kernel::types::ForeignOwnable>::Borrowed<'_>,
65-
_file: &File,
66-
cmd: u32,
67-
_arg: usize,
68-
) -> Result<isize> {
85+
fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result<isize> {
6986
dev_info!(me.dev, "IOCTLing Rust Misc Device Sample\n");
7087

88+
let size = _IOC_SIZE(cmd);
89+
7190
match cmd {
72-
RUST_MISC_DEV_HELLO => dev_info!(me.dev, "Hello from the Rust Misc Device\n"),
91+
RUST_MISC_DEV_GET_VALUE => me.get_value(UserSlice::new(arg, size).writer())?,
92+
RUST_MISC_DEV_SET_VALUE => me.set_value(UserSlice::new(arg, size).reader())?,
93+
RUST_MISC_DEV_HELLO => me.hello()?,
7394
_ => {
7495
dev_err!(me.dev, "-> IOCTL not recognised: {}\n", cmd);
7596
return Err(ENOTTY);
7697
}
77-
}
98+
};
7899

79100
Ok(0)
80101
}
81102
}
82103

83-
impl Drop for RustMiscDevice {
84-
fn drop(&mut self) {
104+
#[pinned_drop]
105+
impl PinnedDrop for RustMiscDevice {
106+
fn drop(self: Pin<&mut Self>) {
85107
dev_info!(self.dev, "Exiting the Rust Misc Device Sample\n");
86108
}
87109
}
110+
111+
impl RustMiscDevice {
112+
fn set_value(&self, mut reader: UserSliceReader) -> Result<isize> {
113+
let new_value = reader.read::<i32>()?;
114+
let mut guard = self.inner.lock();
115+
116+
dev_info!(
117+
self.dev,
118+
"-> Copying data from userspace (value: {})\n",
119+
new_value
120+
);
121+
122+
guard.value = new_value;
123+
Ok(0)
124+
}
125+
126+
fn get_value(&self, mut writer: UserSliceWriter) -> Result<isize> {
127+
let guard = self.inner.lock();
128+
let value = guard.value;
129+
130+
// Free-up the lock and use our locally cached instance from here
131+
drop(guard);
132+
133+
dev_info!(
134+
self.dev,
135+
"-> Copying data to userspace (value: {})\n",
136+
&value
137+
);
138+
139+
writer.write::<i32>(&value)?;
140+
Ok(0)
141+
}
142+
143+
fn hello(&self) -> Result<isize> {
144+
dev_info!(self.dev, "-> Hello from the Rust Misc Device\n");
145+
146+
Ok(0)
147+
}
148+
}

0 commit comments

Comments
 (0)