Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/auxiliary/hud/hud_sensors_temp.c
4565 views
1
/**************************************************************************
2
*
3
* Copyright (C) 2016 Steven Toth <[email protected]>
4
* Copyright (C) 2016 Zodiac Inflight Innovations
5
* All Rights Reserved.
6
*
7
* Permission is hereby granted, free of charge, to any person obtaining a
8
* copy of this software and associated documentation files (the
9
* "Software"), to deal in the Software without restriction, including
10
* without limitation the rights to use, copy, modify, merge, publish,
11
* distribute, sub license, and/or sell copies of the Software, and to
12
* permit persons to whom the Software is furnished to do so, subject to
13
* the following conditions:
14
*
15
* The above copyright notice and this permission notice (including the
16
* next paragraph) shall be included in all copies or substantial portions
17
* of the Software.
18
*
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22
* IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
23
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
*
27
**************************************************************************/
28
29
#ifdef HAVE_LIBSENSORS
30
/* Purpose: Extract lm-sensors data, expose temperature, power, voltage. */
31
32
#include "hud/hud_private.h"
33
#include "util/list.h"
34
#include "util/os_time.h"
35
#include "os/os_thread.h"
36
#include "util/u_memory.h"
37
#include "util/u_string.h"
38
#include <stdio.h>
39
#include <unistd.h>
40
#include <dirent.h>
41
#include <stdlib.h>
42
#include <unistd.h>
43
#include <inttypes.h>
44
#include <sys/types.h>
45
#include <sys/stat.h>
46
#include <unistd.h>
47
#include <sensors/sensors.h>
48
49
/* TODO: We don't handle dynamic sensor discovery / arrival or removal.
50
* Static globals specific to this HUD category.
51
*/
52
static int gsensors_temp_count = 0;
53
static struct list_head gsensors_temp_list;
54
static mtx_t gsensor_temp_mutex = _MTX_INITIALIZER_NP;
55
56
struct sensors_temp_info
57
{
58
struct list_head list;
59
60
/* Combined chip and feature name, human readable. */
61
char name[64];
62
63
/* The type of measurement, critical or current. */
64
unsigned int mode;
65
66
uint64_t last_time;
67
68
char chipname[64];
69
char featurename[128];
70
71
sensors_chip_name *chip;
72
const sensors_feature *feature;
73
double current, min, max, critical;
74
};
75
76
static double
77
get_value(const sensors_chip_name *name, const sensors_subfeature *sub)
78
{
79
double val;
80
int err;
81
82
err = sensors_get_value(name, sub->number, &val);
83
if (err) {
84
fprintf(stderr, "ERROR: Can't get value of subfeature %s\n", sub->name);
85
val = 0;
86
}
87
return val;
88
}
89
90
static void
91
get_sensor_values(struct sensors_temp_info *sti)
92
{
93
const sensors_subfeature *sf;
94
95
switch(sti->mode) {
96
case SENSORS_VOLTAGE_CURRENT:
97
sf = sensors_get_subfeature(sti->chip, sti->feature,
98
SENSORS_SUBFEATURE_IN_INPUT);
99
if (sf)
100
sti->current = get_value(sti->chip, sf);
101
break;
102
case SENSORS_CURRENT_CURRENT:
103
sf = sensors_get_subfeature(sti->chip, sti->feature,
104
SENSORS_SUBFEATURE_CURR_INPUT);
105
if (sf) {
106
/* Sensors API returns in AMPs, even though driver is reporting mA,
107
* convert back to mA */
108
sti->current = get_value(sti->chip, sf) * 1000;
109
}
110
break;
111
case SENSORS_TEMP_CURRENT:
112
sf = sensors_get_subfeature(sti->chip, sti->feature,
113
SENSORS_SUBFEATURE_TEMP_INPUT);
114
if (sf)
115
sti->current = get_value(sti->chip, sf);
116
break;
117
case SENSORS_TEMP_CRITICAL:
118
sf = sensors_get_subfeature(sti->chip, sti->feature,
119
SENSORS_SUBFEATURE_TEMP_CRIT);
120
if (sf)
121
sti->critical = get_value(sti->chip, sf);
122
break;
123
case SENSORS_POWER_CURRENT:
124
sf = sensors_get_subfeature(sti->chip, sti->feature,
125
SENSORS_SUBFEATURE_POWER_INPUT);
126
if (!sf)
127
sf = sensors_get_subfeature(sti->chip, sti->feature,
128
SENSORS_SUBFEATURE_POWER_AVERAGE);
129
if (sf) {
130
/* Sensors API returns in WATTs, even though driver is reporting mW,
131
* convert back to mW */
132
sti->current = get_value(sti->chip, sf) * 1000;
133
}
134
break;
135
}
136
137
sf = sensors_get_subfeature(sti->chip, sti->feature,
138
SENSORS_SUBFEATURE_TEMP_MIN);
139
if (sf)
140
sti->min = get_value(sti->chip, sf);
141
142
sf = sensors_get_subfeature(sti->chip, sti->feature,
143
SENSORS_SUBFEATURE_TEMP_MAX);
144
if (sf)
145
sti->max = get_value(sti->chip, sf);
146
}
147
148
static struct sensors_temp_info *
149
find_sti_by_name(const char *n, unsigned int mode)
150
{
151
list_for_each_entry(struct sensors_temp_info, sti, &gsensors_temp_list, list) {
152
if (sti->mode != mode)
153
continue;
154
if (strcasecmp(sti->name, n) == 0)
155
return sti;
156
}
157
return 0;
158
}
159
160
static void
161
query_sti_load(struct hud_graph *gr, struct pipe_context *pipe)
162
{
163
struct sensors_temp_info *sti = gr->query_data;
164
uint64_t now = os_time_get();
165
166
if (sti->last_time) {
167
if (sti->last_time + gr->pane->period <= now) {
168
get_sensor_values(sti);
169
170
switch (sti->mode) {
171
case SENSORS_TEMP_CURRENT:
172
hud_graph_add_value(gr, sti->current);
173
break;
174
case SENSORS_TEMP_CRITICAL:
175
hud_graph_add_value(gr, sti->critical);
176
break;
177
case SENSORS_VOLTAGE_CURRENT:
178
hud_graph_add_value(gr, sti->current * 1000);
179
break;
180
case SENSORS_CURRENT_CURRENT:
181
hud_graph_add_value(gr, sti->current);
182
break;
183
case SENSORS_POWER_CURRENT:
184
hud_graph_add_value(gr, sti->current);
185
break;
186
}
187
188
sti->last_time = now;
189
}
190
}
191
else {
192
/* initialize */
193
get_sensor_values(sti);
194
sti->last_time = now;
195
}
196
}
197
198
/**
199
* Create and initialize a new object for a specific sensor interface dev.
200
* \param pane parent context.
201
* \param dev_name device name, EG. 'coretemp-isa-0000.Core 1'
202
* \param mode query type (NIC_DIRECTION_RX/WR/RSSI) statistics.
203
*/
204
void
205
hud_sensors_temp_graph_install(struct hud_pane *pane, const char *dev_name,
206
unsigned int mode)
207
{
208
struct hud_graph *gr;
209
struct sensors_temp_info *sti;
210
211
int num_devs = hud_get_num_sensors(0);
212
if (num_devs <= 0)
213
return;
214
215
sti = find_sti_by_name(dev_name, mode);
216
if (!sti)
217
return;
218
219
gr = CALLOC_STRUCT(hud_graph);
220
if (!gr)
221
return;
222
223
snprintf(gr->name, sizeof(gr->name), "%.6s..%s (%s)",
224
sti->chipname,
225
sti->featurename,
226
sti->mode == SENSORS_VOLTAGE_CURRENT ? "Volts" :
227
sti->mode == SENSORS_CURRENT_CURRENT ? "Amps" :
228
sti->mode == SENSORS_TEMP_CURRENT ? "Curr" :
229
sti->mode == SENSORS_POWER_CURRENT ? "Pow" :
230
sti->mode == SENSORS_TEMP_CRITICAL ? "Crit" : "Unkn");
231
232
gr->query_data = sti;
233
gr->query_new_value = query_sti_load;
234
235
hud_pane_add_graph(pane, gr);
236
switch (sti->mode) {
237
case SENSORS_TEMP_CURRENT:
238
case SENSORS_TEMP_CRITICAL:
239
hud_pane_set_max_value(pane, 120);
240
break;
241
case SENSORS_VOLTAGE_CURRENT:
242
hud_pane_set_max_value(pane, 12);
243
break;
244
case SENSORS_CURRENT_CURRENT:
245
hud_pane_set_max_value(pane, 5000);
246
break;
247
case SENSORS_POWER_CURRENT:
248
hud_pane_set_max_value(pane, 5000 /* mW */);
249
break;
250
}
251
}
252
253
static void
254
create_object(const char *chipname, const char *featurename,
255
const sensors_chip_name *chip, const sensors_feature *feature,
256
int mode)
257
{
258
struct sensors_temp_info *sti = CALLOC_STRUCT(sensors_temp_info);
259
260
sti->mode = mode;
261
sti->chip = (sensors_chip_name *) chip;
262
sti->feature = feature;
263
snprintf(sti->chipname, sizeof(sti->chipname), "%s", chipname);
264
snprintf(sti->featurename, sizeof(sti->featurename), "%s", featurename);
265
snprintf(sti->name, sizeof(sti->name), "%s.%s", sti->chipname,
266
sti->featurename);
267
268
list_addtail(&sti->list, &gsensors_temp_list);
269
gsensors_temp_count++;
270
}
271
272
static void
273
build_sensor_list(void)
274
{
275
const sensors_chip_name *chip;
276
const sensors_chip_name *match = 0;
277
const sensors_feature *feature;
278
int chip_nr = 0;
279
280
char name[256];
281
while ((chip = sensors_get_detected_chips(match, &chip_nr))) {
282
sensors_snprintf_chip_name(name, sizeof(name), chip);
283
284
/* Get all features and filter accordingly. */
285
int fnr = 0;
286
while ((feature = sensors_get_features(chip, &fnr))) {
287
char *featurename = sensors_get_label(chip, feature);
288
if (!featurename)
289
continue;
290
291
/* Create a 'current' and 'critical' object pair.
292
* Ignore sensor if its not temperature based.
293
*/
294
switch(feature->type) {
295
case SENSORS_FEATURE_TEMP:
296
create_object(name, featurename, chip, feature,
297
SENSORS_TEMP_CURRENT);
298
create_object(name, featurename, chip, feature,
299
SENSORS_TEMP_CRITICAL);
300
break;
301
case SENSORS_FEATURE_IN:
302
create_object(name, featurename, chip, feature,
303
SENSORS_VOLTAGE_CURRENT);
304
break;
305
case SENSORS_FEATURE_CURR:
306
create_object(name, featurename, chip, feature,
307
SENSORS_CURRENT_CURRENT);
308
break;
309
case SENSORS_FEATURE_POWER:
310
create_object(name, featurename, chip, feature,
311
SENSORS_POWER_CURRENT);
312
break;
313
default:
314
break;
315
}
316
free(featurename);
317
}
318
}
319
}
320
321
/**
322
* Initialize internal object arrays and display lmsensors HUD help.
323
* \param displayhelp true if the list of detected devices should be
324
displayed on the console.
325
* \return number of detected lmsensor devices.
326
*/
327
int
328
hud_get_num_sensors(bool displayhelp)
329
{
330
/* Return the number of sensors detected. */
331
mtx_lock(&gsensor_temp_mutex);
332
if (gsensors_temp_count) {
333
mtx_unlock(&gsensor_temp_mutex);
334
return gsensors_temp_count;
335
}
336
337
int ret = sensors_init(NULL);
338
if (ret) {
339
mtx_unlock(&gsensor_temp_mutex);
340
return 0;
341
}
342
343
list_inithead(&gsensors_temp_list);
344
345
/* Scan /sys/block, for every object type we support, create and
346
* persist an object to represent its different statistics.
347
*/
348
build_sensor_list();
349
350
if (displayhelp) {
351
list_for_each_entry(struct sensors_temp_info, sti, &gsensors_temp_list, list) {
352
char line[64];
353
switch (sti->mode) {
354
case SENSORS_TEMP_CURRENT:
355
snprintf(line, sizeof(line), " sensors_temp_cu-%s", sti->name);
356
break;
357
case SENSORS_TEMP_CRITICAL:
358
snprintf(line, sizeof(line), " sensors_temp_cr-%s", sti->name);
359
break;
360
case SENSORS_VOLTAGE_CURRENT:
361
snprintf(line, sizeof(line), " sensors_volt_cu-%s", sti->name);
362
break;
363
case SENSORS_CURRENT_CURRENT:
364
snprintf(line, sizeof(line), " sensors_curr_cu-%s", sti->name);
365
break;
366
case SENSORS_POWER_CURRENT:
367
snprintf(line, sizeof(line), " sensors_pow_cu-%s", sti->name);
368
break;
369
}
370
371
puts(line);
372
}
373
}
374
375
mtx_unlock(&gsensor_temp_mutex);
376
return gsensors_temp_count;
377
}
378
379
#endif /* HAVE_LIBSENSORS */
380
381