blob: f386f0c292c4104ca691c1d81d2bbd9fa992387d [file] [log] [blame]
Amit Arora39f29542010-09-14 12:03:22 +05301/*******************************************************************************
Amit Kucheriac0e17fc2011-01-17 09:35:52 +02002 * Copyright (C) 2010, Linaro Limited.
Amit Arora39f29542010-09-14 12:03:22 +05303 *
4 * This file is part of PowerDebug.
5 *
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 * Contributors:
12 * Amit Arora <amit.arora@linaro.org> (IBM Corporation)
13 * - initial API and implementation
14 *******************************************************************************/
15
Amit Arorae9e16b02010-08-03 10:15:20 +053016#include "powerdebug.h"
17#include "sensor.h"
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020018#include "tree.h"
19#include "utils.h"
Amit Arorae9e16b02010-08-03 10:15:20 +053020
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020021#define SYSFS_SENSOR "/sys/class/hwmon"
Daniel Lezcanod3ffa812011-03-26 22:06:22 +010022
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020023static struct tree *sensor_tree;
24
25struct temp_info {
26 char name[NAME_MAX];
27 int temp;
28};
29
30struct fan_info {
31 char name[NAME_MAX];
32 int rpms;
33};
34
35struct sensor_info {
36 char name[NAME_MAX];
37 struct temp_info *temperatures;
38 struct fan_info *fans;
39 short nrtemps;
40 short nrfans;
41};
42
43static int sensor_dump_cb(struct tree *tree, void *data)
Amit Arorae9e16b02010-08-03 10:15:20 +053044{
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020045 int i;
46 struct sensor_info *sensor = tree->private;
Amit Arorae9e16b02010-08-03 10:15:20 +053047
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020048 if (!strlen(sensor->name))
49 return 0;
Amit Arorae9e16b02010-08-03 10:15:20 +053050
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020051 printf("%s\n", sensor->name);
Amit Arorae9e16b02010-08-03 10:15:20 +053052
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020053 for (i = 0; i < sensor->nrtemps; i++)
54 printf(" %s %.1f °C\n", sensor->temperatures[i].name,
55 (float)sensor->temperatures[i].temp / 1000);
Amit Arorae9e16b02010-08-03 10:15:20 +053056
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020057 for (i = 0; i < sensor->nrfans; i++)
58 printf(" %s %d rpm\n", sensor->fans[i].name,
59 sensor->fans[i].rpms);
Amit Arora422c52f2010-12-02 16:22:29 +053060
Amit Arora17552782010-12-02 12:23:14 +053061 return 0;
62}
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020063
64int sensor_dump(void)
65{
66 printf("\nSensor Information:\n");
67 printf("*******************\n\n");
68
69 return tree_for_each(sensor_tree, sensor_dump_cb, NULL);
70}
71
72static struct sensor_info *sensor_alloc(void)
73{
74 struct sensor_info *sensor;
75
76 sensor = malloc(sizeof(*sensor));
77 if (sensor)
78 memset(sensor, 0, sizeof(*sensor));
79
80 return sensor;
81}
82
83static int read_sensor_cb(struct tree *tree, void *data)
84{
85 DIR *dir;
86 int value;
87 struct dirent dirent, *direntp;
88 struct sensor_info *sensor = tree->private;
89
90 int nrtemps = 0;
91 int nrfans = 0;
92
93 dir = opendir(tree->path);
94 if (!dir)
95 return -1;
96
97 file_read_value(tree->path, "name", "%s", sensor->name);
98
99 while (!readdir_r(dir, &dirent, &direntp)) {
100
101 if (!direntp)
102 break;
103
104 if (direntp->d_type != DT_REG)
105 continue;
106
107 if (!strncmp(direntp->d_name, "temp", 4)) {
108
109 if (file_read_value(tree->path, direntp->d_name, "%d",
110 &value))
111 continue;
112
113 sensor->temperatures =
114 realloc(sensor->temperatures,
115 sizeof(struct temp_info) * (nrtemps + 1));
116 if (!sensor->temperatures)
117 continue;
118
119 strcpy(sensor->temperatures[nrtemps].name,
120 direntp->d_name);
121 sensor->temperatures[nrtemps].temp = value;
122
123 nrtemps++;
124 }
125
126 if (!strncmp(direntp->d_name, "fan", 3)) {
127
128 if (file_read_value(tree->path, direntp->d_name, "%d",
129 &value))
130 continue;
131
132 sensor->fans =
133 realloc(sensor->fans,
134 sizeof(struct temp_info) * (nrfans + 1));
135 if (!sensor->fans)
136 continue;
137
138 strcpy(sensor->fans[nrfans].name,
139 direntp->d_name);
140 sensor->fans[nrfans].rpms = value;
141
142 nrfans++;
143 }
144 }
145
146 sensor->nrtemps = nrtemps;
147 sensor->nrfans = nrfans;
148
149 closedir(dir);
150
151 return 0;
152}
153
154static int fill_sensor_cb(struct tree *t, void *data)
155{
156 struct sensor_info *sensor;
157
158 sensor = sensor_alloc();
159 if (!sensor)
160 return -1;
161
162 t->private = sensor;
163
164 if (!t->parent)
165 return 0;
166
167 return read_sensor_cb(t, data);
168}
169
170static int fill_sensor_tree(void)
171{
172 return tree_for_each(sensor_tree, fill_sensor_cb, NULL);
173}
174
175static int sensor_filter_cb(const char *name)
176{
177 /* let's ignore some directories in order to avoid to be
178 * pulled inside the sysfs circular symlinks mess/hell
179 * (choose the word which fit better)
180 */
181 if (!strcmp(name, "subsystem"))
182 return 1;
183
184 if (!strcmp(name, "driver"))
185 return 1;
186
187 if (!strcmp(name, "hwmon"))
188 return 1;
189
190 if (!strcmp(name, "power"))
191 return 1;
192
193 return 0;
194}
195
196int sensor_init(void)
197{
198 sensor_tree = tree_load(SYSFS_SENSOR, sensor_filter_cb);
199 if (!sensor_tree)
200 return -1;
201
202 return fill_sensor_tree();
203}