// Take a look at the license at the top of the repository in the LICENSE file. use core_foundation_sys::base::{mach_port_t, CFAllocatorRef}; use core_foundation_sys::dictionary::{CFDictionaryRef, CFMutableDictionaryRef}; use core_foundation_sys::string::CFStringRef; use libc::{c_char, kern_return_t}; // Note: IOKit is only available on MacOS up until very recent iOS versions: https://developer.apple.com/documentation/iokit #[allow(non_camel_case_types)] pub type io_object_t = mach_port_t; #[allow(non_camel_case_types)] pub type io_iterator_t = io_object_t; #[allow(non_camel_case_types)] pub type io_registry_entry_t = io_object_t; #[allow(non_camel_case_types)] pub type io_name_t = *const c_char; pub type IOOptionBits = u32; #[allow(non_upper_case_globals)] pub const kIOServicePlane: &str = "IOService\0"; #[allow(non_upper_case_globals)] pub const kIOPropertyDeviceCharacteristicsKey: &str = "Device Characteristics"; #[allow(non_upper_case_globals)] pub const kIOPropertyMediumTypeKey: &str = "Medium Type"; #[allow(non_upper_case_globals)] pub const kIOPropertyMediumTypeSolidStateKey: &str = "Solid State"; #[allow(non_upper_case_globals)] pub const kIOPropertyMediumTypeRotationalKey: &str = "Rotational"; // Note: Obtaining information about disks using IOKIt is allowed inside the default macOS App Sandbox. #[link(name = "IOKit", kind = "framework")] extern "C" { pub fn IOServiceGetMatchingServices( mainPort: mach_port_t, matching: CFMutableDictionaryRef, existing: *mut io_iterator_t, ) -> kern_return_t; pub fn IOIteratorNext(iterator: io_iterator_t) -> io_object_t; pub fn IOObjectRelease(obj: io_object_t) -> kern_return_t; pub fn IORegistryEntryCreateCFProperty( entry: io_registry_entry_t, key: CFStringRef, allocator: CFAllocatorRef, options: IOOptionBits, ) -> CFDictionaryRef; pub fn IORegistryEntryGetParentEntry( entry: io_registry_entry_t, plane: io_name_t, parent: *mut io_registry_entry_t, ) -> kern_return_t; pub fn IOBSDNameMatching( mainPort: mach_port_t, options: u32, bsdName: *const c_char, ) -> CFMutableDictionaryRef; // This is deprecated as of macOS 12.0, but Rust doesn't have a good way to only use the replacement on 12+. pub static kIOMasterPortDefault: mach_port_t; } #[cfg(all( not(feature = "apple-sandbox"), any(target_arch = "x86", target_arch = "x86_64") ))] mod io_service { use super::{io_object_t, mach_port_t}; use core_foundation_sys::dictionary::CFMutableDictionaryRef; use libc::{c_char, kern_return_t, size_t, task_t}; #[allow(non_camel_case_types)] pub type io_connect_t = io_object_t; #[allow(non_camel_case_types)] pub type io_service_t = io_object_t; #[allow(non_camel_case_types)] pub type task_port_t = task_t; extern "C" { pub fn IOServiceMatching(a: *const c_char) -> CFMutableDictionaryRef; pub fn IOServiceOpen( device: io_service_t, owning_task: task_port_t, type_: u32, connect: *mut io_connect_t, ) -> kern_return_t; pub fn IOServiceClose(a: io_connect_t) -> kern_return_t; #[allow(dead_code)] pub fn IOConnectCallStructMethod( connection: mach_port_t, selector: u32, inputStruct: *const KeyData_t, inputStructCnt: size_t, outputStruct: *mut KeyData_t, outputStructCnt: *mut size_t, ) -> kern_return_t; } #[cfg_attr(feature = "debug", derive(Debug, Eq, Hash, PartialEq))] #[repr(C)] pub struct KeyData_vers_t { pub major: u8, pub minor: u8, pub build: u8, pub reserved: [u8; 1], pub release: u16, } #[cfg_attr(feature = "debug", derive(Debug, Eq, Hash, PartialEq))] #[repr(C)] pub struct KeyData_pLimitData_t { pub version: u16, pub length: u16, pub cpu_plimit: u32, pub gpu_plimit: u32, pub mem_plimit: u32, } #[cfg_attr(feature = "debug", derive(Debug, Eq, Hash, PartialEq))] #[repr(C)] pub struct KeyData_keyInfo_t { pub data_size: u32, pub data_type: u32, pub data_attributes: u8, } #[cfg_attr(feature = "debug", derive(Debug, Eq, Hash, PartialEq))] #[repr(C)] pub struct KeyData_t { pub key: u32, pub vers: KeyData_vers_t, pub p_limit_data: KeyData_pLimitData_t, pub key_info: KeyData_keyInfo_t, pub result: u8, pub status: u8, pub data8: u8, pub data32: u32, pub bytes: [i8; 32], // SMCBytes_t } #[allow(dead_code)] pub const KERNEL_INDEX_SMC: i32 = 2; #[allow(dead_code)] pub const SMC_CMD_READ_KEYINFO: u8 = 9; #[allow(dead_code)] pub const SMC_CMD_READ_BYTES: u8 = 5; pub const KIO_RETURN_SUCCESS: i32 = 0; } #[cfg(feature = "apple-sandbox")] mod io_service {} #[cfg(all( not(feature = "apple-sandbox"), any(target_arch = "x86", target_arch = "x86_64") ))] pub use io_service::*; #[cfg(all(not(feature = "apple-sandbox"), target_arch = "aarch64"))] mod io_service { use std::ptr::null; use core_foundation_sys::array::CFArrayRef; use core_foundation_sys::base::{CFAllocatorRef, CFRelease}; use core_foundation_sys::dictionary::{ kCFTypeDictionaryKeyCallBacks, kCFTypeDictionaryValueCallBacks, CFDictionaryCreate, CFDictionaryRef, }; use core_foundation_sys::number::{kCFNumberSInt32Type, CFNumberCreate}; use core_foundation_sys::string::{CFStringCreateWithCString, CFStringRef}; #[repr(C)] pub struct __IOHIDServiceClient(libc::c_void); pub type IOHIDServiceClientRef = *const __IOHIDServiceClient; #[repr(C)] pub struct __IOHIDEventSystemClient(libc::c_void); pub type IOHIDEventSystemClientRef = *const __IOHIDEventSystemClient; #[repr(C)] pub struct __IOHIDEvent(libc::c_void); pub type IOHIDEventRef = *const __IOHIDEvent; #[allow(non_upper_case_globals)] pub const kIOHIDEventTypeTemperature: i64 = 15; #[inline] #[allow(non_snake_case)] pub fn IOHIDEventFieldBase(event_type: i64) -> i64 { event_type << 16 } #[cfg(not(feature = "apple-sandbox"))] extern "C" { pub fn IOHIDEventSystemClientCreate(allocator: CFAllocatorRef) -> IOHIDEventSystemClientRef; pub fn IOHIDEventSystemClientSetMatching( client: IOHIDEventSystemClientRef, matches: CFDictionaryRef, ) -> i32; pub fn IOHIDEventSystemClientCopyServices(client: IOHIDEventSystemClientRef) -> CFArrayRef; pub fn IOHIDServiceClientCopyProperty( service: IOHIDServiceClientRef, key: CFStringRef, ) -> CFStringRef; pub fn IOHIDServiceClientCopyEvent( service: IOHIDServiceClientRef, v0: i64, v1: i32, v2: i64, ) -> IOHIDEventRef; pub fn IOHIDEventGetFloatValue(event: IOHIDEventRef, field: i64) -> f64; } pub(crate) const HID_DEVICE_PROPERTY_PRODUCT: &[u8] = b"Product\0"; pub(crate) const HID_DEVICE_PROPERTY_PRIMARY_USAGE: &[u8] = b"PrimaryUsage\0"; pub(crate) const HID_DEVICE_PROPERTY_PRIMARY_USAGE_PAGE: &[u8] = b"PrimaryUsagePage\0"; #[allow(non_upper_case_globals)] pub(crate) const kHIDPage_AppleVendor: i32 = 0xff00; #[allow(non_upper_case_globals)] pub(crate) const kHIDUsage_AppleVendor_TemperatureSensor: i32 = 0x0005; pub(crate) fn matching(page: i32, usage: i32) -> CFDictionaryRef { unsafe { let keys = [ CFStringCreateWithCString( null() as *const _, HID_DEVICE_PROPERTY_PRIMARY_USAGE_PAGE.as_ptr() as *const _, 0, ), CFStringCreateWithCString( null() as *const _, HID_DEVICE_PROPERTY_PRIMARY_USAGE.as_ptr() as *const _, 0, ), ]; let nums = [ CFNumberCreate(null(), kCFNumberSInt32Type, &page as *const _ as *const _), CFNumberCreate(null(), kCFNumberSInt32Type, &usage as *const _ as *const _), ]; let dict = CFDictionaryCreate( null(), &keys as *const _ as *const _, &nums as *const _ as *const _, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks, ); for key in keys { CFRelease(key as _); } for num in nums { CFRelease(num as _); } dict } } } #[cfg(all(not(feature = "apple-sandbox"), target_arch = "aarch64"))] pub use io_service::*;