Skip to content

Commit 6340d5c

Browse files
committed
macos: clean up IOCreatePlugInInterfaceForService retry loop
1 parent d07caaf commit 6340d5c

File tree

1 file changed

+38
-40
lines changed

1 file changed

+38
-40
lines changed

src/platform/macos_iokit/iokit_usb.rs

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use io_kit_sys::{
1111
ret::{kIOReturnNoResources, kIOReturnSuccess, IOReturn},
1212
types::io_iterator_t,
1313
};
14-
use log::error;
14+
use log::{debug, error};
1515

1616
use crate::{
1717
platform::macos_iokit::{
@@ -57,11 +57,12 @@ impl IoKitDevice {
5757
// macOS is preventing us from touching the relevant device due to its security
5858
// model. This happens when the device has a kernel-mode driver bound to the
5959
// whole device -- the kernel owns it, and it's unwilling to give it to us.
60+
let mut rc: IOReturn = 0;
61+
let mut raw_device_plugin: *mut *mut IOCFPlugInInterface = std::ptr::null_mut();
6062
for _ in 0..5 {
6163
let mut _score: i32 = 0;
62-
let mut raw_device_plugin: *mut *mut IOCFPlugInInterface = std::ptr::null_mut();
6364

64-
let rc = IOCreatePlugInInterfaceForService(
65+
rc = IOCreatePlugInInterfaceForService(
6566
service.get(),
6667
kIOUsbDeviceUserClientTypeID(),
6768
kIOCFPlugInInterfaceID(),
@@ -70,49 +71,48 @@ impl IoKitDevice {
7071
);
7172

7273
if rc == kIOReturnNoResources {
74+
debug!("IOCreatePlugInInterfaceForService failed with `kIOReturnNoResources`, retrying");
7375
std::thread::sleep(Duration::from_millis(1));
7476
continue;
77+
} else {
78+
break;
7579
}
80+
}
7681

77-
if rc != kIOReturnSuccess {
78-
return Err(Error::new_os(ErrorKind::Other, "failed to open device", rc));
79-
}
82+
if rc != kIOReturnSuccess {
83+
return Err(
84+
Error::new_os(ErrorKind::Other, "failed to create IOKit PlugInInterface for device", rc).log_error()
85+
);
86+
}
8087

81-
if raw_device_plugin.is_null() {
82-
error!("IOKit indicated it successfully created a PlugInInterface, but the pointer was NULL");
83-
return Err(Error::new(
84-
ErrorKind::Other,
85-
"could not create PlugInInterface",
86-
));
87-
}
88+
if raw_device_plugin.is_null() {
89+
error!("IOKit indicated it successfully created a PlugInInterface, but the pointer was NULL");
90+
return Err(Error::new(
91+
ErrorKind::Other,
92+
"could not create PlugInInterface",
93+
));
94+
}
8895

89-
let device_plugin = PluginInterface::new(raw_device_plugin);
96+
let device_plugin = PluginInterface::new(raw_device_plugin);
97+
let mut raw_device: *mut *mut iokit::UsbDevice = std::ptr::null_mut();
9098

91-
let mut raw_device: *mut *mut iokit::UsbDevice = std::ptr::null_mut();
99+
call_iokit_function!(
100+
device_plugin.get(),
101+
QueryInterface(
102+
usb_device_type_id(),
103+
&mut raw_device as *mut *mut *mut _ as *mut *mut c_void
104+
)
105+
);
92106

93-
call_iokit_function!(
94-
device_plugin.get(),
95-
QueryInterface(
96-
usb_device_type_id(),
97-
&mut raw_device as *mut *mut *mut _ as *mut *mut c_void
98-
)
107+
// macOS claims that call will never fail, and will always produce a valid pointer.
108+
// We don't trust it, so we're going to panic if it's lied to us.
109+
if raw_device.is_null() {
110+
panic!(
111+
"query_interface returned a null pointer, which Apple says is impossible"
99112
);
100-
101-
// macOS claims that call will never fail, and will always produce a valid pointer.
102-
// We don't trust it, so we're going to panic if it's lied to us.
103-
if raw_device.is_null() {
104-
panic!(
105-
"query_interface returned a null pointer, which Apple says is impossible"
106-
);
107-
}
108-
109-
return Ok(IoKitDevice { raw: raw_device });
110113
}
111114

112-
Err(Error::new(
113-
ErrorKind::NotFound,
114-
"Couldn't create device after retries",
115-
))
115+
Ok(IoKitDevice { raw: raw_device })
116116
}
117117
}
118118

@@ -228,11 +228,9 @@ impl IoKitInterface {
228228
);
229229

230230
if rc != kIOReturnSuccess {
231-
return Err(Error::new_os(
232-
ErrorKind::Other,
233-
"failed to open interface",
234-
rc,
235-
));
231+
return Err(
232+
Error::new_os(ErrorKind::Other, "failed to open interface", rc).log_error(),
233+
);
236234
}
237235

238236
if raw_interface_plugin.is_null() {

0 commit comments

Comments
 (0)