Skip to content

Commit

Permalink
Merge branch 'main' into endpoint_fix
Browse files Browse the repository at this point in the history
  • Loading branch information
martinling committed Sep 18, 2024
2 parents a682a05 + 130498b commit 8ad8b94
Show file tree
Hide file tree
Showing 8 changed files with 630 additions and 91 deletions.
42 changes: 26 additions & 16 deletions src/capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,12 @@ pub enum DeviceItem {
ConfigurationDescriptor(DeviceId, ConfigNum),
ConfigurationDescriptorField(DeviceId, ConfigNum,
ConfigField, DeviceVersion),
Interface(DeviceId, ConfigNum, InterfaceNum),
InterfaceDescriptor(DeviceId, ConfigNum, InterfaceNum),
InterfaceDescriptorField(DeviceId, ConfigNum,
InterfaceNum, InterfaceField, DeviceVersion),
EndpointDescriptor(DeviceId, ConfigNum, InterfaceNum, InterfaceEpNum),
EndpointDescriptorField(DeviceId, ConfigNum, InterfaceNum,
Interface(DeviceId, ConfigNum, ConfigIfaceNum),
InterfaceDescriptor(DeviceId, ConfigNum, ConfigIfaceNum),
InterfaceDescriptorField(DeviceId, ConfigNum, ConfigIfaceNum,
InterfaceField, DeviceVersion),
EndpointDescriptor(DeviceId, ConfigNum, ConfigIfaceNum, InterfaceEpNum),
EndpointDescriptorField(DeviceId, ConfigNum, ConfigIfaceNum,
InterfaceEpNum, EndpointField, DeviceVersion),
}

Expand Down Expand Up @@ -385,7 +385,7 @@ impl DeviceData {
if let Some(number) = self.config_number.load().as_ref() {
if let Some(config) = &self.configurations.load().get(**number) {
self.endpoint_details.update(|endpoint_details| {
for iface in &config.interfaces {
for iface in config.interfaces.values() {
for ep_desc in &iface.endpoint_descriptors {
let ep_addr = ep_desc.endpoint_address;
let ep_type = ep_desc.attributes.endpoint_type();
Expand Down Expand Up @@ -497,12 +497,13 @@ impl DeviceData {
}

impl Configuration {
pub fn interface(&self, number: &InterfaceNum)
pub fn interface(&self, number: &ConfigIfaceNum)
-> Result<&Interface, Error>
{
match self.interfaces.get(*number) {
let index = number.0 as usize;
match self.interfaces.values().nth(index) {
Some(iface) => Ok(iface),
_ => bail!("Configuration has no interface {number}")
_ => bail!("Configuration has no interface with index {index}")
}
}
}
Expand Down Expand Up @@ -1641,7 +1642,7 @@ impl ItemSource<DeviceItem> for CaptureReader {
Configuration(dev, conf) => match index {
0 => ConfigurationDescriptor(*dev, *conf),
n => Interface(*dev, *conf,
InterfaceNum((n - 1).try_into()?)),
ConfigIfaceNum((n - 1).try_into()?)),
},
ConfigurationDescriptor(dev, conf) =>
ConfigurationDescriptorField(*dev, *conf,
Expand Down Expand Up @@ -1696,9 +1697,8 @@ impl ItemSource<DeviceItem> for CaptureReader {
},
Some(Interface(dev, conf, iface)) =>
match self.try_configuration(dev, conf) {
Some(conf) =>
(Ongoing,
1 + conf.interface(iface)?.endpoint_descriptors.len()),
Some(conf) => (Ongoing,
1 + conf.interface(iface)?.endpoint_descriptors.len()),
None => (Ongoing, 0)
},
Some(InterfaceDescriptor(..)) =>
Expand Down Expand Up @@ -1747,8 +1747,18 @@ impl ItemSource<DeviceItem> for CaptureReader {
let strings = data.strings.load();
config_descriptor.field_text(*field, strings.as_ref())
},
Interface(_, _, iface) => format!(
"Interface {iface}"),
Interface(dev, conf, iface) => {
let data = self.device_data(dev)?;
let config = data.configuration(conf)?;
let iface_desc = config.interface(iface)?.descriptor;
let num = iface_desc.interface_number;
match iface_desc.alternate_setting {
InterfaceAlt(0) => format!(
"Interface {num}"),
InterfaceAlt(alt) => format!(
"Interface {num} (alternate {alt})"),
}
},
InterfaceDescriptor(..) =>
"Interface descriptor".to_string(),
InterfaceDescriptorField(dev, conf, iface, field, _ver) => {
Expand Down
117 changes: 42 additions & 75 deletions src/usb.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::BTreeMap;
use std::mem::size_of;

use bytemuck_derive::{Pod, Zeroable};
Expand Down Expand Up @@ -120,60 +121,30 @@ pub fn validate_packet(packet: &[u8]) -> Result<PID, Option<PID>> {
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct DeviceAddr(pub u8);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct DeviceField(pub u8);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct StringId(pub u8);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct ConfigNum(pub u8);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct ConfigField(pub u8);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct InterfaceNum(pub u8);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct InterfaceField(pub u8);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct InterfaceEpNum(pub u8);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct EndpointNum(pub u8);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct EndpointField(pub u8);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct EndpointAddr(pub u8);
macro_rules! byte_type {
($name: ident) => {
#[derive(Copy, Clone, Debug, Default,
PartialEq, Eq, PartialOrd, Ord,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct $name(pub u8);
}
}

byte_type!(DeviceAddr);
byte_type!(DeviceField);
byte_type!(StringId);
byte_type!(ConfigNum);
byte_type!(ConfigField);
byte_type!(ConfigIfaceNum);
byte_type!(InterfaceNum);
byte_type!(InterfaceAlt);
byte_type!(InterfaceField);
byte_type!(InterfaceEpNum);
byte_type!(EndpointNum);
byte_type!(EndpointField);
byte_type!(EndpointAddr);
byte_type!(EndpointAttr);

impl EndpointAddr {
pub fn number(&self) -> EndpointNum {
Expand All @@ -193,11 +164,6 @@ impl EndpointAddr {
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default,
Pod, Zeroable, From, Into, Display)]
#[repr(transparent)]
pub struct EndpointAttr(pub u8);

impl EndpointAttr {
pub fn endpoint_type(&self) -> EndpointType {
EndpointType::from(self.0 & 0x03)
Expand Down Expand Up @@ -667,7 +633,7 @@ pub struct InterfaceDescriptor {
pub length: u8,
pub descriptor_type: u8,
pub interface_number: InterfaceNum,
pub alternate_setting: u8,
pub alternate_setting: InterfaceAlt,
pub num_endpoints: u8,
pub interface_class: u8,
pub interface_subclass: u8,
Expand Down Expand Up @@ -805,28 +771,29 @@ pub struct Interface {

pub struct Configuration {
pub descriptor: ConfigDescriptor,
pub interfaces: VecMap<InterfaceNum, Interface>,
pub interfaces: BTreeMap<(InterfaceNum, InterfaceAlt), Interface>,
}

impl Configuration {
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
let mut result: Option<Configuration> = None;
let mut iface_num: Option<InterfaceNum> = None;
let mut iface_key: Option<(InterfaceNum, InterfaceAlt)> = None;
for descriptor in DescriptorIterator::from(bytes) {
match descriptor {
Descriptor::Configuration(config_desc) => {
result = Some(Configuration {
descriptor: config_desc,
interfaces:
VecMap::with_capacity(
config_desc.num_interfaces),
interfaces: BTreeMap::new(),
});
},
Descriptor::Interface(iface_desc) => {
if let Some(config) = result.as_mut() {
iface_num = Some(iface_desc.interface_number);
config.interfaces.set(
iface_desc.interface_number,
let iface_num = iface_desc.interface_number;
let iface_alt = iface_desc.alternate_setting;
let key = (iface_num, iface_alt);
iface_key = Some(key);
config.interfaces.insert(
key,
Interface {
descriptor: iface_desc,
endpoint_descriptors:
Expand All @@ -837,13 +804,11 @@ impl Configuration {
}
},
Descriptor::Endpoint(ep_desc) => {
if let Some(config) = result.as_mut() {
if let Some(num) = iface_num {
if let Some(iface) =
config.interfaces.get_mut(num)
{
iface.endpoint_descriptors.push(ep_desc);
}
if let (Some(config), Some(key)) =
(result.as_mut(), iface_key)
{
if let Some(iface) = config.interfaces.get_mut(&key) {
iface.endpoint_descriptors.push(ep_desc);
}
}
},
Expand Down Expand Up @@ -1076,8 +1041,10 @@ pub mod prelude {
DeviceField,
StringId,
ConfigNum,
ConfigIfaceNum,
ConfigField,
InterfaceNum,
InterfaceAlt,
InterfaceField,
InterfaceEpNum,
EndpointNum,
Expand Down
Binary file added tests/ksolti-core-enum/capture.pcap
Binary file not shown.
Loading

0 comments on commit 8ad8b94

Please sign in to comment.