This commit is contained in:
Daniel Graziotin 2012-06-11 21:43:53 +02:00
parent a179c7dc73
commit cd3c15ba9d
8 changed files with 327 additions and 25 deletions

View file

@ -10,9 +10,9 @@ which itself is an enhanced version of [Allan McRae mbpfan](http://allanmcrae.co
Fan-Control-Daemon is a daemon that uses input from coretemp module and sets the fan speed using the applesmc module. 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). This enhanced version assumes any number of processors and fans (max. 10).
* It only uses the temperatures from the processors as input. * It only uses the temperatures from the processors as input.
* It requires coretemp and applesmc kernel modules to be loaded. * It requires coretemp and applesmc kernel modules to be loaded.
* It requires root use * It requires root use
Compile Instructions Compile Instructions
@ -40,8 +40,8 @@ GNU General Public License version 3
Based On Based On
--------------------- ---------------------
http://allanmcrae.com/2010/05/simple-macbook-pro-fan-daemon/ * http://allanmcrae.com/2010/05/simple-macbook-pro-fan-daemon/
http://allanmcrae.com/2011/08/mbp-fan-daemon-update/ * http://allanmcrae.com/2011/08/mbp-fan-daemon-update/
https://launchpad.net/macfanctld * https://launchpad.net/macfanctld
http://paste2.org/p/862259 * http://paste2.org/p/862259
http://www.lobotomo.com/products/FanControl/ * http://www.lobotomo.com/products/FanControl/

103
mbpfan.init Executable file
View file

@ -0,0 +1,103 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: mbpfan
# Required-Start: $remote_fs
# Required-Stop: $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: mbpfan initscript
# Description: Start the mbpfan daemon
### END INIT INFO
DESC="Start the mbpfan daemon"
NAME=mbpfan
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DAEMON=/usr/sbin/$NAME
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
DAEMON_ARGS=""
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
# Function that starts the daemon/service
do_start()
{
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
}
# Function that stops the daemon/service
do_stop()
{
# Return
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
return "$RETVAL"
}
# Function that sends a SIGHUP to the daemon/service
do_reload()
{
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
return 0
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac
:

106
src/daemon.c Normal file
View file

@ -0,0 +1,106 @@
/**
* Credits: http://peterlombardo.wikidot.com/linux-daemon-in-c
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <syslog.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <unistd.h>
#include "mbpfan.h"
#include "global.h"
#define DAEMON_NAME "mbpfan"
#define PID_FILE "/var/run/mbpfan.pid"
void signal_handler(int signal)
{
switch(signal) {
case SIGHUP:
//TODO: restart myself
syslog(LOG_WARNING, "Received SIGHUP signal.");
exit(0);
break;
case SIGTERM:
syslog(LOG_WARNING, "Received SIGTERM signal.");
//TODO: free resources
exit(0);
break;
case SIGINT:
syslog(LOG_WARNING, "Received SIGINT signal.");
//TODO: free resources
exit(0);
default:
syslog(LOG_WARNING, "Unhandled signal (%d) %s", signal, strsignal(signal));
break;
}
}
void go_daemon(void (*function)())
{
// Setup signal handling before we start
signal(SIGHUP, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
syslog(LOG_INFO, "%s starting up", DAEMON_NAME);
// Setup syslog logging - see SETLOGMASK(3)
if(verbose) {
setlogmask(LOG_UPTO(LOG_DEBUG));
openlog(DAEMON_NAME, LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
} else {
setlogmask(LOG_UPTO(LOG_INFO));
openlog(DAEMON_NAME, LOG_CONS, LOG_USER);
}
pid_t pid;
pid_t sid;
if (daemonize) {
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
if (pid > 0) {
exit(EXIT_SUCCESS);
}
umask(0);
// new SID for the child process
sid = setsid();
if (sid < 0) {
exit(EXIT_FAILURE);
}
if ((chdir("/")) < 0) {
exit(EXIT_FAILURE);
}
/* Close out the standard file descriptors */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
function();
if(daemonize)
syslog(LOG_INFO, "%s daemon exiting", DAEMON_NAME);
return;
}

