diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | rcm-server-main.c | 307 | ||||
-rw-r--r-- | rcm-server-udev.c | 332 | ||||
-rw-r--r-- | rcm-server-udev.h | 9 |
4 files changed, 345 insertions, 307 deletions
@@ -19,8 +19,8 @@ RCM_CFLAGS = ${GENERIC_CFLAGS} ${EXTRA_CFLAGS} $(shell pkg-config --cflags ${RCM RCM_LDFLAGS = ${GENERIC_LDFLAGS} ${EXTRA_LDFLAGS} $(shell pkg-config --libs ${RCM_PACKAGES}) RCM_COMPILE = $(CC) $(RCM_CFLAGS) RCM_LINK = $(CC) $(RCM_CFLAGS) $(RCM_LDFLAGS) -RCM_OBJECTS = rcm-server-main.o rcm-server-keymap.o rcm-server-evdev.o rcm-server-kdb.o shared.o -RCM_HEADERS = rcm-server-main.h rcm-server-keymap.h rcm-server-evdev.h rcm-server-kdb.h utils.h $(COMMON_HEADERS) +RCM_OBJECTS = rcm-server-main.o rcm-server-keymap.o rcm-server-udev.o rcm-server-evdev.o rcm-server-kdb.o shared.o +RCM_HEADERS = rcm-server-main.h rcm-server-keymap.h rcm-server-udev.h rcm-server-evdev.h rcm-server-kdb.h utils.h $(COMMON_HEADERS) RCC_PACKAGES = gtk+-3.0 gmodule-2.0 RCC_CFLAGS = ${GENERIC_CFLAGS} ${EXTRA_CFLAGS} $(shell pkg-config --cflags ${RCC_PACKAGES}) diff --git a/rcm-server-main.c b/rcm-server-main.c index d2f0160..7aadb69 100644 --- a/rcm-server-main.c +++ b/rcm-server-main.c @@ -2,7 +2,6 @@ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> -#include <libudev.h> #include <unistd.h> #include <string.h> #include <systemd/sd-bus.h> @@ -15,6 +14,7 @@ #include "utils.h" #include "shared.h" #include "rcm-server-main.h" +#include "rcm-server-udev.h" #include "rcm-server-keymap.h" #include "rcm-server-evdev.h" #include "rcm-server-kdb.h" @@ -854,308 +854,6 @@ static const sd_bus_vtable device_vtable[] = { SD_BUS_VTABLE_END }; -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); - sd_bus_emit_object_removed(mgr->bus, device->path); - mgr->num_devices--; - break; - } -} - -static int -lirc_read(sd_event_source *s, int fd, uint32_t revents, void *userdata) -{ - struct device *device = userdata; - uint8_t buf[100]; - ssize_t bytes_read; - - if (fd != device->lirc_fd) - fprintf(stderr, "lirc fd mismatch: %i != %i\n", device->lirc_fd, fd); - - if (revents & EPOLLHUP) { - fprintf(stderr, "lirc connection closed!\n"); - close(fd); - device->lirc_fd = -1; - return 0; - } - - if (!(revents & EPOLLIN)) { - fprintf(stderr, "unexpected lirc event: %" PRIu32 "\n", revents); - return 0; - } - - while ((bytes_read = read(fd, buf, sizeof(buf))) > 0) - printf("Read %zi bytes from lirc dev\n", bytes_read); - - return 0; -} - -static int -lirc_setup(struct device *device, const char *path) -{ - if (!device) - return -EINVAL; - - if (device->lirc_fd >= 0) { - printf("Multiple lirc devices!?\n"); - return 0; - } - - device->lirc_fd = open(path, O_RDWR | O_NONBLOCK); - if (device->lirc_fd < 0) { - printf("Failed to open lirc device %s: %s\n", path, strerror(errno)); - return -errno; - } - - if (sd_event_add_io(device->mgr->event, &device->lirc_ev, - device->lirc_fd, EPOLLIN, lirc_read, device) < 0) { - printf("Failed to add event source for lirc device %s: %s\n", - path, strerror(errno)); - close(device->lirc_fd); - device->lirc_fd = -1; - return -errno; - } - - return 0; -} - -static void -add_device(struct manager *mgr, struct udev_device *udev) -{ - const char *name; - const char *str; - char *path; - struct device *device; - struct udev_enumerate *enumerate; - struct udev_list_entry *devices, *dev_list_entry; - int r; - - 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->mgr = mgr; - device->path = path; - device->name = device->path + strlen("/org/gnome/RemoteControlManager/"); - device->evdev_fd = -1; - device->lirc_fd = -1; - device->error = NULL; - device->input_name = NULL; - device->driver_name = NULL; - device->keymap_name = NULL; - device->dev_name = NULL; - - if (keymaps_load(device) < 0) { - fprintf(stderr, "failed to load keymaps: %m\n"); - free(path); - free(device); - return; - } - - enumerate = udev_enumerate_new(mgr->udev); - udev_enumerate_add_match_parent(enumerate, udev); - udev_enumerate_add_match_sysname(enumerate, "event*"); - udev_enumerate_add_match_sysname(enumerate, "lirc*"); - udev_enumerate_scan_devices(enumerate); - devices = udev_enumerate_get_list_entry(enumerate); - - udev_list_entry_foreach(dev_list_entry, devices) { - const char *path; - struct udev_device *udev_dev; - const char *devnode; - const char *subsys; - - path = udev_list_entry_get_name(dev_list_entry); - if (!path) { - printf("Failed to get udev name\n"); - continue; - } - - udev_dev = udev_device_new_from_syspath(mgr->udev, path); - if (!udev_dev) { - printf("Failed to create udev device\n"); - continue; - } - - devnode = udev_device_get_devnode(udev_dev); - if (!devnode) { - printf("Failed to determine udev_dev devnode\n"); - goto next; - } - - subsys = udev_device_get_subsystem(udev_dev); - if (!subsys) { - printf("Failed to determine udev_dev subsystem\n"); - goto next; - } - - if (!strcmp(subsys, "input")) { - r = evdev_setup(device, devnode); - if (r < 0) { - printf("Failed to setup evdev: %s\n", devnode); - device->error = "Error: Failed to setup evdev"; - goto next; - } - - } else if (!strcmp(subsys, "lirc")) { - r = lirc_setup(device, devnode); - if (r < 0) { - printf("Failed to setup lirc: %s\n", devnode); - device->error = "Error: Failed to setup lirc"; - goto next; - } - - } else { - printf("Unknown subsystem, ignored %s\n", devnode); - goto next; - } - -next: - udev_device_unref(udev_dev); - } - udev_enumerate_unref(enumerate); - - 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 if (!strncmp(token, "DEVNAME=", strlen("DEVNAME="))) - device->dev_name = strdup(token + strlen("DEVNAME=")); - else if (!strncmp(token, "MAJOR=", strlen("MAJOR="))) - continue; - else if (!strncmp(token, "MINOR=", strlen("MINOR="))) - continue; - else - printf("Unused uevent: %s\n", token); - } - } - - printf("Adding Device Object\n"); - printf("\tPath : %s\n", udev_device_get_syspath(udev)); - printf("\tNode : %s\n", udev_device_get_devnode(udev)); - printf("\tSubsystem : %s\n", udev_device_get_subsystem(udev)); - printf("\tDevtype : %s\n", udev_device_get_devtype(udev)); - printf("\tAction : %s\n", udev_device_get_action(udev)); - printf("\tName : %s\n", device->name); - printf("\tInput name: %s\n", device->input_name); - printf("\tDriver : %s\n", device->driver_name); - printf("\tKernel map: %s\n", device->keymap_name); - printf("\tDev name : %s\n", device->dev_name); - printf("\tevdev fd : %i\n", device->evdev_fd); - printf("\tLIRC fd : %i\n", device->lirc_fd); - printf("\tDBUS path : %s\n", device->path); - printf("\tProtocols : %s\n", - udev_device_get_sysattr_value(udev, "protocols")); - - list_add(&device->list, &mgr->devices); - mgr->num_devices++; - - sd_bus_emit_object_added(mgr->bus, path); -} - -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) { @@ -1194,8 +892,7 @@ free_manager(struct manager *mgr) { 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); + udev_close(mgr); while (!list_empty(&mgr->devices)) { struct device *dev = list_first_entry(&mgr->devices, typeof(*dev), list); diff --git a/rcm-server-udev.c b/rcm-server-udev.c new file mode 100644 index 0000000..d29b4d9 --- /dev/null +++ b/rcm-server-udev.c @@ -0,0 +1,332 @@ +#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 <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "utils.h" +#include "shared.h" +#include "rcm-server-main.h" +#include "rcm-server-keymap.h" +#include "rcm-server-evdev.h" +#include "rcm-server-udev.h" + +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); + sd_bus_emit_object_removed(mgr->bus, device->path); + mgr->num_devices--; + break; + } +} + +static int +lirc_read(sd_event_source *s, int fd, uint32_t revents, void *userdata) +{ + struct device *device = userdata; + uint8_t buf[100]; + ssize_t bytes_read; + + if (fd != device->lirc_fd) + fprintf(stderr, "lirc fd mismatch: %i != %i\n", device->lirc_fd, fd); + + if (revents & EPOLLHUP) { + fprintf(stderr, "lirc connection closed!\n"); + close(fd); + device->lirc_fd = -1; + return 0; + } + + if (!(revents & EPOLLIN)) { + fprintf(stderr, "unexpected lirc event: %" PRIu32 "\n", revents); + return 0; + } + + while ((bytes_read = read(fd, buf, sizeof(buf))) > 0) + printf("Read %zi bytes from lirc dev\n", bytes_read); + + return 0; +} + +static int +lirc_setup(struct device *device, const char *path) +{ + if (!device) + return -EINVAL; + + if (device->lirc_fd >= 0) { + printf("Multiple lirc devices!?\n"); + return 0; + } + + device->lirc_fd = open(path, O_RDWR | O_NONBLOCK); + if (device->lirc_fd < 0) { + printf("Failed to open lirc device %s: %s\n", path, strerror(errno)); + return -errno; + } + + if (sd_event_add_io(device->mgr->event, &device->lirc_ev, + device->lirc_fd, EPOLLIN, lirc_read, device) < 0) { + printf("Failed to add event source for lirc device %s: %s\n", + path, strerror(errno)); + close(device->lirc_fd); + device->lirc_fd = -1; + return -errno; + } + + return 0; +} + +static void +add_device(struct manager *mgr, struct udev_device *udev) +{ + const char *name; + const char *str; + char *path; + struct device *device; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + int r; + + 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->mgr = mgr; + device->path = path; + device->name = device->path + strlen("/org/gnome/RemoteControlManager/"); + device->evdev_fd = -1; + device->lirc_fd = -1; + device->error = NULL; + device->input_name = NULL; + device->driver_name = NULL; + device->keymap_name = NULL; + device->dev_name = NULL; + + if (keymaps_load(device) < 0) { + fprintf(stderr, "failed to load keymaps: %m\n"); + free(path); + free(device); + return; + } + + enumerate = udev_enumerate_new(mgr->udev); + udev_enumerate_add_match_parent(enumerate, udev); + udev_enumerate_add_match_sysname(enumerate, "event*"); + udev_enumerate_add_match_sysname(enumerate, "lirc*"); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + + udev_list_entry_foreach(dev_list_entry, devices) { + const char *path; + struct udev_device *udev_dev; + const char *devnode; + const char *subsys; + + path = udev_list_entry_get_name(dev_list_entry); + if (!path) { + printf("Failed to get udev name\n"); + continue; + } + + udev_dev = udev_device_new_from_syspath(mgr->udev, path); + if (!udev_dev) { + printf("Failed to create udev device\n"); + continue; + } + + devnode = udev_device_get_devnode(udev_dev); + if (!devnode) { + printf("Failed to determine udev_dev devnode\n"); + goto next; + } + + subsys = udev_device_get_subsystem(udev_dev); + if (!subsys) { + printf("Failed to determine udev_dev subsystem\n"); + goto next; + } + + if (!strcmp(subsys, "input")) { + r = evdev_setup(device, devnode); + if (r < 0) { + printf("Failed to setup evdev: %s\n", devnode); + device->error = "Error: Failed to setup evdev"; + goto next; + } + + } else if (!strcmp(subsys, "lirc")) { + r = lirc_setup(device, devnode); + if (r < 0) { + printf("Failed to setup lirc: %s\n", devnode); + device->error = "Error: Failed to setup lirc"; + goto next; + } + + } else { + printf("Unknown subsystem, ignored %s\n", devnode); + goto next; + } + +next: + udev_device_unref(udev_dev); + } + udev_enumerate_unref(enumerate); + + 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 if (!strncmp(token, "DEVNAME=", strlen("DEVNAME="))) + device->dev_name = strdup(token + strlen("DEVNAME=")); + else if (!strncmp(token, "MAJOR=", strlen("MAJOR="))) + continue; + else if (!strncmp(token, "MINOR=", strlen("MINOR="))) + continue; + else + printf("Unused uevent: %s\n", token); + } + } + + printf("Adding Device Object\n"); + printf("\tPath : %s\n", udev_device_get_syspath(udev)); + printf("\tNode : %s\n", udev_device_get_devnode(udev)); + printf("\tSubsystem : %s\n", udev_device_get_subsystem(udev)); + printf("\tDevtype : %s\n", udev_device_get_devtype(udev)); + printf("\tAction : %s\n", udev_device_get_action(udev)); + printf("\tName : %s\n", device->name); + printf("\tInput name: %s\n", device->input_name); + printf("\tDriver : %s\n", device->driver_name); + printf("\tKernel map: %s\n", device->keymap_name); + printf("\tDev name : %s\n", device->dev_name); + printf("\tevdev fd : %i\n", device->evdev_fd); + printf("\tLIRC fd : %i\n", device->lirc_fd); + printf("\tDBUS path : %s\n", device->path); + printf("\tProtocols : %s\n", + udev_device_get_sysattr_value(udev, "protocols")); + + list_add(&device->list, &mgr->devices); + mgr->num_devices++; + + sd_bus_emit_object_added(mgr->bus, path); +} + +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; +} + +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); +} + +void +udev_close(struct manager *mgr) +{ + if (!mgr) + return; + + udev_monitor_unref(mgr->udev_mon); + udev_unref(mgr->udev); +} + diff --git a/rcm-server-udev.h b/rcm-server-udev.h new file mode 100644 index 0000000..58ccd1b --- /dev/null +++ b/rcm-server-udev.h @@ -0,0 +1,9 @@ +#ifndef foorcmserverudevhfoo +#define foorcmserverudevhfoo + +int udev_setup(struct manager *mgr); + +void udev_close(struct manager *mgr); + +#endif + |