blob: 2def3c11bd1d0690d53a68cdf362635c7288e9fa [file] [log] [blame]
/*
// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#include <ChassisIntrusionSensor.hpp>
#include <Utils.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/asio.hpp>
#include <chrono>
#include <ctime>
#include <iostream>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/asio/sd_event.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/exception.hpp>
#include <sdbusplus/server.hpp>
#include <sdbusplus/timer.hpp>
static constexpr bool DEBUG = false;
static constexpr const char* sensorType =
"xyz.openbmc_project.Configuration.ChassisIntrusionSensor";
static bool getIntrusionSensorConfig(
std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
IntrusionSensorType* pType, int* pBusId, int* pSlaveAddr, int* pGpioIndex,
bool* pGpioInverted)
{
// find matched configuration according to sensor type
ManagedObjectType sensorConfigurations;
bool useCache = false;
if (!getSensorConfiguration(sensorType, dbusConnection,
sensorConfigurations, useCache))
{
std::cerr << "error communicating to entity manager\n";
return false;
}
const SensorData* sensorData = nullptr;
const std::pair<std::string,
boost::container::flat_map<std::string, BasicVariantType>>*
baseConfiguration = nullptr;
// Get bus and addr of matched configuration
for (const std::pair<sdbusplus::message::object_path, SensorData>& sensor :
sensorConfigurations)
{
baseConfiguration = nullptr;
sensorData = &(sensor.second);
// match sensor type
auto sensorBase = sensorData->find(sensorType);
if (sensorBase == sensorData->end())
{
std::cerr << "error finding base configuration \n";
continue;
}
baseConfiguration = &(*sensorBase);
// judge class, "Gpio" or "I2C"
auto findClass = baseConfiguration->second.find("Class");
if (findClass != baseConfiguration->second.end() &&
sdbusplus::message::variant_ns::get<std::string>(
findClass->second) == "Gpio")
{
*pType = IntrusionSensorType::gpio;
}
else
{
*pType = IntrusionSensorType::pch;
}
// case to find GPIO info
if (*pType == IntrusionSensorType::gpio)
{
auto gpioConfig =
sensorData->find(sensorType + std::string(".GpioIntrusion"));
if (gpioConfig == sensorData->end())
{
std::cerr
<< "error finding GpioIntrusion info in configuration \n";
continue;
}
auto findGpioIndex = gpioConfig->second.find("Index");
auto findGpioPolarity = gpioConfig->second.find("Polarity");
if (findGpioIndex == gpioConfig->second.end() ||
findGpioPolarity == gpioConfig->second.end())
{
std::cerr << "error finding gpio info in configuration \n";
continue;
}
try
{
*pGpioIndex = sdbusplus::message::variant_ns::get<uint64_t>(
findGpioIndex->second);
*pGpioInverted =
(sdbusplus::message::variant_ns::get<std::string>(
findGpioPolarity->second) == "Low");
}
catch (const std::bad_variant_access& e)
{
std::cerr << "invalid value for gpio info in config. \n";
continue;
}
if (DEBUG)
{
std::cout << "find matched GPIO index " << *pGpioIndex
<< ", polarity inverted flag is " << *pGpioInverted
<< "\n";
}
return true;
}
// case to find I2C info
else if (*pType == IntrusionSensorType::pch)
{
auto findBus = baseConfiguration->second.find("Bus");
auto findAddress = baseConfiguration->second.find("Address");
if (findBus == baseConfiguration->second.end() ||
findAddress == baseConfiguration->second.end())
{
std::cerr << "error finding bus or address in configuration \n";
continue;
}
try
{
*pBusId = sdbusplus::message::variant_ns::get<uint64_t>(
findBus->second);
*pSlaveAddr = sdbusplus::message::variant_ns::get<uint64_t>(
findAddress->second);
}
catch (const std::bad_variant_access& e)
{
std::cerr << "invalid value for bus or address in config. \n";
continue;
}
if (DEBUG)
{
std::cout << "find matched bus " << *pBusId
<< ", matched slave addr " << *pSlaveAddr << "\n";
}
return true;
}
}
std::cerr << "can't find matched I2C or GPIO configuration. \n";
*pBusId = -1;
*pSlaveAddr = -1;
*pGpioIndex = -1;
return false;
}
int main()
{
int busId = -1, slaveAddr = -1, gpioIndex = -1;
bool gpioInverted = false;
IntrusionSensorType type = IntrusionSensorType::gpio;
// setup connection to dbus
boost::asio::io_service io;
auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
auto objServer = sdbusplus::asio::object_server(systemBus);
// setup object server, define interface
systemBus->request_name("xyz.openbmc_project.IntrusionSensor");
std::shared_ptr<sdbusplus::asio::dbus_interface> ifaceChassis =
objServer.add_interface(
"/xyz/openbmc_project/Intrusion/Chassis_Intrusion",
"xyz.openbmc_project.Chassis.Intrusion");
ChassisIntrusionSensor chassisIntrusionSensor(io, ifaceChassis);
if (getIntrusionSensorConfig(systemBus, &type, &busId, &slaveAddr,
&gpioIndex, &gpioInverted))
{
chassisIntrusionSensor.start(type, busId, slaveAddr, gpioIndex,
gpioInverted);
}
// callback to handle configuration change
std::function<void(sdbusplus::message::message&)> eventHandler =
[&](sdbusplus::message::message& message) {
if (message.is_method_error())
{
std::cerr << "callback method error\n";
return;
}
std::cout << "rescan due to configuration change \n";
if (getIntrusionSensorConfig(systemBus, &type, &busId, &slaveAddr,
&gpioIndex, &gpioInverted))
{
chassisIntrusionSensor.start(type, busId, slaveAddr, gpioIndex,
gpioInverted);
}
};
auto match = std::make_unique<sdbusplus::bus::match::match>(
static_cast<sdbusplus::bus::bus&>(*systemBus),
"type='signal',member='PropertiesChanged',path_namespace='" +
std::string(inventoryPath) + "',arg0namespace='" + sensorType + "'",
eventHandler);
io.run();
return 0;
}