Commit | Line | Data |
---|---|---|
1fbde52b MO |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | ||
3 | //! Crate for all kernel procedural macros. | |
4 | ||
60f18c22 | 5 | mod concat_idents; |
1fbde52b MO |
6 | mod helpers; |
7 | mod module; | |
b44becc5 | 8 | mod vtable; |
1fbde52b MO |
9 | |
10 | use proc_macro::TokenStream; | |
11 | ||
12 | /// Declares a kernel module. | |
13 | /// | |
14 | /// The `type` argument should be a type which implements the [`Module`] | |
15 | /// trait. Also accepts various forms of kernel metadata. | |
16 | /// | |
17 | /// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h) | |
18 | /// | |
19 | /// [`Module`]: ../kernel/trait.Module.html | |
20 | /// | |
21 | /// # Examples | |
22 | /// | |
23 | /// ```ignore | |
24 | /// use kernel::prelude::*; | |
25 | /// | |
26 | /// module!{ | |
27 | /// type: MyModule, | |
b13c9880 GG |
28 | /// name: "my_kernel_module", |
29 | /// author: "Rust for Linux Contributors", | |
30 | /// description: "My very own kernel module!", | |
31 | /// license: "GPL", | |
1fbde52b MO |
32 | /// params: { |
33 | /// my_i32: i32 { | |
34 | /// default: 42, | |
35 | /// permissions: 0o000, | |
b13c9880 | 36 | /// description: "Example of i32", |
1fbde52b MO |
37 | /// }, |
38 | /// writeable_i32: i32 { | |
39 | /// default: 42, | |
40 | /// permissions: 0o644, | |
b13c9880 | 41 | /// description: "Example of i32", |
1fbde52b MO |
42 | /// }, |
43 | /// }, | |
44 | /// } | |
45 | /// | |
46 | /// struct MyModule; | |
47 | /// | |
48 | /// impl kernel::Module for MyModule { | |
49 | /// fn init() -> Result<Self> { | |
50 | /// // If the parameter is writeable, then the kparam lock must be | |
51 | /// // taken to read the parameter: | |
52 | /// { | |
53 | /// let lock = THIS_MODULE.kernel_param_lock(); | |
54 | /// pr_info!("i32 param is: {}\n", writeable_i32.read(&lock)); | |
55 | /// } | |
56 | /// // If the parameter is read only, it can be read without locking | |
57 | /// // the kernel parameters: | |
58 | /// pr_info!("i32 param is: {}\n", my_i32.read()); | |
59 | /// Ok(Self) | |
60 | /// } | |
61 | /// } | |
62 | /// ``` | |
63 | /// | |
64 | /// # Supported argument types | |
65 | /// - `type`: type which implements the [`Module`] trait (required). | |
66 | /// - `name`: byte array of the name of the kernel module (required). | |
67 | /// - `author`: byte array of the author of the kernel module. | |
68 | /// - `description`: byte array of the description of the kernel module. | |
69 | /// - `license`: byte array of the license of the kernel module (required). | |
70 | /// - `alias`: byte array of alias name of the kernel module. | |
71 | #[proc_macro] | |
72 | pub fn module(ts: TokenStream) -> TokenStream { | |
73 | module::module(ts) | |
74 | } | |
60f18c22 | 75 | |
b44becc5 GG |
76 | /// Declares or implements a vtable trait. |
77 | /// | |
78 | /// Linux's use of pure vtables is very close to Rust traits, but they differ | |
79 | /// in how unimplemented functions are represented. In Rust, traits can provide | |
80 | /// default implementation for all non-required methods (and the default | |
81 | /// implementation could just return `Error::EINVAL`); Linux typically use C | |
82 | /// `NULL` pointers to represent these functions. | |
83 | /// | |
84 | /// This attribute is intended to close the gap. Traits can be declared and | |
85 | /// implemented with the `#[vtable]` attribute, and a `HAS_*` associated constant | |
86 | /// will be generated for each method in the trait, indicating if the implementor | |
87 | /// has overridden a method. | |
88 | /// | |
89 | /// This attribute is not needed if all methods are required. | |
90 | /// | |
91 | /// # Examples | |
92 | /// | |
93 | /// ```ignore | |
94 | /// use kernel::prelude::*; | |
95 | /// | |
96 | /// // Declares a `#[vtable]` trait | |
97 | /// #[vtable] | |
98 | /// pub trait Operations: Send + Sync + Sized { | |
99 | /// fn foo(&self) -> Result<()> { | |
100 | /// Err(EINVAL) | |
101 | /// } | |
102 | /// | |
103 | /// fn bar(&self) -> Result<()> { | |
104 | /// Err(EINVAL) | |
105 | /// } | |
106 | /// } | |
107 | /// | |
108 | /// struct Foo; | |
109 | /// | |
110 | /// // Implements the `#[vtable]` trait | |
111 | /// #[vtable] | |
112 | /// impl Operations for Foo { | |
113 | /// fn foo(&self) -> Result<()> { | |
114 | /// # Err(EINVAL) | |
115 | /// // ... | |
116 | /// } | |
117 | /// } | |
118 | /// | |
119 | /// assert_eq!(<Foo as Operations>::HAS_FOO, true); | |
120 | /// assert_eq!(<Foo as Operations>::HAS_BAR, false); | |
121 | /// ``` | |
122 | #[proc_macro_attribute] | |
123 | pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream { | |
124 | vtable::vtable(attr, ts) | |
125 | } | |
126 | ||
60f18c22 BRB |
127 | /// Concatenate two identifiers. |
128 | /// | |
129 | /// This is useful in macros that need to declare or reference items with names | |
130 | /// starting with a fixed prefix and ending in a user specified name. The resulting | |
131 | /// identifier has the span of the second argument. | |
132 | /// | |
133 | /// # Examples | |
134 | /// | |
135 | /// ```ignore | |
136 | /// use kernel::macro::concat_idents; | |
137 | /// | |
138 | /// macro_rules! pub_no_prefix { | |
139 | /// ($prefix:ident, $($newname:ident),+) => { | |
140 | /// $(pub(crate) const $newname: u32 = kernel::macros::concat_idents!($prefix, $newname);)+ | |
141 | /// }; | |
142 | /// } | |
143 | /// | |
144 | /// pub_no_prefix!( | |
145 | /// binder_driver_return_protocol_, | |
146 | /// BR_OK, | |
147 | /// BR_ERROR, | |
148 | /// BR_TRANSACTION, | |
149 | /// BR_REPLY, | |
150 | /// BR_DEAD_REPLY, | |
151 | /// BR_TRANSACTION_COMPLETE, | |
152 | /// BR_INCREFS, | |
153 | /// BR_ACQUIRE, | |
154 | /// BR_RELEASE, | |
155 | /// BR_DECREFS, | |
156 | /// BR_NOOP, | |
157 | /// BR_SPAWN_LOOPER, | |
158 | /// BR_DEAD_BINDER, | |
159 | /// BR_CLEAR_DEATH_NOTIFICATION_DONE, | |
160 | /// BR_FAILED_REPLY | |
161 | /// ); | |
162 | /// | |
163 | /// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK); | |
164 | /// ``` | |
165 | #[proc_macro] | |
166 | pub fn concat_idents(ts: TokenStream) -> TokenStream { | |
167 | concat_idents::concat_idents(ts) | |
168 | } |