blob: 2c1e391f07536386c39d84be06184345ff9e2d39 [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>
James Feist38fb5982020-05-28 10:09:54 -070031#include <sdbusplus/asio/object_server.hpp>
32
Qiang XUe28d1fa2019-02-27 13:50:56 +080033#include <chrono>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070034#include <cstddef>
35#include <cstdint>
36#include <filesystem>
Chau Lycebb28c2022-10-21 10:01:52 +000037#include <fstream>
Qiang XUe28d1fa2019-02-27 13:50:56 +080038#include <iostream>
Patrick Venture96e97db2019-10-31 13:44:38 -070039#include <memory>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070040#include <stdexcept>
Qiang XUe28d1fa2019-02-27 13:50:56 +080041#include <string>
Ed Tanous8a57ec02020-10-09 12:46:52 -070042#include <utility>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070043#include <vector>
Qiang XUe28d1fa2019-02-27 13:50:56 +080044
James Feist38fb5982020-05-28 10:09:54 -070045extern "C"
46{
Qiang XUe28d1fa2019-02-27 13:50:56 +080047#include <i2c/smbus.h>
48#include <linux/i2c-dev.h>
49}
50
Ed Tanous8a57ec02020-10-09 12:46:52 -070051static constexpr bool debug = false;
Qiang XUe28d1fa2019-02-27 13:50:56 +080052
Chau Lycebb28c2022-10-21 10:01:52 +000053static constexpr unsigned int defaultPollSec = 1;
54static constexpr unsigned int sensorFailedPollSec = 5;
55static unsigned int intrusionSensorPollSec = defaultPollSec;
Chau Lyb318dca2022-10-26 04:12:52 +000056static constexpr const char* hwIntrusionValStr =
57 "xyz.openbmc_project.Chassis.Intrusion.Status.HardwareIntrusion";
58static constexpr const char* normalValStr =
59 "xyz.openbmc_project.Chassis.Intrusion.Status.Normal";
60static constexpr const char* manualRearmStr =
61 "xyz.openbmc_project.Chassis.Intrusion.RearmMode.Manual";
62static constexpr const char* autoRearmStr =
63 "xyz.openbmc_project.Chassis.Intrusion.RearmMode.Automatic";
Qiang XUe28d1fa2019-02-27 13:50:56 +080064
65// SMLink Status Register
66const static constexpr size_t pchStatusRegIntrusion = 0x04;
67
68// Status bit field masks
69const static constexpr size_t pchRegMaskIntrusion = 0x01;
70
Chau Ly95f49932023-04-19 09:44:55 +000071// Value to clear intrusion status hwmon file
72const static constexpr size_t intrusionStatusHwmonClearValue = 0;
73
Chau Lycebb28c2022-10-21 10:01:52 +000074void ChassisIntrusionSensor::updateValue(const size_t& value)
Qiang XUe28d1fa2019-02-27 13:50:56 +080075{
Chau Lycebb28c2022-10-21 10:01:52 +000076 std::string newValue = value != 0 ? hwIntrusionValStr : normalValStr;
77
Chau Lyb318dca2022-10-26 04:12:52 +000078 // Take no action if the hardware status does not change
Josh Lehan833661a2020-03-04 17:35:41 -080079 // Same semantics as Sensor::updateValue(const double&)
80 if (newValue == mValue)
81 {
82 return;
83 }
84
Chau Lycebb28c2022-10-21 10:01:52 +000085 if constexpr (debug)
86 {
87 std::cout << "Update value from " << mValue << " to " << newValue
88 << "\n";
89 }
90
Chau Lyb318dca2022-10-26 04:12:52 +000091 // Automatic Rearm mode allows direct update
92 // Manual Rearm mode requires a rearm action to clear the intrusion
93 // status
94 if (!mAutoRearm)
95 {
96 if (newValue == normalValStr)
97 {
98 // Chassis is first closed from being open. If it has been
99 // rearmed externally, reset the flag, update mValue and
100 // return, without having to write "Normal" to DBus property
101 // (because the rearm action already did).
102 // Otherwise, return with no more action.
103 if (mRearmFlag)
104 {
105 mRearmFlag = false;
106 mValue = newValue;
107 }
108 return;
109 }
110 }
111
112 // Flush the rearm flag everytime it allows an update to Dbus
113 mRearmFlag = false;
114
Qiang XUe28d1fa2019-02-27 13:50:56 +0800115 // indicate that it is internal set call
Chau Lyb318dca2022-10-26 04:12:52 +0000116 mOverridenState = false;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800117 mInternalSet = true;
118 mIface->set_property("Status", newValue);
Richard Marian Thomaiyaraf6b87c2019-04-03 23:54:28 +0530119 mInternalSet = false;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800120
121 mValue = newValue;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800122}
123
Chau Lycebb28c2022-10-21 10:01:52 +0000124int ChassisIntrusionPchSensor::readSensor()
Qiang XUe28d1fa2019-02-27 13:50:56 +0800125{
Ed Tanous8a57ec02020-10-09 12:46:52 -0700126 int32_t statusMask = pchRegMaskIntrusion;
127 int32_t statusReg = pchStatusRegIntrusion;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800128
Chau Lycebb28c2022-10-21 10:01:52 +0000129 int32_t value = i2c_smbus_read_byte_data(mBusFd, statusReg);
130 if constexpr (debug)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800131 {
Chau Lycebb28c2022-10-21 10:01:52 +0000132 std::cout << "Pch type: raw value is " << value << "\n";
Qiang XUe28d1fa2019-02-27 13:50:56 +0800133 }
134
Chau Lycebb28c2022-10-21 10:01:52 +0000135 if (value < 0)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800136 {
137 std::cerr << "i2c_smbus_read_byte_data failed \n";
138 return -1;
139 }
140
141 // Get status value with mask
Chau Lycebb28c2022-10-21 10:01:52 +0000142 value &= statusMask;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800143
Chau Lycebb28c2022-10-21 10:01:52 +0000144 if constexpr (debug)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800145 {
Chau Lycebb28c2022-10-21 10:01:52 +0000146 std::cout << "Pch type: masked raw value is " << value << "\n";
Qiang XUe28d1fa2019-02-27 13:50:56 +0800147 }
Chau Lycebb28c2022-10-21 10:01:52 +0000148 return value;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800149}
150
Chau Lycebb28c2022-10-21 10:01:52 +0000151void ChassisIntrusionPchSensor::pollSensorStatus()
Qiang XUe28d1fa2019-02-27 13:50:56 +0800152{
Chau Lycebb28c2022-10-21 10:01:52 +0000153 std::weak_ptr<ChassisIntrusionPchSensor> weakRef = weak_from_this();
Chau Ly95f49932023-04-19 09:44:55 +0000154
Qiang XUe28d1fa2019-02-27 13:50:56 +0800155 // setting a new experation implicitly cancels any pending async wait
Ed Tanous83db50c2023-03-01 10:20:24 -0800156 mPollTimer.expires_after(std::chrono::seconds(intrusionSensorPollSec));
Qiang XUe28d1fa2019-02-27 13:50:56 +0800157
Chau Lycebb28c2022-10-21 10:01:52 +0000158 mPollTimer.async_wait([weakRef](const boost::system::error_code& ec) {
Qiang XUe28d1fa2019-02-27 13:50:56 +0800159 // case of being canceled
Chau Lycebb28c2022-10-21 10:01:52 +0000160 if (ec == boost::asio::error::operation_aborted)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800161 {
Chau Lycebb28c2022-10-21 10:01:52 +0000162 std::cerr << "Timer of intrusion sensor is cancelled\n";
Qiang XUe28d1fa2019-02-27 13:50:56 +0800163 return;
164 }
Chau Ly95f49932023-04-19 09:44:55 +0000165
Chau Lycebb28c2022-10-21 10:01:52 +0000166 std::shared_ptr<ChassisIntrusionPchSensor> self = weakRef.lock();
167 if (!self)
168 {
169 std::cerr << "ChassisIntrusionSensor no self\n";
170 return;
171 }
Chau Ly95f49932023-04-19 09:44:55 +0000172
Chau Lycebb28c2022-10-21 10:01:52 +0000173 int value = self->readSensor();
174 if (value < 0)
175 {
176 intrusionSensorPollSec = sensorFailedPollSec;
177 }
178 else
179 {
180 intrusionSensorPollSec = defaultPollSec;
181 self->updateValue(value);
182 }
Chau Ly95f49932023-04-19 09:44:55 +0000183
Chau Lycebb28c2022-10-21 10:01:52 +0000184 // trigger next polling
185 self->pollSensorStatus();
Qiang XUe28d1fa2019-02-27 13:50:56 +0800186 });
187}
188
Chau Lycebb28c2022-10-21 10:01:52 +0000189int ChassisIntrusionGpioSensor::readSensor()
Qiang XUe28d1fa2019-02-27 13:50:56 +0800190{
ZhikuiRenba8a8bf2020-01-09 15:55:43 -0800191 mGpioLine.event_read();
192 auto value = mGpioLine.get_value();
Chau Lycebb28c2022-10-21 10:01:52 +0000193 if constexpr (debug)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800194 {
Chau Lycebb28c2022-10-21 10:01:52 +0000195 std::cout << "Gpio type: raw value is " << value << "\n";
Qiang XUe28d1fa2019-02-27 13:50:56 +0800196 }
Chau Lycebb28c2022-10-21 10:01:52 +0000197 return value;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800198}
199
Chau Lycebb28c2022-10-21 10:01:52 +0000200void ChassisIntrusionGpioSensor::pollSensorStatus()
Qiang XUe28d1fa2019-02-27 13:50:56 +0800201{
Patrick Williams2aaf7172024-08-16 15:20:40 -0400202 mGpioFd.async_wait(
203 boost::asio::posix::stream_descriptor::wait_read,
204 [this](const boost::system::error_code& ec) {
205 if (ec == boost::system::errc::bad_file_descriptor)
Chau Lycebb28c2022-10-21 10:01:52 +0000206 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400207 return; // we're being destroyed
Chau Lycebb28c2022-10-21 10:01:52 +0000208 }
Patrick Williams2aaf7172024-08-16 15:20:40 -0400209
210 if (ec)
211 {
212 std::cerr
213 << "Error on GPIO based intrusion sensor wait event\n";
214 }
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 {
235 std::cerr << "Error reading status at " << mHwmonPath << "\n";
236 return -1;
237 }
238
239 std::string line;
240 if (!std::getline(stream, line))
241 {
242 std::cerr << "Error reading status at " << mHwmonPath << "\n";
243 return -1;
244 }
245
246 try
247 {
248 value = std::stoi(line);
249 if constexpr (debug)
250 {
251 std::cout << "Hwmon type: raw value is " << value << "\n";
252 }
253 }
254 catch (const std::invalid_argument& e)
255 {
256 std::cerr << "Error reading status at " << mHwmonPath << " : "
257 << e.what() << "\n";
258 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 {
278 std::cerr << "Timer of intrusion sensor is cancelled\n";
279 return;
280 }
281
282 std::shared_ptr<ChassisIntrusionHwmonSensor> self = weakRef.lock();
283 if (!self)
284 {
285 std::cerr << "ChassisIntrusionSensor no self\n";
286 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{
444 std::vector<fs::path> paths;
445
446 if (!findFiles(fs::path("/sys/class/hwmon"), mHwmonName, paths))
447 {
448 throw std::invalid_argument("Failed to find hwmon path in sysfs\n");
449 }
450
451 if (paths.empty())
452 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400453 throw std::invalid_argument(
454 "Hwmon file " + mHwmonName + " can't be found in sysfs\n");
Chau Ly95f49932023-04-19 09:44:55 +0000455 }
456
457 if (paths.size() > 1)
458 {
459 std::cerr << "Found more than 1 hwmon file to read chassis intrusion"
460 << " status. Taking the first one. \n";
461 }
462
463 // Expecting only one hwmon file for one given chassis
464 mHwmonPath = paths[0].string();
465
466 if constexpr (debug)
467 {
468 std::cout << "Found " << paths.size()
469 << " paths for intrusion status \n"
470 << " The first path is: " << mHwmonPath << "\n";
471 }
472}
473
Qiang XUe28d1fa2019-02-27 13:50:56 +0800474ChassisIntrusionSensor::~ChassisIntrusionSensor()
475{
Chau Lycebb28c2022-10-21 10:01:52 +0000476 mObjServer.remove_interface(mIface);
477}
478
479ChassisIntrusionPchSensor::~ChassisIntrusionPchSensor()
480{
481 mPollTimer.cancel();
482 if (close(mBusFd) < 0)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800483 {
Chau Lycebb28c2022-10-21 10:01:52 +0000484 std::cerr << "Failed to close fd " << std::to_string(mBusFd);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800485 }
Chau Lycebb28c2022-10-21 10:01:52 +0000486}
487
488ChassisIntrusionGpioSensor::~ChassisIntrusionGpioSensor()
489{
490 mGpioFd.close();
491 if (mGpioLine)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800492 {
Chau Lycebb28c2022-10-21 10:01:52 +0000493 mGpioLine.release();
Qiang XUe28d1fa2019-02-27 13:50:56 +0800494 }
495}
Chau Ly95f49932023-04-19 09:44:55 +0000496
497ChassisIntrusionHwmonSensor::~ChassisIntrusionHwmonSensor()
498{
499 mPollTimer.cancel();
500}