--- lm_sensors-2.8.0/lib/proc.c.sysfs 2003-06-09 01:33:38.000000000 +0400 +++ lm_sensors-2.8.0/lib/proc.c 2003-08-23 22:23:33.000000000 +0400 @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include "kernel/include/sensors.h" #include "data.h" @@ -59,6 +61,158 @@ static int sensors_get_chip_id(sensors_c &sensors_proc_bus_max,\ sizeof(struct sensors_bus)) +static int using_sysfs; +static char sysfs_i2c_bus[] = "/sys/bus/i2c/devices"; +static char sysfs_i2c_class[] = "/sys/class/i2c-adapter"; + +/* This parses sysfs tree for available i2c chips */ +static int sensors_parse_sysfs_chips(void) +{ + DIR *dir; + struct dirent *dentry; + char path[256], buf[256]; + FILE *f; + int len; + sensors_proc_chips_entry entry; + + if ((dir = opendir(sysfs_i2c_bus)) == NULL) + return -SENSORS_ERR_PROC; + + using_sysfs = 1; + + while ((dentry = readdir(dir)) != NULL) { + if (dentry->d_name[0] == '.' || dentry->d_ino <= 0) + continue; + snprintf(path, sizeof(path), "%s/%s/name", sysfs_i2c_bus, dentry->d_name); + if ((f = fopen(path, "r")) == NULL) + continue; + buf[0] = '\0'; + fgets(buf, sizeof(buf), f); + fclose(f); + len = strlen(buf) - 1; + if (buf[len] == '\n') + buf[len] = '\0'; + if (strchr(buf, ' ')) + continue; /* e.g. "as99127f subclient" */ + sscanf(dentry->d_name, "%d-%x", &entry.name.bus, &entry.name.addr); + entry.name.prefix = strdup(buf); + + add_proc_chips(&entry); + } + closedir(dir); + return 0; +} + +static int sensors_parse_sysfs_class(void) +{ + DIR *dir; + struct dirent *dentry; + char path[256], buf[256]; + FILE *f; + int len; + sensors_bus entry; + + if ((dir = opendir(sysfs_i2c_class)) == NULL) + return -SENSORS_ERR_PROC; + + while ((dentry = readdir(dir)) != NULL) { + if (dentry->d_name[0] == '.' || dentry->d_ino <= 0) + continue; + + sscanf(dentry->d_name, "i2c-%d", &entry.number); + entry.algorithm = strdup("Not available via sysfs"); + sprintf(path, "%s/%s/device/name", sysfs_i2c_class, dentry->d_name); + if ((f = fopen(path, "r")) == NULL) { + entry.adapter = strdup("UNKNOWN"); + continue; + } + fgets(buf, sizeof(buf), f); + fclose(f); + len = strlen(buf) - 1; + if (buf[len] == '\n') + buf[len] = '\0'; + entry.adapter = strdup(buf); + add_bus(&entry); + } + + return 0; +} + +static int ends_with(const char *str, const char *suffix) +{ + int len = strlen(str); + int slen = strlen(suffix); + + if (len <= slen) + return 0; + + return strcmp(str + len - slen, suffix) == 0; +} + +static void +sensors_sysfs_convert_feature_name(const char *name, char *buf) +{ + char part1[256], part2[256]; + int n; + + if (sscanf(name, "temp%d", &n) == 1) { + if (ends_with(name, "_hyst")) + sprintf(buf, "temp_min%d", n); + else if (ends_with(name, "_over")) + sprintf(buf, "temp_max%d", n); + else + sprintf(buf, "temp_input%d", n); + } else if (sscanf(name, "%[^0-9]%d_%s", part1, &n, part2) == 3) + sprintf(buf, "%s_%s%d", part1, part2, n); + else if (sscanf(name, "%[^0-9]%d", part1, &n) == 2) + sprintf(buf, "%s_input%d", part1, n); + else if (strcmp(name, "beeps") == 0) + strcpy(buf, "beep_mask"); + else + strcpy(buf, name); +} + +/* This reads a feature /proc file */ +static int sensors_read_sysfs(sensors_chip_name name, + const sensors_chip_feature *the_feature, double *value) +{ + char path[256], buf[256]; + FILE *f; + long l; + + sensors_sysfs_convert_feature_name(the_feature->name, buf); + snprintf(path, sizeof(path), "%s/%d-%04x/%s", sysfs_i2c_bus, name.bus, name.addr, buf); + if ((f = fopen(path, "r")) == NULL) + return -SENSORS_ERR_PROC; + fscanf(f, "%ld", &l); + fclose(f); + *value = l; + if (strncmp(buf, "in_", strlen("in_")) == 0 + || strncmp(buf, "temp_", strlen("temp_")) == 0) + *value /= 10.0; + return 0; +} + +static int sensors_write_sysfs(sensors_chip_name name, + const sensors_chip_feature *the_feature, double value) +{ + char path[256], buf[256]; + FILE *f; + long l; + + sensors_sysfs_convert_feature_name(the_feature->name, buf); + snprintf(path, sizeof(path), "%s/%d-%04x/%s", sysfs_i2c_bus, name.bus, name.addr, buf); + if (strncmp(buf, "in_", strlen("in_")) == 0 + || strncmp(buf, "temp_", strlen("temp_")) == 0) + value *= 10.0; + l = (long) value; + if ((f = fopen(path, "w")) == NULL) + return -SENSORS_ERR_PROC; + fprintf(f, "%ld", l); + fclose(f); + + return 0; +} /* This reads /proc/sys/dev/sensors/chips into memory */ int sensors_read_proc_chips(void) { @@ -69,7 +223,7 @@ int sensors_read_proc_chips(void) int res,lineno; if (sysctl(name, 3, bufptr, &buflen, NULL, 0)) - return -SENSORS_ERR_PROC; + return sensors_parse_sysfs_chips(); lineno = 1; while (buflen >= sizeof(struct i2c_chips_data)) { @@ -96,6 +250,9 @@ int sensors_read_proc_bus(void) sensors_bus entry; int lineno; + if (using_sysfs) + return sensors_parse_sysfs_class(); + f = fopen("/proc/bus/i2c","r"); if (!f) return -SENSORS_ERR_PROC; @@ -158,10 +315,17 @@ int sensors_read_proc(sensors_chip_name return sysctl_name[2]; if (! (the_feature = sensors_lookup_feature_nr(name.prefix,feature))) return -SENSORS_ERR_NO_ENTRY; - 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)); + + if (using_sysfs) { + int ret = sensors_read_sysfs(name, the_feature, value); + if (ret) + return ret; + } 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 ++) @@ -180,17 +344,22 @@ int sensors_write_proc(sensors_chip_name return sysctl_name[2]; if (! (the_feature = sensors_lookup_feature_nr(name.prefix,feature))) return -SENSORS_ERR_NO_ENTRY; - sysctl_name[3] = the_feature->sysctl; - if (sysctl(sysctl_name, 4, buf, &buflen, NULL, 0)) - return -SENSORS_ERR_PROC; - if (sysctl_name[0] != CTL_DEV) { sysctl_name[0] = CTL_DEV ; } 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); - if (sysctl(sysctl_name, 4, NULL, 0, buf, buflen)) - return -SENSORS_ERR_PROC; - return 0; + + if (using_sysfs) { + return sensors_write_sysfs(name, the_feature, value); + } else { + sysctl_name[3] = the_feature->sysctl; + if (sysctl(sysctl_name, 4, buf, &buflen, NULL, 0)) + return -SENSORS_ERR_PROC; + if (sysctl_name[0] != CTL_DEV) { sysctl_name[0] = CTL_DEV ; } + * ((long *) (buf + the_feature->offset)) = (long) value; + buflen = the_feature->offset + sizeof(long); + if (sysctl(sysctl_name, 4, NULL, 0, buf, buflen)) + return -SENSORS_ERR_PROC; + return 0; + } }