fix(macos): claiming incorrect interface (#124)

* fix(macos): claiming interface on macOS treats interface number as index

Bug is exposed when connected device has not continuous interface numbers. Then getting nth interface is not the same as getting interface of specific number.

This commit fixes it by getting and comparing bInterfaceNumber instead of using `nth(interface_number)` function on iterator.

* refactor: reformatted find closure in claim_interface

Extracted `get_integer_property` usage into a local variable for clarity and improved readability. This refactor maintains existing functionality while simplifying the comparison logic.

* feat: Add debug logging for interface discovery in macOS IOKit

This change introduces a debug log to provide more visibility during the interface discovery process. It logs the target interface number and the current interface being examined, noting whether a match was found. This aids debugging and troubleshooting in device enumeration scenarios.

* refactor: Rephrase debug log for interface claim process.
This commit is contained in:
Paweł Gorgoń 2025-04-02 16:11:37 +02:00 committed by GitHub
parent 2801deedce
commit 873f96b8e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 12 additions and 3 deletions

View file

@ -19,7 +19,7 @@ use crate::{
};
use super::{
enumeration::{device_descriptor_from_fields, service_by_registry_id},
enumeration::{device_descriptor_from_fields, get_integer_property, service_by_registry_id},
events::{add_event_source, EventRegistration},
iokit::{call_iokit_function, check_iokit_return},
iokit_c::IOUSBDevRequestTO,
@ -241,7 +241,16 @@ impl MacDevice {
let intf_service = self
.device
.create_interface_iterator()?
.nth(interface_number as usize)
.find(|io_service| {
let current_number = get_integer_property(io_service, "bInterfaceNumber");
let found = current_number == Some(interface_number as i64);
debug!(
"Looking for interface to claim [n={interface_number}], examining interface [n={}]{}",
current_number.map(|n| n.to_string()).unwrap_or_else(|| "unknown".to_string()),
found.then(|| " (found)").unwrap_or("")
);
found
})
.ok_or(Error::new(ErrorKind::NotFound, "interface not found"))?;
let mut interface = IoKitInterface::new(intf_service)?;

View file

@ -219,7 +219,7 @@ fn get_string_property(device: &IoService, property: &'static str) -> Option<Str
get_property::<CFString>(device, property).map(|s| s.to_string())
}
fn get_integer_property(device: &IoService, property: &'static str) -> Option<i64> {
pub fn get_integer_property(device: &IoService, property: &'static str) -> Option<i64> {
let n = get_property::<CFNumber>(device, property)?;
n.to_i64().or_else(|| {
debug!("failed to convert {property} value {n:?} to i64");