blob: 55ee5399329f894688f9e5ea9b5dd75f0b2105ab [file] [log] [blame]
#pragma once
#include <functional>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/object.hpp>
#include <org/open_power/OCC/Status/server.hpp>
#include <org/open_power/Control/Host/server.hpp>
#include "occ_events.hpp"
#include "occ_device.hpp"
#include "i2c_occ.hpp"
namespace open_power
{
namespace occ
{
class Manager;
namespace Base = sdbusplus::org::open_power::OCC::server;
using Interface = sdbusplus::server::object::object<Base::Status>;
// IPMID's host control application
namespace Control = sdbusplus::org::open_power::Control::server;
// For waiting on signals
namespace sdbusRule = sdbusplus::bus::match::rules;
// OCC status instance. Ex. for "occ0", the instance is 0
using instanceID = int;
// IPMI sensor ID for a given OCC instance
using sensorID = uint8_t;
/** @class Status
* @brief Implementation of OCC Active Status
*/
class Status : public Interface
{
public:
Status() = delete;
~Status() = default;
Status(const Status&) = delete;
Status& operator=(const Status&) = delete;
Status(Status&&) = default;
Status& operator=(Status&&) = default;
/** @brief Constructs the Status object and
* the underlying device object
*
* @param[in] bus - DBus bus to attach to
* @param[in] event - sd_event unique pointer reference
* @param[in] path - DBus object path
* @param[in] manager - OCC manager instance
* @param[in] callBack - Callback handler to invoke during
* property change
*/
Status(sdbusplus::bus::bus& bus,
EventPtr& event,
const char* path,
const Manager& manager,
std::function<void(bool)> callBack = nullptr)
: Interface(bus, path, true),
bus(bus),
path(path),
callBack(callBack),
instance(((this->path.back() - '0'))),
device(event,
#ifdef I2C_OCC
i2c_occ::getI2cDeviceName(path),
#else
name + std::to_string(instance + 1),
#endif
manager,
std::bind(&Status::deviceErrorHandler, this)),
hostControlSignal(
bus,
sdbusRule::type::signal() +
sdbusRule::member("CommandComplete") +
sdbusRule::path("/org/open_power/control/host0") +
sdbusRule::interface("org.open_power.Control.Host") +
sdbusRule::argN(0, Control::convertForMessage(
Control::Host::Command::OCCReset)),
std::bind(std::mem_fn(&Status::hostControlEvent),
this, std::placeholders::_1))
{
// Check to see if we have OCC already bound. If so, just set it
if (device.bound())
{
this->occActive(true);
}
// Announce that we are ready
this->emit_object_added();
}
/** @brief Since we are overriding the setter-occActive but not the
* getter-occActive, we need to have this using in order to
* allow passthrough usage of the getter-occActive
*/
using Base::Status::occActive;
/** @brief SET OccActive to True or False
*
* @param[in] value - Intended value
*
* @return - Updated value of the property
*/
bool occActive(bool value) override;
/** @brief Starts OCC error detection */
inline void addErrorWatch()
{
return device.addErrorWatch();
}
/** @brief Stops OCC error detection */
inline void removeErrorWatch()
{
return device.removeErrorWatch();
}
private:
/** @brief sdbus handle */
sdbusplus::bus::bus& bus;
/** @brief OCC dbus object path */
std::string path;
/** @brief Callback handler to be invoked during property change.
* This is a handler in Manager class
*/
std::function<void(bool)> callBack;
/** @brief occ name prefix */
std::string name = OCC_NAME;
/** @brief OCC instance number. Ex, 0,1, etc */
int instance;
/** @brief OCC instance to Sensor ID mapping */
static const std::map<instanceID, sensorID> sensorMap;
/** @brief OCC device object to do bind and unbind */
Device device;
/** @brief Subscribe to host control signal
*
* Once the OCC reset is requested, BMC sends that message to host.
* If the host does not ack the message, then there would be a timeout
* and we need to catch that to log an error
**/
sdbusplus::bus::match_t hostControlSignal;
/** @brief Callback handler when device errors are detected */
void deviceErrorHandler();
/** @brief Callback function on host control signals
*
* @param[in] msg - Data associated with subscribed signal
*/
void hostControlEvent(sdbusplus::message::message& msg);
/** @brief Sends a message to host control command handler to reset OCC
*/
void resetOCC();
};
} // namespace occ
} // namespace open_power