Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Apple Silicon #137

Merged
merged 7 commits into from
Dec 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions Classes/FanControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#import "NSFileManager+DirectoryLocations.h"
#import "smc.h"
#import "smcWrapper.h"
#import "IOHIDSensor.h"
#import "MachineDefaults.h"

#import "Power.h"
Expand Down
39 changes: 34 additions & 5 deletions Classes/FanControl.m
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,11 @@ -(void) awakeFromNib {
@0, PREF_AC_SELECTION,
@0, PREF_CHARGING_SELECTION,
@0, PREF_MENU_DISPLAYMODE,
#if TARGET_CPU_ARM64
@"Tp0D",PREF_TEMPERATURE_SENSOR,
#else
@"TC0D",PREF_TEMPERATURE_SENSOR,
#endif
@0, PREF_NUMBEROF_LAUNCHES,
@NO,PREF_DONATIONMESSAGE_DISPLAY,
[NSArchiver archivedDataWithRootObject:[NSColor blackColor]],PREF_MENU_TEXTCOLOR,
Expand Down Expand Up @@ -334,6 +338,13 @@ - (IBAction)delete_favorite:(id)sender{
}


- (BOOL)usesIOHIDForTemperature {
#if TARGET_CPU_ARM64
return [[MachineDefaults computerModel] rangeOfString:@"MacBookPro17"].length > 0;
#else
return false;
#endif
}

// Called via a timer mechanism. This is where all the temp / RPM reading is done.
//reads fan data and updates the gui
Expand Down Expand Up @@ -399,7 +410,11 @@ -(void) readFanData:(id)caller{

if (bNeedTemp == true) {
// Read current temperature and format text for the menubar.
c_temp = [smcWrapper get_maintemp];
if ([self usesIOHIDForTemperature]) {
c_temp = [IOHIDSensor getSOCTemperature];
} else {
c_temp = [smcWrapper get_maintemp];
}

if ([[defaults objectForKey:PREF_TEMP_UNIT] intValue]==0) {
temp = [NSString stringWithFormat:@"%@%CC",@(c_temp),(unsigned short)0xb0];
Expand Down Expand Up @@ -534,6 +549,15 @@ - (IBAction)closePreferences:(id)sender{
[DefaultsController revert:sender];
}

-(void)setFansToAuto:(bool)is_auto {
for (int fan_index=0;fan_index<[[FavoritesController arrangedObjects][0][PREF_FAN_ARRAY] count];fan_index++) {
[self setFanToAuto:fan_index is_auto:is_auto];
}
}

-(void)setFanToAuto:(int)fan_index is_auto:(bool)is_auto {
[smcWrapper setKey_external:[NSString stringWithFormat:@"F%dMd",fan_index] value:is_auto ? @"00" : @"01"];
}

//set the new fan settings

Expand All @@ -549,7 +573,7 @@ -(void)apply_settings:(id)sender controllerindex:(int)cIndex{
[smcWrapper setKey_external:[NSString stringWithFormat:@"F%dMn",i] value:[[FanController arrangedObjects][i][PREF_FAN_SELSPEED] tohex]];
} else {
bool is_auto = [[FanController arrangedObjects][i][PREF_FAN_AUTO] boolValue];
[smcWrapper setKey_external:[NSString stringWithFormat:@"F%dMd",i] value:is_auto ? @"00" : @"01"];
[self setFanToAuto:i is_auto:is_auto];
float f_val = [[FanController arrangedObjects][i][PREF_FAN_SELSPEED] floatValue];
uint8 *vals = (uint8*)&f_val;
//NSString str_val = ;
Expand Down Expand Up @@ -676,9 +700,7 @@ -(void)performReset
}
error = nil;
if ([[MachineDefaults computerModel] rangeOfString:@"MacBookPro15"].location != NSNotFound) {
for (int i=0;i<[[FavoritesController arrangedObjects][0][PREF_FAN_ARRAY] count];i++) {
[smcWrapper setKey_external:[NSString stringWithFormat:@"F%dMd",i] value:@"00"];
}
[self setFansToAuto:true];
}

NSString *domainName = [[NSBundle mainBundle] bundleIdentifier];
Expand Down Expand Up @@ -733,6 +755,13 @@ -(void) syncBinder:(Boolean)bind{

#pragma mark **Power Watchdog-Methods**

- (void)systemWillSleep:(id)sender{
#if TARGET_CPU_ARM64
[FanControl setRights];
[self setFansToAuto:true];
#endif
}

- (void)systemDidWakeFromSleep:(id)sender{
[self apply_settings:nil controllerindex:[[defaults objectForKey:PREF_SELECTION_DEFAULT] intValue]];
}
Expand Down
57 changes: 57 additions & 0 deletions Classes/IOHIDSensor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* FanControl
*
* Copyright (c) 2006-2012 Hendrik Holtmann
*
* IOHIDSensor.h - MacBook(Pro) FanControl application
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#import <Foundation/Foundation.h>

#import <IOKit/hidsystem/IOHIDEventSystemClient.h>
#import <IOKit/hidsystem/IOHIDServiceClient.h>

// https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-1035.70.7/IOHIDFamily/AppleHIDUsageTables.h.auto.html
#define kHIDPage_AppleVendor 0xff00
#define kHIDUsage_AppleVendor_TemperatureSensor 0x0005

// https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-1035.70.7/IOHIDFamily/IOHIDEventTypes.h.auto.html
#ifdef __LP64__
typedef double IOHIDFloat;
#else
typedef float IOHIDFloat;
#endif

// https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-1035.70.7/IOHIDFamily/IOHIDEventTypes.h.auto.html
#define IOHIDEventFieldBase(type) (type << 16)
#define kIOHIDEventTypeTemperature 15


typedef struct __IOHIDEvent *IOHIDEventRef;
typedef struct __IOHIDServiceClient *IOHIDServiceClientRef;

IOHIDEventSystemClientRef IOHIDEventSystemClientCreate(CFAllocatorRef);
void IOHIDEventSystemClientSetMatching(IOHIDEventSystemClientRef, CFDictionaryRef);
IOHIDEventRef IOHIDServiceClientCopyEvent(IOHIDServiceClientRef, int64_t, int32_t, int64_t);
IOHIDFloat IOHIDEventGetFloatValue(IOHIDEventRef event, uint32_t field);

@interface IOHIDSensor : NSObject {
}

+ (float) getSOCTemperature;

@end
70 changes: 70 additions & 0 deletions Classes/IOHIDSensor.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* FanControl
*
* Copyright (c) 2006-2012 Hendrik Holtmann
*
* IOHIDSensor.m - MacBook(Pro) FanControl application
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#import "IOHIDSensor.h"

@implementation IOHIDSensor

static BOOL isSOCSensor(CFStringRef sensorName) {
return CFStringFind(sensorName, CFSTR("SOC"), kCFCompareCaseInsensitive).location != kCFNotFound;
}

static float toOneDecimalPlace(float value) {
return roundf(10.0f * value) / 10.0f;
}

+ (float) getSOCTemperature {
IOHIDEventSystemClientRef eventSystemClient = IOHIDEventSystemClientCreate(kCFAllocatorDefault);
CFArrayRef services = IOHIDEventSystemClientCopyServices(eventSystemClient);
if (services) {

float socSensorSum = 0.0f;
int socSensorCount = 0;

for (int i = 0; i < CFArrayGetCount(services); i++) {
IOHIDServiceClientRef serviceClientRef = (IOHIDServiceClientRef)CFArrayGetValueAtIndex(services, i);
CFStringRef sensorName = IOHIDServiceClientCopyProperty(serviceClientRef, CFSTR("Product"));
if (sensorName) {
if (isSOCSensor(sensorName)) {
IOHIDEventRef event = IOHIDServiceClientCopyEvent(serviceClientRef, kIOHIDEventTypeTemperature, 0, 0);
if (event) {
IOHIDFloat sensorTemperature = IOHIDEventGetFloatValue(event, IOHIDEventFieldBase(kIOHIDEventTypeTemperature));
CFRelease(event);
socSensorSum += sensorTemperature;
socSensorCount++;
}
}
CFRelease(sensorName);
}
}

CFRelease(services);
CFRelease(eventSystemClient);

float avgSOCTemp = socSensorCount > 0 ? socSensorSum / socSensorCount : 0.0f;
return toOneDecimalPlace(avgSOCTemp);
}

return 0.0f;
}

@end
2 changes: 2 additions & 0 deletions Classes/Power.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
//delegate Prototypes
@interface NSObject (PowerDelegate)

- (void)systemWillSleep:(id)sender;

- (void)systemDidWakeFromSleep:(id)sender;

- (void)powerChangeToBattery:(id)sender;
Expand Down
1 change: 1 addition & 0 deletions Classes/Power.m
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ - (void)powerMessageReceived:(natural_t)messageType withArgument:(void *) messag
switch (messageType)
{
case kIOMessageSystemWillSleep:
[_delegate systemWillSleep:self];
IOAllowPowerChange(root_port, (long)messageArgument);
break;
case kIOMessageCanSystemSleep:
Expand Down
4 changes: 4 additions & 0 deletions Classes/smcWrapper.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,11 @@ +(float)readTempSensors
NSString *sensor = [[NSUserDefaults standardUserDefaults] objectForKey:PREF_TEMPERATURE_SENSOR];
SMCReadKey2((char*)[sensor UTF8String], &val,conn);
retValue = [self convertToNumber:val];
#if TARGET_CPU_ARM64
allSensors = [NSArray arrayWithObjects:@"Tp01",@"Tp05",@"Tp09",@"Tp0b",@"Tp0D",@"Tp0H",@"Tp0L",@"Tp0P",@"Tp0T",@"Tp0X",nil];
#else
allSensors = [NSArray arrayWithObjects:@"TC0D",@"TC0P",@"TCAD",@"TC0H",@"TC0F",@"TCAH",@"TCBH",nil];
#endif
if (retValue<=0 || floor(retValue) == 129 ) { //workaround for some iMac Models
for (NSString *sensor in allSensors) {
SMCReadKey2((char*)[sensor UTF8String], &val,conn);
Expand Down
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ $ brew install --cask smcfancontrol
After that you'll be able to use Spotlight to launch smcFanControl normally. :-)


Requirements: Intel Mac / OS X 10.7 or higher
Requirements: Apple Silicon or Intel Mac / OS X 10.7 or higher


Compiled version: https://www.eidac.de/smcfancontrol/smcfancontrol_2_6.zip
Expand Down
4 changes: 2 additions & 2 deletions Ressources/Dutch.lproj/F.A.Q.rtf
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ All changes smcFanControl does to the fan controlling get lost after you shutdow

\b I get a "smcFanControl has not been tested on this machine" warning. What does that mean?\

\b0 Technically smcFanControl supports every intel mac, but it does not come with defaults for every machine. If you get the warning, smcFanControl tries to read out the fan-details directly from the System Management Controller. If you follow the instructions (no other fan control software is running etc.) you should have no problem running smcFanControl on a machine it has not been tested on.\
\b0 Technically smcFanControl supports every Apple Silicon & Intel Mac, but it does not come with defaults for every machine. If you get the warning, smcFanControl tries to read out the fan-details directly from the System Management Controller. If you follow the instructions (no other fan control software is running etc.) you should have no problem running smcFanControl on a machine it has not been tested on.\
\

\b How can I restore the Apple defaults for fanspeed?\
Expand Down Expand Up @@ -74,7 +74,7 @@ Will there be a version of smcFanControl for Powerbooks or other PPC based Macs?

\b Wouldn't it be even better to read out the temperature and set the fan speeds depending on the readout than just set the minimum fan speed and let automatic fan control as defined by apple do the rest?\

\b0 Yes, that approach is even better and could make your machine running cooler, when you are at higher loads. BUT: I did not take this route for smcFanControl, cause it has some risks. Adjusting the fan speed to CPU temperature requires you have a program running in the background (e.g. a daemon) that adjust fan speed continuously . If that program ever crashes or becomes incompatible cause of a System Update (or the readouts of the temperature sensor get inappropriate) , the fans could get set to a wrong (too low) speed and this could probably damage the machine. In addition to that the fan-control-logic is quite complicate. An intel mac has about 10 temperature sensors, that are continuously read out and are used for monitoring and setting the right fan speeds. So it would be "not so great" to read out just the CPU temperature as a foundation for the fan-controlling.\
\b0 Yes, that approach is even better and could make your machine running cooler, when you are at higher loads. BUT: I did not take this route for smcFanControl, cause it has some risks. Adjusting the fan speed to CPU temperature requires you have a program running in the background (e.g. a daemon) that adjust fan speed continuously . If that program ever crashes or becomes incompatible cause of a System Update (or the readouts of the temperature sensor get inappropriate) , the fans could get set to a wrong (too low) speed and this could probably damage the machine. In addition to that the fan-control-logic is quite complicate. A Mac has about 10 temperature sensors, that are continuously read out and are used for monitoring and setting the right fan speeds. So it would be "not so great" to read out just the CPU temperature as a foundation for the fan-controlling.\
\

\b I have got a MBP and smcFanControl is reporting 0rpm for one of my fans?\
Expand Down
4 changes: 2 additions & 2 deletions Ressources/English.lproj/F.A.Q.rtf
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ All changes smcFanControl does to the fan controlling get lost after you shutdow

\b I get a "smcFanControl has not been tested on this machine" warning. What does that mean?\

\b0 Technically smcFanControl supports every intel mac, but it does not come with defaults for every machine. If you get the warning, smcFanControl tries to read out the fan-details directly from the System Management Controller. If you follow the instructions (no other fan control software is running etc.) you should have no problem running smcFanControl on a machine it has not been tested on.\
\b0 Technically smcFanControl supports every Apple Silicon & Intel Mac, but it does not come with defaults for every machine. If you get the warning, smcFanControl tries to read out the fan-details directly from the System Management Controller. If you follow the instructions (no other fan control software is running etc.) you should have no problem running smcFanControl on a machine it has not been tested on.\
\

\b How can I restore the Apple defaults for fanspeed?\
Expand Down Expand Up @@ -73,7 +73,7 @@ Will there be a version of smcFanControl for Powerbooks or other PPC based Macs?

\b Wouldn't it be even better to read out the temperature and set the fan speeds depending on the readout than just set the minimum fan speed and let automatic fan control as defined by apple do the rest?\

\b0 Yes, that approach is even better and could make your machine running cooler, when you are at higher loads. BUT: I did not take this route for smcFanControl, cause it has some risks. Adjusting the fan speed to CPU temperature requires you have a program running in the background (e.g. a daemon) that adjust fan speed continuously . If that program ever crashes or becomes incompatible cause of a System Update (or the readouts of the temperature sensor get inappropriate) , the fans could get set to a wrong (too low) speed and this could probably damage the machine. In addition to that the fan-control-logic is quite complicate. An intel mac has about 10 temperature sensors, that are continuously read out and are used for monitoring and setting the right fan speeds. So it would be "not so great" to read out just the CPU temperature as a foundation for the fan-controlling.\
\b0 Yes, that approach is even better and could make your machine running cooler, when you are at higher loads. BUT: I did not take this route for smcFanControl, cause it has some risks. Adjusting the fan speed to CPU temperature requires you have a program running in the background (e.g. a daemon) that adjust fan speed continuously . If that program ever crashes or becomes incompatible cause of a System Update (or the readouts of the temperature sensor get inappropriate) , the fans could get set to a wrong (too low) speed and this could probably damage the machine. In addition to that the fan-control-logic is quite complicate. A Mac has about 10 temperature sensors, that are continuously read out and are used for monitoring and setting the right fan speeds. So it would be "not so great" to read out just the CPU temperature as a foundation for the fan-controlling.\
\

\b I have got a MBP and smcFanControl is reporting 0rpm for one of my fans?\
Expand Down
4 changes: 2 additions & 2 deletions Ressources/French.lproj/F.A.Q.rtf
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Oui

\b J'obtiens le message d'avertissement "smcFanControl n'a pas encore \'e9t\'e9 test\'e9 sur cette machine". Qu'est ce que cela signifie?\

\b0 Techniquement, smcFanControl fonctionne avec tous les Mac intel, mais ces machines ont des valeurs par d\'e9faut diff\'e9rente. Si vous obtenez ce message, smcFanControl tente de lire la valeur par d\'e9faut directement du System Management Controller. Si vous suivez les instructions (ne pas lancer d'autres logiciels de gestion de ventilation, etc.) vous devriez pouvoir utiliser smcFanControl sur une machine que n'a pas encore \'e9t\'e9 test\'e9e par nos soins.\
\b0 Techniquement, smcFanControl fonctionne avec tous les Mac Apple Silicon et Intel, mais ces machines ont des valeurs par d\'e9faut diff\'e9rente. Si vous obtenez ce message, smcFanControl tente de lire la valeur par d\'e9faut directement du System Management Controller. Si vous suivez les instructions (ne pas lancer d'autres logiciels de gestion de ventilation, etc.) vous devriez pouvoir utiliser smcFanControl sur une machine que n'a pas encore \'e9t\'e9 test\'e9e par nos soins.\
\

\b Comment revenir au valeur par d\'e9fauts d\'e9finies par Apple ?\
Expand Down Expand Up @@ -63,7 +63,7 @@ Toutefois, vous pouvez d\'e9finir une vitesse minimale sous OSX puis red\'e9mar

\b Ne serait-il pas mieux de d\'e9finir la vitesse de rotation en fonction de la temp\'e9rature plut\'f4t que de choisir une vitesse minimale et laisse Apple faire le reste ?\

\b0 Oui, cette approche serait probablement plus int\'e9ressante. MAIS : cette m\'e9thode n'a pas \'e9t\'e9 retenue car elle comporte des risques. D\'e9finir la vitesse en fonction de la temp\'e9rature requiert un programme qui tourne en continue. Si ce programme crash ou devient incompatible \'e0 la suite d'une mise \'e0 jour, le ventilateur pourrait \'eatre d\'e9fini \'e0 une valeur trop basse qui pourrait endommager votre machine. D'autre part, cette logique est complexe \'e0 mettre en oeuvre. Un mac intel poss\'e8de une dizaine de sondes de temp\'e9rature, lues continuellement afin de d\'e9finir la vitesse ad\'e9quate de rotation des ventilateurs. Ainsi il ne serait pas judicieux de se reposer sur la lecture d'une seule sonde pour le contr\'f4le de la ventilation.\
\b0 Oui, cette approche serait probablement plus int\'e9ressante. MAIS : cette m\'e9thode n'a pas \'e9t\'e9 retenue car elle comporte des risques. D\'e9finir la vitesse en fonction de la temp\'e9rature requiert un programme qui tourne en continue. Si ce programme crash ou devient incompatible \'e0 la suite d'une mise \'e0 jour, le ventilateur pourrait \'eatre d\'e9fini \'e0 une valeur trop basse qui pourrait endommager votre machine. D'autre part, cette logique est complexe \'e0 mettre en oeuvre. Un Mac poss\'e8de une dizaine de sondes de temp\'e9rature, lues continuellement afin de d\'e9finir la vitesse ad\'e9quate de rotation des ventilateurs. Ainsi il ne serait pas judicieux de se reposer sur la lecture d'une seule sonde pour le contr\'f4le de la ventilation.\
\

\b Je poss\'e8de un MBP et smcFanControl m'indique 0 rpm pour l'un des ventilateurs\
Expand Down
Loading