blob: 7c7b3118296ccf893b3cd0e4aa93aafb76357e61 [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>
21#include <storagecommands.hpp>
22
23#pragma once
24
25struct CmpStrVersion
26{
27 bool operator()(std::string a, std::string b) const
28 {
29 return strverscmp(a.c_str(), b.c_str()) < 0;
30 }
31};
32
33using SensorSubTree = boost::container::flat_map<
34 std::string,
35 boost::container::flat_map<std::string, std::vector<std::string>>,
36 CmpStrVersion>;
37
38inline static bool getSensorSubtree(SensorSubTree& subtree)
39{
40 sd_bus* bus = NULL;
41 int ret = sd_bus_default_system(&bus);
42 if (ret < 0)
43 {
44 phosphor::logging::log<phosphor::logging::level::ERR>(
45 "Failed to connect to system bus",
46 phosphor::logging::entry("ERRNO=0x%X", -ret));
47 sd_bus_unref(bus);
48 return false;
49 }
50 sdbusplus::bus::bus dbus(bus);
51 auto mapperCall =
52 dbus.new_method_call("xyz.openbmc_project.ObjectMapper",
53 "/xyz/openbmc_project/object_mapper",
54 "xyz.openbmc_project.ObjectMapper", "GetSubTree");
55 static const auto depth = 2;
56 static constexpr std::array<const char*, 3> interfaces = {
57 "xyz.openbmc_project.Sensor.Value",
58 "xyz.openbmc_project.Sensor.Threshold.Warning",
59 "xyz.openbmc_project.Sensor.Threshold.Critical"};
60 mapperCall.append("/xyz/openbmc_project/sensors", depth, interfaces);
61
62 try
63 {
64 auto mapperReply = dbus.call(mapperCall);
65 subtree.clear();
66 mapperReply.read(subtree);
67 }
68 catch (sdbusplus::exception_t&)
69 {
70 phosphor::logging::log<phosphor::logging::level::ERR>(
71 "getSensorSubtree: Error calling mapper");
72 return false;
73 }
74 return true;
75}
76
77struct CmpStr
78{
79 bool operator()(const char* a, const char* b) const
80 {
81 return std::strcmp(a, b) < 0;
82 }
83};
84
85const static boost::container::flat_map<const char*, SensorTypeCodes, CmpStr>
86 sensorTypes{{{"temperature", SensorTypeCodes::temperature},
87 {"voltage", SensorTypeCodes::voltage},
88 {"current", SensorTypeCodes::current},
89 {"fan_tach", SensorTypeCodes::fan},
90 {"power", SensorTypeCodes::other}}};
91
92inline static std::string getSensorTypeStringFromPath(const std::string& path)
93{
94 // get sensor type string from path, path is defined as
95 // /xyz/openbmc_project/sensors/<type>/label
96 size_t typeEnd = path.rfind("/");
Jason M. Bills360f5932018-11-14 09:08:54 -080097 if (typeEnd == std::string::npos)
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070098 {
Jason M. Bills360f5932018-11-14 09:08:54 -080099 return path;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700100 }
Jason M. Bills360f5932018-11-14 09:08:54 -0800101 size_t typeStart = path.rfind("/", typeEnd - 1);
102 if (typeStart == std::string::npos)
103 {
104 return path;
105 }
106 // Start at the character after the '/'
107 typeStart++;
108 return path.substr(typeStart, typeEnd - typeStart);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700109}
110
111inline static uint8_t getSensorTypeFromPath(const std::string& path)
112{
113 uint8_t sensorType = 0;
114 std::string type = getSensorTypeStringFromPath(path);
115 auto findSensor = sensorTypes.find(type.c_str());
116 if (findSensor != sensorTypes.end())
117 {
118 sensorType = static_cast<uint8_t>(findSensor->second);
119 } // else default 0x0 RESERVED
120
121 return sensorType;
122}
123
124inline static uint8_t getSensorNumberFromPath(const std::string& path)
125{
126 SensorSubTree sensorTree;
127 if (!getSensorSubtree(sensorTree))
128 return 0xFF;
129 uint8_t sensorNum = 0xFF;
130
131 for (const auto& sensor : sensorTree)
132 {
133 sensorNum++;
134 if (sensor.first == path)
135 {
136 break;
137 }
138 }
139 return sensorNum;
140}
141
142inline static uint8_t getSensorEventTypeFromPath(const std::string& path)
143{
144 // TODO: Add support for additional reading types as needed
145 return 0x1; // reading type = threshold
146}
147
148inline static std::string getPathFromSensorNumber(uint8_t sensorNum)
149{
150 SensorSubTree sensorTree;
151 std::string path;
152 if (!getSensorSubtree(sensorTree))
153 return path;
154
155 if (sensorTree.size() < sensorNum)
156 {
157 return path;
158 }
159
160 uint8_t sensorIndex = sensorNum;
161 for (const auto& sensor : sensorTree)
162 {
163 if (sensorIndex-- == 0)
164 {
165 path = sensor.first;
166 break;
167 }
168 }
169
170 return path;
171}