Hello
I writhed for my fun a fancontrol in C. Currently is do only managing
speed fan and detect startup value and stop value for fans (for example,
my cpu fan is stoping at 18 and start at value 30 set in pwm file).
In the future I want to implement:
- control fan reading hdd temp (currently is using only fans that are
visible in /sys/class/hwmon/*)
- detect fan controlers
- detect GPU temp (this is a plan for far far away time)
- save settings in files
- use multiple temp sensors (for example, use mb sensors...for normal
operations, but if CPU temp si jumping a trigger value...speed all case
fans - usefull if cpu heat sink is good, but you need and a good airflow
in case)
- a nice gui for fans/sensors (this is a plan to start in
october-november...)
If lm-sensors team are interested about this, please announce me. To
know if is worth to make some cosmetics for apps etc.
The current code is working almost...without erros.
I attached a older version (currently, the new version is not on my
laptop..)
Ioan Rusan
#include "main.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char **argv){
char *config_file;
int i;
int autoload = 0;
int autodetect = 0;
int ii = 0;
config_file = NULL;
if(argc < 2){
printf("Usage: fanmanager --config full_path_to_config_file\n");
exit(-1);
}
for(i = 0; i < argc; i++){
if(strstr(argv[i], "--config") != 0)
config_file = argv[i+1];
if(strstr(argv[i], "--autoload") != 0)
autoload = atoi(argv[i+1]);
if(strstr(argv[i], "--autodetect") != 0)
autodetect = 1;
if(strstr(argv[i], "--detect_startup") !=0)
autodetect = 2;
}
if(config_file == NULL){
printf("There are no config file!\n");
exit(0);
}
if(load_fan_settings(config_file) !=0){
printf("Error loading config file");
exit(0);
}
printf("Enable fan control for %d fans...\n", number_of_fans);
enable_fan_control();
if(autodetect == 1){
autodetect_fan_range();
exit(0);
}
if(autodetect == 2){
detect_startup_value();
exit(0);
}
for(;;){
system("clear");
if(autoload !=0){
ii++;
if(ii == autoload){
load_fan_settings(config_file);
ii = 0;
}
}
for(i = 0; i <= number_of_fans; i++){
load_fan_status(i);
}
calc_fan_speed();
for(i = 0; i <= number_of_fans; i++){
printf("Temp: %d, min_speed: %d, start_speed: %d, max_temp = %d, current_fan_speed %d, current_fan_rpm %d, \noutput_fan_speed %s, input_temp_sensor %s, input_fan_speed %s\n", fan[i].current_temp, fan[i].min_speed, fan[i].start_temp, fan[i].max_temp, fan[i].current_fan_speed, fan[i].fan_rpm, fan[i].output_fan_speed, fan[i].input_temp_sensor, fan[i].input_fan_speed);
}
for(i = 0; i <= number_of_fans; i++)
set_fan_speed(i);
usleep(300000);
}
return 0;
}
int autodetect_fan_range(){
int i;
int found = 0;
int half, last_min, min;
for (i = 0; number_of_fans >= i; i++){
last_min = 255;
fan[i].current_fan_speed = 255;
fan[i].min_speed = 255;
set_fan_speed(i);
printf("SpeedUp fan %d\n", i);
sleep(5);
min = 255;
do{
fan[i].current_fan_speed--;
if(set_fan_speed(i) != 0){
printf("Error setting new speed\n");
break;
}
sleep(1);
load_fan_status(i);
printf("rpm: %d, fan_speed %d\n", fan[i].fan_rpm, fan[i].current_fan_speed);
if(fan[i].fan_rpm == 0){
found = 1;
fan[i].min_speed = fan[i].current_fan_speed+1;
}else
found = 0;
}while(found == 0);
}
}
int detect_startup_value(){
int i,ii;
for(i = 0; number_of_fans >= i; i++){
fan[i].current_fan_speed = 0;
set_fan_speed(i);
printf("Wait for fans to stop");
sleep(5);
for(ii = 0; ii < 255; ii++){
printf("rpm: %d, fan_speed %d\n", fan[i].fan_rpm, fan[i].current_fan_speed);
fan[i].current_fan_speed = ii;
set_fan_speed(i);
sleep(1);
load_fan_status(i);
if(fan[i].fan_rpm > 0){
fan[i].min_speed = ii;
printf("Fan %d is starting at value %d", i, ii);
ii = 255;
}
}
}
}
int enable_fan_control(){
FILE *fp;
char *file_name, *int_point;
int i;
file_name = (char *) malloc(1024);
printf("%d\n", number_of_fans);
for(i = 0; number_of_fans >= i; i++){
memcpy(file_name, fan[i].output_fan_speed, strlen(fan[i].output_fan_speed));
int_point = file_name+strlen(fan[i].output_fan_speed);
memcpy(int_point, "_enable", 8);
printf("Enable for %s\n", file_name);
fp = fopen(file_name, "w");
if(fp == NULL){
printf("Enable fan %d failed\n", i);
}
fwrite("1", 1, 1, fp);
fclose(fp);
}
free(file_name);
return 0;
}
char *extract_value(char *string){
char *buffer;
char *buffer1;
char *val;
int first = 0;
buffer1 = (char *) malloc(1024);
buffer = (char *) malloc(1024);
memcpy(buffer1, string, 1023);
strtok(buffer1, "=");
while (buffer != NULL){
val = strtok(NULL, "=");
if(strlen(val) < 1023)
memcpy(buffer, val, strlen(val));
else
memcpy(buffer, val, 1023);
free(buffer1);
return buffer;
}
free(buffer1);
}
int load_fan_settings(char *file_config){
FILE *fp;
char *line;
char *buffer;
int fan_number = 0;
int check = 7;
fp = fopen(file_config, "r");
line = (char *) malloc(1024);
number_of_fans = -1;
while(!feof(fp)){
memset(line, 0, 1023);
fgets(line, 1023, fp);
buffer = extract_value(line);
if(strstr(line, "SENSOR=") != 0){
if(check < 7){
prinf("configuration file with erros for sensor %d", number_of_fans);
exit(-1);
}
check = 7;
number_of_fans++;
fan_number = (atoi(buffer)-1);
if(fan_number < 0)
exit(-2);
if(number_of_fans > 0)
fan = (fans *) realloc(fan, (number_of_fans + 1) * sizeof(fans));
else
fan = (fans *) calloc((number_of_fans + 1), sizeof(fans));
fan[fan_number].fan_id = fan_number;
}
fan[fan_number].max_temp = 50;
fan[fan_number].min_temp = 30;
fan[fan_number].min_speed = 255;
if(strstr(line, "MAX_TEMP") != NULL){
if(atoi(buffer) < 255){
fan[fan_number].max_temp = atoi(buffer);
check++;
}else{
printf("for MAX_TEMP range is 0 to 255\n");
exit(-1);
}
}
if(strstr(line, "MIN_TEMP") != NULL){
if(atoi(buffer) < 255){
fan[fan_number].start_temp = atoi(buffer);
check++;
}else{
printf("for MIN_TEMP range is 0 to 255\n");
exit(-1);
}
}
if(strstr(line, "MIN_SPEED") != NULL){
if(atoi(buffer) < 255){
fan[fan_number].min_speed = atoi(buffer);
check++;
}else{
printf("for MIN_SPEED range is 0 to 255\n");
exit(-1);
}
}
if(strstr(line, "TEMP_INPUT") != NULL){
memcpy(fan[fan_number].input_temp_sensor, buffer, strlen(buffer) - 1);
check++;
}
if(strstr(line, "OUTPUT_FAN") != NULL){
memcpy(fan[fan_number].output_fan_speed, buffer, strlen(buffer) - 1);
check++;
}
if(strstr(line, "INPUT_FAN") != NULL){
memcpy(fan[fan_number].input_fan_speed, buffer, strlen(buffer) - 1);
check++;
}
if(strstr(line, "LINIAR_FAN") != NULL){
fan[fan_number].liniar_fan = atoi(buffer);
check++;
}
}
if(check < 7){
printf("error in config file\n");
exit(-1);
}
free(line);
return 0;
}
int set_fan_speed(int fan_number){
FILE *fp;
char *mem_zone;
mem_zone = (char *) calloc(255, 1);
sprintf(mem_zone, "%d", fan[fan_number].current_fan_speed);
fp = fopen(fan[fan_number].output_fan_speed, "w");
if(fp != NULL)
fwrite(mem_zone, sizeof(mem_zone), 1, fp);
else{
printf("Error opening fan device %s \n",fan[fan_number].output_fan_speed);
return -1;
}
fclose(fp);
return 0;
}
int load_fan_status(int fan_number){
FILE *fp;
char *buffer;
buffer = (char *) calloc(32,1);
fp = fopen(fan[fan_number].output_fan_speed, "r");
if(fp == NULL){
printf("Error opening %s\n", fan[fan_number].output_fan_speed);
}else{
fscanf(fp, "%s", buffer);
fan[fan_number].current_fan_speed = atoi(buffer);
fclose(fp);
}
fp = fopen(fan[fan_number].input_temp_sensor, "r");
if(fp == NULL){
printf("Error opening %s\n", fan[fan_number].input_temp_sensor);
}else{
memset(buffer, 0, 31);
fscanf(fp, "%s", buffer);
if((atoi(buffer)/1000) < 255)
fan[fan_number].current_temp = (atoi(buffer)/1000);
else
fan[fan_number].current_temp = 255;
fclose(fp);
}
fp = fopen(fan[fan_number].input_fan_speed, "r");
if(fp == NULL){
printf("Error opening %s\n", fan[fan_number].input_fan_speed);
}else{
memset(buffer, 0, 31);
fscanf(fp, "%s", buffer);
if((atoi(buffer) < 65355))
fan[fan_number].fan_rpm = atoi(buffer);
else
fan[fan_number].fan_rpm = 65355;
fclose(fp);
}
free(buffer);
if(fp == NULL)
return -1;
return 0;
}
int full_speed(){
return 0;
}
int calc_fan_speed(){
unsigned int i = 0;
unsigned int diviziune, temp_diff, current_need_speed;
for(i = 0; i <= number_of_fans; i++){
if(fan[i].current_temp >= fan[i].max_temp){
fan[i].current_fan_speed = 255;
}else{
temp_diff = fan[i].max_temp - fan[i].start_temp;
if((temp_diff < 0) || (temp_diff > 255) || (fan[i].min_speed < 0))
diviziune = 1;
else
diviziune = (255 - fan[i].min_speed)/temp_diff;
if(fan[i].current_temp >= fan[i].start_temp)
current_need_speed = (fan[i].current_temp - fan[i].start_temp) * diviziune;
else
current_need_speed = 0;
if((current_need_speed > 255) || (current_need_speed < 0))
current_need_speed = 255;
printf("diviziune: %d, current_need_speed %d\n", diviziune, current_need_speed);
if(current_need_speed < fan[i].min_speed)
fan[i].current_fan_speed = fan[i].min_speed;
else{
if(fan[i].liniar_fan == 0){
fan[i].current_fan_speed = current_need_speed * current_need_speed;
}else
fan[i].current_fan_speed = current_need_speed;
}
}
}
return 0;
}
typedef struct fans{
int fan_id;
char input_temp_sensor[255];
char input_fan_speed[255];
char output_fan_speed[255];
unsigned char current_fan_speed;
unsigned int fan_rpm;
int current_temp;
unsigned int min_speed;
int start_temp;
int max_temp;
char liniar_fan;
char intermediar_step;
}fans;
fans *fan;
int number_of_fans;
int load_fan_settings(char *file_config);
int load_fan_status(int fan_number);
int set_fan_speed(int fan_number);
int full_speed();
int calc_fan_speed();
int get_value_setting(char *source, char *store);
char *extract_value(char *string);
int autodetect_range();
int detect_startup_value();
int enable_fan_control();
_______________________________________________
lm-sensors mailing list
lm-sensors@xxxxxxxxxxxxxx
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors