1998-12-20 16:54:03 +00:00
|
|
|
/*
|
|
|
|
proc.c - Part of libsensors, a Linux library for reading sensor data.
|
1999-02-08 22:50:29 +00:00
|
|
|
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
|
1998-12-20 16:54:03 +00:00
|
|
|
|
|
|
|
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
2004-01-17 18:12:38 +00:00
|
|
|
/* for open() */
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
1998-12-20 16:54:03 +00:00
|
|
|
#include <stddef.h>
|
2004-01-17 18:12:38 +00:00
|
|
|
#include <unistd.h>
|
1998-12-21 14:14:25 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
1998-12-20 16:54:03 +00:00
|
|
|
#include <sys/sysctl.h>
|
1999-01-27 06:10:00 +00:00
|
|
|
#include "kernel/include/sensors.h"
|
1998-12-20 16:54:03 +00:00
|
|
|
#include "data.h"
|
|
|
|
#include "error.h"
|
|
|
|
#include "access.h"
|
|
|
|
#include "general.h"
|
2003-11-16 19:43:05 +00:00
|
|
|
#include <limits.h>
|
|
|
|
#include <dirent.h>
|
1998-12-20 16:54:03 +00:00
|
|
|
|
|
|
|
/* OK, this proves one thing: if there are too many chips detected, we get in
|
|
|
|
trouble. The limit is around 4096/sizeof(struct sensors_chip_data), which
|
|
|
|
works out to about 100 entries right now. That seems sensible enough,
|
|
|
|
but if we ever get at the point where more chips can be detected, we must
|
|
|
|
enlarge buf, and check that sysctl can handle larger buffers. */
|
|
|
|
|
|
|
|
#define BUF_LEN 4096
|
|
|
|
|
|
|
|
static char buf[BUF_LEN];
|
|
|
|
|
1998-12-21 14:14:25 +00:00
|
|
|
sensors_proc_chips_entry *sensors_proc_chips;
|
2003-11-16 17:57:29 +00:00
|
|
|
int sensors_proc_chips_count, sensors_proc_chips_max;
|
|
|
|
int sensors_sys_chips_count, sensors_sys_chips_max;
|
1998-12-21 14:14:25 +00:00
|
|
|
|
2003-11-16 17:57:29 +00:00
|
|
|
sensors_bus *sensors_sys_bus;
|
|
|
|
int sensors_sys_bus_count, sensors_sys_bus_max;
|
1998-12-21 14:14:25 +00:00
|
|
|
sensors_bus *sensors_proc_bus;
|
2003-11-16 17:57:29 +00:00
|
|
|
int sensors_proc_bus_count, sensors_proc_bus_max;
|
1998-12-21 14:14:25 +00:00
|
|
|
|
1998-12-20 16:54:03 +00:00
|
|
|
static int sensors_get_chip_id(sensors_chip_name name);
|
|
|
|
|
2003-11-16 17:57:29 +00:00
|
|
|
int foundsysfs=0;
|
2003-11-16 19:43:05 +00:00
|
|
|
char sysfsmount[NAME_MAX];
|
2003-11-16 17:57:29 +00:00
|
|
|
|
1998-12-20 16:54:03 +00:00
|
|
|
#define add_proc_chips(el) sensors_add_array_el(el,\
|
|
|
|
(void **) &sensors_proc_chips,\
|
|
|
|
&sensors_proc_chips_count,\
|
|
|
|
&sensors_proc_chips_max,\
|
|
|
|
sizeof(struct sensors_proc_chips_entry))
|
|
|
|
|
2003-11-16 17:57:29 +00:00
|
|
|
#define add_proc_bus(el) sensors_add_array_el(el,\
|
1998-12-21 14:14:25 +00:00
|
|
|
(void **) &sensors_proc_bus,\
|
|
|
|
&sensors_proc_bus_count,\
|
|
|
|
&sensors_proc_bus_max,\
|
|
|
|
sizeof(struct sensors_bus))
|
|
|
|
|
2003-11-19 03:11:13 +00:00
|
|
|
int getsysname(const sensors_chip_feature *feature, char *sysname, int *sysmag);
|
|
|
|
|
1998-12-20 16:54:03 +00:00
|
|
|
/* This reads /proc/sys/dev/sensors/chips into memory */
|
|
|
|
int sensors_read_proc_chips(void)
|
|
|
|
{
|
2003-11-16 17:57:29 +00:00
|
|
|
struct dirent *de;
|
|
|
|
DIR *dir;
|
|
|
|
FILE *f;
|
|
|
|
char dev[NAME_MAX], fstype[NAME_MAX], sysfs[NAME_MAX], n[NAME_MAX];
|
|
|
|
char dirname[NAME_MAX];
|
|
|
|
int res;
|
|
|
|
|
|
|
|
int name[3] = { CTL_DEV, DEV_SENSORS, SENSORS_CHIPS };
|
|
|
|
int buflen = BUF_LEN;
|
|
|
|
char *bufptr = buf;
|
|
|
|
sensors_proc_chips_entry entry;
|
|
|
|
int lineno;
|
|
|
|
|
|
|
|
/* First figure out where sysfs was mounted */
|
|
|
|
if ((f = fopen("/proc/mounts", "r")) == NULL)
|
|
|
|
goto proc;
|
|
|
|
while (fgets(n, NAME_MAX, f)) {
|
|
|
|
sscanf(n, "%[^ ] %[^ ] %[^ ] %*s\n", dev, sysfs, fstype);
|
|
|
|
if (strcasecmp(fstype, "sysfs") == 0) {
|
|
|
|
foundsysfs++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
if (! foundsysfs)
|
|
|
|
goto proc;
|
2003-11-16 19:43:05 +00:00
|
|
|
strcpy(sysfsmount, sysfs);
|
2003-11-16 17:57:29 +00:00
|
|
|
strcat(sysfs, "/bus/i2c/devices");
|
|
|
|
|
|
|
|
/* Then read from it */
|
2003-11-16 19:43:05 +00:00
|
|
|
dir = opendir(sysfs);
|
2003-11-16 17:57:29 +00:00
|
|
|
if (! dir)
|
|
|
|
goto proc;
|
|
|
|
|
|
|
|
while ((de = readdir(dir)) != NULL) {
|
2003-11-16 19:43:05 +00:00
|
|
|
if (!strcmp(de->d_name, "."))
|
2003-11-16 17:57:29 +00:00
|
|
|
continue;
|
2003-11-16 19:43:05 +00:00
|
|
|
if (!strcmp(de->d_name, ".."))
|
2003-11-16 17:57:29 +00:00
|
|
|
continue;
|
|
|
|
/*
|
|
|
|
if (de->d_type != DT_DIR && de->d_type != DT_LNK)
|
|
|
|
continue;
|
|
|
|
*/
|
|
|
|
|
2003-11-17 14:22:05 +00:00
|
|
|
sprintf(n, "%s/%s", sysfs, de->d_name);
|
2003-11-16 17:57:29 +00:00
|
|
|
strcpy(dirname, n);
|
|
|
|
strcat(n, "/name");
|
|
|
|
|
|
|
|
if ((f = fopen(n, "r")) != NULL) {
|
|
|
|
char x[120];
|
2003-11-16 19:43:05 +00:00
|
|
|
fscanf(f, "%[a-zA-z0-9_]", x);
|
2003-11-16 19:54:38 +00:00
|
|
|
fclose(f);
|
2003-11-16 17:57:29 +00:00
|
|
|
/* HACK */ strcat(x, "-*");
|
|
|
|
if ((res = sensors_parse_chip_name(x, &entry.name))) {
|
|
|
|
char em[NAME_MAX + 20];
|
|
|
|
strcpy(em, "Parsing ");
|
|
|
|
strcat(em, n);
|
|
|
|
sensors_parse_error(em, 0);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
entry.name.busname = strdup(dirname);
|
2003-11-22 22:27:47 +00:00
|
|
|
sscanf(de->d_name, "%d-%x", &entry.name.bus, &entry.name.addr);
|
2003-11-16 19:54:38 +00:00
|
|
|
/* find out if ISA or not */
|
|
|
|
sprintf(n, "%s/class/i2c-adapter/i2c-%d/device/name",
|
|
|
|
sysfsmount, entry.name.bus);
|
|
|
|
if ((f = fopen(n, "r")) != NULL) {
|
|
|
|
fgets(x, 5, f);
|
|
|
|
fclose(f);
|
|
|
|
if(!strncmp(x, "ISA ", 4))
|
|
|
|
entry.name.bus = SENSORS_CHIP_NAME_BUS_ISA;
|
|
|
|
}
|
2003-11-16 17:57:29 +00:00
|
|
|
add_proc_chips(&entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
closedir(dir);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
proc:
|
1998-12-20 16:54:03 +00:00
|
|
|
|
|
|
|
if (sysctl(name, 3, bufptr, &buflen, NULL, 0))
|
|
|
|
return -SENSORS_ERR_PROC;
|
|
|
|
|
1998-12-25 22:15:48 +00:00
|
|
|
lineno = 1;
|
2001-05-27 22:49:28 +00:00
|
|
|
while (buflen >= sizeof(struct i2c_chips_data)) {
|
1998-12-20 16:54:03 +00:00
|
|
|
if ((res =
|
2001-05-27 22:49:28 +00:00
|
|
|
sensors_parse_chip_name(((struct i2c_chips_data *) bufptr)->name,
|
1998-12-25 22:15:48 +00:00
|
|
|
&entry.name))) {
|
|
|
|
sensors_parse_error("Parsing /proc/sys/dev/sensors/chips",lineno);
|
1998-12-20 16:54:03 +00:00
|
|
|
return res;
|
1998-12-25 22:15:48 +00:00
|
|
|
}
|
2001-05-27 22:49:28 +00:00
|
|
|
entry.sysctl = ((struct i2c_chips_data *) bufptr)->sysctl_id;
|
1998-12-20 16:54:03 +00:00
|
|
|
add_proc_chips(&entry);
|
2001-05-27 22:49:28 +00:00
|
|
|
bufptr += sizeof(struct i2c_chips_data);
|
|
|
|
buflen -= sizeof(struct i2c_chips_data);
|
1998-12-25 22:15:48 +00:00
|
|
|
lineno++;
|
1998-12-20 16:54:03 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1998-12-21 14:14:25 +00:00
|
|
|
int sensors_read_proc_bus(void)
|
|
|
|
{
|
2003-11-16 19:43:05 +00:00
|
|
|
struct dirent *de;
|
|
|
|
DIR *dir;
|
2003-11-16 17:57:29 +00:00
|
|
|
FILE *f;
|
|
|
|
char line[255];
|
|
|
|
char *border;
|
|
|
|
sensors_bus entry;
|
|
|
|
int lineno;
|
2003-11-16 19:43:05 +00:00
|
|
|
char sysfs[NAME_MAX], n[NAME_MAX];
|
|
|
|
char dirname[NAME_MAX];
|
2003-11-16 17:57:29 +00:00
|
|
|
|
|
|
|
if(foundsysfs) {
|
2003-11-16 19:43:05 +00:00
|
|
|
strcpy(sysfs, sysfsmount);
|
|
|
|
strcat(sysfs, "/class/i2c-adapter");
|
|
|
|
/* Then read from it */
|
|
|
|
dir = opendir(sysfs);
|
|
|
|
if (! dir)
|
|
|
|
goto proc;
|
|
|
|
|
|
|
|
while ((de = readdir(dir)) != NULL) {
|
|
|
|
if (!strcmp(de->d_name, "."))
|
|
|
|
continue;
|
|
|
|
if (!strcmp(de->d_name, ".."))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
strcpy(n, sysfs);
|
|
|
|
strcat(n, "/");
|
|
|
|
strcat(n, de->d_name);
|
|
|
|
strcpy(dirname, n);
|
|
|
|
strcat(n, "/device/name");
|
|
|
|
|
|
|
|
if ((f = fopen(n, "r")) != NULL) {
|
|
|
|
char x[120];
|
|
|
|
fgets(x, 120, f);
|
|
|
|
fclose(f);
|
|
|
|
if((border = index(x, '\n')) != NULL)
|
|
|
|
*border = 0;
|
|
|
|
entry.adapter=strdup(x);
|
|
|
|
if(!strncmp(x, "ISA ", 4)) {
|
|
|
|
entry.number = SENSORS_CHIP_NAME_BUS_ISA;
|
2003-11-29 17:44:30 +00:00
|
|
|
entry.algorithm = strdup("ISA bus algorithm");
|
2003-11-22 22:27:47 +00:00
|
|
|
} else if(!sscanf(de->d_name, "i2c-%d", &entry.number)) {
|
2003-11-16 19:43:05 +00:00
|
|
|
entry.number = SENSORS_CHIP_NAME_BUS_DUMMY;
|
2003-11-29 17:44:30 +00:00
|
|
|
entry.algorithm = strdup("Dummy bus algorithm");
|
2003-11-16 19:43:05 +00:00
|
|
|
} else
|
2003-11-29 17:44:30 +00:00
|
|
|
entry.algorithm = strdup("Unavailable from sysfs");
|
|
|
|
if (entry.algorithm == NULL)
|
|
|
|
goto FAT_ERROR_SYS;
|
2003-11-16 19:43:05 +00:00
|
|
|
add_proc_bus(&entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
closedir(dir);
|
2003-11-16 17:57:29 +00:00
|
|
|
return 0;
|
2003-11-29 17:44:30 +00:00
|
|
|
FAT_ERROR_SYS:
|
|
|
|
sensors_fatal_error("sensors_read_proc_bus", "Allocating entry");
|
|
|
|
closedir(dir);
|
|
|
|
return -SENSORS_ERR_PROC;
|
2003-11-16 17:57:29 +00:00
|
|
|
}
|
1998-12-25 22:15:48 +00:00
|
|
|
|
2003-11-16 19:43:05 +00:00
|
|
|
proc:
|
|
|
|
|
1998-12-21 14:14:25 +00:00
|
|
|
f = fopen("/proc/bus/i2c","r");
|
|
|
|
if (!f)
|
|
|
|
return -SENSORS_ERR_PROC;
|
1998-12-25 22:15:48 +00:00
|
|
|
lineno=1;
|
1998-12-21 14:14:25 +00:00
|
|
|
while (fgets(line,255,f)) {
|
1998-12-22 01:25:25 +00:00
|
|
|
if (strlen(line) > 0)
|
|
|
|
line[strlen(line)-1] = '\0';
|
1998-12-21 14:14:25 +00:00
|
|
|
if (! (border = rindex(line,'\t')))
|
|
|
|
goto ERROR;
|
|
|
|
if (! (entry.algorithm = strdup(border+1)))
|
|
|
|
goto FAT_ERROR;
|
|
|
|
*border='\0';
|
|
|
|
if (! (border = rindex(line,'\t')))
|
|
|
|
goto ERROR;
|
|
|
|
if (! (entry.adapter = strdup(border + 1)))
|
|
|
|
goto FAT_ERROR;
|
|
|
|
*border='\0';
|
|
|
|
if (! (border = rindex(line,'\t')))
|
|
|
|
goto ERROR;
|
|
|
|
*border='\0';
|
|
|
|
if (strncmp(line,"i2c-",4))
|
|
|
|
goto ERROR;
|
|
|
|
if (sensors_parse_i2cbus_name(line,&entry.number))
|
|
|
|
goto ERROR;
|
1998-12-22 01:25:25 +00:00
|
|
|
sensors_strip_of_spaces(entry.algorithm);
|
|
|
|
sensors_strip_of_spaces(entry.adapter);
|
2003-11-16 17:57:29 +00:00
|
|
|
add_proc_bus(&entry);
|
1998-12-25 22:15:48 +00:00
|
|
|
lineno++;
|
1998-12-21 14:14:25 +00:00
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
return 0;
|
|
|
|
FAT_ERROR:
|
|
|
|
sensors_fatal_error("sensors_read_proc_bus","Allocating entry");
|
|
|
|
ERROR:
|
1998-12-25 22:15:48 +00:00
|
|
|
sensors_parse_error("Parsing /proc/bus/i2c",lineno);
|
1998-12-21 14:14:25 +00:00
|
|
|
fclose(f);
|
|
|
|
return -SENSORS_ERR_PROC;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-12-20 16:54:03 +00:00
|
|
|
/* This returns the first detected chip which matches the name */
|
|
|
|
int sensors_get_chip_id(sensors_chip_name name)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < sensors_proc_chips_count; i++)
|
|
|
|
if (sensors_match_chip(name, sensors_proc_chips[i].name))
|
|
|
|
return sensors_proc_chips[i].sysctl;
|
|
|
|
return -SENSORS_ERR_NO_ENTRY;
|
|
|
|
}
|
|
|
|
|
2003-12-13 19:01:43 +00:00
|
|
|
/* This reads a feature /proc or /sys file.
|
|
|
|
Sysfs uses a one-value-per file system...
|
|
|
|
except for eeprom, which puts the entire eeprom into one file.
|
|
|
|
*/
|
1998-12-20 16:54:03 +00:00
|
|
|
int sensors_read_proc(sensors_chip_name name, int feature, double *value)
|
|
|
|
{
|
2003-11-17 14:22:05 +00:00
|
|
|
int sysctl_name[4] = { CTL_DEV, DEV_SENSORS };
|
|
|
|
const sensors_chip_feature *the_feature;
|
|
|
|
int buflen = BUF_LEN;
|
2004-01-17 18:12:38 +00:00
|
|
|
int mag, eepromoffset, fd, ret=0;
|
2003-11-17 14:22:05 +00:00
|
|
|
char n[NAME_MAX];
|
|
|
|
FILE *f;
|
2003-11-16 17:57:29 +00:00
|
|
|
|
|
|
|
if(!foundsysfs)
|
|
|
|
if ((sysctl_name[2] = sensors_get_chip_id(name)) < 0)
|
|
|
|
return sysctl_name[2];
|
|
|
|
if (! (the_feature = sensors_lookup_feature_nr(name.prefix,feature)))
|
|
|
|
return -SENSORS_ERR_NO_ENTRY;
|
|
|
|
if(foundsysfs) {
|
|
|
|
strcpy(n, name.busname);
|
|
|
|
strcat(n, "/");
|
2003-12-13 19:01:43 +00:00
|
|
|
/* total hack for eeprom */
|
|
|
|
if (! strcmp(name.prefix, "eeprom")){
|
|
|
|
strcat(n, "eeprom");
|
2004-01-17 18:12:38 +00:00
|
|
|
/* we use unbuffered I/O to benefit from eeprom driver
|
|
|
|
optimization */
|
|
|
|
if ((fd = open(n, O_RDONLY)) >= 0) {
|
2003-12-13 23:38:08 +00:00
|
|
|
eepromoffset =
|
2003-12-13 19:01:43 +00:00
|
|
|
(the_feature->offset / sizeof(long)) +
|
|
|
|
(16 * (the_feature->sysctl - EEPROM_SYSCTL1));
|
2004-01-17 18:12:38 +00:00
|
|
|
if (lseek(fd, eepromoffset, SEEK_SET) < 0
|
|
|
|
|| read(fd, &ret, 1) != 1) {
|
|
|
|
close(fd);
|
2003-12-13 19:01:43 +00:00
|
|
|
return -SENSORS_ERR_PROC;
|
2004-01-17 18:12:38 +00:00
|
|
|
}
|
|
|
|
close(fd);
|
2003-12-13 19:01:43 +00:00
|
|
|
*value = ret;
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
return -SENSORS_ERR_PROC;
|
|
|
|
} else {
|
|
|
|
/* use rindex to append sysname to n */
|
|
|
|
getsysname(the_feature, rindex(n, '\0'), &mag);
|
|
|
|
if ((f = fopen(n, "r")) != NULL) {
|
|
|
|
fscanf(f, "%lf", value);
|
|
|
|
fclose(f);
|
|
|
|
for (; mag > 0; mag --)
|
|
|
|
*value /= 10.0;
|
|
|
|
// fprintf(stderr, "Feature %s value %lf scale %d offset %d\n",
|
|
|
|
// the_feature->name, *value,
|
|
|
|
// the_feature->scaling, the_feature->offset);
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
return -SENSORS_ERR_PROC;
|
|
|
|
}
|
2003-11-16 17:57:29 +00:00
|
|
|
} else {
|
|
|
|
sysctl_name[3] = the_feature->sysctl;
|
|
|
|
if (sysctl(sysctl_name, 4, buf, &buflen, NULL, 0))
|
|
|
|
return -SENSORS_ERR_PROC;
|
|
|
|
*value = *((long *) (buf + the_feature->offset));
|
|
|
|
for (mag = the_feature->scaling; mag > 0; mag --)
|
|
|
|
*value /= 10.0;
|
|
|
|
for (; mag < 0; mag ++)
|
|
|
|
*value *= 10.0;
|
|
|
|
}
|
|
|
|
return 0;
|
1998-12-20 16:54:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int sensors_write_proc(sensors_chip_name name, int feature, double value)
|
|
|
|
{
|
2003-11-17 14:22:05 +00:00
|
|
|
int sysctl_name[4] = { CTL_DEV, DEV_SENSORS };
|
|
|
|
const sensors_chip_feature *the_feature;
|
|
|
|
int buflen = BUF_LEN;
|
|
|
|
int mag;
|
|
|
|
char n[NAME_MAX];
|
|
|
|
FILE *f;
|
1998-12-20 16:54:03 +00:00
|
|
|
|
2003-11-17 14:22:05 +00:00
|
|
|
if(!foundsysfs)
|
|
|
|
if ((sysctl_name[2] = sensors_get_chip_id(name)) < 0)
|
|
|
|
return sysctl_name[2];
|
|
|
|
if (! (the_feature = sensors_lookup_feature_nr(name.prefix,feature)))
|
|
|
|
return -SENSORS_ERR_NO_ENTRY;
|
|
|
|
if(foundsysfs) {
|
|
|
|
strcpy(n, name.busname);
|
|
|
|
strcat(n, "/");
|
2003-11-19 03:11:13 +00:00
|
|
|
/* use rindex to append sysname to n */
|
|
|
|
getsysname(the_feature, rindex(n, '\0'), &mag);
|
2003-11-17 14:22:05 +00:00
|
|
|
if ((f = fopen(n, "w")) != NULL) {
|
|
|
|
for (; mag > 0; mag --)
|
|
|
|
value *= 10.0;
|
|
|
|
fprintf(f, "%d", (int) value);
|
|
|
|
fclose(f);
|
|
|
|
} else
|
|
|
|
return -SENSORS_ERR_PROC;
|
|
|
|
} else {
|
|
|
|
sysctl_name[3] = the_feature->sysctl;
|
|
|
|
if (sysctl(sysctl_name, 4, buf, &buflen, NULL, 0))
|
|
|
|
return -SENSORS_ERR_PROC;
|
2003-11-24 20:18:47 +00:00
|
|
|
/* The following line is known to solve random problems, still it
|
|
|
|
can't be considered a definitive solution...
|
|
|
|
if (sysctl_name[0] != CTL_DEV) { sysctl_name[0] = CTL_DEV ; } */
|
2003-11-17 14:22:05 +00:00
|
|
|
for (mag = the_feature->scaling; mag > 0; mag --)
|
|
|
|
value *= 10.0;
|
|
|
|
for (; mag < 0; mag ++)
|
|
|
|
value /= 10.0;
|
|
|
|
* ((long *) (buf + the_feature->offset)) = (long) value;
|
|
|
|
buflen = the_feature->offset + sizeof(long);
|
2003-11-29 13:28:54 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
/* The following get* calls don't do anything, they are here
|
|
|
|
for debugging purposes only. Strace will show the
|
|
|
|
returned values. */
|
|
|
|
getuid(); geteuid();
|
|
|
|
getgid(); getegid();
|
|
|
|
#endif
|
2003-11-17 14:22:05 +00:00
|
|
|
if (sysctl(sysctl_name, 4, NULL, 0, buf, buflen))
|
|
|
|
return -SENSORS_ERR_PROC;
|
|
|
|
}
|
|
|
|
return 0;
|
1998-12-20 16:54:03 +00:00
|
|
|
}
|
2003-11-19 03:11:13 +00:00
|
|
|
|
|
|
|
#define CURRMAG 3
|
|
|
|
#define FANMAG 0
|
|
|
|
#define INMAG 3
|
|
|
|
#define TEMPMAG 3
|
|
|
|
|
|
|
|
/*
|
|
|
|
Returns the sysfs name and magnitude for a given feature.
|
|
|
|
First looks for a sysfs name and magnitude in the feature structure.
|
|
|
|
These should be added in chips.c for all non-standard feature names.
|
2003-12-31 21:30:43 +00:00
|
|
|
If that fails, converts common /proc feature names
|
2003-11-19 03:11:13 +00:00
|
|
|
to their sysfs equivalent, and uses common sysfs magnitude.
|
2003-12-30 22:21:40 +00:00
|
|
|
Common magnitudes are #defined above.
|
|
|
|
Common conversions are as follows:
|
|
|
|
fan%d_div -> fan_div%d
|
|
|
|
fan%d_min -> fan_min%d
|
2004-01-26 21:50:42 +00:00
|
|
|
fan%d_state -> fan_status%d
|
2003-12-30 22:21:40 +00:00
|
|
|
fan%d -> fan_input%d
|
|
|
|
in%d_max -> in_max%d
|
|
|
|
in%d_min -> in_min%d
|
|
|
|
in%d -> in_input%d
|
2004-01-05 20:39:59 +00:00
|
|
|
temp%d_over -> temp_max%d
|
|
|
|
temp%d_hyst -> temp_hyst%d
|
2003-12-30 22:21:40 +00:00
|
|
|
temp%d_max -> temp_max%d
|
2003-12-31 21:30:43 +00:00
|
|
|
temp%d_high -> temp_max%d
|
2003-12-30 22:21:40 +00:00
|
|
|
temp%d_min -> temp_min%d
|
2003-12-31 21:30:43 +00:00
|
|
|
temp%d_low -> temp_min%d
|
2004-01-26 21:50:42 +00:00
|
|
|
temp%d_state -> temp_status%d
|
2003-12-30 22:21:40 +00:00
|
|
|
temp%d -> temp_input%d
|
2003-12-31 21:30:43 +00:00
|
|
|
tcrit%d -> temp_crit%d
|
2004-01-09 21:35:27 +00:00
|
|
|
hyst%d -> temp_hyst%d
|
2003-12-30 22:21:40 +00:00
|
|
|
AND all conversions listed in the matches[] structure below.
|
|
|
|
|
2003-11-19 03:11:13 +00:00
|
|
|
If that fails, returns old /proc feature name and magnitude.
|
|
|
|
|
|
|
|
References: doc/developers/proc in the lm_sensors package;
|
|
|
|
Documentation/i2c/sysfs_interface in the kernel
|
|
|
|
*/
|
|
|
|
int getsysname(const sensors_chip_feature *feature, char *sysname, int *sysmag)
|
|
|
|
{
|
|
|
|
const char * name = feature->name;
|
|
|
|
char last;
|
|
|
|
char check; /* used to verify end of string */
|
|
|
|
int num;
|
|
|
|
|
2003-11-22 22:27:47 +00:00
|
|
|
struct match {
|
|
|
|
const char * name, * sysname;
|
|
|
|
const int sysmag;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct match *m;
|
|
|
|
|
|
|
|
struct match matches[] = {
|
|
|
|
{ "beeps", "beep_mask", 0 },
|
|
|
|
{ "pwm", "pwm1", 0 },
|
2003-12-31 21:30:43 +00:00
|
|
|
{ "remote_temp", "temp_input2", TEMPMAG },
|
2003-11-22 22:27:47 +00:00
|
|
|
{ "remote_temp_hyst", "temp_hyst2", TEMPMAG },
|
|
|
|
{ "remote_temp_low", "temp_min2", TEMPMAG },
|
|
|
|
{ "remote_temp_over", "temp_max2", TEMPMAG },
|
|
|
|
{ "temp", "temp_input1", TEMPMAG },
|
2004-01-05 20:39:59 +00:00
|
|
|
{ "temp_hyst", "temp_hyst1", TEMPMAG },
|
2003-11-22 22:27:47 +00:00
|
|
|
{ "temp_low", "temp_min1", TEMPMAG },
|
|
|
|
{ "temp_over", "temp_max1", TEMPMAG },
|
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
2003-11-19 03:11:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* use override in feature structure if present */
|
|
|
|
if(feature->sysname != NULL) {
|
|
|
|
strcpy(sysname, feature->sysname);
|
|
|
|
if(feature->sysscaling)
|
|
|
|
*sysmag = feature->sysscaling;
|
|
|
|
else
|
|
|
|
*sysmag = feature->scaling;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check for constant mappings */
|
|
|
|
for(m = matches; m->name != NULL; m++) {
|
|
|
|
if(!strcmp(m->name, name)) {
|
|
|
|
strcpy(sysname, m->sysname);
|
|
|
|
*sysmag = m->sysmag;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert common /proc names to common sysfs names */
|
|
|
|
if(sscanf(name, "fan%d_di%c%c", &num, &last, &check) == 2 && last == 'v') {
|
|
|
|
sprintf(sysname, "fan_div%d", num);
|
|
|
|
*sysmag = FANMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(sscanf(name, "fan%d_mi%c%c", &num, &last, &check) == 2 && last == 'n') {
|
|
|
|
sprintf(sysname, "fan_min%d", num);
|
|
|
|
*sysmag = FANMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
2004-01-26 21:50:42 +00:00
|
|
|
if(sscanf(name, "fan%d_stat%c%c", &num, &last, &check) == 2 && last == 'e') {
|
|
|
|
sprintf(sysname, "fan_status%d", num);
|
|
|
|
*sysmag = FANMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
2003-11-19 03:11:13 +00:00
|
|
|
if(sscanf(name, "fan%d%c", &num, &check) == 1) {
|
|
|
|
sprintf(sysname, "fan_input%d", num);
|
|
|
|
*sysmag = FANMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sscanf(name, "in%d_mi%c%c", &num, &last, &check) == 2 && last == 'n') {
|
|
|
|
sprintf(sysname, "in_min%d", num);
|
|
|
|
*sysmag = INMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(sscanf(name, "in%d_ma%c%c", &num, &last, &check) == 2 && last == 'x') {
|
|
|
|
sprintf(sysname, "in_max%d", num);
|
|
|
|
*sysmag = INMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(sscanf(name, "in%d%c", &num, &check) == 1) {
|
|
|
|
sprintf(sysname, "in_input%d", num);
|
|
|
|
*sysmag = INMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sscanf(name, "pwm%d%c", &num, &check) == 1) {
|
|
|
|
strcpy(sysname, name);
|
|
|
|
*sysmag = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sscanf(name, "sensor%d%c", &num, &check) == 1) {
|
|
|
|
strcpy(sysname, name);
|
|
|
|
*sysmag = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sscanf(name, "temp%d_hys%c%c", &num, &last, &check) == 2 && last == 't') {
|
2004-01-05 20:39:59 +00:00
|
|
|
sprintf(sysname, "temp_hyst%d", num);
|
2003-11-19 03:11:13 +00:00
|
|
|
*sysmag = TEMPMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(sscanf(name, "temp%d_ove%c%c", &num, &last, &check) == 2 && last == 'r') {
|
|
|
|
sprintf(sysname, "temp_max%d", num);
|
|
|
|
*sysmag = TEMPMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(sscanf(name, "temp%d_mi%c%c", &num, &last, &check) == 2 && last == 'n') {
|
|
|
|
sprintf(sysname, "temp_min%d", num);
|
|
|
|
*sysmag = TEMPMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
2003-12-31 21:30:43 +00:00
|
|
|
if(sscanf(name, "temp%d_lo%c%c", &num, &last, &check) == 2 && last == 'w') {
|
|
|
|
sprintf(sysname, "temp_min%d", num);
|
|
|
|
*sysmag = TEMPMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
2003-11-19 03:11:13 +00:00
|
|
|
if(sscanf(name, "temp%d_ma%c%c", &num, &last, &check) == 2 && last == 'x') {
|
|
|
|
sprintf(sysname, "temp_max%d", num);
|
|
|
|
*sysmag = TEMPMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
2003-12-31 21:30:43 +00:00
|
|
|
if(sscanf(name, "temp%d_hig%c%c", &num, &last, &check) == 2 && last == 'h') {
|
|
|
|
sprintf(sysname, "temp_max%d", num);
|
|
|
|
*sysmag = TEMPMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
2004-01-26 21:50:42 +00:00
|
|
|
if(sscanf(name, "temp%d_stat%c%c", &num, &last, &check) == 2 && last == 'e') {
|
|
|
|
sprintf(sysname, "temp_status%d", num);
|
|
|
|
*sysmag = TEMPMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
2003-12-31 21:30:43 +00:00
|
|
|
if(sscanf(name, "tcrit%d%c", &num, &check) == 1) {
|
|
|
|
sprintf(sysname, "temp_crit%d", num);
|
|
|
|
*sysmag = TEMPMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
2004-01-09 21:35:27 +00:00
|
|
|
if(sscanf(name, "hyst%d%c", &num, &check) == 1) {
|
|
|
|
sprintf(sysname, "temp_hyst%d", num);
|
|
|
|
*sysmag = TEMPMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
2003-11-19 03:11:13 +00:00
|
|
|
if(sscanf(name, "temp%d%c", &num, &check) == 1) {
|
|
|
|
sprintf(sysname, "temp_input%d", num);
|
|
|
|
*sysmag = TEMPMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* bmcsensors only, not yet in kernel */
|
|
|
|
/*
|
|
|
|
if(sscanf(name, "curr%d_mi%c%c", &num, &last, &check) == 2 && last == 'n') {
|
|
|
|
sprintf(sysname, "curr_min%d", num);
|
|
|
|
*sysmag = CURRMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(sscanf(name, "curr%d_ma%c%c", &num, &last, &check) == 2 && last == 'x') {
|
|
|
|
sprintf(sysname, "curr_max%d", num);
|
|
|
|
*sysmag = CURRMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(sscanf(name, "curr%d%c", &num, &check) == 1) {
|
|
|
|
sprintf(sysname, "curr_input%d", num);
|
|
|
|
*sysmag = CURRMAG;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* give up, use old name (probably won't work though...) */
|
|
|
|
/* known to be the same:
|
|
|
|
"alarms", "beep_enable", "vid", "vrm"
|
|
|
|
*/
|
|
|
|
strcpy(sysname, name);
|
|
|
|
*sysmag = feature->scaling;
|
|
|
|
return 0;
|
|
|
|
}
|