DUDS
Distributed Update of Data from Something
EvdevInput.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the DUDS project. It is subject to the BSD-style
3  * license terms in the LICENSE file found in the top-level directory of this
4  * distribution and at https://github.com/jjackowski/duds/blob/master/LICENSE.
5  * No part of DUDS, including this file, may be copied, modified, propagated,
6  * or distributed except according to the terms contained in the LICENSE file.
7  *
8  * Copyright (C) 2020 Jeff Jackowski
9  */
10 // for open() and related items; may be more than needed
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
16 #include <boost/exception/errinfo_file_name.hpp>
17 #include <boost/exception/errinfo_errno.hpp>
18 #include <duds/general/Errors.hpp>
19 
20 namespace duds { namespace os { namespace linux {
21 
22 EvdevInput::EvdevInput() : fd(-1) { }
23 
24 EvdevInput::EvdevInput(const std::string &path) {
25  open(path);
26 }
27 
28 void EvdevInput::open(const std::string &path) {
29  if (dev) {
31  }
32  fd = ::open(path.c_str(), O_RDONLY);
33  if (fd < 0) {
35  boost::errinfo_file_name(path)
36  );
37  }
38  int result = libevdev_new_from_fd(fd, &dev);
39  if (result < 0) {
40  close(fd);
42  boost::errinfo_errno(-result) <<
43  // the file may have nothing to do with the error, but it will
44  // add context
45  boost::errinfo_file_name(path)
46  );
47  }
48 }
49 
52 dev(e.dev),
53 fd(e.fd) {
54  e.dev = nullptr;
55  e.fd = -1;
56 }
57 
59  if (dev) {
60  libevdev_free(dev);
61  }
62  if (fd > 0) {
63  close(fd);
64  }
65 }
66 
68  defReceiver = std::move(old.defReceiver);
69  dev = old.dev;
70  old.dev = nullptr;
71  fd = old.fd;
72  old.fd = -1;
73  return *this;
74 }
75 
76 std::string EvdevInput::name() const {
77  return libevdev_get_name(dev);
78 }
79 
81  return libevdev_grab(dev, LIBEVDEV_GRAB) == 0;
82 }
83 
84 bool EvdevInput::hasEventType(unsigned int et) const {
85  return libevdev_has_event_type(dev, et) == 1;
86 }
87 
89  return libevdev_has_event_code(dev, etc.type, etc.code) == 1;
90 }
91 
93  return libevdev_get_num_slots(dev);
94 }
95 
97  int val;
98  if (!libevdev_fetch_event_value(dev, etc.type, etc.code, &val)) {
101  );
102  }
103  return val;
104 }
105 
107  return libevdev_has_event_pending(dev) > 0;
108 }
109 
111  input_event ie;
112  int result;
113  do {
114  result = libevdev_next_event(
115  dev,
116  LIBEVDEV_READ_FLAG_NORMAL | LIBEVDEV_READ_FLAG_BLOCKING,
117  &ie
118  );
119  if (result == LIBEVDEV_READ_STATUS_SUCCESS) {
120  EventTypeCode etc(ie.type, ie.code);
121  // don't let input handlers prevent handling all the input
122  try {
123  defReceiver(etc, ie.value);
124  } catch (...) { }
125  }
126  } while ((result >= 0) && (libevdev_has_event_pending(dev) > 0));
127 }
128 
131 }
132 
134  p.add(shared_from_this(), fd);
135 }
136 
137 const input_absinfo *EvdevInput::absInfo(unsigned int absEc) const {
138  const input_absinfo *ia = libevdev_get_abs_info(dev, absEc);
139  if (!ia) {
141  EvdevEventType(EV_ABS) << EvdevEventCode(absEc)
142  );
143  }
144  return ia;
145 }
146 
147 boost::signals2::connection EvdevInput::connect(const InputHandlersSptr &ihs) {
148  return defReceiver.connect(InputSignal::slot_type(
150  ihs.get(),
151  boost::placeholders::_1,
152  boost::placeholders::_2
153  ).track_foreign(ihs));
154 }
155 
157  InputHandlersSptr ihs = std::make_shared<InputHandlers>();
158  connect(ihs);
159  return ihs;
160 }
161 
162 } } }
bool grab()
Attempts to gain exclusive access to the input device.
Definition: EvdevInput.cpp:80
EvdevInput & operator=(EvdevInput &&old) noexcept
Move assignment.
Definition: EvdevInput.cpp:67
The specified event type or code is not supported by the input device.
Definition: EvdevErrors.hpp:45
InputSignal defReceiver
Handles all input events.
Definition: EvdevInput.hpp:37
void respond(Poller *, int)
Same as calling respondToNextEvent(); used with Poller.
Definition: EvdevInput.cpp:129
bool hasEventType(unsigned int et) const
Returns true if the input device can produce events of the given type.
Definition: EvdevInput.cpp:84
boost::error_info< struct Info_EvdevEventType, unsigned int > EvdevEventType
The event type integer involved in an EvdevError.
Definition: EvdevErrors.hpp:68
libevdev * dev
The object provided by libevdev that is needed to work with the input device.
Definition: EvdevInput.hpp:42
int fd
The file descriptor to the input device file.
Definition: EvdevInput.hpp:46
STL namespace.
move_impl move(unsigned int c, unsigned int r)
Display stream manipulator that moves the display cursor to the given location.
InputHandlersSptr makeConnectedHandlers()
Makes a new InputHandlers object, connects it to the input event signal for this device, and retruns the object.
Definition: EvdevInput.cpp:156
The input device file could not be opened.
Definition: EvdevErrors.hpp:29
std::uint16_t code
An event code, such as KEY_A, ABS_X, or REL_Y.
A simple C++ interface to using Linux&#39;s epoll functions.
Definition: Poller.hpp:117
std::shared_ptr< InputHandlers > InputHandlersSptr
Shared pointer to a InputHandlers class.
void handleEvent(EventTypeCode etc, std::int32_t value)
Dispatches the provided input event to the appropriate InputSignal.
bool hasEvent(EventTypeCode etc) const
Returns true if the input device can produce events of the given type and code.
Definition: EvdevInput.cpp:88
Combines an event type and an event code, as defined by libevdev, for the purpose of using a combinat...
std::uint16_t type
An event type, such as EV_KEY, EV_ABS, or EV_REL.
bool eventsAvailable() const
Returns true if there are events awaiting processing on this device.
Definition: EvdevInput.cpp:106
boost::signals2::connection connect(const InputHandlersSptr &ihs)
Connect the given InputHandlers to the end of the input event signal.
Definition: EvdevInput.cpp:147
int numMultitouchSlots() const
Returns the number of slots supported by a multitouch input device.
Definition: EvdevInput.cpp:92
void open(const std::string &path)
Opens the given input device file.
Definition: EvdevInput.cpp:28
void usePoller(Poller &p)
Registers this object with the given Poller so that Poller::wait() will invoke respondToNextEvent().
Definition: EvdevInput.cpp:133
int value(EventTypeCode etc) const
Returns the current input value for the given event.
Definition: EvdevInput.cpp:96
boost::error_info< struct Info_EvdevEventCode, unsigned int > EvdevEventCode
The event code integer involved in an EvdevError.
Definition: EvdevErrors.hpp:74
std::string name() const
Reports the name of the device using libevdev_get_name().
Definition: EvdevInput.cpp:76
EvdevInput()
Constructs an EvdevInput object without opening a device file.
Definition: EvdevInput.cpp:22
void respondToNextEvent()
Responds to the next input event on the device.
Definition: EvdevInput.cpp:110
const input_absinfo * absInfo(unsigned int absEc) const
Provides information about a specified absolute axis.
Definition: EvdevInput.cpp:137
void add(const PollResponderSptr &prs, int fd, int events=EPOLLIN)
Adds a PollResponder to check for events on a file descriptor.
Definition: Poller.cpp:54
An attempt was made to open a device file when one was already open.
Definition: EvdevErrors.hpp:34
General errors.
#define DUDS_THROW_EXCEPTION(x)
Works like BOOST_THROW_EXCEPTION, but includes a stack trace if DUDS_ERRORS_VERBOSE is defined...
Definition: Errors.hpp:48
Handles getting input from a specific input device using libevdev.
Definition: EvdevInput.hpp:29
Initializing use of the input device failed.
Definition: EvdevErrors.hpp:40