diff options
author | David Härdeman <david@hardeman.nu> | 2017-04-18 23:56:15 +0200 |
---|---|---|
committer | David Härdeman <david@hardeman.nu> | 2017-04-18 23:56:15 +0200 |
commit | 84bd8a887a3b8ec35fd4701a7b93f2ac166ca393 (patch) | |
tree | 897a9ac160f82823097bc515b5fd61da7d9ab1b2 | |
parent | 927f0751fc8be8a71c2d8b255522259d01a7fcef (diff) |
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | rcm-server-main.c | 3 | ||||
-rw-r--r-- | rcm-server-main.h | 3 | ||||
-rw-r--r-- | rcm-server-rcdev.c | 279 | ||||
-rw-r--r-- | rcm-server-rcdev.h | 13 | ||||
-rw-r--r-- | rcm-server-udev.c | 84 | ||||
-rw-r--r-- | rcm-server-udev.h | 2 |
7 files changed, 324 insertions, 68 deletions
@@ -19,8 +19,12 @@ 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-udev.o rcm-server-lirc.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-lirc.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-rcdev.o rcm-server-lirc.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-rcdev.h rcm-server-lirc.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 5cb5ebe..31bfdb6 100644 --- a/rcm-server-main.c +++ b/rcm-server-main.c @@ -18,6 +18,7 @@ #include "rcm-server-keymap.h" #include "rcm-server-evdev.h" #include "rcm-server-lirc.h" +#include "rcm-server-rcdev.h" #include "rcm-server-kdb.h" static struct rc_device * @@ -882,7 +883,7 @@ free_manager(struct manager *mgr) { while (!list_empty(&mgr->rc_devs)) { struct rc_device *rcdev = list_first_entry(&mgr->rc_devs, typeof(*rcdev), list); - rc_device_free(rcdev); + rcdev_free(rcdev); } free(mgr); } diff --git a/rcm-server-main.h b/rcm-server-main.h index 79d9b72..63b3439 100644 --- a/rcm-server-main.h +++ b/rcm-server-main.h @@ -7,8 +7,9 @@ struct rc_device { char *input_name; char *driver_name; char *keymap_name; - char *dev_name; char *error; + int rcdev_fd; + sd_event_source *rcdev_ev; int lirc_fd; sd_event_source *lirc_ev; int evdev_fd; diff --git a/rcm-server-rcdev.c b/rcm-server-rcdev.c new file mode 100644 index 0000000..82fa8ed --- /dev/null +++ b/rcm-server-rcdev.c @@ -0,0 +1,279 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdbool.h> +#include <stdint.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <string.h> +#include <errno.h> + +#include "utils.h" +#include "shared.h" +#include "rcm-server-main.h" +#include "rcm-server-keymap.h" +#include "rcm-server-lirc.h" +#include "rcm-server-evdev.h" +#include "rcm-server-rcdev.h" + +struct rc_event { + uint16_t type; + uint16_t code; + uint32_t val; +} __attribute__((packed)); + +/* rc_event.type value */ +#define RC_DEBUG 0x0 +#define RC_CORE 0x1 +#define RC_KEY 0x2 +#define RC_IR 0x3 + +/* RC_CORE codes */ +#define RC_CORE_DROPPED 0x0 + +/* RC_KEY codes */ +#define RC_KEY_REPEAT 0x0 +#define RC_KEY_PROTOCOL 0x1 +#define RC_KEY_SCANCODE 0x2 +#define RC_KEY_SCANCODE_PART 0x3 +#define RC_KEY_TOGGLE 0x4 + +/* RC_IR codes */ +#define RC_IR_SPACE 0x0 +#define RC_IR_PULSE 0x1 +#define RC_IR_START 0x2 +#define RC_IR_STOP 0x3 +#define RC_IR_RESET 0x4 +#define RC_IR_CARRIER 0x5 +#define RC_IR_DUTY_CYCLE 0x6 + +static int +rcdev_read(sd_event_source *s, int fd, uint32_t revents, void *userdata) +{ + struct rc_device *rcdev = userdata; + + if (fd != rcdev->rcdev_fd) + fprintf(stderr, "rcdev fd mismatch: %i != %i\n", rcdev->rcdev_fd, fd); + + if (revents & EPOLLHUP) { + fprintf(stderr, "rcdev connection closed!\n"); + rcdev_close(rcdev); + return 0; + } + + if (!(revents & EPOLLIN)) { + fprintf(stderr, "unexpected rcdev event: %" PRIu32 "\n", revents); + return 0; + } + + while (true) { + struct rc_event ev; + ssize_t r; + + r = read(rcdev->rcdev_fd, &ev, sizeof(ev)); + if (r < 0) { + fprintf(stderr, "rcdev read failed: %s\n", strerror(errno)); + break; + } + + if (r != sizeof(ev)) { + fprintf(stderr, "rcdev read failed, got %zi bytes, expected %zu\n", r, sizeof(ev)); + break; + } + + printf("rcdev event - type "); + switch (ev.type) { + case RC_DEBUG: + printf("RC_DEBUG; code 0x%0" PRIx16 "; val 0x%0" PRIx32 "\n", + ev.code, ev.val); + break; + + case RC_CORE: + printf("RC_CORE; code "); + if (ev.code == RC_CORE_DROPPED) + printf("RC_CORE_DROPPED"); + else + printf("UNKNOWN (0x%0" PRIx16 ")", ev.code); + printf("; val 0x%0" PRIx32 "\n", ev.val); + break; + + case RC_KEY: + printf("RC_KEY; code "); + switch (ev.code) { + case RC_KEY_REPEAT: + printf("RC_KEY_REPEAT"); + break; + case RC_KEY_PROTOCOL: + printf("RC_KEY_PROTOCOL"); + break; + case RC_KEY_SCANCODE: + printf("RC_KEY_SCANCODE"); + break; + case RC_KEY_SCANCODE_PART: + printf("RC_KEY_SCANCODE_PART"); + break; + case RC_KEY_TOGGLE: + printf("RC_KEY_TOGGLE"); + break; + default: + printf("UNKNOWN (0x%0" PRIx16 ")", ev.code); + break; + } + printf("; val 0x%0" PRIx32 "\n", ev.val); + break; + + case RC_IR: + printf("RC_IR; code "); + switch (ev.code) { + case RC_IR_SPACE: + printf("RC_IR_SPACE"); + break; + case RC_IR_PULSE: + printf("RC_IR_PULSE"); + break; + case RC_IR_START: + printf("RC_IR_START"); + break; + case RC_IR_STOP: + printf("RC_IR_STOP"); + break; + case RC_IR_RESET: + printf("RC_IR_RESET"); + break; + case RC_IR_CARRIER: + printf("RC_IR_CARRIER"); + break; + case RC_IR_DUTY_CYCLE: + printf("RC_IR_DUTY_CYCLE"); + break; + default: + printf("UNKNOWN (0x%0" PRIx16 ")", ev.code); + break; + } + printf("; val 0x%0" PRIx32 "\n", ev.val); + break; + + default: + printf("type UNKNOWN (0x%0" PRIx16 "); code 0x%0" PRIx16 "; val 0x%0" PRIx32 "\n", + ev.type, ev.code, ev.val); + break; + } + } + + return 0; +} + +struct rc_device * +rcdev_create(struct manager *mgr, const char *name) +{ + struct rc_device *rcdev; + + if (!name) + return NULL; + + rcdev = malloc(sizeof(*rcdev)); + if (!rcdev) { + fprintf(stderr, "malloc failed: %m\n"); + return NULL; + } + + if (asprintf(&rcdev->path, "/org/gnome/RemoteControlManager/%s", name) < 0) { + fprintf(stderr, "asprintf failed: %m\n"); + free(rcdev); + return NULL; + } + + list_init(&rcdev->keymaps); + rcdev->mgr = mgr; + rcdev->name = rcdev->path + strlen("/org/gnome/RemoteControlManager/"); + rcdev->rcdev_fd = -1; + rcdev->evdev_fd = -1; + rcdev->lirc_fd = -1; + rcdev->error = NULL; + rcdev->input_name = NULL; + rcdev->driver_name = NULL; + rcdev->keymap_name = NULL; + + if (keymaps_load(rcdev) < 0) { + fprintf(stderr, "failed to load keymaps: %m\n"); + rcdev_free(rcdev); + return NULL; + } + + return rcdev; +} + +void +rcdev_free(struct rc_device *rcdev) +{ + if (!rcdev) + return; + + list_del(&rcdev->list); + lirc_close(rcdev); + evdev_close(rcdev); + rcdev_close(rcdev); + + free(rcdev->path); + free(rcdev->input_name); + free(rcdev->driver_name); + free(rcdev->keymap_name); + + while (!list_empty(&rcdev->keymaps)) { + struct keymap *keymap = list_first_entry(&rcdev->keymaps, typeof(*keymap), list); + list_del(&keymap->list); + free(keymap->name); + free(keymap); + } + + free(rcdev); +} + +int +rcdev_setup(struct rc_device *rcdev, const char *path) +{ + int r; + + if (!rcdev) + return -EINVAL; + + if (rcdev->rcdev_fd >= 0) { + printf("Multiple rcdev devices!?\n"); + return 0; + } + + rcdev->rcdev_fd = open(path, O_RDONLY | O_NONBLOCK); + if (rcdev->rcdev_fd < 0) { + printf("Failed to open rcdev device %s: %s\n", path, strerror(errno)); + return -errno; + } + + if (sd_event_add_io(rcdev->mgr->event, &rcdev->rcdev_ev, + rcdev->rcdev_fd, EPOLLIN, rcdev_read, rcdev) < 0) { + printf("Failed to add event source for rcdev device %s: %s\n", + path, strerror(errno)); + r = -errno; + rcdev_close(rcdev); + return r; + } + + return 0; +} + +void +rcdev_close(struct rc_device *rcdev) +{ + if (!rcdev) + return; + + if (rcdev->rcdev_fd < 0) + return; + + close(rcdev->rcdev_fd); + rcdev->rcdev_fd = -1; +} + diff --git a/rcm-server-rcdev.h b/rcm-server-rcdev.h new file mode 100644 index 0000000..1e685ce --- /dev/null +++ b/rcm-server-rcdev.h @@ -0,0 +1,13 @@ +#ifndef foorcmserverrcdevhfoo +#define foorcmserverrcdevhfoo + +struct rc_device *rcdev_create(struct manager *mgr, const char *name); + +void rcdev_free(struct rc_device *rcdev); + +int rcdev_setup(struct rc_device *rcdev, const char *path); + +void rcdev_close(struct rc_device *rcdev); + +#endif + diff --git a/rcm-server-udev.c b/rcm-server-udev.c index fec809d..82a33a8 100644 --- a/rcm-server-udev.c +++ b/rcm-server-udev.c @@ -13,34 +13,9 @@ #include "rcm-server-keymap.h" #include "rcm-server-evdev.h" #include "rcm-server-lirc.h" +#include "rcm-server-rcdev.h" #include "rcm-server-udev.h" -void -rc_device_free(struct rc_device *rcdev) -{ - if (!rcdev) - return; - - list_del(&rcdev->list); - lirc_close(rcdev); - evdev_close(rcdev); - - free(rcdev->path); - free(rcdev->input_name); - free(rcdev->driver_name); - free(rcdev->keymap_name); - free(rcdev->dev_name); - - while (!list_empty(&rcdev->keymaps)) { - struct keymap *keymap = list_first_entry(&rcdev->keymaps, typeof(*keymap), list); - list_del(&keymap->list); - free(keymap->name); - free(keymap); - } - - free(rcdev); -} - static void udev_device_remove(struct manager *mgr, struct udev_device *udev) { @@ -54,7 +29,7 @@ udev_device_remove(struct manager *mgr, struct udev_device *udev) if (strcmp(rcdev->name, name)) continue; sd_bus_emit_object_removed(mgr->bus, rcdev->path); - rc_device_free(rcdev); + rcdev_free(rcdev); mgr->num_rc_devs--; break; } @@ -64,43 +39,19 @@ static void udev_device_add(struct manager *mgr, struct udev_device *udev) { const char *name; - const char *str; - char *path; + const char *tmpstr; struct rc_device *rcdev; 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"); + if (!name) return; - } - rcdev = malloc(sizeof(*rcdev)); - if (!rcdev) { - fprintf(stderr, "malloc failed: %m\n"); - free(path); - return; - } - - list_init(&rcdev->keymaps); - rcdev->mgr = mgr; - rcdev->path = path; - rcdev->name = rcdev->path + strlen("/org/gnome/RemoteControlManager/"); - rcdev->evdev_fd = -1; - rcdev->lirc_fd = -1; - rcdev->error = NULL; - rcdev->input_name = NULL; - rcdev->driver_name = NULL; - rcdev->keymap_name = NULL; - rcdev->dev_name = NULL; - - if (keymaps_load(rcdev) < 0) { - fprintf(stderr, "failed to load keymaps: %m\n"); - rc_device_free(rcdev); + rcdev = rcdev_create(mgr, name); + if (!rcdev) return; - } enumerate = udev_enumerate_new(mgr->udev); udev_enumerate_add_match_parent(enumerate, udev); @@ -165,12 +116,21 @@ next: } udev_enumerate_unref(enumerate); - str = udev_device_get_sysattr_value(udev, "uevent"); - if (str) { - char tmp[strlen(str) + 1]; + tmpstr = udev_device_get_devnode(udev); + if (tmpstr) { + r = rcdev_setup(rcdev, tmpstr); + if (r < 0) { + printf("Failed to setup rcdev: %s\n", tmpstr); + rcdev->error = "Error: Failed to setup rcdev"; + } + } + + tmpstr = udev_device_get_sysattr_value(udev, "uevent"); + if (tmpstr) { + char tmp[strlen(tmpstr) + 1]; char *token; - strcpy(tmp, str); + strcpy(tmp, tmpstr); for (token = strtok(tmp, "\n"); token; token = strtok(NULL, "\n")) { if (!strncmp(token, "DRV_NAME=", strlen("DRV_NAME="))) @@ -178,7 +138,7 @@ next: else if (!strncmp(token, "NAME=", strlen("NAME="))) rcdev->keymap_name = strdup(token + strlen("NAME=")); else if (!strncmp(token, "DEVNAME=", strlen("DEVNAME="))) - rcdev->dev_name = strdup(token + strlen("DEVNAME=")); + continue; else if (!strncmp(token, "MAJOR=", strlen("MAJOR="))) continue; else if (!strncmp(token, "MINOR=", strlen("MINOR="))) @@ -198,7 +158,7 @@ next: printf("\tInput name: %s\n", rcdev->input_name); printf("\tDriver : %s\n", rcdev->driver_name); printf("\tKernel map: %s\n", rcdev->keymap_name); - printf("\tDev name : %s\n", rcdev->dev_name); + printf("\trcdev fd : %i\n", rcdev->rcdev_fd); printf("\tevdev fd : %i\n", rcdev->evdev_fd); printf("\tLIRC fd : %i\n", rcdev->lirc_fd); printf("\tDBUS path : %s\n", rcdev->path); @@ -208,7 +168,7 @@ next: list_add(&rcdev->list, &mgr->rc_devs); mgr->num_rc_devs++; - sd_bus_emit_object_added(mgr->bus, path); + sd_bus_emit_object_added(mgr->bus, rcdev->path); } static int diff --git a/rcm-server-udev.h b/rcm-server-udev.h index ba90752..58ccd1b 100644 --- a/rcm-server-udev.h +++ b/rcm-server-udev.h @@ -1,8 +1,6 @@ #ifndef foorcmserverudevhfoo #define foorcmserverudevhfoo -void rc_device_free(struct rc_device *rcdev); - int udev_setup(struct manager *mgr); void udev_close(struct manager *mgr); |