uinput-mapper/map.c

216 lines
5.3 KiB
C
Raw Normal View History

2012-12-03 16:12:48 -05:00
/*
* Status:
*
* - Can map keys from some keyboard to keys on a joystick.
2012-12-05 13:00:17 -05:00
* - Has programmable config format (see config.h)
2012-12-03 16:12:48 -05:00
*
2012-12-05 13:00:17 -05:00
* TODO:
* - Allow multiple keymaps per input key event; currently we override previous
* values.
* - Allow multiple inputs, modify config file to allow for mapping from
* specific inputs.
2012-12-03 16:12:48 -05:00
*
*/
2012-12-03 14:16:19 -05:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
2012-12-03 14:16:19 -05:00
#include <linux/input.h>
#include <linux/uinput.h>
2012-12-07 14:20:19 -05:00
#include <err.h>
#include <poll.h>
#include <errno.h>
2012-12-04 18:50:26 -05:00
#include "config.h"
2012-12-04 14:05:00 -05:00
2012-12-03 14:16:19 -05:00
#define UINPUT_PATH "/dev/uinput"
2012-12-03 16:12:48 -05:00
/* Reverse mapping, for later use */
static const struct _key_to_str {
char *name;
int num;
} key_map[] = {
#define DEF_KEY(NAME) \
{#NAME,NAME},
#include "def_keys.h"
{NULL, -1}
};
static int get_key_num(char* name)
{
int i = 0;
while (key_map[i].name) {
if (!strcmp(key_map[i].name, name))
return key_map[i].num;
i++;
}
return -1;
}
2012-12-04 14:05:00 -05:00
static int js[JOYCOUNT];
2012-12-03 16:12:48 -05:00
void free_js(int sig) {
int j;
2012-12-04 14:13:43 -05:00
(void) sig;
2012-12-04 14:05:00 -05:00
for(j = 0; j < JOYCOUNT; j++) {
printf("Freeing joystick: %d\n", j);
if (ioctl(js[j], UI_DEV_DESTROY) < 0) {
perror("Error freeing joystick");
}
close(js[j]);
}
exit(1);
}
2012-12-03 14:16:19 -05:00
int main(int argc, char** argv) {
2012-12-07 14:20:19 -05:00
int j, nowrite, rfds, fdrr = 0;
int in[INPUT_DEVICE_COUNT]; /* fds */
struct pollfd pin[INPUT_DEVICE_COUNT];
2012-12-03 14:16:19 -05:00
struct input_event e, je;
struct uinput_user_dev uidev;
2012-12-03 16:12:48 -05:00
2012-12-04 14:13:43 -05:00
(void)argc;
(void)argv;
(void)get_key_num;
2012-12-07 14:20:19 -05:00
/* Open required input devices */
#define H_CONFIGURE_EVENTS
#include "config.h"
/* Now setup poll structure */
for (j = 0; j < INPUT_DEVICE_COUNT; j++)
{
pin[j].fd = in[j];
pin[j].events = POLLIN;
}
2012-12-07 14:20:19 -05:00
if(signal(SIGINT, free_js) == SIG_ERR) {
printf("SIGINT handler registration failed\n");
2012-12-03 14:16:19 -05:00
return 1;
}
2012-12-04 14:05:00 -05:00
for(j = 0; j < JOYCOUNT; j++) {
2012-12-03 18:07:34 -05:00
/* Memset because we are already setting the absmax/absmin */
memset(&uidev, '\0', sizeof(struct uinput_user_dev));
js[j] = open(UINPUT_PATH, O_WRONLY | O_NONBLOCK);
if (js[j] < 0) {
2012-12-05 13:00:17 -05:00
perror("Could not open:" UINPUT_PATH);
return 1;
}
2012-12-03 14:16:19 -05:00
#define H_CONFIGURE_JOYSTICKS
2012-12-04 18:50:26 -05:00
#include "config.h"
2012-12-03 14:16:19 -05:00
/* Allocate device info */
2012-12-04 14:05:00 -05:00
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "key2joy:%d", j);
2012-12-03 14:16:19 -05:00
uidev.id.bustype = BUS_USB;
uidev.id.vendor = 0x42;
uidev.id.product = 0xbebe;
uidev.id.version = 1;
2012-12-03 14:16:19 -05:00
if (write(js[j], &uidev, sizeof(uidev)) < 0) {
perror("write");
2012-12-07 14:20:19 -05:00
return EXIT_FAILURE;
}
if (ioctl(js[j], UI_DEV_CREATE)) {
perror("ioctl create");
2012-12-07 14:20:19 -05:00
return EXIT_FAILURE;
}
2012-12-03 14:16:19 -05:00
}
2012-12-03 16:12:48 -05:00
/* Do it! */
2012-12-03 14:16:19 -05:00
while (1) {
2012-12-07 14:20:19 -05:00
printf("Entering poll..\n");
/* Any data available? */
if ((rfds = poll(pin, INPUT_DEVICE_COUNT, -1)) < 0) {
/* Interrupted by signal */
if (errno == EINTR)
continue;
perror("poll");
return EXIT_FAILURE;
2012-12-03 14:16:19 -05:00
}
2012-12-07 14:20:19 -05:00
printf("Leaving poll..\n");
/* Round-robin check readers */
while (rfds) {
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;
#if 0
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
err(EXIT_FAILURE, "reading input device nr. %d failed", fdrr);
}
printf("Event: (Type: %d, Code: %d, Value %d)\n", e.type, e.code, e.value);
}
2012-12-03 14:16:19 -05:00
2012-12-07 14:20:19 -05:00
/* Update poll read mechanism */
fdrr = (fdrr + 1) % INPUT_DEVICE_COUNT;
rfds -= 1;
2012-12-03 16:12:48 -05:00
2012-12-07 14:20:19 -05:00
/* Now handle received event */
memset(&je, '\0', sizeof(struct input_event));
nowrite = 1;
j = 0;
#define H_JOYMAP
#include "config.h"
if (nowrite == 0) {
printf("Writing %d to %d\n", e.code, j);
if(write(js[j], &je, sizeof(struct input_event)) < 0) {
perror("Event write event");
return EXIT_FAILURE;
}
2012-12-03 14:16:19 -05:00
}
2012-12-03 16:12:48 -05:00
2012-12-07 14:20:19 -05:00
/* Synchronisation events */
if (e.type == EV_SYN) {
memset(&je, '\0', sizeof(struct input_event));
printf("SYN event\n");
2012-12-03 14:16:19 -05:00
2012-12-07 14:20:19 -05:00
je.type = EV_SYN;
je.code = 0;
je.value = 0;
2012-12-03 14:16:19 -05:00
2012-12-07 14:20:19 -05:00
if (write(js[j], &je, sizeof(struct input_event)) < 0) {
perror("SYN write event");
return EXIT_FAILURE;
}
2012-12-03 14:16:19 -05:00
}
2012-12-07 14:20:19 -05:00
} /* End reader check loop */
} /* End main loop */
2012-12-03 14:16:19 -05:00
2012-12-07 14:20:19 -05:00
return 0;
2012-12-03 14:16:19 -05:00
}