From c415fbc066e6a0a10f1b5d63079d2b47ca3482f6 Mon Sep 17 00:00:00 2001 From: martii Date: Fri, 13 Jul 2012 16:29:53 +0200 Subject: [PATCH] input handling: copy input data from secondary devices to the main rc device Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/7f45271ad2f351f64f99bdf0621cb7f4fe1427e6 Author: martii Date: 2012-07-13 (Fri, 13 Jul 2012) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libspark/init.cpp | 242 +++++++++++++++++++++++++++++++++++++++ libspark/lirmp_input.cpp | 29 +++++ 2 files changed, 271 insertions(+) diff --git a/libspark/init.cpp b/libspark/init.cpp index 5b6071f..587b34c 100644 --- a/libspark/init.cpp +++ b/libspark/init.cpp @@ -16,6 +16,235 @@ #define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args) #define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args) +#ifdef MARTII +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VIRTUALINPUT "/sys/devices/virtual/input" +#define DEVINPUT "/dev/input" + +typedef struct { + const char *name; + const char *desc; + int fd; + int major; + int minor; + time_t next_discovery; +} input_device_t; + +static input_device_t input_device[] = { + { "/dev/input/nevis_ir", "lircd", -1, 0, 0, 0 }, + { "/dev/input/tdt_rc", "TDT RC event driver", -1, 0, 0, 0 }, + { "/dev/input/fulan_fp", "fulan front panel buttons", -1, 0, 0, 0 }, + { "/dev/input/event0", NULL, -1, 0, 0, 0 }, + { "/dev/input/event1", NULL, -1, 0, 0, 0 }, + { "/dev/input/event2", NULL, -1, 0, 0, 0 }, + { "/dev/input/event3", NULL, -1, 0, 0, 0 }, + { "/dev/input/event4", NULL, -1, 0, 0, 0 }, + { "/dev/input/event5", NULL, -1, 0, 0, 0 }, + { "/dev/input/event6", NULL, -1, 0, 0, 0 }, + { "/dev/input/event7", NULL, -1, 0, 0, 0 }, + { NULL, NULL, -1, 0, 0, 0 } +}; + +static int number_of_input_devices = 0; + +static int do_mknod(int i, char *d_name) { + char name[255]; + int dev = -1; + // I've no idea how the event device number is actually calculated. Just loop. --martii + + for (int j = 0; j < 99 && dev < 0; j++) { + snprintf(name, sizeof(name), VIRTUALINPUT "/%s/event%d/dev", d_name, j); + dev = open (name, O_RDONLY); + } + + if (dev > -1) { + char buf[255]; + int l = read(dev, buf, sizeof(buf) - 1); + close(dev); + if (l > -1) { + buf[l] = 0; + if (2 == sscanf(buf, "%d:%d", &input_device[i].major, &input_device[i].minor)) { + mknod(input_device[i].name, 0666 | S_IFCHR, + gnu_dev_makedev(input_device[i].major, input_device[i].minor)); + } + } + } +} + +static void create_input_devices (void) { + DIR *d = opendir (VIRTUALINPUT); + if (d) { + struct dirent *e; + while ((e = readdir(d))) { + char name[255]; + if (e->d_name[0] == '.') + continue; + snprintf(name, sizeof(name), VIRTUALINPUT "/%s/name", e->d_name); + int n = open(name, O_RDONLY); + if (n > -1) { + char buf[255]; + int l = read(n, buf, sizeof(buf) - 1); + close(n); + if (l > 1) { + do + buf[l--] = 0; + while (l > 1 && buf[l] == '\n'); + + for (int i = 0; i < number_of_input_devices; i++) + if (input_device[i].desc && !strcmp(buf, input_device[i].desc)) { + do_mknod(i, e->d_name); + break; + } + } + } + } + closedir(d); + } + // remove any event* files left that point to our "well-known" inputs + d = opendir (DEVINPUT); + if (d) { + struct dirent *e; + while ((e = readdir(d))) { + char name[255]; + if (strncmp(e->d_name, "event", 5)) + continue; + snprintf(name, sizeof(name), DEVINPUT "/%s", e->d_name); + struct stat st; + if (stat(name, &st)) + continue; + for (int i = 0; i < number_of_input_devices; i++) + if (input_device[i].major && + gnu_dev_major(st.st_rdev) == input_device[i].major && + gnu_dev_minor(st.st_rdev) == input_device[i].minor) + unlink(name); + } + closedir(d); + } +} + +static pthread_t inmux_task = 0; +static int inmux_thread_running = 0; + +static void count_input_devices(void) { + input_device_t *i = input_device; + while (i->name) + i++, number_of_input_devices++; +} + +static void open_input_devices(void) { + time_t now = time(NULL); + for (int i = 0; i < number_of_input_devices; i++) + if ((input_device[i].fd < 0) && (input_device[i].next_discovery <= now)) { + input_device[i].next_discovery = now + 60; + input_device[i].fd = open(input_device[i].name, O_RDWR | O_NONBLOCK); + } +} + +static void close_input_devices(void) { + for (int i = 0; i < number_of_input_devices; i++) + if (input_device[i].fd > -1) { + close(input_device[i].fd); + input_device[i].fd = -1; + } +} + +static void poll_input_devices(void) { + struct pollfd fds[number_of_input_devices]; + input_device_t *inputs[number_of_input_devices]; + int nfds = 0; + for (int i = 1; i < number_of_input_devices; i++) + if (input_device[i].fd > -1) { + fds[nfds].fd = input_device[i].fd; + fds[nfds].events = POLLIN | POLLHUP | POLLERR; + fds[nfds].revents = 0; + inputs[nfds] = &input_device[i]; + nfds++; + } + + if (nfds == 0) { + // Only a single input device, which happens to be our master. poll() to avoid looping too fast. + fds[0].fd = input_device[0].fd; + fds[0].events = POLLIN | POLLHUP | POLLERR; + fds[0].revents = 0; + poll(fds, 1, 60000 /* ms */); + return; + } + + int r = poll(fds, nfds, 60000 /* ms */); + if (r < 0) { + if (errno != EAGAIN) { + lt_info("%s: poll(): %m\n", __func__); + inmux_thread_running = 0; + } + return; + } + for (int i = 0; i < nfds && r > 0; i++) { + if (fds[i].revents & POLLIN) { +//fprintf(stderr, "### input from fd %d (%s)\n", fds[i].fd, inputs[i]->name); + struct input_event ev; + while (sizeof(ev) == read(fds[i].fd, &ev, sizeof(ev))) + write(input_device[0].fd, &ev, sizeof(ev)); + r--; + } else if (fds[i].revents & (POLLHUP | POLLERR | POLLNVAL)) { +//fprintf(stderr, "### error on %d (%s)\n", fds[i].fd, inputs[i]->name); + close (fds[i].fd); + inputs[i]->fd = -1; + r--; + } + } +} + +static void *inmux_thread(void *) +{ + char threadname[17]; + strncpy(threadname, __func__, sizeof(threadname)); + threadname[16] = 0; + prctl (PR_SET_NAME, (unsigned long)&threadname); + + inmux_thread_running = 1; + while (inmux_thread_running) { + open_input_devices(); + poll_input_devices(); + } + + return NULL; +} + +void start_inmux_thread(void) +{ + input_device[0].fd = open(input_device[0].name, O_RDWR | O_NONBLOCK); // nevis_ir. This is mandatory. + if (input_device[0].fd < 0){ + lt_info("%s: open(%s): %m\n", __func__, input_device[0].name); + return; + } + if (pthread_create(&inmux_task, 0, inmux_thread, NULL) != 0) + { + lt_info("%s: inmux thread pthread_create: %m\n", __func__); + inmux_thread_running = 0; + return; + } + pthread_detach(inmux_task); +} + +void stop_inmux_thread(void) +{ + inmux_thread_running = 0; +} + +#endif + static bool initialized = false; void init_td_api() @@ -32,6 +261,11 @@ void init_td_api() start_input_thread(); else lt_info("%s: lircd pidfile present, not starting input thread\n", __func__); +#ifdef MARTII + count_input_devices(); + create_input_devices(); + start_inmux_thread(); +#endif } initialized = true; lt_info("%s end\n", __FUNCTION__); @@ -40,7 +274,15 @@ void init_td_api() void shutdown_td_api() { lt_info("%s, initialized = %d\n", __FUNCTION__, (int)initialized); +#ifdef MARTII + if (initialized) { + stop_input_thread(); + stop_inmux_thread(); + close_input_devices(); + } +#else if (initialized) stop_input_thread(); +#endif initialized = false; } diff --git a/libspark/lirmp_input.cpp b/libspark/lirmp_input.cpp index e556a1e..4f46953 100644 --- a/libspark/lirmp_input.cpp +++ b/libspark/lirmp_input.cpp @@ -38,6 +38,10 @@ #include #include +#ifdef MARTII +#include +#endif + #include "lirmp_input.h" extern "C" { #include "irmp.h" @@ -192,12 +196,19 @@ static void *input_thread(void *) uint32_t lircdata; /* lirc_t to be correct... */ unsigned int count = 0; /* how many timeouts? */ unsigned int nodec = 0; /* how many timeouts since last decoded? */ +#ifdef MARTII + int aotom_fd = -1; +#endif IRMP_DATA d; lt_info("LIRC/IRMP input converter thread starting...\n"); /* modprobe does not complain if the module is already loaded... */ +#ifdef MARTII + system("/sbin/insmod /lib/modules/uinput.ko"); +#else system("/sbin/modprobe uinput"); +#endif do { usleep(100000); /* mdev needs some time to create the device? */ uinput = open("/dev/uinput", O_WRONLY|O_NDELAY); @@ -298,6 +309,10 @@ static void *input_thread(void *) #define LIRC_PULSE_MASK 0x00FFFFFF lt_info("LIRC/IRMP input converter going into main loop...\n"); +#ifdef MARTII + aotom_fd = open("/dev/vfd", O_RDONLY); +#endif + /* TODO: ioctl to find out if we have a compatible LIRC_MODE2 device */ thread_running = 1; while (thread_running) @@ -392,6 +407,14 @@ static void *input_thread(void *) //lt_debug("uinput write: value: %d code: %d\n", u.value, u.code); last_code = u.code; write(uinput, &u, sizeof(u)); +#ifdef MARTII + if (aotom_fd > -1) { + struct aotom_ioctl_data vfd_data; + vfd_data.u.led.led_nr = 1; + vfd_data.u.led.on = 10; + ioctl(aotom_fd, VFDSETLED, &vfd_data); + } +#endif break; } } @@ -401,6 +424,12 @@ static void *input_thread(void *) } /* clean up */ close (lircfd); + +#ifdef MARTII + if (aotom_fd > -1) + close(aotom_fd); +#endif + out: ioctl(uinput, UI_DEV_DESTROY); return NULL;