blob: 6c528d703f978b2855d7f1e3dd5360f0286675c1 [file] [log] [blame]
Chris Cain83929002024-03-06 14:20:09 -06001/*
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 "PresenceGpio.hpp"
18
19#include <boost/asio/io_context.hpp>
20#include <boost/asio/posix/stream_descriptor.hpp>
21#include <gpiod.hpp>
22
23#include <iostream>
24#include <memory>
25#include <stdexcept>
26#include <string>
27#include <system_error>
28
29PresenceGpio::~PresenceGpio()
30{
31 gpioLine.release();
32}
33
34void PresenceGpio::updateAndTracePresence()
35{
36 status = (gpioLine.get_value() != 0);
37 if (status)
38 {
39 logPresent(deviceName);
40 }
41 else
42 {
43 logRemoved(deviceName);
44 }
45}
46
47EventPresenceGpio::EventPresenceGpio(
48 const std::string& iDeviceType, const std::string& iDeviceName,
49 const std::string& gpioName, bool inverted, boost::asio::io_context& io) :
50 PresenceGpio(iDeviceType, iDeviceName), gpioFd(io)
51{
52 gpioLine = gpiod::find_line(gpioName);
53 if (!gpioLine)
54 {
55 std::cerr << "Error requesting gpio: " << gpioName << "\n";
56 return;
57 }
58
59 try
60 {
61 gpioLine.request(
62 {deviceType + "Sensor", gpiod::line_request::EVENT_BOTH_EDGES,
63 inverted ? gpiod::line_request::FLAG_ACTIVE_LOW : 0});
64 updateAndTracePresence();
65
66 int gpioLineFd = gpioLine.event_get_fd();
67 if (gpioLineFd < 0)
68 {
69 std::cerr << "Failed to get " << gpioName << " fd\n";
70 throw std::runtime_error("Failed to get GPIO fd " + gpioName);
71 }
72
73 gpioFd.assign(gpioLineFd);
74 }
75 catch (const std::system_error& e)
76 {
77 std::cerr << "Error reading gpio " << gpioName << ": " << e.what()
78 << "\n";
79 return;
80 }
81
82 monitorPresence();
83}
84
85void EventPresenceGpio::monitorPresence()
86{
87 std::weak_ptr<EventPresenceGpio> weakRef = weak_from_this();
88 gpioFd.async_wait(
89 boost::asio::posix::stream_descriptor::wait_read,
90 [weakRef](const boost::system::error_code& ec) {
91 std::shared_ptr<EventPresenceGpio> self = weakRef.lock();
92 if (!self)
93 {
94 std::cerr << "Failed to get lock for eventPresenceGpio: "
95 << ec.message() << "\n";
96 return;
97 }
98 if (ec)
99 {
100 if (ec != boost::system::errc::bad_file_descriptor)
101 {
102 std::cerr
103 << "Error on event presence device " << self->deviceName
104 << ": " << ec.message() << "\n";
105 }
106 return;
107 }
108 self->read();
109 self->monitorPresence();
110 });
111}
112
113void EventPresenceGpio::read()
114{
115 // Read is invoked when an edge event is detected by monitorPresence
116 gpioLine.event_read();
117 updateAndTracePresence();
118}