summaryrefslogtreecommitdiff
path: root/rcm-server-main.c
diff options
context:
space:
mode:
Diffstat (limited to 'rcm-server-main.c')
-rw-r--r--rcm-server-main.c135
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"));