blob: 445adbecf3e10b9993daae588545807a073a37ae [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
Andrew Jefferye73bd0a2023-01-25 10:39:57 +103017#include "ChassisIntrusionSensor.hpp"
18
Qiang XUe28d1fa2019-02-27 13:50:56 +080019#include <fcntl.h>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070020#include <linux/i2c.h>
Qiang XUe28d1fa2019-02-27 13:50:56 +080021#include <sys/ioctl.h>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070022#include <sys/syslog.h>
Matt Simmering79a160b2022-11-14 16:50:48 -080023#include <systemd/sd-journal.h>
Qiang XUe28d1fa2019-02-27 13:50:56 +080024#include <unistd.h>
25
Chau Lycebb28c2022-10-21 10:01:52 +000026#include <Utils.hpp>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070027#include <boost/asio/error.hpp>
Ed Tanous1f978632023-02-28 18:16:39 -080028#include <boost/asio/io_context.hpp>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070029#include <boost/asio/posix/stream_descriptor.hpp>
30#include <gpiod.hpp>
George Liue9a1c9c2025-02-20 15:02:35 +080031#include <phosphor-logging/lg2.hpp>
James Feist38fb5982020-05-28 10:09:54 -070032#include <sdbusplus/asio/object_server.hpp>
33
Qiang XUe28d1fa2019-02-27 13:50:56 +080034#include <chrono>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070035#include <cstddef>
36#include <cstdint>
37#include <filesystem>
Chau Lycebb28c2022-10-21 10:01:52 +000038#include <fstream>
Qiang XUe28d1fa2019-02-27 13:50:56 +080039#include <iostream>
Patrick Venture96e97db2019-10-31 13:44:38 -070040#include <memory>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070041#include <stdexcept>
Qiang XUe28d1fa2019-02-27 13:50:56 +080042#include <string>
Ed Tanous8a57ec02020-10-09 12:46:52 -070043#include <utility>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070044#include <vector>
Qiang XUe28d1fa2019-02-27 13:50:56 +080045
James Feist38fb5982020-05-28 10:09:54 -070046extern "C"
47{
Qiang XUe28d1fa2019-02-27 13:50:56 +080048#include <i2c/smbus.h>
49#include <linux/i2c-dev.h>
50}
51
Ed Tanous8a57ec02020-10-09 12:46:52 -070052static constexpr bool debug = false;
Qiang XUe28d1fa2019-02-27 13:50:56 +080053
Chau Lycebb28c2022-10-21 10:01:52 +000054static constexpr unsigned int defaultPollSec = 1;
55static constexpr unsigned int sensorFailedPollSec = 5;
56static unsigned int intrusionSensorPollSec = defaultPollSec;
Chau Lyb318dca2022-10-26 04:12:52 +000057static constexpr const char* hwIntrusionValStr =
58 "xyz.openbmc_project.Chassis.Intrusion.Status.HardwareIntrusion";
59static constexpr const char* normalValStr =
60 "xyz.openbmc_project.Chassis.Intrusion.Status.Normal";
61static constexpr const char* manualRearmStr =
62 "xyz.openbmc_project.Chassis.Intrusion.RearmMode.Manual";
63static constexpr const char* autoRearmStr =
64 "xyz.openbmc_project.Chassis.Intrusion.RearmMode.Automatic";
Qiang XUe28d1fa2019-02-27 13:50:56 +080065
66// SMLink Status Register
67const static constexpr size_t pchStatusRegIntrusion = 0x04;
68
69// Status bit field masks
70const static constexpr size_t pchRegMaskIntrusion = 0x01;
71
Chau Ly95f49932023-04-19 09:44:55 +000072// Value to clear intrusion status hwmon file
73const static constexpr size_t intrusionStatusHwmonClearValue = 0;
74
Chau Lycebb28c2022-10-21 10:01:52 +000075void ChassisIntrusionSensor::updateValue(const size_t& value)
Qiang XUe28d1fa2019-02-27 13:50:56 +080076{
Chau Lycebb28c2022-10-21 10:01:52 +000077 std::string newValue = value != 0 ? hwIntrusionValStr : normalValStr;
78
Chau Lyb318dca2022-10-26 04:12:52 +000079 // Take no action if the hardware status does not change
Josh Lehan833661a2020-03-04 17:35:41 -080080 // Same semantics as Sensor::updateValue(const double&)
81 if (newValue == mValue)
82 {
83 return;
84 }
85
Chau Lycebb28c2022-10-21 10:01:52 +000086 if constexpr (debug)
87 {
George Liue9a1c9c2025-02-20 15:02:35 +080088 lg2::info("Update value from '{VALUE}' to '{NEWVALUE}'", "VALUE",
89 mValue, "NEWVALUE", newValue);
Chau Lycebb28c2022-10-21 10:01:52 +000090 }
91
Chau Lyb318dca2022-10-26 04:12:52 +000092 // Automatic Rearm mode allows direct update
93 // Manual Rearm mode requires a rearm action to clear the intrusion
94 // status
95 if (!mAutoRearm)
96 {
97 if (newValue == normalValStr)
98 {
99 // Chassis is first closed from being open. If it has been
100 // rearmed externally, reset the flag, update mValue and
101 // return, without having to write "Normal" to DBus property
102 // (because the rearm action already did).
103 // Otherwise, return with no more action.
104 if (mRearmFlag)
105 {
106 mRearmFlag = false;
107 mValue = newValue;
108 }
109 return;
110 }
111 }
112
113 // Flush the rearm flag everytime it allows an update to Dbus
114 mRearmFlag = false;
115
Qiang XUe28d1fa2019-02-27 13:50:56 +0800116 // indicate that it is internal set call
Chau Lyb318dca2022-10-26 04:12:52 +0000117 mOverridenState = false;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800118 mInternalSet = true;
119 mIface->set_property("Status", newValue);
Richard Marian Thomaiyaraf6b87c2019-04-03 23:54:28 +0530120 mInternalSet = false;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800121
122 mValue = newValue;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800123}
124
Chau Lycebb28c2022-10-21 10:01:52 +0000125int ChassisIntrusionPchSensor::readSensor()
Qiang XUe28d1fa2019-02-27 13:50:56 +0800126{
Ed Tanous8a57ec02020-10-09 12:46:52 -0700127 int32_t statusMask = pchRegMaskIntrusion;
128 int32_t statusReg = pchStatusRegIntrusion;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800129
Chau Lycebb28c2022-10-21 10:01:52 +0000130 int32_t value = i2c_smbus_read_byte_data(mBusFd, statusReg);
131 if constexpr (debug)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800132 {
George Liue9a1c9c2025-02-20 15:02:35 +0800133 lg2::info("Pch type: raw value is '{VALUE}'", "VALUE", value);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800134 }
135
Chau Lycebb28c2022-10-21 10:01:52 +0000136 if (value < 0)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800137 {
George Liue9a1c9c2025-02-20 15:02:35 +0800138 lg2::error("i2c_smbus_read_byte_data failed");
Qiang XUe28d1fa2019-02-27 13:50:56 +0800139 return -1;
140 }
141
142 // Get status value with mask
Chau Lycebb28c2022-10-21 10:01:52 +0000143 value &= statusMask;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800144
Chau Lycebb28c2022-10-21 10:01:52 +0000145 if constexpr (debug)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800146 {
George Liue9a1c9c2025-02-20 15:02:35 +0800147 lg2::info("Pch type: masked raw value is '{VALUE}'", "VALUE", value);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800148 }
Chau Lycebb28c2022-10-21 10:01:52 +0000149 return value;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800150}
151
Chau Lycebb28c2022-10-21 10:01:52 +0000152void ChassisIntrusionPchSensor::pollSensorStatus()
Qiang XUe28d1fa2019-02-27 13:50:56 +0800153{
Chau Lycebb28c2022-10-21 10:01:52 +0000154 std::weak_ptr<ChassisIntrusionPchSensor> weakRef = weak_from_this();
Chau Ly95f49932023-04-19 09:44:55 +0000155
Qiang XUe28d1fa2019-02-27 13:50:56 +0800156 // setting a new experation implicitly cancels any pending async wait
Ed Tanous83db50c2023-03-01 10:20:24 -0800157 mPollTimer.expires_after(std::chrono::seconds(intrusionSensorPollSec));
Qiang XUe28d1fa2019-02-27 13:50:56 +0800158
Chau Lycebb28c2022-10-21 10:01:52 +0000159 mPollTimer.async_wait([weakRef](const boost::system::error_code& ec) {
Qiang XUe28d1fa2019-02-27 13:50:56 +0800160 // case of being canceled
Chau Lycebb28c2022-10-21 10:01:52 +0000161 if (ec == boost::asio::error::operation_aborted)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800162 {
George Liue9a1c9c2025-02-20 15:02:35 +0800163 lg2::error("Timer of intrusion sensor is cancelled");
Qiang XUe28d1fa2019-02-27 13:50:56 +0800164 return;
165 }
Chau Ly95f49932023-04-19 09:44:55 +0000166
Chau Lycebb28c2022-10-21 10:01:52 +0000167 std::shared_ptr<ChassisIntrusionPchSensor> self = weakRef.lock();
168 if (!self)
169 {
George Liue9a1c9c2025-02-20 15:02:35 +0800170 lg2::error("ChassisIntrusionSensor no self");
Chau Lycebb28c2022-10-21 10:01:52 +0000171 return;
172 }
Chau Ly95f49932023-04-19 09:44:55 +0000173
Chau Lycebb28c2022-10-21 10:01:52 +0000174 int value = self->readSensor();
175 if (value < 0)
176 {
177 intrusionSensorPollSec = sensorFailedPollSec;
178 }
179 else
180 {
181 intrusionSensorPollSec = defaultPollSec;
182 self->updateValue(value);
183 }
Chau Ly95f49932023-04-19 09:44:55 +0000184
Chau Lycebb28c2022-10-21 10:01:52 +0000185 // trigger next polling
186 self->pollSensorStatus();
Qiang XUe28d1fa2019-02-27 13:50:56 +0800187 });
188}
189
Chau Lycebb28c2022-10-21 10:01:52 +0000190int ChassisIntrusionGpioSensor::readSensor()
Qiang XUe28d1fa2019-02-27 13:50:56 +0800191{
ZhikuiRenba8a8bf2020-01-09 15:55:43 -0800192 mGpioLine.event_read();
193 auto value = mGpioLine.get_value();
Chau Lycebb28c2022-10-21 10:01:52 +0000194 if constexpr (debug)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800195 {
George Liue9a1c9c2025-02-20 15:02:35 +0800196 lg2::info("Gpio type: raw value is '{VALUE}'", "VALUE", value);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800197 }
Chau Lycebb28c2022-10-21 10:01:52 +0000198 return value;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800199}
200
Chau Lycebb28c2022-10-21 10:01:52 +0000201void ChassisIntrusionGpioSensor::pollSensorStatus()
Qiang XUe28d1fa2019-02-27 13:50:56 +0800202{
Patrick Williams2aaf7172024-08-16 15:20:40 -0400203 mGpioFd.async_wait(
204 boost::asio::posix::stream_descriptor::wait_read,
205 [this](const boost::system::error_code& ec) {
206 if (ec == boost::system::errc::bad_file_descriptor)
Chau Lycebb28c2022-10-21 10:01:52 +0000207 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400208 return; // we're being destroyed
Chau Lycebb28c2022-10-21 10:01:52 +0000209 }
Patrick Williams2aaf7172024-08-16 15:20:40 -0400210
211 if (ec)
212 {
George Liue9a1c9c2025-02-20 15:02:35 +0800213 lg2::error("Error on GPIO based intrusion sensor wait event");
Patrick Williams2aaf7172024-08-16 15:20:40 -0400214 }
215 else
216 {
217 int value = readSensor();
218 if (value >= 0)
219 {
220 updateValue(value);
221 }
222 // trigger next polling
223 pollSensorStatus();
224 }
225 });
Qiang XUe28d1fa2019-02-27 13:50:56 +0800226}
227
Chau Ly95f49932023-04-19 09:44:55 +0000228int ChassisIntrusionHwmonSensor::readSensor()
229{
230 int value = 0;
231
232 std::fstream stream(mHwmonPath, std::ios::in | std::ios::out);
233 if (!stream.good())
234 {
George Liue9a1c9c2025-02-20 15:02:35 +0800235 lg2::error("Error reading status at '{PATH}'", "PATH", mHwmonPath);
Chau Ly95f49932023-04-19 09:44:55 +0000236 return -1;
237 }
238
239 std::string line;
240 if (!std::getline(stream, line))
241 {
George Liue9a1c9c2025-02-20 15:02:35 +0800242 lg2::error("Error reading status at '{PATH}'", "PATH", mHwmonPath);
Chau Ly95f49932023-04-19 09:44:55 +0000243 return -1;
244 }
245
246 try
247 {
248 value = std::stoi(line);
249 if constexpr (debug)
250 {
George Liue9a1c9c2025-02-20 15:02:35 +0800251 lg2::info("Hwmon type: raw value is '{VALUE}'", "VALUE", value);
Chau Ly95f49932023-04-19 09:44:55 +0000252 }
253 }
254 catch (const std::invalid_argument& e)
255 {
George Liue9a1c9c2025-02-20 15:02:35 +0800256 lg2::error("Error reading status at '{PATH}': '{ERR}'", "PATH",
257 mHwmonPath, "ERR", e);
Chau Ly95f49932023-04-19 09:44:55 +0000258 return -1;
259 }
260
261 // Reset chassis intrusion status after every reading
262 stream << intrusionStatusHwmonClearValue;
263
264 return value;
265}
266
267void ChassisIntrusionHwmonSensor::pollSensorStatus()
268{
269 std::weak_ptr<ChassisIntrusionHwmonSensor> weakRef = weak_from_this();
270
271 // setting a new experation implicitly cancels any pending async wait
272 mPollTimer.expires_after(std::chrono::seconds(intrusionSensorPollSec));
273
274 mPollTimer.async_wait([weakRef](const boost::system::error_code& ec) {
275 // case of being canceled
276 if (ec == boost::asio::error::operation_aborted)
277 {
George Liue9a1c9c2025-02-20 15:02:35 +0800278 lg2::error("Timer of intrusion sensor is cancelled");
Chau Ly95f49932023-04-19 09:44:55 +0000279 return;
280 }
281
282 std::shared_ptr<ChassisIntrusionHwmonSensor> self = weakRef.lock();
283 if (!self)
284 {
George Liue9a1c9c2025-02-20 15:02:35 +0800285 lg2::error("ChassisIntrusionSensor no self");
Chau Ly95f49932023-04-19 09:44:55 +0000286 return;
287 }
288
289 int value = self->readSensor();
290 if (value < 0)
291 {
292 intrusionSensorPollSec = sensorFailedPollSec;
293 }
294 else
295 {
296 intrusionSensorPollSec = defaultPollSec;
297 self->updateValue(value);
298 }
299
300 // trigger next polling
301 self->pollSensorStatus();
302 });
303}
304
Qiang XUe28d1fa2019-02-27 13:50:56 +0800305int ChassisIntrusionSensor::setSensorValue(const std::string& req,
306 std::string& propertyValue)
307{
Richard Marian Thomaiyaraf6b87c2019-04-03 23:54:28 +0530308 if (!mInternalSet)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800309 {
Chau Lyb318dca2022-10-26 04:12:52 +0000310 /*
311 1. Assuming that setting property in Automatic mode causes
312 no effect but only event logs and propertiesChanged signal
313 (because the property will be updated continuously to the
314 current hardware status anyway), only update Status property
315 and raise rearm flag in Manual rearm mode.
316 2. Only accept Normal value from an external call.
317 */
318 if (!mAutoRearm && req == normalValStr)
319 {
320 mRearmFlag = true;
321 propertyValue = req;
322 mOverridenState = true;
323 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800324 }
Richard Marian Thomaiyaraf6b87c2019-04-03 23:54:28 +0530325 else if (!mOverridenState)
326 {
327 propertyValue = req;
328 }
Chau Lyb318dca2022-10-26 04:12:52 +0000329 else
330 {
331 return 1;
332 }
333 // Send intrusion event to Redfish
334 if (mValue == normalValStr && propertyValue != normalValStr)
335 {
336 sd_journal_send("MESSAGE=%s", "Chassis intrusion assert event",
337 "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
338 "OpenBMC.0.1.ChassisIntrusionDetected", NULL);
339 }
340 else if (mValue == hwIntrusionValStr && propertyValue == normalValStr)
341 {
342 sd_journal_send("MESSAGE=%s", "Chassis intrusion de-assert event",
343 "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
344 "OpenBMC.0.1.ChassisIntrusionReset", NULL);
345 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800346 return 1;
347}
348
Chau Lycebb28c2022-10-21 10:01:52 +0000349void ChassisIntrusionSensor::start()
Qiang XUe28d1fa2019-02-27 13:50:56 +0800350{
Chau Lycebb28c2022-10-21 10:01:52 +0000351 mIface->register_property(
352 "Status", mValue,
353 [&](const std::string& req, std::string& propertyValue) {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400354 return setSensorValue(req, propertyValue);
355 });
Chau Lyb318dca2022-10-26 04:12:52 +0000356 std::string rearmStr = mAutoRearm ? autoRearmStr : manualRearmStr;
357 mIface->register_property("Rearm", rearmStr);
Chau Lycebb28c2022-10-21 10:01:52 +0000358 mIface->initialize();
359 pollSensorStatus();
Qiang XUe28d1fa2019-02-27 13:50:56 +0800360}
361
362ChassisIntrusionSensor::ChassisIntrusionSensor(
Chau Lyb318dca2022-10-26 04:12:52 +0000363 bool autoRearm, sdbusplus::asio::object_server& objServer) :
Patrick Williams2aaf7172024-08-16 15:20:40 -0400364 mValue(normalValStr), mAutoRearm(autoRearm), mObjServer(objServer)
Chau Lycebb28c2022-10-21 10:01:52 +0000365{
366 mIface = mObjServer.add_interface("/xyz/openbmc_project/Chassis/Intrusion",
367 "xyz.openbmc_project.Chassis.Intrusion");
368}
369
370ChassisIntrusionPchSensor::ChassisIntrusionPchSensor(
Chau Lyb318dca2022-10-26 04:12:52 +0000371 bool autoRearm, boost::asio::io_context& io,
372 sdbusplus::asio::object_server& objServer, int busId, int slaveAddr) :
Patrick Williams2aaf7172024-08-16 15:20:40 -0400373 ChassisIntrusionSensor(autoRearm, objServer), mPollTimer(io)
Chau Lycebb28c2022-10-21 10:01:52 +0000374{
375 if (busId < 0 || slaveAddr <= 0)
376 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400377 throw std::invalid_argument(
378 "Invalid i2c bus " + std::to_string(busId) + " address " +
379 std::to_string(slaveAddr) + "\n");
Chau Lycebb28c2022-10-21 10:01:52 +0000380 }
Chau Ly95f49932023-04-19 09:44:55 +0000381
Chau Lycebb28c2022-10-21 10:01:52 +0000382 mSlaveAddr = slaveAddr;
Chau Ly95f49932023-04-19 09:44:55 +0000383
Chau Lycebb28c2022-10-21 10:01:52 +0000384 std::string devPath = "/dev/i2c-" + std::to_string(busId);
385 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
386 mBusFd = open(devPath.c_str(), O_RDWR | O_CLOEXEC);
387 if (mBusFd < 0)
388 {
389 throw std::invalid_argument("Unable to open " + devPath + "\n");
390 }
391
392 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
393 if (ioctl(mBusFd, I2C_SLAVE_FORCE, mSlaveAddr) < 0)
394 {
395 throw std::runtime_error("Unable to set device address\n");
396 }
397
398 unsigned long funcs = 0;
399
400 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
401 if (ioctl(mBusFd, I2C_FUNCS, &funcs) < 0)
402 {
403 throw std::runtime_error("Don't support I2C_FUNCS\n");
404 }
405
406 if ((funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA) == 0U)
407 {
408 throw std::runtime_error(
409 "Do not have I2C_FUNC_SMBUS_READ_BYTE_DATA \n");
410 }
411}
412
413ChassisIntrusionGpioSensor::ChassisIntrusionGpioSensor(
Chau Lyb318dca2022-10-26 04:12:52 +0000414 bool autoRearm, boost::asio::io_context& io,
415 sdbusplus::asio::object_server& objServer, bool gpioInverted) :
Patrick Williams2aaf7172024-08-16 15:20:40 -0400416 ChassisIntrusionSensor(autoRearm, objServer), mGpioInverted(gpioInverted),
417 mGpioFd(io)
Chau Lycebb28c2022-10-21 10:01:52 +0000418{
419 mGpioLine = gpiod::find_line(mPinName);
420 if (!mGpioLine)
421 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400422 throw std::invalid_argument(
423 "Error finding gpio pin name: " + mPinName + "\n");
Chau Lycebb28c2022-10-21 10:01:52 +0000424 }
425 mGpioLine.request(
426 {"ChassisIntrusionSensor", gpiod::line_request::EVENT_BOTH_EDGES,
427 mGpioInverted ? gpiod::line_request::FLAG_ACTIVE_LOW : 0});
428
429 auto gpioLineFd = mGpioLine.event_get_fd();
430 if (gpioLineFd < 0)
431 {
432 throw std::invalid_argument("Failed to get " + mPinName + " fd\n");
433 }
Chau Ly95f49932023-04-19 09:44:55 +0000434
Chau Lycebb28c2022-10-21 10:01:52 +0000435 mGpioFd.assign(gpioLineFd);
436}
Qiang XUe28d1fa2019-02-27 13:50:56 +0800437
Chau Ly95f49932023-04-19 09:44:55 +0000438ChassisIntrusionHwmonSensor::ChassisIntrusionHwmonSensor(
Chau Lyb318dca2022-10-26 04:12:52 +0000439 bool autoRearm, boost::asio::io_context& io,
440 sdbusplus::asio::object_server& objServer, std::string hwmonName) :
441 ChassisIntrusionSensor(autoRearm, objServer),
Chau Ly95f49932023-04-19 09:44:55 +0000442 mHwmonName(std::move(hwmonName)), mPollTimer(io)
443{
Ed Tanous2e466962025-01-30 10:59:49 -0800444 std::vector<std::filesystem::path> paths;
Chau Ly95f49932023-04-19 09:44:55 +0000445
Ed Tanous2e466962025-01-30 10:59:49 -0800446 if (!findFiles(std::filesystem::path("/sys/class/hwmon"), mHwmonName,
447 paths))
Chau Ly95f49932023-04-19 09:44:55 +0000448 {
449 throw std::invalid_argument("Failed to find hwmon path in sysfs\n");
450 }
451
452 if (paths.empty())
453 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400454 throw std::invalid_argument(
455 "Hwmon file " + mHwmonName + " can't be found in sysfs\n");
Chau Ly95f49932023-04-19 09:44:55 +0000456 }
457
458 if (paths.size() > 1)
459 {
George Liue9a1c9c2025-02-20 15:02:35 +0800460 lg2::error("Found more than 1 hwmon file to read chassis intrusion"
461 " status. Taking the first one.");
Chau Ly95f49932023-04-19 09:44:55 +0000462 }
463
464 // Expecting only one hwmon file for one given chassis
465 mHwmonPath = paths[0].string();
466
467 if constexpr (debug)
468 {
George Liue9a1c9c2025-02-20 15:02:35 +0800469 lg2::info(
470 "Found '{NUM_PATHS}' paths for intrusion status. The first path is: '{PATH}'",
471 "NUM_PATHS", paths.size(), "PATH", mHwmonPath);
Chau Ly95f49932023-04-19 09:44:55 +0000472 }
473}
474
Qiang XUe28d1fa2019-02-27 13:50:56 +0800475ChassisIntrusionSensor::~ChassisIntrusionSensor()
476{
Chau Lycebb28c2022-10-21 10:01:52 +0000477 mObjServer.remove_interface(mIface);
478}
479
480ChassisIntrusionPchSensor::~ChassisIntrusionPchSensor()
481{
482 mPollTimer.cancel();
483 if (close(mBusFd) < 0)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800484 {
George Liue9a1c9c2025-02-20 15:02:35 +0800485 lg2::error("Failed to close fd '{FD}'", "FD", mBusFd);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800486 }
Chau Lycebb28c2022-10-21 10:01:52 +0000487}
488
489ChassisIntrusionGpioSensor::~ChassisIntrusionGpioSensor()
490{
491 mGpioFd.close();
492 if (mGpioLine)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800493 {
Chau Lycebb28c2022-10-21 10:01:52 +0000494 mGpioLine.release();
Qiang XUe28d1fa2019-02-27 13:50:56 +0800495 }
496}
Chau Ly95f49932023-04-19 09:44:55 +0000497
498ChassisIntrusionHwmonSensor::~ChassisIntrusionHwmonSensor()
499{
500 mPollTimer.cancel();
501}