diff options
Diffstat (limited to 'firmware/target/hosted/button-devinput.c')
-rw-r--r-- | firmware/target/hosted/button-devinput.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/firmware/target/hosted/button-devinput.c b/firmware/target/hosted/button-devinput.c new file mode 100644 index 0000000000..8c469b8308 --- /dev/null +++ b/firmware/target/hosted/button-devinput.c @@ -0,0 +1,130 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2017 Marcin Bukat + * Copyright (C) 2020 Solomon Peachy + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include <poll.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <linux/input.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +#include "kernel.h" +#include "sysfs.h" +#include "button.h" +#include "panic.h" + +#define NR_POLL_DESC 4 + +static int num_devices = 0; +static struct pollfd poll_fds[NR_POLL_DESC]; + +void button_init_device(void) +{ + const char * const input_devs[NR_POLL_DESC] = { + "/dev/input/event0", + "/dev/input/event1", + "/dev/input/event2", + "/dev/input/event3", + }; + + for(int i = 0; i < NR_POLL_DESC; i++) + { + int fd = open(input_devs[i], O_RDONLY | O_CLOEXEC); + + if(fd >= 0) + { + poll_fds[num_devices].fd = fd; + poll_fds[num_devices].events = POLLIN; + poll_fds[num_devices].revents = 0; + num_devices++; + } + } +} + +void button_close_device(void) +{ + /* close descriptors */ + for(int i = 0; i < num_devices; i++) + { + close(poll_fds[i].fd); + } + num_devices = 0; +} + +int button_read_device(void) +{ + static int button_bitmap = 0; + struct input_event event; + +#if defined(BUTTON_SCROLL_BACK) + // FIXME TODO: Make this work via HAVE_SCROLL_WHEEL instead + + /* Wheel gives us press+release back to back, clear them after time elapses */ + static long last_tick = 0; + if (button_bitmap & (BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD) && + current_tick - last_tick >= 2) + { + button_bitmap &= ~(BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD); + } +#endif + + /* check if there are any events pending and process them */ + while(poll(poll_fds, num_devices, 0)) + { + for(int i = 0; i < num_devices; i++) + { + /* read only if non-blocking */ + if(poll_fds[i].revents & POLLIN) + { + int size = read(poll_fds[i].fd, &event, sizeof(event)); + if(size == (int)sizeof(event)) + { + int keycode = event.code; + /* event.value == 0x10000 means press + * event.value == 0 means release + */ + bool press = event.value ? true : false; + + /* map linux event code to rockbox button bitmap */ + if(press) + { + button_bitmap |= button_map(keycode); + } + else + { +#if defined(BUTTON_SCROLL_BACK) + /* Wheel gives us press+release back to back; ignore the release */ + int bmap = button_map(keycode) & ~(BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD); + button_bitmap &= ~bmap; +#else + button_bitmap &= ~button_map(keycode); +#endif + } + } + } + } + } + + return button_bitmap; +} |