blob: 2def3c11bd1d0690d53a68cdf362635c7288e9fa [file] [log] [blame]
Qiang XUe28d1fa2019-02-27 13:50:56 +08001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#include <ChassisIntrusionSensor.hpp>
18#include <Utils.hpp>
19#include <boost/algorithm/string/predicate.hpp>
20#include <boost/asio.hpp>
21#include <chrono>
22#include <ctime>
23#include <iostream>
24#include <sdbusplus/asio/connection.hpp>
25#include <sdbusplus/asio/object_server.hpp>
26#include <sdbusplus/asio/sd_event.hpp>
27#include <sdbusplus/bus.hpp>
28#include <sdbusplus/exception.hpp>
29#include <sdbusplus/server.hpp>
30#include <sdbusplus/timer.hpp>
31
32static constexpr bool DEBUG = false;
33
34static constexpr const char* sensorType =
35 "xyz.openbmc_project.Configuration.ChassisIntrusionSensor";
36
37static bool getIntrusionSensorConfig(
38 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
39 IntrusionSensorType* pType, int* pBusId, int* pSlaveAddr, int* pGpioIndex,
40 bool* pGpioInverted)
41{
42 // find matched configuration according to sensor type
43 ManagedObjectType sensorConfigurations;
44 bool useCache = false;
45
46 if (!getSensorConfiguration(sensorType, dbusConnection,
47 sensorConfigurations, useCache))
48 {
49 std::cerr << "error communicating to entity manager\n";
50 return false;
51 }
52
53 const SensorData* sensorData = nullptr;
54 const std::pair<std::string,
55 boost::container::flat_map<std::string, BasicVariantType>>*
56 baseConfiguration = nullptr;
57
58 // Get bus and addr of matched configuration
59 for (const std::pair<sdbusplus::message::object_path, SensorData>& sensor :
60 sensorConfigurations)
61 {
62 baseConfiguration = nullptr;
63 sensorData = &(sensor.second);
64
65 // match sensor type
66 auto sensorBase = sensorData->find(sensorType);
67 if (sensorBase == sensorData->end())
68 {
69 std::cerr << "error finding base configuration \n";
70 continue;
71 }
72
73 baseConfiguration = &(*sensorBase);
74
75 // judge class, "Gpio" or "I2C"
76 auto findClass = baseConfiguration->second.find("Class");
77 if (findClass != baseConfiguration->second.end() &&
78 sdbusplus::message::variant_ns::get<std::string>(
79 findClass->second) == "Gpio")
80 {
81 *pType = IntrusionSensorType::gpio;
82 }
83 else
84 {
85 *pType = IntrusionSensorType::pch;
86 }
87
88 // case to find GPIO info
89 if (*pType == IntrusionSensorType::gpio)
90 {
91 auto gpioConfig =
92 sensorData->find(sensorType + std::string(".GpioIntrusion"));
93
94 if (gpioConfig == sensorData->end())
95 {
96 std::cerr
97 << "error finding GpioIntrusion info in configuration \n";
98 continue;
99 }
100
101 auto findGpioIndex = gpioConfig->second.find("Index");
102 auto findGpioPolarity = gpioConfig->second.find("Polarity");
103
104 if (findGpioIndex == gpioConfig->second.end() ||
105 findGpioPolarity == gpioConfig->second.end())
106 {
107 std::cerr << "error finding gpio info in configuration \n";
108 continue;
109 }
110
111 try
112 {
113 *pGpioIndex = sdbusplus::message::variant_ns::get<uint64_t>(
114 findGpioIndex->second);
115 *pGpioInverted =
116 (sdbusplus::message::variant_ns::get<std::string>(
117 findGpioPolarity->second) == "Low");
118 }
119 catch (const std::bad_variant_access& e)
120 {
121 std::cerr << "invalid value for gpio info in config. \n";
122 continue;
123 }
124
125 if (DEBUG)
126 {
127 std::cout << "find matched GPIO index " << *pGpioIndex
128 << ", polarity inverted flag is " << *pGpioInverted
129 << "\n";
130 }
131
132 return true;
133 }
134
135 // case to find I2C info
136 else if (*pType == IntrusionSensorType::pch)
137 {
138 auto findBus = baseConfiguration->second.find("Bus");
139 auto findAddress = baseConfiguration->second.find("Address");
140 if (findBus == baseConfiguration->second.end() ||
141 findAddress == baseConfiguration->second.end())
142 {
143 std::cerr << "error finding bus or address in configuration \n";
144 continue;
145 }
146
147 try
148 {
149 *pBusId = sdbusplus::message::variant_ns::get<uint64_t>(
150 findBus->second);
151 *pSlaveAddr = sdbusplus::message::variant_ns::get<uint64_t>(
152 findAddress->second);
153 }
154 catch (const std::bad_variant_access& e)
155 {
156 std::cerr << "invalid value for bus or address in config. \n";
157 continue;
158 }
159
160 if (DEBUG)
161 {
162 std::cout << "find matched bus " << *pBusId
163 << ", matched slave addr " << *pSlaveAddr << "\n";
164 }
165 return true;
166 }
167 }
168
169 std::cerr << "can't find matched I2C or GPIO configuration. \n";
170 *pBusId = -1;
171 *pSlaveAddr = -1;
172 *pGpioIndex = -1;
173 return false;
174}
175
176int main()
177{
178 int busId = -1, slaveAddr = -1, gpioIndex = -1;
179 bool gpioInverted = false;
180 IntrusionSensorType type = IntrusionSensorType::gpio;
181
182 // setup connection to dbus
183 boost::asio::io_service io;
184 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
185 auto objServer = sdbusplus::asio::object_server(systemBus);
186
187 // setup object server, define interface
188 systemBus->request_name("xyz.openbmc_project.IntrusionSensor");
189
190 std::shared_ptr<sdbusplus::asio::dbus_interface> ifaceChassis =
191 objServer.add_interface(
192 "/xyz/openbmc_project/Intrusion/Chassis_Intrusion",
193 "xyz.openbmc_project.Chassis.Intrusion");
194
195 ChassisIntrusionSensor chassisIntrusionSensor(io, ifaceChassis);
196
197 if (getIntrusionSensorConfig(systemBus, &type, &busId, &slaveAddr,
198 &gpioIndex, &gpioInverted))
199 {
200 chassisIntrusionSensor.start(type, busId, slaveAddr, gpioIndex,
201 gpioInverted);
202 }
203
204 // callback to handle configuration change
205 std::function<void(sdbusplus::message::message&)> eventHandler =
206 [&](sdbusplus::message::message& message) {
207 if (message.is_method_error())
208 {
209 std::cerr << "callback method error\n";
210 return;
211 }
212
213 std::cout << "rescan due to configuration change \n";
214 if (getIntrusionSensorConfig(systemBus, &type, &busId, &slaveAddr,
215 &gpioIndex, &gpioInverted))
216 {
217 chassisIntrusionSensor.start(type, busId, slaveAddr, gpioIndex,
218 gpioInverted);
219 }
220 };
221
222 auto match = std::make_unique<sdbusplus::bus::match::match>(
223 static_cast<sdbusplus::bus::bus&>(*systemBus),
224 "type='signal',member='PropertiesChanged',path_namespace='" +
225 std::string(inventoryPath) + "',arg0namespace='" + sensorType + "'",
226 eventHandler);
227
228 io.run();
229
230 return 0;
231}