Group :: System/Kernel and hardware
RPM: hardinfo
Main Changelog Spec Patches Sources Download Gear Bugs and FR Repocop
Patch: 05-fix-sensors-output.patch
Download
Download
--- a/arch/linux/common/sensors.h 2009-04-06 17:43:15.000000000 +0400
+++ b/arch/linux/common/sensors.h 2013-09-16 23:57:42.000000000 +0400
@@ -15,242 +15,457 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
+#include <ctype.h>
static gchar *sensors = NULL;
-static GHashTable *sensor_labels = NULL;
-static GHashTable *sensor_compute = NULL;
+// structure to hold an individual sensor entry
+struct sensor_entry
+ {
+ gchar *driver;
+ gchar *raw_name;
+ gchar *label;
+ gchar *cooked_name;
+ gchar *compute_string;
+ int ignore_flag;
+ float raw_value;
+ float cooked_value;
+ struct sensor_entry *next;
+ };
+static void remove_lf(gchar *p)
+ {
+ while(*p)
+ {
+ if(*p=='\n')
+ *p=0;
+ p++;
+ }
+ }
+static struct sensor_entry *first_sensor=NULL;
+/* given a driver to match, return it if matched or null if not exists */
+static gchar *sensor_driver_matched(gchar* driver)
+ {
+ struct sensor_entry *p;
+ for(p=first_sensor;p;p=p->next) // walk through list.
+ {
+ if (g_str_has_prefix(driver,p->driver)) // if this driver matches one in the list
+ return (p->driver);
+ }
+ return (gchar *) 0; //reached end no match.
+ }
+static struct sensor_entry *find_sensor_entry(gchar *driver,gchar *raw_name)
+ {
+ struct sensor_entry *p;
+ for(p=first_sensor;p;p=p->next) // walk through list.
+ {
+ if(strcmp(driver, p->driver) || strcmp(raw_name,p->raw_name)) // no match
+ continue;
+ else return (p); // found it!!
+ }
+ return ((struct sensor_entry *)0);
+ }
+static void add_sensor_entry(gchar *driver, gchar *raw_name, gchar *label, float raw_value)
+ {
+ struct sensor_entry *p,*new;
+ if(!first_sensor) // first entry
+ {
+ new=first_sensor=g_malloc(sizeof(struct sensor_entry));
+ new->driver=g_strdup(driver);
+ new->raw_name=g_strdup(raw_name);
+ if(label)
+ new->label=g_strdup(label);
+ else new->label=(gchar *)0;
+ new->raw_value=raw_value;
+ // next values null..filled in later after parsing sensors3.conf.
+ new->ignore_flag=0;
+ new->cooked_name=(gchar *)0;
+ new->compute_string=(gchar *)0;
+ new->cooked_value=0.0;
+ new->next = (struct sensor_entry *) 0;
+ return;
+ }
+ // otherwise scan to the end..
+ for(p=first_sensor;p;p=p->next) // walk through list.
+ {
+ if(!(p->next)) //last entry
+ {
+ new=g_malloc(sizeof(struct sensor_entry));
+ p->next=new;
+ new->driver=g_strdup(driver);
+ new->raw_name=g_strdup(raw_name);
+ if(label)
+ new->label=g_strdup(label);
+ else new->label=(gchar *)0;
+ new->raw_value=raw_value;
+ // next values null..filled in later after parsing sensors3.conf.
+ new->ignore_flag=0;
+ new->cooked_name=(gchar *)0;
+ new->compute_string=(gchar *)0;
+ new->cooked_value=0.0;
+ new->next = (struct sensor_entry *) 0;
+ return;
+ }
+ }
+ }
+static void free_sensor_entry(struct sensor_entry *p)
+ {
+ if(!p)
+ return; // dont free blanks!
+ // clear all g_malloced strings
+ if(p->driver) g_free(p->driver);
+ if(p->raw_name) g_free(p->raw_name);
+ if(p->label) g_free(p->label);
+ if(p->cooked_name) g_free(p->cooked_name);
+ if(p->compute_string) g_free(p->compute_string);
+ //free up the structure itself
+ g_free(p);
+ }
+static void free_all_sensor_entries()
+ {
+ struct sensor_entry *p,*next;
+ for(p=first_sensor;p;) // walk through list.
+ {
+ next=p->next;
+ free_sensor_entry(p);
+ p=next;
+ }
+ first_sensor=(struct sensor_entry *) 0;
+ }
+static void update_sensor_entry_name(gchar*driver, gchar *raw_name, gchar *cooked_name)
+ {
+ struct sensor_entry *p;
+ if((p=find_sensor_entry(driver,raw_name)))
+ {
+ p->cooked_name=g_strdup(cooked_name);
+ }
+ }
+static void ignore_sensor_entry(gchar*driver, gchar *raw_name)
+ {
+ struct sensor_entry *p;
+ if((p=find_sensor_entry(driver,raw_name)))
+ {
+ p->ignore_flag=1;
+ }
+ }
-static void read_sensor_labels(gchar * driver)
-{
- FILE *conf;
- gchar buf[256], *line, *p;
- gboolean lock = FALSE;
+static void update_sensor_entry_compute_string(gchar *driver, gchar *raw_name, gchar* compute_string)
+ {
+ struct sensor_entry *p;
+ if((p=find_sensor_entry(driver,raw_name)))
+ {
+ p->compute_string=g_strdup(compute_string);
+ p->cooked_value=math_postfix_eval(math_string_to_postfix(compute_string),p->raw_value);
+ }
+ }
+/**************************************************************************************
+ * This scans the linked list and outputs the relevant values to the sensors string *
+ **************************************************************************************/
+static void print_sensors (void)
+ {
+ struct sensor_entry *p;
+ gchar *name;
+ float value;
+ gchar *header;
+ // start with Fans
+ header="[Cooling Fans]\n";
+ for(p=first_sensor;p;p=p->next)
+ {
+ // skip any ignored items or that aren't fans
+ if((!g_ascii_strncasecmp (p->raw_name, "fan", 3)) && (p->ignore_flag==0))
+ {
+ if(p->cooked_value !=0.0)
+ value=p->cooked_value;
+ else
+ value=p->raw_value;
+ if(p->cooked_name)
+ name=p->cooked_name;
+ else if (p->label)
+ name=p->label;
+ else name=p->raw_name;
+ sensors=h_strdup_cprintf("%s%s=%.0fRPM\n", sensors, header,name,value);
+ header=""; // dont reprint the header
+ }
+ }
+ // Temperatures
+ header="[Temperatures]\n";
+ for(p=first_sensor;p;p=p->next)
+ {
+ // skip any ignored items or that aren't temps
+ if((!g_ascii_strncasecmp (p->raw_name, "temp", 4)) && (p->ignore_flag==0))
+ {
+ if(p->cooked_value !=0.0)
+ value=p->cooked_value;
+ else
+ value=p->raw_value;
+ if(p->cooked_name)
+ name=p->cooked_name;
+ else if (p->label)
+ name=p->label;
+ else name=p->raw_name;
+ sensors=h_strdup_cprintf("%s%s=%.0f\302\260C\n", sensors, header,name,value);
+ header=""; // dont reprint the header
+ }
+ }
+ // voltages
+ header="[Voltages]\n";
+ for(p=first_sensor;p;p=p->next)
+ {
+ // skip any ignored items or that aren't voltages
+ if(!(g_ascii_strncasecmp (p->raw_name, "in", 2)) && (p->ignore_flag==0))
+ {
+ if(p->cooked_value !=0.0)
+ value=p->cooked_value;
+ else
+ value=p->raw_value;
+ if(p->cooked_name)
+ name=p->cooked_name;
+ else if (p->label)
+ name=p->label;
+ else name=p->raw_name;
+ sensors=h_strdup_cprintf("%s%s=%.3fV\n", sensors, header,name,value);
+ header=""; // dont reprint the header
+ }
+ }
+ }
+/************************************************************************************
+ * reads the sensors[3].conf file and updates the linked list of items accordingly *
+ ************************************************************************************/
+static void cook_sensor_values(void)
+ {
+ FILE *conf;
+ gchar buf[2000], *line, *driver,*p;
+ gchar **chips;
+ int flag=0;
gint i;
-
- sensor_labels = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, g_free);
- sensor_compute = g_hash_table_new(g_str_hash, g_str_equal);
-
- /* Try to open lm-sensors config file sensors3.conf */
conf = fopen("/etc/sensors3.conf", "r");
-
- /* If it fails, try to open sensors.conf */
- if (!conf) conf = fopen("/etc/sensors.conf", "r");
-
- if (!conf) {
+ if (!conf)
+ {
+ printf(" failed to open /etc/sensors3.conf\n");
+ conf = fopen("/etc/sensors.conf", "r");
+ }
+ if (!conf)
+ {
/* Cannot open config file. */
+ printf("unable to open a config file\n");
return;
- }
-
- while (fgets(buf, 256, conf)) {
- line = buf;
-
- remove_linefeed(line);
- strend(line, '#');
-
- if (*line == '\0') {
- continue;
- } else if (lock && strstr(line, "label")) { /* label lines */
- gchar **names = g_strsplit(strstr(line, "label") + 5, " ", 0);
- gchar *name = NULL, *value = NULL;
-
- for (i = 0; names[i]; i++) {
- if (names[i][0] == '\0')
- continue;
-
- if (!name)
- name = g_strdup(names[i]);
- else if (!value)
- value = g_strdup(names[i]);
- else
- value = g_strconcat(value, " ", names[i], NULL);
- }
-
- remove_quotes(value);
- g_hash_table_insert(sensor_labels, name, value);
-
- g_strfreev(names);
- } else if (lock && strstr(line, "ignore")) { /* ignore lines */
- p = strstr(line, "ignore") + 6;
- if (!strchr(p, ' '))
- continue;
-
- while (*p == ' ')
- p++;
- g_hash_table_insert(sensor_labels, g_strdup(p), "ignore");
- } else if (lock && strstr(line, "compute")) { /* compute lines */
- gchar **formulas =
- g_strsplit(strstr(line, "compute") + 7, " ", 0);
- gchar *name = NULL, *formula = NULL;
-
- for (i = 0; formulas[i]; i++) {
- if (formulas[i][0] == '\0')
- continue;
- if (formulas[i][0] == ',')
- break;
-
- if (!name)
- name = g_strdup(formulas[i]);
- else if (!formula)
- formula = g_strdup(formulas[i]);
- else
- formula = g_strconcat(formula, formulas[i], NULL);
- }
-
- g_strfreev(formulas);
- g_hash_table_insert(sensor_compute, name,
- math_string_to_postfix(formula));
- } else if (g_str_has_prefix(line, "chip")) { /* chip lines (delimiter) */
- if (lock == FALSE) {
- gchar **chips = g_strsplit(line, " ", 0);
-
- for (i = 1; chips[i]; i++) {
- strend(chips[i], '*');
-
- if (g_str_has_prefix(chips[i] + 1, driver)) {
- lock = TRUE;
- break;
- }
- }
-
- g_strfreev(chips);
- } else {
- break;
- }
+ }
+ // file now open one presumes..so scan it.
+ while (fgets(buf, 2000, conf))
+ {
+ line=buf;
+ remove_linefeed(line);
+ while(*line && isspace(*line)) //strip leading space.
+ line++;
+ if(*line== '#' || !(*line))
+ continue; // skip lines beginning with hash or whitespace and then hash or all whitespace!
+ // Now test for chips match. We need to know that this is a chip we have a driver for.
+ // if it isn't we just keep skipping till it is.
+ if(!g_ascii_strncasecmp (line, "chip", 4))
+ {
+ chips = g_strsplit(line, " ", 0);
+ for (i = 1; chips[i]; i++)
+ {
+ strend(chips[i], '*'); // remove trailing asterisk
+ // if we have an entry in our list of sensors whose chippery matches get the exact name of the driver
+ if ((driver=sensor_driver_matched(chips[i] + 1)))
+ {
+ flag=1;
+ break;
+ }
+ else flag=0; // reset the flag if the chips don't match.
+ }
+ // ok this line is of no further interst.
+ g_strfreev(chips);
+ continue;
+ }
+ if(!flag)
+ continue; // until we have a matching chip entry.
+ // if we got this far, we have a matching driver and some kind of valid line beyond 'chip' so all lines are of interest.
+ if(!g_ascii_strncasecmp (line, "label", 5)) // a label line!
+ {
+ gchar **names = g_strsplit(line+ 5, " ", 0);
+ gchar *name = NULL, *value = NULL;
+
+ for (i = 0; names[i]; i++)
+ {
+ if (names[i][0] == '\0')
+ continue;
+ if (!name)
+ name = g_strdup(names[i]);
+ else if (!value)
+ value = g_strdup(names[i]);
+ else
+ value = g_strconcat(value, " ", names[i], NULL);
+ }
+ remove_quotes(value);
+ update_sensor_entry_name(driver, name, value); //update the list
+ g_free(name);
+ g_free(value);
+ g_strfreev(names);
+ }
+ else if (!g_ascii_strncasecmp (line, "ignore", 6)) // an ignore line
+ {
+ gchar **names = g_strsplit(line + 6, " ", 0);
+ gchar *name = NULL;
+ for (i = 0; names[i]; i++)
+ {
+ if (names[i][0] == '\0')
+ continue;
+ if (!name)
+ name = g_strdup(names[i]);
+ }
+ ignore_sensor_entry(driver, name);
+ g_free(name);
+ g_strfreev(names);
+ }
+ else if (!g_ascii_strncasecmp (line, "compute", 7)) // a compute line
+ {
+ // replace comma with \0 as we dont want the fag end of the line
+ for(p=line+7;*p;p++)
+ {
+ if(*p==',')
+ {
+ *p=0;
+ break;
+ }
+ }
+ gchar **formulas = g_strsplit(line + 7, " ", 0);
+ gchar *name = NULL, *formula = NULL;
+ for (i = 0; formulas[i]; i++)
+ {
+ if (formulas[i][0] == '\0')
+ continue;
+ if (formulas[i][0] == ',')
+ break;
+ if (!name)
+ name = g_strdup(formulas[i]);
+ else if (!formula)
+ formula = g_strdup(formulas[i]);
+ else
+ formula = g_strconcat(formula, formulas[i], NULL);
+ }
+ update_sensor_entry_compute_string(driver, name, formula);
+ g_free (name);
+ g_free (formula);
+ g_strfreev(formulas);
+ }
+ }
+ fclose(conf);
}
- }
-
- fclose(conf);
-}
-
-static gchar *get_sensor_label(gchar * sensor)
-{
- gchar *ret;
-
- ret = g_hash_table_lookup(sensor_labels, sensor);
- if (!ret)
- ret = g_strdup(sensor);
- else
- ret = g_strdup(ret);
-
- return ret;
-}
-
-static float adjust_sensor(gchar * name, float value)
-{
- GSList *postfix;
-
- postfix = g_hash_table_lookup(sensor_compute, name);
- if (!postfix)
- return value;
-
- return math_postfix_eval(postfix, value);
-}
-
-
static void read_sensors_hwmon(void)
-{
- int hwmon, count;
- gchar *path_hwmon, *path_sensor, *tmp, *driver, *name, *mon;
- hwmon = 0;
-
- path_hwmon = g_strdup_printf("/sys/class/hwmon/hwmon%d/device/", hwmon);
- while (g_file_test(path_hwmon, G_FILE_TEST_EXISTS)) {
- tmp = g_strdup_printf("%sdriver", path_hwmon);
- driver = g_file_read_link(tmp, NULL);
- g_free(tmp);
-
- tmp = g_path_get_basename(driver);
- g_free(driver);
- driver = tmp;
-
- if (!sensor_labels) {
- read_sensor_labels(driver);
- }
-
- sensors = g_strconcat(sensors, "[Cooling Fans]\n", NULL);
- for (count = 1;; count++) {
- path_sensor =
- g_strdup_printf("%sfan%d_input", path_hwmon, count);
- if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL)) {
- g_free(path_sensor);
- break;
- }
-
- mon = g_strdup_printf("fan%d", count);
- name = get_sensor_label(mon);
- if (!g_str_equal(name, "ignore")) {
- sensors = h_strdup_cprintf("%s=%.0fRPM\n",
- sensors, name,
- adjust_sensor(mon, atof(tmp)));
- }
-
- g_free(name);
- g_free(mon);
- g_free(tmp);
- g_free(path_sensor);
- }
-
- sensors = g_strconcat(sensors, "[Temperatures]\n", NULL);
- for (count = 1;; count++) {
- path_sensor =
- g_strdup_printf("%stemp%d_input", path_hwmon, count);
- if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL)) {
- g_free(path_sensor);
- break;
- }
-
- mon = g_strdup_printf("temp%d", count);
- name = get_sensor_label(mon);
- if (!g_str_equal(name, "ignore")) {
- sensors = h_strdup_cprintf("%s=%.2f\302\260C\n",
- sensors, name,
- adjust_sensor(mon,
- atof(tmp) /
- 1000.0));
- }
-
- g_free(tmp);
- g_free(name);
- g_free(path_sensor);
- g_free(mon);
- }
-
- sensors = g_strconcat(sensors, "[Voltage Values]\n", NULL);
- for (count = 0;; count++) {
- path_sensor =
- g_strdup_printf("%sin%d_input", path_hwmon, count);
- if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL)) {
- g_free(path_sensor);
- break;
- }
-
-
- mon = g_strdup_printf("in%d", count);
- name = get_sensor_label(mon);
- if (!g_str_equal(name, "ignore")) {
- sensors = h_strdup_cprintf("%s=%.3fV\n",
- sensors, name,
- adjust_sensor(mon,
- atof(tmp) /
- 1000.0));
- }
-
- g_free(tmp);
- g_free(mon);
- g_free(name);
- g_free(path_sensor);
+ {
+ int hwmon, count;
+ gchar *path_hwmon, *path_sensor, *tmp, *driver, *name, *label;
+ float value;
+ hwmon = 0;
+ // see what drivers we have.
+ path_hwmon = g_strdup_printf("/sys/class/hwmon/hwmon%d/device/", hwmon);
+ while( g_file_test(path_hwmon, G_FILE_TEST_EXISTS))
+ {
+ // establish the driver name i.e. coretemp or w83627ehf etc etc.
+ tmp = g_strdup_printf("%sdriver", path_hwmon);
+ driver = g_file_read_link(tmp, NULL);
+ g_free(tmp);
+ tmp = g_path_get_basename(driver);
+ g_free(driver);
+ driver = tmp;
+ // Now see what we have in the directory making no assumptions.
+ // the old sensor.h relied on temperatures and in fact everything starting at eg temp1.
+ // but coretemp often uses values starting with temp2...so the safest thing is to simply make no assumptions
+ // beyon the fact that there won't be more the 20 of anything, and simply probe.
+ // coretemp also has temp[n]_label as a more human readable name for the parameter.
+ //fans
+ for(count=1;count<21;count++)
+ {
+ path_sensor = g_strdup_printf("%sfan%d_input", path_hwmon, count);
+ if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL))
+ {
+ g_free(path_sensor);
+ continue; // its simply not there.
+ }
+ name = g_strdup_printf("fan%d", count);
+ value=atof(tmp);
+ g_free(tmp);
+ path_sensor = g_strdup_printf("%sfan%d_label", path_hwmon, count);
+ if (g_file_get_contents(path_sensor, &tmp, NULL, NULL))
+ {
+ remove_lf(tmp);
+ label=g_strdup(tmp);
+ g_free(tmp);
+ }
+ else label=(gchar *)0;
+ add_sensor_entry(driver, name, label, value); // insert this sensor into the linked list
+ if(label)
+ g_free(label);
+ g_free(name);
+ g_free(path_sensor);
+ }
+ // temperatures
+ for(count=1;count<21;count++)
+ {
+ path_sensor = g_strdup_printf("%stemp%d_input", path_hwmon, count);
+ if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL))
+ {
+ g_free(path_sensor);
+ continue; // its simply not there.
+ }
+ name = g_strdup_printf("temp%d", count);
+ value=(atof(tmp))/1000;
+ g_free(tmp);
+ path_sensor = g_strdup_printf("%stemp%d_label", path_hwmon, count);
+ if (g_file_get_contents(path_sensor, &tmp, NULL, NULL))
+ {
+ remove_lf(tmp);
+ label=g_strdup(tmp);
+ g_free(tmp);
+ }
+ else label=(gchar *)0;
+ add_sensor_entry(driver, name, label, value); // insert this sensor into the linked list
+ if(label)
+ g_free(label);
+ g_free(name);
+ g_free(path_sensor);
+ }
+
+ // and voltages
+ for(count=1;count<21;count++)
+ {
+ path_sensor = g_strdup_printf("%sin%d_input", path_hwmon, count);
+ if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL))
+ {
+ g_free(path_sensor);
+ continue; // its simply not there.
+ }
+ name = g_strdup_printf("in%d", count);
+ value=(atof(tmp))/1000;
+ g_free(tmp);
+ path_sensor = g_strdup_printf("%sin%d_label", path_hwmon, count);
+ if (g_file_get_contents(path_sensor, &tmp, NULL, NULL))
+ {
+ remove_lf(tmp);
+ label=g_strdup(tmp);
+ g_free(tmp);
+ }
+ else label=(gchar *)0;
+ add_sensor_entry(driver, name, label, value); // insert this sensor into the linked list
+ if(label)
+ g_free(label);
+ g_free(name);
+ g_free(path_sensor);
+ }
+ // clear the path and the driver string
+ g_free(path_hwmon);
+ g_free(driver);
+ hwmon++; // try next driver
+ path_hwmon = g_strdup_printf("/sys/class/hwmon/hwmon%d/device/", hwmon);
+ }
+ g_free(path_hwmon); // and clear the last path..
+ // now to adjust the values
+ cook_sensor_values();
+ // and now print the output values to the sensors string.
+ print_sensors();
+ // destroy the linked list..
+ free_all_sensor_entries();
}
- g_free(path_hwmon);
- g_free(driver);
- path_hwmon =
- g_strdup_printf("/sys/class/hwmon/hwmon%d/device/", ++hwmon);
- }
-
- g_free(path_hwmon);
-
-}
static void read_sensors_acpi(void)
{
@@ -364,10 +579,8 @@
static void __scan_sensors(void)
{
if (sensors)
- g_free(sensors);
-
+ g_free(sensors);
sensors = g_strdup("");
-
read_sensors_hwmon();
read_sensors_acpi();
read_sensors_omnibook();