Re: [PATCH RFC 1/2] rust: usb: add endpoint abstraction

"Alrexandru Radovici" <[email protected]> Mon, 03 Aug 2026 15:46:44 +0300
Newsgroups org.kernel.vger.rust-for-linux,org.kernel.vger.linux-kernel,org.kernel.vger.linux-usb
Message-ID <[email protected]>
On Sun Aug 2, 2026 at 11:39 AM EEST, Greg Kroah-Hartman wrote:
> On Sat, Aug 01, 2026 at 03:01:07AM +0300, Alexandru Radovici wrote:
>> Add an abstraction for `struct usb_host_endpoint`, together with the
>> accessors needed to reach one: `AlternateSetting` wrapping
>> `struct usb_host_interface`, `Interface::alternate_settings()` and
>> `Interface::current_alternate_setting()`, and `Device::control_endpoint(=
)`
>> for the default control endpoint, which no interface descriptor lists.
>
> Why?  USB drivers shouldn't be messing with usb_host_endpoint structures
> for the most part, what user do you have for this?

The more I think of this, I think you are right. `HostEndpoint`'s accessor
methods are only used for debug, as the `kernel` crate can access
the actual `usb_host_endpoint` underneeth. For debug purposes, we should
just derive the `Debug` trait instead.

>
>> `HostEndpoint` is generic over two sealed marker traits,
>> `EndpointDirection` and `EndpointTransferType`, whose implementors are
>> 1-ZSTs held in `PhantomData`. An endpoint borrowed from an alternate
>> setting starts out generic in both; `as_in()`, `as_out()` and
>> `as_control()` check the descriptor once and return a reference
>> carrying the corresponding marker, so a function taking
>> `&HostEndpoint<In, Bulk>` needs no check of its own. The type is
>> `#[repr(transparent)]` over the C struct and the markers are
>> zero-sized, so the refinement costs nothing and a slice of endpoints
>> can be borrowed directly from the C array.
>>=20
>> Control endpoints get a distinct `Bidirectional` marker rather than an
>> IN or OUT one. A control transfer takes its direction from bit 7 of the
>> setup packet's bmRequestType, and USB 2.0 section 9.6.6 defines the
>> corresponding bit of bEndpointAddress as ignored for control endpoints.
>> `as_in()` and `as_out()` are not implemented for `Bidirectional`, making
>> calling them a compile error rather than a misleading result.
>
> Don't over-think USB endpoints, they are "just" a pipe that contain a
> numbering scheme that the USB core uses.  Is that what you are trying to
> create here?  What are you trying to "enforce" here that the C code does
> not already do?

My USB knowledge is limited, so I hope I am not saying something
stupid here. My understanding is that drivers should not expect
interfaces to map the same endpoints (numbers) every time.
A driver should expect an interface to expose a certain number of
endpoints, each one with a certain type, but the actual number of each
exposed endpoint is not to be considered hardcoded. This means that drivers
should anyway iterate over the endpoints to discover the numbers
of the required endpoints.

My idea is to leaverage Rust's type system to prevent users from supplying
the wrong endpoint type at compile time rather then at runtime. By making
the `HostEndpoint` its own Rust type with no public constructor,
users will be forced to iterate the endpoints to discover the correct
number for each endpoint that they require. Once they have it, users
can hold to the reference as long as the interface is valid.

By adding the `Dir` and `Type` generic markers, suplying the wrong endpoint
to a function will be caught at compile time rather than at runtime. This
should hopefully shorthen the debug work needed for a driver, as some of
the errors become impossible.

As endpoint 0 is always provided and basically _almost hardcoded_``, I adde=
d
the `control_endpoint` function.=20

Best regards,
Alexandru