278 lines
8 KiB
C
278 lines
8 KiB
C
/*
|
|
data.c - Part of libsensors, a Linux library for reading sensor data.
|
|
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
|
|
Copyright (C) 2007, 2009 Jean Delvare <khali@linux-fr.org>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02110-1301 USA.
|
|
*/
|
|
|
|
/*** This file modified by ARM on Jan 23, 2013 to move version.h to the current directory. ***/
|
|
|
|
/* this define needed for strndup() */
|
|
#define _GNU_SOURCE
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "access.h"
|
|
#include "error.h"
|
|
#include "data.h"
|
|
#include "sensors.h"
|
|
#include "version.h"
|
|
|
|
const char *libsensors_version = LM_VERSION;
|
|
|
|
char **sensors_config_files = NULL;
|
|
int sensors_config_files_count = 0;
|
|
int sensors_config_files_max = 0;
|
|
|
|
sensors_chip *sensors_config_chips = NULL;
|
|
int sensors_config_chips_count = 0;
|
|
int sensors_config_chips_subst = 0;
|
|
int sensors_config_chips_max = 0;
|
|
|
|
sensors_bus *sensors_config_busses = NULL;
|
|
int sensors_config_busses_count = 0;
|
|
int sensors_config_busses_max = 0;
|
|
|
|
sensors_chip_features *sensors_proc_chips = NULL;
|
|
int sensors_proc_chips_count = 0;
|
|
int sensors_proc_chips_max = 0;
|
|
|
|
sensors_bus *sensors_proc_bus = NULL;
|
|
int sensors_proc_bus_count = 0;
|
|
int sensors_proc_bus_max = 0;
|
|
|
|
void sensors_free_chip_name(sensors_chip_name *chip)
|
|
{
|
|
free(chip->prefix);
|
|
}
|
|
|
|
/*
|
|
Parse a chip name to the internal representation. These are valid names:
|
|
|
|
lm78-i2c-10-5e *-i2c-10-5e
|
|
lm78-i2c-10-* *-i2c-10-*
|
|
lm78-i2c-*-5e *-i2c-*-5e
|
|
lm78-i2c-*-* *-i2c-*-*
|
|
lm78-isa-10dd *-isa-10dd
|
|
lm78-isa-* *-isa-*
|
|
lm78-* *-*
|
|
|
|
Here 'lm78' can be any prefix. 'i2c' and 'isa' are
|
|
literal strings, just like all dashes '-' and wildcards '*'. '10' can
|
|
be any decimal i2c bus number. '5e' can be any hexadecimal i2c device
|
|
address, and '10dd' any hexadecimal isa address.
|
|
|
|
The 'prefix' part in the result is freshly allocated. All old contents
|
|
of res is overwritten. res itself is not allocated. In case of an error
|
|
return (ie. != 0), res is undefined, but all allocations are undone.
|
|
*/
|
|
|
|
int sensors_parse_chip_name(const char *name, sensors_chip_name *res)
|
|
{
|
|
char *dash;
|
|
|
|
/* First, the prefix. It's either "*" or a real chip name. */
|
|
if (!strncmp(name, "*-", 2)) {
|
|
res->prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
|
|
name += 2;
|
|
} else {
|
|
if (!(dash = strchr(name, '-')))
|
|
return -SENSORS_ERR_CHIP_NAME;
|
|
res->prefix = strndup(name, dash - name);
|
|
if (!res->prefix)
|
|
sensors_fatal_error(__func__,
|
|
"Allocating name prefix");
|
|
name = dash + 1;
|
|
}
|
|
|
|
/* Then we have either a sole "*" (all chips with this name) or a bus
|
|
type and an address. */
|
|
if (!strcmp(name, "*")) {
|
|
res->bus.type = SENSORS_BUS_TYPE_ANY;
|
|
res->bus.nr = SENSORS_BUS_NR_ANY;
|
|
res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
|
|
return 0;
|
|
}
|
|
|
|
if (!(dash = strchr(name, '-')))
|
|
goto ERROR;
|
|
if (!strncmp(name, "i2c", dash - name))
|
|
res->bus.type = SENSORS_BUS_TYPE_I2C;
|
|
else if (!strncmp(name, "isa", dash - name))
|
|
res->bus.type = SENSORS_BUS_TYPE_ISA;
|
|
else if (!strncmp(name, "pci", dash - name))
|
|
res->bus.type = SENSORS_BUS_TYPE_PCI;
|
|
else if (!strncmp(name, "spi", dash - name))
|
|
res->bus.type = SENSORS_BUS_TYPE_SPI;
|
|
else if (!strncmp(name, "virtual", dash - name))
|
|
res->bus.type = SENSORS_BUS_TYPE_VIRTUAL;
|
|
else if (!strncmp(name, "acpi", dash - name))
|
|
res->bus.type = SENSORS_BUS_TYPE_ACPI;
|
|
else if (!strncmp(name, "hid", dash - name))
|
|
res->bus.type = SENSORS_BUS_TYPE_HID;
|
|
else
|
|
goto ERROR;
|
|
name = dash + 1;
|
|
|
|
/* Some bus types (i2c, spi) have an additional bus number.
|
|
For these, the next part is either a "*" (any bus of that type)
|
|
or a decimal number. */
|
|
switch (res->bus.type) {
|
|
case SENSORS_BUS_TYPE_I2C:
|
|
case SENSORS_BUS_TYPE_SPI:
|
|
case SENSORS_BUS_TYPE_HID:
|
|
if (!strncmp(name, "*-", 2)) {
|
|
res->bus.nr = SENSORS_BUS_NR_ANY;
|
|
name += 2;
|
|
break;
|
|
}
|
|
|
|
res->bus.nr = strtoul(name, &dash, 10);
|
|
if (*name == '\0' || *dash != '-' || res->bus.nr < 0)
|
|
goto ERROR;
|
|
name = dash + 1;
|
|
break;
|
|
default:
|
|
res->bus.nr = SENSORS_BUS_NR_ANY;
|
|
}
|
|
|
|
/* Last part is the chip address, or "*" for any address. */
|
|
if (!strcmp(name, "*")) {
|
|
res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
|
|
} else {
|
|
res->addr = strtoul(name, &dash, 16);
|
|
if (*name == '\0' || *dash != '\0' || res->addr < 0)
|
|
goto ERROR;
|
|
}
|
|
|
|
return 0;
|
|
|
|
ERROR:
|
|
free(res->prefix);
|
|
return -SENSORS_ERR_CHIP_NAME;
|
|
}
|
|
|
|
int sensors_snprintf_chip_name(char *str, size_t size,
|
|
const sensors_chip_name *chip)
|
|
{
|
|
if (sensors_chip_name_has_wildcards(chip))
|
|
return -SENSORS_ERR_WILDCARDS;
|
|
|
|
switch (chip->bus.type) {
|
|
case SENSORS_BUS_TYPE_ISA:
|
|
return snprintf(str, size, "%s-isa-%04x", chip->prefix,
|
|
chip->addr);
|
|
case SENSORS_BUS_TYPE_PCI:
|
|
return snprintf(str, size, "%s-pci-%04x", chip->prefix,
|
|
chip->addr);
|
|
case SENSORS_BUS_TYPE_I2C:
|
|
return snprintf(str, size, "%s-i2c-%hd-%02x", chip->prefix,
|
|
chip->bus.nr, chip->addr);
|
|
case SENSORS_BUS_TYPE_SPI:
|
|
return snprintf(str, size, "%s-spi-%hd-%x", chip->prefix,
|
|
chip->bus.nr, chip->addr);
|
|
case SENSORS_BUS_TYPE_VIRTUAL:
|
|
return snprintf(str, size, "%s-virtual-%x", chip->prefix,
|
|
chip->addr);
|
|
case SENSORS_BUS_TYPE_ACPI:
|
|
return snprintf(str, size, "%s-acpi-%x", chip->prefix,
|
|
chip->addr);
|
|
case SENSORS_BUS_TYPE_HID:
|
|
return snprintf(str, size, "%s-hid-%hd-%x", chip->prefix,
|
|
chip->bus.nr, chip->addr);
|
|
}
|
|
|
|
return -SENSORS_ERR_CHIP_NAME;
|
|
}
|
|
|
|
int sensors_parse_bus_id(const char *name, sensors_bus_id *bus)
|
|
{
|
|
char *endptr;
|
|
|
|
if (strncmp(name, "i2c-", 4)) {
|
|
return -SENSORS_ERR_BUS_NAME;
|
|
}
|
|
name += 4;
|
|
bus->type = SENSORS_BUS_TYPE_I2C;
|
|
bus->nr = strtoul(name, &endptr, 10);
|
|
if (*name == '\0' || *endptr != '\0' || bus->nr < 0)
|
|
return -SENSORS_ERR_BUS_NAME;
|
|
return 0;
|
|
}
|
|
|
|
static int sensors_substitute_chip(sensors_chip_name *name,
|
|
const char *filename, int lineno)
|
|
{
|
|
int i, j;
|
|
for (i = 0; i < sensors_config_busses_count; i++)
|
|
if (sensors_config_busses[i].bus.type == name->bus.type &&
|
|
sensors_config_busses[i].bus.nr == name->bus.nr)
|
|
break;
|
|
|
|
if (i == sensors_config_busses_count) {
|
|
sensors_parse_error_wfn("Undeclared bus id referenced",
|
|
filename, lineno);
|
|
name->bus.nr = SENSORS_BUS_NR_IGNORE;
|
|
return -SENSORS_ERR_BUS_NAME;
|
|
}
|
|
|
|
/* Compare the adapter names */
|
|
for (j = 0; j < sensors_proc_bus_count; j++) {
|
|
if (!strcmp(sensors_config_busses[i].adapter,
|
|
sensors_proc_bus[j].adapter)) {
|
|
name->bus.nr = sensors_proc_bus[j].bus.nr;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* We did not find a matching bus name, simply ignore this chip
|
|
config entry. */
|
|
name->bus.nr = SENSORS_BUS_NR_IGNORE;
|
|
return 0;
|
|
}
|
|
|
|
/* Bus substitution is on a per-configuration file basis, so we keep
|
|
memory (in sensors_config_chips_subst) of which chip entries have been
|
|
already substituted. */
|
|
int sensors_substitute_busses(void)
|
|
{
|
|
int err, i, j, lineno;
|
|
sensors_chip_name_list *chips;
|
|
const char *filename;
|
|
int res = 0;
|
|
|
|
for (i = sensors_config_chips_subst;
|
|
i < sensors_config_chips_count; i++) {
|
|
filename = sensors_config_chips[i].line.filename;
|
|
lineno = sensors_config_chips[i].line.lineno;
|
|
chips = &sensors_config_chips[i].chips;
|
|
for (j = 0; j < chips->fits_count; j++) {
|
|
/* We can only substitute if a specific bus number
|
|
is given. */
|
|
if (chips->fits[j].bus.nr == SENSORS_BUS_NR_ANY)
|
|
continue;
|
|
|
|
err = sensors_substitute_chip(&chips->fits[j],
|
|
filename, lineno);
|
|
if (err)
|
|
res = err;
|
|
}
|
|
}
|
|
sensors_config_chips_subst = sensors_config_chips_count;
|
|
return res;
|
|
}
|