99use crate :: bindings;
1010use crate :: error:: { Error , Result } ;
1111use crate :: file_operations:: { FileOpenAdapter , FileOperations , FileOperationsVtable } ;
12- use crate :: { str:: CStr , KernelModule , ThisModule } ;
12+ use crate :: { device , str:: CStr , KernelModule , ThisModule } ;
1313use alloc:: boxed:: Box ;
1414use core:: marker:: PhantomPinned ;
1515use core:: { mem:: MaybeUninit , pin:: Pin } ;
1616
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+
1795/// A registration of a miscellaneous device.
1896///
1997/// # Invariants
@@ -46,25 +124,28 @@ impl<T: FileOperations> Registration<T> {
46124 /// Registers a miscellaneous device.
47125 ///
48126 /// 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)
57129 }
58130
59131 /// Registers a miscellaneous device with the rest of the kernel.
60132 ///
61133 /// 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 (
64145 self : Pin < & mut Self > ,
65146 name : & ' static CStr ,
66- minor : Option < i32 > ,
67147 open_data : T :: OpenData ,
148+ opts : & Options < ' _ > ,
68149 ) -> Result {
69150 // SAFETY: We must ensure that we never move out of `this`.
70151 let this = unsafe { self . get_unchecked_mut ( ) } ;
@@ -76,7 +157,11 @@ impl<T: FileOperations> Registration<T> {
76157 // SAFETY: The adapter is compatible with `misc_register`.
77158 this. mdev . fops = unsafe { FileOperationsVtable :: < Self , T > :: build ( ) } ;
78159 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 ( ) ) ;
80165
81166 // We write to `open_data` here because as soon as `misc_register` succeeds, the file can be
82167 // opened, so we need `open_data` configured ahead of time.
@@ -150,7 +235,7 @@ pub struct Module<T: FileOperations<OpenData = ()>> {
150235impl < T : FileOperations < OpenData = ( ) > > KernelModule for Module < T > {
151236 fn init ( name : & ' static CStr , _module : & ' static ThisModule ) -> Result < Self > {
152237 Ok ( Self {
153- _dev : Registration :: new_pinned ( name, None , ( ) ) ?,
238+ _dev : Registration :: new_pinned ( name, ( ) ) ?,
154239 } )
155240 }
156241}
0 commit comments