blob: 8969bd65f4ed8b0a1b561a762b66e95e7579e11c [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>
Jason M. Billsa9423b62018-11-29 10:25:16 -080018#include <boost/bimap.hpp>
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070019#include <boost/container/flat_map.hpp>
20#include <cstring>
21#include <phosphor-logging/log.hpp>
Jason M. Billsa9423b62018-11-29 10:25:16 -080022#include <sdbusplus/bus/match.hpp>
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070023
24#pragma once
25
26struct CmpStrVersion
27{
28 bool operator()(std::string a, std::string b) const
29 {
30 return strverscmp(a.c_str(), b.c_str()) < 0;
31 }
32};
33
34using SensorSubTree = boost::container::flat_map<
35 std::string,
36 boost::container::flat_map<std::string, std::vector<std::string>>,
37 CmpStrVersion>;
38
Jason M. Billsa9423b62018-11-29 10:25:16 -080039using SensorNumMap = boost::bimap<int, std::string>;
40
41namespace details
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070042{
Jason M. Billsa9423b62018-11-29 10:25:16 -080043inline static bool getSensorSubtree(std::shared_ptr<SensorSubTree>& subtree)
44{
45 static std::shared_ptr<SensorSubTree> sensorTreePtr;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070046 sd_bus* bus = NULL;
47 int ret = sd_bus_default_system(&bus);
48 if (ret < 0)
49 {
50 phosphor::logging::log<phosphor::logging::level::ERR>(
51 "Failed to connect to system bus",
52 phosphor::logging::entry("ERRNO=0x%X", -ret));
53 sd_bus_unref(bus);
54 return false;
55 }
56 sdbusplus::bus::bus dbus(bus);
Jason M. Billsa9423b62018-11-29 10:25:16 -080057 static sdbusplus::bus::match::match sensorAdded(
58 dbus,
59 "type='signal',member='InterfacesAdded',arg0path='/xyz/openbmc_project/"
60 "sensors/'",
61 [](sdbusplus::message::message& m) { sensorTreePtr.reset(); });
62
63 static sdbusplus::bus::match::match sensorRemoved(
64 dbus,
65 "type='signal',member='InterfacesRemoved',arg0path='/xyz/"
66 "openbmc_project/sensors/'",
67 [](sdbusplus::message::message& m) { sensorTreePtr.reset(); });
68
69 bool sensorTreeUpdated = false;
70 if (sensorTreePtr)
71 {
72 subtree = sensorTreePtr;
73 return sensorTreeUpdated;
74 }
75
76 sensorTreePtr = std::make_shared<SensorSubTree>();
77
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070078 auto mapperCall =
79 dbus.new_method_call("xyz.openbmc_project.ObjectMapper",
80 "/xyz/openbmc_project/object_mapper",
81 "xyz.openbmc_project.ObjectMapper", "GetSubTree");
Jason M. Bills52341e82018-11-28 17:34:43 -080082 static constexpr const auto depth = 2;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070083 static constexpr std::array<const char*, 3> interfaces = {
84 "xyz.openbmc_project.Sensor.Value",
85 "xyz.openbmc_project.Sensor.Threshold.Warning",
86 "xyz.openbmc_project.Sensor.Threshold.Critical"};
87 mapperCall.append("/xyz/openbmc_project/sensors", depth, interfaces);
88
89 try
90 {
91 auto mapperReply = dbus.call(mapperCall);
Jason M. Billsa9423b62018-11-29 10:25:16 -080092 mapperReply.read(*sensorTreePtr);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070093 }
Jason M. Bills52341e82018-11-28 17:34:43 -080094 catch (sdbusplus::exception_t& e)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070095 {
Jason M. Bills52341e82018-11-28 17:34:43 -080096 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
Jason M. Billsa9423b62018-11-29 10:25:16 -080097 return sensorTreeUpdated;
98 }
99 subtree = sensorTreePtr;
100 sensorTreeUpdated = true;
101 return sensorTreeUpdated;
102}
103
104inline static bool getSensorNumMap(std::shared_ptr<SensorNumMap>& sensorNumMap)
105{
106 static std::shared_ptr<SensorNumMap> sensorNumMapPtr;
107 bool sensorNumMapUpated = false;
108
109 std::shared_ptr<SensorSubTree> sensorTree;
110 bool sensorTreeUpdated = details::getSensorSubtree(sensorTree);
111 if (!sensorTree)
112 {
113 return sensorNumMapUpated;
114 }
115
116 if (!sensorTreeUpdated && sensorNumMapPtr)
117 {
118 sensorNumMap = sensorNumMapPtr;
119 return sensorNumMapUpated;
120 }
121
122 sensorNumMapPtr = std::make_shared<SensorNumMap>();
123
Jason M. Billscaed9052019-06-14 10:42:20 -0700124 uint8_t sensorNum = 0;
Jason M. Billsa9423b62018-11-29 10:25:16 -0800125 for (const auto& sensor : *sensorTree)
126 {
127 sensorNumMapPtr->insert(
128 SensorNumMap::value_type(sensorNum++, sensor.first));
129 }
130 sensorNumMap = sensorNumMapPtr;
131 sensorNumMapUpated = true;
132 return sensorNumMapUpated;
133}
134} // namespace details
135
136inline static bool getSensorSubtree(SensorSubTree& subtree)
137{
138 std::shared_ptr<SensorSubTree> sensorTree;
139 details::getSensorSubtree(sensorTree);
140 if (!sensorTree)
141 {
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700142 return false;
143 }
Jason M. Billsa9423b62018-11-29 10:25:16 -0800144
145 subtree = *sensorTree;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700146 return true;
147}
148
149struct CmpStr
150{
151 bool operator()(const char* a, const char* b) const
152 {
153 return std::strcmp(a, b) < 0;
154 }
155};
156
Jason M. Bills52341e82018-11-28 17:34:43 -0800157enum class SensorTypeCodes : uint8_t
158{
159 reserved = 0x0,
160 temperature = 0x1,
161 voltage = 0x2,
162 current = 0x3,
163 fan = 0x4,
164 other = 0xB,
165};
166
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700167const static boost::container::flat_map<const char*, SensorTypeCodes, CmpStr>
168 sensorTypes{{{"temperature", SensorTypeCodes::temperature},
169 {"voltage", SensorTypeCodes::voltage},
170 {"current", SensorTypeCodes::current},
171 {"fan_tach", SensorTypeCodes::fan},
James Feistf426f332019-01-04 12:48:16 -0800172 {"fan_pwm", SensorTypeCodes::fan},
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700173 {"power", SensorTypeCodes::other}}};
174
175inline static std::string getSensorTypeStringFromPath(const std::string& path)
176{
177 // get sensor type string from path, path is defined as
178 // /xyz/openbmc_project/sensors/<type>/label
179 size_t typeEnd = path.rfind("/");
Jason M. Bills360f5932018-11-14 09:08:54 -0800180 if (typeEnd == std::string::npos)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700181 {
Jason M. Bills360f5932018-11-14 09:08:54 -0800182 return path;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700183 }
Jason M. Bills360f5932018-11-14 09:08:54 -0800184 size_t typeStart = path.rfind("/", typeEnd - 1);
185 if (typeStart == std::string::npos)
186 {
187 return path;
188 }
189 // Start at the character after the '/'
190 typeStart++;
191 return path.substr(typeStart, typeEnd - typeStart);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700192}
193
194inline static uint8_t getSensorTypeFromPath(const std::string& path)
195{
196 uint8_t sensorType = 0;
197 std::string type = getSensorTypeStringFromPath(path);
198 auto findSensor = sensorTypes.find(type.c_str());
199 if (findSensor != sensorTypes.end())
200 {
201 sensorType = static_cast<uint8_t>(findSensor->second);
202 } // else default 0x0 RESERVED
203
204 return sensorType;
205}
206
207inline static uint8_t getSensorNumberFromPath(const std::string& path)
208{
Jason M. Billsa9423b62018-11-29 10:25:16 -0800209 std::shared_ptr<SensorNumMap> sensorNumMapPtr;
210 details::getSensorNumMap(sensorNumMapPtr);
211 if (!sensorNumMapPtr)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700212 {
Jason M. Billsa9423b62018-11-29 10:25:16 -0800213 return 0xFF;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700214 }
Jason M. Billsa9423b62018-11-29 10:25:16 -0800215
216 try
217 {
218 return sensorNumMapPtr->right.at(path);
219 }
220 catch (std::out_of_range& e)
221 {
222 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
223 return 0xFF;
224 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700225}
226
227inline static uint8_t getSensorEventTypeFromPath(const std::string& path)
228{
229 // TODO: Add support for additional reading types as needed
230 return 0x1; // reading type = threshold
231}
232
233inline static std::string getPathFromSensorNumber(uint8_t sensorNum)
234{
Jason M. Billsa9423b62018-11-29 10:25:16 -0800235 std::shared_ptr<SensorNumMap> sensorNumMapPtr;
236 details::getSensorNumMap(sensorNumMapPtr);
237 if (!sensorNumMapPtr)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700238 {
Jason M. Billsa9423b62018-11-29 10:25:16 -0800239 return std::string();
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700240 }
241
Jason M. Billsa9423b62018-11-29 10:25:16 -0800242 try
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700243 {
Jason M. Billsa9423b62018-11-29 10:25:16 -0800244 return sensorNumMapPtr->left.at(sensorNum);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700245 }
Jason M. Billsa9423b62018-11-29 10:25:16 -0800246 catch (std::out_of_range& e)
247 {
248 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
249 return std::string();
250 }
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700251}