Re: [RFC PATCH 2/3] rust: power_supply: add power supply class abstraction

From: Alice Ryhl

Date: Thu Jul 09 2026 - 05:06:33 EST


On Wed, Jul 08, 2026 at 09:47:37PM +0000, Bruce Robertson wrote:
> There is no Rust abstraction for the power supply class in mainline or
> rust-next. Add a minimal one:
>
> - a Driver trait carrying the supply's name, type and property list,
> plus a get_property() method;
> - a generic extern "C" trampoline the power supply core calls back
> into, recovering the driver's private data via the parent device and
> dispatching to get_property();
> - a Registration that owns the power_supply_desc and unregisters the
> supply on drop, freeing the descriptor in the correct order.
>
> Property, type and status constants are re-exported so drivers need not
> reach into the generated bindings directly.
>
> Signed-off-by: Bruce Robertson <brucer42@xxxxxxxxx>

> +impl Drop for Registration {
> + fn drop(&mut self) {
> + // SAFETY: `psy` came from a successful `power_supply_register` and has not been
> + // unregistered. `power_supply_unregister` blocks until no callback is running;
> + // `_desc` (dropped immediately after) is then no longer referenced by the core.
> + unsafe { bindings::power_supply_unregister(self.psy) };
> + }
> +}
> +
> +/// Register a power supply backed by driver `T` against `dev`.
> +pub fn register<T: Driver + 'static>(dev: &Device) -> Result<Registration> {

Should this be &Device<Bound>?

> + let mut desc = KBox::new(bindings::power_supply_desc::default(), GFP_KERNEL)?;
> + desc.name = T::NAME.as_char_ptr();
> + desc.type_ = T::TYPE;
> + desc.properties = T::PROPERTIES.as_ptr();
> + desc.num_properties = T::PROPERTIES.len();
> + desc.get_property = Some(get_property_trampoline::<T>);
> +
> + // Stable heap address; moving the KBox into `Registration` keeps this valid
> + // (moving a KBox moves the pointer, not the heap allocation).
> + let desc_ptr: *const bindings::power_supply_desc = &*desc;
> +
> + let cfg = bindings::power_supply_config {
> + drv_data: dev.as_raw().cast::<kernel::ffi::c_void>(),
> + ..Default::default()
> + };
> +
> + // SAFETY: `dev` valid; `desc_ptr` points into `desc`, kept alive in the returned
> + // `Registration` and freed only after `power_supply_unregister`; `cfg` valid for the call.
> + let psy = unsafe { bindings::power_supply_register(dev.as_raw(), desc_ptr, &cfg) };
> + let psy = from_err_ptr(psy)?;
> +
> + Ok(Registration { psy, _desc: desc })
> +}

This looks like it should be a ::new() method on Registration instead?

I would compare with existing Registration abstractions and mirror how
they do it.

Alice