Merge pull request #148 from kevinmehall/macos-update

macOS: Update core-foundation, switch to IOUSBInterfaceInterface700 and IOUSBDeviceInterface650
This commit is contained in:
Kevin Mehall 2025-06-15 14:35:17 -06:00 committed by GitHub
commit 915f79005d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 210 additions and 63 deletions

View file

@ -28,7 +28,7 @@ linux-raw-sys = { version = "0.9.2", features = ["ioctl"] }
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.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"] }
[target.'cfg(target_os="macos")'.dependencies] [target.'cfg(target_os="macos")'.dependencies]
core-foundation = "0.9.3" core-foundation = "0.10.1"
core-foundation-sys = "0.8.4" core-foundation-sys = "0.8.4"
io-kit-sys = "0.4.0" io-kit-sys = "0.4.0"

View file

@ -1,5 +1,4 @@
use std::{ use std::{
ops::Deref,
sync::{mpsc, Mutex}, sync::{mpsc, Mutex},
thread, thread,
}; };
@ -8,23 +7,13 @@ use core_foundation::runloop::{CFRunLoop, CFRunLoopSource};
use core_foundation_sys::runloop::kCFRunLoopCommonModes; use core_foundation_sys::runloop::kCFRunLoopCommonModes;
use log::info; use log::info;
// Pending release of https://github.com/servo/core-foundation-rs/pull/610 // Pending https://github.com/servo/core-foundation-rs/pull/649
struct SendCFRunLoop(CFRunLoop);
unsafe impl Send for SendCFRunLoop {}
impl Deref for SendCFRunLoop {
type Target = CFRunLoop;
fn deref(&self) -> &Self::Target {
&self.0
}
}
struct SendCFRunLoopSource(CFRunLoopSource); struct SendCFRunLoopSource(CFRunLoopSource);
unsafe impl Send for SendCFRunLoopSource {} unsafe impl Send for SendCFRunLoopSource {}
unsafe impl Sync for SendCFRunLoopSource {} unsafe impl Sync for SendCFRunLoopSource {}
struct EventLoop { struct EventLoop {
runloop: Option<SendCFRunLoop>, runloop: Option<CFRunLoop>,
count: usize, count: usize,
} }
@ -49,7 +38,7 @@ pub(crate) fn add_event_source(source: CFRunLoopSource) -> EventRegistration {
let runloop = CFRunLoop::get_current(); let runloop = CFRunLoop::get_current();
let source = source; let source = source;
runloop.add_source(&source.0, unsafe { kCFRunLoopCommonModes }); runloop.add_source(&source.0, unsafe { kCFRunLoopCommonModes });
tx.send(SendCFRunLoop(runloop)).unwrap(); tx.send(runloop).unwrap();
CFRunLoop::run_current(); CFRunLoop::run_current();
info!("event loop thread exited"); info!("event loop thread exited");
}); });

View file

