Path: blob/21.2-virgl/src/gallium/auxiliary/hud/hud_sensors_temp.c
4565 views
/**************************************************************************1*2* Copyright (C) 2016 Steven Toth <[email protected]>3* Copyright (C) 2016 Zodiac Inflight Innovations4* All Rights Reserved.5*6* Permission is hereby granted, free of charge, to any person obtaining a7* copy of this software and associated documentation files (the8* "Software"), to deal in the Software without restriction, including9* without limitation the rights to use, copy, modify, merge, publish,10* distribute, sub license, and/or sell copies of the Software, and to11* permit persons to whom the Software is furnished to do so, subject to12* the following conditions:13*14* The above copyright notice and this permission notice (including the15* next paragraph) shall be included in all copies or substantial portions16* of the Software.17*18* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS19* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF20* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.21* IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR22* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,23* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE24* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.25*26**************************************************************************/2728#ifdef HAVE_LIBSENSORS29/* Purpose: Extract lm-sensors data, expose temperature, power, voltage. */3031#include "hud/hud_private.h"32#include "util/list.h"33#include "util/os_time.h"34#include "os/os_thread.h"35#include "util/u_memory.h"36#include "util/u_string.h"37#include <stdio.h>38#include <unistd.h>39#include <dirent.h>40#include <stdlib.h>41#include <unistd.h>42#include <inttypes.h>43#include <sys/types.h>44#include <sys/stat.h>45#include <unistd.h>46#include <sensors/sensors.h>4748/* TODO: We don't handle dynamic sensor discovery / arrival or removal.49* Static globals specific to this HUD category.50*/51static int gsensors_temp_count = 0;52static struct list_head gsensors_temp_list;53static mtx_t gsensor_temp_mutex = _MTX_INITIALIZER_NP;5455struct sensors_temp_info56{57struct list_head list;5859/* Combined chip and feature name, human readable. */60char name[64];6162/* The type of measurement, critical or current. */63unsigned int mode;6465uint64_t last_time;6667char chipname[64];68char featurename[128];6970sensors_chip_name *chip;71const sensors_feature *feature;72double current, min, max, critical;73};7475static double76get_value(const sensors_chip_name *name, const sensors_subfeature *sub)77{78double val;79int err;8081err = sensors_get_value(name, sub->number, &val);82if (err) {83fprintf(stderr, "ERROR: Can't get value of subfeature %s\n", sub->name);84val = 0;85}86return val;87}8889static void90get_sensor_values(struct sensors_temp_info *sti)91{92const sensors_subfeature *sf;9394switch(sti->mode) {95case SENSORS_VOLTAGE_CURRENT:96sf = sensors_get_subfeature(sti->chip, sti->feature,97SENSORS_SUBFEATURE_IN_INPUT);98if (sf)99sti->current = get_value(sti->chip, sf);100break;101case SENSORS_CURRENT_CURRENT:102sf = sensors_get_subfeature(sti->chip, sti->feature,103SENSORS_SUBFEATURE_CURR_INPUT);104if (sf) {105/* Sensors API returns in AMPs, even though driver is reporting mA,106* convert back to mA */107sti->current = get_value(sti->chip, sf) * 1000;108}109break;110case SENSORS_TEMP_CURRENT:111sf = sensors_get_subfeature(sti->chip, sti->feature,112SENSORS_SUBFEATURE_TEMP_INPUT);113if (sf)114sti->current = get_value(sti->chip, sf);115break;116case SENSORS_TEMP_CRITICAL:117sf = sensors_get_subfeature(sti->chip, sti->feature,118SENSORS_SUBFEATURE_TEMP_CRIT);119if (sf)120sti->critical = get_value(sti->chip, sf);121break;122case SENSORS_POWER_CURRENT:123sf = sensors_get_subfeature(sti->chip, sti->feature,124SENSORS_SUBFEATURE_POWER_INPUT);125if (!sf)126sf = sensors_get_subfeature(sti->chip, sti->feature,127SENSORS_SUBFEATURE_POWER_AVERAGE);128if (sf) {129/* Sensors API returns in WATTs, even though driver is reporting mW,130* convert back to mW */131sti->current = get_value(sti->chip, sf) * 1000;132}133break;134}135136sf = sensors_get_subfeature(sti->chip, sti->feature,137SENSORS_SUBFEATURE_TEMP_MIN);138if (sf)139sti->min = get_value(sti->chip, sf);140141sf = sensors_get_subfeature(sti->chip, sti->feature,142SENSORS_SUBFEATURE_TEMP_MAX);143if (sf)144sti->max = get_value(sti->chip, sf);145}146147static struct sensors_temp_info *148find_sti_by_name(const char *n, unsigned int mode)149{150list_for_each_entry(struct sensors_temp_info, sti, &gsensors_temp_list, list) {151if (sti->mode != mode)152continue;153if (strcasecmp(sti->name, n) == 0)154return sti;155}156return 0;157}158159static void160query_sti_load(struct hud_graph *gr, struct pipe_context *pipe)161{162struct sensors_temp_info *sti = gr->query_data;163uint64_t now = os_time_get();164165if (sti->last_time) {166if (sti->last_time + gr->pane->period <= now) {167get_sensor_values(sti);168169switch (sti->mode) {170case SENSORS_TEMP_CURRENT:171hud_graph_add_value(gr, sti->current);172break;173case SENSORS_TEMP_CRITICAL:174hud_graph_add_value(gr, sti->critical);175break;176case SENSORS_VOLTAGE_CURRENT:177hud_graph_add_value(gr, sti->current * 1000);178break;179case SENSORS_CURRENT_CURRENT:180hud_graph_add_value(gr, sti->current);181break;182case SENSORS_POWER_CURRENT:183hud_graph_add_value(gr, sti->current);184break;185}186187sti->last_time = now;188}189}190else {191/* initialize */192get_sensor_values(sti);193sti->last_time = now;194}195}196197/**198* Create and initialize a new object for a specific sensor interface dev.199* \param pane parent context.200* \param dev_name device name, EG. 'coretemp-isa-0000.Core 1'201* \param mode query type (NIC_DIRECTION_RX/WR/RSSI) statistics.202*/203void204hud_sensors_temp_graph_install(struct hud_pane *pane, const char *dev_name,205unsigned int mode)206{207struct hud_graph *gr;208struct sensors_temp_info *sti;209210int num_devs = hud_get_num_sensors(0);211if (num_devs <= 0)212return;213214sti = find_sti_by_name(dev_name, mode);215if (!sti)216return;217218gr = CALLOC_STRUCT(hud_graph);219if (!gr)220return;221222snprintf(gr->name, sizeof(gr->name), "%.6s..%s (%s)",223sti->chipname,224sti->featurename,225sti->mode == SENSORS_VOLTAGE_CURRENT ? "Volts" :226sti->mode == SENSORS_CURRENT_CURRENT ? "Amps" :227sti->mode == SENSORS_TEMP_CURRENT ? "Curr" :228sti->mode == SENSORS_POWER_CURRENT ? "Pow" :229sti->mode == SENSORS_TEMP_CRITICAL ? "Crit" : "Unkn");230231gr->query_data = sti;232gr->query_new_value = query_sti_load;233234hud_pane_add_graph(pane, gr);235switch (sti->mode) {236case SENSORS_TEMP_CURRENT:237case SENSORS_TEMP_CRITICAL:238hud_pane_set_max_value(pane, 120);239break;240case SENSORS_VOLTAGE_CURRENT:241hud_pane_set_max_value(pane, 12);242break;243case SENSORS_CURRENT_CURRENT:244hud_pane_set_max_value(pane, 5000);245break;246case SENSORS_POWER_CURRENT:247hud_pane_set_max_value(pane, 5000 /* mW */);248break;249}250}251252static void253create_object(const char *chipname, const char *featurename,254const sensors_chip_name *chip, const sensors_feature *feature,255int mode)256{257struct sensors_temp_info *sti = CALLOC_STRUCT(sensors_temp_info);258259sti->mode = mode;260sti->chip = (sensors_chip_name *) chip;261sti->feature = feature;262snprintf(sti->chipname, sizeof(sti->chipname), "%s", chipname);263snprintf(sti->featurename, sizeof(sti->featurename), "%s", featurename);264snprintf(sti->name, sizeof(sti->name), "%s.%s", sti->chipname,265sti->featurename);266267list_addtail(&sti->list, &gsensors_temp_list);268gsensors_temp_count++;269}270271static void272build_sensor_list(void)273{274const sensors_chip_name *chip;275const sensors_chip_name *match = 0;276const sensors_feature *feature;277int chip_nr = 0;278279char name[256];280while ((chip = sensors_get_detected_chips(match, &chip_nr))) {281sensors_snprintf_chip_name(name, sizeof(name), chip);282283/* Get all features and filter accordingly. */284int fnr = 0;285while ((feature = sensors_get_features(chip, &fnr))) {286char *featurename = sensors_get_label(chip, feature);287if (!featurename)288continue;289290/* Create a 'current' and 'critical' object pair.291* Ignore sensor if its not temperature based.292*/293switch(feature->type) {294case SENSORS_FEATURE_TEMP:295create_object(name, featurename, chip, feature,296SENSORS_TEMP_CURRENT);297create_object(name, featurename, chip, feature,298SENSORS_TEMP_CRITICAL);299break;300case SENSORS_FEATURE_IN:301create_object(name, featurename, chip, feature,302SENSORS_VOLTAGE_CURRENT);303break;304case SENSORS_FEATURE_CURR:305create_object(name, featurename, chip, feature,306SENSORS_CURRENT_CURRENT);307break;308case SENSORS_FEATURE_POWER:309create_object(name, featurename, chip, feature,310SENSORS_POWER_CURRENT);311break;312default:313break;314}315free(featurename);316}317}318}319320/**321* Initialize internal object arrays and display lmsensors HUD help.322* \param displayhelp true if the list of detected devices should be323displayed on the console.324* \return number of detected lmsensor devices.325*/326int327hud_get_num_sensors(bool displayhelp)328{329/* Return the number of sensors detected. */330mtx_lock(&gsensor_temp_mutex);331if (gsensors_temp_count) {332mtx_unlock(&gsensor_temp_mutex);333return gsensors_temp_count;334}335336int ret = sensors_init(NULL);337if (ret) {338mtx_unlock(&gsensor_temp_mutex);339return 0;340}341342list_inithead(&gsensors_temp_list);343344/* Scan /sys/block, for every object type we support, create and345* persist an object to represent its different statistics.346*/347build_sensor_list();348349if (displayhelp) {350list_for_each_entry(struct sensors_temp_info, sti, &gsensors_temp_list, list) {351char line[64];352switch (sti->mode) {353case SENSORS_TEMP_CURRENT:354snprintf(line, sizeof(line), " sensors_temp_cu-%s", sti->name);355break;356case SENSORS_TEMP_CRITICAL:357snprintf(line, sizeof(line), " sensors_temp_cr-%s", sti->name);358break;359case SENSORS_VOLTAGE_CURRENT:360snprintf(line, sizeof(line), " sensors_volt_cu-%s", sti->name);361break;362case SENSORS_CURRENT_CURRENT:363snprintf(line, sizeof(line), " sensors_curr_cu-%s", sti->name);364break;365case SENSORS_POWER_CURRENT:366snprintf(line, sizeof(line), " sensors_pow_cu-%s", sti->name);367break;368}369370puts(line);371}372}373374mtx_unlock(&gsensor_temp_mutex);375return gsensors_temp_count;376}377378#endif /* HAVE_LIBSENSORS */379380381