Convert MS OS descriptor builder to a writer API
This brings it inline with the other embassy-usb descriptor APIs and allows it to integrate well with the Builder to allow class constructors to add MS OS descriptors. Also adds a `usb_serial_winusb` example to demonstrate how to use the API.
This commit is contained in:
@ -3,6 +3,8 @@ use heapless::Vec;
|
||||
use crate::control::ControlHandler;
|
||||
use crate::descriptor::{BosWriter, DescriptorWriter};
|
||||
use crate::driver::{Driver, Endpoint, EndpointType};
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter};
|
||||
use crate::types::*;
|
||||
use crate::{DeviceStateHandler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START};
|
||||
|
||||
@ -130,7 +132,9 @@ pub struct Builder<'d, D: Driver<'d>> {
|
||||
device_descriptor: DescriptorWriter<'d>,
|
||||
config_descriptor: DescriptorWriter<'d>,
|
||||
bos_descriptor: BosWriter<'d>,
|
||||
msos_descriptor: Option<crate::msos::MsOsDescriptorSet<'d>>,
|
||||
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
msos_descriptor: MsOsDescriptorWriter<'d>,
|
||||
}
|
||||
|
||||
impl<'d, D: Driver<'d>> Builder<'d, D> {
|
||||
@ -145,6 +149,7 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
|
||||
device_descriptor_buf: &'d mut [u8],
|
||||
config_descriptor_buf: &'d mut [u8],
|
||||
bos_descriptor_buf: &'d mut [u8],
|
||||
#[cfg(feature = "msos-descriptor")] msos_descriptor_buf: &'d mut [u8],
|
||||
control_buf: &'d mut [u8],
|
||||
handler: Option<&'d dyn DeviceStateHandler>,
|
||||
) -> Self {
|
||||
@ -183,12 +188,17 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
|
||||
device_descriptor,
|
||||
config_descriptor,
|
||||
bos_descriptor,
|
||||
msos_descriptor: None,
|
||||
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
msos_descriptor: MsOsDescriptorWriter::new(msos_descriptor_buf),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates the [`UsbDevice`] instance with the configuration in this builder.
|
||||
pub fn build(mut self) -> UsbDevice<'d, D> {
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
let msos_descriptor = self.msos_descriptor.build(&mut self.bos_descriptor);
|
||||
|
||||
self.config_descriptor.end_configuration();
|
||||
self.bos_descriptor.end_bos();
|
||||
|
||||
@ -201,7 +211,8 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
|
||||
self.bos_descriptor.writer.into_buf(),
|
||||
self.interfaces,
|
||||
self.control_buf,
|
||||
self.msos_descriptor,
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
msos_descriptor,
|
||||
)
|
||||
}
|
||||
|
||||
@ -218,14 +229,10 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
|
||||
///
|
||||
/// If it's not set, no IAD descriptor is added.
|
||||
pub fn function(&mut self, class: u8, subclass: u8, protocol: u8) -> FunctionBuilder<'_, 'd, D> {
|
||||
let first_interface = InterfaceNumber::new(self.interfaces.len() as u8);
|
||||
let iface_count_index = if self.config.composite_with_iads {
|
||||
self.config_descriptor.iad(
|
||||
InterfaceNumber::new(self.interfaces.len() as _),
|
||||
0,
|
||||
class,
|
||||
subclass,
|
||||
protocol,
|
||||
);
|
||||
self.config_descriptor
|
||||
.iad(first_interface, 0, class, subclass, protocol);
|
||||
|
||||
Some(self.config_descriptor.position() - 5)
|
||||
} else {
|
||||
@ -235,19 +242,31 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
|
||||
FunctionBuilder {
|
||||
builder: self,
|
||||
iface_count_index,
|
||||
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
first_interface,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
/// Add an MS OS 2.0 Descriptor Set.
|
||||
///
|
||||
/// Panics if called more than once.
|
||||
pub fn msos_descriptor(&mut self, msos_descriptor: crate::msos::MsOsDescriptorSet<'d>) {
|
||||
if self.msos_descriptor.is_some() {
|
||||
panic!("msos_descriptor already set");
|
||||
}
|
||||
self.msos_descriptor
|
||||
.insert(msos_descriptor)
|
||||
.write_bos_capability(&mut self.bos_descriptor);
|
||||
pub fn msos_descriptor(&mut self, windows_version: u32, vendor_code: u8) {
|
||||
self.msos_descriptor.header(windows_version, vendor_code);
|
||||
}
|
||||
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
/// Add an MS OS 2.0 Device Level Feature Descriptor.
|
||||
pub fn msos_feature<T: DeviceLevelDescriptor>(&mut self, desc: T) {
|
||||
self.msos_descriptor.device_feature(desc);
|
||||
}
|
||||
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
/// Gets the underlying [`MsOsDescriptorWriter`] to allow adding subsets and features for classes that
|
||||
/// do not add their own.
|
||||
pub fn msos_writer(&mut self) -> &mut MsOsDescriptorWriter<'d> {
|
||||
&mut self.msos_descriptor
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,6 +278,16 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
|
||||
pub struct FunctionBuilder<'a, 'd, D: Driver<'d>> {
|
||||
builder: &'a mut Builder<'d, D>,
|
||||
iface_count_index: Option<usize>,
|
||||
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
first_interface: InterfaceNumber,
|
||||
}
|
||||
|
||||
impl<'a, 'd, D: Driver<'d>> Drop for FunctionBuilder<'a, 'd, D> {
|
||||
fn drop(&mut self) {
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
self.builder.msos_descriptor.end_function();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
|
||||
@ -288,6 +317,21 @@ impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
|
||||
next_alt_setting_number: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
/// Add an MS OS 2.0 Function Level Feature Descriptor.
|
||||
pub fn msos_feature<T: FunctionLevelDescriptor>(&mut self, desc: T) {
|
||||
if !self.builder.msos_descriptor.is_in_config_subset() {
|
||||
self.builder.msos_descriptor.configuration(0);
|
||||
}
|
||||
|
||||
if !self.builder.msos_descriptor.is_in_function_subset() {
|
||||
self.builder.msos_descriptor.function(self.first_interface.0);
|
||||
}
|
||||
|
||||
#[cfg(feature = "msos-descriptor")]
|
||||
self.builder.msos_descriptor.function_feature(desc);
|
||||
}
|
||||
}
|
||||
|
||||
/// Interface builder.
|
||||
|
Reference in New Issue
Block a user