1# Copyright 2015 ARM Limited 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# 15import re 16from collections import defaultdict 17 18from devlib.module import Module 19from devlib.utils.types import integer 20 21 22HWMON_ROOT = '/sys/class/hwmon' 23HWMON_FILE_REGEX = re.compile(r'(?P<kind>\w+?)(?P<number>\d+)_(?P<item>\w+)') 24 25 26class HwmonSensor(object): 27 28 def __init__(self, device, path, kind, number): 29 self.device = device 30 self.path = path 31 self.kind = kind 32 self.number = number 33 self.target = self.device.target 34 self.name = '{}/{}{}'.format(self.device.name, self.kind, self.number) 35 self.label = self.name 36 self.items = set() 37 38 def add(self, item): 39 self.items.add(item) 40 if item == 'label': 41 self.label = self.get('label') 42 43 def get(self, item): 44 path = self.get_file(item) 45 value = self.target.read_value(path) 46 try: 47 return integer(value) 48 except (TypeError, ValueError): 49 return value 50 51 def set(self, item, value): 52 path = self.get_file(item) 53 self.target.write_value(path, value) 54 55 def get_file(self, item): 56 if item not in self.items: 57 raise ValueError('item "{}" does not exist for {}'.format(item, self.name)) 58 filename = '{}{}_{}'.format(self.kind, self.number, item) 59 return self.target.path.join(self.path, filename) 60 61 def __str__(self): 62 if self.name != self.label: 63 text = 'HS({}, {})'.format(self.name, self.label) 64 else: 65 text = 'HS({})'.format(self.name) 66 return text 67 68 __repr__ = __str__ 69 70 71class HwmonDevice(object): 72 73 @property 74 def sensors(self): 75 all_sensors = [] 76 for sensors_of_kind in self._sensors.itervalues(): 77 all_sensors.extend(sensors_of_kind.values()) 78 return all_sensors 79 80 def __init__(self, target, path): 81 self.target = target 82 self.path = path 83 self.name = self.target.read_value(self.target.path.join(self.path, 'name')) 84 self._sensors = defaultdict(dict) 85 path = self.path 86 if not path.endswith(self.target.path.sep): 87 path += self.target.path.sep 88 for entry in self.target.list_directory(path, 89 as_root=self.target.is_rooted): 90 match = HWMON_FILE_REGEX.search(entry) 91 if match: 92 kind = match.group('kind') 93 number = int(match.group('number')) 94 item = match.group('item') 95 if number not in self._sensors[kind]: 96 sensor = HwmonSensor(self, self.path, kind, number) 97 self._sensors[kind][number] = sensor 98 self._sensors[kind][number].add(item) 99 100 def get(self, kind, number=None): 101 if number is None: 102 return [s for _, s in sorted(self._sensors[kind].iteritems(), 103 key=lambda x: x[0])] 104 else: 105 return self._sensors[kind].get(number) 106 107 def __str__(self): 108 return 'HD({})'.format(self.name) 109 110 __repr__ = __str__ 111 112 113class HwmonModule(Module): 114 115 name = 'hwmon' 116 117 @staticmethod 118 def probe(target): 119 return target.file_exists(HWMON_ROOT) 120 121 @property 122 def sensors(self): 123 all_sensors = [] 124 for device in self.devices: 125 all_sensors.extend(device.sensors) 126 return all_sensors 127 128 def __init__(self, target): 129 super(HwmonModule, self).__init__(target) 130 self.root = HWMON_ROOT 131 self.devices = [] 132 self.scan() 133 134 def scan(self): 135 for entry in self.target.list_directory(self.root, 136 as_root=self.target.is_rooted): 137 if entry.startswith('hwmon'): 138 entry_path = self.target.path.join(self.root, entry) 139 if self.target.file_exists(self.target.path.join(entry_path, 'name')): 140 device = HwmonDevice(self.target, entry_path) 141 self.devices.append(device) 142 143