Expose a handle to the config descriptor writer
This commit is contained in:
parent
7b91597e9c
commit
847e5a7a75
@ -295,6 +295,13 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
|
|||||||
pub fn msos_writer(&mut self) -> &mut MsOsDescriptorWriter<'d> {
|
pub fn msos_writer(&mut self) -> &mut MsOsDescriptorWriter<'d> {
|
||||||
&mut self.msos_descriptor
|
&mut self.msos_descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a handle to the inner config descriptor writer owned by the [`UsbDevice`] builder.
|
||||||
|
///
|
||||||
|
/// This can be used to overwrite parts of the descriptor buffer or other granular controls over the buffer.
|
||||||
|
pub fn config_descriptor_writer(&mut self) -> &mut DescriptorWriter<'d> {
|
||||||
|
&mut self.config_descriptor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function builder.
|
/// Function builder.
|
||||||
@ -360,6 +367,13 @@ impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
|
|||||||
#[cfg(feature = "msos-descriptor")]
|
#[cfg(feature = "msos-descriptor")]
|
||||||
self.builder.msos_descriptor.function_feature(desc);
|
self.builder.msos_descriptor.function_feature(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a handle to the inner config descriptor writer owned by the [`UsbDevice`] builder.
|
||||||
|
///
|
||||||
|
/// This can be used to overwrite parts of the descriptor buffer or other granular controls over the buffer.
|
||||||
|
pub fn config_descriptor_writer(&mut self) -> &mut DescriptorWriter<'d> {
|
||||||
|
self.builder.config_descriptor_writer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interface builder.
|
/// Interface builder.
|
||||||
@ -411,6 +425,13 @@ impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> {
|
|||||||
alt_setting_number: number,
|
alt_setting_number: number,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a handle to the inner config descriptor writer owned by the [`UsbDevice`] builder.
|
||||||
|
///
|
||||||
|
/// This can be used to overwrite parts of the descriptor buffer or other granular controls over the buffer.
|
||||||
|
pub fn config_descriptor_writer(&mut self) -> &mut DescriptorWriter<'d> {
|
||||||
|
self.builder.config_descriptor_writer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interface alternate setting builder.
|
/// Interface alternate setting builder.
|
||||||
@ -435,50 +456,17 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
|
|||||||
///
|
///
|
||||||
/// Descriptors are written in the order builder functions are called. Note that some
|
/// Descriptors are written in the order builder functions are called. Note that some
|
||||||
/// classes care about the order.
|
/// classes care about the order.
|
||||||
pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) {
|
///
|
||||||
|
/// Returns the byte length of the descriptor which has been written.
|
||||||
|
pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) -> usize {
|
||||||
self.builder.config_descriptor.write(descriptor_type, descriptor)
|
self.builder.config_descriptor.write(descriptor_type, descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a custom descriptor to this alternate setting,
|
/// Returns a handle to the inner config descriptor writer owned by the [`UsbDevice`] builder.
|
||||||
/// assuming that the descriptor is the initial one which will be followed by variable number
|
|
||||||
/// of descriptors of the same type forming a compound descriptor set.
|
|
||||||
///
|
///
|
||||||
/// Descriptors are written in the order builder functions are called. Note that some
|
/// This can be used to overwrite parts of the descriptor buffer or other granular controls over the buffer.
|
||||||
/// classes care about the order.
|
pub fn config_descriptor_writer(&mut self) -> &mut DescriptorWriter<'d> {
|
||||||
///
|
self.builder.config_descriptor_writer()
|
||||||
/// # Details
|
|
||||||
///
|
|
||||||
/// In the USB specification, when it comes to class-specific descriptors, the presence of a "total length" field is not universally common across all classes.
|
|
||||||
/// However, it is found in several class specifications, particularly in those where a variable number of descriptors or a variable configuration might follow.
|
|
||||||
///
|
|
||||||
/// For instance:
|
|
||||||
///
|
|
||||||
/// - **Audio Class:** The class-specific header descriptor in the Audio class contains a "Total Length" field, which indicates the entire length of the class-specific AudioControl interface descriptor. This is useful because the AudioControl interface can have a variable configuration depending on the number and type of audio channels, terminal interfaces, etc.
|
|
||||||
///
|
|
||||||
/// - **Video Class:** The Video class's class-specific header descriptor also contains a "Total Length" field.
|
|
||||||
///
|
|
||||||
/// The purpose behind the "Total Length" (or equivalent) field in these class-specific descriptors is to provide a straightforward way to determine the full length of a compound descriptor set.
|
|
||||||
/// This can be especially helpful for parsing or skipping over the entirety of the descriptor set if needed.
|
|
||||||
///
|
|
||||||
/// While it's common in certain classes like Audio and Video,
|
|
||||||
/// it's not a universal feature of all USB class-specific descriptors.
|
|
||||||
pub fn start_writing_compound_set_tracking_total_length(&mut self, descriptor_type: u8, descriptor: &[u8]) {
|
|
||||||
let descriptor_writer = &mut self.builder.config_descriptor;
|
|
||||||
// Start tracking the total length of the compound descriptor set.
|
|
||||||
descriptor_writer.start_tracking_total_length_of_compound_descriptor_set(descriptor_writer.position());
|
|
||||||
// Write the initial descriptor of that particular set.
|
|
||||||
self.builder.config_descriptor.write(descriptor_type, descriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// End writing a compound descriptor set updating the total length area in the initial descriptor.
|
|
||||||
///
|
|
||||||
/// The offset of the total length bytes should be provided.
|
|
||||||
/// This number may change depending on the class, please derive it from the specification.
|
|
||||||
pub fn end_writing_compound_set_updating_total_length(&mut self, offset: usize) {
|
|
||||||
// End tracking the total length of the compound descriptor set and write it to the initial descriptor of that set on provided offset.
|
|
||||||
self.builder
|
|
||||||
.config_descriptor
|
|
||||||
.end_tracking_total_length_of_compound_descriptor_set_and_update_the_initial_descriptor(offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn endpoint_in(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn {
|
fn endpoint_in(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn {
|
||||||
|
@ -182,7 +182,6 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
|
|||||||
// Control interface
|
// Control interface
|
||||||
let mut iface = func.interface();
|
let mut iface = func.interface();
|
||||||
let comm_if = iface.interface_number();
|
let comm_if = iface.interface_number();
|
||||||
let data_if = u8::from(comm_if) + 1;
|
|
||||||
let mut alt = iface.alt_setting(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE, None);
|
let mut alt = iface.alt_setting(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE, None);
|
||||||
|
|
||||||
alt.descriptor(
|
alt.descriptor(
|
||||||
@ -208,19 +207,29 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
|
|||||||
&[
|
&[
|
||||||
CDC_TYPE_UNION, // bDescriptorSubtype
|
CDC_TYPE_UNION, // bDescriptorSubtype
|
||||||
comm_if.into(), // bControlInterface
|
comm_if.into(), // bControlInterface
|
||||||
data_if.into(), // bSubordinateInterface
|
// Padding, bSubordinateInterface byte will be written later.
|
||||||
|
0x0, // bSubordinateInterface
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Keep the position of the subordinate interface byte so we can fill it in later
|
||||||
|
let subordinate_interface_position = alt.config_descriptor_writer().position() - 1;
|
||||||
|
|
||||||
let comm_ep = alt.endpoint_interrupt_in(8, 255);
|
let comm_ep = alt.endpoint_interrupt_in(8, 255);
|
||||||
|
|
||||||
// Data interface
|
// Data interface
|
||||||
let mut iface = func.interface();
|
let mut iface = func.interface();
|
||||||
let data_if = iface.interface_number();
|
let data_if = iface.interface_number();
|
||||||
|
let data_if_number_byte = data_if.0;
|
||||||
|
|
||||||
let mut alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NONE, None);
|
let mut alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NONE, None);
|
||||||
let read_ep = alt.endpoint_bulk_out(max_packet_size);
|
let read_ep = alt.endpoint_bulk_out(max_packet_size);
|
||||||
let write_ep = alt.endpoint_bulk_in(max_packet_size);
|
let write_ep = alt.endpoint_bulk_in(max_packet_size);
|
||||||
|
|
||||||
|
// Fill in the subordinate interface byte with the right interface number.
|
||||||
|
alt.config_descriptor_writer()
|
||||||
|
.overwrite(subordinate_interface_position, &[data_if_number_byte]);
|
||||||
|
|
||||||
drop(func);
|
drop(func);
|
||||||
|
|
||||||
let control = state.control.write(Control {
|
let control = state.control.write(Control {
|
||||||
|
@ -37,7 +37,8 @@ pub mod capability_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A writer for USB descriptors.
|
/// A writer for USB descriptors.
|
||||||
pub(crate) struct DescriptorWriter<'a> {
|
pub struct DescriptorWriter<'a> {
|
||||||
|
/// The inner buffer of the descriptor writer.
|
||||||
pub buf: &'a mut [u8],
|
pub buf: &'a mut [u8],
|
||||||
position: usize,
|
position: usize,
|
||||||
num_interfaces_mark: Option<usize>,
|
num_interfaces_mark: Option<usize>,
|
||||||
|
Loading…
Reference in New Issue
Block a user