root/lm-sensors/branches/lm-sensors-3.0.0/prog/sensord/chips.c @ 4846

Revision 4846, 10.5 KB (checked in by khali, 7 years ago)

New public library function: sensors_get_subfeature(). Applications can
use it to retrieve a specific subfeature by type. While it is slighly
less efficient than looping over sensors_get_all_subfeatures(), it
often makes the application code much more elegant.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * sensord
3 *
4 * A daemon that periodically logs sensor information to syslog.
5 *
6 * Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include "sensord.h"
28
29/* TODO: Temp in C/F */
30
31/** formatters **/
32
33static char buff[4096];
34
35static const char *
36fmtExtra
37(int alarm, int beep) {
38  if (alarm)
39    sprintf (buff + strlen (buff), " [ALARM]");
40  if (beep)
41    sprintf (buff + strlen (buff), " (beep)");
42  return buff;
43}
44
45static const char *
46fmtTemps_1
47(const double values[], int alarm, int beep) {
48  sprintf (buff, "%.1f C (limit = %.1f C, hysteresis = %.1f C)", values[0], values[1], values[2]);
49  return fmtExtra (alarm, beep);
50}
51
52static const char *
53fmtTemps_minmax_1
54(const double values[], int alarm, int beep) {
55 sprintf (buff, "%.1f C (min = %.1f C, max = %.1f C)", values[0], values[1], values[2]);
56 return fmtExtra (alarm, beep);
57}
58
59static const char *
60fmtTemp_only
61(const double values[], int alarm, int beep) {
62  sprintf (buff, "%.1f C", values[0]);
63  return fmtExtra (alarm, beep);
64}
65
66static const char *
67fmtVolt_2
68(const double values[], int alarm, int beep) {
69  sprintf (buff, "%+.2f V", values[0]);
70  return fmtExtra (alarm, beep);
71}
72
73static const char *
74fmtVolt_3
75(const double values[], int alarm, int beep) {
76  sprintf (buff, "%+.3f V", values[0]);
77  return fmtExtra (alarm, beep);
78}
79
80static const char *
81fmtVolts_2
82(const double values[], int alarm, int beep) {
83  sprintf (buff, "%+.2f V (min = %+.2f V, max = %+.2f V)", values[0], values[1], values[2]);
84  return fmtExtra (alarm, beep);
85}
86
87static const char *
88fmtFans_0
89(const double values[], int alarm, int beep) {
90  sprintf (buff, "%.0f RPM (min = %.0f RPM, div = %.0f)", values[0], values[1], values[2]);
91  return fmtExtra (alarm, beep);
92}
93
94static const char *
95fmtFans_nodiv_0
96(const double values[], int alarm, int beep) {
97  sprintf (buff, "%.0f RPM (min = %.0f RPM)", values[0], values[1]);
98  return fmtExtra (alarm, beep);
99}
100
101static const char *
102fmtFan_only
103(const double values[], int alarm, int beep) {
104  sprintf (buff, "%.0f RPM", values[0]);
105  return fmtExtra (alarm, beep);
106}
107
108static const char *
109fmtSoundAlarm
110(const double values[], int alarm, int beep) {
111  sprintf (buff, "Sound alarm %s", (values[0] < 0.5) ? "disabled" : "enabled");
112  return fmtExtra (alarm, beep);
113}
114
115static const char *
116rrdF0
117(const double values[]) {
118  sprintf (buff, "%.0f", values[0]);
119  return buff;
120}
121
122static const char *
123rrdF1
124(const double values[]) {
125  sprintf (buff, "%.1f", values[0]);
126  return buff;
127}
128
129static const char *
130rrdF2
131(const double values[]) {
132  sprintf (buff, "%.2f", values[0]);
133  return buff;
134}
135
136static const char *
137rrdF3
138(const double values[]) {
139  sprintf (buff, "%.3f", values[0]);
140  return buff;
141}
142
143static void fillChipVoltage (FeatureDescriptor *voltage,
144                             const sensors_chip_name *name,
145                             const sensors_feature *feature)
146{
147  const sensors_subfeature *sf, *sfmin, *sfmax;
148  int pos = 0;
149
150  voltage->rrd = rrdF2;
151  voltage->type = DataType_voltage;
152
153  sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_INPUT);
154  if (sf)
155    voltage->dataNumbers[pos++] = sf->number;
156
157  sfmin = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_MIN);
158  sfmax = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_MAX);
159  if (sfmin && sfmax) {
160    voltage->format = fmtVolts_2;
161    voltage->dataNumbers[pos++] = sfmin->number;
162    voltage->dataNumbers[pos++] = sfmax->number;
163  } else {
164    voltage->format = fmtVolt_2;
165  }
166 
167  /* terminate the list */
168  voltage->dataNumbers[pos] = -1;
169
170  /* alarm if applicable */
171  if ((sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_ALARM)) ||
172      (sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_MIN_ALARM)) ||
173      (sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_MAX_ALARM))) {
174    voltage->alarmNumber = sf->number;
175  } else {
176    voltage->alarmNumber = -1;
177  }
178  /* beep if applicable */
179  if ((sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_BEEP))) {
180    voltage->beepNumber = sf->number;
181  } else {
182    voltage->beepNumber = -1;
183  }
184}
185
186static void fillChipTemperature (FeatureDescriptor *temperature,
187                                 const sensors_chip_name *name,
188                                 const sensors_feature *feature)
189{
190  const sensors_subfeature *sf, *sfmin, *sfmax, *sfhyst;
191  int pos = 0;
192
193  temperature->rrd = rrdF1;
194  temperature->type = DataType_temperature;
195
196  sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_INPUT);
197  if (sf)
198    temperature->dataNumbers[pos++] = sf->number;
199
200  sfmin = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_MIN);
201  sfmax = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_MAX);
202  sfhyst = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_MAX_HYST);
203  if (sfmin && sfmax) {
204    temperature->format = fmtTemps_minmax_1;
205    temperature->dataNumbers[pos++] = sfmin->number;
206    temperature->dataNumbers[pos++] = sfmax->number;
207  } else if (sfmax && sfhyst) {
208    temperature->format = fmtTemps_1;
209    temperature->dataNumbers[pos++] = sfmax->number;
210    temperature->dataNumbers[pos++] = sfhyst->number;
211  } else {
212    temperature->format = fmtTemp_only;
213  }
214 
215  /* terminate the list */
216  temperature->dataNumbers[pos] = -1;
217
218  /* alarm if applicable */
219  if ((sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_ALARM)) ||
220      (sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_MAX_ALARM))) {
221    temperature->alarmNumber = sf->number;
222  } else {
223    temperature->alarmNumber = -1;
224  }
225  /* beep if applicable */
226  if ((sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_BEEP))) {
227    temperature->beepNumber = sf->number;
228  } else {
229    temperature->beepNumber = -1;
230  }
231}
232
233static void fillChipFan (FeatureDescriptor *fan,
234                         const sensors_chip_name *name,
235                         const sensors_feature *feature)
236{
237  const sensors_subfeature *sf, *sfmin, *sfdiv;
238  int pos = 0;
239
240  fan->rrd = rrdF0;
241  fan->type = DataType_rpm;
242
243  sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_FAN_INPUT);
244  if (sf)
245    fan->dataNumbers[pos++] = sf->number;
246
247  sfmin = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_FAN_MIN);
248  if (sfmin) {
249    fan->dataNumbers[pos++] = sfmin->number;
250    sfdiv = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_FAN_DIV);
251    if (sfdiv) {
252      fan->format = fmtFans_0;
253      fan->dataNumbers[pos++] = sfdiv->number;
254    } else {
255      fan->format = fmtFans_nodiv_0;
256    }
257  } else {
258      fan->format = fmtFan_only;
259  }
260 
261  /* terminate the list */
262  fan->dataNumbers[pos] = -1;
263
264  /* alarm if applicable */
265  sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_FAN_ALARM);
266  if (sf) {
267    fan->alarmNumber = sf->number;
268  } else {
269    fan->alarmNumber = -1;
270  }
271  /* beep if applicable */
272  sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_FAN_BEEP);
273  if (sf) {
274    fan->beepNumber = sf->number;
275  } else {
276    fan->beepNumber = -1;
277  }
278}
279
280static void fillChipVid (FeatureDescriptor *vid,
281                         const sensors_chip_name *name,
282                         const sensors_feature *feature)
283{
284  const sensors_subfeature *sub;
285
286  sub = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_VID);
287  if (!sub)
288    return;
289
290  vid->format = fmtVolt_3;
291  vid->rrd = rrdF3;
292  vid->type = DataType_voltage;
293  vid->alarmNumber = -1;
294  vid->beepNumber = -1;
295  vid->dataNumbers[0] = sub->number;
296  vid->dataNumbers[1] = -1;
297}
298
299static void fillChipBeepEnable (FeatureDescriptor *beepen,
300                                const sensors_chip_name *name,
301                                const sensors_feature *feature)
302{
303  const sensors_subfeature *sub;
304
305  sub = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_BEEP_ENABLE);
306  if (!sub)
307    return;
308
309  beepen->format = fmtSoundAlarm;
310  beepen->rrd = rrdF0;
311  beepen->type = DataType_other;
312  beepen->alarmNumber = -1;
313  beepen->beepNumber = -1;
314  beepen->dataNumbers[0] = sub->number;
315  beepen->dataNumbers[1] = -1;
316}
317
318static
319FeatureDescriptor * generateChipFeatures (const sensors_chip_name *chip)
320{
321        int nr, count = 1;
322        const sensors_feature *sensor;
323        FeatureDescriptor *features;
324
325        /* How many main features do we have? */
326        nr = 0;
327        while ((sensor = sensors_get_features(chip, &nr)))
328                count++;
329
330        /* Allocate the memory we need */
331        features = calloc(count, sizeof(FeatureDescriptor));
332        if (!features)
333                return NULL;
334
335        /* Fill in the data structures */
336        count = 0;
337        nr = 0;
338        while ((sensor = sensors_get_features(chip, &nr))) {
339                switch (sensor->type) {
340                case SENSORS_FEATURE_TEMP:
341                        fillChipTemperature(&features[count], chip, sensor);
342                        break;
343                case SENSORS_FEATURE_IN:
344                        fillChipVoltage(&features[count], chip, sensor);
345                        break;
346                case SENSORS_FEATURE_FAN:
347                        fillChipFan(&features[count], chip, sensor);
348                        break;
349                case SENSORS_FEATURE_VID:
350                        fillChipVid(&features[count], chip, sensor);
351                        break;
352                case SENSORS_FEATURE_BEEP_ENABLE:
353                        fillChipBeepEnable(&features[count], chip, sensor);
354                        break;
355                default:
356                        continue;
357                }
358
359                features[count].feature = sensor;
360                count++;
361        }
362
363        return features;
364}
365
366ChipDescriptor * knownChips;
367
368int initKnownChips (void)
369{
370  int nr, count = 1;
371  const sensors_chip_name *name;
372
373  /* How many chips do we have? */
374  nr = 0;
375  while ((name = sensors_get_detected_chips(NULL, &nr)))
376    count++;
377
378  /* Allocate the memory we need */
379  knownChips = calloc(count, sizeof(ChipDescriptor));
380  if (!knownChips)
381    return 1;
382
383  /* Fill in the data structures */
384  count = 0;
385  nr = 0;
386  while ((name = sensors_get_detected_chips(NULL, &nr))) {
387    knownChips[count].name = name;
388    if ((knownChips[count].features = generateChipFeatures(name)))
389      count++;
390  }
391
392  return 0;
393}
394
395void freeKnownChips (void)
396{
397  int index0;
398
399  for (index0 = 0; knownChips[index0].features; index0++)
400    free (knownChips[index0].features);
401  free (knownChips);
402}
Note: See TracBrowser for help on using the browser.