blob: ae49f40ee8ee60bcfde62ef98b8935aff68b346c [file] [log] [blame]
# Copyright 2015 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from __future__ import division
import re
from devlib.instrument import Instrument, Measurement, INSTANTANEOUS
from devlib.exception import TargetError
class HwmonInstrument(Instrument):
name = 'hwmon'
mode = INSTANTANEOUS
# sensor kind --> (meaure, standard unit conversion)
measure_map = {
'temp': ('temperature', lambda x: x / 1000),
'in': ('voltage', lambda x: x / 1000),
'curr': ('current', lambda x: x / 1000),
'power': ('power', lambda x: x / 1000000),
'energy': ('energy', lambda x: x / 1000000),
}
def __init__(self, target):
if not hasattr(target, 'hwmon'):
raise TargetError('Target does not support HWMON')
super(HwmonInstrument, self).__init__(target)
self.logger.debug('Discovering available HWMON sensors...')
for ts in self.target.hwmon.sensors:
try:
ts.get_file('input')
measure = self.measure_map.get(ts.kind)[0]
if measure:
self.logger.debug('\tAdding sensor {}'.format(ts.name))
self.add_channel(_guess_site(ts), measure, name=ts.name, sensor=ts)
else:
self.logger.debug('\tSkipping sensor {} (unknown kind "{}")'.format(ts.name, ts.kind))
except ValueError:
message = 'Skipping sensor {} because it does not have an input file'
self.logger.debug(message.format(ts.name))
continue
def take_measurement(self):
result = []
for chan in self.active_channels:
convert = self.measure_map[chan.sensor.kind][1]
value = convert(chan.sensor.get('input'))
result.append(Measurement(value, chan))
return result
def _guess_site(sensor):
"""
HWMON does not specify a standard for labeling its sensors, or for
device/item split (the implication is that each hwmon device a separate chip
with possibly several sensors on it, but not everyone adheres to that, e.g.,
with some mobile devices splitting a chip's sensors across multiple hwmon
devices. This function processes name/label of the senors to attempt to
identify the best "candidate" for the site to which the sensor belongs.
"""
if sensor.name == sensor.label:
# If no label has been specified for the sensor (in which case, it
# defaults to the sensor's name), assume that the "site" of the sensor
# is identified by the HWMON device
text = sensor.device.name
else:
# If a label has been specified, assume multiple sensors controlled by
# the same device and the label identifies the site.
text = sensor.label
# strip out sensor kind suffix, if any, as that does not indicate a site
for kind in ['volt', 'in', 'curr', 'power', 'energy',
'temp', 'voltage', 'temperature', 'current']:
if kind in text.lower():
regex = re.compile(r'_*{}\d*_*'.format(kind), re.I)
text = regex.sub('', text)
return text.strip()