diff options
Diffstat (limited to 'minui/events.cpp')
-rw-r--r-- | minui/events.cpp | 207 |
1 files changed, 105 insertions, 102 deletions
diff --git a/minui/events.cpp b/minui/events.cpp index c95861036..7d0250e97 100644 --- a/minui/events.cpp +++ b/minui/events.cpp @@ -23,144 +23,148 @@ #include <string.h> #include <sys/epoll.h> #include <sys/ioctl.h> +#include <sys/types.h> #include <unistd.h> #include <functional> +#include <memory> + +#include <android-base/unique_fd.h> #include "minui/minui.h" -#define MAX_DEVICES 16 -#define MAX_MISC_FDS 16 +constexpr size_t MAX_DEVICES = 16; +constexpr size_t MAX_MISC_FDS = 16; -#define BITS_PER_LONG (sizeof(unsigned long) * 8) -#define BITS_TO_LONGS(x) (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG) +constexpr size_t BITS_PER_LONG = sizeof(unsigned long) * 8; +constexpr size_t BITS_TO_LONGS(size_t bits) { + return ((bits + BITS_PER_LONG - 1) / BITS_PER_LONG); +} -struct fd_info { - int fd; +struct FdInfo { + android::base::unique_fd fd; ev_callback cb; }; -static int g_epoll_fd; -static epoll_event polledevents[MAX_DEVICES + MAX_MISC_FDS]; -static int npolledevents; +static android::base::unique_fd g_epoll_fd; +static epoll_event g_polled_events[MAX_DEVICES + MAX_MISC_FDS]; +static int g_polled_events_count; -static fd_info ev_fdinfo[MAX_DEVICES + MAX_MISC_FDS]; +static FdInfo ev_fdinfo[MAX_DEVICES + MAX_MISC_FDS]; -static unsigned ev_count = 0; -static unsigned ev_dev_count = 0; -static unsigned ev_misc_count = 0; +static size_t g_ev_count = 0; +static size_t g_ev_dev_count = 0; +static size_t g_ev_misc_count = 0; static bool test_bit(size_t bit, unsigned long* array) { // NOLINT - return (array[bit/BITS_PER_LONG] & (1UL << (bit % BITS_PER_LONG))) != 0; + return (array[bit / BITS_PER_LONG] & (1UL << (bit % BITS_PER_LONG))) != 0; } int ev_init(ev_callback input_cb, bool allow_touch_inputs) { - g_epoll_fd = epoll_create1(EPOLL_CLOEXEC); - if (g_epoll_fd == -1) { + g_epoll_fd.reset(); + + android::base::unique_fd epoll_fd(epoll_create1(EPOLL_CLOEXEC)); + if (epoll_fd == -1) { return -1; } - bool epollctlfail = false; - DIR* dir = opendir("/dev/input"); - if (dir != nullptr) { - dirent* de; - while ((de = readdir(dir))) { - if (strncmp(de->d_name, "event", 5)) continue; - int fd = openat(dirfd(dir), de->d_name, O_RDONLY | O_CLOEXEC); - if (fd == -1) continue; - - // Use unsigned long to match ioctl's parameter type. - unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT - - // Read the evbits of the input device. - if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) { - close(fd); - continue; - } + std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/dev/input"), closedir); + if (!dir) { + return -1; + } - // We assume that only EV_KEY, EV_REL, and EV_SW event types are ever needed. EV_ABS is also - // allowed if allow_touch_inputs is set. - if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits) && !test_bit(EV_SW, ev_bits)) { - if (!allow_touch_inputs || !test_bit(EV_ABS, ev_bits)) { - close(fd); - continue; - } - } + bool epoll_ctl_failed = false; + dirent* de; + while ((de = readdir(dir.get())) != nullptr) { + if (strncmp(de->d_name, "event", 5)) continue; + android::base::unique_fd fd(openat(dirfd(dir.get()), de->d_name, O_RDONLY | O_CLOEXEC)); + if (fd == -1) continue; + + // Use unsigned long to match ioctl's parameter type. + unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT - epoll_event ev; - ev.events = EPOLLIN | EPOLLWAKEUP; - ev.data.ptr = &ev_fdinfo[ev_count]; - if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) { - close(fd); - epollctlfail = true; + // Read the evbits of the input device. + if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) { + continue; + } + + // We assume that only EV_KEY, EV_REL, and EV_SW event types are ever needed. EV_ABS is also + // allowed if allow_touch_inputs is set. + if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits) && !test_bit(EV_SW, ev_bits)) { + if (!allow_touch_inputs || !test_bit(EV_ABS, ev_bits)) { continue; } + } - ev_fdinfo[ev_count].fd = fd; - ev_fdinfo[ev_count].cb = input_cb; - ev_count++; - ev_dev_count++; - if (ev_dev_count == MAX_DEVICES) break; + epoll_event ev; + ev.events = EPOLLIN | EPOLLWAKEUP; + ev.data.ptr = &ev_fdinfo[g_ev_count]; + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) { + epoll_ctl_failed = true; + continue; } - closedir(dir); + ev_fdinfo[g_ev_count].fd.reset(fd.release()); + ev_fdinfo[g_ev_count].cb = input_cb; + g_ev_count++; + g_ev_dev_count++; + if (g_ev_dev_count == MAX_DEVICES) break; } - if (epollctlfail && !ev_count) { - close(g_epoll_fd); - g_epoll_fd = -1; + if (epoll_ctl_failed && !g_ev_count) { return -1; } + g_epoll_fd.reset(epoll_fd.release()); return 0; } int ev_get_epollfd(void) { - return g_epoll_fd; + return g_epoll_fd.get(); } -int ev_add_fd(int fd, ev_callback cb) { - if (ev_misc_count == MAX_MISC_FDS || cb == NULL) { +int ev_add_fd(android::base::unique_fd&& fd, ev_callback cb) { + if (g_ev_misc_count == MAX_MISC_FDS || cb == nullptr) { return -1; } epoll_event ev; ev.events = EPOLLIN | EPOLLWAKEUP; - ev.data.ptr = static_cast<void*>(&ev_fdinfo[ev_count]); + ev.data.ptr = static_cast<void*>(&ev_fdinfo[g_ev_count]); int ret = epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, fd, &ev); if (!ret) { - ev_fdinfo[ev_count].fd = fd; - ev_fdinfo[ev_count].cb = std::move(cb); - ev_count++; - ev_misc_count++; + ev_fdinfo[g_ev_count].fd.reset(fd.release()); + ev_fdinfo[g_ev_count].cb = std::move(cb); + g_ev_count++; + g_ev_misc_count++; } return ret; } void ev_exit(void) { - while (ev_count > 0) { - close(ev_fdinfo[--ev_count].fd); - } - ev_misc_count = 0; - ev_dev_count = 0; - close(g_epoll_fd); + while (g_ev_count > 0) { + ev_fdinfo[--g_ev_count].fd.reset(); + } + g_ev_misc_count = 0; + g_ev_dev_count = 0; + g_epoll_fd.reset(); } int ev_wait(int timeout) { - npolledevents = epoll_wait(g_epoll_fd, polledevents, ev_count, timeout); - if (npolledevents <= 0) { - return -1; - } - return 0; + g_polled_events_count = epoll_wait(g_epoll_fd, g_polled_events, g_ev_count, timeout); + if (g_polled_events_count <= 0) { + return -1; + } + return 0; } void ev_dispatch(void) { - for (int n = 0; n < npolledevents; n++) { - fd_info* fdi = static_cast<fd_info*>(polledevents[n].data.ptr); + for (int n = 0; n < g_polled_events_count; n++) { + FdInfo* fdi = static_cast<FdInfo*>(g_polled_events[n].data.ptr); const ev_callback& cb = fdi->cb; if (cb) { - cb(fdi->fd, polledevents[n].events); + cb(fdi->fd, g_polled_events[n].events); } } } @@ -180,7 +184,7 @@ int ev_sync_key_state(const ev_set_key_callback& set_key_cb) { unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; // NOLINT - for (size_t i = 0; i < ev_dev_count; ++i) { + for (size_t i = 0; i < g_ev_dev_count; ++i) { memset(ev_bits, 0, sizeof(ev_bits)); memset(key_bits, 0, sizeof(key_bits)); @@ -205,37 +209,36 @@ int ev_sync_key_state(const ev_set_key_callback& set_key_cb) { } void ev_iterate_available_keys(const std::function<void(int)>& f) { - // Use unsigned long to match ioctl's parameter type. - unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT - unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; // NOLINT + // Use unsigned long to match ioctl's parameter type. + unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT + unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; // NOLINT - for (size_t i = 0; i < ev_dev_count; ++i) { - memset(ev_bits, 0, sizeof(ev_bits)); - memset(key_bits, 0, sizeof(key_bits)); + for (size_t i = 0; i < g_ev_dev_count; ++i) { + memset(ev_bits, 0, sizeof(ev_bits)); + memset(key_bits, 0, sizeof(key_bits)); - // Does this device even have keys? - if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) { - continue; - } - if (!test_bit(EV_KEY, ev_bits)) { - continue; - } + // Does this device even have keys? + if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) { + continue; + } + if (!test_bit(EV_KEY, ev_bits)) { + continue; + } - int rc = ioctl(ev_fdinfo[i].fd, EVIOCGBIT(EV_KEY, KEY_MAX), key_bits); - if (rc == -1) { - continue; - } + if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(EV_KEY, KEY_MAX), key_bits) == -1) { + continue; + } - for (int key_code = 0; key_code <= KEY_MAX; ++key_code) { - if (test_bit(key_code, key_bits)) { - f(key_code); - } - } + for (int key_code = 0; key_code <= KEY_MAX; ++key_code) { + if (test_bit(key_code, key_bits)) { + f(key_code); + } } + } } void ev_iterate_touch_inputs(const std::function<void(int)>& action) { - for (size_t i = 0; i < ev_dev_count; ++i) { + for (size_t i = 0; i < g_ev_dev_count; ++i) { // Use unsigned long to match ioctl's parameter type. unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)] = {}; // NOLINT if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) { |