Multiple input files by means of poll.

This commit is contained in:
Bas Weelinck 2012-12-07 20:20:19 +01:00
parent 71557bd433
commit 4d202546a5
5 changed files with 315 additions and 39 deletions

View File

@ -1,6 +1,15 @@
#ifndef H_CONFIG_FUNCTIONS #ifndef H_CONFIG_FUNCTIONS
#define H_CONFIG_FUNCTIONS #define H_CONFIG_FUNCTIONS
#define ADD_INPUT_PATH(INPUT_PATH, NUM) \
/* Open input and uinput */ \
in[NUM] = open(INPUT_PATH, O_RDONLY); \
if(in[NUM] < 0) { \
perror("Could not open: " INPUT_PATH); \
return 1; \
}
#define JOYSTICK_SET_OPT(opt, bit, device) \ #define JOYSTICK_SET_OPT(opt, bit, device) \
if (device == j) { \ if (device == j) { \
if (ioctl(js[device], bit, opt) < 0) { \ if (ioctl(js[device], bit, opt) < 0) { \

View File

@ -6,11 +6,24 @@
/* Set up amount of joysticks here */ /* Set up amount of joysticks here */
#define JOYCOUNT 1 #define JOYCOUNT 1
/* Set up event to read from */ /* Set up amount of input devices here */
#define INPUT_PATH "/dev/input/by-path/platform-i8042-serio-0-event-kbd" #define INPUT_DEVICE_COUNT 1
#endif #endif
/* -------------------------------------------------------------------------- */
/* ------------------- FIRST AND A HALF SECTION ----------------------------- */
/* -------------------------------------------------------------------------- */
#ifdef H_CONFIGURE_EVENTS
#ifndef H_CONFIGURE_EVENTS_SEEN
#define H_CONFIGURE_EVENTS_SEEN
ADD_INPUT_PATH("/dev/input/by-path/platform-i8042-serio-0-event-kbd", 0)
#endif
#endif
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* ----------------------------- SECOND SECTION ----------------------------- */ /* ----------------------------- SECOND SECTION ----------------------------- */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */

192
confs/mulitput.h Normal file
View File

@ -0,0 +1,192 @@
/*
* Copyright Merlijn Wajer 2012
*
* This is the uinput-mapper configuration file.
*
* We are still working out all the details, but it basically boils down to the
* following: You write the configuration entirely in the C preprocessor by
* adding the right commands (macros) to the right sections.
*
*
* As of now, there are three sections:
*
* - GLOBAL_MAP;
* This is where you set the amount of devices to be emulated (currently
* called JOYCOUNT) and the INPUT_PATH.
*
* - CONFIGURE_JOYSTICKS:
* This is where you tell uinput-mapper what buttons your new joysticks (or
* other devices) should expose. Any button not exposed here will never be
* send.
*
* Macros that make sense to use here:
* - JOYSTICK_SET_OPT(<opt>, <bit>, <device>)
* - JOYSTICK_ADD_KEY(<key>, <bit to set>, <device>)
* - JOYSTICK_SET_LIM(<absmin|absmax>, <value>, <key>)
*
* JOYSTICK_SET_LIM is mostly used for ABS_HATs.
*
* - JOYMAP:
*
* Set the key mappings here.
*
* Macros that make sense here:
* - KEYMAP(<in_key>, <out_key>, <out_type>, <device>, <val>)
*
*
* Notes:
* - To expose a joystick device, expose the BTN_JOYSTICK ``button'' with
* JOYSTICK_ADD_KEY
* - To expose a mouse device, expose (at least) the BTN_LEFT button with
* JOYSTICK_ADD_KEY
*
* ----------------------------------------------------------------------------
*
* TODO:
* - For KEYMAPs, add parameter that species the INPUT_PATH to map from
* - Add support for multiple INPUT_PATH
* - Figure out more details. There's probably a lot missing.
* - Remove EV_KEY constraint in map.c and use it as arg to KEY_MAP
*
* ----------------------------------------------------------------------------
*/
#include "config_functions.h"
/* -------------------------------------------------------------------------- */
/* ----------------------------- FIRST SECTION ----------------------------- */
/* -------------------------------------------------------------------------- */
#ifndef H_GLOBAL_MAP
#define H_GLOBAL_MAP
/* Set up amount of joysticks here */
#define JOYCOUNT 2
/* Set up amount of input devices here */
#define INPUT_DEVICE_COUNT 2
#endif
/* -------------------------------------------------------------------------- */
/* ------------------- FIRST AND A HALF SECTION ----------------------------- */
/* -------------------------------------------------------------------------- */
#ifdef H_CONFIGURE_EVENTS
#ifndef H_CONFIGURE_EVENTS_SEEN
#define H_CONFIGURE_EVENTS_SEEN
ADD_INPUT_PATH("/dev/input/event4", 0)
ADD_INPUT_PATH("/dev/input/event5", 1)
#endif
#endif
/* -------------------------------------------------------------------------- */
/* ----------------------------- SECOND SECTION ----------------------------- */
/* -------------------------------------------------------------------------- */
#ifdef H_CONFIGURE_JOYSTICKS
#ifndef H_CONFIGURE_JOYSTICKS_SEEN
#define H_CONFIGURE_JOYSTICKS_SEEN
/* Configure first joystick.
*
* Here we just tell the program what keys event we will expose and what
* keys we want to use.
*
* If a key is not enabled here, it will never be passed.
*/
/* We want to send ABS and KEY events */
JOYSTICK_SET_OPT(EV_ABS, UI_SET_EVBIT, 0)
JOYSTICK_SET_OPT(EV_KEY, UI_SET_EVBIT, 0)
/* Hats:
* We set the absmax and absmin; otherwise the hats make no sense.
*/
JOYSTICK_ADD_KEY(ABS_HAT0X, UI_SET_ABSBIT, 0)
JOYSTICK_SET_LIM(absmax, 1, ABS_HAT0X)
JOYSTICK_SET_LIM(absmin, -1, ABS_HAT0X)
JOYSTICK_ADD_KEY(ABS_HAT0Y, UI_SET_ABSBIT, 0)
JOYSTICK_SET_LIM(absmax, 1, ABS_HAT0Y)
JOYSTICK_SET_LIM(absmin, -1, ABS_HAT0Y)
/* XXX: ALWAYS SET BTN_JOYSTICK TO EXPOSE A JOYSTICK DEVICE */
JOYSTICK_ADD_KEY(BTN_JOYSTICK, UI_SET_KEYBIT, 0)
/* Buttons. */
JOYSTICK_ADD_KEY(BTN_0, UI_SET_KEYBIT, 0)
JOYSTICK_ADD_KEY(BTN_1, UI_SET_KEYBIT, 0)
JOYSTICK_ADD_KEY(BTN_2, UI_SET_KEYBIT, 0)
JOYSTICK_ADD_KEY(BTN_3, UI_SET_KEYBIT, 0)
/* Second joystick ; same comments as first one */
JOYSTICK_SET_OPT(EV_ABS, UI_SET_EVBIT, 1)
JOYSTICK_SET_OPT(EV_KEY, UI_SET_EVBIT, 1)
JOYSTICK_ADD_KEY(ABS_HAT0X, UI_SET_ABSBIT, 1)
JOYSTICK_SET_LIM(absmax, 1, ABS_HAT0X)
JOYSTICK_SET_LIM(absmin, -1, ABS_HAT0X)
JOYSTICK_ADD_KEY(ABS_HAT0Y, UI_SET_ABSBIT, 1)
JOYSTICK_SET_LIM(absmax, 1, ABS_HAT0X)
JOYSTICK_SET_LIM(absmin, -1, ABS_HAT0X)
JOYSTICK_ADD_KEY(BTN_JOYSTICK, UI_SET_KEYBIT, 1)
JOYSTICK_ADD_KEY(BTN_0, UI_SET_KEYBIT, 1)
JOYSTICK_ADD_KEY(BTN_1, UI_SET_KEYBIT, 1)
JOYSTICK_ADD_KEY(BTN_2, UI_SET_KEYBIT, 1)
JOYSTICK_ADD_KEY(BTN_3, UI_SET_KEYBIT, 1)
#endif
#endif
/* -------------------------------------------------------------------------- */
/* ----------------------------- THIRD SECTION ----------------------------- */
/* -------------------------------------------------------------------------- */
#ifdef H_JOYMAP
#ifndef H_JOYMAP_SEEN
#define H_JOYMAP_SEEN
/* First joystick */
LEGAL_VALUE(e.value == 1 || e.value == 0,
/* HAT */
KEYMAP(EV_KEY, KEY_UP, ABS_HAT0Y, EV_ABS, 0, -)
KEYMAP(EV_KEY, KEY_DOWN, ABS_HAT0Y, EV_ABS, 0, +)
KEYMAP(EV_KEY, KEY_LEFT, ABS_HAT0X, EV_ABS, 0, -)
KEYMAP(EV_KEY, KEY_RIGHT, ABS_HAT0X, EV_ABS, 0, +)
/* Red buttons */
KEYMAP(EV_KEY, KEY_LEFTCTRL, BTN_0, EV_KEY, 0, +)
KEYMAP(EV_KEY, KEY_LEFTALT, BTN_1, EV_KEY, 0, +)
KEYMAP(EV_KEY, KEY_SPACE, BTN_2, EV_KEY, 0, +)
/* Yellow button */
KEYMAP(EV_KEY, KEY_1, BTN_3, EV_KEY, 0, +)
)
/* Second joystick */
LEGAL_VALUE(e.value == 1 || e.value == 0,
/* HAT */
KEYMAP(EV_KEY, KEY_R, ABS_HAT0Y, EV_ABS, 1, -)
KEYMAP(EV_KEY, KEY_F, ABS_HAT0Y, EV_ABS, 1, +)
KEYMAP(EV_KEY, KEY_D, ABS_HAT0X, EV_ABS, 1, -)
KEYMAP(EV_KEY, KEY_G, ABS_HAT0X, EV_ABS, 1, +)
/* Red buttons */
KEYMAP(EV_KEY, KEY_A, BTN_0, EV_KEY, 1, +)
KEYMAP(EV_KEY, KEY_S, BTN_1, EV_KEY, 1, +)
KEYMAP(EV_KEY, KEY_Q, BTN_2, EV_KEY, 1, +)
/* Yellow button */
KEYMAP(EV_KEY, KEY_2, BTN_3, EV_KEY, 1, +)
)
#endif
#endif

View File

@ -63,11 +63,24 @@
/* Set up amount of joysticks here */ /* Set up amount of joysticks here */
#define JOYCOUNT 2 #define JOYCOUNT 2
/* Set up event to read from */ /* Set up amount of input devices here */
#define INPUT_PATH "/dev/input/by-path/platform-i8042-serio-0-event-kbd" #define INPUT_DEVICE_COUNT 1
#endif #endif
/* -------------------------------------------------------------------------- */
/* ------------------- FIRST AND A HALF SECTION ----------------------------- */
/* -------------------------------------------------------------------------- */
#ifdef H_CONFIGURE_EVENTS
#ifndef H_CONFIGURE_EVENTS_SEEN
#define H_CONFIGURE_EVENTS_SEEN
ADD_INPUT_PATH("/dev/input/by-path/platform-i8042-serio-0-event-kbd", 0)
#endif
#endif
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* ----------------------------- SECOND SECTION ----------------------------- */ /* ----------------------------- SECOND SECTION ----------------------------- */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */

119
map.c
View File

@ -25,6 +25,10 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/uinput.h> #include <linux/uinput.h>
#include <err.h>
#include <poll.h>
#include <errno.h>
#include "config.h" #include "config.h"
#define UINPUT_PATH "/dev/uinput" #define UINPUT_PATH "/dev/uinput"
@ -71,8 +75,9 @@ void free_js(int sig) {
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
int j, nowrite; int j, nowrite, rfds, fdrr = 0;
int in; /* fds */ int in[INPUT_DEVICE_COUNT]; /* fds */
struct pollfd pin[INPUT_DEVICE_COUNT];
struct input_event e, je; struct input_event e, je;
struct uinput_user_dev uidev; struct uinput_user_dev uidev;
@ -82,15 +87,19 @@ int main(int argc, char** argv) {
(void)get_key_num; (void)get_key_num;
if(signal(SIGINT, free_js)) { /* Open required input devices */
printf("SIGINT handler registration failed\n"); #define H_CONFIGURE_EVENTS
return 1; #include "config.h"
/* Now setup poll structure */
for (j = 0; j < INPUT_DEVICE_COUNT; j++)
{
pin[j].fd = in[j];
pin[j].events = POLLIN;
} }
/* Open input and uinput */ if(signal(SIGINT, free_js) == SIG_ERR) {
in = open(INPUT_PATH, O_RDONLY); printf("SIGINT handler registration failed\n");
if(in < 0) {
perror("Could not open: " INPUT_PATH);
return 1; return 1;
} }
@ -116,51 +125,91 @@ int main(int argc, char** argv) {
if (write(js[j], &uidev, sizeof(uidev)) < 0) { if (write(js[j], &uidev, sizeof(uidev)) < 0) {
perror("write"); perror("write");
return -1; return EXIT_FAILURE;
} }
if (ioctl(js[j], UI_DEV_CREATE)) { if (ioctl(js[j], UI_DEV_CREATE)) {
perror("ioctl create"); perror("ioctl create");
return 1; return EXIT_FAILURE;
} }
} }
/* Do it! */ /* Do it! */
while (1) { while (1) {
if (read(in, &e, sizeof(struct input_event))) { printf("Entering poll..\n");
printf("Event: (Type: %d, Code: %d, Value %d)\n", e.type, e.code, e.value); /* Any data available? */
if ((rfds = poll(pin, INPUT_DEVICE_COUNT, -1)) < 0) {
/* Interrupted by signal */
if (errno == EINTR)
continue;
perror("poll");
return EXIT_FAILURE;
} }
printf("Leaving poll..\n");
memset(&je, '\0', sizeof(struct input_event)); /* Round-robin check readers */
nowrite = 1; while (rfds) {
j = 0; if (pin[fdrr].revents & POLLIN) {
printf("Device %d has input\n", fdrr);
/* XXX: Need checking for complete read? */
if (read(in[fdrr], &e, sizeof(struct input_event)) < 0) {
/* Interrupted by singal? Retry */
if (errno == EINTR)
continue;
#define H_JOYMAP #if 0
#include "config.h" if (errno == EWOULDBLOCK || errno == EAGAIN) {
printf("poll tells us device %d is readable.. it is not\n", fdrr);
rfds -= 1;
fdrr = (fdrr + 1) % INPUT_DEVICE_COUNT;
continue;
}
#endif
if (nowrite == 0) { err(EXIT_FAILURE, "reading input device nr. %d failed", fdrr);
printf("Writing %d to %d\n", e.code, j); }
if(write(js[j], &je, sizeof(struct input_event)) < 0) {
perror("Event write event"); printf("Event: (Type: %d, Code: %d, Value %d)\n", e.type, e.code, e.value);
return -1;
} }
}
/* Synchronisation events */ /* Update poll read mechanism */
if (e.type == EV_SYN) { fdrr = (fdrr + 1) % INPUT_DEVICE_COUNT;
rfds -= 1;
/* Now handle received event */
memset(&je, '\0', sizeof(struct input_event)); memset(&je, '\0', sizeof(struct input_event));
printf("SYN event\n"); nowrite = 1;
j = 0;
je.type = EV_SYN; #define H_JOYMAP
je.code = 0; #include "config.h"
je.value = 0;
if (write(js[j], &je, sizeof(struct input_event)) < 0) { if (nowrite == 0) {
perror("SYN write event"); printf("Writing %d to %d\n", e.code, j);
return -1; if(write(js[j], &je, sizeof(struct input_event)) < 0) {
perror("Event write event");
return EXIT_FAILURE;
}
} }
}
}
/* Synchronisation events */
if (e.type == EV_SYN) {
memset(&je, '\0', sizeof(struct input_event));
printf("SYN event\n");
je.type = EV_SYN;
je.code = 0;
je.value = 0;
if (write(js[j], &je, sizeof(struct input_event)) < 0) {
perror("SYN write event");
return EXIT_FAILURE;
}
}
} /* End reader check loop */
} /* End main loop */
return 0;
} }