diff --git a/examples/descriptors.rs b/examples/descriptors.rs index 3955170..b8f59b1 100644 --- a/examples/descriptors.rs +++ b/examples/descriptors.rs @@ -20,35 +20,19 @@ fn inspect_device(dev: DeviceInfo) { let dev = match dev.open() { Ok(dev) => dev, Err(e) => { - println!(" Failed to open device: {}", e); + println!("Failed to open device: {}", e); return; } }; match dev.active_configuration() { - Ok(config) => println!(" Active configuration is {}", config.configuration_value()), + Ok(config) => println!("Active configuration is {}", config.configuration_value()), Err(e) => println!("Unknown active configuration: {e}"), } for config in dev.configurations() { - println!(" Configuration {}", config.configuration_value()); - for intf in config.interfaces() { - for alt in intf.alt_settings() { - println!( - " Interface {}, alt setting {}", - alt.interface_number(), - alt.alternate_setting() - ); - for ep in alt.endpoints() { - println!( - " Endpoint {:02x} {:?} {:?}", - ep.address(), - ep.transfer_type(), - ep.direction() - ); - } - } - } + println!("{config:#?}"); } println!(""); + println!(""); } diff --git a/fuzz/fuzz_targets/descriptors.rs b/fuzz/fuzz_targets/descriptors.rs index da320c2..5b7a42e 100644 --- a/fuzz/fuzz_targets/descriptors.rs +++ b/fuzz/fuzz_targets/descriptors.rs @@ -5,12 +5,7 @@ use libfuzzer_sys::fuzz_target; fuzz_target!(|data: &[u8]| { for config in nusb::descriptors::fuzz_parse_concatenated_config_descriptors(data) { let config = nusb::descriptors::Configuration::new(config); - for interface in config.interfaces() { - for alt in interface.alt_settings() { - for endpoint in alt.endpoints() { - std::hint::black_box(endpoint); - } - } - } + let s = format!("{config:?}"); + std::hint::black_box(s); } }); diff --git a/src/descriptors.rs b/src/descriptors.rs index 282130d..4ae1a4f 100644 --- a/src/descriptors.rs +++ b/src/descriptors.rs @@ -2,7 +2,7 @@ //! //! Descriptors are blocks of data that describe the functionality of a USB device. -use std::{collections::BTreeMap, fmt::Display, io::ErrorKind, iter, ops::Deref}; +use std::{collections::BTreeMap, fmt::{Display, Debug}, io::ErrorKind, iter, ops::Deref}; use log::warn; @@ -285,6 +285,27 @@ impl<'a> Configuration<'a> { } } +struct DebugEntries(F); + +impl Debug for DebugEntries where F: Fn() -> I, I: Iterator, I::Item: Debug { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_list().entries(self.0()).finish() + } +} + +impl<'a> Debug for Configuration<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Configuration") + .field("configuration_value", &self.configuration_value()) + .field("num_interfaces", &self.num_interfaces()) + .field("attributes", &self.attributes()) + .field("max_power", &self.max_power()) + .field("string_index", &self.string_index()) + .field("interface_alt_settings", &DebugEntries(|| self.interface_alt_settings())) + .finish() + } +} + /// Interface descriptors for alternate settings, grouped by the interface number. #[derive(Clone)] pub struct InterfaceGroup<'a> { @@ -371,6 +392,21 @@ impl<'a> InterfaceAltSetting<'a> { } } +impl<'a> Debug for InterfaceAltSetting<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("InterfaceAltSetting") + .field("interface_number", &self.interface_number()) + .field("alternate_setting", &self.alternate_setting()) + .field("num_endpoints", &self.num_endpoints()) + .field("class", &self.class()) + .field("subclass", &self.subclass()) + .field("protocol", &self.protocol()) + .field("string_index", &self.string_index()) + .field("endpoints", &DebugEntries(|| self.endpoints())) + .finish() + } +} + /// Information about a USB endpoint, with access to any associated descriptors. pub struct Endpoint<'a>(&'a [u8]); @@ -435,6 +471,19 @@ descriptor_fields! { } } +impl<'a> Debug for Endpoint<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Endpoint") + .field("address", &format_args!("0x{:02X}", self.address())) + .field("direction", &self.direction()) + .field("transfer_type", &self.transfer_type()) + .field("max_packet_size", &self.max_packet_size()) + .field("packets_per_microframe", &self.packets_per_microframe()) + .field("interval", &self.interval()) + .finish() + } +} + /// Error from [`crate::Device::active_configuration`] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct ActiveConfigurationError {