diff options
author | Mark Brown <broonie@kernel.org> | 2014-11-21 17:41:26 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-11-21 17:41:26 +0000 |
commit | 3070bdc3c302c80996502639e03a2e550571e152 (patch) | |
tree | 9cdbb36ed76dea9b27e1b27d0fcaa3bd2e87f056 /tools/gator/daemon/HwmonDriver.cpp | |
parent | 4f41964e046a17586c216f74f14bd97b3e5164c9 (diff) | |
parent | a0cee48898708dd3074492edf369fd4c5aecb6c3 (diff) |
Merge branch 'linux-linaro-lsk-v3.14' into linux-linaro-lsk-v3.14-android
Diffstat (limited to 'tools/gator/daemon/HwmonDriver.cpp')
-rw-r--r-- | tools/gator/daemon/HwmonDriver.cpp | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/tools/gator/daemon/HwmonDriver.cpp b/tools/gator/daemon/HwmonDriver.cpp new file mode 100644 index 000000000000..9d161ae5ac56 --- /dev/null +++ b/tools/gator/daemon/HwmonDriver.cpp @@ -0,0 +1,245 @@ +/** + * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "HwmonDriver.h" + +#include "libsensors/sensors.h" + +#include "Logging.h" + +// feature->type to input map +static sensors_subfeature_type getInput(const sensors_feature_type type) { + switch (type) { + case SENSORS_FEATURE_IN: return SENSORS_SUBFEATURE_IN_INPUT; + case SENSORS_FEATURE_FAN: return SENSORS_SUBFEATURE_FAN_INPUT; + case SENSORS_FEATURE_TEMP: return SENSORS_SUBFEATURE_TEMP_INPUT; + case SENSORS_FEATURE_POWER: return SENSORS_SUBFEATURE_POWER_INPUT; + case SENSORS_FEATURE_ENERGY: return SENSORS_SUBFEATURE_ENERGY_INPUT; + case SENSORS_FEATURE_CURR: return SENSORS_SUBFEATURE_CURR_INPUT; + case SENSORS_FEATURE_HUMIDITY: return SENSORS_SUBFEATURE_HUMIDITY_INPUT; + default: + logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", type); + handleException(); + } +}; + +class HwmonCounter : public DriverCounter { +public: + HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *chip, const sensors_feature *feature); + ~HwmonCounter(); + + const char *getLabel() const { return label; } + const char *getTitle() const { return title; } + bool isDuplicate() const { return duplicate; } + const char *getDisplay() const { return display; } + const char *getCounterClass() const { return counter_class; } + const char *getUnit() const { return unit; } + int getModifier() const { return modifier; } + + int64_t read(); + +private: + void init(const sensors_chip_name *chip, const sensors_feature *feature); + + const sensors_chip_name *chip; + const sensors_feature *feature; + char *label; + const char *title; + const char *display; + const char *counter_class; + const char *unit; + double previous_value; + int modifier; + int monotonic: 1, + duplicate : 1; + + // Intentionally unimplemented + HwmonCounter(const HwmonCounter &); + HwmonCounter &operator=(const HwmonCounter &); +}; + +HwmonCounter::HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *chip, const sensors_feature *feature) : DriverCounter(next, name), chip(chip), feature(feature), duplicate(false) { + label = sensors_get_label(chip, feature); + + switch (feature->type) { + case SENSORS_FEATURE_IN: + title = "Voltage"; + display = "maximum"; + counter_class = "absolute"; + unit = "V"; + modifier = 1000; + monotonic = false; + break; + case SENSORS_FEATURE_FAN: + title = "Fan"; + display = "average"; + counter_class = "absolute"; + unit = "RPM"; + modifier = 1; + monotonic = false; + break; + case SENSORS_FEATURE_TEMP: + title = "Temperature"; + display = "maximum"; + counter_class = "absolute"; + unit = "°C"; + modifier = 1000; + monotonic = false; + break; + case SENSORS_FEATURE_POWER: + title = "Power"; + display = "maximum"; + counter_class = "absolute"; + unit = "W"; + modifier = 1000000; + monotonic = false; + break; + case SENSORS_FEATURE_ENERGY: + title = "Energy"; + display = "accumulate"; + counter_class = "delta"; + unit = "J"; + modifier = 1000000; + monotonic = true; + break; + case SENSORS_FEATURE_CURR: + title = "Current"; + display = "maximum"; + counter_class = "absolute"; + unit = "A"; + modifier = 1000; + monotonic = false; + break; + case SENSORS_FEATURE_HUMIDITY: + title = "Humidity"; + display = "average"; + counter_class = "absolute"; + unit = "%"; + modifier = 1000; + monotonic = false; + break; + default: + logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", feature->type); + handleException(); + } + + for (HwmonCounter * counter = static_cast<HwmonCounter *>(next); counter != NULL; counter = static_cast<HwmonCounter *>(counter->getNext())) { + if (strcmp(label, counter->getLabel()) == 0 && strcmp(title, counter->getTitle()) == 0) { + duplicate = true; + counter->duplicate = true; + break; + } + } +} + +HwmonCounter::~HwmonCounter() { + free((void *)label); +} + +int64_t HwmonCounter::read() { + double value; + double result; + const sensors_subfeature *subfeature; + + // Keep in sync with the read check in HwmonDriver::readEvents + subfeature = sensors_get_subfeature(chip, feature, getInput(feature->type)); + if (!subfeature) { + logg->logError(__FILE__, __LINE__, "No input value for hwmon sensor %s", label); + handleException(); + } + + if (sensors_get_value(chip, subfeature->number, &value) != 0) { + logg->logError(__FILE__, __LINE__, "Can't get input value for hwmon sensor %s", label); + handleException(); + } + + result = (monotonic ? value - previous_value : value); + previous_value = value; + + return result; +} + +HwmonDriver::HwmonDriver() { +} + +HwmonDriver::~HwmonDriver() { + sensors_cleanup(); +} + +void HwmonDriver::readEvents(mxml_node_t *const) { + int err = sensors_init(NULL); + if (err) { + logg->logMessage("Failed to initialize libsensors! (%d)", err); + return; + } + sensors_sysfs_no_scaling = 1; + + int chip_nr = 0; + const sensors_chip_name *chip; + while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) { + int feature_nr = 0; + const sensors_feature *feature; + while ((feature = sensors_get_features(chip, &feature_nr))) { + // Keep in sync with HwmonCounter::read + // Can this counter be read? + double value; + const sensors_subfeature *const subfeature = sensors_get_subfeature(chip, feature, getInput(feature->type)); + if ((subfeature == NULL) || (sensors_get_value(chip, subfeature->number, &value) != 0)) { + continue; + } + + // Get the name of the counter + int len = sensors_snprintf_chip_name(NULL, 0, chip) + 1; + char *chip_name = new char[len]; + sensors_snprintf_chip_name(chip_name, len, chip); + len = snprintf(NULL, 0, "hwmon_%s_%d_%d", chip_name, chip_nr, feature->number) + 1; + char *const name = new char[len]; + snprintf(name, len, "hwmon_%s_%d_%d", chip_name, chip_nr, feature->number); + delete [] chip_name; + + setCounters(new HwmonCounter(getCounters(), name, chip, feature)); + } + } +} + +void HwmonDriver::writeEvents(mxml_node_t *root) const { + root = mxmlNewElement(root, "category"); + mxmlElementSetAttr(root, "name", "hwmon"); + + char buf[1024]; + for (HwmonCounter *counter = static_cast<HwmonCounter *>(getCounters()); counter != NULL; counter = static_cast<HwmonCounter *>(counter->getNext())) { + mxml_node_t *node = mxmlNewElement(root, "event"); + mxmlElementSetAttr(node, "counter", counter->getName()); + mxmlElementSetAttr(node, "title", counter->getTitle()); + if (counter->isDuplicate()) { + mxmlElementSetAttrf(node, "name", "%s (0x%x)", counter->getLabel(), counter->getKey()); + } else { + mxmlElementSetAttr(node, "name", counter->getLabel()); + } + mxmlElementSetAttr(node, "display", counter->getDisplay()); + mxmlElementSetAttr(node, "class", counter->getCounterClass()); + mxmlElementSetAttr(node, "units", counter->getUnit()); + if (counter->getModifier() != 1) { + mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier()); + } + if (strcmp(counter->getDisplay(), "average") == 0 || strcmp(counter->getDisplay(), "maximum") == 0) { + mxmlElementSetAttr(node, "average_selection", "yes"); + } + snprintf(buf, sizeof(buf), "libsensors %s sensor %s (%s)", counter->getTitle(), counter->getLabel(), counter->getName()); + mxmlElementSetAttr(node, "description", buf); + } +} + +void HwmonDriver::start() { + for (DriverCounter *counter = getCounters(); counter != NULL; counter = counter->getNext()) { + if (!counter->isEnabled()) { + continue; + } + counter->read(); + } +} |