Add chassis intrusion sensor daemon
Chassis intrusion signal is read from PCH via I2C or from GPIO.
Create a new daemon to poll its status and expose to dbus.
Related patches to run test:
- meta-phosphor: dbus-sensors: Enable new service of intrusion sensor
https://gerrit.openbmc-project.xyz/#/c/openbmc/meta-phosphor/+/17063/
- redfish: chassis: add property of physical security
https://gerrit.openbmc-project.xyz/#/c/openbmc/bmcweb/+/17691/
Tested-by: Check intrusion status value by redfish,
verified PCH solution on WFP and GPIO solution on STP.
Change-Id: Id5e67abbd80bbf2ef502db49fa183d92d0d31bda
Signed-off-by: Qiang XU <qiang.xu@linux.intel.com>
diff --git a/src/IntrusionSensorMain.cpp b/src/IntrusionSensorMain.cpp
new file mode 100644
index 0000000..2def3c1
--- /dev/null
+++ b/src/IntrusionSensorMain.cpp
@@ -0,0 +1,231 @@
+/*
+// 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;
+}