summaryrefslogtreecommitdiff
path: root/rcm-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'rcm-server.c')
-rw-r--r--rcm-server.c563
1 files changed, 0 insertions, 563 deletions
diff --git a/rcm-server.c b/rcm-server.c
deleted file mode 100644
index 11223b1..0000000
--- a/rcm-server.c
+++ /dev/null
@@ -1,563 +0,0 @@
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <libudev.h>
-#include <unistd.h>
-#include <string.h>
-#include <systemd/sd-bus.h>
-#include <errno.h>
-
-#include "utils.h"
-#include "rcm-server.h"
-#include "rcm-server-keymap.h"
-
-static int
-method_echostring(sd_bus_message *m, void *userdata, sd_bus_error *error)
-{
- const char *msg;
- int r;
-
- r = sd_bus_message_read(m, "s", &msg);
- if (r < 0) {
- fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r));
- return sd_bus_error_set_errno(error, r);
- }
-
- return sd_bus_reply_method_return(m, "s", msg);
-}
-
-static struct device *
-find_device_by_path(struct manager *mgr, const char *path)
-{
- struct device *dev;
-
- list_for_each_entry(dev, &mgr->devices, list)
- if (!strcmp(dev->path, path))
- return dev;
-
- return NULL;
-}
-
-static int
-property_get_driver_name(sd_bus *bus, const char *path, const char *interface,
- const char *property, sd_bus_message *reply, void *userdata,
- sd_bus_error *error)
-{
- struct manager *mgr = userdata;
- struct device *dev;
-
- dev = find_device_by_path(mgr, path);
- if (!dev) {
- sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device");
- return -EINVAL;
- }
-
- if (!strcmp(property, "DriverName"))
- return sd_bus_message_append(reply, "s", dev->driver_name);
- else if (!strcmp(property, "KernelKeymapName"))
- return sd_bus_message_append(reply, "s", dev->keymap_name);
-
- sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidProperty", "Sorry, invalid property");
- return -EINVAL;
-}
-
-
-static int
-method_listkeymaps(sd_bus_message *m, void *userdata, sd_bus_error *error)
-{
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- struct manager *mgr = userdata;
- struct device *dev;
- struct keymap *keymap;
- int r;
-
- dev = find_device_by_path(mgr, sd_bus_message_get_path(m));
- if (!dev) {
- sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device");
- return -EINVAL;
- }
-
- r = sd_bus_message_new_method_return(m, &reply);
- if (r < 0)
- goto out;
-
- r = sd_bus_message_open_container(reply, 'a', "s");
- if (r < 0)
- goto out;
-
- list_for_each_entry(keymap, &dev->keymaps, list) {
- printf("Listing keymaps for %s: %s\n", dev->name, keymap->name);
- r = sd_bus_message_append(reply, "s", keymap->name);
- if (r < 0)
- goto out;
- }
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- goto out;
-
- r = sd_bus_send(NULL, reply, NULL);
- if (r < 0)
- goto out;
-
- return 1;
-
-out:
- return sd_bus_error_set_errno(error, r);
-}
-
-static int
-method_getkeymap(sd_bus_message *m, void *userdata, sd_bus_error *error)
-{
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- struct manager *mgr = userdata;
- struct device *dev;
- struct keymap *keymap;
- const char *name;
- int r;
- unsigned i;
-
- dev = find_device_by_path(mgr, sd_bus_message_get_path(m));
- if (!dev) {
- sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device");
- return -EINVAL;
- }
-
- r = sd_bus_message_read(m, "s", &name);
- if (r < 0) {
- fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r));
- return r;
- }
-
- keymap = find_keymap_by_name(dev, name);
- if (!keymap) {
- sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidKeymap", "Sorry, unknown keymap");
- return -EINVAL;
- }
-
- r = sd_bus_message_new_method_return(m, &reply);
- if (r < 0)
- goto out;
-
- r = sd_bus_message_append(reply, "q", keymap->cols);
- if (r < 0)
- goto out;
-
- r = sd_bus_message_append(reply, "q", keymap->rows);
- if (r < 0)
- goto out;
-
- r = sd_bus_message_open_container(reply, 'a', "a{sv}");
- if (r < 0)
- goto out;
-
- for (i = 0; i < (keymap->rows * keymap->cols); i++) {
- r = sd_bus_message_append(reply, "a{sv}", 2,
- "name", "s", keymap->layout[i]->name,
- "keycode", "s", keymap->layout[i]->value);
- if (r < 0)
- goto out;
- }
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- goto out;
-
- r = sd_bus_send(NULL, reply, NULL);
- if (r < 0)
- goto out;
-
- return 1;
-
-out:
- return sd_bus_error_set_errno(error, r);
-}
-
-static const sd_bus_vtable device_vtable[] = {
- SD_BUS_VTABLE_START(0),
- SD_BUS_PROPERTY("DriverName", "s", property_get_driver_name, 0, 0),
- SD_BUS_PROPERTY("KernelKeymapName", "s", property_get_driver_name, 0, 0),
- SD_BUS_METHOD("EchoString", "s", "s", method_echostring, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ListKeymaps", NULL, "as", method_listkeymaps, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetKeymap", "s", "qqaa{sv}", method_getkeymap, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_VTABLE_END
-};
-
-static int
-my_bus_emit_object_changed(sd_bus *bus, const char *path, bool added)
-{
- int r;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-
- printf("Sending signal %s for path %s\n",
- added ? "InterfacesAdded" : "InterfacesRemoved",
- path);
-
- r = sd_bus_message_new_signal(bus, &m, "/org/gnome/RemoteControlManager",
- "org.freedesktop.DBus.ObjectManager",
- added ? "InterfacesAdded" : "InterfacesRemoved");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append_basic(m, 'o', path);
- if (r < 0)
- return r;
-
- if (added) {
- r = sd_bus_message_open_container(m, 'a', "{sa{sv}}");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(m, "{sa{sv}}", "org.gnome.RemoteControlManager.Device", 0);
- if (r < 0)
- return r;
- } else {
- r = sd_bus_message_open_container(m, 'a', "s");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(m, "s", "org.gnome.RemoteControlManager.Device");
- if (r < 0)
- return r;
- }
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
-
- r = sd_bus_send(bus, m, NULL);
- return r;
-}
-
-static void
-remove_device(struct manager *mgr, struct udev_device *udev)
-{
- const char *name;
- struct device *device;
-
- name = udev_device_get_sysname(udev);
- printf("Asked to remove device %s\n", name);
-
- list_for_each_entry(device, &mgr->devices, list) {
- if (strcmp(device->name, name))
- continue;
- list_del(&device->list);
- my_bus_emit_object_changed(mgr->bus, device->path, false);
- mgr->num_devices--;
- break;
- }
-}
-
-static void
-add_device(struct manager *mgr, struct udev_device *udev)
-{
- const char *name;
- const char *str;
- char *path;
- struct device *device;
-
- name = udev_device_get_sysname(udev);
- if (asprintf(&path, "/org/gnome/RemoteControlManager/%s", name) < 0) {
- fprintf(stderr, "asprintf failed: %m\n");
- return;
- }
-
- device = malloc(sizeof(*device));
- if (!device) {
- fprintf(stderr, "malloc failed: %m\n");
- free(path);
- return;
- }
-
- list_init(&device->keymaps);
- device->path = path;
- device->name = device->path + strlen("/org/gnome/RemoteControlManager/");
-
- if (keymaps_load(device) < 0) {
- fprintf(stderr, "failed to load keymaps: %m\n");
- free(path);
- free(device);
- }
-
- str = udev_device_get_sysattr_value(udev, "uevent");
- if (str) {
- char tmp[strlen(str) + 1];
- char *token;
-
- strcpy(tmp, str);
-
- for (token = strtok(tmp, "\n"); token; token = strtok(NULL, "\n")) {
- if (!strncmp(token, "DRV_NAME=", strlen("DRV_NAME=")))
- device->driver_name = strdup(token + strlen("DRV_NAME="));
- else if (!strncmp(token, "NAME=", strlen("NAME=")))
- device->keymap_name = strdup(token + strlen("NAME="));
- else
- printf("Unused uevent: %s\n", token);
- }
- }
-
- printf("Adding Device Object\n");
- printf(" Path : %s\n", udev_device_get_syspath(udev));
- printf(" Node : %s\n", udev_device_get_devnode(udev));
- printf(" Subsystem : %s\n", udev_device_get_subsystem(udev));
- printf(" Devtype : %s\n", udev_device_get_devtype(udev));
- printf(" Action : %s\n", udev_device_get_action(udev));
- printf(" Protocols : %s\n",
- udev_device_get_sysattr_value(udev, "protocols"));
- printf(" Uevent : %s\n",
- udev_device_get_sysattr_value(udev, "uevent"));
-
- list_add(&device->list, &mgr->devices);
- mgr->num_devices++;
-
- my_bus_emit_object_changed(mgr->bus, path, true);
-}
-
-static int
-udev_read(sd_event_source *s, int fd, uint32_t revents, void *userdata)
-{
- struct manager *mgr = userdata;
- struct udev_device *dev;
-
- if (revents & EPOLLHUP) {
- fprintf(stderr, "udev connection closed!\n");
- return 0;
- }
-
- if (!(revents & EPOLLIN)) {
- fprintf(stderr, "unexpected udev event: %" PRIu32 "\n", revents);
- return 0;
- }
-
- while ((dev = udev_monitor_receive_device(mgr->udev_mon))) {
- printf("Read device: %s\n", udev_device_get_syspath(dev));
- if (!strcmp(udev_device_get_action(dev), "add"))
- add_device(mgr, dev);
- else if (!strcmp(udev_device_get_action(dev), "remove"))
- remove_device(mgr, dev);
- udev_device_unref(dev);
- }
-
- return 1;
-}
-
-static int
-udev_setup(struct manager *mgr)
-{
- struct udev_enumerate *enumerate;
- struct udev_list_entry *devices, *dev_list_entry;
- struct udev_device *dev;
-
- mgr->udev = udev_new();
- if (!mgr->udev)
- return -ENOMEM;
-
- mgr->udev_mon = udev_monitor_new_from_netlink(mgr->udev, "udev");
- udev_monitor_filter_add_match_subsystem_devtype(mgr->udev_mon, "rc", NULL);
- udev_monitor_enable_receiving(mgr->udev_mon);
-
- enumerate = udev_enumerate_new(mgr->udev);
- udev_enumerate_add_match_subsystem(enumerate, "rc");
- udev_enumerate_scan_devices(enumerate);
- devices = udev_enumerate_get_list_entry(enumerate);
-
- udev_list_entry_foreach(dev_list_entry, devices) {
- const char *path;
-
- path = udev_list_entry_get_name(dev_list_entry);
- if (!path) {
- printf("Failed to get udev name\n");
- continue;
- }
-
- dev = udev_device_new_from_syspath(mgr->udev, path);
- if (!dev) {
- printf("Failed to create udev device\n");
- continue;
- }
-
- add_device(mgr, dev);
-
- udev_device_unref(dev);
- }
- udev_enumerate_unref(enumerate);
-
- return sd_event_add_io(mgr->event, &mgr->udev_ev,
- udev_monitor_get_fd(mgr->udev_mon),
- EPOLLIN, udev_read, mgr);
-}
-
-static int
-enumerator(sd_bus *bus, const char *path, void *userdata, char ***retnodes, sd_bus_error *error)
-{
- _cleanup_strv_free_ char **nodes = NULL;
- struct manager *mgr = userdata;
- struct device *device;
- int i = 0;
-
- if (!path)
- return 0;
-
- nodes = zmalloc((mgr->num_devices + 1) * sizeof(char *));
- if (!nodes)
- return -ENOMEM;
-
- list_for_each_entry(device, &mgr->devices, list) {
- nodes[i] = strdup(device->path);
- if (!nodes[i])
- return -ENOMEM;
- i++;
- }
-
- nodes[i++] = NULL;
- *retnodes = nodes;
- nodes = NULL;
-
- return 1;
-}
-
-static void
-free_manager(struct manager *mgr) {
- if (!mgr)
- return;
-
- sd_event_source_unref(mgr->udev_ev);
- sd_bus_detach_event(mgr->bus);
- sd_event_unref(mgr->event);
- udev_monitor_unref(mgr->udev_mon);
- udev_unref(mgr->udev);
-
- while (!list_empty(&mgr->devices)) {
- struct device *dev = list_first_entry(&mgr->devices, typeof(*dev), list);
- list_del(&dev->list);
- free(dev->path);
- free(dev->driver_name);
- free(dev->keymap_name);
-
- while (!list_empty(&dev->keymaps)) {
- struct keymap *keymap = list_first_entry(&dev->keymaps, typeof(*keymap), list);
- list_del(&keymap->list);
- free(keymap->name);
- free(keymap);
- }
-
- free(dev);
- }
- free(mgr);
-}
-
-static int
-block_signals(void)
-{
- sigset_t sigset;
- int r;
-
- r = sigemptyset(&sigset);
- if (r < 0)
- return r;
-
- r = sigaddset(&sigset, SIGINT);
- if (r < 0)
- return r;
-
- r = sigaddset(&sigset, SIGTERM);
- if (r < 0)
- return r;
-
- return sigprocmask(SIG_BLOCK, &sigset, NULL);
-}
-
-int
-main(int argc, char **argv)
-{
- int r;
- struct manager *mgr;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
- _cleanup_bus_slot_unref_ struct sd_bus_slot *vtable_slot = NULL;
- _cleanup_bus_slot_unref_ struct sd_bus_slot *enumerator_slot = NULL;
- _cleanup_bus_slot_unref_ struct sd_bus_slot *objm_slot = NULL;
- _cleanup_event_source_unref_ sd_event_source *sigint_ev = NULL;
- _cleanup_event_source_unref_ sd_event_source *sigterm_ev = NULL;
-
- mgr = zmalloc(sizeof(*mgr));
- if (!mgr) {
- fprintf(stderr, "Failed to allocate memory: %m\n");
- goto finish;
- }
- list_init(&mgr->devices);
-
- r = sd_bus_open_user(&bus);
- if (r < 0) {
- fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r));
- goto finish;
- }
- mgr->bus = bus;
-
- r = sd_bus_request_name(mgr->bus, "org.gnome.RemoteControlManager", 0);
- if (r < 0) {
- fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-r));
- goto finish;
- }
-
- r = sd_bus_add_fallback_vtable(mgr->bus, &vtable_slot, "/org/gnome/RemoteControlManager",
- "org.gnome.RemoteControlManager.Device",
- device_vtable, NULL, mgr);
- if (r < 0) {
- fprintf(stderr, "Failed to add vtable: %s\n", strerror(-r));
- goto finish;
- }
-
- r = sd_bus_add_node_enumerator(mgr->bus, &enumerator_slot, "/org/gnome/RemoteControlManager", enumerator, mgr);
- if (r < 0) {
- fprintf(stderr, "Failed to create node enumerator: %s\n", strerror(-r));
- goto finish;
- }
-
- r = sd_bus_add_object_manager(mgr->bus, &objm_slot, "/org/gnome/RemoteControlManager");
- if (r < 0) {
- fprintf(stderr, "Failed to create object manager: %s\n", strerror(-r));
- goto finish;
- }
-
- r = sd_event_default(&mgr->event);
- if (r < 0) {
- fprintf(stderr, "Failed to create sd_event: %s\n", strerror(-r));
- goto finish;
- }
-
- r = sd_bus_attach_event(mgr->bus, mgr->event, 0);
- if (r < 0) {
- fprintf(stderr, "Failed to attach bus to event loop: %s\n", strerror(-r));
- goto finish;
- }
-
- r = udev_setup(mgr);
- if (r < 0) {
- fprintf(stderr, "Failed to setup udev monitoring: %s\n", strerror(-r));
- goto finish;
- }
-
- r = block_signals();
- if (r < 0) {
- fprintf(stderr, "Failed to block signals: %m\n");
- goto finish;
- }
-
- sd_event_add_signal(mgr->event, &sigint_ev, SIGINT, NULL, NULL);
- sd_event_add_signal(mgr->event, &sigterm_ev, SIGTERM, NULL, NULL);
-
- r = sd_event_loop(mgr->event);
- if (r < 0) {
- fprintf(stderr, "Event loop failed: %s\n", strerror(-r));
- goto finish;
- }
-
- sd_event_get_exit_code(mgr->event, &r);
-
-finish:
- free_manager(mgr);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-