* [PATCH 0/2] rust: usb: add initial USB abstractions @ 2025-08-25 18:18 Daniel Almeida 2025-08-25 18:18 ` [PATCH 1/2] rust: usb: add basic " Daniel Almeida ` (2 more replies) 0 siblings, 3 replies; 18+ messages in thread From: Daniel Almeida @ 2025-08-25 18:18 UTC (permalink / raw) To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, Greg Kroah-Hartman Cc: linux-kernel, rust-for-linux, linux-usb, Daniel Almeida This adds initial support for USB Rust drivers, not only because I see a widespread use of module_usb_driver() in media (which is a subsystem I aim to support) but also because I want to learn about USB in general and this is a nice opportunity to start doing so. I tried to keep things as consistent with pci.rs and platform.rs as possible and tested it by manually binding a device (i.e.: my Logitech mouse) to the sample driver via: /sys/bus/usb/drivers/rust_driver_usb/new_id This initial patch is therefore comprised of the same patterns that are known to work for pci and platform already. Physically disconnecting the device also worked, i.e.: nothing bad showed up in dmesg. Note that I did not touch MAINTAINERS at all. The objective is to kickstart the discussion of what to do there here in v1. --- Daniel Almeida (2): rust: usb: add basic USB abstractions samples: rust: add a USB driver sample rust/bindings/bindings_helper.h | 1 + rust/helpers/helpers.c | 1 + rust/helpers/usb.c | 8 + rust/kernel/lib.rs | 2 + rust/kernel/usb.rs | 457 ++++++++++++++++++++++++++++++++++++++++ samples/rust/Kconfig | 11 + samples/rust/Makefile | 1 + samples/rust/rust_driver_usb.rs | 47 +++++ 8 files changed, 528 insertions(+) --- base-commit: 44d454fcffa8b08d6d66df132121c1d387fa85db change-id: 20250825-b4-usb-dd0fe44fd78b Best regards, -- Daniel Almeida <daniel.almeida@collabora.com> ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1/2] rust: usb: add basic USB abstractions 2025-08-25 18:18 [PATCH 0/2] rust: usb: add initial USB abstractions Daniel Almeida @ 2025-08-25 18:18 ` Daniel Almeida 2025-08-25 20:49 ` Benno Lossin 2025-08-25 18:18 ` [PATCH 2/2] samples: rust: add a USB driver sample Daniel Almeida 2025-08-25 20:32 ` [PATCH 0/2] rust: usb: add initial USB abstractions Greg Kroah-Hartman 2 siblings, 1 reply; 18+ messages in thread From: Daniel Almeida @ 2025-08-25 18:18 UTC (permalink / raw) To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, Greg Kroah-Hartman Cc: linux-kernel, rust-for-linux, linux-usb, Daniel Almeida Add basic USB abstractions, consisting of usb::{Device, Interface, Driver, Adapter, DeviceId} and the module_usb_driver macro. This is the first step in being able to write USB device drivers, which paves the way for USB media drivers - for example - among others. This initial support will then be used by a subsequent sample driver, which constitutes the only user of the USB abstractions so far. Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> --- rust/bindings/bindings_helper.h | 1 + rust/helpers/helpers.c | 1 + rust/helpers/usb.c | 8 + rust/kernel/lib.rs | 2 + rust/kernel/usb.rs | 457 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 469 insertions(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 69a975da829f0c35760f71a1b32b8fcb12c8a8dc..645afe578668097ae04455d9eefb102d1f1ce4af 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -73,6 +73,7 @@ #include <linux/security.h> #include <linux/slab.h> #include <linux/tracepoint.h> +#include <linux/usb.h> #include <linux/wait.h> #include <linux/workqueue.h> #include <linux/xarray.h> diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 44b2005d50140d34a44ae37d01c2ddbae6aeaa32..da1ee0d3705739e789c7ad21b957bbdb7ca23521 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -48,6 +48,7 @@ #include "task.c" #include "time.c" #include "uaccess.c" +#include "usb.c" #include "vmalloc.c" #include "wait.c" #include "workqueue.c" diff --git a/rust/helpers/usb.c b/rust/helpers/usb.c new file mode 100644 index 0000000000000000000000000000000000000000..fb2aad0cbf4d26ac7fb1a3f176ee7a1d30800f92 --- /dev/null +++ b/rust/helpers/usb.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/usb.h> + +struct usb_device *rust_helper_interface_to_usbdev(struct usb_interface *intf) +{ + return interface_to_usbdev(intf); +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index f8db761c5c95fc66e4c55f539b17fca613161ada..b15277a02028aa1d27480d0630f9f599cacd6e4d 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -127,6 +127,8 @@ pub mod tracepoint; pub mod transmute; pub mod types; +#[cfg(CONFIG_USB)] +pub mod usb; pub mod uaccess; pub mod workqueue; pub mod xarray; diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs new file mode 100644 index 0000000000000000000000000000000000000000..8899e7520b58d4e4b08927d54c8912650b78da33 --- /dev/null +++ b/rust/kernel/usb.rs @@ -0,0 +1,457 @@ +// SPDX-License-Identifier: GPL-2.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd. + +//! Abstractions for the USB bus. +//! +//! C header: [`include/linux/usb.h`](srctree/include/linux/usb.h) + +use crate::{ + bindings, device, + device_id::{RawDeviceId, RawDeviceIdIndex}, + driver, + error::{from_result, to_result, Result}, + prelude::*, + str::CStr, + types::{AlwaysRefCounted, Opaque}, + ThisModule, +}; +use core::{marker::PhantomData, mem::MaybeUninit, ptr::NonNull}; + +/// An adapter for the registration of USB drivers. +pub struct Adapter<T: Driver>(T); + +// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if +// a preceding call to `register` has been successful. +unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { + type RegType = bindings::usb_driver; + + unsafe fn register( + udrv: &Opaque<Self::RegType>, + name: &'static CStr, + module: &'static ThisModule, + ) -> Result { + // SAFETY: It's safe to set the fields of `struct usb_driver` on initialization. + unsafe { + (*udrv.get()).name = name.as_char_ptr(); + (*udrv.get()).probe = Some(Self::probe_callback); + (*udrv.get()).disconnect = Some(Self::disconnect_callback); + (*udrv.get()).id_table = T::ID_TABLE.as_ptr(); + } + + // SAFETY: `udrv` is guaranteed to be a valid `RegType`. + to_result(unsafe { + bindings::usb_register_driver(udrv.get(), module.0, name.as_char_ptr()) + }) + } + + unsafe fn unregister(udrv: &Opaque<Self::RegType>) { + // SAFETY: `udrv` is guaranteed to be a valid `RegType`. + unsafe { bindings::usb_deregister(udrv.get()) }; + } +} + +impl<T: Driver + 'static> Adapter<T> { + extern "C" fn probe_callback( + intf: *mut bindings::usb_interface, + id: *const bindings::usb_device_id, + ) -> kernel::ffi::c_int { + // SAFETY: The USB core only ever calls the probe callback with a valid pointer to a + // `struct usb_interface` and `struct usb_device_id`. + // + // INVARIANT: `intf` is valid for the duration of `probe_callback()`. + let intf = unsafe { &*intf.cast::<Interface<device::CoreInternal>>() }; + + from_result(|| { + // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct usb_device_id` and + // does not add additional invariants, so it's safe to transmute. + let id = unsafe { &*id.cast::<DeviceId>() }; + + let info = T::ID_TABLE.info(id.index()); + let data = T::probe(intf, id, info)?; + + let dev: &device::Device<device::CoreInternal> = intf.as_ref(); + dev.set_drvdata(data); + Ok(0) + }) + } + + extern "C" fn disconnect_callback(intf: *mut bindings::usb_interface) { + // SAFETY: The USB core only ever calls the disconnect callback with a valid pointer to a + // `struct usb_interface`. + // + // INVARIANT: `intf` is valid for the duration of `disconnect_callback()`. + let intf = unsafe { &*intf.cast::<Interface<device::CoreInternal>>() }; + + let dev: &device::Device<device::CoreInternal> = intf.as_ref(); + + // SAFETY: `disconnect_callback` is only ever called after a successful call to + // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called + // and stored a `Pin<KBox<T>>`. + let data = unsafe { dev.drvdata_obtain::<Pin<KBox<T>>>() }; + + T::disconnect(intf, data.as_ref()); + } +} + +/// Abstraction for the USB device ID structure, i.e. [`struct usb_device_id`]. +/// +/// [`struct usb_device_id`]: https://docs.kernel.org/driver-api/basics.html#c.usb_device_id +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct DeviceId(bindings::usb_device_id); + +impl DeviceId { + /// Equivalent to C's `USB_DEVICE` macro. + pub const fn from_id(vendor: u16, product: u16) -> Self { + Self(bindings::usb_device_id { + match_flags: bindings::USB_DEVICE_ID_MATCH_DEVICE as u16, + idVendor: vendor, + idProduct: product, + // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. + ..unsafe { MaybeUninit::zeroed().assume_init() } + }) + } + + /// Equivalent to C's `USB_DEVICE_VER` macro. + pub const fn from_device_ver(vendor: u16, product: u16, bcd_lo: u16, bcd_hi: u16) -> Self { + Self(bindings::usb_device_id { + match_flags: bindings::USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION as u16, + idVendor: vendor, + idProduct: product, + bcdDevice_lo: bcd_lo, + bcdDevice_hi: bcd_hi, + // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. + ..unsafe { MaybeUninit::zeroed().assume_init() } + }) + } + + /// Equivalent to C's `USB_DEVICE_INFO` macro. + pub const fn from_device_info(class: u8, subclass: u8, protocol: u8) -> Self { + Self(bindings::usb_device_id { + match_flags: bindings::USB_DEVICE_ID_MATCH_DEV_INFO as u16, + bDeviceClass: class, + bDeviceSubClass: subclass, + bDeviceProtocol: protocol, + // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. + ..unsafe { MaybeUninit::zeroed().assume_init() } + }) + } + + /// Equivalent to C's `USB_INTERFACE_INFO` macro. + pub const fn from_interface_info(class: u8, subclass: u8, protocol: u8) -> Self { + Self(bindings::usb_device_id { + match_flags: bindings::USB_DEVICE_ID_MATCH_INT_INFO as u16, + bInterfaceClass: class, + bInterfaceSubClass: subclass, + bInterfaceProtocol: protocol, + // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. + ..unsafe { MaybeUninit::zeroed().assume_init() } + }) + } + + /// Equivalent to C's `USB_DEVICE_INTERFACE_CLASS` macro. + pub const fn from_device_interface_class(vendor: u16, product: u16, class: u8) -> Self { + Self(bindings::usb_device_id { + match_flags: (bindings::USB_DEVICE_ID_MATCH_DEVICE + | bindings::USB_DEVICE_ID_MATCH_INT_CLASS) as u16, + idVendor: vendor, + idProduct: product, + bInterfaceClass: class, + // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. + ..unsafe { MaybeUninit::zeroed().assume_init() } + }) + } + + /// Equivalent to C's `USB_DEVICE_INTERFACE_PROTOCOL` macro. + pub const fn from_device_interface_protocol(vendor: u16, product: u16, protocol: u8) -> Self { + Self(bindings::usb_device_id { + match_flags: (bindings::USB_DEVICE_ID_MATCH_DEVICE + | bindings::USB_DEVICE_ID_MATCH_INT_PROTOCOL) as u16, + idVendor: vendor, + idProduct: product, + bInterfaceProtocol: protocol, + // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. + ..unsafe { MaybeUninit::zeroed().assume_init() } + }) + } + + /// Equivalent to C's `USB_DEVICE_INTERFACE_NUMBER` macro. + pub const fn from_device_interface_number(vendor: u16, product: u16, number: u8) -> Self { + Self(bindings::usb_device_id { + match_flags: (bindings::USB_DEVICE_ID_MATCH_DEVICE + | bindings::USB_DEVICE_ID_MATCH_INT_NUMBER) as u16, + idVendor: vendor, + idProduct: product, + bInterfaceNumber: number, + // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. + ..unsafe { MaybeUninit::zeroed().assume_init() } + }) + } + + /// Equivalent to C's `USB_DEVICE_AND_INTERFACE_INFO` macro. + pub const fn from_device_and_interface_info( + vendor: u16, + product: u16, + class: u8, + subclass: u8, + protocol: u8, + ) -> Self { + Self(bindings::usb_device_id { + match_flags: (bindings::USB_DEVICE_ID_MATCH_INT_INFO + | bindings::USB_DEVICE_ID_MATCH_DEVICE) as u16, + idVendor: vendor, + idProduct: product, + bInterfaceClass: class, + bInterfaceSubClass: subclass, + bInterfaceProtocol: protocol, + // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. + ..unsafe { MaybeUninit::zeroed().assume_init() } + }) + } +} + +// SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `usb_device_id` and does not add +// additional invariants, so it's safe to transmute to `RawType`. +unsafe impl RawDeviceId for DeviceId { + type RawType = bindings::usb_device_id; +} + +// SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_info` field. +unsafe impl RawDeviceIdIndex for DeviceId { + const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::usb_device_id, driver_info); + + fn index(&self) -> usize { + self.0.driver_info + } +} + +/// [`IdTable`](kernel::device_id::IdTable) type for USB. +pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>; + +/// Create a USB `IdTable` with its alias for modpost. +#[macro_export] +macro_rules! usb_device_table { + ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => { + const $table_name: $crate::device_id::IdArray< + $crate::usb::DeviceId, + $id_info_type, + { $table_data.len() }, + > = $crate::device_id::IdArray::new($table_data); + + $crate::module_device_table!("usb", $module_table_name, $table_name); + }; +} + +/// The USB driver trait. +/// +/// # Examples +/// +///``` +/// # use kernel::{bindings, device::Core, usb}; +/// use kernel::prelude::*; +/// +/// struct MyDriver; +/// +/// kernel::usb_device_table!( +/// USB_TABLE, +/// MODULE_USB_TABLE, +/// <MyDriver as usb::Driver>::IdInfo, +/// [ +/// (usb::DeviceId::from_id(0x1234, 0x5678), ()), +/// (usb::DeviceId::from_id(0xabcd, 0xef01), ()), +/// ] +/// ); +/// +/// impl usb::Driver for MyDriver { +/// type IdInfo = (); +/// const ID_TABLE: usb::IdTable<Self::IdInfo> = &USB_TABLE; +/// +/// fn probe( +/// _interface: &usb::Interface<Core>, +/// _id: &usb::DeviceId, +/// _info: &Self::IdInfo, +/// ) -> Result<Pin<KBox<Self>>> { +/// Err(ENODEV) +/// } +/// +/// fn disconnect(_interface: &usb::Interface<Core>, _data: Pin<&Self>) {} +/// } +///``` +pub trait Driver { + /// The type holding information about each one of the device ids supported by the driver. + type IdInfo: 'static; + + /// The table of device ids supported by the driver. + const ID_TABLE: IdTable<Self::IdInfo>; + + /// USB driver probe. + /// + /// Called when a new USB interface is bound to this driver. + /// Implementers should attempt to initialize the interface here. + fn probe( + interface: &Interface<device::Core>, + id: &DeviceId, + id_info: &Self::IdInfo, + ) -> Result<Pin<KBox<Self>>>; + + /// USB driver disconnect. + /// + /// Called when the USB interface is about to be unbound from this driver. + fn disconnect(interface: &Interface<device::Core>, data: Pin<&Self>); +} + +/// A USB interface. +/// +/// This structure represents the Rust abstraction for a C [`struct usb_interface`]. +/// The implementation abstracts the usage of a C [`struct usb_interface`] passed +/// in from the C side. +/// +/// # Invariants +/// +/// An [`Interface`] instance represents a valid [`struct usb_interface`] created +/// by the C portion of the kernel. +/// +/// [`struct usb_interface`]: https://www.kernel.org/doc/html/latest/driver-api/usb/usb.html#c.usb_interface +#[repr(transparent)] +pub struct Interface<Ctx: device::DeviceContext = device::Normal>( + Opaque<bindings::usb_interface>, + PhantomData<Ctx>, +); + +impl<Ctx: device::DeviceContext> Interface<Ctx> { + fn as_raw(&self) -> *mut bindings::usb_interface { + self.0.get() + } +} + +// SAFETY: `Interface` is a transparent wrapper of a type that doesn't depend on +// `Interface`'s generic argument. +kernel::impl_device_context_deref!(unsafe { Interface }); +kernel::impl_device_context_into_aref!(Interface); + +impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Interface<Ctx> { + fn as_ref(&self) -> &device::Device<Ctx> { + // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid + // `struct usb_interface`. + let dev = unsafe { &raw mut ((*self.as_raw()).dev) }; + + // SAFETY: `dev` points to a valid `struct device`. + unsafe { device::Device::from_raw(dev) } + } +} + +impl<Ctx: device::DeviceContext> AsRef<Device<Ctx>> for Interface<Ctx> { + fn as_ref(&self) -> &Device<Ctx> { + // SAFETY: `self.as_raw()` is valid by the type invariants. For a valid interface, + // the helper should always return a valid USB device pointer. + let usb_dev = unsafe { bindings::interface_to_usbdev(self.as_raw()) }; + + // SAFETY: The helper returns a valid interface pointer that shares the + // same `DeviceContext`. + unsafe { &*(usb_dev.cast()) } + } +} + +// SAFETY: Instances of `Interface` are always reference-counted. +unsafe impl AlwaysRefCounted for Interface { + fn inc_ref(&self) { + // SAFETY: The invariants of `Interface` guarantee that `self.as_raw()` + // returns a valid `struct usb_interface` pointer, for which we will + // acquire a new refcount. + unsafe { bindings::usb_get_intf(self.as_raw()) }; + } + + unsafe fn dec_ref(obj: NonNull<Self>) { + // SAFETY: The safety requirements guarantee that the refcount is non-zero. + unsafe { bindings::usb_put_intf(obj.cast().as_ptr()) } + } +} + +// SAFETY: A `Interface` is always reference-counted and can be released from any thread. +unsafe impl Send for Interface {} + +// SAFETY: It is safe to send a &Interface to another thread because we do not +// allow any mutation through a shared reference. +unsafe impl Sync for Interface {} + +/// A USB device. +/// +/// This structure represents the Rust abstraction for a C [`struct usb_device`]. +/// The implementation abstracts the usage of a C [`struct usb_device`] passed in +/// from the C side. +/// +/// # Invariants +/// +/// A [`Device`] instance represents a valid [`struct usb_device`] created by the C portion of the +/// kernel. +/// +/// [`struct usb_device`]: https://www.kernel.org/doc/html/latest/driver-api/usb/usb.html#c.usb_device +#[repr(transparent)] +pub struct Device<Ctx: device::DeviceContext = device::Normal>( + Opaque<bindings::usb_device>, + PhantomData<Ctx>, +); + +impl<Ctx: device::DeviceContext> Device<Ctx> { + fn as_raw(&self) -> *mut bindings::usb_device { + self.0.get() + } +} + +// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic +// argument. +kernel::impl_device_context_deref!(unsafe { Device }); +kernel::impl_device_context_into_aref!(Device); + +// SAFETY: Instances of `Device` are always reference-counted. +unsafe impl AlwaysRefCounted for Device { + fn inc_ref(&self) { + // SAFETY: The invariants of `Device` guarantee that `self.as_raw()` + // returns a valid `struct usb_device` pointer, for which we will + // acquire a new refcount. + unsafe { bindings::usb_get_dev(self.as_raw()) }; + } + + unsafe fn dec_ref(obj: NonNull<Self>) { + // SAFETY: The safety requirements guarantee that the refcount is non-zero. + unsafe { bindings::usb_put_dev(obj.cast().as_ptr()) } + } +} + +impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> { + fn as_ref(&self) -> &device::Device<Ctx> { + // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid + // `struct usb_device`. + let dev = unsafe { &raw mut ((*self.as_raw()).dev) }; + + // SAFETY: `dev` points to a valid `struct device`. + unsafe { device::Device::from_raw(dev) } + } +} + +// SAFETY: A `Device` is always reference-counted and can be released from any thread. +unsafe impl Send for Device {} + +// SAFETY: It is safe to send a &Device to another thread because we do not +// allow any mutation through a shared reference. +unsafe impl Sync for Device {} + +/// Declares a kernel module that exposes a single USB driver. +/// +/// # Examples +/// +/// ```ignore +/// module_usb_driver! { +/// type: MyDriver, +/// name: "Module name", +/// author: ["Author name"], +/// description: "Description", +/// license: "GPL v2", +/// } +/// ``` +#[macro_export] +macro_rules! module_usb_driver { + ($($f:tt)*) => { + $crate::module_driver!(<T>, $crate::usb::Adapter<T>, { $($f)* }); + } +} -- 2.50.1 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 1/2] rust: usb: add basic USB abstractions 2025-08-25 18:18 ` [PATCH 1/2] rust: usb: add basic " Daniel Almeida @ 2025-08-25 20:49 ` Benno Lossin 2025-08-25 21:03 ` Daniel Almeida 0 siblings, 1 reply; 18+ messages in thread From: Benno Lossin @ 2025-08-25 20:49 UTC (permalink / raw) To: Daniel Almeida, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, Greg Kroah-Hartman Cc: linux-kernel, rust-for-linux, linux-usb On Mon Aug 25, 2025 at 8:18 PM CEST, Daniel Almeida wrote: > +impl DeviceId { > + /// Equivalent to C's `USB_DEVICE` macro. > + pub const fn from_id(vendor: u16, product: u16) -> Self { > + Self(bindings::usb_device_id { > + match_flags: bindings::USB_DEVICE_ID_MATCH_DEVICE as u16, > + idVendor: vendor, > + idProduct: product, > + // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. > + ..unsafe { MaybeUninit::zeroed().assume_init() } You can avoid this usage of `unsafe` with this patch series: https://lore.kernel.org/all/20250814093046.2071971-1-lossin@kernel.org I'd like to avoid introducing any new one of these. --- Cheers, Benno > + }) > + } ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/2] rust: usb: add basic USB abstractions 2025-08-25 20:49 ` Benno Lossin @ 2025-08-25 21:03 ` Daniel Almeida 0 siblings, 0 replies; 18+ messages in thread From: Daniel Almeida @ 2025-08-25 21:03 UTC (permalink / raw) To: Benno Lossin Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, Greg Kroah-Hartman, linux-kernel, rust-for-linux, linux-usb Hi Benno, > On 25 Aug 2025, at 17:49, Benno Lossin <lossin@kernel.org> wrote: > > On Mon Aug 25, 2025 at 8:18 PM CEST, Daniel Almeida wrote: >> +impl DeviceId { >> + /// Equivalent to C's `USB_DEVICE` macro. >> + pub const fn from_id(vendor: u16, product: u16) -> Self { >> + Self(bindings::usb_device_id { >> + match_flags: bindings::USB_DEVICE_ID_MATCH_DEVICE as u16, >> + idVendor: vendor, >> + idProduct: product, >> + // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. >> + ..unsafe { MaybeUninit::zeroed().assume_init() } > > You can avoid this usage of `unsafe` with this patch series: > > https://lore.kernel.org/all/20250814093046.2071971-1-lossin@kernel.org > > I'd like to avoid introducing any new one of these. > > --- > Cheers, > Benno > >> + }) >> + } > Ah, nice, you spoke about this in the last RFL call, I remember it now. Ok, I will address this in the next version. — Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 2/2] samples: rust: add a USB driver sample 2025-08-25 18:18 [PATCH 0/2] rust: usb: add initial USB abstractions Daniel Almeida 2025-08-25 18:18 ` [PATCH 1/2] rust: usb: add basic " Daniel Almeida @ 2025-08-25 18:18 ` Daniel Almeida 2025-09-06 11:14 ` Greg Kroah-Hartman 2025-08-25 20:32 ` [PATCH 0/2] rust: usb: add initial USB abstractions Greg Kroah-Hartman 2 siblings, 1 reply; 18+ messages in thread From: Daniel Almeida @ 2025-08-25 18:18 UTC (permalink / raw) To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, Greg Kroah-Hartman Cc: linux-kernel, rust-for-linux, linux-usb, Daniel Almeida In light of the newly-added Rust abstractions for USB devices and drivers, add a sample USB rust driver that serves both to showcase what is currently supported, as well as be the only user of the USB abstractions for now. Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> --- samples/rust/Kconfig | 11 ++++++++++ samples/rust/Makefile | 1 + samples/rust/rust_driver_usb.rs | 47 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index 7f7371a004ee0a8f67dca99c836596709a70c4fa..fb222f93014c921b27a8a9a4293e90a2532faa82 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -83,6 +83,17 @@ config SAMPLE_RUST_DRIVER_PLATFORM If unsure, say N. +config SAMPLE_RUST_DRIVER_USB + tristate "USB Driver" + depends on USB + help + This option builds the Rust USB driver sample. + + To compile this as a module, choose M here: + the module will be called rust_driver_usb. + + If unsure, say N. + config SAMPLE_RUST_DRIVER_FAUX tristate "Faux Driver" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index bd2faad63b4f3befe7d1ed5139fe25c7a8b6d7f6..4e7df8a5cd277d101920c4b89a3ac6648b372b28 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o obj-$(CONFIG_SAMPLE_RUST_DMA) += rust_dma.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o +obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) += rust_driver_usb.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) += rust_driver_auxiliary.o obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) += rust_configfs.o diff --git a/samples/rust/rust_driver_usb.rs b/samples/rust/rust_driver_usb.rs new file mode 100644 index 0000000000000000000000000000000000000000..5c396f421de7f972985e57af48e8a9da0c558973 --- /dev/null +++ b/samples/rust/rust_driver_usb.rs @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd. + +//! Rust USB driver sample. + +use kernel::{device, device::Core, prelude::*, sync::aref::ARef, usb}; + +struct SampleDriver { + _intf: ARef<usb::Interface>, +} + +kernel::usb_device_table!( + USB_TABLE, + MODULE_USB_TABLE, + <SampleDriver as usb::Driver>::IdInfo, + [(usb::DeviceId::from_id(0x1234, 0x5678), ()),] +); + +impl usb::Driver for SampleDriver { + type IdInfo = (); + const ID_TABLE: usb::IdTable<Self::IdInfo> = &USB_TABLE; + + fn probe( + intf: &usb::Interface<Core>, + _id: &usb::DeviceId, + _info: &Self::IdInfo, + ) -> Result<Pin<KBox<Self>>> { + let dev: &device::Device<Core> = intf.as_ref(); + dev_info!(dev, "Rust USB driver sample probed\n"); + + let drvdata = KBox::new(Self { _intf: intf.into() }, GFP_KERNEL)?; + Ok(drvdata.into()) + } + + fn disconnect(intf: &usb::Interface<Core>, _data: Pin<&Self>) { + let dev: &device::Device<Core> = intf.as_ref(); + dev_info!(dev, "Rust USB driver sample disconnected\n"); + } +} + +kernel::module_usb_driver! { + type: SampleDriver, + name: "rust_driver_usb", + authors: ["Daniel Almeida"], + description: "Rust USB driver sample", + license: "GPL v2", +} -- 2.50.1 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-08-25 18:18 ` [PATCH 2/2] samples: rust: add a USB driver sample Daniel Almeida @ 2025-09-06 11:14 ` Greg Kroah-Hartman 2025-09-06 12:04 ` Daniel Almeida 0 siblings, 1 reply; 18+ messages in thread From: Greg Kroah-Hartman @ 2025-09-06 11:14 UTC (permalink / raw) To: Daniel Almeida Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel, rust-for-linux, linux-usb On Mon, Aug 25, 2025 at 03:18:06PM -0300, Daniel Almeida wrote: > In light of the newly-added Rust abstractions for USB devices and > drivers, add a sample USB rust driver that serves both to showcase what > is currently supported, as well as be the only user of the USB > abstractions for now. > > Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> > --- > samples/rust/Kconfig | 11 ++++++++++ > samples/rust/Makefile | 1 + > samples/rust/rust_driver_usb.rs | 47 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 59 insertions(+) > > diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig > index 7f7371a004ee0a8f67dca99c836596709a70c4fa..fb222f93014c921b27a8a9a4293e90a2532faa82 100644 > --- a/samples/rust/Kconfig > +++ b/samples/rust/Kconfig > @@ -83,6 +83,17 @@ config SAMPLE_RUST_DRIVER_PLATFORM > > If unsure, say N. > > +config SAMPLE_RUST_DRIVER_USB > + tristate "USB Driver" > + depends on USB > + help > + This option builds the Rust USB driver sample. > + > + To compile this as a module, choose M here: > + the module will be called rust_driver_usb. > + > + If unsure, say N. > + > config SAMPLE_RUST_DRIVER_FAUX > tristate "Faux Driver" > help > diff --git a/samples/rust/Makefile b/samples/rust/Makefile > index bd2faad63b4f3befe7d1ed5139fe25c7a8b6d7f6..4e7df8a5cd277d101920c4b89a3ac6648b372b28 100644 > --- a/samples/rust/Makefile > +++ b/samples/rust/Makefile > @@ -7,6 +7,7 @@ obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o > obj-$(CONFIG_SAMPLE_RUST_DMA) += rust_dma.o > obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o > obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o > +obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) += rust_driver_usb.o > obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o > obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) += rust_driver_auxiliary.o > obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) += rust_configfs.o > diff --git a/samples/rust/rust_driver_usb.rs b/samples/rust/rust_driver_usb.rs > new file mode 100644 > index 0000000000000000000000000000000000000000..5c396f421de7f972985e57af48e8a9da0c558973 > --- /dev/null > +++ b/samples/rust/rust_driver_usb.rs > @@ -0,0 +1,47 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd. > + > +//! Rust USB driver sample. > + > +use kernel::{device, device::Core, prelude::*, sync::aref::ARef, usb}; > + > +struct SampleDriver { > + _intf: ARef<usb::Interface>, > +} > + > +kernel::usb_device_table!( > + USB_TABLE, > + MODULE_USB_TABLE, > + <SampleDriver as usb::Driver>::IdInfo, > + [(usb::DeviceId::from_id(0x1234, 0x5678), ()),] > +); > + > +impl usb::Driver for SampleDriver { > + type IdInfo = (); > + const ID_TABLE: usb::IdTable<Self::IdInfo> = &USB_TABLE; > + > + fn probe( > + intf: &usb::Interface<Core>, > + _id: &usb::DeviceId, > + _info: &Self::IdInfo, > + ) -> Result<Pin<KBox<Self>>> { > + let dev: &device::Device<Core> = intf.as_ref(); > + dev_info!(dev, "Rust USB driver sample probed\n"); > + > + let drvdata = KBox::new(Self { _intf: intf.into() }, GFP_KERNEL)?; > + Ok(drvdata.into()) > + } > + > + fn disconnect(intf: &usb::Interface<Core>, _data: Pin<&Self>) { > + let dev: &device::Device<Core> = intf.as_ref(); > + dev_info!(dev, "Rust USB driver sample disconnected\n"); > + } > +} > + > +kernel::module_usb_driver! { > + type: SampleDriver, > + name: "rust_driver_usb", > + authors: ["Daniel Almeida"], > + description: "Rust USB driver sample", > + license: "GPL v2", > +} Sorry for the delay. But these bindings really are only for a usb interface probe/disconnect sequence, right? no real data flow at all? I recommend looking at the usb-skeleton.c driver, and implementing that as your sample driver for rust. That will ensure that you actually have the correct apis implemented and the reference count logic working properly. You have urb anchors and callbacks and other stuff as well to ensure that you get right. That driver pretty much should handle everything that you need to do to write a usb driver for any type of "real" device. thanks, greg k-h ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-09-06 11:14 ` Greg Kroah-Hartman @ 2025-09-06 12:04 ` Daniel Almeida 2025-09-06 12:10 ` Greg Kroah-Hartman 0 siblings, 1 reply; 18+ messages in thread From: Daniel Almeida @ 2025-09-06 12:04 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel, rust-for-linux, linux-usb Hi Greg, […] > > Sorry for the delay. > > But these bindings really are only for a usb interface probe/disconnect > sequence, right? no real data flow at all? > > I recommend looking at the usb-skeleton.c driver, and implementing that > as your sample driver for rust. That will ensure that you actually have > the correct apis implemented and the reference count logic working > properly. You have urb anchors and callbacks and other stuff as well to > ensure that you get right. That driver pretty much should handle > everything that you need to do to write a usb driver for any type of > "real" device. > > thanks, > > greg k-h I thought that an iterative approach would work here, i.e.: merge this, then URBs, then more stuff, etc. In any case that’s OK. I will work on the other stuff you listed here. — Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-09-06 12:04 ` Daniel Almeida @ 2025-09-06 12:10 ` Greg Kroah-Hartman 2025-09-06 12:41 ` Daniel Almeida 0 siblings, 1 reply; 18+ messages in thread From: Greg Kroah-Hartman @ 2025-09-06 12:10 UTC (permalink / raw) To: Daniel Almeida Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel, rust-for-linux, linux-usb On Sat, Sep 06, 2025 at 09:04:04AM -0300, Daniel Almeida wrote: > Hi Greg, > > […] > > > > > Sorry for the delay. > > > > But these bindings really are only for a usb interface probe/disconnect > > sequence, right? no real data flow at all? > > > > I recommend looking at the usb-skeleton.c driver, and implementing that > > as your sample driver for rust. That will ensure that you actually have > > the correct apis implemented and the reference count logic working > > properly. You have urb anchors and callbacks and other stuff as well to > > ensure that you get right. That driver pretty much should handle > > everything that you need to do to write a usb driver for any type of > > "real" device. > > > > thanks, > > > > greg k-h > > > I thought that an iterative approach would work here, i.e.: merge this, then > URBs, then more stuff, etc. Ah, that makes sense, I didn't realize you want that here. What USB device do you want to write a rust driver for? Are you going to need bindings to the usb major number, or is it going to talk to some other subsystem instead? Right now, these bindings don't really do anything USB specific at all except allow a driver to bind to a device. thanks, greg k-h ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-09-06 12:10 ` Greg Kroah-Hartman @ 2025-09-06 12:41 ` Daniel Almeida 2025-09-06 13:07 ` Greg Kroah-Hartman 2025-09-06 13:22 ` Danilo Krummrich 0 siblings, 2 replies; 18+ messages in thread From: Daniel Almeida @ 2025-09-06 12:41 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel, rust-for-linux, linux-usb >> >> I thought that an iterative approach would work here, i.e.: merge this, then >> URBs, then more stuff, etc. > > Ah, that makes sense, I didn't realize you want that here. What USB > device do you want to write a rust driver for? Are you going to need > bindings to the usb major number, or is it going to talk to some other > subsystem instead? > > Right now, these bindings don't really do anything USB specific at all > except allow a driver to bind to a device. > > thanks, > > greg k-h To be honest, I'm trying to pave the way for others. I often hear people saying that they would look into Rust drivers if only they did not have to write all the surrounding infrastructure themselves. On the other hand, there is no infrastructure because there are no drivers. It's a chicken and egg problem that I am trying to solve. It's also a cool opportunity to learn about USB, but I don't have any plans for a driver at the moment other than a instructional sample driver in Rust. Give me a few more weeks and I'll come up with the code for the other things you've pointed out. By the way, I wonder how testing would work. I tested this by plugging in my mouse and fiddling around with /sys/bus/usb/drivers/rust_driver_usb/new_id. I am not sure how this is going to work once I start looking into data transfer and etc. Perhaps there's a simple device out there that I should target? Or maybe there's a way to "fake" a USB device that would work with the sample driver for demonstration purposes. -- Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-09-06 12:41 ` Daniel Almeida @ 2025-09-06 13:07 ` Greg Kroah-Hartman 2025-09-06 14:49 ` Alan Stern 2025-09-06 14:56 ` Daniel Almeida 2025-09-06 13:22 ` Danilo Krummrich 1 sibling, 2 replies; 18+ messages in thread From: Greg Kroah-Hartman @ 2025-09-06 13:07 UTC (permalink / raw) To: Daniel Almeida Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel, rust-for-linux, linux-usb On Sat, Sep 06, 2025 at 09:41:16AM -0300, Daniel Almeida wrote: > > > >> > >> I thought that an iterative approach would work here, i.e.: merge this, then > >> URBs, then more stuff, etc. > > > > Ah, that makes sense, I didn't realize you want that here. What USB > > device do you want to write a rust driver for? Are you going to need > > bindings to the usb major number, or is it going to talk to some other > > subsystem instead? > > > > Right now, these bindings don't really do anything USB specific at all > > except allow a driver to bind to a device. > > > > thanks, > > > > greg k-h > > To be honest, I'm trying to pave the way for others. > > I often hear people saying that they would look into Rust drivers if only they > did not have to write all the surrounding infrastructure themselves. On the > other hand, there is no infrastructure because there are no drivers. It's a > chicken and egg problem that I am trying to solve. Sure, but a framework like this (probe/disconnect), really isn't USB, it's just driver core stuff :) > It's also a cool opportunity to learn about USB, but I don't have any plans > for a driver at the moment other than a instructional sample driver in Rust. Then let's not add bindings without a real user please. We don't want to maintain them for no good reason. > Give me a few more weeks and I'll come up with the code for the other things > you've pointed out. > > By the way, I wonder how testing would work. I tested this by plugging in my > mouse and fiddling around with /sys/bus/usb/drivers/rust_driver_usb/new_id. I > am not sure how this is going to work once I start looking into data transfer > and etc. Perhaps there's a simple device out there that I should target? Or > maybe there's a way to "fake" a USB device that would work with the sample > driver for demonstration purposes. You can use the usb-gadget subsystem and dummy-hcd to create a loop-back for a virtual USB device. That's how syzbot does USB driver fuzz testing, there should be some documentation on that somewhere in the tree. thanks greg k-h ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-09-06 13:07 ` Greg Kroah-Hartman @ 2025-09-06 14:49 ` Alan Stern 2025-09-06 14:56 ` Daniel Almeida 1 sibling, 0 replies; 18+ messages in thread From: Alan Stern @ 2025-09-06 14:49 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: Daniel Almeida, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel, rust-for-linux, linux-usb On Sat, Sep 06, 2025 at 03:07:16PM +0200, Greg Kroah-Hartman wrote: > On Sat, Sep 06, 2025 at 09:41:16AM -0300, Daniel Almeida wrote: > > By the way, I wonder how testing would work. I tested this by plugging in my > > mouse and fiddling around with /sys/bus/usb/drivers/rust_driver_usb/new_id. I > > am not sure how this is going to work once I start looking into data transfer > > and etc. Perhaps there's a simple device out there that I should target? Or > > maybe there's a way to "fake" a USB device that would work with the sample > > driver for demonstration purposes. > > You can use the usb-gadget subsystem and dummy-hcd to create a loop-back > for a virtual USB device. That's how syzbot does USB driver fuzz > testing, there should be some documentation on that somewhere in the > tree. Gadget zero is a good one to use for testing. That's what it's meant for. If you need any help setting it up, just ask. Alan Stern ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-09-06 13:07 ` Greg Kroah-Hartman 2025-09-06 14:49 ` Alan Stern @ 2025-09-06 14:56 ` Daniel Almeida 1 sibling, 0 replies; 18+ messages in thread From: Daniel Almeida @ 2025-09-06 14:56 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel, rust-for-linux, linux-usb > On 6 Sep 2025, at 10:07, Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote: > > On Sat, Sep 06, 2025 at 09:41:16AM -0300, Daniel Almeida wrote: >> >> >>>> >>>> I thought that an iterative approach would work here, i.e.: merge this, then >>>> URBs, then more stuff, etc. >>> >>> Ah, that makes sense, I didn't realize you want that here. What USB >>> device do you want to write a rust driver for? Are you going to need >>> bindings to the usb major number, or is it going to talk to some other >>> subsystem instead? >>> >>> Right now, these bindings don't really do anything USB specific at all >>> except allow a driver to bind to a device. >>> >>> thanks, >>> >>> greg k-h >> >> To be honest, I'm trying to pave the way for others. >> >> I often hear people saying that they would look into Rust drivers if only they >> did not have to write all the surrounding infrastructure themselves. On the >> other hand, there is no infrastructure because there are no drivers. It's a >> chicken and egg problem that I am trying to solve. > > Sure, but a framework like this (probe/disconnect), really isn't USB, > it's just driver core stuff :) > >> It's also a cool opportunity to learn about USB, but I don't have any plans >> for a driver at the moment other than a instructional sample driver in Rust. > > Then let's not add bindings without a real user please. We don't want > to maintain them for no good reason. > That’s OK Greg, I totally see your point here. I guess we can shelve this work for the time being then. To everybody else: if anyone is willing to write USB drivers, let me know. I will work with you to get the abstractions in place so that we have both the abstractions and a real user. -- Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-09-06 12:41 ` Daniel Almeida 2025-09-06 13:07 ` Greg Kroah-Hartman @ 2025-09-06 13:22 ` Danilo Krummrich 2025-09-06 14:50 ` Daniel Almeida 1 sibling, 1 reply; 18+ messages in thread From: Danilo Krummrich @ 2025-09-06 13:22 UTC (permalink / raw) To: Daniel Almeida Cc: Greg Kroah-Hartman, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, linux-kernel, rust-for-linux, linux-usb On Sat Sep 6, 2025 at 2:41 PM CEST, Daniel Almeida wrote: >>> >>> I thought that an iterative approach would work here, i.e.: merge this, then >>> URBs, then more stuff, etc. >> >> Ah, that makes sense, I didn't realize you want that here. What USB >> device do you want to write a rust driver for? Are you going to need >> bindings to the usb major number, or is it going to talk to some other >> subsystem instead? >> >> Right now, these bindings don't really do anything USB specific at all >> except allow a driver to bind to a device. >> >> thanks, >> >> greg k-h > > To be honest, I'm trying to pave the way for others. > > I often hear people saying that they would look into Rust drivers if only they > did not have to write all the surrounding infrastructure themselves. On the > other hand, there is no infrastructure because there are no drivers. I think saying that there is no infrastructure for writing Rust drivers is not accurate: We already have lots of infrastructure in place, such as device / driver core infrastructure, PCI, platform (with OF and ACPI), faux and auxilirary bus infrastructure, I/O, workqueues, timekeeping, cpufreq, firmware, DMA and a lot more. Not to forget the absolute core primitives, such as kernel allocators, xarray, locking infrastructure or very recently maple tree and LKMM atomics. Besides that we also have a lot of infrastructure that we do not have in C because it's simply not possible or applicable. However, it is in fact true that there is no USB infrastructure yet. > It's a chicken and egg problem that I am trying to solve. This is exactly why we develop Nova in-tree, such that we have a justification for adding all this infrastructure. Lot's of the stuff I listed above originates from that and I think the Nova project has proven that we can break this chicken and egg problem. I think one proof for that is that Tyr follows the approach. However, I agree that it still remains that someone (i.e. some driver) has to take the burden of doing the "heavy lifting" for a particular subsystem. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-09-06 13:22 ` Danilo Krummrich @ 2025-09-06 14:50 ` Daniel Almeida 2025-09-06 15:22 ` Danilo Krummrich 0 siblings, 1 reply; 18+ messages in thread From: Daniel Almeida @ 2025-09-06 14:50 UTC (permalink / raw) To: Danilo Krummrich Cc: Greg Kroah-Hartman, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, linux-kernel, rust-for-linux, linux-usb Hi Danilo, > On 6 Sep 2025, at 10:22, Danilo Krummrich <dakr@kernel.org> wrote: > > On Sat Sep 6, 2025 at 2:41 PM CEST, Daniel Almeida wrote: >>>> >>>> I thought that an iterative approach would work here, i.e.: merge this, then >>>> URBs, then more stuff, etc. >>> >>> Ah, that makes sense, I didn't realize you want that here. What USB >>> device do you want to write a rust driver for? Are you going to need >>> bindings to the usb major number, or is it going to talk to some other >>> subsystem instead? >>> >>> Right now, these bindings don't really do anything USB specific at all >>> except allow a driver to bind to a device. >>> >>> thanks, >>> >>> greg k-h >> >> To be honest, I'm trying to pave the way for others. >> >> I often hear people saying that they would look into Rust drivers if only they >> did not have to write all the surrounding infrastructure themselves. On the >> other hand, there is no infrastructure because there are no drivers. > > I think saying that there is no infrastructure for writing Rust drivers is not > accurate: > > We already have lots of infrastructure in place, such as device / driver core > infrastructure, PCI, platform (with OF and ACPI), faux and auxilirary bus > infrastructure, I/O, workqueues, timekeeping, cpufreq, firmware, DMA and a lot > more. > > Not to forget the absolute core primitives, such as kernel allocators, xarray, > locking infrastructure or very recently maple tree and LKMM atomics. > > Besides that we also have a lot of infrastructure that we do not have in C > because it's simply not possible or applicable. > > However, it is in fact true that there is no USB infrastructure yet. Ah yes, of course there’s plenty of things but this is specifically about USB. I worked on a few of those so I'm not denying them, I guess I should have written this more clearly :) I’ve also been told the same about media drivers. For example, someone trying to write a USB media driver stares at work needed to just _start_ doing what they had initially planned and simply gives up. It creates a scenario where people continuously wait on each other to do the "heavy work", i.e.: to come up with the common code/abstractions. So far I see a pattern where sample drivers count as users. This has been the case, for example, for rust_dma.rs. I was under the impression that the same would apply here. Although I do realize that there were plans for dma code other than rust_dma.rs, of course. > >> It's a chicken and egg problem that I am trying to solve. > > This is exactly why we develop Nova in-tree, such that we have a justification > for adding all this infrastructure. > > Lot's of the stuff I listed above originates from that and I think the Nova > project has proven that we can break this chicken and egg problem. I think > one proof for that is that Tyr follows the approach. > > However, I agree that it still remains that someone (i.e. some driver) has to > take the burden of doing the "heavy lifting" for a particular subsystem. As for Nova and Tyr, these are projects with a lot of big companies involved. They were able to break this chicken and egg situation in part due to that, because companies were willing to allocate engineers for both the drivers _and_ the required infrastructure. Unless the same can be said for USB, media or any other subsystems, I don't see it happening. Also, even if there is a company interested, smaller ones are not willing to work on the infrastructure either, only on the actual end results (i.e.: drivers). That's just my humble opinion, of course. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-09-06 14:50 ` Daniel Almeida @ 2025-09-06 15:22 ` Danilo Krummrich 2025-09-06 15:46 ` Daniel Almeida 0 siblings, 1 reply; 18+ messages in thread From: Danilo Krummrich @ 2025-09-06 15:22 UTC (permalink / raw) To: Daniel Almeida Cc: Greg Kroah-Hartman, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Michal Wilczynski, Igor Korotin, linux-kernel, rust-for-linux, linux-usb On Sat Sep 6, 2025 at 4:50 PM CEST, Daniel Almeida wrote: > So far I see a pattern where sample drivers count as users. This has been the > case, for example, for rust_dma.rs. I was under the impression that the same > would apply here. Although I do realize that there were plans for dma code > other than rust_dma.rs, of course. This isn't the case, we have those sample drivers to make it easy to review the the code and illustrate in an isolated context how it works. But, there has always been a "real" user behind that. In the case of the DMA work it was Nova. > As for Nova and Tyr, these are projects with a lot of big companies involved. > > They were able to break this chicken and egg situation in part due to that, > because companies were willing to allocate engineers for both the drivers _and_ > the required infrastructure. Unless the same can be said for USB, media or any > other subsystems, I don't see it happening. Well, this is true for Nova and Tyr, but I disagree that this is the reason we were able to break the chicken and egg problem. For instance, the initial lift around the driver core, PCI, I/O, etc. infrastructure was done by me, a single person. This could have been happening in the context of a very simple and small driver as well, rather than a big GPU driver with lots of companies and people involved. Igor (Cc) is doing the initial lift for I2C and Michal (Cc) for PWM for instance. So, I see those things happen and I don't think that such initial lifting necessarily needs big companies with dozens of engineers being involved. If we know people who want to write drivers for a subsystem that doesn't yet have Rust infrastructure (such as USB), let's encourage them to get started / involved anyways and let's help them as they go. But also please don't get me wrong, I understand and very much appreciate you want to get the ball rolling, but let's not discourage people by making it sounds as if it would be impossible for individuals. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-09-06 15:22 ` Danilo Krummrich @ 2025-09-06 15:46 ` Daniel Almeida 2025-09-06 15:48 ` Danilo Krummrich 0 siblings, 1 reply; 18+ messages in thread From: Daniel Almeida @ 2025-09-06 15:46 UTC (permalink / raw) To: Danilo Krummrich Cc: Greg Kroah-Hartman, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Michal Wilczynski, Igor Korotin, linux-kernel, rust-for-linux, linux-usb > On 6 Sep 2025, at 12:22, Danilo Krummrich <dakr@kernel.org> wrote: > > On Sat Sep 6, 2025 at 4:50 PM CEST, Daniel Almeida wrote: >> So far I see a pattern where sample drivers count as users. This has been the >> case, for example, for rust_dma.rs. I was under the impression that the same >> would apply here. Although I do realize that there were plans for dma code >> other than rust_dma.rs, of course. > > This isn't the case, we have those sample drivers to make it easy to review the > the code and illustrate in an isolated context how it works. But, there has > always been a "real" user behind that. In the case of the DMA work it was Nova. I see, thanks for clarifying! > >> As for Nova and Tyr, these are projects with a lot of big companies involved. >> >> They were able to break this chicken and egg situation in part due to that, >> because companies were willing to allocate engineers for both the drivers _and_ >> the required infrastructure. Unless the same can be said for USB, media or any >> other subsystems, I don't see it happening. > > Well, this is true for Nova and Tyr, but I disagree that this is the reason we > were able to break the chicken and egg problem. > > For instance, the initial lift around the driver core, PCI, I/O, etc. > infrastructure was done by me, a single person. This could have been happening > in the context of a very simple and small driver as well, rather than a big GPU > driver with lots of companies and people involved. > > Igor (Cc) is doing the initial lift for I2C and Michal (Cc) for PWM for > instance. > > So, I see those things happen and I don't think that such initial lifting > necessarily needs big companies with dozens of engineers being involved. It’s not about the number of people, or the work being out of reach for a single person, but more of someone asking themselves why it should be them to do it when there’s no big project like Nova or Tyr to justify it and employ them to do it all, vs employ them only for the actual drivers but not for the abstractions. Or if they’re working on their free time, it becomes even harder to justify spending energy on the abstractions if all they want is to write a driver. But if anyone got the impression that it is impossible to do it, my bad. It isn’t. > > If we know people who want to write drivers for a subsystem that doesn't yet > have Rust infrastructure (such as USB), let's encourage them to get started / > involved anyways and let's help them as they go. > > But also please don't get me wrong, I understand and very much appreciate you > want to get the ball rolling, but let's not discourage people by making it > sounds as if it would be impossible for individuals. > Yeah, point taken :) As I said to Greg above, I’m here to help if anyone wants to write a USB driver. Those interested are free to reach out to me and we will work together to merge the required abstractions with a real user in mind. Hopefully this encourages others to join in this work :) — Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] samples: rust: add a USB driver sample 2025-09-06 15:46 ` Daniel Almeida @ 2025-09-06 15:48 ` Danilo Krummrich 0 siblings, 0 replies; 18+ messages in thread From: Danilo Krummrich @ 2025-09-06 15:48 UTC (permalink / raw) To: Daniel Almeida Cc: Greg Kroah-Hartman, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Michal Wilczynski, Igor Korotin, linux-kernel, rust-for-linux, linux-usb On Sat Sep 6, 2025 at 5:46 PM CEST, Daniel Almeida wrote: > As I said to Greg above, I’m here to help if anyone wants to write a USB > driver. Those interested are free to reach out to me and we will work together > to merge the required abstractions with a real user in mind. Hopefully this > encourages others to join in this work :) Yes, that'd be great! :) ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/2] rust: usb: add initial USB abstractions 2025-08-25 18:18 [PATCH 0/2] rust: usb: add initial USB abstractions Daniel Almeida 2025-08-25 18:18 ` [PATCH 1/2] rust: usb: add basic " Daniel Almeida 2025-08-25 18:18 ` [PATCH 2/2] samples: rust: add a USB driver sample Daniel Almeida @ 2025-08-25 20:32 ` Greg Kroah-Hartman 2 siblings, 0 replies; 18+ messages in thread From: Greg Kroah-Hartman @ 2025-08-25 20:32 UTC (permalink / raw) To: Daniel Almeida Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel, rust-for-linux, linux-usb On Mon, Aug 25, 2025 at 03:18:04PM -0300, Daniel Almeida wrote: > This adds initial support for USB Rust drivers, not only because I see a > widespread use of module_usb_driver() in media (which is a subsystem I > aim to support) but also because I want to learn about USB in general > and this is a nice opportunity to start doing so. Oh wow, I wasn't expecting this, nice! I'm at a conference all this week so I can't review this just yet, give me a week please. But I am happy to see this happen, thanks for doing it. greg k-h ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2025-09-06 15:48 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-08-25 18:18 [PATCH 0/2] rust: usb: add initial USB abstractions Daniel Almeida 2025-08-25 18:18 ` [PATCH 1/2] rust: usb: add basic " Daniel Almeida 2025-08-25 20:49 ` Benno Lossin 2025-08-25 21:03 ` Daniel Almeida 2025-08-25 18:18 ` [PATCH 2/2] samples: rust: add a USB driver sample Daniel Almeida 2025-09-06 11:14 ` Greg Kroah-Hartman 2025-09-06 12:04 ` Daniel Almeida 2025-09-06 12:10 ` Greg Kroah-Hartman 2025-09-06 12:41 ` Daniel Almeida 2025-09-06 13:07 ` Greg Kroah-Hartman 2025-09-06 14:49 ` Alan Stern 2025-09-06 14:56 ` Daniel Almeida 2025-09-06 13:22 ` Danilo Krummrich 2025-09-06 14:50 ` Daniel Almeida 2025-09-06 15:22 ` Danilo Krummrich 2025-09-06 15:46 ` Daniel Almeida 2025-09-06 15:48 ` Danilo Krummrich 2025-08-25 20:32 ` [PATCH 0/2] rust: usb: add initial USB abstractions Greg Kroah-Hartman
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).