Skip to content

Instantly share code, notes, and snippets.

@lierdakil
Created December 10, 2018 19:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lierdakil/09d94a1c68f46da73398f4efd3922966 to your computer and use it in GitHub Desktop.
Save lierdakil/09d94a1c68f46da73398f4efd3922966 to your computer and use it in GitHub Desktop.
Linux polling all key event devices for key presses (minimalist example)
// Note: uses C++17 fs features; build with
// g++ -std=c++17 event-reader.cpp -lstdc++fs
//
// Licensed under the following terms:
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
#include <linux/input.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#include <signal.h>
#include <iostream>
#include <filesystem>
#include <string_view>
#include <vector>
bool supports_key_events(const int &fd) {
unsigned long evbit = 0;
ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
return (evbit & (1 << EV_KEY));
}
int main() {
char eventPathStart[] = "/dev/input/event";
std::vector<pollfd> poll_fds;
for (auto &i : std::filesystem::directory_iterator("/dev/input")) {
if(i.is_character_file()) {
std::string view(i.path());
if (view.compare(0, sizeof(eventPathStart)-1, eventPathStart) == 0) {
int evfile = open(view.c_str(), O_RDONLY | O_NONBLOCK);
if(supports_key_events(evfile)) {
std::cout << "Adding " << i.path() << std::endl;
poll_fds.push_back({evfile, POLLIN, 0});
} else {
close(evfile);
}
}
}
}
input_event ev;
while(true) {
poll(poll_fds.data(), poll_fds.size(), -1);
for (auto &pfd : poll_fds) {
if (pfd.revents & POLLIN) {
if(read(pfd.fd, &ev, sizeof(ev)) == sizeof(ev)) {
if(ev.type == EV_KEY && ev.value == 1 && ev.code < 0x100) {
std::cout << "Key pressed! Code: " << ev.code << std::endl;
}
}
}
}
}
// cleanup, but it's pointless since the code is unreachable
// besides, fds will be closed anyway when the program terminates
for (auto &pfd : poll_fds) {
close(pfd.fd);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment