Home | History | Annotate | Download | only in minui
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      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 <dirent.h>
     18 #include <errno.h>
     19 #include <fcntl.h>
     20 #include <linux/input.h>
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 #include <sys/epoll.h>
     25 #include <sys/ioctl.h>
     26 #include <unistd.h>
     27 
     28 #include <functional>
     29 
     30 #include "minui/minui.h"
     31 
     32 #define MAX_DEVICES 16
     33 #define MAX_MISC_FDS 16
     34 
     35 #define BITS_PER_LONG (sizeof(unsigned long) * 8)
     36 #define BITS_TO_LONGS(x) (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG)
     37 
     38 struct fd_info {
     39   int fd;
     40   ev_callback cb;
     41 };
     42 
     43 static int g_epoll_fd;
     44 static epoll_event polledevents[MAX_DEVICES + MAX_MISC_FDS];
     45 static int npolledevents;
     46 
     47 static fd_info ev_fdinfo[MAX_DEVICES + MAX_MISC_FDS];
     48 
     49 static unsigned ev_count = 0;
     50 static unsigned ev_dev_count = 0;
     51 static unsigned ev_misc_count = 0;
     52 
     53 static bool test_bit(size_t bit, unsigned long* array) { // NOLINT
     54     return (array[bit/BITS_PER_LONG] & (1UL << (bit % BITS_PER_LONG))) != 0;
     55 }
     56 
     57 int ev_init(ev_callback input_cb, bool allow_touch_inputs) {
     58   g_epoll_fd = epoll_create(MAX_DEVICES + MAX_MISC_FDS);
     59   if (g_epoll_fd == -1) {
     60     return -1;
     61   }
     62 
     63   bool epollctlfail = false;
     64   DIR* dir = opendir("/dev/input");
     65   if (dir != nullptr) {
     66     dirent* de;
     67     while ((de = readdir(dir))) {
     68       if (strncmp(de->d_name, "event", 5)) continue;
     69       int fd = openat(dirfd(dir), de->d_name, O_RDONLY);
     70       if (fd == -1) continue;
     71 
     72       // Use unsigned long to match ioctl's parameter type.
     73       unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];  // NOLINT
     74 
     75       // Read the evbits of the input device.
     76       if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) {
     77         close(fd);
     78         continue;
     79       }
     80 
     81       // We assume that only EV_KEY, EV_REL, and EV_SW event types are ever needed. EV_ABS is also
     82       // allowed if allow_touch_inputs is set.
     83       if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits) && !test_bit(EV_SW, ev_bits)) {
     84         if (!allow_touch_inputs || !test_bit(EV_ABS, ev_bits)) {
     85           close(fd);
     86           continue;
     87         }
     88       }
     89 
     90       epoll_event ev;
     91       ev.events = EPOLLIN | EPOLLWAKEUP;
     92       ev.data.ptr = &ev_fdinfo[ev_count];
     93       if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
     94         close(fd);
     95         epollctlfail = true;
     96         continue;
     97       }
     98 
     99       ev_fdinfo[ev_count].fd = fd;
    100       ev_fdinfo[ev_count].cb = std::move(input_cb);
    101       ev_count++;
    102       ev_dev_count++;
    103       if (ev_dev_count == MAX_DEVICES) break;
    104     }
    105 
    106     closedir(dir);
    107   }
    108 
    109   if (epollctlfail && !ev_count) {
    110     close(g_epoll_fd);
    111     g_epoll_fd = -1;
    112     return -1;
    113   }
    114 
    115   return 0;
    116 }
    117 
    118 int ev_get_epollfd(void) {
    119     return g_epoll_fd;
    120 }
    121 
    122 int ev_add_fd(int fd, ev_callback cb) {
    123   if (ev_misc_count == MAX_MISC_FDS || cb == NULL) {
    124     return -1;
    125   }
    126 
    127   epoll_event ev;
    128   ev.events = EPOLLIN | EPOLLWAKEUP;
    129   ev.data.ptr = static_cast<void*>(&ev_fdinfo[ev_count]);
    130   int ret = epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, fd, &ev);
    131   if (!ret) {
    132     ev_fdinfo[ev_count].fd = fd;
    133     ev_fdinfo[ev_count].cb = std::move(cb);
    134     ev_count++;
    135     ev_misc_count++;
    136   }
    137 
    138   return ret;
    139 }
    140 
    141 void ev_exit(void) {
    142     while (ev_count > 0) {
    143         close(ev_fdinfo[--ev_count].fd);
    144     }
    145     ev_misc_count = 0;
    146     ev_dev_count = 0;
    147     close(g_epoll_fd);
    148 }
    149 
    150 int ev_wait(int timeout) {
    151     npolledevents = epoll_wait(g_epoll_fd, polledevents, ev_count, timeout);
    152     if (npolledevents <= 0) {
    153         return -1;
    154     }
    155     return 0;
    156 }
    157 
    158 void ev_dispatch(void) {
    159   for (int n = 0; n < npolledevents; n++) {
    160     fd_info* fdi = static_cast<fd_info*>(polledevents[n].data.ptr);
    161     const ev_callback& cb = fdi->cb;
    162     if (cb) {
    163       cb(fdi->fd, polledevents[n].events);
    164     }
    165   }
    166 }
    167 
    168 int ev_get_input(int fd, uint32_t epevents, input_event* ev) {
    169     if (epevents & EPOLLIN) {
    170         ssize_t r = TEMP_FAILURE_RETRY(read(fd, ev, sizeof(*ev)));
    171         if (r == sizeof(*ev)) {
    172             return 0;
    173         }
    174     }
    175     return -1;
    176 }
    177 
    178 int ev_sync_key_state(const ev_set_key_callback& set_key_cb) {
    179   // Use unsigned long to match ioctl's parameter type.
    180   unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];    // NOLINT
    181   unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)];  // NOLINT
    182 
    183   for (size_t i = 0; i < ev_dev_count; ++i) {
    184     memset(ev_bits, 0, sizeof(ev_bits));
    185     memset(key_bits, 0, sizeof(key_bits));
    186 
    187     if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) {
    188       continue;
    189     }
    190     if (!test_bit(EV_KEY, ev_bits)) {
    191       continue;
    192     }
    193     if (ioctl(ev_fdinfo[i].fd, EVIOCGKEY(sizeof(key_bits)), key_bits) == -1) {
    194       continue;
    195     }
    196 
    197     for (int code = 0; code <= KEY_MAX; code++) {
    198       if (test_bit(code, key_bits)) {
    199         set_key_cb(code, 1);
    200       }
    201     }
    202   }
    203 
    204   return 0;
    205 }
    206 
    207 void ev_iterate_available_keys(const std::function<void(int)>& f) {
    208     // Use unsigned long to match ioctl's parameter type.
    209     unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT
    210     unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; // NOLINT
    211 
    212     for (size_t i = 0; i < ev_dev_count; ++i) {
    213         memset(ev_bits, 0, sizeof(ev_bits));
    214         memset(key_bits, 0, sizeof(key_bits));
    215 
    216         // Does this device even have keys?
    217         if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) {
    218             continue;
    219         }
    220         if (!test_bit(EV_KEY, ev_bits)) {
    221             continue;
    222         }
    223 
    224         int rc = ioctl(ev_fdinfo[i].fd, EVIOCGBIT(EV_KEY, KEY_MAX), key_bits);
    225         if (rc == -1) {
    226             continue;
    227         }
    228 
    229         for (int key_code = 0; key_code <= KEY_MAX; ++key_code) {
    230             if (test_bit(key_code, key_bits)) {
    231                 f(key_code);
    232             }
    233         }
    234     }
    235 }
    236 
    237 void ev_iterate_touch_inputs(const std::function<void(int)>& action) {
    238   for (size_t i = 0; i < ev_dev_count; ++i) {
    239     // Use unsigned long to match ioctl's parameter type.
    240     unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)] = {};  // NOLINT
    241     if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) {
    242       continue;
    243     }
    244     if (!test_bit(EV_ABS, ev_bits)) {
    245       continue;
    246     }
    247 
    248     unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)] = {};  // NOLINT
    249     if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(EV_ABS, KEY_MAX), key_bits) == -1) {
    250       continue;
    251     }
    252 
    253     for (int key_code = 0; key_code <= KEY_MAX; ++key_code) {
    254       if (test_bit(key_code, key_bits)) {
    255         action(key_code);
    256       }
    257     }
    258   }
    259 }
    260