9
9
use crate :: bindings;
10
10
use crate :: error:: { Error , Result } ;
11
11
use crate :: file_operations:: { FileOpenAdapter , FileOperations , FileOperationsVtable } ;
12
- use crate :: { str:: CStr , KernelModule , ThisModule } ;
12
+ use crate :: { device , str:: CStr , KernelModule , ThisModule } ;
13
13
use alloc:: boxed:: Box ;
14
14
use core:: marker:: PhantomPinned ;
15
15
use core:: { mem:: MaybeUninit , pin:: Pin } ;
16
16
17
+ /// Options which can be used to configure how a misc device is registered.
18
+ ///
19
+ /// # Examples
20
+ ///
21
+ /// ```
22
+ /// # use kernel::{c_str, device::RawDevice, file_operations::FileOperations, miscdev, prelude::*};
23
+ /// pub fn example(
24
+ /// reg: Pin<&mut miscdev::Registration<impl FileOperations<OpenData = ()>>>,
25
+ /// parent: &dyn RawDevice,
26
+ /// ) -> Result {
27
+ /// miscdev::Options::new()
28
+ /// .mode(0o600)
29
+ /// .minor(10)
30
+ /// .parent(parent)
31
+ /// .register(reg, c_str!("sample"), ())
32
+ /// }
33
+ /// ```
34
+ #[ derive( Default ) ]
35
+ pub struct Options < ' a > {
36
+ minor : Option < i32 > ,
37
+ mode : Option < u16 > ,
38
+ parent : Option < & ' a dyn device:: RawDevice > ,
39
+ }
40
+
41
+ impl < ' a > Options < ' a > {
42
+ /// Creates new [`Options`] instance with the required fields.
43
+ pub const fn new ( ) -> Self {
44
+ Self {
45
+ minor : None ,
46
+ mode : None ,
47
+ parent : None ,
48
+ }
49
+ }
50
+
51
+ /// Sets the minor device number.
52
+ pub const fn minor ( & mut self , v : i32 ) -> & mut Self {
53
+ self . minor = Some ( v) ;
54
+ self
55
+ }
56
+
57
+ /// Sets the device mode.
58
+ ///
59
+ /// This is usually an octal number and describes who can perform read/write/execute operations
60
+ /// on the device.
61
+ pub const fn mode ( & mut self , m : u16 ) -> & mut Self {
62
+ self . mode = Some ( m) ;
63
+ self
64
+ }
65
+
66
+ /// Sets the device parent.
67
+ pub const fn parent ( & mut self , p : & ' a dyn device:: RawDevice ) -> & mut Self {
68
+ self . parent = Some ( p) ;
69
+ self
70
+ }
71
+
72
+ /// Registers a misc device using the configured options.
73
+ pub fn register < T : FileOperations > (
74
+ & self ,
75
+ reg : Pin < & mut Registration < T > > ,
76
+ name : & ' static CStr ,
77
+ open_data : T :: OpenData ,
78
+ ) -> Result {
79
+ reg. register_with_options ( name, open_data, self )
80
+ }
81
+
82
+ /// Allocates a new registration of a misc device and completes the registration with the
83
+ /// configured options.
84
+ pub fn register_new < T : FileOperations > (
85
+ & self ,
86
+ name : & ' static CStr ,
87
+ open_data : T :: OpenData ,
88
+ ) -> Result < Pin < Box < Registration < T > > > > {
89
+ let mut r = Pin :: from ( Box :: try_new ( Registration :: new ( ) ) ?) ;
90
+ self . register ( r. as_mut ( ) , name, open_data) ?;
91
+ Ok ( r)
92
+ }
93
+ }
94
+
17
95
/// A registration of a miscellaneous device.
18
96
///
19
97
/// # Invariants
@@ -46,25 +124,28 @@ impl<T: FileOperations> Registration<T> {
46
124
/// Registers a miscellaneous device.
47
125
///
48
126
/// Returns a pinned heap-allocated representation of the registration.
49
- pub fn new_pinned (
50
- name : & ' static CStr ,
51
- minor : Option < i32 > ,
52
- open_data : T :: OpenData ,
53
- ) -> Result < Pin < Box < Self > > > {
54
- let mut r = Pin :: from ( Box :: try_new ( Self :: new ( ) ) ?) ;
55
- r. as_mut ( ) . register ( name, minor, open_data) ?;
56
- Ok ( r)
127
+ pub fn new_pinned ( name : & ' static CStr , open_data : T :: OpenData ) -> Result < Pin < Box < Self > > > {
128
+ Options :: new ( ) . register_new ( name, open_data)
57
129
}
58
130
59
131
/// Registers a miscellaneous device with the rest of the kernel.
60
132
///
61
133
/// It must be pinned because the memory block that represents the registration is
62
- /// self-referential. If a minor is not given, the kernel allocates a new one if possible.
63
- pub fn register (
134
+ /// self-referential.
135
+ pub fn register ( self : Pin < & mut Self > , name : & ' static CStr , open_data : T :: OpenData ) -> Result {
136
+ Options :: new ( ) . register ( self , name, open_data)
137
+ }
138
+
139
+ /// Registers a miscellaneous device with the rest of the kernel. Additional optional settings
140
+ /// are provided via the `opts` parameter.
141
+ ///
142
+ /// It must be pinned because the memory block that represents the registration is
143
+ /// self-referential.
144
+ pub fn register_with_options (
64
145
self : Pin < & mut Self > ,
65
146
name : & ' static CStr ,
66
- minor : Option < i32 > ,
67
147
open_data : T :: OpenData ,
148
+ opts : & Options < ' _ > ,
68
149
) -> Result {
69
150
// SAFETY: We must ensure that we never move out of `this`.
70
151
let this = unsafe { self . get_unchecked_mut ( ) } ;
@@ -76,7 +157,11 @@ impl<T: FileOperations> Registration<T> {
76
157
// SAFETY: The adapter is compatible with `misc_register`.
77
158
this. mdev . fops = unsafe { FileOperationsVtable :: < Self , T > :: build ( ) } ;
78
159
this. mdev . name = name. as_char_ptr ( ) ;
79
- this. mdev . minor = minor. unwrap_or ( bindings:: MISC_DYNAMIC_MINOR as i32 ) ;
160
+ this. mdev . minor = opts. minor . unwrap_or ( bindings:: MISC_DYNAMIC_MINOR as i32 ) ;
161
+ this. mdev . mode = opts. mode . unwrap_or ( 0 ) ;
162
+ this. mdev . parent = opts
163
+ . parent
164
+ . map_or ( core:: ptr:: null_mut ( ) , |p| p. raw_device ( ) ) ;
80
165
81
166
// We write to `open_data` here because as soon as `misc_register` succeeds, the file can be
82
167
// opened, so we need `open_data` configured ahead of time.
@@ -150,7 +235,7 @@ pub struct Module<T: FileOperations<OpenData = ()>> {
150
235
impl < T : FileOperations < OpenData = ( ) > > KernelModule for Module < T > {
151
236
fn init ( name : & ' static CStr , _module : & ' static ThisModule ) -> Result < Self > {
152
237
Ok ( Self {
153
- _dev : Registration :: new_pinned ( name, None , ( ) ) ?,
238
+ _dev : Registration :: new_pinned ( name, ( ) ) ?,
154
239
} )
155
240
}
156
241
}
0 commit comments