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