diff options
author | Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com> | 2017-07-12 06:35:20 -0500 |
---|---|---|
committer | Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com> | 2017-08-04 13:23:46 -0500 |
commit | e0af7209c748794b867bce6901f834d10d47773f (patch) | |
tree | 4b658091ac50d581faf8cb458375e6fe3c40c717 /sensordatahandler.cpp | |
parent | 84b3a08074b87dfd15127849ad5e0e6de6a7de2b (diff) | |
download | phosphor-host-ipmid-e0af7209c748794b867bce6901f834d10d47773f.tar.gz phosphor-host-ipmid-e0af7209c748794b867bce6901f834d10d47773f.zip |
IPMI: Virtual sensor support in host ipmid
Resolves openbmc/openbmc#1608
Change-Id: Id76446061fd0fa6dc3dead702538e424293af7ce
Signed-off-by: Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com>
Diffstat (limited to 'sensordatahandler.cpp')
-rw-r--r-- | sensordatahandler.cpp | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/sensordatahandler.cpp b/sensordatahandler.cpp new file mode 100644 index 0000000..6c7b9ac --- /dev/null +++ b/sensordatahandler.cpp @@ -0,0 +1,258 @@ +#include <bitset> +#include <phosphor-logging/elog-errors.hpp> +#include <phosphor-logging/log.hpp> +#include "xyz/openbmc_project/Common/error.hpp" +#include "types.hpp" +#include "sensordatahandler.hpp" + +namespace ipmi +{ +namespace sensor +{ + +using namespace phosphor::logging; +using InternalFailure = + sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; + +static constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; +static constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; +static constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; + +/** @brief get the D-Bus service and service path + * @param[in] bus - The Dbus bus object + * @param[in] interface - interface to the service + * @param[in] path - interested path in the list of objects + * @return pair of service path and service + */ +ServicePath getServiceAndPath(sdbusplus::bus::bus& bus, + const std::string& interface, + const std::string& path) +{ + auto depth = 0; + auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, + MAPPER_PATH, + MAPPER_INTERFACE, + "GetSubTree"); + mapperCall.append("/"); + mapperCall.append(depth); + mapperCall.append(std::vector<Interface>({interface})); + + auto mapperResponseMsg = bus.call(mapperCall); + if (mapperResponseMsg.is_method_error()) + { + std::string err = "Error in mapper GetSubTree " + "Interface: " + interface; + log<level::ERR>(err.c_str()); + elog<InternalFailure>(); + } + + MapperResponseType mapperResponse; + mapperResponseMsg.read(mapperResponse); + if (mapperResponse.empty()) + { + std::string err = "Invalid response from mapper " + "Command: GetSubTree " + "Interface:" + interface; + log<level::ERR>(err.c_str()); + elog<InternalFailure>(); + } + + if (path.empty()) + { + //Get the first one if the path is not in list. + return std::make_pair(mapperResponse.begin()->first, + mapperResponse.begin()->second.begin()->first); + } + const auto& iter = mapperResponse.find(path); + if (iter == mapperResponse.end()) + { + std::string err = "Error in finding sensor dbus" + "Command: GetSubTree " + "Interface:" + interface; + log<level::ERR>(err.c_str()); + elog<InternalFailure>(); + } + return std::make_pair(iter->first, iter->second.begin()->first); +} + +AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData) +{ + Assertion assertionStates = + (static_cast<Assertion>(cmdData.assertOffset8_14)) << 8 | + cmdData.assertOffset0_7; + Deassertion deassertionStates = + (static_cast<Deassertion>(cmdData.deassertOffset8_14)) << 8 | + cmdData.deassertOffset0_7; + return std::make_pair(assertionStates, deassertionStates); +} + +ipmi_ret_t updateToDbus(IpmiUpdateData& msg) +{ + sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; + try + { + auto serviceResponseMsg = bus.call(msg); + if (serviceResponseMsg.is_method_error()) + { + log<level::ERR>("Error in D-Bus call"); + return IPMI_CC_UNSPECIFIED_ERROR; + } + } + catch (InternalFailure& e) + { + commit<InternalFailure>(); + return IPMI_CC_UNSPECIFIED_ERROR; + } + return IPMI_CC_OK; +} + +namespace set +{ + +IpmiUpdateData makeDbusMsg(const std::string& updateInterface, + const std::string& sensorPath, + const std::string& command, + const std::string& sensorInterface) +{ + sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; + using namespace std::string_literals; + + std::string dbusService; + std::string dbusPath; + + std::tie(dbusPath, dbusService) = getServiceAndPath(bus, + sensorInterface, + sensorPath); + return bus.new_method_call(dbusService.c_str(), + dbusPath.c_str(), + updateInterface.c_str(), + command.c_str()); +} + +ipmi_ret_t appendDiscreteSignalData(IpmiUpdateData& msg, + const DbusInterfaceMap& interfaceMap, + uint8_t data) +{ + const auto& interface = interfaceMap.begin(); + msg.append(interface->first); + for (const auto& property : interface->second) + { + msg.append(property.first); + const auto& iter = property.second.find(data); + if (iter == property.second.end()) + { + log<level::ERR>("Invalid event data"); + return IPMI_CC_PARM_OUT_OF_RANGE; + } + msg.append(iter->second.assert); + } + return IPMI_CC_OK; +} + +ipmi_ret_t appendReadingData(IpmiUpdateData& msg, + const DbusInterfaceMap& interfaceMap, + const Value &data) +{ + const auto& interface = interfaceMap.begin(); + msg.append(interface->first); + for (const auto& property : interface->second) + { + msg.append(property.first); + msg.append(data); + } + return IPMI_CC_OK; +} + +ipmi_ret_t appendAssertion(IpmiUpdateData& msg, + const DbusInterfaceMap& interfaceMap, + const std::string& sensorPath, + const SetSensorReadingReq& cmdData) +{ + std::bitset<16> assertionSet(getAssertionSet(cmdData).first); + std::bitset<16> deassertionSet(getAssertionSet(cmdData).second); + + const auto& interface = interfaceMap.begin(); + msg.append(interface->first); + for (const auto& property : interface->second) + { + msg.append(property.first); + for (const auto& value : property.second) + { + if (assertionSet.test(value.first)) + { + msg.append(value.second.assert); + } + if (deassertionSet.test(value.first)) + { + msg.append(value.second.deassert); + } + } + } + return IPMI_CC_OK; +} +}//namespace set + +namespace notify +{ + +IpmiUpdateData makeDbusMsg(const std::string& updateInterface, + const std::string& sensorPath, + const std::string& command, + const std::string& sensorInterface) +{ + sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; + using namespace std::string_literals; + + std::string dbusService; + std::string dbusPath; + + std::tie(dbusPath, dbusService) = getServiceAndPath(bus, + updateInterface); + + return bus.new_method_call(dbusService.c_str(), + dbusPath.c_str(), + updateInterface.c_str(), + command.c_str()); +} + +ipmi_ret_t appendAssertion(IpmiUpdateData& msg, + const DbusInterfaceMap& interfaceMap, + const std::string& sensorPath, + const SetSensorReadingReq& cmdData) +{ + std::bitset<16> assertionSet(getAssertionSet(cmdData).first); + std::bitset<16> deassertionSet(getAssertionSet(cmdData).second); + ipmi::sensor::ObjectMap objects; + ipmi::sensor::InterfaceMap interfaces; + for (const auto& interface : interfaceMap) + { + for (const auto& property : interface.second) + { + ipmi::sensor::PropertyMap props; + bool valid = false; + for (const auto& value : property.second) + { + if (assertionSet.test(value.first)) + { + props.emplace(property.first, value.second.assert); + valid = true; + } + else if (deassertionSet.test(value.first)) + { + props.emplace(property.first, value.second.deassert); + valid = true; + } + } + if (valid) + { + interfaces.emplace(interface.first, std::move(props)); + } + } + } + objects.emplace(sensorPath, std::move(interfaces)); + msg.append(std::move(objects)); + return IPMI_CC_OK; +} +}//namespace notify +}//namespace sensor +}//namespace ipmi |