summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rw-r--r--rcm-server-main.c3
-rw-r--r--rcm-server-main.h3
-rw-r--r--rcm-server-rcdev.c279
-rw-r--r--rcm-server-rcdev.h13
-rw-r--r--rcm-server-udev.c84
-rw-r--r--rcm-server-udev.h2
7 files changed, 324 insertions, 68 deletions
diff --git a/Makefile b/Makefile
index 6ef27cb..bac3dc0 100644
--- a/Makefile
+++ b/Makefile
@@ -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);