diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | argparse.c | 5 | ||||
-rw-r--r-- | cputemp.c | 128 | ||||
-rw-r--r-- | cputemp.h | 12 | ||||
-rw-r--r-- | cputemp2maxfreq.c | 29 | ||||
-rwxr-xr-x | generate_debug_h.sh | 2 |
6 files changed, 173 insertions, 5 deletions
@@ -1,4 +1,4 @@ -cputemp2maxfreq: version.o debug.o sysfs.o cpufreq.o failsafe.o argparse.o logger.o +cputemp2maxfreq: version.o debug.o sysfs.o cpufreq.o failsafe.o argparse.o logger.o cputemp.o version.h: generate_version_h.sh .git/index ./generate_version_h.sh > version.h @@ -20,7 +20,10 @@ void printhelp() " Default: %ld\n" "-g <governor> cpufreq governor to use, use \"keep\" to keep current governor\n" " Default: %s\n" - "-i <file> Input for temperature readout, usually somewhere in sysfs\n" + "-i <sensor> Input for temperature readout, this can be specified as:\n" + " A full path that starts with /, usually somewhere in sysfs\n" + " A sensor name, for example \"Core 0\"\n" + " The word \"auto\" autodetects a valid sensor\n" " Default: %s\n" "-p <time> Poll interval in seconds\n" " Default: %d\n" diff --git a/cputemp.c b/cputemp.c new file mode 100644 index 0000000..559056f --- /dev/null +++ b/cputemp.c @@ -0,0 +1,128 @@ +#include <stdio.h> +#include <sys/types.h> +#include <dirent.h> +#include <string.h> +#include "cputemp2maxfreq.h" +#include "debug.h" +#include "sysfs.h" +#include "cputemp.h" + +extern struct s_config config; + +// Read a single hwmon directory and search for the requested sensor name +void cputemp_read_hwmon(char *hwmon,char *sensor_name,struct s_sensor *sensor) +{ + DIR *hwmon_dir; + struct dirent *hwmon_dirent; + int count; + char buf[255]; + int datalen; + char sysfs_file[255]; + long int testdata; + int offset; + + DEBUG1_CPUTEMP("Searching for sensors in %s\n",hwmon); + + hwmon_dir=opendir(hwmon); + if (hwmon_dir==NULL) + { + DEBUG1_CPUTEMP("Failed to open hwmon dir\n"); + return; + } + + hwmon_dirent=readdir(hwmon_dir); + while((hwmon_dirent!=NULL) && (sensor->valid==0)) + { + DEBUG3_CPUTEMP("%s\n",hwmon_dirent->d_name); + +// We are searching for files named "temp<number>_label" + if (strncmp(hwmon_dirent->d_name,"temp",4)==0) + { + DEBUG3_CPUTEMP("Found temp entry: %s\n",hwmon_dirent->d_name); + offset=0; + for(count=5;count<7;count++) + { + if (hwmon_dirent->d_name[count]=='_') + { + DEBUG3_CPUTEMP("Underscore at %d\n",count); + offset=count+1; + break; + } + } + if (strncmp(hwmon_dirent->d_name+offset,"label",5)==0) + { + DEBUG2_CPUTEMP("Found label %s\n",hwmon_dirent->d_name); + sprintf(sysfs_file,"%s/%s",hwmon,hwmon_dirent->d_name); + +// Read the label to see if it matches what we're looking for + datalen=sysfs_read_str(sysfs_file,buf,sizeof(buf)); + if (datalen<0) + { + DEBUG2_CPUTEMP("Failed to read label\n"); + } else { + DEBUG1_CPUTEMP("Label is: %s\n",buf); + if (strncasecmp(buf,sensor_name,255)==0) + { + DEBUG2_CPUTEMP("Label machtes our search criteria\n"); + offset=strlen(sysfs_file)-5; + strncpy(sysfs_file+offset,"input",5); + DEBUG1_CPUTEMP("Input filename: %s\n",sysfs_file); + +// Validate the sensor by reading it + testdata=sysfs_read_long_int(sysfs_file); + DEBUG2_CPUTEMP("Input value: %ld\n",testdata); + if ((testdata>=VALID_TEMP_MIN) && (testdata<=VALID_TEMP_MAX)) + { + DEBUG1_CPUTEMP("Input data is valid, marking sensor as valid\n"); + sensor->valid=1; + strncpy(sensor->name,buf,sizeof(buf)); + strncpy(sensor->filename,sysfs_file,sizeof(sysfs_file)); + } else { + DEBUG1_CPUTEMP("Input data is invalid, ignoring sensor\n"); + } + } + } + } + } + hwmon_dirent=readdir(hwmon_dir); + } + closedir(hwmon_dir); +} + +// Find all entries under /sys/class/hwmon and check them with +// cputemp_read_hwmon +void cputemp_find_sensor(char *sensor_name,struct s_sensor *sensor) +{ + DIR *hwmon_dir; + struct dirent *hwmon_dirent; + char subdir[255]; + + DEBUG1_CPUTEMP("Searching for sensor %s\n",sensor_name); + +// Mark sensor data as invalid, it will be set valid if we find something + sensor->valid=0; + + hwmon_dir=opendir("/sys/class/hwmon"); + if (hwmon_dir==NULL) + { + DEBUG1_CPUTEMP("Failed to open /sys/class/hwmon, is sysfs mounted?\n"); + return; + } + + hwmon_dirent=readdir(hwmon_dir); + while((hwmon_dirent!=NULL) && (sensor->valid==0)) + { + DEBUG3_CPUTEMP("Found file: %s\n",hwmon_dirent->d_name); + +// If the name starts with hwmon try to read it +// Note that /sys/class/hwmon actually contains symlinks but we treat them like directories + if (strncmp(hwmon_dirent->d_name,"hwmon",5)==0) + { + sprintf(subdir,"/sys/class/hwmon/%s",hwmon_dirent->d_name); + DEBUG2_CPUTEMP("Found hwmon entry: %s\n",subdir); + cputemp_read_hwmon(subdir,sensor_name,sensor); + } + hwmon_dirent=readdir(hwmon_dir); + } + closedir(hwmon_dir); +} diff --git a/cputemp.h b/cputemp.h new file mode 100644 index 0000000..8cd39d5 --- /dev/null +++ b/cputemp.h @@ -0,0 +1,12 @@ +#ifndef HAVE_CPUTEMP_H +#define HAVE_CPUTEMP_H + +struct s_sensor { + char name[255]; + char filename[255]; + char valid; +}; + +void cputemp_find_sensor(char *sensor_name,struct s_sensor *sensor); + +#endif diff --git a/cputemp2maxfreq.c b/cputemp2maxfreq.c index 47b1f53..d3242b6 100644 --- a/cputemp2maxfreq.c +++ b/cputemp2maxfreq.c @@ -12,13 +12,14 @@ #include "version.h" #include "argparse.h" #include "logger.h" +#include "cputemp.h" // Set default config struct s_config config={ "", // Name of this program, set by argparse "conservative", // Governor 70000, // Temperature - "/sys/devices/virtual/thermal/thermal_zone0/temp", // Temperature input + "auto", // Temperature input 100000, // Frequency step 2000000, // Fallback frequency 10, // Interval @@ -49,7 +50,7 @@ int main(int argc,char **argv) { long int diff; long int newfreq; - + struct s_sensor sensor; char *transition_latency_remark; argparse(argc,argv); @@ -98,6 +99,30 @@ int main(int argc,char **argv) exit(1); } +// Autodetect temperature input if needed + if (config.temp_input[0]!='/') + { + if (strcmp(config.temp_input,"auto")==0) + { + DEBUG1_MAIN("Starting temperature sensor detection with name \"Package id 0\"\n"); + cputemp_find_sensor("Package id 0",&sensor); + } else { + DEBUG1_MAIN("Starting temperature sensor detection with name \"%s\"\n",config.temp_input); + cputemp_find_sensor(config.temp_input,&sensor); + } + if (sensor.valid==1) + { + DEBUG1_MAIN("Found sensor \"%s\"\n",sensor.name); + DEBUG1_MAIN("Sensor file: %s\n",sensor.filename); + strncpy(config.temp_input,sensor.filename,sizeof(config.temp_input)); + config.logger("Detection returned temperature input: %s",config.temp_input); + config.logger("Temperature input name: %s",sensor.name); + } else { + config.logger("Detection failed to return a valid sensor, set it using -i"); + exit(1); + } + } + // Get and validate CPU data cpudata.min_freq=sysfs_read_long_int("/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_min_freq"); cpudata.max_freq=sysfs_read_long_int("/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_max_freq"); diff --git a/generate_debug_h.sh b/generate_debug_h.sh index 209495c..4049af9 100755 --- a/generate_debug_h.sh +++ b/generate_debug_h.sh @@ -5,7 +5,7 @@ # Configuration DEBUG_LEVELS=4 -DEBUG_PARTS="MAIN ARGPARSE SYSFS CPUFREQ LOG" +DEBUG_PARTS="MAIN ARGPARSE SYSFS CPUFREQ LOG CPUTEMP" DEBUG_HELPER_DEF=`grep -o "void .*()" debug.c | head -n 1` DEBUG_HELPER=${DEBUG_HELPER_DEF##* } HEXDUMP_HELPER_DEF=`grep -o "void .*(unsigned char \*data,int len)" debug.c` |