ceckb

libcec to uinput key event mapper
git clone git://git.2f30.org/ceckb
Log | Files | Refs | README | LICENSE

commit 63ae472a6386f37dc85d442c57d701816fd40a77
Author: lostd <lostd@2f30.org>
Date:   Fri, 27 Mar 2015 18:23:02 +0200

The uinput part works so far

Diffstat:
AMakefile | 17+++++++++++++++++
AREADME | 9+++++++++
Aceckb.c | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig.def.h | 10++++++++++
4 files changed, 138 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,17 @@ +LDLIBS = -lcec +OBJS = ceckb.o +BIN = ceckb + +all: $(BIN) + +ceckb.o: config.h + +clean: + rm -f $(OBJS) $(BIN) + +.PHONY: all clean + +.SUFFIXES: .def.h + +.def.h.h: + cp $< $@ diff --git a/README b/README @@ -0,0 +1,9 @@ +Simple program that translates HDMI-CEC commands to Linux uinput key events. +Inspired by libcec-daemon: + +https://github.com/bramp/libcec-daemon + +Initial sample code from: + +https://github.com/Pulse-Eight/libcec +http://thiemonge.org/getting-started-with-uinput diff --git a/ceckb.c b/ceckb.c @@ -0,0 +1,102 @@ +#include <sys/stat.h> + +#include <linux/input.h> +#include <linux/uinput.h> + +#include <err.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> + +#include <libcec/cectypes.h> + +#define LEN(x) (sizeof(x) / sizeof(*(x))) + +struct map { + unsigned cec; + unsigned code; +}; + +#include "config.h" + +void +setupuinput(int fd) +{ + struct uinput_user_dev uidev; + unsigned int i; + int ret; + + ret = ioctl(fd, UI_SET_EVBIT, EV_KEY); + if (ret == -1) + err(1, "key events"); + ret = ioctl(fd, UI_SET_EVBIT, EV_SYN); + if (ret == -1) + err(1, "sync events"); + + /* Set available keys */ + for (i = 0; i < LEN(bindings); i++) { + ret = ioctl(fd, UI_SET_KEYBIT, bindings[i].code); + if (ret == -1) + err(1, "set key 0x%x", bindings[i].code); + } + + memset(&uidev, 0, sizeof(uidev)); + snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "ceckb"); + uidev.id.bustype = BUS_USB; + uidev.id.vendor = 0xdead; + uidev.id.product = 0xbabe; + uidev.id.version = 1; + + ret = write(fd, &uidev, sizeof(uidev)); + if (ret == -1) + err(1, "write uidev"); + ret = ioctl(fd, UI_DEV_CREATE); + if (ret == -1) + err(1, "create dev"); +} + +void +cleanuinput(int fd) +{ + int ret; + + ret = ioctl(fd, UI_DEV_DESTROY); + if (ret == -1) + err(1, "destroy dev"); +} + +void +sendevent(int fd, unsigned type, unsigned code) +{ + struct input_event ev; + int ret; + + memset(&ev, 0, sizeof(ev)); + ev.type = type; + ev.code = code; + ev.value = 1; + ret = write(fd, &ev, sizeof(ev)); + if (ret == -1) + err(1, "send event type 0x%x code 0x%x", type, code); +} + +int +main(void) +{ + int fd; + + fd = open(upath, O_WRONLY | O_NONBLOCK); + if (fd == -1) + err(1, "open %s", upath); + + setupuinput(fd); + + sendevent(fd, EV_KEY, KEY_DOWN); + sendevent(fd, EV_SYN, SYN_REPORT); + + cleanuinput(fd); + + close(fd); + + return 0; +} diff --git a/config.def.h b/config.def.h @@ -0,0 +1,10 @@ +const char *upath = "/dev/uinput"; + +struct map bindings[] = { + { CEC_USER_CONTROL_CODE_EXIT, KEY_Q }, + { CEC_USER_CONTROL_CODE_SELECT, KEY_ENTER }, + { CEC_USER_CONTROL_CODE_UP, KEY_UP }, + { CEC_USER_CONTROL_CODE_DOWN, KEY_DOWN }, + { CEC_USER_CONTROL_CODE_LEFT, KEY_LEFT }, + { CEC_USER_CONTROL_CODE_RIGHT, KEY_RIGHT }, +};