root/lm-sensors/trunk/lib/proc.c @ 120

Revision 120, 6.1 KB (checked in by frodo, 14 years ago)

Some library cleanup; no interface changes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    proc.c - Part of libsensors, a Linux library for reading sensor data.
3    Copyright (c) 1998  Frodo Looijaard <frodol@dds.nl>
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20#include <stddef.h>
21#include <stdio.h>
22#include <string.h>
23#include <sys/sysctl.h>
24#include <linux/sysctl.h>
25#include "src/sensors.h"
26#include "data.h"
27#include "error.h"
28#include "access.h"
29#include "general.h"
30
31/* OK, this proves one thing: if there are too many chips detected, we get in
32   trouble. The limit is around 4096/sizeof(struct sensors_chip_data), which
33   works out to about 100 entries right now. That seems sensible enough,
34   but if we ever get at the point where more chips can be detected, we must
35   enlarge buf, and check that sysctl can handle larger buffers. */
36
37#define BUF_LEN 4096
38
39static char buf[BUF_LEN];
40
41sensors_proc_chips_entry *sensors_proc_chips;
42int sensors_proc_chips_count;
43int sensors_proc_chips_max;
44
45sensors_bus *sensors_proc_bus;
46int sensors_proc_bus_count;
47int sensors_proc_bus_max;
48
49static int sensors_get_chip_id(sensors_chip_name name);
50
51#define add_proc_chips(el) sensors_add_array_el(el,\
52                                       (void **) &sensors_proc_chips,\
53                                       &sensors_proc_chips_count,\
54                                       &sensors_proc_chips_max,\
55                                       sizeof(struct sensors_proc_chips_entry))
56
57#define add_bus(el) sensors_add_array_el(el,\
58                                       (void **) &sensors_proc_bus,\
59                                       &sensors_proc_bus_count,\
60                                       &sensors_proc_bus_max,\
61                                       sizeof(struct sensors_bus))
62
63/* This reads /proc/sys/dev/sensors/chips into memory */
64int sensors_read_proc_chips(void)
65{
66  int name[3] = { CTL_DEV, DEV_SENSORS, SENSORS_CHIPS };
67  int buflen = BUF_LEN;
68  char *bufptr = buf;
69  sensors_proc_chips_entry entry;
70  int res,lineno;
71
72  if (sysctl(name, 3, bufptr, &buflen, NULL, 0))
73    return -SENSORS_ERR_PROC;
74
75  lineno = 1;
76  while (buflen >= sizeof(struct sensors_chips_data)) {
77    if ((res = 
78          sensors_parse_chip_name(((struct sensors_chips_data *) bufptr)->name, 
79                                   &entry.name))) {
80      sensors_parse_error("Parsing /proc/sys/dev/sensors/chips",lineno);
81      return res;
82    }
83    entry.sysctl = ((struct sensors_chips_data *) bufptr)->sysctl_id;
84    add_proc_chips(&entry);
85    bufptr += sizeof(struct sensors_chips_data);
86    buflen -= sizeof(struct sensors_chips_data);
87    lineno++;
88  }
89  return 0;
90}
91
92int sensors_read_proc_bus(void)
93{
94  FILE *f;
95  char line[255];
96  char *border;
97  sensors_bus entry;
98  int lineno;
99
100  f = fopen("/proc/bus/i2c","r");
101  if (!f)
102    return -SENSORS_ERR_PROC;
103  lineno=1;
104  while (fgets(line,255,f)) {
105    if (strlen(line) > 0)
106      line[strlen(line)-1] = '\0';
107    if (! (border = rindex(line,'\t')))
108      goto ERROR;
109    if (! (entry.algorithm = strdup(border+1)))
110      goto FAT_ERROR;
111    *border='\0';
112    if (! (border = rindex(line,'\t')))
113      goto ERROR;
114    if (! (entry.adapter = strdup(border + 1)))
115      goto FAT_ERROR;
116    *border='\0';
117    if (! (border = rindex(line,'\t')))
118      goto ERROR;
119    *border='\0';
120    if (strncmp(line,"i2c-",4))
121      goto ERROR;
122    if (sensors_parse_i2cbus_name(line,&entry.number))
123      goto ERROR;
124    sensors_strip_of_spaces(entry.algorithm);
125    sensors_strip_of_spaces(entry.adapter);
126    add_bus(&entry);
127    lineno++;
128  }
129  fclose(f);
130  return 0;
131FAT_ERROR:
132  sensors_fatal_error("sensors_read_proc_bus","Allocating entry");
133ERROR:
134  sensors_parse_error("Parsing /proc/bus/i2c",lineno);
135  fclose(f);
136  return -SENSORS_ERR_PROC;
137}
138   
139
140/* This returns the first detected chip which matches the name */
141int sensors_get_chip_id(sensors_chip_name name)
142{
143  int i;
144  for (i = 0; i < sensors_proc_chips_count; i++)
145    if (sensors_match_chip(name, sensors_proc_chips[i].name))
146      return sensors_proc_chips[i].sysctl;
147  return -SENSORS_ERR_NO_ENTRY;
148}
149 
150/* This reads a feature /proc file */
151int sensors_read_proc(sensors_chip_name name, int feature, double *value)
152{
153  int sysctl_name[4] = { CTL_DEV, DEV_SENSORS };
154  const sensors_chip_feature *the_feature;
155  int buflen = BUF_LEN;
156  int mag;
157 
158  if ((sysctl_name[2] = sensors_get_chip_id(name)) < 0)
159    return sysctl_name[2];
160  if (! (the_feature = sensors_lookup_feature_nr(name.prefix,feature)))
161    return -SENSORS_ERR_NO_ENTRY;
162  sysctl_name[3] = the_feature->sysctl;
163  if (sysctl(sysctl_name, 4, buf, &buflen, NULL, 0))
164    return -SENSORS_ERR_PROC;
165  *value = *((long *) (buf + the_feature->offset));
166  for (mag = the_feature->scaling; mag > 0; mag --)
167    *value /= 10.0;
168  for (; mag < 0; mag --)
169    *value *= 10.0;
170  return 0;
171}
172 
173int sensors_write_proc(sensors_chip_name name, int feature, double value)
174{
175  int sysctl_name[4] = { CTL_DEV, DEV_SENSORS };
176  const sensors_chip_feature *the_feature;
177  int buflen = BUF_LEN;
178  int mag;
179 
180  if ((sysctl_name[2] = sensors_get_chip_id(name)) < 0)
181    return sysctl_name[2];
182  if (! (the_feature = sensors_lookup_feature_nr(name.prefix,feature)))
183    return -SENSORS_ERR_NO_ENTRY;
184  sysctl_name[3] = the_feature->sysctl;
185  if (sysctl(sysctl_name, 4, buf, &buflen, NULL, 0))
186    return -SENSORS_ERR_PROC;
187  for (mag = the_feature->scaling; mag > 0; mag --)
188    value *= 10.0;
189  for (; mag < 0; mag --)
190    value /= 10.0;
191  * ((long *) (buf + the_feature->offset)) = (long) value;
192  buflen = the_feature->offset + sizeof(long);
193  if (sysctl(sysctl_name, 4, NULL, 0, buf, buflen))
194    return -SENSORS_ERR_PROC;
195  return 0;
196}
Note: See TracBrowser for help on using the browser.