blob: bb75ce474cbe69eedd20d817e1c6a5d02ac3d3fe [file] [log] [blame]
Jason M. Bills3f7c5e42018-10-03 14:00:41 -07001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#include <boost/algorithm/string.hpp>
18#include <boost/container/flat_map.hpp>
19#include <cstring>
20#include <phosphor-logging/log.hpp>
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070021
22#pragma once
23
24struct CmpStrVersion
25{
26 bool operator()(std::string a, std::string b) const
27 {
28 return strverscmp(a.c_str(), b.c_str()) < 0;
29 }
30};
31
32using SensorSubTree = boost::container::flat_map<
33 std::string,
34 boost::container::flat_map<std::string, std::vector<std::string>>,
35 CmpStrVersion>;
36
37inline static bool getSensorSubtree(SensorSubTree& subtree)
38{
39 sd_bus* bus = NULL;
40 int ret = sd_bus_default_system(&bus);
41 if (ret < 0)
42 {
43 phosphor::logging::log<phosphor::logging::level::ERR>(
44 "Failed to connect to system bus",
45 phosphor::logging::entry("ERRNO=0x%X", -ret));
46 sd_bus_unref(bus);
47 return false;
48 }
49 sdbusplus::bus::bus dbus(bus);
50 auto mapperCall =
51 dbus.new_method_call("xyz.openbmc_project.ObjectMapper",
52 "/xyz/openbmc_project/object_mapper",
53 "xyz.openbmc_project.ObjectMapper", "GetSubTree");
Jason M. Bills52341e82018-11-28 17:34:43 -080054 static constexpr const auto depth = 2;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070055 static constexpr std::array<const char*, 3> interfaces = {
56 "xyz.openbmc_project.Sensor.Value",
57 "xyz.openbmc_project.Sensor.Threshold.Warning",
58 "xyz.openbmc_project.Sensor.Threshold.Critical"};
59 mapperCall.append("/xyz/openbmc_project/sensors", depth, interfaces);
60
61 try
62 {
63 auto mapperReply = dbus.call(mapperCall);
64 subtree.clear();
65 mapperReply.read(subtree);
66 }
Jason M. Bills52341e82018-11-28 17:34:43 -080067 catch (sdbusplus::exception_t& e)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070068 {
Jason M. Bills52341e82018-11-28 17:34:43 -080069 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070070 return false;
71 }
72 return true;
73}
74
75struct CmpStr
76{
77 bool operator()(const char* a, const char* b) const
78 {
79 return std::strcmp(a, b) < 0;
80 }
81};
82
Jason M. Bills52341e82018-11-28 17:34:43 -080083enum class SensorTypeCodes : uint8_t
84{
85 reserved = 0x0,
86 temperature = 0x1,
87 voltage = 0x2,
88 current = 0x3,
89 fan = 0x4,
90 other = 0xB,
91};
92
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070093const static boost::container::flat_map<const char*, SensorTypeCodes, CmpStr>
94 sensorTypes{{{"temperature", SensorTypeCodes::temperature},
95 {"voltage", SensorTypeCodes::voltage},
96 {"current", SensorTypeCodes::current},
97 {"fan_tach", SensorTypeCodes::fan},
James Feistf426f332019-01-04 12:48:16 -080098 {"fan_pwm", SensorTypeCodes::fan},
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070099 {"power", SensorTypeCodes::other}}};
100
101inline static std::string getSensorTypeStringFromPath(const std::string& path)
102{
103 // get sensor type string from path, path is defined as
104 // /xyz/openbmc_project/sensors/<type>/label
105 size_t typeEnd = path.rfind("/");
Jason M. Bills360f5932018-11-14 09:08:54 -0800106 if (typeEnd == std::string::npos)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700107 {
Jason M. Bills360f5932018-11-14 09:08:54 -0800108 return path;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700109 }
Jason M. Bills360f5932018-11-14 09:08:54 -0800110 size_t typeStart = path.rfind("/", typeEnd - 1);
111 if (typeStart == std::string::npos)
112 {
113 return path;
114 }
115 // Start at the character after the '/'
116 typeStart++;
117 return path.substr(typeStart, typeEnd - typeStart);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700118}
119
120inline static uint8_t getSensorTypeFromPath(const std::string& path)
121{
122 uint8_t sensorType = 0;
123 std::string type = getSensorTypeStringFromPath(path);
124 auto findSensor = sensorTypes.find(type.c_str());
125 if (findSensor != sensorTypes.end())
126 {
127 sensorType = static_cast<uint8_t>(findSensor->second);
128 } // else default 0x0 RESERVED
129
130 return sensorType;
131}
132
133inline static uint8_t getSensorNumberFromPath(const std::string& path)
134{
135 SensorSubTree sensorTree;
136 if (!getSensorSubtree(sensorTree))
137 return 0xFF;
138 uint8_t sensorNum = 0xFF;
139
140 for (const auto& sensor : sensorTree)
141 {
142 sensorNum++;
143 if (sensor.first == path)
144 {
145 break;
146 }
147 }
148 return sensorNum;
149}
150
151inline static uint8_t getSensorEventTypeFromPath(const std::string& path)
152{
153 // TODO: Add support for additional reading types as needed
154 return 0x1; // reading type = threshold
155}
156
157inline static std::string getPathFromSensorNumber(uint8_t sensorNum)
158{
159 SensorSubTree sensorTree;
160 std::string path;
161 if (!getSensorSubtree(sensorTree))
162 return path;
163
164 if (sensorTree.size() < sensorNum)
165 {
166 return path;
167 }
168
169 uint8_t sensorIndex = sensorNum;
170 for (const auto& sensor : sensorTree)
171 {
172 if (sensorIndex-- == 0)
173 {
174 path = sensor.first;
175 break;
176 }
177 }
178
179 return path;
180}