Skip to content

Commit

Permalink
Add support for get temperature on m1 (#792)
Browse files Browse the repository at this point in the history
Add support for get temperature on m1

Co-authored-by: sangluo <[email protected]>
  • Loading branch information
Mark3K and sangluo authored Aug 21, 2022
1 parent 5b76b69 commit 634ea3d
Show file tree
Hide file tree
Showing 8 changed files with 444 additions and 34 deletions.
172 changes: 172 additions & 0 deletions src/apple/macos/component/arm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// Take a look at the license at the top of the repository in the LICENSE file.

use std::ffi::CStr;

use core_foundation_sys::array::{CFArrayGetCount, CFArrayGetValueAtIndex};
use core_foundation_sys::base::kCFAllocatorDefault;
use core_foundation_sys::string::{
kCFStringEncodingUTF8, CFStringCreateWithBytes, CFStringGetCStringPtr,
};

use super::super::CFReleaser;
use crate::apple::inner::ffi::{
kHIDPage_AppleVendor, kHIDUsage_AppleVendor_TemperatureSensor, kIOHIDEventTypeTemperature,
matching, IOHIDEventFieldBase, IOHIDEventGetFloatValue, IOHIDEventSystemClientCopyServices,
IOHIDEventSystemClientCreate, IOHIDEventSystemClientSetMatching, IOHIDServiceClientCopyEvent,
IOHIDServiceClientCopyProperty, __IOHIDEventSystemClient, __IOHIDServiceClient,
HID_DEVICE_PROPERTY_PRODUCT,
};
use crate::ComponentExt;

pub(crate) struct Components {
pub inner: Vec<Component>,
client: Option<CFReleaser<__IOHIDEventSystemClient>>,
}

impl Components {
pub(crate) fn new() -> Self {
Self {
inner: vec![],
client: None,
}
}

pub(crate) fn refresh(&mut self) {
self.inner.clear();

unsafe {
let matches = match CFReleaser::new(matching(
kHIDPage_AppleVendor,
kHIDUsage_AppleVendor_TemperatureSensor,
)) {
Some(m) => m,
None => return,
};

let client = match CFReleaser::new(IOHIDEventSystemClientCreate(kCFAllocatorDefault)) {
Some(c) => c,
None => return,
};

let _ = IOHIDEventSystemClientSetMatching(client.inner(), matches.inner());

let services = match CFReleaser::new(IOHIDEventSystemClientCopyServices(client.inner()))
{
Some(s) => s,
None => return,
};

let key_ref = match CFReleaser::new(CFStringCreateWithBytes(
kCFAllocatorDefault,
HID_DEVICE_PROPERTY_PRODUCT.as_ptr(),
HID_DEVICE_PROPERTY_PRODUCT.len() as _,
kCFStringEncodingUTF8,
false as _,
)) {
Some(r) => r,
None => return,
};

let count = CFArrayGetCount(services.inner());

for i in 0..count {
let service = match CFReleaser::new(
CFArrayGetValueAtIndex(services.inner(), i) as *const _
) {
Some(s) => s,
None => continue,
};

let name = match CFReleaser::new(IOHIDServiceClientCopyProperty(
service.inner(),
key_ref.inner(),
)) {
Some(n) => n,
None => continue,
};

let name_ptr =
CFStringGetCStringPtr(name.inner() as *const _, kCFStringEncodingUTF8);
let name_str = CStr::from_ptr(name_ptr).to_string_lossy().to_string();

let mut component = Component::new(name_str, None, None, service);
component.refresh();

self.inner.push(component);
}

self.client.replace(client);
}
}
}

unsafe impl Send for Components {}

unsafe impl Sync for Components {}

#[doc = include_str!("../../../../md_doc/component.md")]
pub struct Component {
service: CFReleaser<__IOHIDServiceClient>,
temperature: f32,
label: String,
max: f32,
critical: Option<f32>,
}

impl Component {
pub(crate) fn new(
label: String,
max: Option<f32>,
critical: Option<f32>,
service: CFReleaser<__IOHIDServiceClient>,
) -> Self {
Self {
service,
label,
max: max.unwrap_or(0.),
critical,
temperature: 0.,
}
}
}

unsafe impl Send for Component {}

unsafe impl Sync for Component {}

impl ComponentExt for Component {
fn temperature(&self) -> f32 {
self.temperature
}

fn max(&self) -> f32 {
self.max
}

fn critical(&self) -> Option<f32> {
self.critical
}

fn label(&self) -> &str {
&self.label
}

fn refresh(&mut self) {
unsafe {
let event = match CFReleaser::new(IOHIDServiceClientCopyEvent(
self.service.inner() as *const _,
kIOHIDEventTypeTemperature,
0,
0,
)) {
Some(e) => e,
None => return,
};

self.temperature = IOHIDEventGetFloatValue(
event.inner(),
IOHIDEventFieldBase(kIOHIDEventTypeTemperature),
) as _;
}
}
}
13 changes: 13 additions & 0 deletions src/apple/macos/component/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Take a look at the license at the top of the repository in the LICENSE file.

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub(crate) mod x86;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub use self::x86::*;

#[cfg(target_arch = "aarch64")]
pub(crate) mod arm;

#[cfg(target_arch = "aarch64")]
pub use self::arm::*;
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl ComponentFFI {
}
}

#[doc = include_str!("../../../md_doc/component.md")]
#[doc = include_str!("../../../../md_doc/component.md")]
pub struct Component {
temperature: f32,
max: f32,
Expand Down
26 changes: 1 addition & 25 deletions src/apple/macos/disk.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file.

use super::CFReleaser;
use crate::sys::{ffi, utils};
use crate::utils::to_cpath;
use crate::{Disk, DiskType};
Expand Down Expand Up @@ -33,31 +34,6 @@ fn to_path(mount_path: &[c_char]) -> Option<PathBuf> {
}
}

#[repr(transparent)]
struct CFReleaser<T>(*const T);

impl<T> CFReleaser<T> {
fn new(ptr: *const T) -> Option<Self> {
if ptr.is_null() {
None
} else {
Some(Self(ptr))
}
}

fn inner(&self) -> *const T {
self.0
}
}

impl<T> Drop for CFReleaser<T> {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe { CFRelease(self.0 as _) }
}
}
}

pub(crate) fn get_disks(session: ffi::DASessionRef) -> Vec<Disk> {
if session.is_null() {
return Vec::new();
Expand Down
Loading

0 comments on commit 634ea3d

Please sign in to comment.