9
src/daemon.h Normal file
View file

@ -0,0 +1,9 @@
/**
* ...handles signals :-)
*/
void signal_handler(int signal);
/**
* Daemonizes
*/
int go_daemon(void (*function)());

2
src/global.h Normal file
View file

@ -0,0 +1,2 @@
extern int daemonize;
extern int verbose;

50
src/main.c Normal file
View file

@ -0,0 +1,50 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "mbpfan.h"
#include "daemon.h"
#include "global.h"
int daemonize = 1;
int verbose = 0;
void print_usage(int argc, char *argv[])
{
if (argc >=1) {
printf("Usage: %s OPTION(S) \n", argv[0]);
printf("Options:\n");
printf("\t-h Show this help screen\n");
printf("\t-f Run in foreground\n");
printf("\t-v Be (a lot) verbose\n");
printf("\n");
}
}
int main(int argc, char *argv[])
{
int c;
while( (c = getopt(argc, argv, "hfv|help")) != -1) {
switch(c) {
case 'h':
print_usage(argc, argv);
exit(0);
break;
case 'f':
daemonize = 0;
break;
case 'v':
verbose = 1;
break;
default:
print_usage(argc, argv);
exit(0);
break;
}
}
// pointer to mbpfan() function in mbpfan.c
void (*function)() = mbpfan;
go_daemon(function);
exit(0);
}

View file

