Skip to content

Commit

Permalink
Merge branch 'atykhyy-master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
mvirkkunen committed Oct 3, 2020
2 parents c737d67 + ff5f9c7 commit 6f14f93
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod descriptor_type {
pub const STRING: u8 = 3;
pub const INTERFACE: u8 = 4;
pub const ENDPOINT: u8 = 5;
pub const IAD: u8 = 11;
pub const BOS: u8 = 15;
pub const CAPABILITY: u8 = 16;
}
Expand Down Expand Up @@ -39,6 +40,7 @@ pub struct DescriptorWriter<'a> {
position: usize,
num_interfaces_mark: Option<usize>,
num_endpoints_mark: Option<usize>,
write_iads: bool,
}

impl DescriptorWriter<'_> {
Expand All @@ -48,6 +50,7 @@ impl DescriptorWriter<'_> {
position: 0,
num_interfaces_mark: None,
num_endpoints_mark: None,
write_iads: false,
}
}

Expand Down Expand Up @@ -98,6 +101,8 @@ impl DescriptorWriter<'_> {
pub(crate) fn configuration(&mut self, config: &device::Config) -> Result<()> {
self.num_interfaces_mark = Some(self.position + 4);

self.write_iads = config.composite_with_iads;

self.write(
descriptor_type::CONFIGURATION,
&[
Expand All @@ -121,6 +126,42 @@ impl DescriptorWriter<'_> {
self.buf[2..4].copy_from_slice(&position.to_le_bytes());
}

/// Writes a interface association descriptor. Call from `UsbClass::get_configuration_descriptors`
/// before writing the USB class or function's interface descriptors if your class has more than
/// one interface and wants to play nicely with composite devices on Windows. If the USB device
/// hosting the class was not configured as composite with IADs enabled, calling this function
/// does nothing, so it is safe to call from libraries.
///
/// # Arguments
///
/// * `first_interface` - Number of the function's first interface, previously allocated with
/// [`UsbBusAllocator::interface`](crate::bus::UsbBusAllocator::interface).
/// * `interface_count` - Number of interfaces in the function.
/// * `function_class` - Class code assigned by USB.org. Use `0xff` for vendor-specific devices
/// that do not conform to any class.
/// * `function_sub_class` - Sub-class code. Depends on class.
/// * `function_protocol` - Protocol code. Depends on class and sub-class.
pub fn iad(&mut self, first_interface: InterfaceNumber, interface_count: u8,
function_class: u8, function_sub_class: u8, function_protocol: u8) -> Result<()>
{
if !self.write_iads {
return Ok(());
}

self.write(
descriptor_type::IAD,
&[
first_interface.into(), // bFirstInterface
interface_count, // bInterfaceCount
function_class,
function_sub_class,
function_protocol,
0
])?;

Ok(())
}

/// Writes a interface descriptor.
///
/// # Arguments
Expand Down
1 change: 1 addition & 0 deletions src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub(crate) struct Config<'a> {
pub serial_number: Option<&'a str>,
pub self_powered: bool,
pub supports_remote_wakeup: bool,
pub composite_with_iads: bool,
pub max_power: u8,
}

Expand Down
12 changes: 12 additions & 0 deletions src/device_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl<'a, B: UsbBus> UsbDeviceBuilder<'a, B> {
serial_number: None,
self_powered: false,
supports_remote_wakeup: false,
composite_with_iads: false,
max_power: 50,
}
}
Expand Down Expand Up @@ -91,6 +92,17 @@ impl<'a, B: UsbBus> UsbDeviceBuilder<'a, B> {
supports_remote_wakeup: bool,
}

/// Configures the device as a composite device with interface association descriptors.
pub fn composite_with_iads(mut self) -> Self {
// Magic values specified in USB-IF ECN on IADs.
self.config.device_class = 0xEF;
self.config.device_sub_class = 0x02;
self.config.device_protocol = 0x01;

self.config.composite_with_iads = true;
self
}

/// Sets the manufacturer name string descriptor.
///
/// Default: (none)
Expand Down

0 comments on commit 6f14f93

Please sign in to comment.