gkrellm/src/sysdeps/sensors-common.c

410 lines
9.6 KiB
C

/* GKrellM
| Copyright (C) 1999-2010 Bill Wilson
|
| Author: Bill Wilson billw@gkrellm.net
| Latest versions might be found at: http://gkrellm.net
|
|
| GKrellM is free software: you can redistribute it and/or modify it
| under the terms of the GNU General Public License as published by
| the Free Software Foundation, either version 3 of the License, or
| (at your option) any later version.
|
| GKrellM 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.
|
| You should have received a copy of the GNU General Public License
| along with this program. If not, see http://www.gnu.org/licenses/
|
|
| Additional permission under GNU GPL version 3 section 7
|
| If you modify this program, or any covered work, by linking or
| combining it with the OpenSSL project's OpenSSL library (or a
| modified version of that library), containing parts covered by
| the terms of the OpenSSL or SSLeay licenses, you are granted
| additional permission to convey the resulting work.
| Corresponding Source for a non-source form of such a combination
| shall include the source code for the parts of OpenSSL used as well
| as that of the covered work.
*/
/* A system dependent interface can include this file to get sensors
| from daemons that can run under different operating systems.
*/
#define SENSORS_COMMON 1
/* --------------- Interface to mbmon daemon sensor reading ---------
*/
typedef struct
{
gchar *name;
gfloat value;
}
MbmonSensor;
static GList *mbmon_list;
static gchar gkrellm_decimal_point,
mbmon_decimal_point;
static gboolean mbmon_need_decimal_point_fix;
static gboolean (*mbmon_check_func)();
static gboolean
mbmon_decimal_point_fix(gchar *buf)
{
gchar *s;
for (s = buf; *s; ++s)
if (*s == mbmon_decimal_point)
{
*s = gkrellm_decimal_point;
return TRUE;
}
return FALSE;
}
static gboolean
mbmon_decimal_point_check(gchar *buf)
{
struct lconv *lc;
gchar *s;
lc = localeconv();
gkrellm_decimal_point = *lc->decimal_point;
mbmon_decimal_point = (gkrellm_decimal_point == ',' ? '.' : ',');
s = g_strdup(buf);
if (mbmon_decimal_point_fix(s))
{
mbmon_need_decimal_point_fix = TRUE;
gkrellm_debug(DEBUG_SENSORS, "mbmon_need_decimal_point_fix: %c -> %c\n",
mbmon_decimal_point, gkrellm_decimal_point);
}
g_free(s);
return mbmon_need_decimal_point_fix;;
}
static MbmonSensor *
mbmon_lookup(gchar *name)
{
GList *list;
MbmonSensor *mb;
for (list = mbmon_list; list; list = list->next)
{
mb = (MbmonSensor *) list->data;
if (!strcmp(name, mb->name))
return mb;
}
return NULL;
}
/* Read sensor data from the mbmon daemon, which must be run with the
| -r option and no -f option: mbmon -r -P port
| and 'port' must be configured in the sensors config.
| With '-r' mbmon output will be:
| TEMP0 : 37.0
| TEMP1 : 35.5
| TEMP2 : 43.0
| FAN0 : 1704
| FAN1 : 2220
| FAN2 : 2057
| VC0 : +1.71
| VC1 : +2.51
| V33 : +3.22
| V50P : +4.87
| V12P : +11.80
| V12N : -12.12
| V50N : -5.25
*/
static gboolean
mbmon_daemon_read(void)
{
gchar *server = "127.0.0.1";
gpointer sr;
MbmonSensor *mb;
gchar *default_label, *id_name;
gchar name[32], buf[256];
gfloat value;
gint fd, n, type;
gboolean result = FALSE;
static GString *mbmon_gstring;
static gboolean decimal_point_check_done;
if ((fd = gkrellm_connect_to(server, _GK.mbmon_port)) < 0)
{
gkrellm_debug(DEBUG_SENSORS,
"mbmon_daemon_read: can't connect to %s:%d.\n", server,
_GK.mbmon_port);
return FALSE;
}
if (!mbmon_gstring)
mbmon_gstring = g_string_new("");
mbmon_gstring = g_string_truncate(mbmon_gstring, 0);
while ((n = read(fd, buf, sizeof(buf) - 1)) > 0)
{
buf[n] = '\0';
mbmon_gstring = g_string_append(mbmon_gstring, buf);
}
close(fd);
gkrellm_debug(DEBUG_SENSORS, "mbmon_daemon_read:\n%s\n", mbmon_gstring->str);
while (gkrellm_getline_from_gstring(&mbmon_gstring, buf, sizeof(buf)))
{
if (mbmon_need_decimal_point_fix)
mbmon_decimal_point_fix(buf);
if ( sscanf(buf, "%31s : %f", name, &value) != 2
|| value == 0.0 /* Sensor not available */
)
continue;
if (name[0] == 'T')
type = SENSOR_TEMPERATURE;
else if (name[0] == 'F')
type = SENSOR_FAN;
else if (name[0] == 'V')
type = SENSOR_VOLTAGE;
else
continue;
if ( !decimal_point_check_done
&& (type == SENSOR_TEMPERATURE || type == SENSOR_VOLTAGE)
)
{
mbmon_decimal_point_check(buf);
decimal_point_check_done = TRUE;
}
if ((mb = mbmon_lookup(name)) == NULL)
{
mb = g_new0(MbmonSensor, 1);
mbmon_list = g_list_append(mbmon_list, mb);
mb->name = g_strdup(name);
default_label = name;
id_name = g_strdup_printf("mbmon/%s", name);
sr = gkrellm_sensors_add_sensor(type,
name, id_name,
0, 0, MBMON_INTERFACE,
1.0, 0.0, NULL, default_label);
g_free(id_name);
}
mb->value = value; /* Assume centigrade, mbmon gives no units */
result = TRUE;
}
return result;
}
gboolean
gkrellm_sys_sensors_mbmon_check(gboolean force)
{
GList *list;
MbmonSensor *mb;
gboolean result = TRUE;
static gint port;
static gint check_time = -1;
static gboolean tmp;
mbmon_check_func = gkrellm_sys_sensors_mbmon_check;
if (port > 0 && port != _GK.mbmon_port)
{
for (list = mbmon_list; list; list = list->next)
{
mb = (MbmonSensor *) list->data;
g_free(mb->name);
}
gkrellm_free_glist_and_data(&mbmon_list);
}
if (_GK.mbmon_port <= 0)
return FALSE;
port = _GK.mbmon_port;
if (check_time < _GK.time_now || force)
{
/* The first mbmon_daemon_read can set need_decimal_point_fix in
| which case don't update check_time so the mbmon daemon will be
| read again immediately at next call to this function. The first
| call of this function should be made from gkrellm_sys_sensors_init()
| function where we just want to get the sensors loaded into
| sensors.c and we don't actually use the mbmon sensor values.
*/
tmp = mbmon_need_decimal_point_fix;
result = mbmon_daemon_read();
if (tmp == mbmon_need_decimal_point_fix)
check_time = _GK.time_now + 3; /* Interval < sensor update */
}
return result;
}
gboolean
gkrellm_sys_sensors_mbmon_get_value(gchar *name, gfloat *value)
{
MbmonSensor *mb;
if ((mb = mbmon_lookup(name)) != NULL)
{
*value = mb->value;
return TRUE;
}
return FALSE;
}
/* --------------- Interface to hddtemp daemon sensor reading ---------
*/
/* Use hddtemp default port. Should make this configurable.
*/
#define HDDTEMP_PORT 7634
typedef struct
{
gchar *device;
gfloat value;
gchar unit;
}
HddtempSensor;
static GList *hddtemp_list;
static HddtempSensor *
hddtemp_lookup(gchar *device)
{
GList *list;
HddtempSensor *hdd;
for (list = hddtemp_list; list; list = list->next)
{
hdd = (HddtempSensor *) list->data;
if (!strcmp(device, hdd->device))
return hdd;
}
return NULL;
}
/* Read output from the hddtemp daemon which must have been started in
| daemon mode: hddtemp -d /dev/hda /dev/hdb ...
| And example hddtemp output will be:
|
| |/dev/hda|SAMSUNG SP1614N|30|C||/dev/hdc|SAMSUNG SP1614N|30|C|
|
*/
static gboolean
hddtemp_daemon_read(void)
{
gchar *server = "127.0.0.1";
gpointer sr;
HddtempSensor *hdd;
gchar **argv, **info, *id_name, *default_label;
gchar buf[256], sep;
gint fd, n, j;
static GString *hddtemp_gstring;
gboolean result = FALSE;
if ((fd = gkrellm_connect_to(server, HDDTEMP_PORT)) < 0)
{
gkrellm_debug(DEBUG_SENSORS,
"hddtemp_daemon_read: can't connect to %s:%d.\n", server,
HDDTEMP_PORT);
return FALSE;
}
if (!hddtemp_gstring)
hddtemp_gstring = g_string_new("");
hddtemp_gstring = g_string_truncate(hddtemp_gstring, 0);
while ((n = read(fd, buf, sizeof(buf) - 1)) > 0)
{
buf[n] = '\0';
hddtemp_gstring = g_string_append(hddtemp_gstring, buf);
}
close(fd);
gkrellm_debug(DEBUG_SENSORS, "hddtemp_daemon_read (once a minute):\n\t%s\n",
hddtemp_gstring->str);
sep = hddtemp_gstring->str[0];
if (sep == '\0')
return FALSE;
sprintf(buf, "%c%c", sep, sep);
argv = g_strsplit(hddtemp_gstring->str + 1, buf, 20);
buf[1] = '\0';
for (n = 0; argv[n] != NULL; ++n)
{
info = g_strsplit(argv[n], buf, 4);
for (j = 0; info[j] != NULL; ++j)
;
if (j < 4)
{
g_strfreev(info);
continue;
}
if ((hdd = hddtemp_lookup(info[0])) == NULL)
{
hdd = g_new0(HddtempSensor, 1);
hddtemp_list = g_list_append(hddtemp_list, hdd);
hdd->device = g_strdup(info[0]);
default_label = strrchr(hdd->device, '/');
if (default_label)
++default_label;
else
default_label = hdd->device;
id_name = g_strdup_printf("hddtemp/%s", default_label);
sr = gkrellm_sensors_add_sensor(SENSOR_TEMPERATURE,
hdd->device, id_name,
0, 0, HDDTEMP_INTERFACE,
1.0, 0.0, NULL, default_label);
gkrellm_sensors_set_group(sr, SENSOR_GROUP_DISK);
g_free(id_name);
}
hdd->value = atof(info[2]);
if (*info[3] == 'F')
hdd->value = (hdd->value - 32.0) / 1.8;
g_strfreev(info);
result = TRUE;
}
g_strfreev(argv);
return result;
}
void
gkrellm_sys_sensors_hddtemp_check(void)
{
static gint check_time = -1;
/* hddtemp docs say shouldn't check more than once per minute.
*/
if (check_time < _GK.time_now)
{
hddtemp_daemon_read();
check_time = _GK.time_now + 60;
}
}
gboolean
gkrellm_sys_sensors_hddtemp_get_value(gchar *name, gfloat *value)
{
HddtempSensor *hdd;
if ((hdd = hddtemp_lookup(name)) != NULL)
{
*value = hdd->value;
return TRUE;
}
return FALSE;
}