mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-libstb-hal.git
synced 2025-08-26 23:12:44 +02:00
input handling: copy input data from secondary devices to the main rc device
Origin commit data
------------------
Branch: master
Commit: 7f45271ad2
Author: martii <you@example.com>
Date: 2012-07-13 (Fri, 13 Jul 2012)
------------------
No further description and justification available within origin commit message!
------------------
This commit was generated by Migit
This commit is contained in:
@@ -16,6 +16,235 @@
|
|||||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args)
|
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args)
|
||||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args)
|
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args)
|
||||||
|
|
||||||
|
#ifdef MARTII
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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;
|
static bool initialized = false;
|
||||||
|
|
||||||
void init_td_api()
|
void init_td_api()
|
||||||
@@ -32,6 +261,11 @@ void init_td_api()
|
|||||||
start_input_thread();
|
start_input_thread();
|
||||||
else
|
else
|
||||||
lt_info("%s: lircd pidfile present, not starting input thread\n", __func__);
|
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;
|
initialized = true;
|
||||||
lt_info("%s end\n", __FUNCTION__);
|
lt_info("%s end\n", __FUNCTION__);
|
||||||
@@ -40,7 +274,15 @@ void init_td_api()
|
|||||||
void shutdown_td_api()
|
void shutdown_td_api()
|
||||||
{
|
{
|
||||||
lt_info("%s, initialized = %d\n", __FUNCTION__, (int)initialized);
|
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)
|
if (initialized)
|
||||||
stop_input_thread();
|
stop_input_thread();
|
||||||
|
#endif
|
||||||
initialized = false;
|
initialized = false;
|
||||||
}
|
}
|
||||||
|
@@ -38,6 +38,10 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef MARTII
|
||||||
|
#include <aotom_main.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "lirmp_input.h"
|
#include "lirmp_input.h"
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "irmp.h"
|
#include "irmp.h"
|
||||||
@@ -192,12 +196,19 @@ static void *input_thread(void *)
|
|||||||
uint32_t lircdata; /* lirc_t to be correct... */
|
uint32_t lircdata; /* lirc_t to be correct... */
|
||||||
unsigned int count = 0; /* how many timeouts? */
|
unsigned int count = 0; /* how many timeouts? */
|
||||||
unsigned int nodec = 0; /* how many timeouts since last decoded? */
|
unsigned int nodec = 0; /* how many timeouts since last decoded? */
|
||||||
|
#ifdef MARTII
|
||||||
|
int aotom_fd = -1;
|
||||||
|
#endif
|
||||||
IRMP_DATA d;
|
IRMP_DATA d;
|
||||||
|
|
||||||
lt_info("LIRC/IRMP input converter thread starting...\n");
|
lt_info("LIRC/IRMP input converter thread starting...\n");
|
||||||
|
|
||||||
/* modprobe does not complain if the module is already loaded... */
|
/* modprobe does not complain if the module is already loaded... */
|
||||||
|
#ifdef MARTII
|
||||||
|
system("/sbin/insmod /lib/modules/uinput.ko");
|
||||||
|
#else
|
||||||
system("/sbin/modprobe uinput");
|
system("/sbin/modprobe uinput");
|
||||||
|
#endif
|
||||||
do {
|
do {
|
||||||
usleep(100000); /* mdev needs some time to create the device? */
|
usleep(100000); /* mdev needs some time to create the device? */
|
||||||
uinput = open("/dev/uinput", O_WRONLY|O_NDELAY);
|
uinput = open("/dev/uinput", O_WRONLY|O_NDELAY);
|
||||||
@@ -298,6 +309,10 @@ static void *input_thread(void *)
|
|||||||
#define LIRC_PULSE_MASK 0x00FFFFFF
|
#define LIRC_PULSE_MASK 0x00FFFFFF
|
||||||
lt_info("LIRC/IRMP input converter going into main loop...\n");
|
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 */
|
/* TODO: ioctl to find out if we have a compatible LIRC_MODE2 device */
|
||||||
thread_running = 1;
|
thread_running = 1;
|
||||||
while (thread_running)
|
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);
|
//lt_debug("uinput write: value: %d code: %d\n", u.value, u.code);
|
||||||
last_code = u.code;
|
last_code = u.code;
|
||||||
write(uinput, &u, sizeof(u));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -401,6 +424,12 @@ static void *input_thread(void *)
|
|||||||
}
|
}
|
||||||
/* clean up */
|
/* clean up */
|
||||||
close (lircfd);
|
close (lircfd);
|
||||||
|
|
||||||
|
#ifdef MARTII
|
||||||
|
if (aotom_fd > -1)
|
||||||
|
close(aotom_fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
out:
|
out:
|
||||||
ioctl(uinput, UI_DEV_DESTROY);
|
ioctl(uinput, UI_DEV_DESTROY);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Reference in New Issue
Block a user