@ -99,19 +99,17 @@ impl Drop for PluginInterface {
} }
} }
/// Alias that select the "version 500" (IOKit 5.0.0) version of UsbDevice, which means /// Alias to select the "version 650" version of UsbDevice, and and "version 700" of UsbInterface.
/// that we support macOS versions back to 10.7.3, which is currently every version that Rust /// These are supported on macOS versions back to 10.10, which is older than Rust's minimum supported version of 10.12.
/// supports. Use this instead of touching the iokit_c structure; this may be bumped to pub(crate) type UsbDevice = iokit_c::IOUSBDeviceStruct650;
/// (compatible) newer versions of the struct as Rust's support changes. pub(crate) type UsbInterface = iokit_c::IOUSBInterfaceStruct700;
pub(crate) type UsbDevice = iokit_c::IOUSBDeviceStruct500;
pub(crate) type UsbInterface = iokit_c::IOUSBInterfaceStruct500;
pub(crate) fn usb_device_type_id() -> CFUUIDBytes { pub(crate) fn usb_device_type_id() -> CFUUIDBytes {
unsafe { CFUUIDGetUUIDBytes(iokit_c::kIOUSBDeviceInterfaceID500()) } unsafe { CFUUIDGetUUIDBytes(iokit_c::kIOUSBDeviceInterfaceID650()) }
} }
pub(crate) fn usb_interface_type_id() -> CFUUIDBytes { pub(crate) fn usb_interface_type_id() -> CFUUIDBytes {
unsafe { CFUUIDGetUUIDBytes(iokit_c::kIOUSBInterfaceInterfaceID500()) } unsafe { CFUUIDGetUUIDBytes(iokit_c::kIOUSBInterfaceInterfaceID700()) }
} }
pub(crate) fn check_iokit_return(r: IOReturn) -> Result<(), IOReturn> { pub(crate) fn check_iokit_return(r: IOReturn) -> Result<(), IOReturn> {

View file

@ -22,7 +22,7 @@ use core_foundation_sys::{
use io_kit_sys::{ use io_kit_sys::{
ret::IOReturn, ret::IOReturn,
types::{io_iterator_t, io_service_t, IOByteCount}, types::{io_iterator_t, io_service_t, IOByteCount},
IOAsyncCallback1, IOAsyncCallback1, IOAsyncCallback2,
}; };
// //
@ -77,6 +77,24 @@ pub(crate) type USBDeviceAddress = UInt16;
pub(crate) type AbsoluteTime = UnsignedWide; pub(crate) type AbsoluteTime = UnsignedWide;
pub(crate) type Boolean = std::os::raw::c_uchar; pub(crate) type Boolean = std::os::raw::c_uchar;
#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
pub struct IOUSBEndpointProperties {
pub bVersion: UInt8,
pub bAlternateSetting: UInt8,
pub bDirection: UInt8,
pub bEndpointNumber: UInt8,
pub bTransferType: UInt8,
pub bUsageType: UInt8,
pub bSyncType: UInt8,
pub bInterval: UInt8,
pub wMaxPacketSize: UInt16,
pub bMaxBurst: UInt8,
pub bMaxStreams: UInt8,
pub bMult: UInt8,
pub wBytesPerInterval: UInt16,
}
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct NumVersion { pub struct NumVersion {
@ -297,50 +315,50 @@ pub fn kIOCFPlugInInterfaceID() -> CFUUIDRef {
} }
} }
pub fn kIOUSBDeviceInterfaceID500() -> CFUUIDRef { pub fn kIOUSBDeviceInterfaceID650() -> CFUUIDRef {
unsafe { unsafe {
CFUUIDGetConstantUUIDWithBytes( CFUUIDGetConstantUUIDWithBytes(
kCFAllocatorSystemDefault, kCFAllocatorSystemDefault,
0xA3, 0x4A,
0x3C, 0xAC,
0xF0, 0x1B,
0x2E,
0x24,
0xC2,
0x47, 0x47,
0x4B, 0x6A,
0x5B, 0x96,
0x48, 0x4D,
0xE2, 0x91,
0xB5, 0x33,
0x7D, 0x35,
0x02, 0x34,
0x07, 0xF2,
0xFC, 0xCC,
0xEA,
0xE1,
0x3B,
) )
} }
} }
pub fn kIOUSBInterfaceInterfaceID500() -> CFUUIDRef { pub fn kIOUSBInterfaceInterfaceID700() -> CFUUIDRef {
unsafe { unsafe {
CFUUIDGetConstantUUIDWithBytes( CFUUIDGetConstantUUIDWithBytes(
kCFAllocatorSystemDefault, kCFAllocatorSystemDefault,
0x6C, 0x17,
0x0D, 0xF9,
0x38, 0xE5,
0xC3, 0x9C,
0xB0, 0xB0,
0x93, 0xA1,
0x4E, 0x40,
0xA7, 0x1D,
0x80, 0x9A,
0x9B, 0xC0,
0x09, 0x8D,
0xFB, 0xE2,
0x5D, 0x7A,
0xDD, 0xC6,
0xAC, 0x04,
0x16, 0x7E,
) )
} }
} }
@ -361,7 +379,7 @@ pub type IOUSBConfigurationDescriptorPtr = *mut IOUSBConfigurationDescriptor;
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct IOUSBDeviceStruct500 { pub struct IOUSBDeviceStruct650 {
pub _reserved: *mut ::std::os::raw::c_void, pub _reserved: *mut ::std::os::raw::c_void,
pub QueryInterface: ::std::option::Option< pub QueryInterface: ::std::option::Option<
unsafe extern "C" fn( unsafe extern "C" fn(
@ -583,19 +601,48 @@ pub struct IOUSBDeviceStruct500 {
bandwidth: *mut UInt32, bandwidth: *mut UInt32,
) -> IOReturn, ) -> IOReturn,
>, >,
pub SetConfigurationV2: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
configNum: UInt8,
startInterfaceMatching: bool,
issueRemoteWakeup: bool,
) -> IOReturn,
>,
pub RegisterForNotification: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
notificationMask: UInt64,
callback: IOAsyncCallback2,
refCon: *mut ::std::os::raw::c_void,
pRegistrationToken: *mut UInt64,
) -> IOReturn,
>,
pub UnregisterNotification: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
registrationToken: UInt64,
) -> IOReturn,
>,
pub AcknowledgeNotification: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
notificationToken: UInt64,
) -> IOReturn,
>,
} }
pub type IOUSBDeviceInterface500 = IOUSBDeviceStruct500; pub type IOUSBDeviceInterface650 = IOUSBDeviceStruct650;
// Tweak: these are just function pointers to thread-safe functions, // Tweak: these are just function pointers to thread-safe functions,
// so add send and sync to the C-type. (Calling these from multiple threads // so add send and sync to the C-type. (Calling these from multiple threads
// may cause odd behavior on the USB bus, though, so we'll still want to wrap the // may cause odd behavior on the USB bus, though, so we'll still want to wrap the
// device in Mutex somewhere up from here.) // device in Mutex somewhere up from here.)
unsafe impl Send for IOUSBDeviceInterface500 {} unsafe impl Send for IOUSBDeviceInterface650 {}
unsafe impl Sync for IOUSBDeviceInterface500 {} unsafe impl Sync for IOUSBDeviceInterface650 {}
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct IOUSBInterfaceStruct500 { pub struct IOUSBInterfaceStruct700 {
pub _reserved: *mut ::std::os::raw::c_void, pub _reserved: *mut ::std::os::raw::c_void,
pub QueryInterface: ::std::option::Option< pub QueryInterface: ::std::option::Option<
unsafe extern "C" fn( unsafe extern "C" fn(
@ -998,11 +1045,124 @@ pub struct IOUSBInterfaceStruct500 {
bytesPerInterval: *mut UInt16, bytesPerInterval: *mut UInt16,
) -> IOReturn, ) -> IOReturn,
>, >,
pub GetPipePropertiesV3: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
pipeRef: UInt8,
properties: *mut IOUSBEndpointProperties,
) -> IOReturn,
>,
pub GetEndpointPropertiesV3: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
properties: *mut IOUSBEndpointProperties,
) -> IOReturn,
>,
pub SupportsStreams: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
pipeRef: UInt8,
supportsStreams: *mut UInt32,
) -> IOReturn,
>,
pub CreateStreams: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
pipeRef: UInt8,
streamID: UInt32,
) -> IOReturn,
>,
pub GetConfiguredStreams: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
pipeRef: UInt8,
configuredStreams: *mut UInt32,
) -> IOReturn,
>,
pub ReadStreamsPipeTO: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
pipeRef: UInt8,
streamID: UInt32,
buf: *mut ::std::os::raw::c_void,
size: *mut UInt32,
noDataTimeout: UInt32,
completionTimeout: UInt32,
) -> IOReturn,
>,
pub WriteStreamsPipeTO: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
pipeRef: UInt8,
streamID: UInt32,
buf: *mut ::std::os::raw::c_void,
size: UInt32,
noDataTimeout: UInt32,
completionTimeout: UInt32,
) -> IOReturn,
>,
pub ReadStreamsPipeAsyncTO: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
pipeRef: UInt8,
streamID: UInt32,
buf: *mut ::std::os::raw::c_void,
size: UInt32,
noDataTimeout: UInt32,
completionTimeout: UInt32,
callback: IOAsyncCallback1,
refcon: *mut ::std::os::raw::c_void,
) -> IOReturn,
>,
pub WriteStreamsPipeAsyncTO: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
pipeRef: UInt8,
streamID: UInt32,
buf: *mut ::std::os::raw::c_void,
size: UInt32,
noDataTimeout: UInt32,
completionTimeout: UInt32,
callback: IOAsyncCallback1,
refcon: *mut ::std::os::raw::c_void,
) -> IOReturn,
>,
pub AbortStreamsPipe: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
pipeRef: UInt8,
streamID: UInt32,
) -> IOReturn,
>,
pub RegisterForNotification: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
notificationMask: UInt64,
callback: IOAsyncCallback2,
refCon: *mut ::std::os::raw::c_void,
pRegistrationToken: *mut UInt64,
) -> IOReturn,
>,
pub UnregisterNotification: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
registrationToken: UInt64,
) -> IOReturn,
>,
pub AcknowledgeNotification: ::std::option::Option<
unsafe extern "C" fn(
self_: *mut ::std::os::raw::c_void,
notificationToken: UInt64,
) -> IOReturn,
>,
pub RegisterDriver:
::std::option::Option<unsafe extern "C" fn(self_: *mut ::std::os::raw::c_void) -> IOReturn>,
} }
pub type IOUSBInterfaceInterface700 = IOUSBInterfaceStruct700;
// Tweak: these are just function pointers to thread-safe functions, // Tweak: these are just function pointers to thread-safe functions,
// so add send and sync to the C-type. (Calling these from multiple threads // so add send and sync to the C-type. (Calling these from multiple threads
// may cause odd behavior on the USB bus, though, so we'll still want to wrap the // may cause odd behavior on the USB bus, though, so we'll still want to wrap the
// device in Mutex somewhere up from here.) // device in Mutex somewhere up from here.)
unsafe impl Send for IOUSBInterfaceStruct500 {} unsafe impl Send for IOUSBInterfaceInterface700 {}
unsafe impl Sync for IOUSBInterfaceStruct500 {} unsafe impl Sync for IOUSBInterfaceInterface700 {}