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.
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
* 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 Instructions
@ -40,8 +40,8 @@ GNU General Public License version 3
Based On
---------------------
http://allanmcrae.com/2010/05/simple-macbook-pro-fan-daemon/
http://allanmcrae.com/2011/08/mbp-fan-daemon-update/
https://launchpad.net/macfanctld
http://paste2.org/p/862259
http://www.lobotomo.com/products/FanControl/
* http://allanmcrae.com/2010/05/simple-macbook-pro-fan-daemon/
* http://allanmcrae.com/2011/08/mbp-fan-daemon-update/
* https://launchpad.net/macfanctld
* http://paste2.org/p/862259
* 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 <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <syslog.h>
#include "mbpfan.h"
#include "global.h"
/* lazy min/max... */
#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;
@ -130,14 +132,15 @@ void find_fans(t_sensors* sensors)
char number[1];
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[0] = '\0';
path_man = (char*) malloc(sizeof( char ) * path_man_size);
path_man[0] = '\0';
sprintf(number,"%d",counter);
sprintf(number,"%d",n_sensors);
strncat( path_min, path_begin, strlen(path_begin) );
strncat( path_min, number, strlen(number) );
@ -151,17 +154,25 @@ void find_fans(t_sensors* sensors)
FILE *file = fopen(path_min, "r");
if(file != NULL) {
if (tmp->path != NULL){
tmp->fan_min_path = (char *) malloc(sizeof( char ) * path_min_size);
tmp->fan_man_path = (char *) malloc(sizeof( char ) * path_man_size);
if (tmp->path != NULL) {
tmp->fan_min_path = (char *) malloc(sizeof( char ) * path_min_size);
tmp->fan_man_path = (char *) malloc(sizeof( char ) * path_man_size);
}
strcpy(tmp->fan_min_path, path_min);
strcpy(tmp->fan_man_path, path_man);
tmp = tmp->next;
n_fans++;
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);
path_min = NULL;
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 temp_change;
int step_up, step_down;
t_sensors* sensors = find_sensors();
t_sensors* sensors = retrieve_sensors();
set_fans_man(sensors);
new_temp = get_temp(sensors);
fan_speed = 2000;
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);
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) );
}
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);
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);
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 max_temp;
/** Temperature polling interval
* 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
* 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
@ -44,4 +43,9 @@ void find_fans(t_sensors *sensors);
* Given a list of sensors with associated fans
* Set them to manual control
*/
void set_fans_man(t_sensors *sensors);
void set_fans_man(t_sensors *sensors);
/**
* Main Program
*/
void mbpfan();