diff --git a/AUTHORS b/AUTHORS index 28a96558..8fb7486e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -138,6 +138,7 @@ Pascal Eberhard Peter Tarjan IBM acpi support patch SMP support for freq stuff + CPU voltage patch Petr Holub fix autotools on FreeBSD in autogen.sh diff --git a/ChangeLog b/ChangeLog index 84787192..62fc87a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ # $Id$ +2006-05-23 + * CPU voltage support via $voltage_mv and $voltage_v (thanks to Peter + Tarjan for the patch) + 2006-05-21 * SMP support for $freq and $freq_g (thanks to Peter Tarjan for the patch) diff --git a/README b/README index d66a21cc..d117adeb 100644 --- a/README +++ b/README @@ -561,6 +561,16 @@ VARIABLES omitted, the parameter defaults to 1. + voltage_mv (n) + Returns CPU #n's voltage in mV. CPUs are counted from 1. If + omitted, the parameter defaults to 1. + + + voltage_v (n) + Returns CPU #n's voltage in V. CPUs are counted from 1. If omit- + ted, the parameter defaults to 1. + + freq_dyn Returns CPU frequency in MHz, but is calculated by counting to clock cycles to complete an instruction. Only available for diff --git a/doc/conky.1 b/doc/conky.1 index 5b9a15ee..b4a6f791 100644 --- a/doc/conky.1 +++ b/doc/conky.1 @@ -512,6 +512,18 @@ Returns CPU #n's frequency in GHz. CPUs are counted from 1. If omitted, the parameter defaults to 1. +.TP +\fBvoltage_mv\fR \fB(n)\fR +Returns CPU #n's voltage in mV. CPUs are +counted from 1. If omitted, the parameter +defaults to 1. + +.TP +\fBvoltage_v\fR \fB(n)\fR +Returns CPU #n's voltage in V. CPUs are +counted from 1. If omitted, the parameter +defaults to 1. + .TP \fBfreq_dyn\fR Returns CPU frequency in MHz, but is calculated by counting to clock cycles to complete an instruction. Only available for x86/amd64. diff --git a/doc/variables.xml b/doc/variables.xml index d9abf2aa..2a8122b1 100644 --- a/doc/variables.xml +++ b/doc/variables.xml @@ -385,6 +385,29 @@ + + + + + + + Returns CPU #n's voltage in mV. CPUs are + counted from 1. If omitted, the parameter + defaults to 1. + + + + + + + + + Returns CPU #n's voltage in V. CPUs are + counted from 1. If omitted, the parameter + defaults to 1. + + + diff --git a/src/conky.c b/src/conky.c index 15767b92..006334b6 100644 --- a/src/conky.c +++ b/src/conky.c @@ -873,6 +873,8 @@ enum text_object_type { OBJ_ibm_volume, OBJ_ibm_brightness, OBJ_pb_battery, + OBJ_voltage_mv, + OBJ_voltage_v, #endif /* __linux__ */ OBJ_if_existing, OBJ_if_mounted, @@ -2009,6 +2011,36 @@ static struct text_object *construct_text_object(const char *s, const char *arg, { obj->data.cpu_index=atoi(&arg[0]); } + END OBJ(voltage_mv, 0) + get_cpu_count(); + if (!arg + || !isdigit(arg[0]) + || strlen(arg) >=2 + || atoi(&arg[0])==0 + || (unsigned int)atoi(&arg[0])>info.cpu_count) + { + obj->data.cpu_index=1; + ERR("voltage_mv: Invalid CPU number or you don't have that many CPUs! Displaying voltage for CPU 1."); + } + else + { + obj->data.cpu_index=atoi(&arg[0]); + } + END OBJ(voltage_v, 0) + get_cpu_count(); + if (!arg + || !isdigit(arg[0]) + || strlen(arg) >=2 + || atoi(&arg[0])==0 + || (unsigned int)atoi(&arg[0])>info.cpu_count) + { + obj->data.cpu_index=1; + ERR("voltage_v: Invalid CPU number or you don't have that many CPUs! Displaying voltage for CPU 1."); + } + else + { + obj->data.cpu_index=atoi(&arg[0]); + } #else END OBJ(freq, 0); END OBJ(freq_g, 0); @@ -3128,6 +3160,13 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object * OBJ(freq_g) { get_freq(p, p_max_size, "%'.2f", 1000, obj->data.cpu_index); /* pk */ } + OBJ(voltage_mv) { + get_voltage(p, p_max_size, "%.0f", 1, obj->data.cpu_index); /* ptarjan */ + } + OBJ(voltage_v) { + get_voltage(p, p_max_size, "%'.3f", 1000, obj->data.cpu_index); /* ptarjan */ + } + OBJ(freq_dyn) { if (use_spacer) { get_freq_dynamic(p, 6, "%.0f ", 1 ); /* pk */ diff --git a/src/conky.h b/src/conky.h index a228becc..64959f79 100644 --- a/src/conky.h +++ b/src/conky.h @@ -463,6 +463,7 @@ void update_running_processes(void); void update_i8k(void); void get_freq( char *, size_t, char *, int, unsigned int ); /* pk */ void get_freq_dynamic( char *, size_t, char *, int ); /* pk */ +void get_voltage(char *, size_t, char *, int, unsigned int ); /* ptarjan */ void update_load_average(); int open_i2c_sensor(const char *dev, const char *type, int n, int *div, char *devtype); diff --git a/src/linux.c b/src/linux.c index 9eeb657e..53c93c65 100644 --- a/src/linux.c +++ b/src/linux.c @@ -918,6 +918,84 @@ void get_freq( char * p_client_buffer, size_t client_buffer_size, char * p_forma return; } +#define CPUFREQ_VOLTAGE "cpufreq/scaling_voltages" + +/* return cpu voltage in mV (use divisor=1) or V (use divisor=1000) */ +void get_voltage( char * p_client_buffer, size_t client_buffer_size, char * p_format, int divisor, unsigned int cpu ) +{ +/* /sys/devices/system/cpu/cpu0/cpufreq/scaling_voltages looks + something like this: +# frequency voltage +1800000 1340 +1600000 1292 +1400000 1100 +1200000 988 +1000000 1116 +800000 1004 +600000 988 +*/ + +/* Peter Tarjan (ptarjan@citromail.hu) */ + FILE *f; + char s[256]; + int freq = 0; + int voltage = 0; + char current_freq_file[128]; + int freq_comp = 0; + + +/* build the voltage file name */ + cpu--; + snprintf(current_freq_file, 127, "%s/cpu%d/%s", + CPUFREQ_PREFIX, cpu, CPUFREQ_POSTFIX); + + if ( !p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0 ) + return; + + /* read the current cpu frequency from the /sys node */ + f = fopen(current_freq_file, "r"); + if (f) { + if (fgets(s, sizeof(s), f)) { + s[strlen(s)-1] = '\0'; + freq = strtod(s, NULL); + } + fclose(f); + } + else + { + ERR("voltage: No %s.", current_freq_file); + fclose(f); + return; + } + + snprintf(current_freq_file, 127, "%s/cpu%d/%s", + CPUFREQ_PREFIX, cpu, CPUFREQ_VOLTAGE); + +/* use the current cpu frequency to find the corresponding voltage */ + f = fopen(current_freq_file, "r"); + + if (f) + { + while (!feof(f)) + { + char line[256]; + if (fgets(line, 255, f) == NULL) break; + sscanf(line, "%d %d", &freq_comp, &voltage); + if(freq_comp == freq) break; + } + fclose(f); + } + else + { + ERR("voltage: No %s.", current_freq_file); + fclose(f); + return; + } + + snprintf( p_client_buffer, client_buffer_size, p_format, (float)voltage/divisor ); + return; + +} #define ACPI_FAN_DIR "/proc/acpi/fan/"