|
6 | 6 | //! register using the [`Registration`] class.
|
7 | 7 |
|
8 | 8 | use crate::error::{Error, Result};
|
9 |
| -use crate::{init::PinInit, str::CStr, try_pin_init, types::Opaque, ThisModule}; |
| 9 | +use crate::{device, init::PinInit, of, str::CStr, try_pin_init, types::Opaque, ThisModule}; |
10 | 10 | use core::pin::Pin;
|
11 | 11 | use macros::{pin_data, pinned_drop};
|
12 | 12 |
|
@@ -115,3 +115,59 @@ macro_rules! module_driver {
|
115 | 115 | }
|
116 | 116 | }
|
117 | 117 | }
|
| 118 | + |
| 119 | +/// The bus independent adapter to match a drivers and a devices. |
| 120 | +/// |
| 121 | +/// This trait should be implemented by the bus specific adapter, which represents the connection |
| 122 | +/// of a device and a driver. |
| 123 | +/// |
| 124 | +/// It provides bus independent functions for device / driver interactions. |
| 125 | +pub trait Adapter { |
| 126 | + /// The type holding driver private data about each device id supported by the driver. |
| 127 | + type IdInfo: 'static; |
| 128 | + |
| 129 | + /// The [`of::IdTable`] of the corresponding driver. |
| 130 | + fn of_id_table() -> Option<of::IdTable<Self::IdInfo>>; |
| 131 | + |
| 132 | + /// Returns the driver's private data from the matching entry in the [`of::IdTable`], if any. |
| 133 | + /// |
| 134 | + /// If this returns `None`, it means there is no match with an entry in the [`of::IdTable`]. |
| 135 | + #[cfg(CONFIG_OF)] |
| 136 | + fn of_id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> { |
| 137 | + let table = Self::of_id_table()?; |
| 138 | + |
| 139 | + // SAFETY: |
| 140 | + // - `table` has static lifetime, hence it's valid for read, |
| 141 | + // - `dev` is guaranteed to be valid while it's alive, and so is `pdev.as_ref().as_raw()`. |
| 142 | + let raw_id = unsafe { bindings::of_match_device(table.as_ptr(), dev.as_raw()) }; |
| 143 | + |
| 144 | + if raw_id.is_null() { |
| 145 | + None |
| 146 | + } else { |
| 147 | + // SAFETY: `DeviceId` is a `#[repr(transparent)` wrapper of `struct of_device_id` and |
| 148 | + // does not add additional invariants, so it's safe to transmute. |
| 149 | + let id = unsafe { &*raw_id.cast::<of::DeviceId>() }; |
| 150 | + |
| 151 | + Some(table.info(<of::DeviceId as crate::device_id::RawDeviceId>::index(id))) |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + #[cfg(not(CONFIG_OF))] |
| 156 | + #[allow(missing_docs)] |
| 157 | + fn of_id_info(_dev: &device::Device) -> Option<&'static Self::IdInfo> { |
| 158 | + None |
| 159 | + } |
| 160 | + |
| 161 | + /// Returns the driver's private data from the matching entry of any of the ID tables, if any. |
| 162 | + /// |
| 163 | + /// If this returns `None`, it means that there is no match in any of the ID tables directly |
| 164 | + /// associated with a [`device::Device`]. |
| 165 | + fn id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> { |
| 166 | + let id = Self::of_id_info(dev); |
| 167 | + if id.is_some() { |
| 168 | + return id; |
| 169 | + } |
| 170 | + |
| 171 | + None |
| 172 | + } |
| 173 | +} |
0 commit comments