blob: 9c97e728f8eff626f17dc3c5c91f9b5022c930bf [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
Daniel Lezcano2e9df762011-06-15 15:45:12 +020016#define _GNU_SOURCE
17#include <stdio.h>
18#undef _GNU_SOURCE
19#include <sys/types.h>
20#include <stdbool.h>
21#include <dirent.h>
22#include <string.h>
23#include <stdlib.h>
24
Amit Arorae9e16b02010-08-03 10:15:20 +053025#include "powerdebug.h"
26#include "sensor.h"
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020027#include "tree.h"
28#include "utils.h"
Amit Arorae9e16b02010-08-03 10:15:20 +053029
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020030#define SYSFS_SENSOR "/sys/class/hwmon"
Daniel Lezcanod3ffa812011-03-26 22:06:22 +010031
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020032static struct tree *sensor_tree;
33
34struct temp_info {
35 char name[NAME_MAX];
36 int temp;
37};
38
39struct fan_info {
40 char name[NAME_MAX];
41 int rpms;
42};
43
44struct sensor_info {
45 char name[NAME_MAX];
46 struct temp_info *temperatures;
47 struct fan_info *fans;
48 short nrtemps;
49 short nrfans;
50};
51
52static int sensor_dump_cb(struct tree *tree, void *data)
Amit Arorae9e16b02010-08-03 10:15:20 +053053{
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020054 int i;
55 struct sensor_info *sensor = tree->private;
Amit Arorae9e16b02010-08-03 10:15:20 +053056
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020057 if (!strlen(sensor->name))
58 return 0;
Amit Arorae9e16b02010-08-03 10:15:20 +053059
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020060 printf("%s\n", sensor->name);
Amit Arorae9e16b02010-08-03 10:15:20 +053061
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020062 for (i = 0; i < sensor->nrtemps; i++)
63 printf(" %s %.1f °C\n", sensor->temperatures[i].name,
64 (float)sensor->temperatures[i].temp / 1000);
Amit Arorae9e16b02010-08-03 10:15:20 +053065
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020066 for (i = 0; i < sensor->nrfans; i++)
67 printf(" %s %d rpm\n", sensor->fans[i].name,
68 sensor->fans[i].rpms);
Amit Arora422c52f2010-12-02 16:22:29 +053069
Amit Arora17552782010-12-02 12:23:14 +053070 return 0;
71}
Daniel Lezcano3d0aef42011-06-15 15:45:12 +020072
73int sensor_dump(void)
74{
75 printf("\nSensor Information:\n");
76 printf("*******************\n\n");
77
78 return tree_for_each(sensor_tree, sensor_dump_cb, NULL);
79}
80
81static struct sensor_info *sensor_alloc(void)
82{
83 struct sensor_info *sensor;
84
85 sensor = malloc(sizeof(*sensor));
86 if (sensor)
87 memset(sensor, 0, sizeof(*sensor));
88
89 return sensor;
90}
91
92static int read_sensor_cb(struct tree *tree, void *data)
93{
94 DIR *dir;
95 int value;
96 struct dirent dirent, *direntp;
97 struct sensor_info *sensor = tree->private;
98
99 int nrtemps = 0;
100 int nrfans = 0;
101
102 dir = opendir(tree->path);
103 if (!dir)
104 return -1;
105
106 file_read_value(tree->path, "name", "%s", sensor->name);
107
108 while (!readdir_r(dir, &dirent, &direntp)) {
109
110 if (!direntp)
111 break;
112
113 if (direntp->d_type != DT_REG)
114 continue;
115
116 if (!strncmp(direntp->d_name, "temp", 4)) {
117
118 if (file_read_value(tree->path, direntp->d_name, "%d",
119 &value))
120 continue;
121
122 sensor->temperatures =
123 realloc(sensor->temperatures,
124 sizeof(struct temp_info) * (nrtemps + 1));
125 if (!sensor->temperatures)
126 continue;
127
128 strcpy(sensor->temperatures[nrtemps].name,
129 direntp->d_name);
130 sensor->temperatures[nrtemps].temp = value;
131
132 nrtemps++;
133 }
134
135 if (!strncmp(direntp->d_name, "fan", 3)) {
136
137 if (file_read_value(tree->path, direntp->d_name, "%d",
138 &value))
139 continue;
140
141 sensor->fans =
142 realloc(sensor->fans,
143 sizeof(struct temp_info) * (nrfans + 1));
144 if (!sensor->fans)
145 continue;
146
147 strcpy(sensor->fans[nrfans].name,
148 direntp->d_name);
149 sensor->fans[nrfans].rpms = value;
150
151 nrfans++;
152 }
153 }
154
155 sensor->nrtemps = nrtemps;
156 sensor->nrfans = nrfans;
157
158 closedir(dir);
159
160 return 0;
161}
162
163static int fill_sensor_cb(struct tree *t, void *data)
164{
165 struct sensor_info *sensor;
166
167 sensor = sensor_alloc();
168 if (!sensor)
169 return -1;
170
171 t->private = sensor;
172
173 if (!t->parent)
174 return 0;
175
176 return read_sensor_cb(t, data);
177}
178
179static int fill_sensor_tree(void)
180{
181 return tree_for_each(sensor_tree, fill_sensor_cb, NULL);
182}
183
184static int sensor_filter_cb(const char *name)
185{
186 /* let's ignore some directories in order to avoid to be
187 * pulled inside the sysfs circular symlinks mess/hell
188 * (choose the word which fit better)
189 */
190 if (!strcmp(name, "subsystem"))
191 return 1;
192
193 if (!strcmp(name, "driver"))
194 return 1;
195
196 if (!strcmp(name, "hwmon"))
197 return 1;
198
199 if (!strcmp(name, "power"))
200 return 1;
201
202 return 0;
203}
204
Daniel Lezcano2e9df762011-06-15 15:45:12 +0200205static int sensor_display_cb(struct tree *t, void *data)
206{
207 struct sensor_info *sensor = t->private;
208 int *line = data;
209 char buf[1024];
210 int i;
211
212 if (!strlen(sensor->name))
213 return 0;
214
215 sprintf(buf, "%s", sensor->name);
216 display_print_line(SENSOR, *line, buf, 1, t);
217
218 (*line)++;
219
220 for (i = 0; i < sensor->nrtemps; i++) {
221 sprintf(buf, " %-35s%.1f °C", sensor->temperatures[i].name,
222 (float)sensor->temperatures[i].temp / 1000);
223 display_print_line(SENSOR, *line, buf, 0, t);
224 (*line)++;
225 }
226
227 for (i = 0; i < sensor->nrfans; i++) {
228 sprintf(buf, " %-35s%d rpm", sensor->fans[i].name,
229 sensor->fans[i].rpms);
230 display_print_line(SENSOR, *line, buf, 0, t);
231 (*line)++;
232 }
233
234 return 0;
235}
236
237int sensor_display(void)
238{
239 int ret, line = 0;
240
241 display_reset_cursor(SENSOR);
242
243 print_sensor_header();
244
245 ret = tree_for_each(sensor_tree, sensor_display_cb, &line);
246
247 display_refresh_pad(SENSOR);
248
249 return ret;
250}
251
Daniel Lezcano3d0aef42011-06-15 15:45:12 +0200252int sensor_init(void)
253{
254 sensor_tree = tree_load(SYSFS_SENSOR, sensor_filter_cb);
255 if (!sensor_tree)
256 return -1;
257
258 return fill_sensor_tree();
259}