Re: [RFC PATCH 2/4] rust: usb: add usb host interface and endpoint abstractions

From: Oliver Neukum

Date: Tue Jul 14 2026 - 05:31:33 EST


On 13.07.26 22:09, Danilo Krummrich wrote:
On Mon Jul 13, 2026 at 10:03 PM CEST, Colin Braun wrote:
On Mon, Jul 13, 2026 at 03:22:33PM +0200, Danilo Krummrich wrote:
(Cc: Oliver)

On Sun Jul 12, 2026 at 11:07 PM CEST, Colin Braun wrote:

[..]

An URB requires either usb::Interface<Bound> or, for a USB device driver,
usb::Device<Bound>. But since we can't derive usb::Device<Bound> from
usb::Interface<Bound> a simple forwarding helper does the trick.

That makes sense, thank you for pointing this out. I should have taken a
look at the git log for that line to try to understand its background.

I'll remove the usb::Device<device::Bound>::set_interface() and
usb::Device<device::Bound>::control_msg() implementations in my next
revision (since they will no longer be used) and just implement them on
usb::Interface<device::Bound>.

I'd keep them unsafely on usb::Device and then safely expose forwarding via
usb::Device<Bound> and usb::Interface<Bound> once required.

Hi,

you are making me think that the fundamental assumptions of the USB
layer are ill documented. If you find this to be the case, please tell
me what should be improved and I'll see what I can do.

Very well, this will be a bit longer, because I'll try to explain:
For now, there is exactly one device driver, named "generic" (yes,
imaginative). However, its behavior in that regard is rather fundamental,
so if another driver were ever to be written, its drivers would not
be normal interface drivers.

In principle the chain goes as such:

Device -> Configuration -> Interfaces

The dependencies are in that order. You can have a configuration without
interfaces and a device without configurations (it would be useless, but
it is within spec)
The life times are limited in the same way. An interface never lives
longer than its configuration and a configuration does not live longer
than its device.

This is controlled by code in drivers/usb/core/generic.c

int usb_generic_driver_probe(struct usb_device *udev)
{
int err, c;

/* Choose and set the configuration. This registers the interfaces
* with the driver core and lets interface drivers bind to them.
*/
if (udev->authorized == 0)
dev_info(&udev->dev, "Device is not authorized for usage\n");
else {
c = usb_choose_configuration(udev);
if (c >= 0) {
err = usb_set_configuration(udev, c);

This is the usual way a configuration is created. [You need not worry about
the other ways. They also call usb_set_configuration().]

Also important for this discussion is that this cannot fail:

if (err && err != -ENODEV) {
dev_err(&udev->dev, "can't set config #%d, error %d\n",
c, err);
/* This need not be fatal. The user can try to
* set other configurations. */
}
}
}
/* USB device state == configured ... usable */
usb_notify_add_device(udev);

return 0;
}

A configuration is destroyed by usb_set_configuration(). This
is used in disconnect:

void usb_generic_driver_disconnect(struct usb_device *udev)
{
usb_notify_remove_device(udev);

/* if this is only an unbind, not a physical disconnect, then
* unconfigure the device */
if (udev->actconfig)
usb_set_configuration(udev, -1);
}

( -1 means without replacement)

You can see that there is no way a configuration and thereby its interfaces
can last longer than its device.

An interface driver is allowed to talk to two sets of endpoints

1. endpoints associated with interfaces it has claimed, accepted or is probed for
2. endpoint 0 of the device whose interfaces it has claimed, accepted or is probed for

(Please do not ask about cdc-wdm)

That does _not_ mean that a driver can communicate to them at all times. Communication
is limited as follows:

Communication may begin when

1. probe() is called
2. usb_claim_interface() returns without error
3. resume() is called
4. reset_resume() is called
5. post_reset() is called

Communication must cease

1. before disconnect() returns
2. before suspend() returns
3. before pre_reset() returns
4. before probe() is exited with an error return

The only exception to that is that you may schedule a reset.

I hope this makes things a bit clearer. Please ask questions
if anything is unclear. I'd be happy to help.
This area may be a bit murky because only the states of devices
are named and documented. There simply is no data structure
equivalent to the binding of a driver and an interface, hence
we cannot just give interfaces a state.

Regards
Oliver