2
0
mirror of https://github.com/lm-sensors/lm-sensors synced 2025-09-05 00:35:35 +00:00
Files
lm-sensors/prog/sensors/main.c
Jean Delvare 79817f34ce Add support for the IT8716F (prefix it8716). It is mostly similar to the
IT8712F so there's not much to do. The most significant difference is that
fan speeds are now reported as 16-bit values, without fan clock dividers.
For this reason, I made the fan_divs optional in sensors. I also made the
fans themselves optional, as I noticed that a number of motherboards don't
use (and don't enable) fan3.

I've made a separate section (chip "it8716-*") in sensors.conf.eg, because
new motherboards tend to have different wirings (e.g. negative voltage
lines are not monitored) so this will make for saner defaults.

Thanks to Stian Oksavik for testing.


git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@4083 7894878c-1315-0410-8ee3-d5d059ff63e0
2006-08-03 20:28:20 +00:00

455 lines
12 KiB
C

/*
main.c - Part of sensors, a user-space program for hardware monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
#include <locale.h>
#include <langinfo.h>
#ifndef __UCLIBC__
#include <iconv.h>
#define HAVE_ICONV
#endif
#include "lib/sensors.h"
#include "lib/error.h"
#include "chips.h"
#include "version.h"
#define PROGRAM "sensors"
#define VERSION LM_VERSION
#define DEFAULT_CONFIG_FILE_NAME "sensors.conf"
FILE *config_file;
extern const char *libsensors_version;
extern int main(int argc, char *arv[]);
static void print_short_help(void);
static void print_long_help(void);
static void print_version(void);
static void do_a_print(sensors_chip_name name);
static int do_a_set(sensors_chip_name name);
static int do_the_real_work(int *error);
static const char *sprintf_chip_name(sensors_chip_name name);
#define CHIPS_MAX 20
sensors_chip_name chips[CHIPS_MAX];
int chips_count=0;
int do_sets, do_unknown, fahrenheit, show_algorithm, hide_adapter, hide_unknown;
char degstr[5]; /* store the correct string to print degrees */
void print_short_help(void)
{
printf("Try `%s -h' for more information\n",PROGRAM);
}
void print_long_help(void)
{
printf("Usage: %s [OPTION]... [CHIP]...\n",PROGRAM);
printf(" -c, --config-file Specify a config file (default: " ETCDIR "/" DEFAULT_CONFIG_FILE_NAME ")\n");
printf(" -h, --help Display this help text\n");
printf(" -s, --set Execute `set' statements too (root only)\n");
printf(" -f, --fahrenheit Show temperatures in degrees fahrenheit\n");
printf(" -a, --algorithm Show algorithm for each chip\n");
printf(" -A, --no-adapter Do not show adapter for each chip\n");
printf(" -U, --no-unknown Do not show unknown chips\n");
printf(" -u, --unknown Treat chips as unknown ones (testing only)\n");
printf(" -v, --version Display the program version\n");
printf("\n");
printf("Use `-' after `-c' to read the config file from stdin.\n");
printf("If no chips are specified, all chip info will be printed.\n");
printf("Example chip names:\n");
printf("\tlm78-i2c-0-2d\t*-i2c-0-2d\n");
printf("\tlm78-i2c-0-*\t*-i2c-0-*\n");
printf("\tlm78-i2c-*-2d\t*-i2c-*-2d\n");
printf("\tlm78-i2c-*-*\t*-i2c-*-*\n");
printf("\tlm78-isa-0290\t*-isa-0290\n");
printf("\tlm78-isa-*\t*-isa-*\n");
printf("\tlm78-*\n");
}
void print_version(void)
{
printf("%s version %s with libsensors version %s\n", PROGRAM, VERSION, libsensors_version);
}
/* This examines global var config_file, and leaves the name there too.
It also opens config_file. */
void open_config_file(const char* config_file_name)
{
if (!strcmp(config_file_name,"-")) {
config_file = stdin;
return;
}
config_file = fopen(config_file_name, "r");
if (!config_file) {
fprintf(stderr, "Could not open config file\n");
perror(config_file_name);
exit(1);
}
}
void close_config_file(const char* config_file_name)
{
if (fclose(config_file) == EOF) {
fprintf(stderr,"Could not close config file\n");
perror(config_file_name);
}
}
static void set_degstr(void)
{
const char *deg_default_text[2] = {" C", " F"};
#ifdef HAVE_ICONV
/* Size hardcoded for better performance.
Don't forget to count the trailing \0! */
size_t deg_latin1_size = 3;
char *deg_latin1_text[2] = {"\260C", "\260F"};
size_t nconv;
size_t degstr_size = sizeof(degstr);
char *degstr_ptr = degstr;
iconv_t cd = iconv_open(nl_langinfo(CODESET), "ISO-8859-1");
if (cd != (iconv_t) -1) {
nconv = iconv(cd, &(deg_latin1_text[fahrenheit]), &deg_latin1_size,
&degstr_ptr, &degstr_size);
iconv_close(cd);
if (nconv != (size_t) -1)
return;
}
#endif /* HAVE_ICONV */
/* There was an error during the conversion, use the default text */
strcpy(degstr, deg_default_text[fahrenheit]);
}
int main (int argc, char *argv[])
{
int c,res,i,error;
char *config_file_name = NULL;
struct option long_opts[] = {
{ "help", no_argument, NULL, 'h' },
{ "set", no_argument, NULL, 's' },
{ "version", no_argument, NULL, 'v'},
{ "fahrenheit", no_argument, NULL, 'f' },
{ "algorithm", no_argument, NULL, 'a' },
{ "no-adapter", no_argument, NULL, 'A' },
{ "no-unknown", no_argument, NULL, 'U' },
{ "config-file", required_argument, NULL, 'c' },
{ "unknown", no_argument, NULL, 'u' },
{ 0,0,0,0 }
};
setlocale(LC_CTYPE, "");
do_unknown = 0;
do_sets = 0;
show_algorithm = 0;
hide_adapter = 0;
hide_unknown = 0;
while (1) {
c = getopt_long(argc,argv,"hsvfaAUc:u",long_opts,NULL);
if (c == EOF)
break;
switch(c) {
case ':':
case '?':
print_short_help();
exit(1);
case 'h':
print_long_help();
exit(0);
case 'v':
print_version();
exit(0);
case 'c':
config_file_name = strdup(optarg);
break;
case 's':
do_sets = 1;
break;
case 'f':
fahrenheit = 1;
break;
case 'a':
show_algorithm = 1;
break;
case 'A':
hide_adapter = 1;
break;
case 'U':
hide_unknown = 1;
break;
case 'u':
do_unknown = 1;
break;
default:
fprintf(stderr,"Internal error while parsing options!\n");
exit(1);
}
}
if (optind == argc) {
chips[0].prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
chips[0].bus = SENSORS_CHIP_NAME_BUS_ANY;
chips[0].addr = SENSORS_CHIP_NAME_ADDR_ANY;
chips_count = 1;
} else
for(i = optind; i < argc; i++)
if ((res = sensors_parse_chip_name(argv[i],chips+chips_count))) {
fprintf(stderr,"Parse error in chip name `%s'\n",argv[i]);
print_short_help();
exit(1);
} else if (++chips_count == CHIPS_MAX) {
fprintf(stderr,"Too many chips on command line!\n");
exit(1);
}
if (config_file_name == NULL)
config_file_name = strdup(ETCDIR "/" DEFAULT_CONFIG_FILE_NAME);
open_config_file(config_file_name);
if ((res = sensors_init(config_file))) {
fprintf(stderr,"%s\n",sensors_strerror(res));
if (res == -SENSORS_ERR_PROC)
fprintf(stderr,
"Unable to find i2c bus information;\n"
"For 2.6 kernels, make sure you have mounted sysfs and libsensors\n"
"was compiled with sysfs support!\n"
"For older kernels, make sure you have done 'modprobe i2c-proc'!\n");
exit(1);
}
close_config_file(config_file_name);
free(config_file_name);
/* build the degrees string */
set_degstr();
if(do_the_real_work(&error)) {
sensors_cleanup();
exit(error);
} else {
if(chips[0].prefix == SENSORS_CHIP_NAME_PREFIX_ANY)
fprintf(stderr,"No sensors found!\n");
else
fprintf(stderr,"Specified sensor(s) not found!\n");
sensors_cleanup();
exit(1);
}
}
/* returns number of chips found */
int do_the_real_work(int *error)
{
const sensors_chip_name *chip;
int chip_nr,i;
int cnt = 0;
*error = 0;
for (chip_nr = 0; (chip = sensors_get_detected_chips(&chip_nr));)
for(i = 0; i < chips_count; i++)
if (sensors_match_chip(*chip,chips[i])) {
if(do_sets) {
if (do_a_set(*chip))
*error = 1;
} else
do_a_print(*chip);
i = chips_count;
cnt++;
}
return(cnt);
}
/* returns 1 on error */
int do_a_set(sensors_chip_name name)
{
int res;
if ((res = sensors_do_chip_sets(name))) {
if (res == -SENSORS_ERR_PROC) {
fprintf(stderr,"%s: %s for writing;\n",sprintf_chip_name(name),
sensors_strerror(res));
fprintf(stderr,"Run as root?\n");
return 1;
} else if (res == -SENSORS_ERR_ACCESS_W) {
fprintf(stderr, "%s: At least one \"set\" statement failed\n",
sprintf_chip_name(name));
} else {
fprintf(stderr,"%s: %s\n",sprintf_chip_name(name),
sensors_strerror(res));
}
}
return 0;
}
const char *sprintf_chip_name(sensors_chip_name name)
{
#define BUF_SIZE 200
static char buf[BUF_SIZE];
if (name.bus == SENSORS_CHIP_NAME_BUS_ISA)
snprintf(buf,BUF_SIZE,"%s-isa-%04x",name.prefix,name.addr);
else if (name.bus == SENSORS_CHIP_NAME_BUS_DUMMY)
snprintf(buf,BUF_SIZE,"%s-%s-%04x",name.prefix,name.busname,name.addr);
else
snprintf(buf,BUF_SIZE,"%s-i2c-%d-%02x",name.prefix,name.bus,name.addr);
return buf;
}
struct match {
const char * prefix;
void (*fn) (const sensors_chip_name *name);
};
struct match matches[] = {
{ "ds1621", print_ds1621 },
{ "lm75", print_lm75 },
{ "adm1021", print_adm1021 },
{ "max1617", print_adm1021 },
{ "max1617a", print_adm1021 },
{ "thmc10", print_adm1021 },
{ "lm84", print_adm1021 },
{ "gl523", print_adm1021 },
{ "adm1023", print_adm1021 },
{ "mc1066", print_adm1021 },
{ "adm9240", print_adm9240 },
{ "ds1780", print_adm9240 },
{ "lm81", print_adm9240 },
{ "lm78", print_lm78 },
{ "lm78-j", print_lm78 },
{ "lm79", print_lm78 },
{ "mtp008", print_mtp008 },
{ "sis5595", print_sis5595 },
{ "via686a", print_via686a },
{ "lm80", print_lm80 },
{ "lm85", print_lm85 },
{ "lm85b", print_lm85 },
{ "lm85c", print_lm85 },
{ "adm1027", print_lm85 },
{ "adt7463", print_lm85 },
{ "emc6d100", print_lm85 },
{ "emc6d102", print_lm85 },
{ "lm87", print_lm87 },
{ "gl518sm", print_gl518 },
{ "gl520sm", print_gl520 },
{ "adm1025", print_adm1025 },
{ "ne1619", print_adm1025 },
{ "adm1024", print_adm1024 },
{ "w83781d", print_w83781d },
{ "w83782d", print_w83781d },
{ "w83783d", print_w83781d },
{ "w83627hf", print_w83781d },
{ "w83627thf", print_w83781d },
{ "w83637hf", print_w83781d },
{ "w83697hf", print_w83781d },
{ "w83687thf", print_w83781d },
{ "w83627ehf", print_w83627ehf },
{ "w83791d", print_w83781d },
{ "w83792d", print_w83792d },
{ "w83l785ts", print_w83l785ts },
{ "as99127f", print_w83781d },
{ "maxilife", print_maxilife },
{ "maxilife-cg", print_maxilife },
{ "maxilife-co", print_maxilife },
{ "maxilife-as", print_maxilife },
{ "maxilife-nba", print_maxilife },
{ "it87", print_it87 },
{ "it8712", print_it87 },
{ "it8716", print_it87 },
{ "ddcmon", print_ddcmon },
{ "eeprom", print_eeprom },
{ "fscpos", print_fscpos },
{ "fscscy", print_fscscy },
{ "fscher", print_fscher },
{ "pcf8591", print_pcf8591 },
{ "vt1211", print_vt1211 },
{ "smsc47m192", print_smsc47m192 },
{ "smsc47m1", print_smsc47m1 },
{ "pc87360", print_pc87360 },
{ "pc87363", print_pc87360 },
{ "pc87364", print_pc87364 },
{ "pc87365", print_pc87366 },
{ "pc87366", print_pc87366 },
{ "lm92", print_lm92 },
{ "vt8231", print_vt8231 },
{ "bmc", print_bmc },
{ "adm1026", print_adm1026 },
{ "lm83", print_lm83 },
{ "lm90", print_lm90 },
{ "adm1032", print_lm90 },
{ "lm99", print_lm90 },
{ "lm86", print_lm90 },
{ "max6657", print_lm90 },
{ "adt7461", print_lm90 },
{ "lm63", print_lm63 },
{ "xeontemp", print_xeontemp },
{ "max6650", print_max6650 },
{ "asb100", print_asb100 },
{ "adm1030", print_adm1031 },
{ "adm1031", print_adm1031 },
{ "lm93", print_lm93 },
{ "smsc47b397", print_smsc47b397 },
{ "f71805f", print_f71805f },
{ "abituguru", print_abituguru },
{ NULL, NULL }
};
void do_a_print(sensors_chip_name name)
{
const char *algo,*adap;
struct match *m;
/* do we know how to display it? */
for(m = matches; m->prefix != NULL; m++) {
if(!strcmp(name.prefix, m->prefix)) break;
}
if(m->prefix==NULL && hide_unknown)
return;
printf("%s\n",sprintf_chip_name(name));
adap = sensors_get_adapter_name(name.bus);
if (adap && !hide_adapter)
printf("Adapter: %s\n",adap);
algo = sensors_get_algorithm_name(name.bus);
if (algo && show_algorithm)
printf("Algorithm: %s\n",algo);
if (!algo || !adap)
printf(" ERROR: Can't get adapter or algorithm?!?\n");
if (do_unknown)
print_unknown_chip(&name);
else {
if(m->prefix == NULL)
print_unknown_chip(&name);
else
m->fn(&name);
}
printf("\n");
}