Initial commit of enhanced version
This commit is contained in:
parent
fe998e484d
commit
8d89d05cf2
8 changed files with 378 additions and 148 deletions
56
Makefile
Normal file
56
Makefile
Normal file
|
@ -0,0 +1,56 @@
|
|||
COMPILER=G++
|
||||
|
||||
# todo: object files into output path, processing c / c++ files in the same time (?), nested directories for source files (?)
|
||||
C = c
|
||||
OUTPUT_PATH = bin/
|
||||
SOURCE_PATH = src/
|
||||
EXE = bin/mbpfan
|
||||
|
||||
ifeq ($(COMPILER), G++)
|
||||
ifeq ($(OS),Windows_NT)
|
||||
OBJ = obj
|
||||
else
|
||||
OBJ = o
|
||||
endif
|
||||
COPT = -O2
|
||||
CCMD = g++
|
||||
OBJFLAG = -o
|
||||
EXEFLAG = -o
|
||||
# INCLUDES = -I../.includes
|
||||
INCLUDES =
|
||||
# LIBS = -lgc
|
||||
LIBS = -lm
|
||||
# LIBPATH = -L../gc/.libs
|
||||
LIBPATH =
|
||||
CPPFLAGS = $(COPT) -g $(INCLUDES)
|
||||
LDFLAGS = $(LIBPATH) -g $(LIBS)
|
||||
DEP = dep
|
||||
else
|
||||
OBJ = obj
|
||||
COPT = /O2
|
||||
CCMD = cl
|
||||
OBJFLAG = /Fo
|
||||
EXEFLAG = /Fe
|
||||
# INCLUDES = /I..\\.includes
|
||||
INCLUDES =
|
||||
# LIBS = ..\\.libs\\libgc.lib
|
||||
LIBS =
|
||||
CPPFLAGS = $(COPT) /DEBUG $(INCLUDES)
|
||||
LDFLAGS = /DEBUG
|
||||
endif
|
||||
|
||||
OBJS := $(patsubst %.$(C),%.$(OBJ),$(wildcard $(SOURCE_PATH)*.$(C)))
|
||||
|
||||
%.$(OBJ):%.$(C)
|
||||
@echo Compiling $(basename $<)...
|
||||
$(CCMD) -c $(CPPFLAGS) $(CXXFLAGS) $< $(OBJFLAG)$@
|
||||
|
||||
all: $(OBJS)
|
||||
@echo Linking...
|
||||
$(CCMD) $(LDFLAGS) $^ $(LIBS) $(EXEFLAG) $(EXE)
|
||||
|
||||
clean:
|
||||
rm -rf $(SOURCE_PATH)*.$(OBJ) $(EXE)
|
||||
|
||||
rebuild: clean all
|
||||
#rebuild is not entirely correct
|
21
README
21
README
|
@ -1,4 +1,23 @@
|
|||
This is a daemon that uses input from coretemp module and sets the fan speed using the applesmc module. It includes a PKGBUILD for easy installation in Arch Linux.
|
||||
This is an enhanced version of rvega's Fan-Control-Daemon <https://github.com/rvega/Fan-Control-Daemon>,
|
||||
which itself is an enhanced version of Allan McRae mbpfan <http://allanmcrae.com/2010/05/simple-macbook-pro-fan-daemon/>
|
||||
|
||||
Fan-Control-Daemon is a daemon that uses input from coretemp module and sets the fan speed using the applesmc module.
|
||||
This enhanced version assumes any number of processors and fans (max. 10).
|
||||
|
||||
* It only uses the temperatures from the processors as input.
|
||||
* It requires coretemp and applesmc kernel modules to be loaded.
|
||||
* It requires root use
|
||||
|
||||
|
||||
Compile with
|
||||
gcc -o mbpfan -lm mbpfan.c
|
||||
|
||||
Run with
|
||||
sudo ./mbpfan
|
||||
|
||||
Original README below.
|
||||
--
|
||||
It includes a PKGBUILD for easy installation in Arch Linux.
|
||||
|
||||
Based on:
|
||||
|
||||
|
|
BIN
bin/mbpfan
Executable file
BIN
bin/mbpfan
Executable file
Binary file not shown.
147
mbpfan.c
147
mbpfan.c
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
* mbpfan.c - automatically control fan for MacBook Pro
|
||||
* Copyright (C) 2010 Allan McRae <allan@archlinux.org>
|
||||
* Modifications by Rafael Vega <rvega@elsoftwarehamuerto.org>
|
||||
*
|
||||
* 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 3 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.
|
||||
*
|
||||
* 20110811 - v1.1
|
||||
*
|
||||
* Notes:
|
||||
* Uses only the temperatures from the processors as input.
|
||||
* Assumes two processors and one fan.
|
||||
* Requires coretemp and applesmc kernel modules to be loaded.
|
||||
*
|
||||
* Tested models:
|
||||
* MacBook Pro 8.1 13" (Intel i7 - Linux 3.2)
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* lazy min/max... */
|
||||
#define min(a,b) a < b ? a : b
|
||||
#define max(a,b) a > b ? a : b
|
||||
|
||||
/* basic fan speed parameters */
|
||||
unsigned short min_fan_speed=2000;
|
||||
unsigned short max_fan_speed=6200;
|
||||
|
||||
/* temperature thresholds
|
||||
* low_temp - temperature below which fan speed will be at minimum
|
||||
* high_temp - fan will increase speed when higher than this temperature
|
||||
* max_temp - fan will run at full speed above this temperature */
|
||||
unsigned short low_temp=63;
|
||||
unsigned short high_temp=66;
|
||||
unsigned short max_temp=86;
|
||||
/* unsigned short low_temp=55; */
|
||||
/* unsigned short high_temp=65; */
|
||||
/* unsigned short max_temp=80; */
|
||||
|
||||
/* temperature polling interval */
|
||||
unsigned short polling_interval=10;
|
||||
|
||||
|
||||
/* Controls the speed of the fan */
|
||||
void set_fan_speed(unsigned short speed)
|
||||
{
|
||||
FILE *file;
|
||||
|
||||
file=fopen("/sys/devices/platform/applesmc.768/fan1_min", "w");
|
||||
fprintf(file, "%d", speed);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
|
||||
/* Takes "manual" control of fan */
|
||||
/* void prepare_fan() */
|
||||
/* { */
|
||||
/* FILE *file; */
|
||||
/* */
|
||||
/* file=fopen("/sys/devices/platform/applesmc.768/fan1_manual", "w"); */
|
||||
/* fprintf(file, "%d", 1); */
|
||||
/* fclose(file); */
|
||||
/* } */
|
||||
|
||||
|
||||
/* Returns average CPU temp in degrees (ceiling) */
|
||||
unsigned short get_temp()
|
||||
{
|
||||
FILE *file;
|
||||
unsigned short temp;
|
||||
unsigned int t0, t1;
|
||||
|
||||
file=fopen("/sys/devices/platform/coretemp.0/temp2_input", "r");
|
||||
fscanf(file, "%d", &t0);
|
||||
fclose(file);
|
||||
|
||||
file=fopen("/sys/devices/platform/coretemp.0/temp3_input", "r");
|
||||
fscanf(file, "%d", &t1);
|
||||
fclose(file);
|
||||
|
||||
temp = (unsigned short)(ceil((float)(t0 + t1) / 2000.));
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned short old_temp, new_temp, fan_speed, steps;
|
||||
short temp_change;
|
||||
float step_up, step_down;
|
||||
|
||||
/* prepare_fan(); */
|
||||
|
||||
/* assume running on boot so set fan speed to minimum */
|
||||
new_temp = get_temp();
|
||||
fan_speed = 2000;
|
||||
set_fan_speed(fan_speed);
|
||||
sleep(polling_interval);
|
||||
|
||||
step_up = (float)(max_fan_speed - min_fan_speed) /
|
||||
(float)((max_temp - high_temp) * (max_temp - high_temp + 1) / 2);
|
||||
|
||||
step_down = (float)(max_fan_speed - min_fan_speed) /
|
||||
(float)((max_temp - low_temp) * (max_temp - low_temp + 1) / 2);
|
||||
|
||||
while(1)
|
||||
{
|
||||
old_temp = new_temp;
|
||||
new_temp = get_temp();
|
||||
|
||||
if(new_temp >= max_temp && fan_speed != max_fan_speed) {
|
||||
fan_speed = max_fan_speed;
|
||||
}
|
||||
|
||||
if(new_temp <= low_temp && fan_speed != min_fan_speed) {
|
||||
fan_speed = min_fan_speed;
|
||||
}
|
||||
|
||||
temp_change = new_temp - old_temp;
|
||||
|
||||
if(temp_change > 0 && new_temp > high_temp && new_temp < max_temp) {
|
||||
steps = (new_temp - high_temp) * (new_temp - high_temp + 1) / 2;
|
||||
fan_speed = max(fan_speed, ceil(min_fan_speed + steps * step_up));
|
||||
}
|
||||
|
||||
if(temp_change < 0 && new_temp > low_temp && new_temp < max_temp) {
|
||||
steps = (max_temp - new_temp) * (max_temp - new_temp + 1) / 2;
|
||||
fan_speed = min(fan_speed, floor(max_fan_speed - steps * step_down));
|
||||
}
|
||||
|
||||
set_fan_speed(fan_speed);
|
||||
sleep(polling_interval);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
261
src/mbpfan.c
Normal file
261
src/mbpfan.c
Normal file
|
@ -0,0 +1,261 @@
|
|||
/**
|
||||
* mbpfan.c - automatically control fan for MacBook Pro
|
||||
* Copyright (C) 2010 Allan McRae <allan@archlinux.org>
|
||||
* Modifications by Rafael Vega <rvega@elsoftwarehamuerto.org>
|
||||
* Modifications (2012) by Daniel Graziotin <dgraziotin@task3.cc>
|
||||
*
|
||||
* 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 3 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.
|
||||
*
|
||||
* 2012-06-09 - v1.2
|
||||
*
|
||||
* Notes:
|
||||
* Assumes any number of processors and fans (max. 10)
|
||||
* It Uses only the temperatures from the processors as input.
|
||||
* Requires coretemp and applesmc kernel modules to be loaded.
|
||||
* Requires root use
|
||||
*
|
||||
* Tested models:
|
||||
* MacBook Pro 8.1 13" (Intel i7 - Linux 3.2)
|
||||
* Macbook Pro 6,2 15" (Intel i7 - Linux 3.2)
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "mbpfan.h"
|
||||
|
||||
/* lazy min/max... */
|
||||
#define min(a,b) a < b ? a : b
|
||||
#define max(a,b) a > b ? a : b
|
||||
|
||||
unsigned short min_fan_speed = 2000;
|
||||
unsigned short max_fan_speed = 6200;
|
||||
|
||||
/* temperature thresholds
|
||||
* low_temp - temperature below which fan speed will be at minimum
|
||||
* high_temp - fan will increase speed when higher than this temperature
|
||||
* max_temp - fan will run at full speed above this temperature */
|
||||
unsigned short low_temp = 63; // try ranges 55-63
|
||||
unsigned short high_temp = 66; // try ranges 58-66
|
||||
unsigned short max_temp = 86; // do not set it > 90
|
||||
|
||||
unsigned short polling_interval = 7;
|
||||
|
||||
|
||||
struct s_sensors {
|
||||
char* path;
|
||||
char* fan_path;
|
||||
unsigned int temperature;
|
||||
struct s_sensors *next;
|
||||
};
|
||||
|
||||
void find_fans(t_sensors* sensors)
|
||||
{
|
||||
t_sensors *tmp = sensors;
|
||||
|
||||
char *path = NULL;
|
||||
const char *path_begin = "/sys/devices/platform/applesmc.768/fan";
|
||||
const char *path_end = "_min";
|
||||
int path_size = strlen(path_begin) + strlen(path_end) + 2;
|
||||
char number[1];
|
||||
sprintf(number,"%d",0);
|
||||
|
||||
int counter = 0;
|
||||
|
||||
for(counter = 0; counter<10; counter++) {
|
||||
path = (char*) malloc(sizeof( char ) * path_size);
|
||||
path[0] = '\0';
|
||||
sprintf(number,"%d",counter);
|
||||
|
||||
strncat( path, path_begin, strlen(path_begin) );
|
||||
strncat( path, number, strlen(number) );
|
||||
strncat( path, path_end, strlen(path_begin) );
|
||||
|
||||
FILE *file = fopen(path, "r");
|
||||
|
||||
if(file != NULL) {
|
||||
if (tmp->path != NULL)
|
||||
tmp->fan_path = (char *) malloc(sizeof( char ) * path_size);
|
||||
strcpy(tmp->fan_path, path);
|
||||
tmp = tmp->next;
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
free(path);
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
|
||||
t_sensors *find_sensors()
|
||||
{
|
||||
|
||||
t_sensors *sensors_head = NULL;
|
||||
t_sensors *s = NULL;
|
||||
|
||||
char *path = NULL;
|
||||
const char *path_begin = "/sys/devices/platform/coretemp.0/temp";
|
||||
const char *path_end = "_input";
|
||||
|
||||
int path_size = strlen(path_begin) + strlen(path_end) + 2;
|
||||
char number[1];
|
||||
sprintf(number,"%d",0);
|
||||
|
||||
int i = 0;
|
||||
for(i = 0; i<10; i++) {
|
||||
path = (char*) malloc(sizeof( char ) * path_size);
|
||||
|
||||
sprintf(number,"%d",i);
|
||||
path[0] = '\0';
|
||||
strncat( path, path_begin, strlen(path_begin) );
|
||||
strncat( path, number, strlen(number) );
|
||||
strncat( path, path_end, strlen(path_begin) );
|
||||
|
||||
FILE *file = fopen(path, "r");
|
||||
|
||||
if(file != NULL) {
|
||||
s = (t_sensors *) malloc( sizeof( t_sensors ) );
|
||||
s->path = (char *) malloc(sizeof( char ) * path_size);
|
||||
strcpy(s->path, path);
|
||||
int result = fscanf(file, "%d", &s->temperature);
|
||||
if (sensors_head == NULL) {
|
||||
sensors_head = s;
|
||||
sensors_head->next = NULL;
|
||||
} else {
|
||||
t_sensors *tmp = sensors_head;
|
||||
while (tmp->next != NULL) {
|
||||
tmp = tmp->next;
|
||||
}
|
||||
tmp->next = s;
|
||||
tmp->next->next = NULL;
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
free(path);
|
||||
path = NULL;
|
||||
}
|
||||
if(sensors_head != NULL)
|
||||
find_fans(sensors_head);
|
||||
return sensors_head;
|
||||
}
|
||||
|
||||
t_sensors *refresh_sensors(t_sensors *sensors)
|
||||
{
|
||||
|
||||
t_sensors *tmp = sensors;
|
||||
|
||||
while(tmp != NULL) {
|
||||
FILE *file = fopen(tmp->path, "r");
|
||||
|
||||
if(file != NULL) {
|
||||
int result = fscanf(file, "%d", &tmp->temperature);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return sensors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Controls the speed of the fan */
|
||||
void set_fan_speed(t_sensors* sensors, unsigned short speed)
|
||||
{
|
||||
|
||||
t_sensors *tmp = sensors;
|
||||
|
||||
while(tmp != NULL) {
|
||||
FILE *file = fopen(tmp->path, "rw");
|
||||
|
||||
if(file != NULL) {
|
||||
fprintf(file, "%d", speed);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Returns average CPU temp in degrees (ceiling) */
|
||||
unsigned short get_temp(t_sensors* sensors)
|
||||
{
|
||||
sensors = refresh_sensors(sensors);
|
||||
int sum_temp = 0;
|
||||
unsigned short temp = 0;
|
||||
|
||||
t_sensors* tmp = sensors;
|
||||
while(tmp != NULL) {
|
||||
sum_temp += tmp->temperature;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
temp = (unsigned short)( ceil( (float)( sum_temp ) / 2000. ) );
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned short old_temp, new_temp, fan_speed, steps;
|
||||
short temp_change;
|
||||
float step_up, step_down;
|
||||
|
||||
t_sensors* sensors = find_sensors();
|
||||
|
||||
new_temp = get_temp(sensors);
|
||||
fan_speed = 2000;
|
||||
set_fan_speed(sensors, fan_speed);
|
||||
sleep(polling_interval);
|
||||
|
||||
step_up = (float)( max_fan_speed - min_fan_speed ) /
|
||||
(float)( ( max_temp - high_temp ) * ( max_temp - high_temp + 1 ) / 2 );
|
||||
|
||||
step_down = (float)( max_fan_speed - min_fan_speed ) /
|
||||
(float)( ( max_temp - low_temp ) * ( max_temp - low_temp + 1 ) / 2 );
|
||||
|
||||
while(1) {
|
||||
old_temp = new_temp;
|
||||
new_temp = get_temp(sensors);
|
||||
|
||||
if(new_temp >= max_temp && fan_speed != max_fan_speed) {
|
||||
fan_speed = max_fan_speed;
|
||||
}
|
||||
|
||||
if(new_temp <= low_temp && fan_speed != min_fan_speed) {
|
||||
fan_speed = min_fan_speed;
|
||||
}
|
||||
|
||||
temp_change = new_temp - old_temp;
|
||||
|
||||
if(temp_change > 0 && new_temp > high_temp && new_temp < max_temp) {
|
||||
steps = ( new_temp - high_temp ) * ( new_temp - high_temp + 1 ) / 2;
|
||||
fan_speed = max( fan_speed, ceil(min_fan_speed + steps * step_up) );
|
||||
}
|
||||
|
||||
if(temp_change < 0 && new_temp > low_temp && new_temp < max_temp) {
|
||||
steps = ( max_temp - new_temp ) * ( max_temp - new_temp + 1 ) / 2;
|
||||
fan_speed = min( fan_speed, floor(max_fan_speed - steps * step_down) );
|
||||
}
|
||||
|
||||
set_fan_speed(sensors, fan_speed);
|
||||
sleep(polling_interval);
|
||||
printf("Old Temp %d: New Temp: %d, Fan Speed: %d\n", old_temp, new_temp, fan_speed);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
41
src/mbpfan.h
Normal file
41
src/mbpfan.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/** Basic fan speed parameters
|
||||
*/
|
||||
extern unsigned short min_fan_speed;
|
||||
extern unsigned short max_fan_speed;
|
||||
|
||||
/** Temperature Thresholds
|
||||
* low_temp - temperature below which fan speed will be at minimum
|
||||
* high_temp - fan will increase speed when higher than this temperature
|
||||
* max_temp - fan will run at full speed above this temperature */
|
||||
extern unsigned short low_temp;
|
||||
extern unsigned short high_temp;
|
||||
extern unsigned short max_temp;
|
||||
|
||||
|
||||
/** Temperature polling interval
|
||||
* Default value was 10 (seconds)
|
||||
*/
|
||||
extern unsigned short polling_interval;
|
||||
|
||||
/** Represents a Temperature sensor
|
||||
*/
|
||||
struct s_sensors;
|
||||
typedef struct s_sensors t_sensors;
|
||||
|
||||
/**
|
||||
* Detect the sensors in /sys/devices/platform/coretemp.0/temp
|
||||
* Return a linked list of t_sensors (first temperature detected)
|
||||
*/
|
||||
t_sensors *find_sensors();
|
||||
|
||||
/**
|
||||
* Detect the fans in /sys/devices/platform/applesmc.768/
|
||||
* Associate each fan to a sensor
|
||||
*/
|
||||
void find_fans(t_sensors *sensors);
|
||||
|
||||
/**
|
||||
* Given a linked list of t_sensors, refresh their detected
|
||||
* temperature
|
||||
*/
|
||||
t_sensors *refresh_sensors(t_sensors *sensors);
|
BIN
src/mbpfan.o
Normal file
BIN
src/mbpfan.o
Normal file
Binary file not shown.
Loading…
Add table
Reference in a new issue