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