/*
* Copyright (C) 2005 Alex Murray <pragmatine@gmail.com>
*
* This program 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 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "i2c-proc-sensors-interface.h"
#include "sensors-applet.h"
#define I2C_PROC_BASE_DIR "/proc/sys/dev/sensors"
/* for error handling */
#define I2C_PROC_DEVICE_FILE_ERROR (i2c_proc_sensors_interface_device_file_error_quark())
enum {
I2C_PROC_DEVICE_FILE_OPEN_ERROR,
I2C_PROC_DEVICE_FILE_READ_ERROR
};
static void i2c_proc_sensors_interface_add_sensor(SensorsApplet *sensors_applet, const gchar *path) {
gchar *filename;
gchar *label;
gboolean enable;
SensorType sensor_type;
const gchar *icon_filename = NULL;
filename = g_path_get_basename(path);
/* setup temp2 as CPU sensor and enable it */
if (g_ascii_strcasecmp(filename, "temp2") == 0) {
sensor_type = TEMP_SENSOR;
label = g_strdup(_("CPU"));
enable = TRUE;
icon_filename = CPU_ICON;
} else {
label = g_strdup(filename);
switch(filename[0]) {
case 'c': /* currents are "curr?" */
sensor_type = CURRENT_SENSOR;
break;
case 'f': /* fans are "fan?" */
sensor_type = FAN_SENSOR;
icon_filename = FAN_ICON;
break;
case 'i': /* voltages are "in?" */
sensor_type = VOLTAGE_SENSOR;
icon_filename = VOLTAGE_ICON;
break;
case 't': /* temps are "temp?" */
sensor_type = TEMP_SENSOR;
break;
case 'v': /* vids are just vid */
sensor_type = VOLTAGE_SENSOR;
icon_filename = VOLTAGE_ICON;
break;
default:
/* SHOULDN'T BE ABLE
* TO GET HERE!! */
g_assert_not_reached();
}
/* disable all other sensors */
enable = FALSE;
}
sensors_applet_add_sensor(sensors_applet,
path,
filename,
label,
I2C_PROC,
enable,
sensor_type,
NULL);
g_free(filename);
g_free(label);
}
/* recursive function to find sensors in a given path - once found
will call function to add sensor to the sensors_list */
static void i2c_proc_sensors_interface_find_sensors(SensorsApplet *sensors_applet, const gchar *path) {
GDir *dir;
FILE *fp;
const gchar* new_file;
gchar *new_path, *filename;
if (g_file_test(path, G_FILE_TEST_IS_REGULAR)) {
filename = g_path_get_basename(path);
/* see if filename starts with any of the sensor
prefixes */
if (g_strrstr(filename, "curr") == filename ||
(g_strrstr(filename, "fan") == filename && g_strrstr(filename, "fan_div") == NULL) ||
g_strrstr(filename, "in") == filename ||
g_strrstr(filename, "temp") == filename ||
g_strrstr(filename, "vid") == filename) {
/* also test can actually open file for
reading */
if (fp = fopen(path, "r")) {
fclose(fp);
i2c_proc_sensors_interface_add_sensor(sensors_applet, path);
}
}
g_free(filename);
}
/* if is a directory (but not a symlinked dir as this
will lead us in circular loops) descend into it and look
for a sensor dir
*/
if (g_file_test(path, G_FILE_TEST_IS_DIR) && !g_file_test(path, G_FILE_TEST_IS_SYMLINK)) {
dir = g_dir_open(path, 0, NULL);
if (dir != NULL) {
while(new_file = g_dir_read_name(dir)) {
new_path = g_strdup_printf("%s/%s", path, new_file);
i2c_proc_sensors_interface_find_sensors(sensors_applet, new_path);
g_free(new_path);
}
g_dir_close(dir);
}
}
}
/* to be called to setup for proc sensors */
void i2c_proc_sensors_interface_init(SensorsApplet *sensors_applet) {
sensors_applet_register_sensors_interface(sensors_applet,
I2C_PROC,
i2c_proc_sensors_interface_get_sensor_value);
/* call function to recursively look for sensors
starting at the defined base directory */
i2c_proc_sensors_interface_find_sensors(sensors_applet, I2C_PROC_BASE_DIR);
}
static GQuark i2c_proc_sensors_interface_device_file_error_quark(void) {
static GQuark quark = 0;
gchar *string;
if (quark == 0) {
string = g_strdup_printf("%s-device-file-error", sensor_interface[I2C_PROC]);
quark = g_quark_from_string(string);
g_free(string);
}
return quark;
}
gdouble i2c_proc_sensors_interface_get_sensor_value(const gchar *path,
const gchar *id,
SensorType type,
GError **error) {
/* to open and access the value of each sensor */
FILE *fp;
gfloat float1, float2, float3;
gint int1, int2, int3;
gfloat sensor_value;
if (NULL == (fp = fopen(path, "r"))) {
g_set_error(error, I2C_PROC_DEVICE_FILE_ERROR, I2C_PROC_DEVICE_FILE_OPEN_ERROR, "Error opening sensor device file %s", path);
return;
}
switch (type) {
case CURRENT_SENSOR:
if (fscanf(fp, "%f %f %f", &float1, &float2, &float3) != 3) {
g_set_error(error, I2C_PROC_DEVICE_FILE_ERROR, I2C_PROC_DEVICE_FILE_READ_ERROR, "Error reading from sensor device file %s", path);
fclose(fp);
return;
}
sensor_value = float3;
break;
case FAN_SENSOR:
if (fscanf(fp, "%d %d", &int1, &int2) != 2) {
g_set_error(error, I2C_PROC_DEVICE_FILE_ERROR, I2C_PROC_DEVICE_FILE_READ_ERROR, "Error reading from sensor device file %s", path);
fclose(fp);
return;
}
sensor_value = (gfloat)int2;
break;
case VOLTAGE_SENSOR:
/* is it CPU_VID or IN */
switch(id[0]) {
case 'i':
if (fscanf(fp, "%f %f %f", &float1, &float2, &float3) != 3) {
g_set_error(error, I2C_PROC_DEVICE_FILE_ERROR, I2C_PROC_DEVICE_FILE_READ_ERROR, "Error reading from sensor device file %s", path);
fclose(fp);
return;
}
sensor_value = float3;
break;
case 'v':
/* want first value in file as float */
if (fscanf(fp, "%f", &float1) != 1) {
g_set_error(error, I2C_PROC_DEVICE_FILE_ERROR, I2C_PROC_DEVICE_FILE_READ_ERROR, "Error reading from sensor device file %s", path);
fclose(fp);
return;
}
sensor_value = float1;
break;
default:
g_assert_not_reached();
}
break;
case TEMP_SENSOR:
if (fscanf(fp, "%f %f %f", &float1, &float2, &float3) != 3) {
g_set_error(error, I2C_PROC_DEVICE_FILE_ERROR, I2C_PROC_DEVICE_FILE_READ_ERROR, "Error reading from sensor device file %s", path);
fclose(fp);
return;
}
sensor_value = float3;
break;
default:
g_assert_not_reached();
} /* end switch */
fclose(fp);
return (gdouble)sensor_value;
}
syntax highlighted by Code2HTML, v. 0.9.1