diff options
Diffstat (limited to 'rcm-server-main.c')
-rw-r--r-- | rcm-server-main.c | 135 |
1 files changed, 127 insertions, 8 deletions
diff --git a/rcm-server-main.c b/rcm-server-main.c index 5d9cb20..294510c 100644 --- a/rcm-server-main.c +++ b/rcm-server-main.c @@ -7,9 +7,14 @@ #include <string.h> #include <systemd/sd-bus.h> #include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <linux/input.h> #include "utils.h" #include "shared.h" +#include "linux-input-keycodes.h" #include "rcm-server-main.h" #include "rcm-server-keymap.h" @@ -692,6 +697,96 @@ remove_device(struct manager *mgr, struct udev_device *udev) } } +static int +evdev_read(sd_event_source *s, int fd, uint32_t revents, void *userdata) +{ + struct device *device = userdata; + struct input_event ev; + static const char *keycode_str = NULL; + static uint32_t keycode = KEY_RESERVED; + static uint32_t scancode; + static bool scancode_recv = false; + static bool pressed = false; + unsigned i; + + if (fd != device->evdev_fd) + fprintf(stderr, "evdev fd mismatch: %i != %i\n", device->evdev_fd, fd); + + if (revents & EPOLLHUP) { + fprintf(stderr, "evdev connection closed!\n"); + close(fd); + device->evdev_fd = -1; + return 0; + } + + if (!(revents & EPOLLIN)) { + fprintf(stderr, "unexpected evdev event: %" PRIu32 "\n", revents); + return 0; + } + + while (read(fd, &ev, sizeof(ev)) == sizeof(ev)) { + switch (ev.type) { + case EV_KEY: + if (keycode != KEY_RESERVED) + printf("Reading from evdev - multiple keycodes?\n"); + + for (i = 0; linux_input_keycodes[i].name; i++) { + if (linux_input_keycodes[i].value == ev.code) + break; + } + + if (!linux_input_keycodes[i].name) { + printf("evdev - unknown keycode (%u)\n", ev.code); + break; + } + + keycode_str = linux_input_keycodes[i].name; + keycode = ev.code; + pressed = ev.value ? true : false; + break; + + case EV_MSC: + if (ev.code == MSC_SCAN) { + if (scancode_recv) + printf("Reading from evdev - multiple scancodes?\n"); + scancode_recv = true; + scancode = ev.value; + } + break; + + case EV_SYN: + if (keycode != KEY_RESERVED || scancode_recv) { + printf("evdev event -"); + if (keycode != KEY_RESERVED) + printf(" keycode %s (%u) %s", + keycode_str, keycode, + pressed ? "pressed" : "released"); + if (scancode_recv) + printf(" scancode 0x%08x", scancode); + printf("\n"); + + if (keycode != KEY_RESERVED) + sd_bus_emit_signal(device->mgr->bus, + device->path, + "org.gnome.RemoteControlManager.Device", + pressed ? "KeyPressed" : "KeyReleased", + "s", keycode_str); + } + + keycode = KEY_RESERVED; + keycode_str = NULL; + scancode_recv = false; + pressed = false; + break; + + default: + break; + } + } + + return 0; +} + static void add_device(struct manager *mgr, struct udev_device *udev) { @@ -717,9 +812,10 @@ add_device(struct manager *mgr, struct udev_device *udev) } list_init(&device->keymaps); + device->mgr = mgr; device->path = path; device->name = device->path + strlen("/org/gnome/RemoteControlManager/"); - device->devnode = NULL; + device->evdev_fd = -1; if (keymaps_load(device) < 0) { fprintf(stderr, "failed to load keymaps: %m\n"); @@ -751,12 +847,34 @@ add_device(struct manager *mgr, struct udev_device *udev) } devnode = udev_device_get_devnode(evdev); - if (devnode && !device->devnode) { - device->devnode = strdup(devnode); - if (!device->devnode) - printf("Failed to strdup devnode\n"); - else - printf("Devnode is %s\n", device->devnode); + if (!devnode) { + printf("Failed to determine evdev devnode\n"); + udev_device_unref(evdev); + continue; + } + + if (device->evdev_fd >= 0) { + printf("Multiple evdev devices!?\n"); + udev_device_unref(evdev); + continue; + } + + device->evdev_fd = open(devnode, O_RDONLY | O_NONBLOCK); + if (device->evdev_fd < 0) { + printf("Failed to open evdev device %s: %s\n", + devnode, strerror(errno)); + udev_device_unref(evdev); + continue; + } + + if (sd_event_add_io(mgr->event, &device->evdev_ev, + device->evdev_fd, EPOLLIN, evdev_read, device) < 0) { + printf("Failed to add event source for evdev device %s: %s\n", + devnode, strerror(errno)); + close(device->evdev_fd); + device->evdev_fd = -1; + udev_device_unref(evdev); + continue; } udev_device_unref(evdev); @@ -788,7 +906,8 @@ add_device(struct manager *mgr, struct udev_device *udev) printf("\tAction : %s\n", udev_device_get_action(udev)); printf("\tDriver : %s\n", device->driver_name); printf("\tKernel map: %s\n", device->keymap_name); - printf("\tDevnode : %s\n", device->devnode); + printf("\tDevnode fd: %i\n", device->evdev_fd); + printf("\tDBUS path : %s\n", device->path); printf("\tProtocols : %s\n", udev_device_get_sysattr_value(udev, "protocols")); |