blob: 6510d6c0f001f53a49f41a04aba34132b2adc8cf [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. Bills17add592018-11-12 14:30:12 -080097 size_t typeStart = path.rfind("/", typeEnd - 1) + 1;
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070098 if (typeEnd != std::string::npos && typeStart != std::string::npos)
99 {
Jason M. Bills17add592018-11-12 14:30:12 -0800100 return path.substr(typeStart, typeEnd - typeStart);
Jason M. Bills3f7c5e42018-10-03 14:00:41 -0700101 }
102 return path;
103}
104
105inline static uint8_t getSensorTypeFromPath(const std::string& path)
106{
107 uint8_t sensorType = 0;
108 std::string type = getSensorTypeStringFromPath(path);
109 auto findSensor = sensorTypes.find(type.c_str());
110 if (findSensor != sensorTypes.end())
111 {
112 sensorType = static_cast<uint8_t>(findSensor->second);
113 } // else default 0x0 RESERVED
114
115 return sensorType;
116}
117
118inline static uint8_t getSensorNumberFromPath(const std::string& path)
119{
120 SensorSubTree sensorTree;
121 if (!getSensorSubtree(sensorTree))
122 return 0xFF;
123 uint8_t sensorNum = 0xFF;
124
125 for (const auto& sensor : sensorTree)
126 {
127 sensorNum++;
128 if (sensor.first == path)
129 {
130 break;
131 }
132 }
133 return sensorNum;
134}
135
136inline static uint8_t getSensorEventTypeFromPath(const std::string& path)
137{
138 // TODO: Add support for additional reading types as needed
139 return 0x1; // reading type = threshold
140}
141
142inline static std::string getPathFromSensorNumber(uint8_t sensorNum)
143{
144 SensorSubTree sensorTree;
145 std::string path;
146 if (!getSensorSubtree(sensorTree))
147 return path;
148
149 if (sensorTree.size() < sensorNum)
150 {
151 return path;
152 }
153
154 uint8_t sensorIndex = sensorNum;
155 for (const auto& sensor : sensorTree)
156 {
157 if (sensorIndex-- == 0)
158 {
159 path = sensor.first;
160 break;
161 }
162 }
163
164 return path;
165}