8
8
use crate :: { clk:: Clk , error:: from_kernel_err_ptr} ;
9
9
10
10
use crate :: {
11
- bindings,
11
+ bindings, c_str , c_types ,
12
12
revocable:: { Revocable , RevocableGuard } ,
13
13
str:: CStr ,
14
14
sync:: { NeedsLockClass , RevocableMutex , RevocableMutexGuard , UniqueRef } ,
15
15
Result ,
16
16
} ;
17
17
use core:: {
18
+ fmt,
18
19
ops:: { Deref , DerefMut } ,
19
20
pin:: Pin ,
20
21
} ;
@@ -64,6 +65,92 @@ pub unsafe trait RawDevice {
64
65
// SAFETY: clock is initialized with valid pointer returned from `bindings::clk_get` call.
65
66
unsafe { Ok ( Clk :: new ( clk_ptr) ) }
66
67
}
68
+
69
+ /// Prints an emergency-level message (level 0) prefixed with device information.
70
+ ///
71
+ /// More details are available from [`dev_emerg`].
72
+ fn pr_emerg ( & self , args : fmt:: Arguments < ' _ > ) {
73
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
74
+ unsafe { self . printk ( bindings:: KERN_EMERG , args) } ;
75
+ }
76
+
77
+ /// Prints an alert-level message (level 1) prefixed with device information.
78
+ ///
79
+ /// More details are available from [`dev_alert`].
80
+ fn pr_alert ( & self , args : fmt:: Arguments < ' _ > ) {
81
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
82
+ unsafe { self . printk ( bindings:: KERN_ALERT , args) } ;
83
+ }
84
+
85
+ /// Prints a critical-level message (level 2) prefixed with device information.
86
+ ///
87
+ /// More details are available from [`dev_crit`].
88
+ fn pr_crit ( & self , args : fmt:: Arguments < ' _ > ) {
89
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
90
+ unsafe { self . printk ( bindings:: KERN_CRIT , args) } ;
91
+ }
92
+
93
+ /// Prints an error-level message (level 3) prefixed with device information.
94
+ ///
95
+ /// More details are available from [`dev_err`].
96
+ fn pr_err ( & self , args : fmt:: Arguments < ' _ > ) {
97
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
98
+ unsafe { self . printk ( bindings:: KERN_ERR , args) } ;
99
+ }
100
+
101
+ /// Prints a warning-level message (level 4) prefixed with device information.
102
+ ///
103
+ /// More details are available from [`dev_warn`].
104
+ fn pr_warn ( & self , args : fmt:: Arguments < ' _ > ) {
105
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
106
+ unsafe { self . printk ( bindings:: KERN_WARNING , args) } ;
107
+ }
108
+
109
+ /// Prints a notice-level message (level 5) prefixed with device information.
110
+ ///
111
+ /// More details are available from [`dev_notice`].
112
+ fn pr_notice ( & self , args : fmt:: Arguments < ' _ > ) {
113
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
114
+ unsafe { self . printk ( bindings:: KERN_NOTICE , args) } ;
115
+ }
116
+
117
+ /// Prints an info-level message (level 6) prefixed with device information.
118
+ ///
119
+ /// More details are available from [`dev_info`].
120
+ fn pr_info ( & self , args : fmt:: Arguments < ' _ > ) {
121
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
122
+ unsafe { self . printk ( bindings:: KERN_INFO , args) } ;
123
+ }
124
+
125
+ /// Prints a debug-level message (level 7) prefixed with device information.
126
+ ///
127
+ /// More details are available from [`dev_dbg`].
128
+ fn pr_dbg ( & self , args : fmt:: Arguments < ' _ > ) {
129
+ if cfg ! ( debug_assertions) {
130
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
131
+ unsafe { self . printk ( bindings:: KERN_DEBUG , args) } ;
132
+ }
133
+ }
134
+
135
+ /// Prints the provided message to the console.
136
+ ///
137
+ /// # Safety
138
+ ///
139
+ /// Callers must ensure that `klevel` is null-terminated; in particular, one of the
140
+ /// `KERN_*`constants, for example, `KERN_CRIT`, `KERN_ALERT`, etc.
141
+ unsafe fn printk ( & self , klevel : & [ u8 ] , msg : fmt:: Arguments < ' _ > ) {
142
+ // SAFETY: `klevel` is null-terminated and one of the kernel constants. `self.raw_device`
143
+ // is valid because `self` is valid. The "%pA" format string expects a pointer to
144
+ // `fmt::Arguments`, which is what we're passing as the last argument.
145
+ unsafe {
146
+ bindings:: _dev_printk (
147
+ klevel as * const _ as * const c_types:: c_char ,
148
+ self . raw_device ( ) ,
149
+ c_str ! ( "%pA" ) . as_char_ptr ( ) ,
150
+ & msg as * const _ as * const c_types:: c_void ,
151
+ )
152
+ } ;
153
+ }
67
154
}
68
155
69
156
/// A ref-counted device.
@@ -76,6 +163,13 @@ pub struct Device {
76
163
pub ( crate ) ptr : * mut bindings:: device ,
77
164
}
78
165
166
+ // SAFETY: `Device` only holds a pointer to a C device, which is safe to be used from any thread.
167
+ unsafe impl Send for Device { }
168
+
169
+ // SAFETY: `Device` only holds a pointer to a C device, references to which are safe to be used
170
+ // from any thread.
171
+ unsafe impl Sync for Device { }
172
+
79
173
impl Device {
80
174
/// Creates a new device instance.
81
175
///
@@ -98,6 +192,13 @@ impl Device {
98
192
}
99
193
}
100
194
195
+ // SAFETY: The device returned by `raw_device` is the one for which we hold a reference.
196
+ unsafe impl RawDevice for Device {
197
+ fn raw_device ( & self ) -> * mut bindings:: device {
198
+ self . ptr
199
+ }
200
+ }
201
+
101
202
impl Drop for Device {
102
203
fn drop ( & mut self ) {
103
204
// SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to
@@ -225,3 +326,224 @@ impl<T, U, V> DerefMut for Data<T, U, V> {
225
326
& mut self . general
226
327
}
227
328
}
329
+
330
+ #[ doc( hidden) ]
331
+ #[ macro_export]
332
+ macro_rules! dev_printk {
333
+ ( $method: ident, $dev: expr, $( $f: tt) * ) => {
334
+ {
335
+ // We have an explicity `use` statement here so that callers of this macro are not
336
+ // required to explicitly use the `RawDevice` trait to use its functions.
337
+ use $crate:: device:: RawDevice ;
338
+ ( $dev) . $method( core:: format_args!( $( $f) * ) ) ;
339
+ }
340
+ }
341
+ }
342
+
343
+ /// Prints an emergency-level message (level 0) prefixed with device information.
344
+ ///
345
+ /// This level should be used if the system is unusable.
346
+ ///
347
+ /// Equivalent to the kernel's `dev_emerg` macro.
348
+ ///
349
+ /// Mimics the interface of [`std::print!`]. More information about the syntax is available from
350
+ /// [`core::fmt`] and [`alloc::format!`].
351
+ ///
352
+ /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
353
+ ///
354
+ /// # Examples
355
+ ///
356
+ /// ```
357
+ /// # use kernel::prelude::*;
358
+ /// # use kernel::device::Device;
359
+ ///
360
+ /// fn example(dev: &Device) {
361
+ /// dev_emerg!(dev, "hello {}\n", "there");
362
+ /// }
363
+ /// ```
364
+ #[ macro_export]
365
+ macro_rules! dev_emerg {
366
+ ( $( $f: tt) * ) => { $crate:: dev_printk!( pr_emerg, $( $f) * ) ; }
367
+ }
368
+
369
+ /// Prints an alert-level message (level 1) prefixed with device information.
370
+ ///
371
+ /// This level should be used if action must be taken immediately.
372
+ ///
373
+ /// Equivalent to the kernel's `dev_alert` macro.
374
+ ///
375
+ /// Mimics the interface of [`std::print!`]. More information about the syntax is available from
376
+ /// [`core::fmt`] and [`alloc::format!`].
377
+ ///
378
+ /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
379
+ ///
380
+ /// # Examples
381
+ ///
382
+ /// ```
383
+ /// # use kernel::prelude::*;
384
+ /// # use kernel::device::Device;
385
+ ///
386
+ /// fn example(dev: &Device) {
387
+ /// dev_alert!(dev, "hello {}\n", "there");
388
+ /// }
389
+ /// ```
390
+ #[ macro_export]
391
+ macro_rules! dev_alert {
392
+ ( $( $f: tt) * ) => { $crate:: dev_printk!( pr_alert, $( $f) * ) ; }
393
+ }
394
+
395
+ /// Prints a critical-level message (level 2) prefixed with device information.
396
+ ///
397
+ /// This level should be used in critical conditions.
398
+ ///
399
+ /// Equivalent to the kernel's `dev_crit` macro.
400
+ ///
401
+ /// Mimics the interface of [`std::print!`]. More information about the syntax is available from
402
+ /// [`core::fmt`] and [`alloc::format!`].
403
+ ///
404
+ /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
405
+ ///
406
+ /// # Examples
407
+ ///
408
+ /// ```
409
+ /// # use kernel::prelude::*;
410
+ /// # use kernel::device::Device;
411
+ ///
412
+ /// fn example(dev: &Device) {
413
+ /// dev_crit!(dev, "hello {}\n", "there");
414
+ /// }
415
+ /// ```
416
+ #[ macro_export]
417
+ macro_rules! dev_crit {
418
+ ( $( $f: tt) * ) => { $crate:: dev_printk!( pr_crit, $( $f) * ) ; }
419
+ }
420
+
421
+ /// Prints an error-level message (level 3) prefixed with device information.
422
+ ///
423
+ /// This level should be used in error conditions.
424
+ ///
425
+ /// Equivalent to the kernel's `dev_err` macro.
426
+ ///
427
+ /// Mimics the interface of [`std::print!`]. More information about the syntax is available from
428
+ /// [`core::fmt`] and [`alloc::format!`].
429
+ ///
430
+ /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
431
+ ///
432
+ /// # Examples
433
+ ///
434
+ /// ```
435
+ /// # use kernel::prelude::*;
436
+ /// # use kernel::device::Device;
437
+ ///
438
+ /// fn example(dev: &Device) {
439
+ /// dev_err!(dev, "hello {}\n", "there");
440
+ /// }
441
+ /// ```
442
+ #[ macro_export]
443
+ macro_rules! dev_err {
444
+ ( $( $f: tt) * ) => { $crate:: dev_printk!( pr_err, $( $f) * ) ; }
445
+ }
446
+
447
+ /// Prints a warning-level message (level 4) prefixed with device information.
448
+ ///
449
+ /// This level should be used in warning conditions.
450
+ ///
451
+ /// Equivalent to the kernel's `dev_warn` macro.
452
+ ///
453
+ /// Mimics the interface of [`std::print!`]. More information about the syntax is available from
454
+ /// [`core::fmt`] and [`alloc::format!`].
455
+ ///
456
+ /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
457
+ ///
458
+ /// # Examples
459
+ ///
460
+ /// ```
461
+ /// # use kernel::prelude::*;
462
+ /// # use kernel::device::Device;
463
+ ///
464
+ /// fn example(dev: &Device) {
465
+ /// dev_warn!(dev, "hello {}\n", "there");
466
+ /// }
467
+ /// ```
468
+ #[ macro_export]
469
+ macro_rules! dev_warn {
470
+ ( $( $f: tt) * ) => { $crate:: dev_printk!( pr_warn, $( $f) * ) ; }
471
+ }
472
+
473
+ /// Prints a notice-level message (level 5) prefixed with device information.
474
+ ///
475
+ /// This level should be used in normal but significant conditions.
476
+ ///
477
+ /// Equivalent to the kernel's `dev_notice` macro.
478
+ ///
479
+ /// Mimics the interface of [`std::print!`]. More information about the syntax is available from
480
+ /// [`core::fmt`] and [`alloc::format!`].
481
+ ///
482
+ /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
483
+ ///
484
+ /// # Examples
485
+ ///
486
+ /// ```
487
+ /// # use kernel::prelude::*;
488
+ /// # use kernel::device::Device;
489
+ ///
490
+ /// fn example(dev: &Device) {
491
+ /// dev_notice!(dev, "hello {}\n", "there");
492
+ /// }
493
+ /// ```
494
+ #[ macro_export]
495
+ macro_rules! dev_notice {
496
+ ( $( $f: tt) * ) => { $crate:: dev_printk!( pr_notice, $( $f) * ) ; }
497
+ }
498
+
499
+ /// Prints an info-level message (level 6) prefixed with device information.
500
+ ///
501
+ /// This level should be used for informational messages.
502
+ ///
503
+ /// Equivalent to the kernel's `dev_info` macro.
504
+ ///
505
+ /// Mimics the interface of [`std::print!`]. More information about the syntax is available from
506
+ /// [`core::fmt`] and [`alloc::format!`].
507
+ ///
508
+ /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
509
+ ///
510
+ /// # Examples
511
+ ///
512
+ /// ```
513
+ /// # use kernel::prelude::*;
514
+ /// # use kernel::device::Device;
515
+ ///
516
+ /// fn example(dev: &Device) {
517
+ /// dev_info!(dev, "hello {}\n", "there");
518
+ /// }
519
+ /// ```
520
+ #[ macro_export]
521
+ macro_rules! dev_info {
522
+ ( $( $f: tt) * ) => { $crate:: dev_printk!( pr_info, $( $f) * ) ; }
523
+ }
524
+
525
+ /// Prints a debug-level message (level 7) prefixed with device information.
526
+ ///
527
+ /// This level should be used for debug messages.
528
+ ///
529
+ /// Equivalent to the kernel's `dev_dbg` macro, except that it doesn't support dynamic debug yet.
530
+ ///
531
+ /// Mimics the interface of [`std::print!`]. More information about the syntax is available from
532
+ /// [`core::fmt`] and [`alloc::format!`].
533
+ ///
534
+ /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
535
+ ///
536
+ /// # Examples
537
+ ///
538
+ /// ```
539
+ /// # use kernel::prelude::*;
540
+ /// # use kernel::device::Device;
541
+ ///
542
+ /// fn example(dev: &Device) {
543
+ /// dev_dbg!(dev, "hello {}\n", "there");
544
+ /// }
545
+ /// ```
546
+ #[ macro_export]
547
+ macro_rules! dev_dbg {
548
+ ( $( $f: tt) * ) => { $crate:: dev_printk!( pr_dbg, $( $f) * ) ; }
549
+ }
0 commit comments