Merge pull request #154 from kevinmehall/windows-interface-info

windows: Always use interface descriptors rather than child device nodes for InterfaceInfo
This commit is contained in:
Kevin Mehall 2025-07-16 23:36:29 -06:00 committed by GitHub
commit c1492ae441
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 22 additions and 49 deletions

View file

@ -26,7 +26,7 @@ rustix = { version = "1.0.1", features = ["fs", "event", "net", "time", "mm"] }
linux-raw-sys = { version = "0.9.2", features = ["ioctl"] }
[target.'cfg(target_os="windows")'.dependencies]
windows-sys = { version = "0.59.0", features = ["Win32_Devices_Usb", "Win32_Devices_DeviceAndDriverInstallation", "Win32_Foundation", "Win32_Devices_Properties", "Win32_Storage_FileSystem", "Win32_Security", "Win32_System_IO", "Win32_System_Registry", "Win32_System_Com"] }
windows-sys = { version = "0.60.2", features = ["Win32_Devices_Usb", "Win32_Devices_DeviceAndDriverInstallation", "Win32_Foundation", "Win32_Devices_Properties", "Win32_Storage_FileSystem", "Win32_Security", "Win32_System_IO", "Win32_System_Registry", "Win32_System_Com"] }
[target.'cfg(target_os="macos")'.dependencies]
core-foundation = "0.10.1"

View file

@ -13,11 +13,11 @@ use windows_sys::{
CM_LOCATE_DEVNODE_PHANTOM, CM_REGISTRY_HARDWARE, CR_BUFFER_SMALL, CR_SUCCESS,
},
Properties::{
DEVPKEY_Device_InstanceId, DEVPROPKEY, DEVPROPTYPE, DEVPROP_TYPE_STRING,
DEVPKEY_Device_InstanceId, DEVPROPTYPE, DEVPROP_TYPE_STRING,
DEVPROP_TYPE_STRING_LIST, DEVPROP_TYPE_UINT32,
},
},
Foundation::INVALID_HANDLE_VALUE,
Foundation::{DEVPROPKEY, INVALID_HANDLE_VALUE},
System::Registry::KEY_READ,
},
};

View file

@ -89,33 +89,28 @@ pub fn probe_device(devinst: DevInst) -> Option<DeviceInfo> {
let driver = get_driver_name(devinst);
let mut interfaces = if driver.eq_ignore_ascii_case("usbccgp") {
let mut interfaces =
list_interfaces_from_desc(&hub_port, info.active_config).unwrap_or_default();
if driver.eq_ignore_ascii_case("usbccgp") {
// Populate interface descriptor strings when available from child device nodes.
devinst
.children()
.flat_map(|intf| {
let interface_number = get_interface_number(intf)?;
let (class, subclass, protocol) = intf
.get_property::<Vec<OsString>>(DEVPKEY_Device_CompatibleIds)?
.iter()
.find_map(|s| parse_compatible_id(s))?;
let interface_string = intf
.get_property::<OsString>(DEVPKEY_Device_BusReportedDeviceDesc)
.and_then(|s| s.into_string().ok());
Some(InterfaceInfo {
interface_number,
class,
subclass,
protocol,
interface_string,
})
let interface_string =
intf.get_property::<OsString>(DEVPKEY_Device_BusReportedDeviceDesc)?;
Some((interface_number, interface_string))
})
.collect()
} else {
list_interfaces_from_desc(&hub_port, info.active_config).unwrap_or_default()
};
interfaces.sort_unstable_by_key(|i| i.interface_number);
.for_each(|(intf_num, interface_string)| {
if let Some(interface_info) = interfaces
.iter_mut()
.find(|i| i.interface_number == intf_num)
{
interface_info.interface_string = interface_string.into_string().ok();
}
});
}
let location_paths = devinst
.get_property::<Vec<OsString>>(DEVPKEY_Device_LocationPaths)
@ -342,28 +337,6 @@ fn test_parse_hardware_id() {
);
}
/// Parse class, subclass, protocol from a Compatible ID value
fn parse_compatible_id(s: &OsStr) -> Option<(u8, u8, u8)> {
let s = s.to_str()?;
let s = s.strip_prefix("USB\\Class_")?;
let class = u8::from_str_radix(s.get(0..2)?, 16).ok()?;
let s = s.get(2..)?.strip_prefix("&SubClass_")?;
let subclass = u8::from_str_radix(s.get(0..2)?, 16).ok()?;
let s = s.get(2..)?.strip_prefix("&Prot_")?;
let protocol = u8::from_str_radix(s.get(0..2)?, 16).ok()?;
Some((class, subclass, protocol))
}
#[test]
fn test_parse_compatible_id() {
assert_eq!(parse_compatible_id(OsStr::new("")), None);
assert_eq!(parse_compatible_id(OsStr::new("USB\\Class_03")), None);
assert_eq!(
parse_compatible_id(OsStr::new("USB\\Class_03&SubClass_11&Prot_22")),
Some((3, 17, 34))
);
}
fn parse_location_path(s: &OsStr) -> Option<(String, Vec<u8>)> {
let s = s.to_str()?;

View file

@ -13,7 +13,7 @@ use windows_sys::Win32::{
DeviceAndDriverInstallation::{
CM_Register_Notification, CM_Unregister_Notification, CM_NOTIFY_ACTION,
CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL, CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL,
CM_NOTIFY_EVENT_DATA, CM_NOTIFY_FILTER, CM_NOTIFY_FILTER_0, CM_NOTIFY_FILTER_0_2,
CM_NOTIFY_EVENT_DATA, CM_NOTIFY_FILTER, CM_NOTIFY_FILTER_0, CM_NOTIFY_FILTER_0_0,
CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, CR_SUCCESS, HCMNOTIFICATION,
},
Properties::DEVPKEY_Device_InstanceId,
@ -62,7 +62,7 @@ impl WindowsHotplugWatch {
FilterType: CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE,
Reserved: 0,
u: CM_NOTIFY_FILTER_0 {
DeviceInterface: CM_NOTIFY_FILTER_0_2 {
DeviceInterface: CM_NOTIFY_FILTER_0_0 {
ClassGuid: GUID_DEVINTERFACE_USB_DEVICE,
},
},