]>
Commit | Line | Data |
---|---|---|
1fbde52b MO |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | ||
3 | //! Crate for all kernel procedural macros. | |
4 | ||
aeb0e24a MO |
5 | // When fixdep scans this, it will find this string `CONFIG_RUSTC_VERSION_TEXT` |
6 | // and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is | |
7 | // touched by Kconfig when the version string from the compiler changes. | |
8 | ||
70a21e54 GG |
9 | #[macro_use] |
10 | mod quote; | |
60f18c22 | 11 | mod concat_idents; |
1fbde52b MO |
12 | mod helpers; |
13 | mod module; | |
823d4737 | 14 | mod paste; |
fc6c6baa | 15 | mod pin_data; |
d0fdc396 | 16 | mod pinned_drop; |
b44becc5 | 17 | mod vtable; |
071cedc8 | 18 | mod zeroable; |
1fbde52b MO |
19 | |
20 | use proc_macro::TokenStream; | |
21 | ||
22 | /// Declares a kernel module. | |
23 | /// | |
24 | /// The `type` argument should be a type which implements the [`Module`] | |
25 | /// trait. Also accepts various forms of kernel metadata. | |
26 | /// | |
bc2e7d5c | 27 | /// C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h) |
1fbde52b MO |
28 | /// |
29 | /// [`Module`]: ../kernel/trait.Module.html | |
30 | /// | |
31 | /// # Examples | |
32 | /// | |
8d3f5079 | 33 | /// ``` |
1fbde52b MO |
34 | /// use kernel::prelude::*; |
35 | /// | |
36 | /// module!{ | |
37 | /// type: MyModule, | |
b13c9880 GG |
38 | /// name: "my_kernel_module", |
39 | /// author: "Rust for Linux Contributors", | |
40 | /// description: "My very own kernel module!", | |
41 | /// license: "GPL", | |
67f9c312 | 42 | /// alias: ["alternate_module_name"], |
1fbde52b MO |
43 | /// } |
44 | /// | |
8d3f5079 | 45 | /// struct MyModule(i32); |
1fbde52b MO |
46 | /// |
47 | /// impl kernel::Module for MyModule { | |
8d3f5079 ET |
48 | /// fn init(_module: &'static ThisModule) -> Result<Self> { |
49 | /// let foo: i32 = 42; | |
50 | /// pr_info!("I contain: {}\n", foo); | |
51 | /// Ok(Self(foo)) | |
1fbde52b MO |
52 | /// } |
53 | /// } | |
8d3f5079 | 54 | /// # fn main() {} |
1fbde52b MO |
55 | /// ``` |
56 | /// | |
549d3c2f FT |
57 | /// ## Firmware |
58 | /// | |
59 | /// The following example shows how to declare a kernel module that needs | |
60 | /// to load binary firmware files. You need to specify the file names of | |
61 | /// the firmware in the `firmware` field. The information is embedded | |
62 | /// in the `modinfo` section of the kernel module. For example, a tool to | |
63 | /// build an initramfs uses this information to put the firmware files into | |
64 | /// the initramfs image. | |
65 | /// | |
8d3f5079 | 66 | /// ``` |
549d3c2f FT |
67 | /// use kernel::prelude::*; |
68 | /// | |
69 | /// module!{ | |
70 | /// type: MyDeviceDriverModule, | |
71 | /// name: "my_device_driver_module", | |
72 | /// author: "Rust for Linux Contributors", | |
73 | /// description: "My device driver requires firmware", | |
74 | /// license: "GPL", | |
75 | /// firmware: ["my_device_firmware1.bin", "my_device_firmware2.bin"], | |
76 | /// } | |
77 | /// | |
78 | /// struct MyDeviceDriverModule; | |
79 | /// | |
80 | /// impl kernel::Module for MyDeviceDriverModule { | |
8d3f5079 | 81 | /// fn init(_module: &'static ThisModule) -> Result<Self> { |
549d3c2f FT |
82 | /// Ok(Self) |
83 | /// } | |
84 | /// } | |
8d3f5079 | 85 | /// # fn main() {} |
549d3c2f FT |
86 | /// ``` |
87 | /// | |
1fbde52b MO |
88 | /// # Supported argument types |
89 | /// - `type`: type which implements the [`Module`] trait (required). | |
63249a07 AU |
90 | /// - `name`: ASCII string literal of the name of the kernel module (required). |
91 | /// - `author`: string literal of the author of the kernel module. | |
92 | /// - `description`: string literal of the description of the kernel module. | |
93 | /// - `license`: ASCII string literal of the license of the kernel module (required). | |
94 | /// - `alias`: array of ASCII string literals of the alias names of the kernel module. | |
549d3c2f | 95 | /// - `firmware`: array of ASCII string literals of the firmware files of |
0ba521d6 | 96 | /// the kernel module. |
1fbde52b MO |
97 | #[proc_macro] |
98 | pub fn module(ts: TokenStream) -> TokenStream { | |
99 | module::module(ts) | |
100 | } | |
60f18c22 | 101 | |
b44becc5 GG |
102 | /// Declares or implements a vtable trait. |
103 | /// | |
104 | /// Linux's use of pure vtables is very close to Rust traits, but they differ | |
105 | /// in how unimplemented functions are represented. In Rust, traits can provide | |
106 | /// default implementation for all non-required methods (and the default | |
107 | /// implementation could just return `Error::EINVAL`); Linux typically use C | |
108 | /// `NULL` pointers to represent these functions. | |
109 | /// | |
88c2e116 BL |
110 | /// This attribute closes that gap. A trait can be annotated with the |
111 | /// `#[vtable]` attribute. Implementers of the trait will then also have to | |
112 | /// annotate the trait with `#[vtable]`. This attribute generates a `HAS_*` | |
113 | /// associated constant bool for each method in the trait that is set to true if | |
114 | /// the implementer has overridden the associated method. | |
115 | /// | |
116 | /// For a trait method to be optional, it must have a default implementation. | |
117 | /// This is also the case for traits annotated with `#[vtable]`, but in this | |
118 | /// case the default implementation will never be executed. The reason for this | |
119 | /// is that the functions will be called through function pointers installed in | |
120 | /// C side vtables. When an optional method is not implemented on a `#[vtable]` | |
121 | /// trait, a NULL entry is installed in the vtable. Thus the default | |
122 | /// implementation is never called. Since these traits are not designed to be | |
123 | /// used on the Rust side, it should not be possible to call the default | |
124 | /// implementation. This is done to ensure that we call the vtable methods | |
125 | /// through the C vtable, and not through the Rust vtable. Therefore, the | |
4401565f | 126 | /// default implementation should call `build_error!`, which prevents |
88c2e116 BL |
127 | /// calls to this function at compile time: |
128 | /// | |
129 | /// ```compile_fail | |
b2c261fa | 130 | /// # // Intentionally missing `use`s to simplify `rusttest`. |
4401565f | 131 | /// build_error!(VTABLE_DEFAULT_ERROR) |
88c2e116 BL |
132 | /// ``` |
133 | /// | |
134 | /// Note that you might need to import [`kernel::error::VTABLE_DEFAULT_ERROR`]. | |
b44becc5 | 135 | /// |
88c2e116 | 136 | /// This macro should not be used when all functions are required. |
b44becc5 GG |
137 | /// |
138 | /// # Examples | |
139 | /// | |
ae7851c2 | 140 | /// ``` |
88c2e116 | 141 | /// use kernel::error::VTABLE_DEFAULT_ERROR; |
b44becc5 GG |
142 | /// use kernel::prelude::*; |
143 | /// | |
144 | /// // Declares a `#[vtable]` trait | |
145 | /// #[vtable] | |
146 | /// pub trait Operations: Send + Sync + Sized { | |
147 | /// fn foo(&self) -> Result<()> { | |
4401565f | 148 | /// build_error!(VTABLE_DEFAULT_ERROR) |
b44becc5 GG |
149 | /// } |
150 | /// | |
151 | /// fn bar(&self) -> Result<()> { | |
4401565f | 152 | /// build_error!(VTABLE_DEFAULT_ERROR) |
b44becc5 GG |
153 | /// } |
154 | /// } | |
155 | /// | |
156 | /// struct Foo; | |
157 | /// | |
158 | /// // Implements the `#[vtable]` trait | |
159 | /// #[vtable] | |
160 | /// impl Operations for Foo { | |
161 | /// fn foo(&self) -> Result<()> { | |
162 | /// # Err(EINVAL) | |
163 | /// // ... | |
164 | /// } | |
165 | /// } | |
166 | /// | |
167 | /// assert_eq!(<Foo as Operations>::HAS_FOO, true); | |
168 | /// assert_eq!(<Foo as Operations>::HAS_BAR, false); | |
169 | /// ``` | |
88c2e116 BL |
170 | /// |
171 | /// [`kernel::error::VTABLE_DEFAULT_ERROR`]: ../kernel/error/constant.VTABLE_DEFAULT_ERROR.html | |
b44becc5 GG |
172 | #[proc_macro_attribute] |
173 | pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream { | |
174 | vtable::vtable(attr, ts) | |
175 | } | |
176 | ||
60f18c22 BRB |
177 | /// Concatenate two identifiers. |
178 | /// | |
179 | /// This is useful in macros that need to declare or reference items with names | |
180 | /// starting with a fixed prefix and ending in a user specified name. The resulting | |
181 | /// identifier has the span of the second argument. | |
182 | /// | |
183 | /// # Examples | |
184 | /// | |
ae7851c2 ET |
185 | /// ``` |
186 | /// # const binder_driver_return_protocol_BR_OK: u32 = 0; | |
187 | /// # const binder_driver_return_protocol_BR_ERROR: u32 = 1; | |
188 | /// # const binder_driver_return_protocol_BR_TRANSACTION: u32 = 2; | |
189 | /// # const binder_driver_return_protocol_BR_REPLY: u32 = 3; | |
190 | /// # const binder_driver_return_protocol_BR_DEAD_REPLY: u32 = 4; | |
191 | /// # const binder_driver_return_protocol_BR_TRANSACTION_COMPLETE: u32 = 5; | |
192 | /// # const binder_driver_return_protocol_BR_INCREFS: u32 = 6; | |
193 | /// # const binder_driver_return_protocol_BR_ACQUIRE: u32 = 7; | |
194 | /// # const binder_driver_return_protocol_BR_RELEASE: u32 = 8; | |
195 | /// # const binder_driver_return_protocol_BR_DECREFS: u32 = 9; | |
196 | /// # const binder_driver_return_protocol_BR_NOOP: u32 = 10; | |
197 | /// # const binder_driver_return_protocol_BR_SPAWN_LOOPER: u32 = 11; | |
198 | /// # const binder_driver_return_protocol_BR_DEAD_BINDER: u32 = 12; | |
199 | /// # const binder_driver_return_protocol_BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = 13; | |
200 | /// # const binder_driver_return_protocol_BR_FAILED_REPLY: u32 = 14; | |
201 | /// use kernel::macros::concat_idents; | |
60f18c22 BRB |
202 | /// |
203 | /// macro_rules! pub_no_prefix { | |
204 | /// ($prefix:ident, $($newname:ident),+) => { | |
ae7851c2 | 205 | /// $(pub(crate) const $newname: u32 = concat_idents!($prefix, $newname);)+ |
60f18c22 BRB |
206 | /// }; |
207 | /// } | |
208 | /// | |
209 | /// pub_no_prefix!( | |
210 | /// binder_driver_return_protocol_, | |
211 | /// BR_OK, | |
212 | /// BR_ERROR, | |
213 | /// BR_TRANSACTION, | |
214 | /// BR_REPLY, | |
215 | /// BR_DEAD_REPLY, | |
216 | /// BR_TRANSACTION_COMPLETE, | |
217 | /// BR_INCREFS, | |
218 | /// BR_ACQUIRE, | |
219 | /// BR_RELEASE, | |
220 | /// BR_DECREFS, | |
221 | /// BR_NOOP, | |
222 | /// BR_SPAWN_LOOPER, | |
223 | /// BR_DEAD_BINDER, | |
224 | /// BR_CLEAR_DEATH_NOTIFICATION_DONE, | |
225 | /// BR_FAILED_REPLY | |
226 | /// ); | |
227 | /// | |
228 | /// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK); | |
229 | /// ``` | |
230 | #[proc_macro] | |
231 | pub fn concat_idents(ts: TokenStream) -> TokenStream { | |
232 | concat_idents::concat_idents(ts) | |
233 | } | |
fc6c6baa BL |
234 | |
235 | /// Used to specify the pinning information of the fields of a struct. | |
236 | /// | |
237 | /// This is somewhat similar in purpose as | |
238 | /// [pin-project-lite](https://crates.io/crates/pin-project-lite). | |
239 | /// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each | |
240 | /// field you want to structurally pin. | |
241 | /// | |
242 | /// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`, | |
243 | /// then `#[pin]` directs the type of initializer that is required. | |
244 | /// | |
d0fdc396 BL |
245 | /// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this |
246 | /// macro, and change your `Drop` implementation to `PinnedDrop` annotated with | |
247 | /// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care. | |
248 | /// | |
fc6c6baa BL |
249 | /// # Examples |
250 | /// | |
ae7851c2 ET |
251 | /// ``` |
252 | /// # #![feature(lint_reasons)] | |
253 | /// # use kernel::prelude::*; | |
254 | /// # use std::{sync::Mutex, process::Command}; | |
255 | /// # use kernel::macros::pin_data; | |
fc6c6baa BL |
256 | /// #[pin_data] |
257 | /// struct DriverData { | |
258 | /// #[pin] | |
58eff8e8 | 259 | /// queue: Mutex<KVec<Command>>, |
8373147c | 260 | /// buf: KBox<[u8; 1024 * 1024]>, |
fc6c6baa BL |
261 | /// } |
262 | /// ``` | |
263 | /// | |
ae7851c2 ET |
264 | /// ``` |
265 | /// # #![feature(lint_reasons)] | |
266 | /// # use kernel::prelude::*; | |
267 | /// # use std::{sync::Mutex, process::Command}; | |
268 | /// # use core::pin::Pin; | |
269 | /// # pub struct Info; | |
270 | /// # mod bindings { | |
271 | /// # pub unsafe fn destroy_info(_ptr: *mut super::Info) {} | |
272 | /// # } | |
273 | /// use kernel::macros::{pin_data, pinned_drop}; | |
274 | /// | |
d0fdc396 BL |
275 | /// #[pin_data(PinnedDrop)] |
276 | /// struct DriverData { | |
277 | /// #[pin] | |
58eff8e8 | 278 | /// queue: Mutex<KVec<Command>>, |
8373147c | 279 | /// buf: KBox<[u8; 1024 * 1024]>, |
d0fdc396 BL |
280 | /// raw_info: *mut Info, |
281 | /// } | |
282 | /// | |
283 | /// #[pinned_drop] | |
284 | /// impl PinnedDrop for DriverData { | |
285 | /// fn drop(self: Pin<&mut Self>) { | |
286 | /// unsafe { bindings::destroy_info(self.raw_info) }; | |
287 | /// } | |
288 | /// } | |
ae7851c2 | 289 | /// # fn main() {} |
d0fdc396 BL |
290 | /// ``` |
291 | /// | |
fc6c6baa BL |
292 | /// [`pin_init!`]: ../kernel/macro.pin_init.html |
293 | // ^ cannot use direct link, since `kernel` is not a dependency of `macros`. | |
294 | #[proc_macro_attribute] | |
295 | pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream { | |
296 | pin_data::pin_data(inner, item) | |
297 | } | |
d0fdc396 BL |
298 | |
299 | /// Used to implement `PinnedDrop` safely. | |
300 | /// | |
301 | /// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`. | |
302 | /// | |
303 | /// # Examples | |
304 | /// | |
ae7851c2 ET |
305 | /// ``` |
306 | /// # #![feature(lint_reasons)] | |
307 | /// # use kernel::prelude::*; | |
308 | /// # use macros::{pin_data, pinned_drop}; | |
309 | /// # use std::{sync::Mutex, process::Command}; | |
310 | /// # use core::pin::Pin; | |
311 | /// # mod bindings { | |
312 | /// # pub struct Info; | |
313 | /// # pub unsafe fn destroy_info(_ptr: *mut Info) {} | |
314 | /// # } | |
d0fdc396 BL |
315 | /// #[pin_data(PinnedDrop)] |
316 | /// struct DriverData { | |
317 | /// #[pin] | |
58eff8e8 | 318 | /// queue: Mutex<KVec<Command>>, |
8373147c | 319 | /// buf: KBox<[u8; 1024 * 1024]>, |
ae7851c2 | 320 | /// raw_info: *mut bindings::Info, |
d0fdc396 BL |
321 | /// } |
322 | /// | |
323 | /// #[pinned_drop] | |
324 | /// impl PinnedDrop for DriverData { | |
325 | /// fn drop(self: Pin<&mut Self>) { | |
326 | /// unsafe { bindings::destroy_info(self.raw_info) }; | |
327 | /// } | |
328 | /// } | |
329 | /// ``` | |
330 | #[proc_macro_attribute] | |
331 | pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { | |
332 | pinned_drop::pinned_drop(args, input) | |
333 | } | |
823d4737 GG |
334 | |
335 | /// Paste identifiers together. | |
336 | /// | |
337 | /// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a | |
338 | /// single identifier. | |
339 | /// | |
2dc318ea TG |
340 | /// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers and |
341 | /// literals (lifetimes and documentation strings are not supported). There is a difference in | |
823d4737 GG |
342 | /// supported modifiers as well. |
343 | /// | |
344 | /// # Example | |
345 | /// | |
7e06561f ET |
346 | /// ``` |
347 | /// # const binder_driver_return_protocol_BR_OK: u32 = 0; | |
348 | /// # const binder_driver_return_protocol_BR_ERROR: u32 = 1; | |
349 | /// # const binder_driver_return_protocol_BR_TRANSACTION: u32 = 2; | |
350 | /// # const binder_driver_return_protocol_BR_REPLY: u32 = 3; | |
351 | /// # const binder_driver_return_protocol_BR_DEAD_REPLY: u32 = 4; | |
352 | /// # const binder_driver_return_protocol_BR_TRANSACTION_COMPLETE: u32 = 5; | |
353 | /// # const binder_driver_return_protocol_BR_INCREFS: u32 = 6; | |
354 | /// # const binder_driver_return_protocol_BR_ACQUIRE: u32 = 7; | |
355 | /// # const binder_driver_return_protocol_BR_RELEASE: u32 = 8; | |
356 | /// # const binder_driver_return_protocol_BR_DECREFS: u32 = 9; | |
357 | /// # const binder_driver_return_protocol_BR_NOOP: u32 = 10; | |
358 | /// # const binder_driver_return_protocol_BR_SPAWN_LOOPER: u32 = 11; | |
359 | /// # const binder_driver_return_protocol_BR_DEAD_BINDER: u32 = 12; | |
360 | /// # const binder_driver_return_protocol_BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = 13; | |
361 | /// # const binder_driver_return_protocol_BR_FAILED_REPLY: u32 = 14; | |
823d4737 GG |
362 | /// macro_rules! pub_no_prefix { |
363 | /// ($prefix:ident, $($newname:ident),+) => { | |
7e06561f | 364 | /// kernel::macros::paste! { |
823d4737 GG |
365 | /// $(pub(crate) const $newname: u32 = [<$prefix $newname>];)+ |
366 | /// } | |
367 | /// }; | |
368 | /// } | |
369 | /// | |
370 | /// pub_no_prefix!( | |
371 | /// binder_driver_return_protocol_, | |
372 | /// BR_OK, | |
373 | /// BR_ERROR, | |
374 | /// BR_TRANSACTION, | |
375 | /// BR_REPLY, | |
376 | /// BR_DEAD_REPLY, | |
377 | /// BR_TRANSACTION_COMPLETE, | |
378 | /// BR_INCREFS, | |
379 | /// BR_ACQUIRE, | |
380 | /// BR_RELEASE, | |
381 | /// BR_DECREFS, | |
382 | /// BR_NOOP, | |
383 | /// BR_SPAWN_LOOPER, | |
384 | /// BR_DEAD_BINDER, | |
385 | /// BR_CLEAR_DEATH_NOTIFICATION_DONE, | |
386 | /// BR_FAILED_REPLY | |
387 | /// ); | |
388 | /// | |
389 | /// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK); | |
390 | /// ``` | |
391 | /// | |
392 | /// # Modifiers | |
393 | /// | |
394 | /// For each identifier, it is possible to attach one or multiple modifiers to | |
395 | /// it. | |
396 | /// | |
397 | /// Currently supported modifiers are: | |
398 | /// * `span`: change the span of concatenated identifier to the span of the specified token. By | |
e516211f | 399 | /// default the span of the `[< >]` group is used. |
823d4737 GG |
400 | /// * `lower`: change the identifier to lower case. |
401 | /// * `upper`: change the identifier to upper case. | |
402 | /// | |
7e06561f ET |
403 | /// ``` |
404 | /// # const binder_driver_return_protocol_BR_OK: u32 = 0; | |
405 | /// # const binder_driver_return_protocol_BR_ERROR: u32 = 1; | |
406 | /// # const binder_driver_return_protocol_BR_TRANSACTION: u32 = 2; | |
407 | /// # const binder_driver_return_protocol_BR_REPLY: u32 = 3; | |
408 | /// # const binder_driver_return_protocol_BR_DEAD_REPLY: u32 = 4; | |
409 | /// # const binder_driver_return_protocol_BR_TRANSACTION_COMPLETE: u32 = 5; | |
410 | /// # const binder_driver_return_protocol_BR_INCREFS: u32 = 6; | |
411 | /// # const binder_driver_return_protocol_BR_ACQUIRE: u32 = 7; | |
412 | /// # const binder_driver_return_protocol_BR_RELEASE: u32 = 8; | |
413 | /// # const binder_driver_return_protocol_BR_DECREFS: u32 = 9; | |
414 | /// # const binder_driver_return_protocol_BR_NOOP: u32 = 10; | |
415 | /// # const binder_driver_return_protocol_BR_SPAWN_LOOPER: u32 = 11; | |
416 | /// # const binder_driver_return_protocol_BR_DEAD_BINDER: u32 = 12; | |
417 | /// # const binder_driver_return_protocol_BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = 13; | |
418 | /// # const binder_driver_return_protocol_BR_FAILED_REPLY: u32 = 14; | |
823d4737 GG |
419 | /// macro_rules! pub_no_prefix { |
420 | /// ($prefix:ident, $($newname:ident),+) => { | |
421 | /// kernel::macros::paste! { | |
15541c92 | 422 | /// $(pub(crate) const fn [<$newname:lower:span>]() -> u32 { [<$prefix $newname:span>] })+ |
823d4737 GG |
423 | /// } |
424 | /// }; | |
425 | /// } | |
426 | /// | |
427 | /// pub_no_prefix!( | |
428 | /// binder_driver_return_protocol_, | |
429 | /// BR_OK, | |
430 | /// BR_ERROR, | |
431 | /// BR_TRANSACTION, | |
432 | /// BR_REPLY, | |
433 | /// BR_DEAD_REPLY, | |
434 | /// BR_TRANSACTION_COMPLETE, | |
435 | /// BR_INCREFS, | |
436 | /// BR_ACQUIRE, | |
437 | /// BR_RELEASE, | |
438 | /// BR_DECREFS, | |
439 | /// BR_NOOP, | |
440 | /// BR_SPAWN_LOOPER, | |
441 | /// BR_DEAD_BINDER, | |
442 | /// BR_CLEAR_DEATH_NOTIFICATION_DONE, | |
443 | /// BR_FAILED_REPLY | |
444 | /// ); | |
445 | /// | |
446 | /// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK); | |
447 | /// ``` | |
448 | /// | |
2dc318ea TG |
449 | /// # Literals |
450 | /// | |
451 | /// Literals can also be concatenated with other identifiers: | |
452 | /// | |
7e06561f | 453 | /// ``` |
2dc318ea TG |
454 | /// macro_rules! create_numbered_fn { |
455 | /// ($name:literal, $val:literal) => { | |
456 | /// kernel::macros::paste! { | |
457 | /// fn [<some_ $name _fn $val>]() -> u32 { $val } | |
458 | /// } | |
459 | /// }; | |
460 | /// } | |
461 | /// | |
462 | /// create_numbered_fn!("foo", 100); | |
463 | /// | |
464 | /// assert_eq!(some_foo_fn100(), 100) | |
465 | /// ``` | |
466 | /// | |
823d4737 GG |
467 | /// [`paste`]: https://docs.rs/paste/ |
468 | #[proc_macro] | |
469 | pub fn paste(input: TokenStream) -> TokenStream { | |
470 | let mut tokens = input.into_iter().collect(); | |
471 | paste::expand(&mut tokens); | |
472 | tokens.into_iter().collect() | |
473 | } | |
071cedc8 BL |
474 | |
475 | /// Derives the [`Zeroable`] trait for the given struct. | |
476 | /// | |
477 | /// This can only be used for structs where every field implements the [`Zeroable`] trait. | |
478 | /// | |
479 | /// # Examples | |
480 | /// | |
ae7851c2 ET |
481 | /// ``` |
482 | /// use kernel::macros::Zeroable; | |
483 | /// | |
071cedc8 BL |
484 | /// #[derive(Zeroable)] |
485 | /// pub struct DriverData { | |
486 | /// id: i64, | |
487 | /// buf_ptr: *mut u8, | |
488 | /// len: usize, | |
489 | /// } | |
490 | /// ``` | |
491 | #[proc_macro_derive(Zeroable)] | |
492 | pub fn derive_zeroable(input: TokenStream) -> TokenStream { | |
493 | zeroable::derive(input) | |
494 | } |