embassy-rs / embassy

Modern embedded framework, using Rust and async.
https://embassy.dev
Apache License 2.0
5.57k stars 773 forks source link

Support sharing USB endpoints between alternative settings of an interface #2994

Open Dominaezzz opened 5 months ago

Dominaezzz commented 5 months ago

At the moment the embassy-usb only supports allocating an endpoint per interface alternative setting.

However, in section 9.6.3 of the USB Spec Rev 2.0

An endpoint is not shared among interfaces within a single configuration unless the endpoint is used by alternate settings of the same interface.

The USB spec supports sharing the endpoint between the alternative settings of an interface, so a device with limited number of endpoints can provide multiple classes where each class only gets exclusive access at a time.

I haven't looked too deeply into how this should be exposed or how users would consume this but I'm just expressing the limitation here as it'll likely involve a breaking change to implement.

What I do wonder though, is whether alternative settings should share endpoints or if they just can.

sourcebox commented 5 months ago

This is also necessary for USB audio when supporting multiple formats (e.g. sample rates) because each requires an alternate setting.

M3gaFr3ak commented 2 months ago

@Dominaezzz I couldn't find any comment on that in the USB standard. But it is imperative for Endpoints to be independent of alternate settings. Each alternative setting on an interface is mutually exclusive to each other alternate setting, so an endpoint will be unused and unusable if it is exclusive to an alternate setting which is currently not in use. It is possible to work with this, but it's a waste of endpoints, which are limited in number varying by device.

My suggestion would be to add alternate builder endpoint functions with similar names, but accepting an existing endpoint reference as additional argument. This should return either void or alternatively a success/failure type. It should retain all other arguments from the original function as alternate setting endpoints can have completely different settings. This also requires reconfiguration of endpoints when changing alternate setting, so the endpoint type and buffer size must be reconfigurable. This is handled by the interrupts in UsbDevice. Buffers will also have to be changeable, but that shouldn't be too hard.

I started implementing this: https://github.com/M3gaFr3ak/embassy/tree/usb-endpoint-reuse