1*e7c364b6SAndroid Build Coastguard Worker /*
2*e7c364b6SAndroid Build Coastguard Worker * Copyright (C) 2007 The Android Open Source Project
3*e7c364b6SAndroid Build Coastguard Worker *
4*e7c364b6SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e7c364b6SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e7c364b6SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e7c364b6SAndroid Build Coastguard Worker *
8*e7c364b6SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e7c364b6SAndroid Build Coastguard Worker *
10*e7c364b6SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e7c364b6SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e7c364b6SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e7c364b6SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e7c364b6SAndroid Build Coastguard Worker * limitations under the License.
15*e7c364b6SAndroid Build Coastguard Worker */
16*e7c364b6SAndroid Build Coastguard Worker
17*e7c364b6SAndroid Build Coastguard Worker #include <dirent.h>
18*e7c364b6SAndroid Build Coastguard Worker #include <errno.h>
19*e7c364b6SAndroid Build Coastguard Worker #include <fcntl.h>
20*e7c364b6SAndroid Build Coastguard Worker #include <linux/input.h>
21*e7c364b6SAndroid Build Coastguard Worker #include <stdio.h>
22*e7c364b6SAndroid Build Coastguard Worker #include <stdlib.h>
23*e7c364b6SAndroid Build Coastguard Worker #include <string.h>
24*e7c364b6SAndroid Build Coastguard Worker #include <sys/epoll.h>
25*e7c364b6SAndroid Build Coastguard Worker #include <sys/inotify.h>
26*e7c364b6SAndroid Build Coastguard Worker #include <sys/ioctl.h>
27*e7c364b6SAndroid Build Coastguard Worker #include <sys/types.h>
28*e7c364b6SAndroid Build Coastguard Worker #include <unistd.h>
29*e7c364b6SAndroid Build Coastguard Worker
30*e7c364b6SAndroid Build Coastguard Worker #include <functional>
31*e7c364b6SAndroid Build Coastguard Worker #include <memory>
32*e7c364b6SAndroid Build Coastguard Worker #include <string>
33*e7c364b6SAndroid Build Coastguard Worker
34*e7c364b6SAndroid Build Coastguard Worker #include <android-base/strings.h>
35*e7c364b6SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
36*e7c364b6SAndroid Build Coastguard Worker
37*e7c364b6SAndroid Build Coastguard Worker #include "minui/minui.h"
38*e7c364b6SAndroid Build Coastguard Worker
39*e7c364b6SAndroid Build Coastguard Worker constexpr const char* INPUT_DEV_DIR = "/dev/input";
40*e7c364b6SAndroid Build Coastguard Worker
41*e7c364b6SAndroid Build Coastguard Worker constexpr size_t MAX_DEVICES = 16;
42*e7c364b6SAndroid Build Coastguard Worker constexpr size_t MAX_MISC_FDS = 16;
43*e7c364b6SAndroid Build Coastguard Worker
44*e7c364b6SAndroid Build Coastguard Worker constexpr size_t BITS_PER_LONG = sizeof(unsigned long) * 8;
BITS_TO_LONGS(size_t bits)45*e7c364b6SAndroid Build Coastguard Worker constexpr size_t BITS_TO_LONGS(size_t bits) {
46*e7c364b6SAndroid Build Coastguard Worker return ((bits + BITS_PER_LONG - 1) / BITS_PER_LONG);
47*e7c364b6SAndroid Build Coastguard Worker }
48*e7c364b6SAndroid Build Coastguard Worker
49*e7c364b6SAndroid Build Coastguard Worker struct FdInfo {
50*e7c364b6SAndroid Build Coastguard Worker android::base::unique_fd fd;
51*e7c364b6SAndroid Build Coastguard Worker ev_callback cb;
52*e7c364b6SAndroid Build Coastguard Worker };
53*e7c364b6SAndroid Build Coastguard Worker
54*e7c364b6SAndroid Build Coastguard Worker static bool g_allow_touch_inputs = true;
55*e7c364b6SAndroid Build Coastguard Worker static ev_callback g_saved_input_cb;
56*e7c364b6SAndroid Build Coastguard Worker static android::base::unique_fd g_epoll_fd;
57*e7c364b6SAndroid Build Coastguard Worker static epoll_event g_polled_events[MAX_DEVICES + MAX_MISC_FDS];
58*e7c364b6SAndroid Build Coastguard Worker static int g_polled_events_count;
59*e7c364b6SAndroid Build Coastguard Worker
60*e7c364b6SAndroid Build Coastguard Worker static FdInfo ev_fdinfo[MAX_DEVICES + MAX_MISC_FDS];
61*e7c364b6SAndroid Build Coastguard Worker
62*e7c364b6SAndroid Build Coastguard Worker static size_t g_ev_count = 0;
63*e7c364b6SAndroid Build Coastguard Worker static size_t g_ev_dev_count = 0;
64*e7c364b6SAndroid Build Coastguard Worker static size_t g_ev_misc_count = 0;
65*e7c364b6SAndroid Build Coastguard Worker
test_bit(size_t bit,unsigned long * array)66*e7c364b6SAndroid Build Coastguard Worker static bool test_bit(size_t bit, unsigned long* array) { // NOLINT
67*e7c364b6SAndroid Build Coastguard Worker return (array[bit / BITS_PER_LONG] & (1UL << (bit % BITS_PER_LONG))) != 0;
68*e7c364b6SAndroid Build Coastguard Worker }
69*e7c364b6SAndroid Build Coastguard Worker
should_add_input_device(int fd,bool allow_touch_inputs)70*e7c364b6SAndroid Build Coastguard Worker static bool should_add_input_device(int fd, bool allow_touch_inputs) {
71*e7c364b6SAndroid Build Coastguard Worker // Use unsigned long to match ioctl's parameter type.
72*e7c364b6SAndroid Build Coastguard Worker unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT
73*e7c364b6SAndroid Build Coastguard Worker
74*e7c364b6SAndroid Build Coastguard Worker // Read the evbits of the input device.
75*e7c364b6SAndroid Build Coastguard Worker if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) {
76*e7c364b6SAndroid Build Coastguard Worker return false;
77*e7c364b6SAndroid Build Coastguard Worker }
78*e7c364b6SAndroid Build Coastguard Worker
79*e7c364b6SAndroid Build Coastguard Worker // We assume that only EV_KEY, EV_REL, and EV_SW event types are ever needed. EV_ABS is also
80*e7c364b6SAndroid Build Coastguard Worker // allowed if allow_touch_inputs is set.
81*e7c364b6SAndroid Build Coastguard Worker if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits) && !test_bit(EV_SW, ev_bits)) {
82*e7c364b6SAndroid Build Coastguard Worker if (!allow_touch_inputs || !test_bit(EV_ABS, ev_bits)) {
83*e7c364b6SAndroid Build Coastguard Worker return false;
84*e7c364b6SAndroid Build Coastguard Worker }
85*e7c364b6SAndroid Build Coastguard Worker }
86*e7c364b6SAndroid Build Coastguard Worker
87*e7c364b6SAndroid Build Coastguard Worker return true;
88*e7c364b6SAndroid Build Coastguard Worker }
89*e7c364b6SAndroid Build Coastguard Worker
inotify_cb(int fd,__unused uint32_t epevents)90*e7c364b6SAndroid Build Coastguard Worker static int inotify_cb(int fd, __unused uint32_t epevents) {
91*e7c364b6SAndroid Build Coastguard Worker if (g_saved_input_cb == nullptr) return -1;
92*e7c364b6SAndroid Build Coastguard Worker
93*e7c364b6SAndroid Build Coastguard Worker // The inotify will put one or several complete events.
94*e7c364b6SAndroid Build Coastguard Worker // Should not read part of one event.
95*e7c364b6SAndroid Build Coastguard Worker int event_len_int;
96*e7c364b6SAndroid Build Coastguard Worker int ret = ioctl(fd, FIONREAD, &event_len_int);
97*e7c364b6SAndroid Build Coastguard Worker if (ret != 0) return -1;
98*e7c364b6SAndroid Build Coastguard Worker if (event_len_int < 0) return -1;
99*e7c364b6SAndroid Build Coastguard Worker size_t event_len = event_len_int;
100*e7c364b6SAndroid Build Coastguard Worker
101*e7c364b6SAndroid Build Coastguard Worker std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(INPUT_DEV_DIR), closedir);
102*e7c364b6SAndroid Build Coastguard Worker if (!dir) {
103*e7c364b6SAndroid Build Coastguard Worker return -1;
104*e7c364b6SAndroid Build Coastguard Worker }
105*e7c364b6SAndroid Build Coastguard Worker
106*e7c364b6SAndroid Build Coastguard Worker std::vector<int8_t> buf(event_len);
107*e7c364b6SAndroid Build Coastguard Worker
108*e7c364b6SAndroid Build Coastguard Worker ssize_t r = TEMP_FAILURE_RETRY(read(fd, buf.data(), event_len));
109*e7c364b6SAndroid Build Coastguard Worker if (r != event_len) {
110*e7c364b6SAndroid Build Coastguard Worker return -1;
111*e7c364b6SAndroid Build Coastguard Worker }
112*e7c364b6SAndroid Build Coastguard Worker
113*e7c364b6SAndroid Build Coastguard Worker size_t offset = 0;
114*e7c364b6SAndroid Build Coastguard Worker while (offset < event_len) {
115*e7c364b6SAndroid Build Coastguard Worker struct inotify_event* pevent = reinterpret_cast<struct inotify_event*>(buf.data() + offset);
116*e7c364b6SAndroid Build Coastguard Worker if (offset + sizeof(inotify_event) + pevent->len > event_len) {
117*e7c364b6SAndroid Build Coastguard Worker // The pevent->len is too large and buffer will over flow.
118*e7c364b6SAndroid Build Coastguard Worker // In general, should not happen, just make more stable.
119*e7c364b6SAndroid Build Coastguard Worker return -1;
120*e7c364b6SAndroid Build Coastguard Worker }
121*e7c364b6SAndroid Build Coastguard Worker offset += sizeof(inotify_event) + pevent->len;
122*e7c364b6SAndroid Build Coastguard Worker
123*e7c364b6SAndroid Build Coastguard Worker std::string event_name(pevent->name, pevent->len);
124*e7c364b6SAndroid Build Coastguard Worker if (!android::base::StartsWith(event_name, "event")) {
125*e7c364b6SAndroid Build Coastguard Worker continue;
126*e7c364b6SAndroid Build Coastguard Worker }
127*e7c364b6SAndroid Build Coastguard Worker
128*e7c364b6SAndroid Build Coastguard Worker android::base::unique_fd dfd(openat(dirfd(dir.get()), event_name.c_str(), O_RDONLY));
129*e7c364b6SAndroid Build Coastguard Worker if (dfd == -1) {
130*e7c364b6SAndroid Build Coastguard Worker break;
131*e7c364b6SAndroid Build Coastguard Worker }
132*e7c364b6SAndroid Build Coastguard Worker
133*e7c364b6SAndroid Build Coastguard Worker if (!should_add_input_device(dfd, g_allow_touch_inputs)) {
134*e7c364b6SAndroid Build Coastguard Worker continue;
135*e7c364b6SAndroid Build Coastguard Worker }
136*e7c364b6SAndroid Build Coastguard Worker
137*e7c364b6SAndroid Build Coastguard Worker // Only add, we assume the user will not plug out and plug in USB device again and again :)
138*e7c364b6SAndroid Build Coastguard Worker ev_add_fd(std::move(dfd), g_saved_input_cb);
139*e7c364b6SAndroid Build Coastguard Worker }
140*e7c364b6SAndroid Build Coastguard Worker
141*e7c364b6SAndroid Build Coastguard Worker return 0;
142*e7c364b6SAndroid Build Coastguard Worker }
143*e7c364b6SAndroid Build Coastguard Worker
ev_init(ev_callback input_cb,bool allow_touch_inputs)144*e7c364b6SAndroid Build Coastguard Worker int ev_init(ev_callback input_cb, bool allow_touch_inputs) {
145*e7c364b6SAndroid Build Coastguard Worker g_epoll_fd.reset();
146*e7c364b6SAndroid Build Coastguard Worker
147*e7c364b6SAndroid Build Coastguard Worker android::base::unique_fd epoll_fd(epoll_create1(EPOLL_CLOEXEC));
148*e7c364b6SAndroid Build Coastguard Worker if (epoll_fd == -1) {
149*e7c364b6SAndroid Build Coastguard Worker return -1;
150*e7c364b6SAndroid Build Coastguard Worker }
151*e7c364b6SAndroid Build Coastguard Worker
152*e7c364b6SAndroid Build Coastguard Worker android::base::unique_fd inotify_fd(inotify_init1(IN_CLOEXEC));
153*e7c364b6SAndroid Build Coastguard Worker if (inotify_fd.get() == -1) {
154*e7c364b6SAndroid Build Coastguard Worker return -1;
155*e7c364b6SAndroid Build Coastguard Worker }
156*e7c364b6SAndroid Build Coastguard Worker
157*e7c364b6SAndroid Build Coastguard Worker if (inotify_add_watch(inotify_fd, INPUT_DEV_DIR, IN_CREATE) < 0) {
158*e7c364b6SAndroid Build Coastguard Worker return -1;
159*e7c364b6SAndroid Build Coastguard Worker }
160*e7c364b6SAndroid Build Coastguard Worker
161*e7c364b6SAndroid Build Coastguard Worker std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(INPUT_DEV_DIR), closedir);
162*e7c364b6SAndroid Build Coastguard Worker if (!dir) {
163*e7c364b6SAndroid Build Coastguard Worker return -1;
164*e7c364b6SAndroid Build Coastguard Worker }
165*e7c364b6SAndroid Build Coastguard Worker
166*e7c364b6SAndroid Build Coastguard Worker bool epoll_ctl_failed = false;
167*e7c364b6SAndroid Build Coastguard Worker dirent* de;
168*e7c364b6SAndroid Build Coastguard Worker while ((de = readdir(dir.get())) != nullptr) {
169*e7c364b6SAndroid Build Coastguard Worker if (strncmp(de->d_name, "event", 5)) continue;
170*e7c364b6SAndroid Build Coastguard Worker android::base::unique_fd fd(openat(dirfd(dir.get()), de->d_name, O_RDONLY | O_CLOEXEC));
171*e7c364b6SAndroid Build Coastguard Worker if (fd == -1) continue;
172*e7c364b6SAndroid Build Coastguard Worker
173*e7c364b6SAndroid Build Coastguard Worker if (!should_add_input_device(fd, allow_touch_inputs)) {
174*e7c364b6SAndroid Build Coastguard Worker continue;
175*e7c364b6SAndroid Build Coastguard Worker }
176*e7c364b6SAndroid Build Coastguard Worker
177*e7c364b6SAndroid Build Coastguard Worker epoll_event ev;
178*e7c364b6SAndroid Build Coastguard Worker ev.events = EPOLLIN | EPOLLWAKEUP;
179*e7c364b6SAndroid Build Coastguard Worker ev.data.ptr = &ev_fdinfo[g_ev_count];
180*e7c364b6SAndroid Build Coastguard Worker if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
181*e7c364b6SAndroid Build Coastguard Worker epoll_ctl_failed = true;
182*e7c364b6SAndroid Build Coastguard Worker continue;
183*e7c364b6SAndroid Build Coastguard Worker }
184*e7c364b6SAndroid Build Coastguard Worker
185*e7c364b6SAndroid Build Coastguard Worker ev_fdinfo[g_ev_count].fd.reset(fd.release());
186*e7c364b6SAndroid Build Coastguard Worker ev_fdinfo[g_ev_count].cb = input_cb;
187*e7c364b6SAndroid Build Coastguard Worker g_ev_count++;
188*e7c364b6SAndroid Build Coastguard Worker g_ev_dev_count++;
189*e7c364b6SAndroid Build Coastguard Worker if (g_ev_dev_count == MAX_DEVICES) break;
190*e7c364b6SAndroid Build Coastguard Worker }
191*e7c364b6SAndroid Build Coastguard Worker
192*e7c364b6SAndroid Build Coastguard Worker if (epoll_ctl_failed && !g_ev_count) {
193*e7c364b6SAndroid Build Coastguard Worker return -1;
194*e7c364b6SAndroid Build Coastguard Worker }
195*e7c364b6SAndroid Build Coastguard Worker
196*e7c364b6SAndroid Build Coastguard Worker g_epoll_fd.reset(epoll_fd.release());
197*e7c364b6SAndroid Build Coastguard Worker
198*e7c364b6SAndroid Build Coastguard Worker g_saved_input_cb = input_cb;
199*e7c364b6SAndroid Build Coastguard Worker g_allow_touch_inputs = allow_touch_inputs;
200*e7c364b6SAndroid Build Coastguard Worker ev_add_fd(std::move(inotify_fd), inotify_cb);
201*e7c364b6SAndroid Build Coastguard Worker
202*e7c364b6SAndroid Build Coastguard Worker return 0;
203*e7c364b6SAndroid Build Coastguard Worker }
204*e7c364b6SAndroid Build Coastguard Worker
ev_get_epollfd(void)205*e7c364b6SAndroid Build Coastguard Worker int ev_get_epollfd(void) {
206*e7c364b6SAndroid Build Coastguard Worker return g_epoll_fd.get();
207*e7c364b6SAndroid Build Coastguard Worker }
208*e7c364b6SAndroid Build Coastguard Worker
ev_add_fd(android::base::unique_fd && fd,ev_callback cb)209*e7c364b6SAndroid Build Coastguard Worker int ev_add_fd(android::base::unique_fd&& fd, ev_callback cb) {
210*e7c364b6SAndroid Build Coastguard Worker if (g_ev_misc_count == MAX_MISC_FDS || cb == nullptr) {
211*e7c364b6SAndroid Build Coastguard Worker return -1;
212*e7c364b6SAndroid Build Coastguard Worker }
213*e7c364b6SAndroid Build Coastguard Worker
214*e7c364b6SAndroid Build Coastguard Worker epoll_event ev;
215*e7c364b6SAndroid Build Coastguard Worker ev.events = EPOLLIN | EPOLLWAKEUP;
216*e7c364b6SAndroid Build Coastguard Worker ev.data.ptr = static_cast<void*>(&ev_fdinfo[g_ev_count]);
217*e7c364b6SAndroid Build Coastguard Worker int ret = epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, fd, &ev);
218*e7c364b6SAndroid Build Coastguard Worker if (!ret) {
219*e7c364b6SAndroid Build Coastguard Worker ev_fdinfo[g_ev_count].fd.reset(fd.release());
220*e7c364b6SAndroid Build Coastguard Worker ev_fdinfo[g_ev_count].cb = std::move(cb);
221*e7c364b6SAndroid Build Coastguard Worker g_ev_count++;
222*e7c364b6SAndroid Build Coastguard Worker g_ev_misc_count++;
223*e7c364b6SAndroid Build Coastguard Worker }
224*e7c364b6SAndroid Build Coastguard Worker
225*e7c364b6SAndroid Build Coastguard Worker return ret;
226*e7c364b6SAndroid Build Coastguard Worker }
227*e7c364b6SAndroid Build Coastguard Worker
ev_exit(void)228*e7c364b6SAndroid Build Coastguard Worker void ev_exit(void) {
229*e7c364b6SAndroid Build Coastguard Worker while (g_ev_count > 0) {
230*e7c364b6SAndroid Build Coastguard Worker ev_fdinfo[--g_ev_count].fd.reset();
231*e7c364b6SAndroid Build Coastguard Worker }
232*e7c364b6SAndroid Build Coastguard Worker g_ev_misc_count = 0;
233*e7c364b6SAndroid Build Coastguard Worker g_ev_dev_count = 0;
234*e7c364b6SAndroid Build Coastguard Worker g_saved_input_cb = nullptr;
235*e7c364b6SAndroid Build Coastguard Worker g_epoll_fd.reset();
236*e7c364b6SAndroid Build Coastguard Worker }
237*e7c364b6SAndroid Build Coastguard Worker
ev_wait(int timeout)238*e7c364b6SAndroid Build Coastguard Worker int ev_wait(int timeout) {
239*e7c364b6SAndroid Build Coastguard Worker g_polled_events_count = epoll_wait(g_epoll_fd, g_polled_events, g_ev_count, timeout);
240*e7c364b6SAndroid Build Coastguard Worker if (g_polled_events_count <= 0) {
241*e7c364b6SAndroid Build Coastguard Worker return -1;
242*e7c364b6SAndroid Build Coastguard Worker }
243*e7c364b6SAndroid Build Coastguard Worker return 0;
244*e7c364b6SAndroid Build Coastguard Worker }
245*e7c364b6SAndroid Build Coastguard Worker
ev_dispatch(void)246*e7c364b6SAndroid Build Coastguard Worker void ev_dispatch(void) {
247*e7c364b6SAndroid Build Coastguard Worker for (int n = 0; n < g_polled_events_count; n++) {
248*e7c364b6SAndroid Build Coastguard Worker FdInfo* fdi = static_cast<FdInfo*>(g_polled_events[n].data.ptr);
249*e7c364b6SAndroid Build Coastguard Worker const ev_callback& cb = fdi->cb;
250*e7c364b6SAndroid Build Coastguard Worker if (cb) {
251*e7c364b6SAndroid Build Coastguard Worker cb(fdi->fd, g_polled_events[n].events);
252*e7c364b6SAndroid Build Coastguard Worker }
253*e7c364b6SAndroid Build Coastguard Worker }
254*e7c364b6SAndroid Build Coastguard Worker }
255*e7c364b6SAndroid Build Coastguard Worker
ev_get_input(int fd,uint32_t epevents,input_event * ev)256*e7c364b6SAndroid Build Coastguard Worker int ev_get_input(int fd, uint32_t epevents, input_event* ev) {
257*e7c364b6SAndroid Build Coastguard Worker if (epevents & EPOLLIN) {
258*e7c364b6SAndroid Build Coastguard Worker ssize_t r = TEMP_FAILURE_RETRY(read(fd, ev, sizeof(*ev)));
259*e7c364b6SAndroid Build Coastguard Worker if (r == sizeof(*ev)) {
260*e7c364b6SAndroid Build Coastguard Worker return 0;
261*e7c364b6SAndroid Build Coastguard Worker }
262*e7c364b6SAndroid Build Coastguard Worker }
263*e7c364b6SAndroid Build Coastguard Worker if (epevents & EPOLLHUP) {
264*e7c364b6SAndroid Build Coastguard Worker // Delete this watch
265*e7c364b6SAndroid Build Coastguard Worker epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, fd, nullptr);
266*e7c364b6SAndroid Build Coastguard Worker }
267*e7c364b6SAndroid Build Coastguard Worker return -1;
268*e7c364b6SAndroid Build Coastguard Worker }
269*e7c364b6SAndroid Build Coastguard Worker
ev_sync_sw_state(const ev_set_sw_callback & set_sw_cb)270*e7c364b6SAndroid Build Coastguard Worker int ev_sync_sw_state(const ev_set_sw_callback& set_sw_cb) {
271*e7c364b6SAndroid Build Coastguard Worker // Use unsigned long to match ioctl's parameter type.
272*e7c364b6SAndroid Build Coastguard Worker unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT
273*e7c364b6SAndroid Build Coastguard Worker unsigned long sw_bits[BITS_TO_LONGS(SW_MAX)]; // NOLINT
274*e7c364b6SAndroid Build Coastguard Worker
275*e7c364b6SAndroid Build Coastguard Worker for (size_t i = 0; i < g_ev_dev_count; ++i) {
276*e7c364b6SAndroid Build Coastguard Worker memset(ev_bits, 0, sizeof(ev_bits));
277*e7c364b6SAndroid Build Coastguard Worker memset(sw_bits, 0, sizeof(sw_bits));
278*e7c364b6SAndroid Build Coastguard Worker
279*e7c364b6SAndroid Build Coastguard Worker if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) {
280*e7c364b6SAndroid Build Coastguard Worker continue;
281*e7c364b6SAndroid Build Coastguard Worker }
282*e7c364b6SAndroid Build Coastguard Worker if (!test_bit(EV_SW, ev_bits)) {
283*e7c364b6SAndroid Build Coastguard Worker continue;
284*e7c364b6SAndroid Build Coastguard Worker }
285*e7c364b6SAndroid Build Coastguard Worker if (ioctl(ev_fdinfo[i].fd, EVIOCGSW(sizeof(sw_bits)), sw_bits) == -1) {
286*e7c364b6SAndroid Build Coastguard Worker continue;
287*e7c364b6SAndroid Build Coastguard Worker }
288*e7c364b6SAndroid Build Coastguard Worker
289*e7c364b6SAndroid Build Coastguard Worker for (int code = 0; code <= SW_MAX; code++) {
290*e7c364b6SAndroid Build Coastguard Worker if (test_bit(code, sw_bits)) {
291*e7c364b6SAndroid Build Coastguard Worker set_sw_cb(code, 1);
292*e7c364b6SAndroid Build Coastguard Worker }
293*e7c364b6SAndroid Build Coastguard Worker }
294*e7c364b6SAndroid Build Coastguard Worker }
295*e7c364b6SAndroid Build Coastguard Worker
296*e7c364b6SAndroid Build Coastguard Worker return 0;
297*e7c364b6SAndroid Build Coastguard Worker }
298*e7c364b6SAndroid Build Coastguard Worker
ev_sync_key_state(const ev_set_key_callback & set_key_cb)299*e7c364b6SAndroid Build Coastguard Worker int ev_sync_key_state(const ev_set_key_callback& set_key_cb) {
300*e7c364b6SAndroid Build Coastguard Worker // Use unsigned long to match ioctl's parameter type.
301*e7c364b6SAndroid Build Coastguard Worker unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT
302*e7c364b6SAndroid Build Coastguard Worker unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; // NOLINT
303*e7c364b6SAndroid Build Coastguard Worker
304*e7c364b6SAndroid Build Coastguard Worker for (size_t i = 0; i < g_ev_dev_count; ++i) {
305*e7c364b6SAndroid Build Coastguard Worker memset(ev_bits, 0, sizeof(ev_bits));
306*e7c364b6SAndroid Build Coastguard Worker memset(key_bits, 0, sizeof(key_bits));
307*e7c364b6SAndroid Build Coastguard Worker
308*e7c364b6SAndroid Build Coastguard Worker if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) {
309*e7c364b6SAndroid Build Coastguard Worker continue;
310*e7c364b6SAndroid Build Coastguard Worker }
311*e7c364b6SAndroid Build Coastguard Worker if (!test_bit(EV_KEY, ev_bits)) {
312*e7c364b6SAndroid Build Coastguard Worker continue;
313*e7c364b6SAndroid Build Coastguard Worker }
314*e7c364b6SAndroid Build Coastguard Worker if (ioctl(ev_fdinfo[i].fd, EVIOCGKEY(sizeof(key_bits)), key_bits) == -1) {
315*e7c364b6SAndroid Build Coastguard Worker continue;
316*e7c364b6SAndroid Build Coastguard Worker }
317*e7c364b6SAndroid Build Coastguard Worker
318*e7c364b6SAndroid Build Coastguard Worker for (int code = 0; code <= KEY_MAX; code++) {
319*e7c364b6SAndroid Build Coastguard Worker if (test_bit(code, key_bits)) {
320*e7c364b6SAndroid Build Coastguard Worker set_key_cb(code, 1);
321*e7c364b6SAndroid Build Coastguard Worker }
322*e7c364b6SAndroid Build Coastguard Worker }
323*e7c364b6SAndroid Build Coastguard Worker }
324*e7c364b6SAndroid Build Coastguard Worker
325*e7c364b6SAndroid Build Coastguard Worker return 0;
326*e7c364b6SAndroid Build Coastguard Worker }
327*e7c364b6SAndroid Build Coastguard Worker
ev_iterate_available_keys(const std::function<void (int)> & f)328*e7c364b6SAndroid Build Coastguard Worker void ev_iterate_available_keys(const std::function<void(int)>& f) {
329*e7c364b6SAndroid Build Coastguard Worker // Use unsigned long to match ioctl's parameter type.
330*e7c364b6SAndroid Build Coastguard Worker unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT
331*e7c364b6SAndroid Build Coastguard Worker unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; // NOLINT
332*e7c364b6SAndroid Build Coastguard Worker
333*e7c364b6SAndroid Build Coastguard Worker for (size_t i = 0; i < g_ev_dev_count; ++i) {
334*e7c364b6SAndroid Build Coastguard Worker memset(ev_bits, 0, sizeof(ev_bits));
335*e7c364b6SAndroid Build Coastguard Worker memset(key_bits, 0, sizeof(key_bits));
336*e7c364b6SAndroid Build Coastguard Worker
337*e7c364b6SAndroid Build Coastguard Worker // Does this device even have keys?
338*e7c364b6SAndroid Build Coastguard Worker if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) {
339*e7c364b6SAndroid Build Coastguard Worker continue;
340*e7c364b6SAndroid Build Coastguard Worker }
341*e7c364b6SAndroid Build Coastguard Worker if (!test_bit(EV_KEY, ev_bits)) {
342*e7c364b6SAndroid Build Coastguard Worker continue;
343*e7c364b6SAndroid Build Coastguard Worker }
344*e7c364b6SAndroid Build Coastguard Worker
345*e7c364b6SAndroid Build Coastguard Worker if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(EV_KEY, KEY_MAX), key_bits) == -1) {
346*e7c364b6SAndroid Build Coastguard Worker continue;
347*e7c364b6SAndroid Build Coastguard Worker }
348*e7c364b6SAndroid Build Coastguard Worker
349*e7c364b6SAndroid Build Coastguard Worker for (int key_code = 0; key_code <= KEY_MAX; ++key_code) {
350*e7c364b6SAndroid Build Coastguard Worker if (test_bit(key_code, key_bits)) {
351*e7c364b6SAndroid Build Coastguard Worker f(key_code);
352*e7c364b6SAndroid Build Coastguard Worker }
353*e7c364b6SAndroid Build Coastguard Worker }
354*e7c364b6SAndroid Build Coastguard Worker }
355*e7c364b6SAndroid Build Coastguard Worker }
356*e7c364b6SAndroid Build Coastguard Worker
ev_iterate_touch_inputs(const std::function<void (int)> & action)357*e7c364b6SAndroid Build Coastguard Worker void ev_iterate_touch_inputs(const std::function<void(int)>& action) {
358*e7c364b6SAndroid Build Coastguard Worker for (size_t i = 0; i < g_ev_dev_count; ++i) {
359*e7c364b6SAndroid Build Coastguard Worker // Use unsigned long to match ioctl's parameter type.
360*e7c364b6SAndroid Build Coastguard Worker unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)] = {}; // NOLINT
361*e7c364b6SAndroid Build Coastguard Worker if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) {
362*e7c364b6SAndroid Build Coastguard Worker continue;
363*e7c364b6SAndroid Build Coastguard Worker }
364*e7c364b6SAndroid Build Coastguard Worker if (!test_bit(EV_ABS, ev_bits)) {
365*e7c364b6SAndroid Build Coastguard Worker continue;
366*e7c364b6SAndroid Build Coastguard Worker }
367*e7c364b6SAndroid Build Coastguard Worker
368*e7c364b6SAndroid Build Coastguard Worker unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)] = {}; // NOLINT
369*e7c364b6SAndroid Build Coastguard Worker if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(EV_ABS, KEY_MAX), key_bits) == -1) {
370*e7c364b6SAndroid Build Coastguard Worker continue;
371*e7c364b6SAndroid Build Coastguard Worker }
372*e7c364b6SAndroid Build Coastguard Worker
373*e7c364b6SAndroid Build Coastguard Worker for (int key_code = 0; key_code <= KEY_MAX; ++key_code) {
374*e7c364b6SAndroid Build Coastguard Worker if (test_bit(key_code, key_bits)) {
375*e7c364b6SAndroid Build Coastguard Worker action(key_code);
376*e7c364b6SAndroid Build Coastguard Worker }
377*e7c364b6SAndroid Build Coastguard Worker }
378*e7c364b6SAndroid Build Coastguard Worker }
379*e7c364b6SAndroid Build Coastguard Worker }
380