@ -28,12 +28,14 @@
*/ */
#include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <math.h>
#include <syslog.h>
#include "mbpfan.h" #include "mbpfan.h"
#include "global.h"
/* lazy min/max... */ /* lazy min/max... */
#define min(a,b) a < b ? a : b #define min(a,b) a < b ? a : b
@ -62,7 +64,7 @@ struct s_sensors {
}; };
t_sensors *find_sensors() t_sensors *retrieve_sensors()
{ {
t_sensors *sensors_head = NULL; t_sensors *sensors_head = NULL;
@ -130,14 +132,15 @@ void find_fans(t_sensors* sensors)
char number[1]; char number[1];
sprintf(number,"%d",0); sprintf(number,"%d",0);
int counter = 0; int n_sensors = 0;
int n_fans = 0;
for(counter = 0; counter<10; counter++) { for(n_sensors = 0; n_sensors<10; n_sensors++) {
path_min = (char*) malloc(sizeof( char ) * path_min_size); path_min = (char*) malloc(sizeof( char ) * path_min_size);
path_min[0] = '\0'; path_min[0] = '\0';
path_man = (char*) malloc(sizeof( char ) * path_man_size); path_man = (char*) malloc(sizeof( char ) * path_man_size);
path_man[0] = '\0'; path_man[0] = '\0';
sprintf(number,"%d",counter); sprintf(number,"%d",n_sensors);
strncat( path_min, path_begin, strlen(path_begin) ); strncat( path_min, path_begin, strlen(path_begin) );
strncat( path_min, number, strlen(number) ); strncat( path_min, number, strlen(number) );
@ -151,17 +154,25 @@ void find_fans(t_sensors* sensors)
FILE *file = fopen(path_min, "r"); FILE *file = fopen(path_min, "r");
if(file != NULL) { if(file != NULL) {
if (tmp->path != NULL){ if (tmp->path != NULL) {
tmp->fan_min_path = (char *) malloc(sizeof( char ) * path_min_size); tmp->fan_min_path = (char *) malloc(sizeof( char ) * path_min_size);
tmp->fan_man_path = (char *) malloc(sizeof( char ) * path_man_size); tmp->fan_man_path = (char *) malloc(sizeof( char ) * path_man_size);
} }
strcpy(tmp->fan_min_path, path_min); strcpy(tmp->fan_min_path, path_min);
strcpy(tmp->fan_man_path, path_man); strcpy(tmp->fan_man_path, path_man);
tmp = tmp->next; tmp = tmp->next;
n_fans++;
fclose(file); fclose(file);
} }
} }
if(verbose) {
printf("Found %d: sensors and %d fans\n", n_sensors, n_fans);
if(daemonize) {
syslog(LOG_INFO, "Found %d: sensors and %d fans", n_sensors, n_fans);
}
}
free(path_min); free(path_min);
path_min = NULL; path_min = NULL;
free(path_man); free(path_man);
@ -239,17 +250,24 @@ unsigned short get_temp(t_sensors* sensors)
} }
int main() void mbpfan()
{ {
int old_temp, new_temp, fan_speed, steps; int old_temp, new_temp, fan_speed, steps;
int temp_change; int temp_change;
int step_up, step_down; int step_up, step_down;
t_sensors* sensors = find_sensors(); t_sensors* sensors = retrieve_sensors();
set_fans_man(sensors); set_fans_man(sensors);
new_temp = get_temp(sensors); new_temp = get_temp(sensors);
fan_speed = 2000; fan_speed = 2000;
set_fan_speed(sensors, fan_speed); set_fan_speed(sensors, fan_speed);
if(verbose) {
printf("Sleeping for %d seconds\n", polling_interval);
if(daemonize) {
syslog(LOG_INFO, "Sleeping for %d seconds\n", polling_interval);
}
}
sleep(polling_interval); sleep(polling_interval);
step_up = (float)( max_fan_speed - min_fan_speed ) / step_up = (float)( max_fan_speed - min_fan_speed ) /
@ -282,11 +300,21 @@ int main()
fan_speed = min( fan_speed, floor(max_fan_speed - steps * step_down) ); fan_speed = min( fan_speed, floor(max_fan_speed - steps * step_down) );
} }
if(verbose) {
printf("Old Temp %d: New Temp: %d, Fan Speed: %d\n", old_temp, new_temp, fan_speed);
if(daemonize) {
syslog(LOG_INFO, "Old Temp %d: New Temp: %d, Fan Speed: %d\n", old_temp, new_temp, fan_speed);
}
}
set_fan_speed(sensors, fan_speed); set_fan_speed(sensors, fan_speed);
if(verbose) {
printf("Sleeping for %d seconds\n", polling_interval);
if(daemonize) {
syslog(LOG_INFO, "Sleeping for %d seconds\n", polling_interval);
}
}
sleep(polling_interval); sleep(polling_interval);
printf("Old Temp %d: New Temp: %d, Fan Speed: %d\n", old_temp, new_temp, fan_speed);
} }
return 0;
} }

View file

@ -11,7 +11,6 @@ extern int low_temp;
extern int high_temp; extern int high_temp;
extern int max_temp; extern int max_temp;
/** Temperature polling interval /** Temperature polling interval
* Default value was 10 (seconds) * Default value was 10 (seconds)
*/ */
@ -26,7 +25,7 @@ typedef struct s_sensors t_sensors;
* Detect the sensors in /sys/devices/platform/coretemp.0/temp * Detect the sensors in /sys/devices/platform/coretemp.0/temp
* Return a linked list of t_sensors (first temperature detected) * Return a linked list of t_sensors (first temperature detected)
*/ */
t_sensors *find_sensors(); t_sensors *retrieve_sensors();
/** /**
* Given a linked list of t_sensors, refresh their detected * Given a linked list of t_sensors, refresh their detected
@ -44,4 +43,9 @@ void find_fans(t_sensors *sensors);
* Given a list of sensors with associated fans * Given a list of sensors with associated fans
* Set them to manual control * Set them to manual control
*/ */
void set_fans_man(t_sensors *sensors); void set_fans_man(t_sensors *sensors);
/**
* Main Program
*/
void mbpfan();