@@ -440,3 +440,81 @@ macro_rules! module_driver {
440
440
}
441
441
}
442
442
}
443
+
444
+ /// Implements a `get_id_info` function for drivers.
445
+ ///
446
+ /// Some kinds of drivers, e.g. platform drivers, need to get info from `of_id`.
447
+ /// This macro implements a function to do so with signature:
448
+ ///
449
+ /// ```ignore
450
+ /// fn get_id_info(dev: &Device) -> Option<&'static T::IdInfo>;
451
+ /// ```
452
+ ///
453
+ /// It should be called from inside an `impl<T: Driver> Adapter<T> {}` item.
454
+ ///
455
+ /// # Examples
456
+ ///
457
+ /// ```ignore
458
+ /// use crate::{
459
+ /// bindings,
460
+ /// device::{self, RawDevice},
461
+ /// driver,
462
+ /// of,
463
+ /// };
464
+ ///
465
+ /// pub trait Driver {
466
+ /// type IdInfo: 'static = ();
467
+ /// const OF_DEVICE_ID_TABLE: Option<driver::IdTable<'static, of::DeviceId, Self::IdInfo>> = None;
468
+ /// }
469
+ ///
470
+ /// pub struct Device {
471
+ /// ptr: *mut bindings::bar_device,
472
+ /// }
473
+ ///
474
+ /// // SAFETY: The device returned by `raw_device` is the raw bar device.
475
+ /// unsafe impl device::RawDevice for Device {
476
+ /// fn raw_device(&self) -> *mut bindings::device {
477
+ /// // SAFETY: By the type invariants, we know that `self.ptr` is non-null and valid.
478
+ /// unsafe { &mut (*self.ptr).dev }
479
+ /// }
480
+ /// }
481
+ ///
482
+ /// pub struct Foo<T: Driver>(T);
483
+ ///
484
+ /// impl<T: Driver> Adapter<T> {
485
+ /// // Implements a `get_id_info` function
486
+ /// crate::get_id_info!()
487
+ /// }
488
+ /// ```
489
+ #[ macro_export]
490
+ macro_rules! get_id_info {
491
+ ( ) => {
492
+ fn get_id_info( dev: & Device ) -> Option <& ' static T :: IdInfo > {
493
+ let table = T :: OF_DEVICE_ID_TABLE ?;
494
+
495
+ // SAFETY: `table` has static lifetime, so it is valid for read. `dev` is guaranteed to be
496
+ // valid while it's alive, so is the raw device returned by it.
497
+ let id = unsafe { bindings:: of_match_device( table. as_ref( ) , dev. raw_device( ) ) } ;
498
+ if id. is_null( ) {
499
+ return None ;
500
+ }
501
+
502
+ // SAFETY: `id` is a pointer within the static table, so it's always valid.
503
+ let offset = unsafe { ( * id) . data } ;
504
+ if offset. is_null( ) {
505
+ return None ;
506
+ }
507
+
508
+ // SAFETY: The offset comes from a previous call to `offset_from` in `IdArray::new`, which
509
+ // guarantees that the resulting pointer is within the table.
510
+ let ptr = unsafe {
511
+ id. cast:: <u8 >( )
512
+ . offset( offset as _)
513
+ . cast:: <Option <T :: IdInfo >>( )
514
+ } ;
515
+
516
+ // SAFETY: The id table has a static lifetime, so `ptr` is guaranteed to be valid for read.
517
+ unsafe { ( & * ptr) . as_ref( ) }
518
+ }
519
+ } ;
520
+ }
0 commit comments