Alternate setting support
kiffie opened this issue · 5 comments
Hi all,
I did not find support for Alternate Settings for Interfaces. Any progress here? As I needed this for one of my projects (USB audio), I use a quite pragmatic solution. Maybe, you would like to integrate it or something similar.
A function like interface_with_alternate_setting
could be added to descriptor.rs
, which must be called multiple times to create multiple interface descriptors for the respective alternate settings. The SET_INTERFACE request can then be handled in an impl<B: UsbBus> UsbClass<B>
. Later, the request handler in device.rs
could be extended to avoid boilerplate code in the UsbClass impl.
In case you are interested in this approach of adding alternate settings, I could create a PR.
Here is the code of the the function I added to my own copy of your code during my experiments:
/// Writes a interface descriptor with a specific alternate setting.
///
/// # Arguments
///
/// * `number` - Interface number previously allocated with
/// [`UsbBusAllocator::interface`](crate::bus::UsbBusAllocator::interface).
/// * `alternate_setting` - number of the alternate setting
/// * `interface_class` - Class code assigned by USB.org. Use `0xff` for vendor-specific devices
/// that do not conform to any class.
/// * `interface_sub_class` - Sub-class code. Depends on class.
/// * `interface_protocol` - Protocol code. Depends on class and sub-class.
pub fn interface_with_alternate_setting(&mut self, number: InterfaceNumber,
alternate_setting: u8,
interface_class: u8, interface_sub_class: u8, interface_protocol: u8) -> Result<()>
{
if alternate_setting == device::DEFAULT_ALTERNATE_SETTING {
match self.num_interfaces_mark {
Some(mark) => self.buf[mark] += 1,
None => return Err(UsbError::InvalidState),
};
}
self.num_endpoints_mark = Some(self.position + 4);
self.write(
descriptor_type::INTERFACE,
&[
number.into(), // bInterfaceNumber
alternate_setting, // bAlternateSetting (how to even handle these...)
0, // bNumEndpoints
interface_class, // bInterfaceClass
interface_sub_class, // bInterfaceSubClass
interface_protocol, // bInterfaceProtocol
0, // iInterface
])?;
Ok(())
}
Best regards,
Stephan
This looks very neat. In my dfu-bootloader project i did something similar:
/// Writes a interface descriptor.
///
/// # Arguments
///
/// * `number` - Interface number previously allocated with
/// [`UsbBusAllocator::interface`](crate::bus::UsbBusAllocator::interface).
/// * `interface_class` - Class code assigned by USB.org. Use `0xff` for vendor-specific devices
/// that do not conform to any class.
/// * `interface_sub_class` - Sub-class code. Depends on class.
/// * `interface_protocol` - Protocol code. Depends on class and sub-class.
pub fn interface(&mut self, number: InterfaceNumber, interface_class: u8,
interface_sub_class: u8, interface_protocol: u8) -> Result<()> {
self.interface_ex(number, interface_class, interface_sub_class,
interface_protocol, device::DEFAULT_ALTERNATE_SETTING,
0)
}
/// Extended writer for an interface descriptor
pub fn interface_ex(&mut self, number: InterfaceNumber,
interface_class: u8, interface_sub_class: u8, interface_protocol: u8,
alternate_setting: u8, i_interface: u8) -> Result<()>
{
match self.num_interfaces_mark {
Some(mark) => self.buf[mark] += 1,
None => return Err(UsbError::InvalidState),
};
self.num_endpoints_mark = Some(self.position + 4);
self.write(
descriptor_type::INTERFACE,
&[
number.into(), // bInterfaceNumber
//device::DEFAULT_ALTERNATE_SETTING, // bAlternateSetting (how to even handle these...)
alternate_setting, // bAlternateSetting
0, // bNumEndpoints
interface_class, // bInterfaceClass
interface_sub_class, // bInterfaceSubClass
interface_protocol, // bInterfaceProtocol
i_interface, // iInterface
])?;
Ok(())
}
I am slowly getting back into this project and updating everything. @mvirkkunen Could you please take a look at our two implementations? Maybe we can glue something together and make a PR for that. It would be awesome to have this feature in upstream.
I've started using this approach, it would be great to get something merged in to usb-device. @mvirkkunen are you OK with the USB class implementer dealing with the interface setting control requests?
I just created a PR (combined and beatified versions of the above two code snippets) for easier review and discussion.
Support was merged in #55. Thanks!
Great! Thank you.