|
4 | 4 |
|
5 | 5 | //! Rust misc device sample.
|
6 | 6 |
|
| 7 | +use core::pin::Pin; |
| 8 | + |
7 | 9 | use kernel::{
|
8 | 10 | c_str,
|
9 | 11 | device::Device,
|
10 | 12 | fs::File,
|
11 |
| - ioctl::_IO, |
| 13 | + ioctl::{_IO, _IOC_SIZE, _IOR, _IOW}, |
12 | 14 | miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration},
|
| 15 | + new_mutex, |
13 | 16 | prelude::*,
|
| 17 | + sync::Mutex, |
14 | 18 | types::ARef,
|
| 19 | + uaccess::{UserSlice, UserSliceReader, UserSliceWriter}, |
15 | 20 | };
|
16 | 21 |
|
17 | 22 | 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); |
18 | 25 |
|
19 | 26 | module! {
|
20 | 27 | type: RustMiscDeviceModule,
|
@@ -44,44 +51,98 @@ impl kernel::InPlaceModule for RustMiscDeviceModule {
|
44 | 51 | }
|
45 | 52 | }
|
46 | 53 |
|
| 54 | +struct Inner { |
| 55 | + value: i32, |
| 56 | +} |
| 57 | + |
| 58 | +#[pin_data(PinnedDrop)] |
47 | 59 | struct RustMiscDevice {
|
| 60 | + #[pin] |
| 61 | + inner: Mutex<Inner>, |
48 | 62 | dev: ARef<Device>,
|
49 | 63 | }
|
50 | 64 |
|
51 | 65 | #[vtable]
|
52 | 66 | impl MiscDevice for RustMiscDevice {
|
53 |
| - type Ptr = KBox<Self>; |
| 67 | + type Ptr = Pin<KBox<Self>>; |
54 | 68 |
|
55 |
| - fn open(_file: &File, misc: &MiscDeviceRegistration<Self>) -> Result<KBox<Self>> { |
| 69 | + fn open(_file: &File, misc: &MiscDeviceRegistration<Self>) -> Result<Pin<KBox<Self>>> { |
56 | 70 | let dev = ARef::from(misc.device());
|
57 | 71 |
|
58 | 72 | dev_info!(dev, "Opening Rust Misc Device Sample\n");
|
59 | 73 |
|
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 | + ) |
61 | 83 | }
|
62 | 84 |
|
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> { |
69 | 86 | dev_info!(me.dev, "IOCTLing Rust Misc Device Sample\n");
|
70 | 87 |
|
| 88 | + let size = _IOC_SIZE(cmd); |
| 89 | + |
71 | 90 | 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()?, |
73 | 94 | _ => {
|
74 | 95 | dev_err!(me.dev, "-> IOCTL not recognised: {}\n", cmd);
|
75 | 96 | return Err(ENOTTY);
|
76 | 97 | }
|
77 |
| - } |
| 98 | + }; |
78 | 99 |
|
79 | 100 | Ok(0)
|
80 | 101 | }
|
81 | 102 | }
|
82 | 103 |
|
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>) { |
85 | 107 | dev_info!(self.dev, "Exiting the Rust Misc Device Sample\n");
|
86 | 108 | }
|
87 | 109 | }
|
| 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