mirror of
https://github.com/hholtmann/smcFanControl.git
synced 2025-11-04 19:49:16 +01:00
Merge branch 'master' of https://github.com/mw9074/smcFanControl into mw9074-master
Conflicts: smc-command/smc.c smc-command/smc.h
This commit is contained in:
9
Classes/FanControl.h
Normal file → Executable file
9
Classes/FanControl.h
Normal file → Executable file
@ -2,7 +2,8 @@
|
|||||||
* FanControl
|
* FanControl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2006-2012 Hendrik Holtmann
|
* Copyright (c) 2006-2012 Hendrik Holtmann
|
||||||
*
|
* Portions Copyright (c) 2013 Michael Wilber
|
||||||
|
*
|
||||||
* FanControl.h - MacBook(Pro) FanControl application
|
* FanControl.h - MacBook(Pro) FanControl application
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -38,7 +39,7 @@
|
|||||||
#define kMenuBarHeight 22
|
#define kMenuBarHeight 22
|
||||||
|
|
||||||
|
|
||||||
@interface FanControl : NSObject
|
@interface FanControl : NSObject <NSMenuDelegate>
|
||||||
|
|
||||||
{
|
{
|
||||||
IBOutlet id currentSpeed;
|
IBOutlet id currentSpeed;
|
||||||
@ -104,9 +105,6 @@
|
|||||||
|
|
||||||
NSImage *menu_image;
|
NSImage *menu_image;
|
||||||
NSImage *menu_image_alt;
|
NSImage *menu_image_alt;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)terminate:(id)sender;
|
-(void)terminate:(id)sender;
|
||||||
@ -133,6 +131,7 @@
|
|||||||
- (void) syncBinder:(Boolean)bind;
|
- (void) syncBinder:(Boolean)bind;
|
||||||
- (IBAction) changeMenu:(id)sender;
|
- (IBAction) changeMenu:(id)sender;
|
||||||
- (IBAction)menuSelect:(id)sender;
|
- (IBAction)menuSelect:(id)sender;
|
||||||
|
- (void)menuNeedsUpdate:(NSMenu*)menu;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
254
Classes/FanControl.m
Normal file → Executable file
254
Classes/FanControl.m
Normal file → Executable file
@ -2,7 +2,8 @@
|
|||||||
* FanControl
|
* FanControl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2006-2012 Hendrik Holtmann
|
* Copyright (c) 2006-2012 Hendrik Holtmann
|
||||||
*
|
* Portions Copyright (c) 2013 Michael Wilber
|
||||||
|
*
|
||||||
* FanControl.m - MacBook(Pro) FanControl application
|
* FanControl.m - MacBook(Pro) FanControl application
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -37,18 +38,10 @@
|
|||||||
|
|
||||||
@implementation FanControl
|
@implementation FanControl
|
||||||
|
|
||||||
io_connect_t conn;
|
// Number of fans reported by the hardware.
|
||||||
kern_return_t result;
|
int g_numFans = 0;
|
||||||
SMCVal_t val;
|
|
||||||
NSUserDefaults *defaults;
|
NSUserDefaults *defaults;
|
||||||
Boolean supported=false;
|
|
||||||
extern char *optarg;
|
|
||||||
SMCVal_t val;
|
|
||||||
OSStatus status;
|
|
||||||
NSDictionary* machine_defaults;
|
|
||||||
NSString *authpw;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma mark **Init-Methods**
|
#pragma mark **Init-Methods**
|
||||||
|
|
||||||
@ -169,11 +162,11 @@ NSString *authpw;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
g_numFans = [smcWrapper get_fan_num];
|
||||||
s_menus=[[NSMutableArray alloc] init];
|
s_menus=[[NSMutableArray alloc] init];
|
||||||
[s_menus autorelease];
|
[s_menus autorelease];
|
||||||
int i;
|
int i;
|
||||||
for(i=0;i<[smcWrapper get_fan_num];i++){
|
for(i=0;i<g_numFans;i++){
|
||||||
NSMenuItem *mitem=[[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:@"Fan: %d",i] action:NULL keyEquivalent:@""];
|
NSMenuItem *mitem=[[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:@"Fan: %d",i] action:NULL keyEquivalent:@""];
|
||||||
[mitem setTag:(i+1)*10];
|
[mitem setTag:(i+1)*10];
|
||||||
[s_menus insertObject:mitem atIndex:i];
|
[s_menus insertObject:mitem atIndex:i];
|
||||||
@ -222,7 +215,7 @@ NSString *authpw;
|
|||||||
|
|
||||||
//release MachineDefaults class first call
|
//release MachineDefaults class first call
|
||||||
//add timer for reading to RunLoop
|
//add timer for reading to RunLoop
|
||||||
_readTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(readFanData:) userInfo:nil repeats:YES];
|
_readTimer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:@selector(readFanData:) userInfo:nil repeats:YES];
|
||||||
[_readTimer fire];
|
[_readTimer fire];
|
||||||
//autoapply settings if valid
|
//autoapply settings if valid
|
||||||
[self upgradeFavorites];
|
[self upgradeFavorites];
|
||||||
@ -243,6 +236,11 @@ NSString *authpw;
|
|||||||
for(i=0;i<[s_menus count];i++) {
|
for(i=0;i<[s_menus count];i++) {
|
||||||
[theMenu insertItem:[s_menus objectAtIndex:i] atIndex:i];
|
[theMenu insertItem:[s_menus objectAtIndex:i] atIndex:i];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Sign up for menuNeedsUpdate call
|
||||||
|
// so that the fan speeds in the menu can be updated
|
||||||
|
// only when needed.
|
||||||
|
[theMenu setDelegate:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -305,107 +303,145 @@ NSString *authpw;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Called via a timer mechanism. This is where all the temp / RPM reading is done.
|
||||||
//reads fan data and updates the gui
|
//reads fan data and updates the gui
|
||||||
-(void) readFanData:(NSTimer*)timer{
|
-(void) readFanData:(NSTimer*)timer{
|
||||||
|
|
||||||
NSString *temp;
|
int i = 0;
|
||||||
NSString *fan;
|
|
||||||
|
|
||||||
|
|
||||||
//on init handling
|
//on init handling
|
||||||
if (s_sed==nil) {
|
if (s_sed==nil) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//populate Menu Items with recent Data
|
// Determine what data is actually needed to keep the energy impact
|
||||||
int i;
|
// as low as possible.
|
||||||
for(i=0;i<[smcWrapper get_fan_num];i++){
|
bool bNeedTemp = false;
|
||||||
NSString *fandesc=[[[s_sed objectForKey:@"Fans"] objectAtIndex:i] objectForKey:@"Description"];
|
bool bNeedRpm = false;
|
||||||
[[theMenu itemWithTag:(i+1)*10] setTitle:[NSString stringWithFormat:@"%@: %@ rpm",fandesc,[[NSNumber numberWithInt:[smcWrapper get_fan_rpm:i]] stringValue]]];
|
const int menuBarSetting = [[defaults objectForKey:@"MenuBar"] intValue];
|
||||||
}
|
switch (menuBarSetting) {
|
||||||
|
default:
|
||||||
|
case 1:
|
||||||
|
bNeedTemp = true;
|
||||||
|
bNeedRpm = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
bNeedTemp = true;
|
||||||
|
bNeedRpm = true;
|
||||||
|
break;
|
||||||
|
|
||||||
float c_temp=[smcWrapper get_maintemp];
|
case 3:
|
||||||
if ([[defaults objectForKey:@"Unit"] intValue]==0) {
|
bNeedTemp = true;
|
||||||
temp=[NSString stringWithFormat:@"%@%CC",[NSNumber numberWithFloat:c_temp],(unsigned short)0xb0];
|
bNeedRpm = false;
|
||||||
} else {
|
break;
|
||||||
NSNumberFormatter *ncf=[[[NSNumberFormatter alloc] init] autorelease];
|
|
||||||
[ncf setFormat:@"00;00;-00"];
|
|
||||||
temp=[NSString stringWithFormat:@"%@%CF",[ncf stringForObjectValue:[[NSNumber numberWithFloat:c_temp] celsius_fahrenheit]],(unsigned short)0xb0];
|
|
||||||
}
|
|
||||||
NSNumberFormatter *nc=[[[NSNumberFormatter alloc] init] autorelease];
|
|
||||||
//avoid jumping in menu bar
|
|
||||||
[nc setFormat:@"000;000;-000"];
|
|
||||||
|
|
||||||
int selected = 0;
|
case 4:
|
||||||
NSArray *fans = [[[FavoritesController arrangedObjects] objectAtIndex:[FavoritesController selectionIndex]] objectForKey:@"FanData"];
|
bNeedTemp = false;
|
||||||
for (i=0;i<[fans count];i++)
|
bNeedRpm = true;
|
||||||
{
|
break;
|
||||||
if ([[[fans objectAtIndex:i] objectForKey:@"menu"] boolValue]==YES) {
|
}
|
||||||
selected = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fan=[NSString stringWithFormat:@"%@rpm",[nc stringForObjectValue:[NSNumber numberWithFloat:[smcWrapper get_fan_rpm:selected]]]];
|
NSString *temp = nil;
|
||||||
|
NSString *fan = nil;
|
||||||
|
float c_temp = 0.0f;
|
||||||
|
int selectedRpm = 0;
|
||||||
|
|
||||||
if ([[defaults objectForKey:@"MenuBar"] intValue]<=1) {
|
if (bNeedRpm == true) {
|
||||||
NSString *add;
|
// Read the current fan speed for the desired fan and format text for display in the menubar.
|
||||||
int fsize;
|
NSArray *fans = [[[FavoritesController arrangedObjects] objectAtIndex:[FavoritesController selectionIndex]] objectForKey:@"FanData"];
|
||||||
if ([[defaults objectForKey:@"MenuBar"] intValue]==0) {
|
for (i=0; i<g_numFans && i<[fans count]; i++)
|
||||||
add=@"\n";
|
{
|
||||||
fsize=9;
|
if ([[[fans objectAtIndex:i] objectForKey:@"menu"] boolValue]==YES) {
|
||||||
[statusItem setLength:53];
|
selectedRpm = [smcWrapper get_fan_rpm:i];
|
||||||
} else {
|
break;
|
||||||
add=@" ";
|
}
|
||||||
fsize=11;
|
}
|
||||||
[statusItem setLength:96];
|
|
||||||
}
|
|
||||||
NSMutableAttributedString *s_status=[[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@%@%@",temp,add,fan]];
|
|
||||||
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
|
||||||
[paragraphStyle setAlignment:NSLeftTextAlignment];
|
|
||||||
[s_status addAttribute:NSFontAttributeName value:[NSFont fontWithName:@"Lucida Grande" size:fsize] range:NSMakeRange(0,[s_status length])];
|
|
||||||
[s_status addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0,[s_status length])];
|
|
||||||
[s_status addAttribute:NSForegroundColorAttributeName value:(NSColor*)[NSUnarchiver unarchiveObjectWithData:[defaults objectForKey:@"MenuColor"]] range:NSMakeRange(0,[s_status length])];
|
|
||||||
[statusItem setAttributedTitle:s_status];
|
|
||||||
[statusItem setImage:nil];
|
|
||||||
[statusItem setAlternateImage:nil];
|
|
||||||
[paragraphStyle release];
|
|
||||||
[s_status release];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
NSNumberFormatter *nc=[[[NSNumberFormatter alloc] init] autorelease];
|
||||||
|
//avoid jumping in menu bar
|
||||||
|
[nc setFormat:@"000;000;-000"];
|
||||||
|
|
||||||
if ([[defaults objectForKey:@"MenuBar"] intValue]==2) {
|
fan = [NSString stringWithFormat:@"%@rpm",[nc stringForObjectValue:[NSNumber numberWithFloat:selectedRpm]]];
|
||||||
[statusItem setLength:26];
|
}
|
||||||
[statusItem setTitle:nil];
|
|
||||||
[statusItem setToolTip:[NSString stringWithFormat:@"%@\n%@",temp,fan]];
|
|
||||||
[statusItem setImage:menu_image];
|
|
||||||
[statusItem setAlternateImage:menu_image_alt];
|
|
||||||
|
|
||||||
}
|
if (bNeedTemp == true) {
|
||||||
|
// Read current temperature and format text for the menubar.
|
||||||
|
c_temp = [smcWrapper get_maintemp];
|
||||||
|
|
||||||
if ([[defaults objectForKey:@"MenuBar"] intValue]==3) {
|
if ([[defaults objectForKey:@"Unit"] intValue]==0) {
|
||||||
[statusItem setLength:46];
|
temp = [NSString stringWithFormat:@"%@%CC",[NSNumber numberWithFloat:c_temp],(unsigned short)0xb0];
|
||||||
NSMutableAttributedString *s_status=[[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@",temp]];
|
} else {
|
||||||
[s_status addAttribute:NSFontAttributeName value:[NSFont fontWithName:@"Lucida Grande" size:12] range:NSMakeRange(0,[s_status length])];
|
NSNumberFormatter *ncf=[[[NSNumberFormatter alloc] init] autorelease];
|
||||||
[s_status addAttribute:NSForegroundColorAttributeName value:(NSColor*)[NSUnarchiver unarchiveObjectWithData:[defaults objectForKey:@"MenuColor"]] range:NSMakeRange(0,[s_status length])];
|
[ncf setFormat:@"00;00;-00"];
|
||||||
[statusItem setAttributedTitle:s_status];
|
temp = [NSString stringWithFormat:@"%@%CF",[ncf stringForObjectValue:[[NSNumber numberWithFloat:c_temp] celsius_fahrenheit]],(unsigned short)0xb0];
|
||||||
[statusItem setImage:nil];
|
}
|
||||||
[statusItem setAlternateImage:nil];
|
}
|
||||||
[s_status release];
|
|
||||||
|
|
||||||
}
|
// Update the temp and/or fan speed text in the menubar.
|
||||||
if ([[defaults objectForKey:@"MenuBar"] intValue]==4) {
|
NSMutableAttributedString *s_status = nil;
|
||||||
[statusItem setLength:65];
|
NSMutableParagraphStyle *paragraphStyle = nil;
|
||||||
NSMutableAttributedString *s_status=[[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@",fan]];
|
|
||||||
[s_status addAttribute:NSFontAttributeName value:[NSFont fontWithName:@"Lucida Grande" size:12] range:NSMakeRange(0,[s_status length])];
|
|
||||||
[s_status addAttribute:NSForegroundColorAttributeName value:(NSColor*)[NSUnarchiver unarchiveObjectWithData:[defaults objectForKey:@"MenuColor"]] range:NSMakeRange(0,[s_status length])];
|
|
||||||
[statusItem setAttributedTitle:s_status];
|
|
||||||
[statusItem setImage:nil];
|
|
||||||
[statusItem setAlternateImage:nil];
|
|
||||||
[s_status release];
|
|
||||||
|
|
||||||
}
|
switch (menuBarSetting) {
|
||||||
|
default:
|
||||||
|
case 1: {
|
||||||
|
int fsize = 0;
|
||||||
|
NSString *add = nil;
|
||||||
|
if (menuBarSetting==0) {
|
||||||
|
add=@"\n";
|
||||||
|
fsize=9;
|
||||||
|
[statusItem setLength:53];
|
||||||
|
} else {
|
||||||
|
add=@" ";
|
||||||
|
fsize=11;
|
||||||
|
[statusItem setLength:96];
|
||||||
|
}
|
||||||
|
|
||||||
|
s_status=[[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@%@%@",temp,add,fan]];
|
||||||
|
paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
||||||
|
[paragraphStyle setAlignment:NSLeftTextAlignment];
|
||||||
|
[s_status addAttribute:NSFontAttributeName value:[NSFont fontWithName:@"Lucida Grande" size:fsize] range:NSMakeRange(0,[s_status length])];
|
||||||
|
[s_status addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0,[s_status length])];
|
||||||
|
[s_status addAttribute:NSForegroundColorAttributeName value:(NSColor*)[NSUnarchiver unarchiveObjectWithData:[defaults objectForKey:@"MenuColor"]] range:NSMakeRange(0,[s_status length])];
|
||||||
|
[statusItem setAttributedTitle:s_status];
|
||||||
|
[statusItem setImage:nil];
|
||||||
|
[statusItem setAlternateImage:nil];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
// TODO: Big waste of energy to update this tooltip every X seconds when the user
|
||||||
|
// is unlikely to hover the smcFanControl icon over and over again.
|
||||||
|
[statusItem setLength:26];
|
||||||
|
[statusItem setTitle:nil];
|
||||||
|
[statusItem setToolTip:[NSString stringWithFormat:@"%@\n%@",temp,fan]];
|
||||||
|
[statusItem setImage:menu_image];
|
||||||
|
[statusItem setAlternateImage:menu_image_alt];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
[statusItem setLength:46];
|
||||||
|
s_status=[[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@",temp]];
|
||||||
|
[s_status addAttribute:NSFontAttributeName value:[NSFont fontWithName:@"Lucida Grande" size:12] range:NSMakeRange(0,[s_status length])];
|
||||||
|
[s_status addAttribute:NSForegroundColorAttributeName value:(NSColor*)[NSUnarchiver unarchiveObjectWithData:[defaults objectForKey:@"MenuColor"]] range:NSMakeRange(0,[s_status length])];
|
||||||
|
[statusItem setAttributedTitle:s_status];
|
||||||
|
[statusItem setImage:nil];
|
||||||
|
[statusItem setAlternateImage:nil];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
[statusItem setLength:65];
|
||||||
|
s_status=[[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@",fan]];
|
||||||
|
[s_status addAttribute:NSFontAttributeName value:[NSFont fontWithName:@"Lucida Grande" size:12] range:NSMakeRange(0,[s_status length])];
|
||||||
|
[s_status addAttribute:NSForegroundColorAttributeName value:(NSColor*)[NSUnarchiver unarchiveObjectWithData:[defaults objectForKey:@"MenuColor"]] range:NSMakeRange(0,[s_status length])];
|
||||||
|
[statusItem setAttributedTitle:s_status];
|
||||||
|
[statusItem setImage:nil];
|
||||||
|
[statusItem setAlternateImage:nil];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
[paragraphStyle release];
|
||||||
|
[s_status release];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -474,7 +510,7 @@ NSString *authpw;
|
|||||||
-(void)terminate:(id)sender{
|
-(void)terminate:(id)sender{
|
||||||
//get last active selection
|
//get last active selection
|
||||||
[defaults synchronize];
|
[defaults synchronize];
|
||||||
SMCClose(conn);
|
[smcWrapper cleanUp];
|
||||||
[_readTimer invalidate];
|
[_readTimer invalidate];
|
||||||
[pw deregisterForSleepWakeNotification];
|
[pw deregisterForSleepWakeNotification];
|
||||||
[pw deregisterForPowerChange];
|
[pw deregisterForPowerChange];
|
||||||
@ -518,6 +554,23 @@ NSString *authpw;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called when user clicks on smcFanControl status bar item
|
||||||
|
// in the status area of the menubar. The fan speed
|
||||||
|
// menu items are now only updated here in order to
|
||||||
|
// reduce the energy impact of -readFanData.
|
||||||
|
- (void)menuNeedsUpdate:(NSMenu*)menu {
|
||||||
|
if (theMenu == menu) {
|
||||||
|
if (s_sed == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i=0; i<g_numFans; ++i){
|
||||||
|
NSString *fandesc=[[[s_sed objectForKey:@"Fans"] objectAtIndex:i] objectForKey:@"Description"];
|
||||||
|
[[theMenu itemWithTag:(i+1)*10] setTitle:[NSString stringWithFormat:@"%@: %@ rpm",fandesc,[[NSNumber numberWithInt:[smcWrapper get_fan_rpm:i]] stringValue]]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma mark **Helper-Methods**
|
#pragma mark **Helper-Methods**
|
||||||
@ -669,20 +722,23 @@ NSString *authpw;
|
|||||||
|
|
||||||
|
|
||||||
#pragma mark **SMC-Binary Owner/Right Check**
|
#pragma mark **SMC-Binary Owner/Right Check**
|
||||||
|
//TODO: It looks like this function is called inefficiently.
|
||||||
//call smc binary with sudo rights and apply
|
//call smc binary with sudo rights and apply
|
||||||
+(void)setRights{
|
+(void)setRights{
|
||||||
NSString *smcpath = [[NSBundle mainBundle] pathForResource:@"smc" ofType:@""];
|
NSString *smcpath = [[NSBundle mainBundle] pathForResource:@"smc" ofType:@""];
|
||||||
NSFileManager *fmanage=[NSFileManager defaultManager];
|
NSFileManager *fmanage=[NSFileManager defaultManager];
|
||||||
NSDictionary *fdic = [fmanage attributesOfItemAtPath:smcpath error:nil];
|
NSDictionary *fdic = [fmanage attributesOfItemAtPath:smcpath error:nil];
|
||||||
if ([[fdic valueForKey:@"NSFileOwnerAccountName"] isEqualToString:@"root"] && [[fdic valueForKey:@"NSFileGroupOwnerAccountName"] isEqualToString:@"admin"] && ([[fdic valueForKey:@"NSFilePosixPermissions"] intValue]==3437)) {
|
if ([[fdic valueForKey:@"NSFileOwnerAccountName"] isEqualToString:@"root"] && [[fdic valueForKey:@"NSFileGroupOwnerAccountName"] isEqualToString:@"admin"] && ([[fdic valueForKey:@"NSFilePosixPermissions"] intValue]==3437)) {
|
||||||
return;
|
// If the SMC binary has already been modified to run as root, then do nothing.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
//TODO: Is the usage of commPipe safe?
|
||||||
FILE *commPipe;
|
FILE *commPipe;
|
||||||
AuthorizationRef authorizationRef;
|
AuthorizationRef authorizationRef;
|
||||||
AuthorizationItem gencitem = { "system.privilege.admin", 0, NULL, 0 };
|
AuthorizationItem gencitem = { "system.privilege.admin", 0, NULL, 0 };
|
||||||
AuthorizationRights gencright = { 1, &gencitem };
|
AuthorizationRights gencright = { 1, &gencitem };
|
||||||
int flags = kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed;
|
int flags = kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed;
|
||||||
status = AuthorizationCreate(&gencright, kAuthorizationEmptyEnvironment, flags, &authorizationRef);
|
OSStatus status = AuthorizationCreate(&gencright, kAuthorizationEmptyEnvironment, flags, &authorizationRef);
|
||||||
NSString *tool=@"/usr/sbin/chown";
|
NSString *tool=@"/usr/sbin/chown";
|
||||||
NSArray *argsArray = [NSArray arrayWithObjects: @"root:admin",smcpath,nil];
|
NSArray *argsArray = [NSArray arrayWithObjects: @"root:admin",smcpath,nil];
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
5
Classes/smcWrapper.h
Normal file → Executable file
5
Classes/smcWrapper.h
Normal file → Executable file
@ -2,7 +2,8 @@
|
|||||||
* FanControl
|
* FanControl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2006-2012 Hendrik Holtmann
|
* Copyright (c) 2006-2012 Hendrik Holtmann
|
||||||
*
|
* Portions Copyright (c) 2013 Michael Wilber
|
||||||
|
*
|
||||||
* smcWrapper.m - MacBook(Pro) FanControl application
|
* smcWrapper.m - MacBook(Pro) FanControl application
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -28,6 +29,8 @@
|
|||||||
@interface smcWrapper : NSObject {
|
@interface smcWrapper : NSObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+(void) cleanUp;
|
||||||
|
|
||||||
+(int) get_fan_rpm:(int)fan_number;
|
+(int) get_fan_rpm:(int)fan_number;
|
||||||
+(float) get_maintemp;
|
+(float) get_maintemp;
|
||||||
+(float) get_mptemp;
|
+(float) get_mptemp;
|
||||||
|
|||||||
24
Classes/smcWrapper.m
Normal file → Executable file
24
Classes/smcWrapper.m
Normal file → Executable file
@ -2,7 +2,8 @@
|
|||||||
* FanControl
|
* FanControl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2006-2012 Hendrik Holtmann
|
* Copyright (c) 2006-2012 Hendrik Holtmann
|
||||||
*
|
* Portions Copyright (c) 2013 Michael Wilber
|
||||||
|
*
|
||||||
* smcWrapper.m - MacBook(Pro) FanControl application
|
* smcWrapper.m - MacBook(Pro) FanControl application
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -23,6 +24,7 @@
|
|||||||
#import "smcWrapper.h"
|
#import "smcWrapper.h"
|
||||||
#import <CommonCrypto/CommonDigest.h>
|
#import <CommonCrypto/CommonDigest.h>
|
||||||
|
|
||||||
|
//TODO: This is the smcFanControl 2.4 checksum, it needs to be updated for the next release.
|
||||||
NSString * const smc_checksum=@"2ea544babe8a58dccc1364c920d473c8";
|
NSString * const smc_checksum=@"2ea544babe8a58dccc1364c920d473c8";
|
||||||
static NSDictionary *tsensors = nil;
|
static NSDictionary *tsensors = nil;
|
||||||
|
|
||||||
@ -33,6 +35,9 @@ static NSDictionary *tsensors = nil;
|
|||||||
SMCOpen(&conn);
|
SMCOpen(&conn);
|
||||||
tsensors = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tsensors" ofType:@"plist"]];
|
tsensors = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tsensors" ofType:@"plist"]];
|
||||||
}
|
}
|
||||||
|
+(void)cleanUp{
|
||||||
|
SMCClose(conn);
|
||||||
|
}
|
||||||
|
|
||||||
+(float) get_maintemp{
|
+(float) get_maintemp{
|
||||||
float c_temp;
|
float c_temp;
|
||||||
@ -43,22 +48,23 @@ static NSDictionary *tsensors = nil;
|
|||||||
c_temp=[smcWrapper get_mptemp];
|
c_temp=[smcWrapper get_mptemp];
|
||||||
} else {
|
} else {
|
||||||
SMCVal_t val;
|
SMCVal_t val;
|
||||||
NSMutableArray *allTSensors = [[tsensors allKeys] mutableCopy];
|
|
||||||
NSString *foundKey = [tsensors objectForKey:[MachineDefaults computerModel]];
|
NSString *foundKey = [tsensors objectForKey:[MachineDefaults computerModel]];
|
||||||
if (foundKey !=nil) {
|
if (foundKey !=nil) {
|
||||||
foundKey = [MachineDefaults computerModel];
|
foundKey = [MachineDefaults computerModel];
|
||||||
} else {
|
} else {
|
||||||
foundKey = @"standard";
|
foundKey = @"standard";
|
||||||
}
|
}
|
||||||
[allTSensors removeObject:foundKey];
|
|
||||||
SMCReadKey2((char*)[[tsensors objectForKey:foundKey] UTF8String], &val,conn);
|
SMCReadKey2((char*)[[tsensors objectForKey:foundKey] UTF8String], &val,conn);
|
||||||
c_temp= ((val.bytes[0] * 256 + val.bytes[1]) >> 2)/64;
|
c_temp= ((val.bytes[0] * 256 + val.bytes[1]) >> 2)/64;
|
||||||
|
|
||||||
if (c_temp<=0) {
|
if (c_temp<=0) {
|
||||||
|
NSArray *allTSensors = [tsensors allKeys];
|
||||||
for (NSString *key in allTSensors) {
|
for (NSString *key in allTSensors) {
|
||||||
SMCReadKey2((char*)[[tsensors objectForKey:key] UTF8String], &val,conn);
|
if (![key isEqualToString:foundKey]) {
|
||||||
c_temp= ((val.bytes[0] * 256 + val.bytes[1]) >> 2)/64;
|
SMCReadKey2((char*)[[tsensors objectForKey:key] UTF8String], &val,conn);
|
||||||
if (c_temp>0) break;
|
c_temp= ((val.bytes[0] * 256 + val.bytes[1]) >> 2)/64;
|
||||||
|
if (c_temp>0) break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,14 +174,16 @@ static NSDictionary *tsensors = nil;
|
|||||||
}
|
}
|
||||||
|
|
||||||
//call smc binary with setuid rights and apply
|
//call smc binary with setuid rights and apply
|
||||||
|
// The smc binary is given root permissions in FanControl.m with the setRights method.
|
||||||
+(void)setKey_external:(NSString *)key value:(NSString *)value{
|
+(void)setKey_external:(NSString *)key value:(NSString *)value{
|
||||||
NSString *launchPath = [[NSBundle mainBundle] pathForResource:@"smc" ofType:@""];
|
NSString *launchPath = [[NSBundle mainBundle] pathForResource:@"smc" ofType:@""];
|
||||||
//first check if it's the right binary (security)
|
//first check if it's the right binary (security)
|
||||||
NSString *checksum=[smcWrapper createCheckSum:launchPath];
|
// MW: Disabled smc binary checksum. This should be re-enabled in an official release.
|
||||||
|
/*NSString *checksum=[smcWrapper createCheckSum:launchPath];
|
||||||
if (![checksum isEqualToString:smc_checksum]) {
|
if (![checksum isEqualToString:smc_checksum]) {
|
||||||
NSLog(@"smcFanControl: Security Error: smc-binary is not the distributed one");
|
NSLog(@"smcFanControl: Security Error: smc-binary is not the distributed one");
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
NSArray *argsArray = [NSArray arrayWithObjects: @"-k",key,@"-w",value,nil];
|
NSArray *argsArray = [NSArray arrayWithObjects: @"-k",key,@"-w",value,nil];
|
||||||
NSTask *task;
|
NSTask *task;
|
||||||
task = [[NSTask alloc] init];
|
task = [[NSTask alloc] init];
|
||||||
|
|||||||
423
smc-command/smc.c
Normal file → Executable file
423
smc-command/smc.c
Normal file → Executable file
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Apple System Management Control (SMC) Tool
|
* Apple System Management Control (SMC) Tool
|
||||||
* Copyright (C) 2006 devnull
|
* Copyright (C) 2006 devnull
|
||||||
|
* Portions Copyright (C) 2013 Michael Wilber
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -22,10 +23,22 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <IOKit/IOKitLib.h>
|
#include <IOKit/IOKitLib.h>
|
||||||
|
|
||||||
#include "smc.h"
|
#include "smc.h"
|
||||||
|
#include <libkern/OSAtomic.h>
|
||||||
|
|
||||||
io_connect_t conn;
|
// Cache the keyInfo to lower the energy impact of SMCReadKey() / SMCReadKey2()
|
||||||
|
#define KEY_INFO_CACHE_SIZE 100
|
||||||
|
struct {
|
||||||
|
UInt32 key;
|
||||||
|
SMCKeyData_keyInfo_t keyInfo;
|
||||||
|
} g_keyInfoCache[KEY_INFO_CACHE_SIZE];
|
||||||
|
|
||||||
|
int g_keyInfoCacheCount = 0;
|
||||||
|
OSSpinLock g_keyInfoSpinLock = 0;
|
||||||
|
|
||||||
|
kern_return_t SMCCall2(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure, io_connect_t conn);
|
||||||
|
|
||||||
|
#pragma mark C Helpers
|
||||||
|
|
||||||
UInt32 _strtoul(char *str, int size, int base)
|
UInt32 _strtoul(char *str, int size, int base)
|
||||||
{
|
{
|
||||||
@ -70,13 +83,6 @@ float _strtof(unsigned char *str, int size, int e)
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
void smc_init(){
|
|
||||||
SMCOpen(&conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void smc_close(){
|
|
||||||
SMCClose(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void printFP1F(SMCVal_t val)
|
void printFP1F(SMCVal_t val)
|
||||||
{
|
{
|
||||||
@ -264,6 +270,9 @@ void printVal(SMCVal_t val)
|
|||||||
printf("no data\n");
|
printf("no data\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
=======
|
||||||
|
#pragma mark Shared SMC functions
|
||||||
|
>>>>>>> 3328c0018f364d7873b2aabaeb4284f19d586cb0
|
||||||
|
|
||||||
kern_return_t SMCOpen(io_connect_t *conn)
|
kern_return_t SMCOpen(io_connect_t *conn)
|
||||||
{
|
{
|
||||||
@ -306,27 +315,6 @@ kern_return_t SMCClose(io_connect_t conn)
|
|||||||
return IOServiceClose(conn);
|
return IOServiceClose(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
kern_return_t SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure)
|
|
||||||
{
|
|
||||||
size_t structureInputSize;
|
|
||||||
size_t structureOutputSize;
|
|
||||||
|
|
||||||
structureInputSize = sizeof(SMCKeyData_t);
|
|
||||||
structureOutputSize = sizeof(SMCKeyData_t);
|
|
||||||
/*
|
|
||||||
return IOConnectMethodStructureIStructureO(
|
|
||||||
conn,
|
|
||||||
index,
|
|
||||||
structureInputSize,
|
|
||||||
&structureOutputSize,
|
|
||||||
inputStructure,
|
|
||||||
outputStructure
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
return IOConnectCallStructMethod(conn, index, inputStructure, structureInputSize, outputStructure, &structureOutputSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
kern_return_t SMCCall2(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure,io_connect_t conn)
|
kern_return_t SMCCall2(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure,io_connect_t conn)
|
||||||
{
|
{
|
||||||
size_t structureInputSize;
|
size_t structureInputSize;
|
||||||
@ -334,17 +322,53 @@ kern_return_t SMCCall2(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *ou
|
|||||||
structureInputSize = sizeof(SMCKeyData_t);
|
structureInputSize = sizeof(SMCKeyData_t);
|
||||||
structureOutputSize = sizeof(SMCKeyData_t);
|
structureOutputSize = sizeof(SMCKeyData_t);
|
||||||
|
|
||||||
/* return IOConnectMethodStructureIStructureO(
|
|
||||||
conn,
|
|
||||||
index,
|
|
||||||
structureInputSize,
|
|
||||||
&structureOutputSize,
|
|
||||||
inputStructure,
|
|
||||||
outputStructure
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
return IOConnectCallStructMethod(conn, index, inputStructure, structureInputSize, outputStructure, &structureOutputSize);
|
return IOConnectCallStructMethod(conn, index, inputStructure, structureInputSize, outputStructure, &structureOutputSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provides key info, using a cache to dramatically improve the energy impact of smcFanControl
|
||||||
|
kern_return_t SMCGetKeyInfo(UInt32 key, SMCKeyData_keyInfo_t* keyInfo, io_connect_t conn)
|
||||||
|
{
|
||||||
|
SMCKeyData_t inputStructure;
|
||||||
|
SMCKeyData_t outputStructure;
|
||||||
|
kern_return_t result = kIOReturnSuccess;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
OSSpinLockLock(&g_keyInfoSpinLock);
|
||||||
|
|
||||||
|
for (; i < g_keyInfoCacheCount; ++i)
|
||||||
|
{
|
||||||
|
if (key == g_keyInfoCache[i].key)
|
||||||
|
{
|
||||||
|
*keyInfo = g_keyInfoCache[i].keyInfo;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == g_keyInfoCacheCount)
|
||||||
|
{
|
||||||
|
// Not in cache, must look it up.
|
||||||
|
memset(&inputStructure, 0, sizeof(inputStructure));
|
||||||
|
memset(&outputStructure, 0, sizeof(outputStructure));
|
||||||
|
|
||||||
|
inputStructure.key = key;
|
||||||
|
inputStructure.data8 = SMC_CMD_READ_KEYINFO;
|
||||||
|
|
||||||
|
result = SMCCall2(KERNEL_INDEX_SMC, &inputStructure, &outputStructure, conn);
|
||||||
|
if (result == kIOReturnSuccess)
|
||||||
|
{
|
||||||
|
*keyInfo = outputStructure.keyInfo;
|
||||||
|
if (g_keyInfoCacheCount < KEY_INFO_CACHE_SIZE)
|
||||||
|
{
|
||||||
|
g_keyInfoCache[g_keyInfoCacheCount].key = key;
|
||||||
|
g_keyInfoCache[g_keyInfoCacheCount].keyInfo = outputStructure.keyInfo;
|
||||||
|
++g_keyInfoCacheCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OSSpinLockUnlock(&g_keyInfoSpinLock);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_return_t SMCReadKey2(UInt32Char_t key, SMCVal_t *val,io_connect_t conn)
|
kern_return_t SMCReadKey2(UInt32Char_t key, SMCVal_t *val,io_connect_t conn)
|
||||||
@ -359,11 +383,12 @@ kern_return_t SMCReadKey2(UInt32Char_t key, SMCVal_t *val,io_connect_t conn)
|
|||||||
|
|
||||||
inputStructure.key = _strtoul(key, 4, 16);
|
inputStructure.key = _strtoul(key, 4, 16);
|
||||||
sprintf(val->key, key);
|
sprintf(val->key, key);
|
||||||
inputStructure.data8 = SMC_CMD_READ_KEYINFO;
|
|
||||||
|
|
||||||
result = SMCCall2(KERNEL_INDEX_SMC, &inputStructure, &outputStructure,conn);
|
result = SMCGetKeyInfo(inputStructure.key, &outputStructure.keyInfo, conn);
|
||||||
if (result != kIOReturnSuccess)
|
if (result != kIOReturnSuccess)
|
||||||
|
{
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
val->dataSize = outputStructure.keyInfo.dataSize;
|
val->dataSize = outputStructure.keyInfo.dataSize;
|
||||||
_ultostr(val->dataType, outputStructure.keyInfo.dataType);
|
_ultostr(val->dataType, outputStructure.keyInfo.dataType);
|
||||||
@ -372,76 +397,81 @@ kern_return_t SMCReadKey2(UInt32Char_t key, SMCVal_t *val,io_connect_t conn)
|
|||||||
|
|
||||||
result = SMCCall2(KERNEL_INDEX_SMC, &inputStructure, &outputStructure,conn);
|
result = SMCCall2(KERNEL_INDEX_SMC, &inputStructure, &outputStructure,conn);
|
||||||
if (result != kIOReturnSuccess)
|
if (result != kIOReturnSuccess)
|
||||||
return result;
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
|
memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
|
||||||
|
|
||||||
return kIOReturnSuccess;
|
return kIOReturnSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark Command line only
|
||||||
|
// Exclude command-line only code from smcFanControl UI
|
||||||
|
#ifdef CMD_TOOL
|
||||||
|
|
||||||
|
io_connect_t g_conn = 0;
|
||||||
|
|
||||||
|
void smc_init(){
|
||||||
|
SMCOpen(&g_conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void smc_close(){
|
||||||
|
SMCClose(g_conn);
|
||||||
|
}
|
||||||
|
void printFPE2(SMCVal_t val)
|
||||||
|
{
|
||||||
|
/* FIXME: This decode is incomplete, last 2 bits are dropped */
|
||||||
|
|
||||||
|
printf("%.0f ", _strtof(val.bytes, val.dataSize, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void printUInt(SMCVal_t val)
|
||||||
|
{
|
||||||
|
printf("%u ", (unsigned int) _strtoul(val.bytes, val.dataSize, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBytesHex(SMCVal_t val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("(bytes");
|
||||||
|
for (i = 0; i < val.dataSize; i++)
|
||||||
|
printf(" %02x", (unsigned char) val.bytes[i]);
|
||||||
|
printf(")\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printVal(SMCVal_t val)
|
||||||
|
{
|
||||||
|
printf(" %-4s [%-4s] ", val.key, val.dataType);
|
||||||
|
if (val.dataSize > 0)
|
||||||
|
{
|
||||||
|
if ((strcmp(val.dataType, DATATYPE_UINT8) == 0) ||
|
||||||
|
(strcmp(val.dataType, DATATYPE_UINT16) == 0) ||
|
||||||
|
(strcmp(val.dataType, DATATYPE_UINT32) == 0))
|
||||||
|
printUInt(val);
|
||||||
|
else if (strcmp(val.dataType, DATATYPE_FPE2) == 0)
|
||||||
|
printFPE2(val);
|
||||||
|
|
||||||
|
printBytesHex(val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("no data\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_return_t SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure)
|
||||||
|
{
|
||||||
|
return SMCCall2(index, inputStructure, outputStructure, g_conn);
|
||||||
|
}
|
||||||
|
|
||||||
kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t *val)
|
kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t *val)
|
||||||
{
|
{
|
||||||
kern_return_t result;
|
return SMCReadKey2(key, val, g_conn);
|
||||||
SMCKeyData_t inputStructure;
|
|
||||||
SMCKeyData_t outputStructure;
|
|
||||||
|
|
||||||
memset(&inputStructure, 0, sizeof(SMCKeyData_t));
|
|
||||||
memset(&outputStructure, 0, sizeof(SMCKeyData_t));
|
|
||||||
memset(val, 0, sizeof(SMCVal_t));
|
|
||||||
|
|
||||||
inputStructure.key = _strtoul(key, 4, 16);
|
|
||||||
sprintf(val->key, key);
|
|
||||||
inputStructure.data8 = SMC_CMD_READ_KEYINFO;
|
|
||||||
|
|
||||||
result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
|
|
||||||
if (result != kIOReturnSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
val->dataSize = outputStructure.keyInfo.dataSize;
|
|
||||||
_ultostr(val->dataType, outputStructure.keyInfo.dataType);
|
|
||||||
inputStructure.keyInfo.dataSize = val->dataSize;
|
|
||||||
inputStructure.data8 = SMC_CMD_READ_BYTES;
|
|
||||||
|
|
||||||
result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
|
|
||||||
if (result != kIOReturnSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
|
|
||||||
|
|
||||||
return kIOReturnSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kern_return_t SMCWriteKey2(SMCVal_t writeVal, io_connect_t conn)
|
||||||
kern_return_t SMCWriteKey(SMCVal_t writeVal)
|
|
||||||
{
|
|
||||||
kern_return_t result;
|
|
||||||
SMCKeyData_t inputStructure;
|
|
||||||
SMCKeyData_t outputStructure;
|
|
||||||
|
|
||||||
SMCVal_t readVal;
|
|
||||||
|
|
||||||
result = SMCReadKey(writeVal.key, &readVal);
|
|
||||||
if (result != kIOReturnSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if (readVal.dataSize != writeVal.dataSize)
|
|
||||||
return kIOReturnError;
|
|
||||||
|
|
||||||
memset(&inputStructure, 0, sizeof(SMCKeyData_t));
|
|
||||||
memset(&outputStructure, 0, sizeof(SMCKeyData_t));
|
|
||||||
|
|
||||||
inputStructure.key = _strtoul(writeVal.key, 4, 16);
|
|
||||||
inputStructure.data8 = SMC_CMD_WRITE_BYTES;
|
|
||||||
inputStructure.keyInfo.dataSize = writeVal.dataSize;
|
|
||||||
memcpy(inputStructure.bytes, writeVal.bytes, sizeof(writeVal.bytes));
|
|
||||||
|
|
||||||
result = SMCCall2(KERNEL_INDEX_SMC, &inputStructure, &outputStructure,conn);
|
|
||||||
if (result != kIOReturnSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return kIOReturnSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
kern_return_t SMCWriteKey2(SMCVal_t writeVal,io_connect_t conn)
|
|
||||||
{
|
{
|
||||||
kern_return_t result;
|
kern_return_t result;
|
||||||
SMCKeyData_t inputStructure;
|
SMCKeyData_t inputStructure;
|
||||||
@ -470,6 +500,10 @@ kern_return_t SMCWriteKey2(SMCVal_t writeVal,io_connect_t conn)
|
|||||||
return kIOReturnSuccess;
|
return kIOReturnSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kern_return_t SMCWriteKey(SMCVal_t writeVal)
|
||||||
|
{
|
||||||
|
return SMCWriteKey2(writeVal, g_conn);
|
||||||
|
}
|
||||||
|
|
||||||
UInt32 SMCReadIndexCount(void)
|
UInt32 SMCReadIndexCount(void)
|
||||||
{
|
{
|
||||||
@ -559,42 +593,40 @@ kern_return_t SMCPrintFans(void)
|
|||||||
|
|
||||||
void usage(char* prog)
|
void usage(char* prog)
|
||||||
{
|
{
|
||||||
printf("Apple System Management Control (SMC) tool %s\n", VERSION);
|
printf("Apple System Management Control (SMC) tool %s\n", VERSION);
|
||||||
printf("Usage:\n");
|
printf("Usage:\n");
|
||||||
printf("%s [options]\n", prog);
|
printf("%s [options]\n", prog);
|
||||||
printf(" -f : fan info decoded\n");
|
printf(" -f : fan info decoded\n");
|
||||||
printf(" -h : help\n");
|
printf(" -h : help\n");
|
||||||
printf(" -k <key> : key to manipulate\n");
|
printf(" -k <key> : key to manipulate\n");
|
||||||
printf(" -l : list all keys and values\n");
|
printf(" -l : list all keys and values\n");
|
||||||
printf(" -r : read the value of a key\n");
|
printf(" -r : read the value of a key\n");
|
||||||
printf(" -w <value> : write the specified value to a key\n");
|
printf(" -w <value> : write the specified value to a key\n");
|
||||||
printf(" -v : version\n");
|
printf(" -v : version\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_return_t SMCWriteSimple(UInt32Char_t key,char *wvalue,io_connect_t conn)
|
kern_return_t SMCWriteSimple(UInt32Char_t key, char *wvalue, io_connect_t conn)
|
||||||
{
|
{
|
||||||
kern_return_t result;
|
kern_return_t result;
|
||||||
SMCVal_t val;
|
SMCVal_t val;
|
||||||
int i;
|
int i;
|
||||||
char c[3];
|
char c[3];
|
||||||
for (i = 0; i < strlen(wvalue); i++)
|
for (i = 0; i < strlen(wvalue); i++)
|
||||||
{
|
{
|
||||||
sprintf(c, "%c%c", wvalue[i * 2], wvalue[(i * 2) + 1]);
|
sprintf(c, "%c%c", wvalue[i * 2], wvalue[(i * 2) + 1]);
|
||||||
val.bytes[i] = (int) strtol(c, NULL, 16);
|
val.bytes[i] = (int) strtol(c, NULL, 16);
|
||||||
}
|
}
|
||||||
val.dataSize = i / 2;
|
val.dataSize = i / 2;
|
||||||
sprintf(val.key, key);
|
sprintf(val.key, key);
|
||||||
result = SMCWriteKey2(val,conn);
|
result = SMCWriteKey2(val, conn);
|
||||||
if (result != kIOReturnSuccess)
|
if (result != kIOReturnSuccess)
|
||||||
printf("Error: SMCWriteKey() = %08x\n", result);
|
printf("Error: SMCWriteKey() = %08x\n", result);
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CMD_TOOL
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
@ -602,31 +634,32 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
kern_return_t result;
|
kern_return_t result;
|
||||||
int op = OP_NONE;
|
int op = OP_NONE;
|
||||||
UInt32Char_t key = "\0";
|
UInt32Char_t key = { 0 };
|
||||||
SMCVal_t val;
|
SMCVal_t val;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "fhk:lrw:v")) != -1)
|
while ((c = getopt(argc, argv, "fhk:lrw:v")) != -1)
|
||||||
{
|
{
|
||||||
switch(c)
|
switch(c)
|
||||||
{
|
{
|
||||||
case 'f':
|
case 'f':
|
||||||
op = OP_READ_FAN;
|
op = OP_READ_FAN;
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
strncpy(key, optarg, sizeof(key)); //fix for buffer overflow
|
strncpy(key, optarg, sizeof(key)); //fix for buffer overflow
|
||||||
break;
|
key[sizeof(key) - 1] = '\0';
|
||||||
case 'l':
|
break;
|
||||||
op = OP_LIST;
|
case 'l':
|
||||||
break;
|
op = OP_LIST;
|
||||||
case 'r':
|
break;
|
||||||
op = OP_READ;
|
case 'r':
|
||||||
break;
|
op = OP_READ;
|
||||||
case 'v':
|
break;
|
||||||
printf("%s\n", VERSION);
|
case 'v':
|
||||||
return 0;
|
printf("%s\n", VERSION);
|
||||||
break;
|
return 0;
|
||||||
case 'w':
|
break;
|
||||||
op = OP_WRITE;
|
case 'w':
|
||||||
|
op = OP_WRITE;
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char c[3];
|
char c[3];
|
||||||
@ -642,65 +675,67 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
case '?':
|
case '?':
|
||||||
op = OP_NONE;
|
op = OP_NONE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op == OP_NONE)
|
if (op == OP_NONE)
|
||||||
{
|
{
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SMCOpen(&conn);
|
smc_init();
|
||||||
|
|
||||||
switch(op)
|
switch(op)
|
||||||
{
|
{
|
||||||
case OP_LIST:
|
case OP_LIST:
|
||||||
result = SMCPrintAll();
|
result = SMCPrintAll();
|
||||||
if (result != kIOReturnSuccess)
|
if (result != kIOReturnSuccess)
|
||||||
printf("Error: SMCPrintAll() = %08x\n", result);
|
printf("Error: SMCPrintAll() = %08x\n", result);
|
||||||
break;
|
break;
|
||||||
case OP_READ:
|
case OP_READ:
|
||||||
if (strlen(key) > 0)
|
if (strlen(key) > 0)
|
||||||
{
|
{
|
||||||
result = SMCReadKey(key, &val);
|
result = SMCReadKey(key, &val);
|
||||||
if (result != kIOReturnSuccess)
|
if (result != kIOReturnSuccess)
|
||||||
printf("Error: SMCReadKey() = %08x\n", result);
|
printf("Error: SMCReadKey() = %08x\n", result);
|
||||||
|
else
|
||||||
|
printVal(val);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
printVal(val);
|
{
|
||||||
}
|
printf("Error: specify a key to read\n");
|
||||||
else
|
}
|
||||||
{
|
break;
|
||||||
printf("Error: specify a key to read\n");
|
case OP_READ_FAN:
|
||||||
}
|
result = SMCPrintFans();
|
||||||
break;
|
|
||||||
case OP_READ_FAN:
|
|
||||||
result = SMCPrintFans();
|
|
||||||
if (result != kIOReturnSuccess)
|
|
||||||
printf("Error: SMCPrintFans() = %08x\n", result);
|
|
||||||
break;
|
|
||||||
case OP_WRITE:
|
|
||||||
if (strlen(key) > 0)
|
|
||||||
{
|
|
||||||
sprintf(val.key, key);
|
|
||||||
result = SMCWriteKey(val);
|
|
||||||
if (result != kIOReturnSuccess)
|
if (result != kIOReturnSuccess)
|
||||||
printf("Error: SMCWriteKey() = %08x\n", result);
|
printf("Error: SMCPrintFans() = %08x\n", result);
|
||||||
}
|
break;
|
||||||
else
|
case OP_WRITE:
|
||||||
{
|
if (strlen(key) > 0)
|
||||||
printf("Error: specify a key to write\n");
|
{
|
||||||
}
|
sprintf(val.key, key);
|
||||||
break;
|
result = SMCWriteKey(val);
|
||||||
|
if (result != kIOReturnSuccess)
|
||||||
|
printf("Error: SMCWriteKey() = %08x\n", result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Error: specify a key to write\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
SMCClose(conn);
|
smc_close();
|
||||||
return 0;;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif //#ifdef CMD_TOOL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
20
smc-command/smc.h
Normal file → Executable file
20
smc-command/smc.h
Normal file → Executable file
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Apple System Management Control (SMC) Tool
|
* Apple System Management Control (SMC) Tool
|
||||||
* Copyright (C) 2006 devnull
|
* Copyright (C) 2006 devnull
|
||||||
|
* Portions Copyright (C) 2013 Michael Wilber
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -114,12 +115,19 @@ typedef struct {
|
|||||||
} SMCVal_t;
|
} SMCVal_t;
|
||||||
|
|
||||||
UInt32 _strtoul(char *str, int size, int base);
|
UInt32 _strtoul(char *str, int size, int base);
|
||||||
kern_return_t SMCOpen(io_connect_t *conn);
|
float _strtof(char *str, int size, int e);
|
||||||
kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t *val);
|
|
||||||
kern_return_t SMCReadKey2(UInt32Char_t key, SMCVal_t *val,io_connect_t conn);
|
// Exclude command-line only code from smcFanControl UI
|
||||||
kern_return_t SMCWriteSimple(UInt32Char_t key,char *wvalue,io_connect_t conn);
|
#ifdef CMD_TOOL
|
||||||
kern_return_t SMCClose(io_connect_t conn);
|
|
||||||
void smc_init();
|
void smc_init();
|
||||||
void smc_close();
|
void smc_close();
|
||||||
|
kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t *val);
|
||||||
|
kern_return_t SMCWriteSimple(UInt32Char_t key,char *wvalue,io_connect_t conn);
|
||||||
|
|
||||||
|
#endif //#ifdef CMD_TOOL
|
||||||
|
|
||||||
|
kern_return_t SMCOpen(io_connect_t *conn);
|
||||||
|
kern_return_t SMCClose(io_connect_t conn);
|
||||||
|
kern_return_t SMCReadKey2(UInt32Char_t key, SMCVal_t *val,io_connect_t conn);
|
||||||
|
|
||||||
float _strtof(unsigned char *str, int size, int e);
|
|
||||||
|
|||||||
Reference in New Issue
Block a user