2 * Copyright (C) ARM Limited 2013-2014. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
11 #include "libsensors/sensors.h"
16 #include "SessionData.h"
20 HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, const sensors_feature *feature);
23 HwmonCounter *getNext() const { return next; }
24 int getKey() const { return key; }
25 bool isEnabled() const { return enabled; }
26 const char *getName() const { return name; }
27 const char *getLabel() const { return label; }
28 const char *getTitle() const { return title; }
29 bool isDuplicate() const { return duplicate; }
30 const char *getDisplay() const { return display; }
31 const char *getCounterClass() const { return counter_class; }
32 const char *getUnit() const { return unit; }
33 int getModifier() const { return modifier; }
35 void setEnabled(const bool enabled) {
36 this->enabled = enabled;
37 // canRead will clear enabled if the counter is not readable
45 void init(const sensors_chip_name *chip, const sensors_feature *feature);
47 HwmonCounter *const next;
55 const sensors_chip_name *chip;
56 const sensors_feature *feature;
62 const char *counter_class;
65 double previous_value;
67 sensors_subfeature_type input;
69 // Intentionally unimplemented
70 HwmonCounter(const HwmonCounter &);
71 HwmonCounter &operator=(const HwmonCounter &);
74 HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, const sensors_feature *feature) : next(next), key(getEventKey()), polled(false), readable(false), enabled(false), duplicate(false), chip(chip), feature(feature) {
76 int len = sensors_snprintf_chip_name(NULL, 0, chip) + 1;
77 char *chip_name = new char[len];
78 sensors_snprintf_chip_name(chip_name, len, chip);
80 len = snprintf(NULL, 0, "hwmon_%s_%d", chip_name, feature->number) + 1;
82 snprintf(name, len, "hwmon_%s_%d", chip_name, feature->number);
86 label = sensors_get_label(chip, feature);
88 switch (feature->type) {
89 case SENSORS_FEATURE_IN:
91 input = SENSORS_SUBFEATURE_IN_INPUT;
93 counter_class = "absolute";
98 case SENSORS_FEATURE_FAN:
100 input = SENSORS_SUBFEATURE_FAN_INPUT;
102 counter_class = "absolute";
107 case SENSORS_FEATURE_TEMP:
108 title = "Temperature";
109 input = SENSORS_SUBFEATURE_TEMP_INPUT;
111 counter_class = "absolute";
116 case SENSORS_FEATURE_POWER:
118 input = SENSORS_SUBFEATURE_POWER_INPUT;
120 counter_class = "absolute";
125 case SENSORS_FEATURE_ENERGY:
127 input = SENSORS_SUBFEATURE_ENERGY_INPUT;
128 display = "accumulate";
129 counter_class = "delta";
134 case SENSORS_FEATURE_CURR:
136 input = SENSORS_SUBFEATURE_CURR_INPUT;
138 counter_class = "absolute";
143 case SENSORS_FEATURE_HUMIDITY:
145 input = SENSORS_SUBFEATURE_HUMIDITY_INPUT;
147 counter_class = "absolute";
153 logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", feature->type);
157 for (HwmonCounter * counter = next; counter != NULL; counter = counter->getNext()) {
158 if (strcmp(label, counter->getLabel()) == 0 && strcmp(title, counter->getTitle()) == 0) {
160 counter->duplicate = true;
166 HwmonCounter::~HwmonCounter() {
171 double HwmonCounter::read() {
174 const sensors_subfeature *subfeature;
176 // Keep in sync with canRead
177 subfeature = sensors_get_subfeature(chip, feature, input);
179 logg->logError(__FILE__, __LINE__, "No input value for hwmon sensor %s", label);
183 if (sensors_get_value(chip, subfeature->number, &value) != 0) {
184 logg->logError(__FILE__, __LINE__, "Can't get input value for hwmon sensor %s", label);
188 result = (monotonic ? value - previous_value : value);
189 previous_value = value;
194 bool HwmonCounter::canRead() {
197 const sensors_subfeature *subfeature;
200 subfeature = sensors_get_subfeature(chip, feature, input);
204 result = sensors_get_value(chip, subfeature->number, &value) == 0;
216 Hwmon::Hwmon() : counters(NULL) {
220 while (counters != NULL) {
221 HwmonCounter * counter = counters;
222 counters = counter->getNext();
228 void Hwmon::setup() {
229 // hwmon does not currently work with perf
230 if (gSessionData->perf.isSetup()) {
234 int err = sensors_init(NULL);
236 logg->logMessage("Failed to initialize libsensors! (%d)", err);
239 sensors_sysfs_no_scaling = 1;
242 const sensors_chip_name *chip;
243 while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
245 const sensors_feature *feature;
246 while ((feature = sensors_get_features(chip, &feature_nr))) {
247 counters = new HwmonCounter(counters, chip, feature);
252 HwmonCounter *Hwmon::findCounter(const Counter &counter) const {
253 for (HwmonCounter * hwmonCounter = counters; hwmonCounter != NULL; hwmonCounter = hwmonCounter->getNext()) {
254 if (hwmonCounter->canRead() && strcmp(hwmonCounter->getName(), counter.getType()) == 0) {
262 bool Hwmon::claimCounter(const Counter &counter) const {
263 return findCounter(counter) != NULL;
266 bool Hwmon::countersEnabled() const {
267 for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
268 if (counter->isEnabled()) {
275 void Hwmon::resetCounters() {
276 for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
277 counter->setEnabled(false);
281 void Hwmon::setupCounter(Counter &counter) {
282 HwmonCounter *const hwmonCounter = findCounter(counter);
283 if (hwmonCounter == NULL) {
284 counter.setEnabled(false);
287 hwmonCounter->setEnabled(true);
288 counter.setKey(hwmonCounter->getKey());
291 int Hwmon::writeCounters(mxml_node_t *root) const {
293 for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
294 if (!counter->canRead()) {
297 mxml_node_t *node = mxmlNewElement(root, "counter");
298 mxmlElementSetAttr(node, "name", counter->getName());
305 void Hwmon::writeEvents(mxml_node_t *root) const {
306 root = mxmlNewElement(root, "category");
307 mxmlElementSetAttr(root, "name", "hwmon");
310 for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
311 if (!counter->canRead()) {
314 mxml_node_t *node = mxmlNewElement(root, "event");
315 mxmlElementSetAttr(node, "counter", counter->getName());
316 mxmlElementSetAttr(node, "title", counter->getTitle());
317 if (counter->isDuplicate()) {
318 mxmlElementSetAttrf(node, "name", "%s (0x%x)", counter->getLabel(), counter->getKey());
320 mxmlElementSetAttr(node, "name", counter->getLabel());
322 mxmlElementSetAttr(node, "display", counter->getDisplay());
323 mxmlElementSetAttr(node, "class", counter->getCounterClass());
324 mxmlElementSetAttr(node, "units", counter->getUnit());
325 if (counter->getModifier() != 1) {
326 mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier());
328 if (strcmp(counter->getDisplay(), "average") == 0 || strcmp(counter->getDisplay(), "maximum") == 0) {
329 mxmlElementSetAttr(node, "average_selection", "yes");
331 snprintf(buf, sizeof(buf), "libsensors %s sensor %s (%s)", counter->getTitle(), counter->getLabel(), counter->getName());
332 mxmlElementSetAttr(node, "description", buf);
336 void Hwmon::start() {
337 for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
338 if (!counter->isEnabled()) {
345 void Hwmon::read(Buffer * const buffer) {
346 for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
347 if (!counter->isEnabled()) {
350 buffer->event(counter->getKey(), counter->read());