📄 sensors.c
字号:
/* GKrellM| Copyright (C) 1999-2006 Bill Wilson|| Author: Bill Wilson billw@gkrellm.net| Latest versions might be found at: http://gkrellm.net|| This program is free software which I release under the GNU General Public| License. You may redistribute and/or modify this program under the terms| of that license as published by the Free Software Foundation; either| version 2 of the License, or (at your option) any later version.|| This program is distributed in the hope that it will be useful,| but WITHOUT ANY WARRANTY; without even the implied warranty of| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the| GNU General Public License for more details. Version 2 is in the| COPYRIGHT file in the top level directory of this distribution.| | To get a copy of the GNU General Puplic License, write to the Free Software| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include "gkrellm.h"#include "gkrellm-private.h"#include "gkrellm-sysdeps.h"/* Useful info:| http://mbm.livewiredev.com/| Look up boards here for sensor chip and temperature sensor type| so sensor[1,2,3] can be set correctly in sensors.conf.*/ /* On Linux, the sensor id_name includes the parent chip directory, so | "lm78/temp" will be a id_name, and not just "temp". This is to | allow unique identification in case of multiple "temp" files. | ie, more than 1 chip directory, each with a "temp" file. */typedef struct _sensor { gchar *name; /* cpuX, mb, Vx name mapped to this sensor */ gchar *name_locale; /* gdk_draw compat */ gchar *default_label; /* Only voltages have default labels */ gchar *path; /* Pathname to sensor data or device file */ gchar *id_name; /* Unique sensor identifier for config */ gint type; gint id; gint iodev; gint inter; gint enabled; gint group; gint location; /* default, Proc panel, or cpu panel */ gfloat factor, /* Scale sensor reading */ offset; /* Add to sensor reading */ gfloat default_factor, default_offset; gchar *vref_name; struct _sensor *vref; /* A neg volt may be function of a ref volt */ gboolean has_config; gfloat value, raw_value; gboolean value_valid; GkrellmAlert *alert; void (*cb_alert)(); gpointer cb_alert_data; gpointer smon; } Sensor;static GList *sensor_list = NULL;static GList *temp_order_list, /* For ordering from the config. */ *fan_order_list, *volt_order_list;static gboolean using_new_config, need_disk_temperature_update;static gboolean (*get_temperature)(gchar *name, gint id, gint iodev, gint inter, gfloat *t);static gboolean (*get_fan)(gchar *name, gint id, gint iodev, gint inter, gfloat *f);static gboolean (*get_voltage)(gchar *name, gint id, gint iodev, gint inter, gfloat *v);static void read_sensors_config(void);voidgkrellm_sensors_client_divert(gboolean (*get_temp_func)(), gboolean (*get_fan_func)(), gboolean (*get_volt_func)()) { get_temperature = get_temp_func; get_fan = get_fan_func; get_voltage = get_volt_func; }static gbooleansetup_sensor_interface(void) { if (!get_temperature && !_GK.client_mode && gkrellm_sys_sensors_init()) { get_temperature = gkrellm_sys_sensors_get_temperature; get_fan = gkrellm_sys_sensors_get_fan; get_voltage = gkrellm_sys_sensors_get_voltage; } return get_temperature ? TRUE : FALSE; }voidgkrellm_sensors_set_group(gpointer sr, gint group) { Sensor *sensor = (Sensor *) sr; if (sensor) sensor->group = group; }gpointergkrellm_sensors_add_sensor(gint type, gchar *sensor_path, gchar *id_name, gint id, gint iodev, gint inter, gfloat factor, gfloat offset, gchar *vref, gchar *default_label) { Sensor *sensor; gchar *r; if (!id_name || !*id_name || type < 0 || type > 2) return NULL; sensor = g_new0(Sensor, 1); sensor->id_name = g_strdup(id_name); if (sensor_path) sensor->path = g_strdup(sensor_path); else sensor->path = g_strdup(id_name); if (!default_label) { r = strrchr(id_name, '/'); default_label = r ? r+1 : id_name; } gkrellm_locale_dup_string(&sensor->name, default_label, &sensor->name_locale); sensor->default_label = g_strdup(default_label); sensor->default_factor = sensor->factor = factor; sensor->default_offset = sensor->offset = offset; sensor->type = type; sensor->id = id; sensor->iodev = iodev; sensor->inter = inter; if (type == SENSOR_VOLTAGE && vref) sensor->vref_name = g_strdup(vref); sensor_list = g_list_append(sensor_list, sensor); return (gpointer) sensor; }/* ======================================================================== */static gboolean use_threads, thread_data_valid, units_fahrenheit;static gboolean thread_busy;static gpointerread_sensors_thread(void *data) { GList *list; Sensor *sensor; for (list = sensor_list; list; list = list->next) { sensor = (Sensor *) list->data; if (!sensor->enabled) continue; if (sensor->type == SENSOR_TEMPERATURE && get_temperature) (*get_temperature)(sensor->path, sensor->id, sensor->iodev, sensor->inter, &sensor->raw_value); if (sensor->type == SENSOR_FAN && get_fan) (*get_fan)(sensor->path, sensor->id, sensor->iodev, sensor->inter, &sensor->raw_value); if (sensor->type == SENSOR_VOLTAGE && get_voltage) (*get_voltage)(sensor->path, sensor->id, sensor->iodev, sensor->inter, &sensor->raw_value); } thread_busy = FALSE; return NULL; }static voidrun_sensors_thread(void) { if (thread_busy) return; thread_busy = TRUE; g_thread_create(read_sensors_thread, NULL, FALSE, NULL); } /* Sort so that sensors are ordered: temp, fan, voltage. */static gintstrcmp_sensor_path(Sensor *s1, Sensor *s2) { if (s1->type == SENSOR_TEMPERATURE && s2->type != SENSOR_TEMPERATURE) return -1; if (s1->type != SENSOR_TEMPERATURE && s2->type == SENSOR_TEMPERATURE) return 1; if (s1->type == SENSOR_FAN && s2->type != SENSOR_FAN) return -1; if (s1->type != SENSOR_FAN && s2->type == SENSOR_FAN) return 1; return strcmp(s1->id_name, s2->id_name); }static voidappend_sensor_to_order_list(Sensor *sr) { if (sr->type == SENSOR_TEMPERATURE) temp_order_list = g_list_append(temp_order_list, sr); else if (sr->type == SENSOR_FAN) fan_order_list = g_list_append(fan_order_list, sr); else if (sr->type == SENSOR_VOLTAGE) volt_order_list = g_list_append(volt_order_list, sr); } /* Remove embedded "-i2c-" or "-isa-" from lm_sensors chip names so | there can be a chance for config name sysfs compatibility. This function | here in sensors.c is a kludge. Give user configs a chance to get | converted and then move this function to sysdeps/linux.c where it | belongs. | Munge names like w83627hf-isa-0290 to w83627hf-0-0290 | or w83627hf-i2c-0-0290 to w83627hf-0-0290 | lm_sensor i2c bus address may not be 4 digits, eg: w83782d-i2c-0-2d | and for that we want: w83782d-0-002d */voidgkrellm_sensors_linux_name_fix(gchar *id_name) {#if defined(__linux__) gchar *s; gint len, bus = 0; guint addr = 0; len = strlen(id_name) + 1; if ((s = strstr(id_name, "-i2c-")) != NULL) { sscanf(s + 5, "%d-%x", &bus, &addr); snprintf(s, len - (s - id_name), "-%d-%04x", bus, addr); } else if ((s = strstr(id_name, "-isa-")) != NULL) { *(s + 1) = '0'; memmove(s + 2, s + 4, strlen(s + 4) + 1); }#endif } /* This is called as sensors are read from the config and I will want to | re-order the sensors_list to reflect the config order. Re-ordering is | done by appending found sensors to type specific lists and later the | sensors_list will be rebuilt from the ordered type lists. If the | id_name is found in the sensor_list, assign the label to it. */static Sensor *map_sensor_label(gchar *label, gchar *name) { GList *list; Sensor *sr; gkrellm_sensors_linux_name_fix(name); /* XXX temporary, remove me */ for (list = sensor_list; list; list = list->next) { sr = (Sensor *) list->data; if (!sr->has_config && !strcmp(sr->id_name, name)) { gkrellm_locale_dup_string(&sr->name, label, &sr->name_locale); append_sensor_to_order_list(sr); sr->has_config = TRUE; return sr; } } return NULL; }gbooleangkrellm_sensors_available(void) { return (sensor_list || _GK.demo) ? TRUE : FALSE; } /* The cpu and proc monitors both need a couple of sensor decals | created on their panels. The left one will only display fan speeds | while the right one will display both fan and temps depending on modes. */voidgkrellm_sensors_create_decals(GkrellmPanel *p, gint style_id, GkrellmDecal **dsensor, GkrellmDecal **dfan) { GkrellmStyle *style; GkrellmMargin *m; GkrellmTextstyle *ts; GkrellmDecal *ds = NULL, *df = NULL; gint w, w_avail; if (sensor_list || _GK.demo) { style = gkrellm_panel_style(style_id); m = gkrellm_get_style_margins(style); ts = gkrellm_panel_alt_textstyle(style_id); w_avail = gkrellm_chart_width() - m->left - m->right; df = gkrellm_create_decal_text(p, "8888", ts, style, -1, -1, 0); /* Sensor decal (fan and/or temp) carves out space remaining to right. | Try to get enough for .1 deg resolution, otherwise what is left. */ w = gkrellm_gdk_string_width(ts->font, "188.8F") + ts->effect; if (w > w_avail - df->w - 3) w = gkrellm_gdk_string_width(ts->font, "88.8C") + ts->effect; ds = gkrellm_create_decal_text(p, "8.C", ts, style, -1, -1, w); ds->x = w_avail + m->left - w; df->x = m->left; } *dsensor = ds; *dfan = df; }voidgkrellm_sensor_draw_fan_decal(GkrellmPanel *p, GkrellmDecal *d, gfloat f) { gchar buf[8]; gint w; if (!p || !d) return; snprintf(buf, sizeof(buf), "%.0f", f); w = gkrellm_gdk_string_width(d->text_style.font, buf) + d->text_style.effect; d->x_off = d->w - w; if (d->x_off < 0) d->x_off = 0; gkrellm_draw_decal_text(p, d, buf, 0); }voidgkrellm_sensor_draw_temperature_decal(GkrellmPanel *p, GkrellmDecal *d, gfloat t, gchar units) { gchar *s, buf[8]; gint w; if (!p || !d) return; snprintf(buf, sizeof(buf), "%.1f%c", t, units); if ((s = strchr(buf, '.')) == NULL) s = strchr(buf, ','); /* Locale may use commas */ w = gkrellm_gdk_string_width(d->text_style.font, buf) + d->text_style.effect; if (w > d->w + 1) { snprintf(buf, sizeof(buf), "%.0f%c", t, units); w = gkrellm_gdk_string_width(d->text_style.font, buf) + d->text_style.effect; } d->x_off = d->w - w; if (d->x_off < 0) d->x_off = 0; gkrellm_draw_decal_text(p, d, buf, 0 /* no longer used */); }static Sensor *lookup_sensor_from_id_name(gchar *name) { GList *list; Sensor *s; if (!name) return NULL; gkrellm_sensors_linux_name_fix(name); /* XXX temporary, remove me */ for (list = sensor_list; list; list = list->next) { s = (Sensor *) list->data; if (!strcmp(s->id_name, name)) return s; } return NULL; } /* Given a in0, in1, ... name as a reference to use for a sensor, | find the sensor with that name for the same chip as sr. */static Sensor *lookup_vref(Sensor *sr, gchar *name) { GList *list; Sensor *sv; gchar *s, buf[128]; snprintf(buf, 96, "%s", sr->id_name); s = strrchr(buf, '/'); if (s) ++s; else s = buf; snprintf(s, 31, "%s", name); for (list = sensor_list; list; list = list->next) { sv = (Sensor *) list->data; if ( sv->type == SENSOR_VOLTAGE && !strcmp(sv->id_name, buf) ) return sv; } return NULL; }static voidcb_command_process(GkrellmAlert *alert, gchar *src, gchar *buf, gint size, Sensor *sensor) { gchar c, *s, *fmt; gint len; if (!buf || size < 1) return; --size; *buf = '\0'; if (!src) return; for (s = src; *s != '\0' && size > 0; ++s) { len = 1; if (*s == '$' && *(s + 1) != '\0') { if ((c = *(s + 1)) == 'H') len = snprintf(buf, size, "%s", gkrellm_sys_get_host_name()); else if (c == 's') { if (sensor->type == SENSOR_FAN) fmt = "%.0f"; else if (sensor->type == SENSOR_TEMPERATURE) fmt = "%.1f"; else fmt = "%.2f"; len = snprintf(buf, size, fmt, sensor->value); } else if (c == 'l') len = snprintf(buf, size, "%s", sensor->name_locale); ++s; } else *buf = *s; size -= len; buf += len; } *buf = '\0'; }GkrellmAlert *gkrellm_sensor_alert(gpointer sr) { if (!sr) return NULL; return ((Sensor *) sr)->alert; }voidgkrellm_sensor_alert_connect(gpointer sr, void (*cb_func)(), gpointer data) { Sensor *sensor = (Sensor *) sr; if (!sensor) return; sensor->cb_alert = cb_func; sensor->cb_alert_data = data; gkrellm_alert_trigger_connect(sensor->alert, cb_func, data); gkrellm_alert_command_process_connect(sensor->alert, cb_command_process, sensor); gkrellm_reset_alert_soft(sensor->alert); }static gbooleansensor_read_temperature(Sensor *sensor, gfloat *temp, gchar *units) { gfloat t = 0; gint found_temp = FALSE; if (sensor && get_temperature) { found_temp = thread_data_valid ? TRUE : (*get_temperature)(sensor->path, sensor->id,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -