aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkraxel <kraxel>2004-04-21 11:55:44 +0000
committerkraxel <kraxel>2004-04-21 11:55:44 +0000
commitc4d7dacb41039e087d20b8889a4d13bd4c9928f2 (patch)
tree0aef1f53f2e8cd55c4db8915d9d9a1265dd97adc
downloadinput-c4d7dacb41039e087d20b8889a4d13bd4c9928f2.tar.gz
Initial revision
-rw-r--r--GNUmakefile62
-rw-r--r--INSTALL59
-rw-r--r--README82
-rw-r--r--input-events.c132
-rw-r--r--input-kbd.c260
-rw-r--r--input-recv.c87
-rw-r--r--input-send.c234
-rw-r--r--input.c132
-rw-r--r--input.h30
-rw-r--r--linux-input.h927
-rwxr-xr-xlirc.sh18
-rw-r--r--list.h169
-rw-r--r--lsinput.c35
-rw-r--r--mk/Autoconf.mk124
-rw-r--r--mk/Compile.mk84
-rw-r--r--mk/Maintainer.mk47
-rw-r--r--mk/Variables.mk33
-rwxr-xr-xname.sh10
-rw-r--r--tcp.c153
-rw-r--r--tcp.h11
20 files changed, 2689 insertions, 0 deletions
diff --git a/GNUmakefile b/GNUmakefile
new file mode 100644
index 0000000..0479955
--- /dev/null
+++ b/GNUmakefile
@@ -0,0 +1,62 @@
+# config
+-include Make.config
+include mk/Variables.mk
+
+# add our flags + libs
+CFLAGS += -DVERSION='"$(VERSION)"'
+LDLIBS += -lm
+
+# build
+TARGETS := lsinput input-events input-kbd input-send input-recv lircd.conf
+HEADERS := EV.h REL.h KEY.h BTN.h BUS.h
+
+# default target
+all: build
+
+
+#################################################################
+# poor man's autoconf ;-)
+
+include mk/Autoconf.mk
+
+define make-config
+LIB := $(LIB)
+endef
+
+
+########################################################################
+# rules
+
+build: $(TARGETS)
+
+$(HEADERS): name.sh
+ sh name.sh $* > $@
+
+lircd.conf: lirc.sh
+ sh lirc.sh > $@
+
+lsinput: lsinput.o input.o
+input-events: input-events.o input.o
+input-kbd: input-kbd.o input.o
+input-send: input-send.o input.o tcp.o
+input-recv: input-recv.o input.o tcp.o
+
+input.o: input.c $(HEADERS)
+
+install: build
+ install -d $(bindir)
+ install -s lsinput input-events input-kbd input-send input-recv $(bindir)
+
+clean:
+ -rm -f *.o $(depfiles)
+
+realclean distclean: clean
+ -rm -f Make.config
+ -rm -f $(TARGETS) $(HEADERS) *~ xpm/*~ *.bak
+
+#############################################
+
+include mk/Compile.mk
+include mk/Maintainer.mk
+-include $(depfiles)
+
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..0d1ba36
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,59 @@
+
+howto compile and install this package
+======================================
+
+
+really short install instructions
+---------------------------------
+
+ $ make
+ $ su -c "make install"
+
+
+
+the more detailed version
+-------------------------
+
+Make sure you use GNU make. The file name "GNUmakefile" isn't a joke,
+this package really requires GNU make.
+
+As first step make will do some config checks on your system and write
+the results to Make.config. If you want to have a look at Make.config
+before the actual build starts you can run this step separately using
+"make config".
+
+The Makefiles use the usual GNU-ish Makefile conventions for variable
+names and default values, i.e. prefix=/usr/local, ...
+
+The values for some frequently adapted variables are initialized from
+the enviroment. Thus you can change the defaults simply by setting
+environment variables:
+
+ $ prefix="/usr"
+ $ CFLAGS="-O3 -mcpu=i686"
+ $ export prefix CFLAGS
+
+Almost any variable can be overridden on the make command line. It is
+often used this way to install into some buildroot for packaging ...
+
+ $ su -c "make DESTDIR=/tmp/buildroot install"
+
+... but it works for most other variables equally well. There are
+some exceptions through, it usually does _not_ work for CFLAGS for
+example.
+
+Try "make verbose=yes" if you want to see the complete command lines
+executed by make instead of the short messages (for trouble shooting,
+because you like this way, for whatever reason ...). This also makes
+the config checks performed by "make config" more verbose.
+
+If you don't trust my Makefiles you can run "make -n install" to see
+what "make install" would do on your system. It will produce
+human-readable output (unlike automake ...).
+
+Have fun,
+
+ Gerd
+
+--
+Gerd Knorr <kraxel@bytesex.org>
diff --git a/README b/README
new file mode 100644
index 0000000..c4ed599
--- /dev/null
+++ b/README
@@ -0,0 +1,82 @@
+
+This is a small collection of input layer utilities. I wrote them
+mainly for testing and debugging, but maybe others find them useful
+too :-)
+
+
+lsinput
+=======
+
+probe and list all devices
+
+
+input-event
+===========
+
+listen for events and print them. Expects a device number as argument
+(0 == /dev/input/event0, ...).
+
+ -t <sec> set timeout, quits after <sec> seconds without input.
+ default is 10
+ -g grab device using EVIOCGRAB, i.e. get exclusive access to
+ the device
+
+
+input-kbd
+=========
+
+read/write keyboard maps (scancode => linux keycode). Also expects a
+device number as argument.
+
+If the input device supports maps, it will print them to stdout.
+Looks like this (AT Keyboard):
+
+ 0x0001 = 67 # KEY_F9
+ 0x0002 = 65 # KEY_F7
+ 0x0003 = 63 # KEY_F5
+ 0x0004 = 61 # KEY_F3
+ [ ... ]
+
+If the device doesn't support maps the utility just prints the keys
+and/or buttons supported by the device (my mouse):
+
+ bits: BTN_LEFT
+ bits: BTN_RIGHT
+ bits: BTN_MIDDLE
+
+If you pass a map file via -f switch the utility will parse it and
+reconfigure the device. Syntax is identical to the maps printed out,
+i.e. you can dump the current map to some file, edit it and then apply
+the changes. The key names are also accepted, i.e. both this ...
+
+ 0x0001 = 67
+
+... and this ...
+
+ 0x0001 = KEY_F9
+
+... works.
+
+
+input-send
+==========
+
+small daemon which reads from a input device and sends it over the
+network to everyone who connects. Listens on tcp port 1234.
+
+
+input-recv
+==========
+
+the receiving end for the send utility. Connects to localhost:1234
+right now and prints stuff to stderr. Plan is to put events into
+/dev/input/uinput some day which basically gives you a remote input
+device.
+
+
+Have fun,
+
+ Gerd
+
+--
+Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
diff --git a/input-events.c b/input-events.c
new file mode 100644
index 0000000..c525757
--- /dev/null
+++ b/input-events.c
@@ -0,0 +1,132 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/select.h>
+
+#include "input.h"
+
+/* ------------------------------------------------------------------ */
+
+static void show_events(int nr, int timeout, int grab)
+{
+ struct input_event event;
+ struct timeval tv;
+ int fd, quit;
+ fd_set set;
+
+ fd = device_open(nr,1);
+ if (-1 == fd)
+ return;
+ device_info(fd);
+
+ if (grab) {
+ if (-1 == ioctl(fd,EVIOCGRAB,1)) {
+ perror("ioctl EVIOCGRAB(1)");
+ close(fd);
+ return;
+ }
+ fprintf(stderr,"grabbed input device\n");
+ }
+
+ fprintf(stderr,"waiting for events\n");
+ quit = 0;
+ for (;;) {
+ /* wait for input */
+ FD_ZERO(&set);
+ FD_SET(fd,&set);
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ switch (select(fd+1,&set,NULL,NULL,&tv)) {
+ case -1:
+ perror("select");
+ quit = 1;
+ break;
+ case 0:
+ fprintf(stderr,"timeout, quitting\n");
+ quit = 1;
+ break;
+ }
+ if (quit)
+ break;
+
+ /* read input */
+ if (FD_ISSET(fd,&set)) {
+ switch (read(fd,&event,sizeof(event))) {
+ case -1:
+ perror("read");
+ quit = 1;
+ break;
+ case 0:
+ fprintf(stderr,"EOF\n");
+ quit = 1;
+ break;
+ default:
+ print_event(&event);
+ break;
+ }
+ }
+ if (quit)
+ break;
+ }
+
+ if (grab) {
+ if (-1 == ioctl(fd,EVIOCGRAB,0)) {
+ perror("ioctl EVIOCGRAB(0)");
+ close(fd);
+ return;
+ }
+ fprintf(stderr,"released input device\n");
+ }
+ close(fd);
+}
+
+static int usage(char *prog, int error)
+{
+ fprintf(error ? stderr : stdout,
+ "usage: %s"
+ " [ -g ] [ -t <sec> ]"
+ " devnr\n",
+ prog);
+ exit(error);
+}
+
+int main(int argc, char *argv[])
+{
+ int timeout = 10;
+ int grab = 0;
+ int c,devnr;
+
+ for (;;) {
+ if (-1 == (c = getopt(argc, argv, "hgt:")))
+ break;
+ switch (c) {
+ case 't':
+ timeout = atoi(optarg);
+ break;
+ case 'g':
+ grab = 1;
+ break;
+ case 'h':
+ usage(argv[0],0);
+ default:
+ usage(argv[0],1);
+ }
+ }
+
+ if (optind == argc)
+ usage(argv[0],1);
+
+ devnr = atoi(argv[optind]);
+ show_events(devnr,timeout,grab);
+ return 0;
+}
+
+/* ---------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/input-kbd.c b/input-kbd.c
new file mode 100644
index 0000000..fbe3f27
--- /dev/null
+++ b/input-kbd.c
@@ -0,0 +1,260 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/select.h>
+
+#include "input.h"
+
+struct kbd_entry {
+ int scancode;
+ int keycode;
+};
+
+struct kbd_map {
+ struct kbd_entry *map;
+ int keys;
+ int size;
+ int alloc;
+};
+
+/* ------------------------------------------------------------------ */
+
+static struct kbd_map* kbd_map_read(int fd)
+{
+ struct kbd_entry entry;
+ struct kbd_map *map;
+ int rc;
+
+ map = malloc(sizeof(*map));
+ memset(map,0,sizeof(*map));
+ for (map->size = 0; map->size < 65536; map->size++) {
+ entry.scancode = map->size;
+ entry.keycode = KEY_RESERVED;
+ rc = ioctl(fd, EVIOCGKEYCODE, &entry);
+ if (rc < 0) {
+ map->size--;
+ break;
+ }
+ if (map->size >= map->alloc) {
+ map->alloc += 64;
+ map->map = realloc(map->map, map->alloc * sizeof(entry));
+ }
+ map->map[map->size] = entry;
+
+ if (KEY_RESERVED != entry.keycode)
+ map->keys++;
+ }
+ if (map->keys) {
+ fprintf(stderr,"map: %d keys, size: %d/%d\n",
+ map->keys, map->size, map->alloc);
+ return map;
+ } else {
+ free(map);
+ return NULL;
+ }
+}
+
+static int kbd_map_write(int fh, struct kbd_map *map)
+{
+ int i,rc;
+
+ for (i = 0; i < map->size; i++) {
+ rc = ioctl(fh, EVIOCSKEYCODE, &map->map[i]);
+ if (0 != rc) {
+ fprintf(stderr,"ioctl EVIOCSKEYCODE(%d,%d): %s\n",
+ map->map[i].scancode,map->map[i].keycode,
+ strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void kbd_key_print(FILE *fp, int scancode, int keycode)
+{
+ fprintf(fp, "0x%04x = %3d # %s\n",
+ scancode, keycode, key_name(keycode));
+}
+
+static void kbd_map_print(FILE *fp, struct kbd_map *map, int complete)
+{
+ int i;
+
+ for (i = 0; i < map->size; i++) {
+ if (!complete && KEY_RESERVED == map->map[i].keycode)
+ continue;
+ kbd_key_print(fp,map->map[i].scancode,map->map[i].keycode);
+ }
+}
+
+static int kbd_map_parse(FILE *fp, struct kbd_map *map)
+{
+ struct kbd_entry entry;
+ char line[80],scancode[80],keycode[80];
+ int i;
+
+ while (NULL != fgets(line,sizeof(line),fp)) {
+ if (2 != sscanf(line," %80s = %80s", scancode, keycode)) {
+ fprintf(stderr,"parse error: %s",line);
+ return -1;
+ }
+
+ /* parse scancode */
+ if (0 == strncasecmp(scancode,"0x",2)) {
+ entry.scancode = strtol(scancode, NULL, 16);
+ } else {
+ entry.scancode = strtol(scancode, NULL, 10);
+ }
+ if (entry.scancode < 0 ||
+ entry.scancode >= map->size) {
+ fprintf(stderr,"scancode %d out of range (0-%d)\n",
+ entry.scancode,map->size);
+ return -1;
+ }
+
+ /* parse keycode */
+ for (i = 0; i < KEY_MAX; i++) {
+ if (!KEY_NAME[i])
+ continue;
+ if (0 == strcmp(keycode,KEY_NAME[i]))
+ break;
+ }
+ if (i == KEY_MAX)
+ entry.keycode = atoi(keycode);
+ else
+ entry.keycode = i;
+
+ fprintf(stderr,"set: ");
+ kbd_key_print(stderr,entry.scancode,entry.keycode);
+ map->map[entry.scancode] = entry;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static void kbd_print_bits(int fd)
+{
+ BITFIELD bits[KEY_MAX/sizeof(BITFIELD)];
+ int rc,bit;
+
+ rc = ioctl(fd,EVIOCGBIT(EV_KEY,sizeof(bits)),bits);
+ if (rc < 0)
+ return;
+ for (bit = 0; bit < rc*8 && bit < KEY_MAX; bit++) {
+ if (!test_bit(bit,bits))
+ continue;
+ if (KEY_NAME[bit]) {
+ fprintf(stderr,"bits: %s\n", KEY_NAME[bit]);
+ } else {
+ fprintf(stderr,"bits: unknown [%d]\n", bit);
+ }
+ }
+}
+
+static void show_kbd(int nr)
+{
+ struct kbd_map *map;
+ int fd;
+
+ fd = device_open(nr,1);
+ if (-1 == fd)
+ return;
+ device_info(fd);
+
+ map = kbd_map_read(fd);
+ if (NULL != map) {
+ kbd_map_print(stdout,map,0);
+ } else {
+ kbd_print_bits(fd);
+ }
+
+ close(fd);
+}
+
+static int set_kbd(int nr, char *mapfile)
+{
+ struct kbd_map *map;
+ FILE *fp;
+ int fd;
+
+ fd = device_open(nr,1);
+ if (-1 == fd)
+ return -1;
+
+ map = kbd_map_read(fd);
+ if (NULL == map) {
+ fprintf(stderr,"device has no map\n");
+ close(fd);
+ return -1;
+ }
+
+ if (0 == strcmp(mapfile,"-"))
+ fp = stdin;
+ else {
+ fp = fopen(mapfile,"r");
+ if (NULL == fp) {
+ fprintf(stderr,"open %s: %s\n",mapfile,strerror(errno));
+ close(fd);
+ return -1;
+ }
+ }
+
+ if (0 != kbd_map_parse(fp,map) ||
+ 0 != kbd_map_write(fd,map)) {
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+static int usage(char *prog, int error)
+{
+ fprintf(error ? stderr : stdout,
+ "usage: %s [ -f file ] devnr\n",
+ prog);
+ exit(error);
+}
+
+int main(int argc, char *argv[])
+{
+ int c,devnr;
+ char *mapfile = NULL;
+
+ for (;;) {
+ if (-1 == (c = getopt(argc, argv, "hf:")))
+ break;
+ switch (c) {
+ case 'f':
+ mapfile = optarg;
+ break;
+ case 'h':
+ usage(argv[0],0);
+ default:
+ usage(argv[0],1);
+ }
+ }
+
+ if (optind == argc)
+ usage(argv[0],1);
+
+ devnr = atoi(argv[optind]);
+ if (mapfile) {
+ set_kbd(devnr,mapfile);
+ } else {
+ show_kbd(devnr);
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/input-recv.c b/input-recv.c
new file mode 100644
index 0000000..4a59f3c
--- /dev/null
+++ b/input-recv.c
@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "input.h"
+#include "tcp.h"
+
+/* ------------------------------------------------------------------ */
+
+static int usage(char *prog, int error)
+{
+ fprintf(error ? stderr : stdout,
+ "usage: %s"
+ "\n",
+ prog);
+ exit(error);
+}
+
+int main(int argc, char *argv[])
+{
+ char *addr = NULL;
+ char *port = NULL;
+ char *host = "localhost";
+ char *serv = "1234";
+ struct addrinfo ask;
+ int c,sock;
+
+ memset(&ask,0,sizeof(ask));
+ ask.ai_family = PF_UNSPEC;
+ ask.ai_socktype = SOCK_STREAM;
+
+ for (;;) {
+ if (-1 == (c = getopt(argc, argv, "h")))
+ break;
+ switch (c) {
+ case 'h':
+ usage(argv[0],0);
+ default:
+ usage(argv[0],1);
+ }
+ }
+
+ tcp_verbose = 1;
+ sock = tcp_connect(&ask,addr,port,host,serv);
+ if (-1 == sock)
+ exit(1);
+
+ for (;;) {
+ struct input_event ev;
+ fd_set set;
+ int rc;
+
+ FD_ZERO(&set);
+ FD_SET(sock,&set);
+ rc = select(sock+1,&set,NULL,NULL,NULL);
+ if (1 != rc) {
+ perror("select");
+ exit(1);
+ }
+
+ rc = read(sock,&ev,sizeof(ev));
+ if (rc != sizeof(ev)) {
+ fprintf(stderr,"read ret=%d (expected %d), errno=%s\n",
+ rc,(int)sizeof(ev),strerror(errno));
+ exit(1);
+ }
+
+ /* convert from network byte order ... */
+ ev.time.tv_sec = ntohl(ev.time.tv_sec);
+ ev.time.tv_usec = ntohl(ev.time.tv_usec);
+ ev.type = ntohs(ev.type);
+ ev.code = ntohs(ev.code);
+ ev.value = ntohl(ev.value);
+
+ print_event(&ev);
+ }
+
+ return 0;
+}
+
+/* ---------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/input-send.c b/input-send.c
new file mode 100644
index 0000000..946832f
--- /dev/null
+++ b/input-send.c
@@ -0,0 +1,234 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "list.h"
+#include "input.h"
+#include "tcp.h"
+
+struct connection {
+ int socket;
+ struct sockaddr_storage peer;
+ struct list_head list;
+ char peerhost[INET6_ADDRSTRLEN+1];
+ char peerserv[33];
+};
+
+/* ------------------------------------------------------------------ */
+
+int debug = 0;
+int timeout = 10;
+int slisten;
+int input;
+LIST_HEAD(connections);
+
+static void conn_new(void)
+{
+ struct connection *conn;
+ int len;
+
+ conn = malloc(sizeof(conn));
+ memset(conn,0,sizeof(conn));
+ len = sizeof(conn->peer);
+ conn->socket = accept(slisten,(struct sockaddr*)&conn->peer,&len);
+ if (-1 == conn->socket) {
+ if (tcp_verbose)
+ perror("accept");
+ free(conn);
+ return;
+ }
+ if (tcp_verbose) {
+ getnameinfo((struct sockaddr*)&conn->peer,len,
+ conn->peerhost,INET6_ADDRSTRLEN,
+ conn->peerserv,32,
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ fprintf(stderr,"connect from [%s]\n",conn->peerhost);
+ }
+ fcntl(conn->socket,F_SETFL,O_NONBLOCK);
+
+ /* FIXME: access control */
+ list_add_tail(&conn->list,&connections);
+}
+
+static void conn_del(struct connection *conn)
+{
+ if (tcp_verbose)
+ fprintf(stderr,"connection from [%s] closed\n",conn->peerhost);
+ close(conn->socket);
+ list_del(&conn->list);
+ free(conn);
+}
+
+static void input_bcast(struct input_event *ev)
+{
+ struct connection *conn;
+ struct list_head *item;
+ struct list_head *safe;
+ int rc;
+
+ if (debug)
+ print_event(ev);
+
+ /* convert to network byte order ... */
+ ev->time.tv_sec = htonl(ev->time.tv_sec);
+ ev->time.tv_usec = htonl(ev->time.tv_usec);
+ ev->type = htons(ev->type);
+ ev->code = htons(ev->code);
+ ev->value = htonl(ev->value);
+
+ /* send out */
+ list_for_each_safe(item,safe,&connections) {
+ conn = list_entry(item, struct connection, list);
+ rc = write(conn->socket,ev,sizeof(*ev));
+ if (rc != sizeof(*ev))
+ conn_del(conn);
+ }
+}
+
+static void loop(void)
+{
+ struct connection *conn;
+ struct list_head *item;
+ struct list_head *safe;
+ fd_set set;
+ struct timeval tv;
+ int max,rc;
+
+ for (;;) {
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ FD_ZERO(&set);
+ FD_SET(slisten,&set);
+ max = slisten;
+
+ FD_SET(input,&set);
+ if (max < input)
+ max = input;
+
+ list_for_each(item,&connections) {
+ conn = list_entry(item, struct connection, list);
+ FD_SET(conn->socket,&set);
+ if (max < conn->socket)
+ max = conn->socket;
+ }
+
+ rc = select(max+1,&set,NULL,NULL,&tv);
+ if (rc < 0) {
+ /* Huh? */
+ perror("select");
+ exit(1);
+ }
+ if (0 == rc) {
+ /* timeout */
+ continue;
+ }
+
+ list_for_each_safe(item,safe,&connections) {
+ conn = list_entry(item, struct connection, list);
+ if (FD_ISSET(conn->socket,&set)) {
+ char dummy[16];
+ rc = read(conn->socket,dummy,sizeof(dummy));
+ if (rc <= 0)
+ conn_del(conn);
+ }
+ }
+
+ if (FD_ISSET(input,&set)) {
+ struct input_event ev;
+ rc = read(input,&ev,sizeof(ev));
+ if (rc != sizeof(ev))
+ exit(1);
+ input_bcast(&ev);
+ }
+
+ if (FD_ISSET(slisten,&set))
+ conn_new();
+ }
+}
+
+/* ------------------------------------------------------------------ */
+
+static void daemonize(void)
+{
+ switch (fork()) {
+ case -1:
+ perror("fork");
+ exit(1);
+ case 0:
+ close(0); close(1); close(2);
+ setsid();
+ open("/dev/null",O_RDWR); dup(0); dup(0);
+ break;
+ default:
+ exit(0);
+ }
+}
+
+static int usage(char *prog, int error)
+{
+ fprintf(error ? stderr : stdout,
+ "usage: %s"
+ " [ -t <sec> ] [ -g ]"
+ " devnr\n",
+ prog);
+ exit(error);
+}
+
+int main(int argc, char *argv[])
+{
+ int grab = 0;
+ char *addr = NULL;
+ char *port = "1234";
+ int c,devnr;
+ struct addrinfo ask;
+
+ memset(&ask,0,sizeof(ask));
+ ask.ai_family = PF_UNSPEC;
+ ask.ai_socktype = SOCK_STREAM;
+
+ for (;;) {
+ if (-1 == (c = getopt(argc, argv, "hdgt:")))
+ break;
+ switch (c) {
+ case 'd':
+ debug = 1;
+ tcp_verbose = 1;
+ break;
+ case 't':
+ timeout = atoi(optarg);
+ break;
+ case 'g':
+ grab = 1;
+ break;
+ case 'h':
+ usage(argv[0],0);
+ default:
+ usage(argv[0],1);
+ }
+ }
+
+ if (optind == argc)
+ usage(argv[0],1);
+ devnr = atoi(argv[optind]);
+ input = device_open(devnr,debug);
+ if (-1 == input)
+ exit(1);
+
+ slisten = tcp_listen(&ask,addr,port);
+ if (-1 == slisten)
+ exit(1);
+
+ if (!debug)
+ daemonize();
+ loop();
+ return 0;
+}
+
+/* ---------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/input.c b/input.c
new file mode 100644
index 0000000..9d27d5a
--- /dev/null
+++ b/input.c
@@ -0,0 +1,132 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include "input.h"
+
+/* ------------------------------------------------------------------ */
+
+char *EV_NAME[EV_MAX] = {
+#include "EV.h"
+};
+
+char *REL_NAME[REL_MAX] = {
+#include "REL.h"
+};
+
+char *KEY_NAME[KEY_MAX] = {
+#include "KEY.h"
+#include "BTN.h"
+};
+
+char *BUS_NAME[] = {
+#include "BUS.h"
+};
+
+/* ------------------------------------------------------------------ */
+
+int device_open(int nr, int verbose)
+{
+ char filename[32];
+ int fd, version;
+
+ snprintf(filename,sizeof(filename),
+ "/dev/input/event%d",nr);
+ fd = open(filename,O_RDONLY);
+ if (-1 == fd) {
+ fprintf(stderr,"open %s: %s\n",
+ filename,strerror(errno));
+ return -1;
+ }
+ if (verbose)
+ fprintf(stderr,"%s\n",filename);
+
+ if (-1 == ioctl(fd,EVIOCGVERSION,&version)) {
+ perror("ioctl EVIOCGVERSION");
+ close(fd);
+ return -1;
+ }
+ if (EV_VERSION != version) {
+ fprintf(stderr, "protocol version mismatch (expected %d, got %d)\n",
+ EV_VERSION, version);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+void device_info(int fd)
+{
+ struct input_id id;
+ BITFIELD bits[32];
+ char buf[32];
+ int rc,bit;
+
+ rc = ioctl(fd,EVIOCGID,&id);
+ if (rc >= 0)
+ fprintf(stderr,
+ " bustype : %s\n"
+ " vendor : 0x%x\n"
+ " product : 0x%x\n"
+ " version : %d\n",
+ BUS_NAME[id.bustype],
+ id.vendor, id.product, id.version);
+ rc = ioctl(fd,EVIOCGNAME(sizeof(buf)),buf);
+ if (rc >= 0)
+ fprintf(stderr," name : \"%.*s\"\n",rc,buf);
+ rc = ioctl(fd,EVIOCGPHYS(sizeof(buf)),buf);
+ if (rc >= 0)
+ fprintf(stderr," phys : \"%.*s\"\n",rc,buf);
+ rc = ioctl(fd,EVIOCGUNIQ(sizeof(buf)),buf);
+ if (rc >= 0)
+ fprintf(stderr," uniq : \"%.*s\"\n",rc,buf);
+ rc = ioctl(fd,EVIOCGBIT(0,sizeof(bits)),bits);
+ if (rc >= 0) {
+ fprintf(stderr," bits ev :");
+ for (bit = 0; bit < rc*8 && bit < EV_MAX; bit++) {
+ if (test_bit(bit,bits))
+ fprintf(stderr," %s", EV_NAME[bit]);
+ }
+ fprintf(stderr,"\n");
+ }
+ fprintf(stderr,"\n");
+}
+
+/* ------------------------------------------------------------------ */
+
+void print_event(struct input_event *event)
+{
+ char ts[32];
+ time_t t;
+
+ t = event->time.tv_sec;
+ strftime(ts,sizeof(ts),"%H:%M:%S",localtime(&t));
+ fprintf(stderr,"%s.%06ld: %s",ts,event->time.tv_usec,
+ EV_NAME[event->type]);
+ switch (event->type) {
+ case EV_KEY:
+ fprintf(stderr," %s %s",
+ KEY_NAME[event->code],
+ event->value ? "pressed" : "released");
+ break;
+ case EV_REL:
+ fprintf(stderr," %s %d",
+ REL_NAME[event->code], event->value);
+ break;
+ default:
+ fprintf(stderr," code=%u value=%d",
+ (unsigned int)event->code, event->value);
+ }
+ fprintf(stderr,"\n");
+}
+
+/* ---------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/input.h b/input.h
new file mode 100644
index 0000000..466cfde
--- /dev/null
+++ b/input.h
@@ -0,0 +1,30 @@
+#include <inttypes.h>
+
+#include <sys/ioctl.h>
+#include "linux-input.h"
+
+#define ev_name(code) ((code) < EV_MAX && EV_NAME[code] ? EV_NAME[code] : "???")
+#define rel_name(code) ((code) < REL_MAX && REL_NAME[code] ? REL_NAME[code] : "???")
+#define key_name(code) ((code) < KEY_MAX && KEY_NAME[code] ? KEY_NAME[code] : "???")
+
+#define BITFIELD uint32_t
+
+extern char *EV_NAME[EV_MAX];
+extern char *REL_NAME[REL_MAX];
+extern char *KEY_NAME[KEY_MAX];
+extern char *BUS_NAME[];
+
+static __inline__ int test_bit(int nr, BITFIELD * addr)
+{
+ BITFIELD mask;
+
+ addr += nr >> 5;
+ mask = 1 << (nr & 0x1f);
+ return ((mask & *addr) != 0);
+}
+
+/* ------------------------------------------------------------------ */
+
+int device_open(int nr, int verbose);
+void device_info(int fd);
+void print_event(struct input_event *event);
diff --git a/linux-input.h b/linux-input.h
new file mode 100644
index 0000000..8c5b194
--- /dev/null
+++ b/linux-input.h
@@ -0,0 +1,927 @@
+/* from 2.6.0-test3 */
+
+#ifndef _INPUT_H
+#define _INPUT_H
+
+/*
+ * Copyright (c) 1999-2002 Vojtech Pavlik
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifdef __KERNEL__
+#include <linux/time.h>
+#include <linux/list.h>
+#else
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <asm/types.h>
+#endif
+
+/*
+ * The event structure itself
+ */
+
+struct input_event {
+ struct timeval time;
+ __u16 type;
+ __u16 code;
+ __s32 value;
+};
+
+/*
+ * Protocol version.
+ */
+
+#define EV_VERSION 0x010000
+
+/*
+ * IOCTLs (0x00 - 0x7f)
+ */
+
+struct input_id {
+ __u16 bustype;
+ __u16 vendor;
+ __u16 product;
+ __u16 version;
+};
+
+struct input_absinfo {
+ __s32 value;
+ __s32 minimum;
+ __s32 maximum;
+ __s32 fuzz;
+ __s32 flat;
+};
+
+#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
+#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */
+#define EVIOCGREP _IOR('E', 0x03, int[2]) /* get repeat settings */
+#define EVIOCSREP _IOW('E', 0x03, int[2]) /* get repeat settings */
+#define EVIOCGKEYCODE _IOR('E', 0x04, int[2]) /* get keycode */
+#define EVIOCSKEYCODE _IOW('E', 0x04, int[2]) /* set keycode */
+
+#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */
+#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */
+#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */
+
+#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global keystate */
+#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */
+#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */
+
+#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + ev, len) /* get event bits */
+#define EVIOCGABS(abs) _IOR('E', 0x40 + abs, struct input_absinfo) /* get abs value/limits */
+#define EVIOCSABS(abs) _IOW('E', 0xc0 + abs, struct input_absinfo) /* set abs value/limits */
+
+#define EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect)) /* send a force effect to a force feedback device */
+#define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */
+#define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */
+
+#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
+
+/*
+ * Event types
+ */
+
+#define EV_SYN 0x00
+#define EV_KEY 0x01
+#define EV_REL 0x02
+#define EV_ABS 0x03
+#define EV_MSC 0x04
+#define EV_LED 0x11
+#define EV_SND 0x12
+#define EV_REP 0x14
+#define EV_FF 0x15
+#define EV_PWR 0x16
+#define EV_FF_STATUS 0x17
+#define EV_MAX 0x1f
+
+/*
+ * Synchronization events.
+ */
+
+#define SYN_REPORT 0
+#define SYN_CONFIG 1
+
+/*
+ * Keys and buttons
+ */
+
+#define KEY_RESERVED 0
+#define KEY_ESC 1
+#define KEY_1 2
+#define KEY_2 3
+#define KEY_3 4
+#define KEY_4 5
+#define KEY_5 6
+#define KEY_6 7
+#define KEY_7 8
+#define KEY_8 9
+#define KEY_9 10
+#define KEY_0 11
+#define KEY_MINUS 12
+#define KEY_EQUAL 13
+#define KEY_BACKSPACE 14
+#define KEY_TAB 15
+#define KEY_Q 16
+#define KEY_W 17
+#define KEY_E 18
+#define KEY_R 19
+#define KEY_T 20
+#define KEY_Y 21
+#define KEY_U 22
+#define KEY_I 23
+#define KEY_O 24
+#define KEY_P 25
+#define KEY_LEFTBRACE 26
+#define KEY_RIGHTBRACE 27
+#define KEY_ENTER 28
+#define KEY_LEFTCTRL 29
+#define KEY_A 30
+#define KEY_S 31
+#define KEY_D 32
+#define KEY_F 33
+#define KEY_G 34
+#define KEY_H 35
+#define KEY_J 36
+#define KEY_K 37
+#define KEY_L 38
+#define KEY_SEMICOLON 39
+#define KEY_APOSTROPHE 40
+#define KEY_GRAVE 41
+#define KEY_LEFTSHIFT 42
+#define KEY_BACKSLASH 43
+#define KEY_Z 44
+#define KEY_X 45
+#define KEY_C 46
+#define KEY_V 47
+#define KEY_B 48
+#define KEY_N 49
+#define KEY_M 50
+#define KEY_COMMA 51
+#define KEY_DOT 52
+#define KEY_SLASH 53
+#define KEY_RIGHTSHIFT 54
+#define KEY_KPASTERISK 55
+#define KEY_LEFTALT 56
+#define KEY_SPACE 57
+#define KEY_CAPSLOCK 58
+#define KEY_F1 59
+#define KEY_F2 60
+#define KEY_F3 61
+#define KEY_F4 62
+#define KEY_F5 63
+#define KEY_F6 64
+#define KEY_F7 65
+#define KEY_F8 66
+#define KEY_F9 67
+#define KEY_F10 68
+#define KEY_NUMLOCK 69
+#define KEY_SCROLLLOCK 70
+#define KEY_KP7 71
+#define KEY_KP8 72
+#define KEY_KP9 73
+#define KEY_KPMINUS 74
+#define KEY_KP4 75
+#define KEY_KP5 76
+#define KEY_KP6 77
+#define KEY_KPPLUS 78
+#define KEY_KP1 79
+#define KEY_KP2 80
+#define KEY_KP3 81
+#define KEY_KP0 82
+#define KEY_KPDOT 83
+#define KEY_103RD 84
+#define KEY_F13 85
+#define KEY_102ND 86
+#define KEY_F11 87
+#define KEY_F12 88
+#define KEY_F14 89
+#define KEY_F15 90
+#define KEY_F16 91
+#define KEY_F17 92
+#define KEY_F18 93
+#define KEY_F19 94
+#define KEY_F20 95
+#define KEY_KPENTER 96
+#define KEY_RIGHTCTRL 97
+#define KEY_KPSLASH 98
+#define KEY_SYSRQ 99
+#define KEY_RIGHTALT 100
+#define KEY_LINEFEED 101
+#define KEY_HOME 102
+#define KEY_UP 103
+#define KEY_PAGEUP 104
+#define KEY_LEFT 105
+#define KEY_RIGHT 106
+#define KEY_END 107
+#define KEY_DOWN 108
+#define KEY_PAGEDOWN 109
+#define KEY_INSERT 110
+#define KEY_DELETE 111
+#define KEY_MACRO 112
+#define KEY_MUTE 113
+#define KEY_VOLUMEDOWN 114
+#define KEY_VOLUMEUP 115
+#define KEY_POWER 116
+#define KEY_KPEQUAL 117
+#define KEY_KPPLUSMINUS 118
+#define KEY_PAUSE 119
+#define KEY_F21 120
+#define KEY_F22 121
+#define KEY_F23 122
+#define KEY_F24 123
+#define KEY_KPCOMMA 124
+#define KEY_LEFTMETA 125
+#define KEY_RIGHTMETA 126
+#define KEY_COMPOSE 127
+
+#define KEY_STOP 128
+#define KEY_AGAIN 129
+#define KEY_PROPS 130
+#define KEY_UNDO 131
+#define KEY_FRONT 132
+#define KEY_COPY 133
+#define KEY_OPEN 134
+#define KEY_PASTE 135
+#define KEY_FIND 136
+#define KEY_CUT 137
+#define KEY_HELP 138
+#define KEY_MENU 139
+#define KEY_CALC 140
+#define KEY_SETUP 141
+#define KEY_SLEEP 142
+#define KEY_WAKEUP 143
+#define KEY_FILE 144
+#define KEY_SENDFILE 145
+#define KEY_DELETEFILE 146
+#define KEY_XFER 147
+#define KEY_PROG1 148
+#define KEY_PROG2 149
+#define KEY_WWW 150
+#define KEY_MSDOS 151
+#define KEY_COFFEE 152
+#define KEY_DIRECTION 153
+#define KEY_CYCLEWINDOWS 154
+#define KEY_MAIL 155
+#define KEY_BOOKMARKS 156
+#define KEY_COMPUTER 157
+#define KEY_BACK 158
+#define KEY_FORWARD 159
+#define KEY_CLOSECD 160
+#define KEY_EJECTCD 161
+#define KEY_EJECTCLOSECD 162
+#define KEY_NEXTSONG 163
+#define KEY_PLAYPAUSE 164
+#define KEY_PREVIOUSSONG 165
+#define KEY_STOPCD 166
+#define KEY_RECORD 167
+#define KEY_REWIND 168
+#define KEY_PHONE 169
+#define KEY_ISO 170
+#define KEY_CONFIG 171
+#define KEY_HOMEPAGE 172
+#define KEY_REFRESH 173
+#define KEY_EXIT 174
+#define KEY_MOVE 175
+#define KEY_EDIT 176
+#define KEY_SCROLLUP 177
+#define KEY_SCROLLDOWN 178
+#define KEY_KPLEFTPAREN 179
+#define KEY_KPRIGHTPAREN 180
+
+#define KEY_INTL1 181
+#define KEY_INTL2 182
+#define KEY_INTL3 183
+#define KEY_INTL4 184
+#define KEY_INTL5 185
+#define KEY_INTL6 186
+#define KEY_INTL7 187
+#define KEY_INTL8 188
+#define KEY_INTL9 189
+#define KEY_LANG1 190
+#define KEY_LANG2 191
+#define KEY_LANG3 192
+#define KEY_LANG4 193
+#define KEY_LANG5 194
+#define KEY_LANG6 195
+#define KEY_LANG7 196
+#define KEY_LANG8 197
+#define KEY_LANG9 198
+
+#define KEY_PLAYCD 200
+#define KEY_PAUSECD 201
+#define KEY_PROG3 202
+#define KEY_PROG4 203
+#define KEY_SUSPEND 205
+#define KEY_CLOSE 206
+#define KEY_PLAY 207
+#define KEY_FASTFORWARD 208
+#define KEY_BASSBOOST 209
+#define KEY_PRINT 210
+#define KEY_HP 211
+#define KEY_CAMERA 212
+#define KEY_SOUND 213
+#define KEY_QUESTION 214
+#define KEY_EMAIL 215
+#define KEY_CHAT 216
+#define KEY_SEARCH 217
+#define KEY_CONNECT 218
+#define KEY_FINANCE 219
+#define KEY_SPORT 220
+#define KEY_SHOP 221
+#define KEY_ALTERASE 222
+#define KEY_CANCEL 223
+#define KEY_BRIGHTNESSDOWN 224
+#define KEY_BRIGHTNESSUP 225
+#define KEY_MEDIA 226
+
+#define KEY_UNKNOWN 240
+
+#define BTN_MISC 0x100
+#define BTN_0 0x100
+#define BTN_1 0x101
+#define BTN_2 0x102
+#define BTN_3 0x103
+#define BTN_4 0x104
+#define BTN_5 0x105
+#define BTN_6 0x106
+#define BTN_7 0x107
+#define BTN_8 0x108
+#define BTN_9 0x109
+
+#define BTN_MOUSE 0x110
+#define BTN_LEFT 0x110
+#define BTN_RIGHT 0x111
+#define BTN_MIDDLE 0x112
+#define BTN_SIDE 0x113
+#define BTN_EXTRA 0x114
+#define BTN_FORWARD 0x115
+#define BTN_BACK 0x116
+#define BTN_TASK 0x117
+
+#define BTN_JOYSTICK 0x120
+#define BTN_TRIGGER 0x120
+#define BTN_THUMB 0x121
+#define BTN_THUMB2 0x122
+#define BTN_TOP 0x123
+#define BTN_TOP2 0x124
+#define BTN_PINKIE 0x125
+#define BTN_BASE 0x126
+#define BTN_BASE2 0x127
+#define BTN_BASE3 0x128
+#define BTN_BASE4 0x129
+#define BTN_BASE5 0x12a
+#define BTN_BASE6 0x12b
+#define BTN_DEAD 0x12f
+
+#define BTN_GAMEPAD 0x130
+#define BTN_A 0x130
+#define BTN_B 0x131
+#define BTN_C 0x132
+#define BTN_X 0x133
+#define BTN_Y 0x134
+#define BTN_Z 0x135
+#define BTN_TL 0x136
+#define BTN_TR 0x137
+#define BTN_TL2 0x138
+#define BTN_TR2 0x139
+#define BTN_SELECT 0x13a
+#define BTN_START 0x13b
+#define BTN_MODE 0x13c
+#define BTN_THUMBL 0x13d
+#define BTN_THUMBR 0x13e
+
+#define BTN_DIGI 0x140
+#define BTN_TOOL_PEN 0x140
+#define BTN_TOOL_RUBBER 0x141
+#define BTN_TOOL_BRUSH 0x142
+#define BTN_TOOL_PENCIL 0x143
+#define BTN_TOOL_AIRBRUSH 0x144
+#define BTN_TOOL_FINGER 0x145
+#define BTN_TOOL_MOUSE 0x146
+#define BTN_TOOL_LENS 0x147
+#define BTN_TOUCH 0x14a
+#define BTN_STYLUS 0x14b
+#define BTN_STYLUS2 0x14c
+
+#define BTN_WHEEL 0x150
+#define BTN_GEAR_DOWN 0x150
+#define BTN_GEAR_UP 0x151
+
+#define KEY_OK 0x160
+#define KEY_SELECT 0x161
+#define KEY_GOTO 0x162
+#define KEY_CLEAR 0x163
+#define KEY_POWER2 0x164
+#define KEY_OPTION 0x165
+#define KEY_INFO 0x166
+#define KEY_TIME 0x167
+#define KEY_VENDOR 0x168
+#define KEY_ARCHIVE 0x169
+#define KEY_PROGRAM 0x16a
+#define KEY_CHANNEL 0x16b
+#define KEY_FAVORITES 0x16c
+#define KEY_EPG 0x16d
+#define KEY_PVR 0x16e
+#define KEY_MHP 0x16f
+#define KEY_LANGUAGE 0x170
+#define KEY_TITLE 0x171
+#define KEY_SUBTITLE 0x172
+#define KEY_ANGLE 0x173
+#define KEY_ZOOM 0x174
+#define KEY_MODE 0x175
+#define KEY_KEYBOARD 0x176
+#define KEY_SCREEN 0x177
+#define KEY_PC 0x178
+#define KEY_TV 0x179
+#define KEY_TV2 0x17a
+#define KEY_VCR 0x17b
+#define KEY_VCR2 0x17c
+#define KEY_SAT 0x17d
+#define KEY_SAT2 0x17e
+#define KEY_CD 0x17f
+#define KEY_TAPE 0x180
+#define KEY_RADIO 0x181
+#define KEY_TUNER 0x182
+#define KEY_PLAYER 0x183
+#define KEY_TEXT 0x184
+#define KEY_DVD 0x185
+#define KEY_AUX 0x186
+#define KEY_MP3 0x187
+#define KEY_AUDIO 0x188
+#define KEY_VIDEO 0x189
+#define KEY_DIRECTORY 0x18a
+#define KEY_LIST 0x18b
+#define KEY_MEMO 0x18c
+#define KEY_CALENDAR 0x18d
+#define KEY_RED 0x18e
+#define KEY_GREEN 0x18f
+#define KEY_YELLOW 0x190
+#define KEY_BLUE 0x191
+#define KEY_CHANNELUP 0x192
+#define KEY_CHANNELDOWN 0x193
+#define KEY_FIRST 0x194
+#define KEY_LAST 0x195
+#define KEY_AB 0x196
+#define KEY_NEXT 0x197
+#define KEY_RESTART 0x198
+#define KEY_SLOW 0x199
+#define KEY_SHUFFLE 0x19a
+#define KEY_BREAK 0x19b
+#define KEY_PREVIOUS 0x19c
+#define KEY_DIGITS 0x19d
+#define KEY_TEEN 0x19e
+#define KEY_TWEN 0x19f
+
+#define KEY_DEL_EOL 0x1c0
+#define KEY_DEL_EOS 0x1c1
+#define KEY_INS_LINE 0x1c2
+#define KEY_DEL_LINE 0x1c3
+
+#define KEY_MAX 0x1ff
+
+/*
+ * Relative axes
+ */
+
+#define REL_X 0x00
+#define REL_Y 0x01
+#define REL_Z 0x02
+#define REL_HWHEEL 0x06
+#define REL_DIAL 0x07
+#define REL_WHEEL 0x08
+#define REL_MISC 0x09
+#define REL_MAX 0x0f
+
+/*
+ * Absolute axes
+ */
+
+#define ABS_X 0x00
+#define ABS_Y 0x01
+#define ABS_Z 0x02
+#define ABS_RX 0x03
+#define ABS_RY 0x04
+#define ABS_RZ 0x05
+#define ABS_THROTTLE 0x06
+#define ABS_RUDDER 0x07
+#define ABS_WHEEL 0x08
+#define ABS_GAS 0x09
+#define ABS_BRAKE 0x0a
+#define ABS_HAT0X 0x10
+#define ABS_HAT0Y 0x11
+#define ABS_HAT1X 0x12
+#define ABS_HAT1Y 0x13
+#define ABS_HAT2X 0x14
+#define ABS_HAT2Y 0x15
+#define ABS_HAT3X 0x16
+#define ABS_HAT3Y 0x17
+#define ABS_PRESSURE 0x18
+#define ABS_DISTANCE 0x19
+#define ABS_TILT_X 0x1a
+#define ABS_TILT_Y 0x1b
+#define ABS_VOLUME 0x20
+#define ABS_MISC 0x28
+#define ABS_MAX 0x3f
+
+/*
+ * Misc events
+ */
+
+#define MSC_SERIAL 0x00
+#define MSC_PULSELED 0x01
+#define MSC_GESTURE 0x02
+#define MSC_MAX 0x07
+
+/*
+ * LEDs
+ */
+
+#define LED_NUML 0x00
+#define LED_CAPSL 0x01
+#define LED_SCROLLL 0x02
+#define LED_COMPOSE 0x03
+#define LED_KANA 0x04
+#define LED_SLEEP 0x05
+#define LED_SUSPEND 0x06
+#define LED_MUTE 0x07
+#define LED_MISC 0x08
+#define LED_MAX 0x0f
+
+/*
+ * Autorepeat values
+ */
+
+#define REP_DELAY 0x00
+#define REP_PERIOD 0x01
+#define REP_MAX 0x01
+
+/*
+ * Sounds
+ */
+
+#define SND_CLICK 0x00
+#define SND_BELL 0x01
+#define SND_TONE 0x02
+#define SND_MAX 0x07
+
+/*
+ * IDs.
+ */
+
+#define ID_BUS 0
+#define ID_VENDOR 1
+#define ID_PRODUCT 2
+#define ID_VERSION 3
+
+#define BUS_PCI 0x01
+#define BUS_ISAPNP 0x02
+#define BUS_USB 0x03
+#define BUS_HIL 0x04
+
+#define BUS_ISA 0x10
+#define BUS_I8042 0x11
+#define BUS_XTKBD 0x12
+#define BUS_RS232 0x13
+#define BUS_GAMEPORT 0x14
+#define BUS_PARPORT 0x15
+#define BUS_AMIGA 0x16
+#define BUS_ADB 0x17
+#define BUS_I2C 0x18
+#define BUS_HOST 0x19
+
+/*
+ * Values describing the status of an effect
+ */
+#define FF_STATUS_STOPPED 0x00
+#define FF_STATUS_PLAYING 0x01
+#define FF_STATUS_MAX 0x01
+
+/*
+ * Structures used in ioctls to upload effects to a device
+ * The first structures are not passed directly by using ioctls.
+ * They are sub-structures of the actually sent structure (called ff_effect)
+ */
+
+struct ff_replay {
+ __u16 length; /* Duration of an effect in ms. All other times are also expressed in ms */
+ __u16 delay; /* Time to wait before to start playing an effect */
+};
+
+struct ff_trigger {
+ __u16 button; /* Number of button triggering an effect */
+ __u16 interval; /* Time to wait before an effect can be re-triggered (ms) */
+};
+
+struct ff_envelope {
+ __u16 attack_length; /* Duration of attack (ms) */
+ __u16 attack_level; /* Level at beginning of attack */
+ __u16 fade_length; /* Duration of fade (ms) */
+ __u16 fade_level; /* Level at end of fade */
+};
+
+/* FF_CONSTANT */
+struct ff_constant_effect {
+ __s16 level; /* Strength of effect. Negative values are OK */
+ struct ff_envelope envelope;
+};
+
+/* FF_RAMP */
+struct ff_ramp_effect {
+ __s16 start_level;
+ __s16 end_level;
+ struct ff_envelope envelope;
+};
+
+/* FF_SPRING of FF_FRICTION */
+struct ff_condition_effect {
+ __u16 right_saturation; /* Max level when joystick is on the right */
+ __u16 left_saturation; /* Max level when joystick in on the left */
+
+ __s16 right_coeff; /* Indicates how fast the force grows when the
+ joystick moves to the right */
+ __s16 left_coeff; /* Same for left side */
+
+ __u16 deadband; /* Size of area where no force is produced */
+ __s16 center; /* Position of dead zone */
+
+};
+
+/* FF_PERIODIC */
+struct ff_periodic_effect {
+ __u16 waveform; /* Kind of wave (sine, square...) */
+ __u16 period; /* in ms */
+ __s16 magnitude; /* Peak value */
+ __s16 offset; /* Mean value of wave (roughly) */
+ __u16 phase; /* 'Horizontal' shift */
+
+ struct ff_envelope envelope;
+
+/* Only used if waveform == FF_CUSTOM */
+ __u32 custom_len; /* Number of samples */
+ __s16 *custom_data; /* Buffer of samples */
+/* Note: the data pointed by custom_data is copied by the driver. You can
+ * therefore dispose of the memory after the upload/update */
+};
+
+/* FF_RUMBLE */
+/* Some rumble pads have two motors of different weight.
+ strong_magnitude represents the magnitude of the vibration generated
+ by the heavy motor.
+*/
+struct ff_rumble_effect {
+ __u16 strong_magnitude; /* Magnitude of the heavy motor */
+ __u16 weak_magnitude; /* Magnitude of the light one */
+};
+
+/*
+ * Structure sent through ioctl from the application to the driver
+ */
+struct ff_effect {
+ __u16 type;
+/* Following field denotes the unique id assigned to an effect.
+ * If user sets if to -1, a new effect is created, and its id is returned in the same field
+ * Else, the user sets it to the effect id it wants to update.
+ */
+ __s16 id;
+
+ __u16 direction; /* Direction. 0 deg -> 0x0000 (down)
+ 90 deg -> 0x4000 (left)
+ 180 deg -> 0x8000 (up)
+ 270 deg -> 0xC000 (right)
+ */
+
+ struct ff_trigger trigger;
+ struct ff_replay replay;
+
+ union {
+ struct ff_constant_effect constant;
+ struct ff_ramp_effect ramp;
+ struct ff_periodic_effect periodic;
+ struct ff_condition_effect condition[2]; /* One for each axis */
+ struct ff_rumble_effect rumble;
+ } u;
+};
+
+/*
+ * Force feedback effect types
+ */
+
+#define FF_RUMBLE 0x50
+#define FF_PERIODIC 0x51
+#define FF_CONSTANT 0x52
+#define FF_SPRING 0x53
+#define FF_FRICTION 0x54
+#define FF_DAMPER 0x55
+#define FF_INERTIA 0x56
+#define FF_RAMP 0x57
+
+/*
+ * Force feedback periodic effect types
+ */
+
+#define FF_SQUARE 0x58
+#define FF_TRIANGLE 0x59
+#define FF_SINE 0x5a
+#define FF_SAW_UP 0x5b
+#define FF_SAW_DOWN 0x5c
+#define FF_CUSTOM 0x5d
+
+/*
+ * Set ff device properties
+ */
+
+#define FF_GAIN 0x60
+#define FF_AUTOCENTER 0x61
+
+#define FF_MAX 0x7f
+
+#ifdef __KERNEL__
+
+/*
+ * In-kernel definitions.
+ */
+
+#include <linux/fs.h>
+#include <linux/timer.h>
+
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define BIT(x) (1UL<<((x)%BITS_PER_LONG))
+#define LONG(x) ((x)/BITS_PER_LONG)
+
+#define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
+ ((dev->keycodesize == 1) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
+
+#define init_input_dev(dev) do { INIT_LIST_HEAD(&((dev)->h_list)); INIT_LIST_HEAD(&((dev)->node)); } while (0)
+
+struct input_dev {
+
+ void *private;
+
+ char *name;
+ char *phys;
+ char *uniq;
+ struct input_id id;
+
+ unsigned long evbit[NBITS(EV_MAX)];
+ unsigned long keybit[NBITS(KEY_MAX)];
+ unsigned long relbit[NBITS(REL_MAX)];
+ unsigned long absbit[NBITS(ABS_MAX)];
+ unsigned long mscbit[NBITS(MSC_MAX)];
+ unsigned long ledbit[NBITS(LED_MAX)];
+ unsigned long sndbit[NBITS(SND_MAX)];
+ unsigned long ffbit[NBITS(FF_MAX)];
+ int ff_effects_max;
+
+ unsigned int keycodemax;
+ unsigned int keycodesize;
+ void *keycode;
+
+ unsigned int repeat_key;
+ struct timer_list timer;
+
+ struct pm_dev *pm_dev;
+ struct pt_regs *regs;
+ int state;
+
+ int sync;
+
+ int abs[ABS_MAX + 1];
+ int rep[REP_MAX + 1];
+
+ unsigned long key[NBITS(KEY_MAX)];
+ unsigned long led[NBITS(LED_MAX)];
+ unsigned long snd[NBITS(SND_MAX)];
+
+ int absmax[ABS_MAX + 1];
+ int absmin[ABS_MAX + 1];
+ int absfuzz[ABS_MAX + 1];
+ int absflat[ABS_MAX + 1];
+
+ int (*open)(struct input_dev *dev);
+ void (*close)(struct input_dev *dev);
+ int (*accept)(struct input_dev *dev, struct file *file);
+ int (*flush)(struct input_dev *dev, struct file *file);
+ int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+ int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
+ int (*erase_effect)(struct input_dev *dev, int effect_id);
+
+ struct input_handle *grab;
+
+ struct list_head h_list;
+ struct list_head node;
+};
+
+/*
+ * Structure for hotplug & device<->driver matching.
+ */
+
+#define INPUT_DEVICE_ID_MATCH_BUS 1
+#define INPUT_DEVICE_ID_MATCH_VENDOR 2
+#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
+#define INPUT_DEVICE_ID_MATCH_VERSION 8
+
+#define INPUT_DEVICE_ID_MATCH_EVBIT 0x010
+#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020
+#define INPUT_DEVICE_ID_MATCH_RELBIT 0x040
+#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080
+#define INPUT_DEVICE_ID_MATCH_MSCIT 0x100
+#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200
+#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400
+#define INPUT_DEVICE_ID_MATCH_FFBIT 0x800
+
+#define INPUT_DEVICE_ID_MATCH_DEVICE\
+ (INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
+#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
+ (INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
+
+struct input_device_id {
+
+ unsigned long flags;
+
+ struct input_id id;
+
+ unsigned long evbit[NBITS(EV_MAX)];
+ unsigned long keybit[NBITS(KEY_MAX)];
+ unsigned long relbit[NBITS(REL_MAX)];
+ unsigned long absbit[NBITS(ABS_MAX)];
+ unsigned long mscbit[NBITS(MSC_MAX)];
+ unsigned long ledbit[NBITS(LED_MAX)];
+ unsigned long sndbit[NBITS(SND_MAX)];
+ unsigned long ffbit[NBITS(FF_MAX)];
+
+ unsigned long driver_info;
+};
+
+struct input_handle;
+
+struct input_handler {
+
+ void *private;
+
+ void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
+ struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id);
+ void (*disconnect)(struct input_handle *handle);
+
+ struct file_operations *fops;
+ int minor;
+ char *name;
+
+ struct input_device_id *id_table;
+
+ struct list_head h_list;
+ struct list_head node;
+};
+
+struct input_handle {
+
+ void *private;
+
+ int open;
+ char *name;
+
+ struct input_dev *dev;
+ struct input_handler *handler;
+
+ struct list_head d_node;
+ struct list_head h_node;
+};
+
+#define to_dev(n) container_of(n,struct input_dev,node)
+#define to_handler(n) container_of(n,struct input_handler,node);
+#define to_handle(n) container_of(n,struct input_handle,d_node)
+#define to_handle_h(n) container_of(n,struct input_handle,h_node)
+
+void input_register_device(struct input_dev *);
+void input_unregister_device(struct input_dev *);
+
+void input_register_handler(struct input_handler *);
+void input_unregister_handler(struct input_handler *);
+
+int input_grab_device(struct input_handle *);
+void input_release_device(struct input_handle *);
+
+int input_open_device(struct input_handle *);
+void input_close_device(struct input_handle *);
+
+int input_accept_process(struct input_handle *handle, struct file *file);
+int input_flush_device(struct input_handle* handle, struct file* file);
+
+void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+
+#define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c))
+#define input_report_rel(a,b,c) input_event(a, EV_REL, b, c)
+#define input_report_abs(a,b,c) input_event(a, EV_ABS, b, c)
+#define input_report_ff(a,b,c) input_event(a, EV_FF, b, c)
+#define input_report_ff_status(a,b,c) input_event(a, EV_FF_STATUS, b, c)
+
+#define input_regs(a,b) do { (a)->regs = (b); } while (0)
+#define input_sync(a) do { input_event(a, EV_SYN, SYN_REPORT, 0); (a)->regs = NULL; } while (0)
+
+extern struct class input_class;
+
+#endif
+#endif
diff --git a/lirc.sh b/lirc.sh
new file mode 100755
index 0000000..d929005
--- /dev/null
+++ b/lirc.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+INPUT="linux-input.h"
+cat <<EOF
+begin remote
+ name linux-input-layer
+ begin codes
+EOF
+awk "
+ /_MAX/ { next };
+ /KEY_RESERVED/ { next };
+ /#define (KEY|BTN)_/ { gsub(/KEY_/,\"\",\$2);
+ printf(\"\t\t%-20s 0x%04x\n\",
+ \$2,0x10000+strtonum(\$3)) }
+" < $INPUT
+cat <<EOF
+ end codes
+end remote
+EOF
diff --git a/list.h b/list.h
new file mode 100644
index 0000000..6072f68
--- /dev/null
+++ b/list.h
@@ -0,0 +1,169 @@
+#ifndef _LIST_H
+#define _LIST_H 1
+
+/*
+ * Simple doubly linked list implementation.
+ * -- shameless stolen from the linux kernel sources
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a item entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_add(struct list_head * item,
+ struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = item;
+ item->next = next;
+ item->prev = prev;
+ prev->next = item;
+}
+
+/**
+ * list_add - add a item entry
+ * @item: item entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a item entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static __inline__ void list_add(struct list_head *item, struct list_head *head)
+{
+ __list_add(item, head, head->next);
+}
+
+/**
+ * list_add_tail - add a item entry
+ * @item: item entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a item entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static __inline__ void list_add_tail(struct list_head *item, struct list_head *head)
+{
+ __list_add(item, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_del(struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
+ */
+static __inline__ void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static __inline__ void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static __inline__ int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the item list to add.
+ * @head: the place to add it in the first list.
+ */
+static __inline__ void list_splice(struct list_head *list, struct list_head *head)
+{
+ struct list_head *first = list->next;
+
+ if (first != list) {
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop counter.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list in reverse order
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; pos != (head); pos = pos->prev)
+
+#endif /* _LIST_H */
diff --git a/lsinput.c b/lsinput.c
new file mode 100644
index 0000000..45f50e5
--- /dev/null
+++ b/lsinput.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "input.h"
+
+/* ------------------------------------------------------------------ */
+
+static void list_devices(void)
+{
+ int i,fd;
+
+ for (i = 0; i < 32; i++) {
+ /* try to open */
+ fd = device_open(i,1);
+ if (-1 == fd)
+ return;
+ device_info(fd);
+ close(fd);
+ }
+ return;
+}
+
+int main(int argc, char *argv[])
+{
+ list_devices();
+ exit(0);
+}
+
+/* ---------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/mk/Autoconf.mk b/mk/Autoconf.mk
new file mode 100644
index 0000000..646e47b
--- /dev/null
+++ b/mk/Autoconf.mk
@@ -0,0 +1,124 @@
+#
+# simple autoconf system for GNU make
+#
+# (c) 2002,2003 Gerd Knorr <kraxel@bytesex.org>
+#
+# credits for creating this one go to the autotools people because
+# they managed it to annoy lots of developers and users (including
+# me) with version incompatibilities.
+#
+# This file is public domain. No warranty. If it breaks you keep
+# both pieces.
+#
+########################################################################
+
+# verbose yes/no
+verbose ?= no
+
+# some stuff used by the tests
+ifneq ($(verbose),no)
+ # verbose (for debug)
+ ac_init = echo "checking $(1) ... " >&2; rc=no
+ ac_b_cmd = echo "run: $(1)" >&2; $(1) >/dev/null && rc=yes
+ ac_s_cmd = echo "run: $(1)" >&2; rc=`$(1)`
+ ac_fini = echo "... result is $${rc}" >&2; echo >&2; echo "$${rc}"
+else
+ # normal
+ ac_init = echo -ne "checking $(1) ... " >&2; rc=no
+ ac_b_cmd = $(1) >/dev/null 2>&1 && rc=yes
+ ac_s_cmd = rc=`$(1) 2>/dev/null`
+ ac_fini = echo "$${rc}" >&2; echo "$${rc}"
+endif
+
+# some helpers to build cflags and related variables
+ac_def_cflags_1 = $(if $(filter yes,$($(1))),-D$(1))
+ac_lib_cflags = $(foreach lib,$(1),$(call ac_def_cflags_1,HAVE_LIB$(lib)))
+ac_inc_cflags = $(foreach inc,$(1),$(call ac_def_cflags_1,HAVE_$(inc)))
+ac_lib_mkvar_1 = $(if $(filter yes,$(HAVE_LIB$(1))),$($(1)_$(2)))
+ac_lib_mkvar = $(foreach lib,$(1),$(call ac_lib_mkvar_1,$(lib),$(2)))
+
+
+########################################################################
+# the tests ...
+
+# get uname
+ac_uname = $(shell \
+ $(call ac_init,for system);\
+ $(call ac_s_cmd,uname -s | tr 'A-Z' 'a-z');\
+ $(call ac_fini))
+
+# check for some header file
+ac_header = $(shell \
+ $(call ac_init,for $(1));\
+ $(call ac_b_cmd,echo '\#include <$(1)>' |\
+ $(CC) $(CFLAGS) -E -);\
+ $(call ac_fini))
+
+# check for some library
+ac_lib = $(shell \
+ $(call ac_init,for $(1) in $(2));\
+ echo 'void $(1)(void); int main(void) {$(1)();return 0;}' \
+ > __actest.c;\
+ $(call ac_b_cmd,$(CC) $(CFLAGS) $(LDFLAGS) -o \
+ __actest __actest.c -l$(2) $(3));\
+ rm -f __actest __actest.c;\
+ $(call ac_fini))
+
+# check if some compiler flag works
+ac_cflag = $(shell \
+ $(call ac_init,if $(CC) supports $(1));\
+ echo 'int main() {return 0;}' > __actest.c;\
+ $(call ac_b_cmd,$(CC) $(CFLAGS) $(1) $(LDFLAGS) -o \
+ __actest __actest.c);\
+ rm -f __actest __actest.c;\
+ $(call ac_fini))
+
+# check for some binary
+ac_binary = $(shell \
+ $(call ac_init,for $(1));\
+ $(call ac_s_cmd,which $(1));\
+ bin="$$rc";rc="no";\
+ $(call ac_b_cmd,test -x "$$$$bin");\
+ $(call ac_fini))
+
+# check if lib64 is used
+ac_lib64 = $(shell \
+ $(call ac_init,for libdir name);\
+ $(call ac_s_cmd,$(CC) -print-search-dirs | grep -q lib64 &&\
+ echo "lib64" || echo "lib");\
+ $(call ac_fini))
+
+# check for x11 ressource dir prefix
+ac_resdir = $(shell \
+ $(call ac_init,for X11 app-defaults prefix);\
+ $(call ac_s_cmd, test -d /etc/X11/app-defaults &&\
+ echo "/etc/X11" || echo "/usr/X11R6/lib/X11");\
+ $(call ac_fini))
+
+
+########################################################################
+# build Make.config
+
+define newline
+
+
+endef
+make-config-q = $(subst $(newline),\n,$(make-config))
+
+ifeq ($(filter config,$(MAKECMDGOALS)),config)
+.PHONY: Make.config
+ LIB := $(call ac_lib64)
+else
+ LIB ?= $(call ac_lib64)
+ LIB := $(LIB)
+endif
+.PHONY: config
+config: Make.config
+ @true
+
+Make.config: GNUmakefile
+ @echo -e "$(make-config-q)" > $@
+ @echo
+ @echo "Make.config written, edit if needed"
+ @echo
+
diff --git a/mk/Compile.mk b/mk/Compile.mk
new file mode 100644
index 0000000..75dadde
--- /dev/null
+++ b/mk/Compile.mk
@@ -0,0 +1,84 @@
+#
+# some rules to compile stuff ...
+#
+# (c) 2002 Gerd Knorr <kraxel@bytesex.org>
+#
+# main features:
+# * autodependencies via "cpp -MD"
+# * fancy, non-verbose output
+#
+# This file is public domain. No warranty. If it breaks you keep
+# both pieces.
+#
+########################################################################
+
+# verbose yes/no
+verbose ?= no
+
+# dependency files
+tmpdep = mk/$(subst /,_,$*).tmp
+depfile = mk/$(subst /,_,$*).dep
+depfiles = mk/*.dep
+
+compile_c = $(CC) $(CFLAGS) -Wp,-MD,$(tmpdep) -c -o $@ $<
+compile_cc = $(CXX) $(CXXFLAGS) -Wp,-MD,$(tmpdep) -c -o $@ $<
+fixup_deps = sed -e "s|.*\.o:|$@:|" < $(tmpdep) > $(depfile) && rm -f $(tmpdep)
+
+link_app = $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+link_so = $(CC) $(LDFLAGS) -shared -Wl,-soname,$(@F) -o $@ $^ $(LDLIBS)
+ar_lib = rm -f $@ && ar -r $@ $^ && ranlib $@
+
+moc_h = $(MOC) $< -o $@
+msgfmt_po = msgfmt -o $@ $<
+
+# non-verbose output
+ifeq ($(verbose),no)
+ echo_compile_c = echo " CC " $@
+ echo_compile_cc = echo " CXX " $@
+ echo_link_app = echo " LD " $@
+ echo_link_so = echo " LD " $@
+ echo_ar_lib = echo " AR " $@
+ echo_moc_h = echo " MOC " $@
+ echo_msgfmt_po = echo " MSGFMT " $@
+else
+ echo_compile_c = echo $(compile_c)
+ echo_compile_cc = echo $(compile_cc)
+ echo_link_app = echo $(link_app)
+ echo_link_so = echo $(link_so)
+ echo_ar_lib = echo $(ar_lib)
+ echo_moc_h = echo $(moc_h)
+ echo_msgfmt_po = echo $(msgfmt_po)
+endif
+
+%.o: %.c
+ @$(echo_compile_c)
+ @$(compile_c)
+ @$(fixup_deps)
+
+%.o: %.cc
+ @$(echo_compile_cc)
+ @$(compile_cc)
+ @$(fixup_deps)
+
+%.o: %.cpp
+ @$(echo_compile_cc)
+ @$(compile_cc)
+ @$(fixup_deps)
+
+
+%.so: %.o
+ @$(echo_link_so)
+ @$(link_so)
+
+%: %.o
+ @$(echo_link_app)
+ @$(link_app)
+
+%.moc : %.h
+ @$(echo_moc_h)
+ @$(moc_h)
+
+%.mo : %.po
+ @$(echo_msgfmt_po)
+ @$(msgfmt_po)
+
diff --git a/mk/Maintainer.mk b/mk/Maintainer.mk
new file mode 100644
index 0000000..f5ff691
--- /dev/null
+++ b/mk/Maintainer.mk
@@ -0,0 +1,47 @@
+# just some maintainer stuff for me ...
+########################################################################
+
+make-sync-dir = $(HOME)/src/gnu-make
+pbuilder-dir = /work/pbuilder/result
+snapshot-dir = $(HOME)/snapshot
+snapshot-date = $(shell date +%Y%m%d)
+snapshot-name = $(snapshot-dir)/$(PACKAGE)-$(snapshot-date).tar.gz
+
+deb-version = $(shell dpkg-parsechangelog | sed -n 's/^Version: \(.*:\|\)//p')
+deb-arch := $(shell uname -m | sed \
+ -e 's/i.86/i386/' \
+ -e 's/ppc/powerpc/')
+deb-dsc := ../$(PACKAGE)_$(VERSION).dsc
+deb-changes := $(pbuilder-dir)/$(PACKAGE)_$(VERSION)_$(deb-arch).changes
+
+
+.PHONY: sync checkit release port tarball dist rpm
+sync:: distclean
+ test -d $(make-sync-dir)
+ rm -f INSTALL mk/*.mk
+ cp -v $(make-sync-dir)/INSTALL .
+ cp -v $(make-sync-dir)/*.mk mk
+ chmod 444 INSTALL mk/*.mk
+
+
+dsc source $(deb-dsc): clean
+ test "$(VERSION)" = "$(deb-version)"
+ dpkg-buildpackage -S -us -uc -rfakeroot
+
+debs pbuild $(deb-changes): $(deb-dsc)
+ sudo /usr/sbin/pbuilder build $(deb-dsc)
+ -lintian -i $(deb-changes)
+
+release: $(deb-changes)
+ debsign $(deb-changes)
+
+
+tarball dist: realclean
+ (cd ..; tar czf $(TARBALL) $(DIR))
+
+snapshot snap: realclean
+ (cd ..; tar czf $(snapshot-name) $(DIR))
+
+rpm: tarball
+ rpm -ta ../$(TARBALL)
+
diff --git a/mk/Variables.mk b/mk/Variables.mk
new file mode 100644
index 0000000..4449d81
--- /dev/null
+++ b/mk/Variables.mk
@@ -0,0 +1,33 @@
+# common variables ...
+########################################################################
+
+# package + version
+empty :=
+space := $(empty) $(empty)
+PWD := $(shell pwd)
+DIR := $(patsubst $(dir $(PWD))%,%,$(PWD))
+PACKAGE := $(word 1,$(subst -,$(space),$(DIR)))
+VERSION := $(word 2,$(subst -,$(space),$(DIR)))
+TARBALL := $(PACKAGE)_$(VERSION).tar.gz
+
+# directories
+DESTDIR =
+prefix ?= /usr/local
+bindir = $(DESTDIR)$(prefix)/bin
+mandir = $(DESTDIR)$(prefix)/share/man
+locdir = $(DESTDIR)$(prefix)/share/locale
+
+# programs
+CC ?= gcc
+CXX ?= g++
+MOC ?= $(if $(QTDIR),$(QTDIR)/bin/moc,moc)
+INSTALL ?= install
+INSTALL_BINARY := $(INSTALL) -s
+INSTALL_SCRIPT := $(INSTALL)
+INSTALL_DATA := $(INSTALL) -m 644
+INSTALL_DIR := $(INSTALL) -d
+
+# cflags
+CFLAGS ?= -g -O2
+CFLAGS += -Wall -Wmissing-prototypes -Wstrict-prototypes \
+ -Wpointer-arith -Wunused
diff --git a/name.sh b/name.sh
new file mode 100755
index 0000000..562e0b4
--- /dev/null
+++ b/name.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+TYPE="$1"
+INPUT="linux-input.h"
+
+awk "
+ /EV_VERSION/ { next };
+ /_MAX/ { next };
+ /#define $1_/ { printf(\"\t[ %-16s ] = \\\"%s\\\",\n\", \$2, \$2); }
+" < $INPUT \ No newline at end of file
diff --git a/tcp.c b/tcp.c
new file mode 100644
index 0000000..f0a7345
--- /dev/null
+++ b/tcp.c
@@ -0,0 +1,153 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "tcp.h"
+
+int tcp_verbose;
+
+/* ------------------------------------------------------------------ */
+
+static char *strfamily(int family)
+{
+ switch (family) {
+ case PF_INET6: return "ipv6";
+ case PF_INET: return "ipv4";
+ case PF_UNIX: return "unix";
+ }
+ return "????";
+}
+
+int tcp_connect(struct addrinfo *ai,
+ char *addr, char *port,
+ char *host, char *serv)
+{
+ struct addrinfo *res,*e;
+ struct addrinfo *lres, ask;
+ char uaddr[INET6_ADDRSTRLEN+1];
+ char uport[33];
+ char uhost[INET6_ADDRSTRLEN+1];
+ char userv[33];
+ int sock,rc,opt=1;
+
+ /* lookup peer */
+ ai->ai_flags = AI_CANONNAME;
+ if (0 != (rc = getaddrinfo(host, serv, ai, &res))) {
+ if (tcp_verbose)
+ fprintf(stderr,"getaddrinfo (peer): %s\n",gai_strerror(rc));
+ return -1;
+ }
+ for (e = res; e != NULL; e = e->ai_next) {
+ if (0 != getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
+ uhost,INET6_ADDRSTRLEN,userv,32,
+ NI_NUMERICHOST | NI_NUMERICSERV)) {
+ if (tcp_verbose)
+ fprintf(stderr,"getnameinfo (peer): oops\n");
+ continue;
+ }
+ if (-1 == (sock = socket(e->ai_family, e->ai_socktype,
+ e->ai_protocol))) {
+ if (tcp_verbose)
+ fprintf(stderr,"socket (%s): %s\n",
+ strfamily(e->ai_family),strerror(errno));
+ continue;
+ }
+ setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
+ if (NULL != addr || NULL != port) {
+ /* bind local port */
+ memset(&ask,0,sizeof(ask));
+ ask.ai_flags = AI_PASSIVE;
+ ask.ai_family = e->ai_family;
+ ask.ai_socktype = e->ai_socktype;
+ if (0 != (rc = getaddrinfo(addr, port, &ask, &lres))) {
+ if (tcp_verbose)
+ fprintf(stderr,"getaddrinfo (local): %s\n",
+ gai_strerror(rc));
+ continue;
+ }
+ if (0 != getnameinfo((struct sockaddr*)lres->ai_addr,
+ lres->ai_addrlen,
+ uaddr,INET6_ADDRSTRLEN,uport,32,
+ NI_NUMERICHOST | NI_NUMERICSERV)) {
+ if (tcp_verbose)
+ fprintf(stderr,"getnameinfo (local): oops\n");
+ continue;
+ }
+ if (-1 == bind(sock, lres->ai_addr, lres->ai_addrlen)) {
+ if (tcp_verbose)
+ fprintf(stderr,"%s [%s] %s bind: %s\n",
+ strfamily(lres->ai_family),uaddr,uport,
+ strerror(errno));
+ continue;
+ }
+ }
+ /* connect to peer */
+ if (-1 == connect(sock,e->ai_addr,e->ai_addrlen)) {
+ if (tcp_verbose)
+ fprintf(stderr,"%s %s [%s] %s connect: %s\n",
+ strfamily(e->ai_family),e->ai_canonname,uhost,userv,
+ strerror(errno));
+ close(sock);
+ continue;
+ }
+ if (tcp_verbose)
+ fprintf(stderr,"%s %s [%s] %s open\n",
+ strfamily(e->ai_family),e->ai_canonname,uhost,userv);
+ fcntl(sock,F_SETFL,O_NONBLOCK);
+ return sock;
+ }
+ return -1;
+}
+
+int tcp_listen(struct addrinfo *ai, char *addr, char *port)
+{
+ struct addrinfo *res,*e;
+ char uaddr[INET6_ADDRSTRLEN+1];
+ char uport[33];
+ int slisten,rc,opt=1;
+
+ /* lookup */
+ ai->ai_flags = AI_PASSIVE;
+ if (0 != (rc = getaddrinfo(addr, port, ai, &res))) {
+ if (tcp_verbose)
+ fprintf(stderr,"getaddrinfo: %s\n",gai_strerror(rc));
+ exit(1);
+ }
+
+ /* create socket + bind */
+ for (e = res; e != NULL; e = e->ai_next) {
+ getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
+ uaddr,INET6_ADDRSTRLEN,uport,32,
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (-1 == (slisten = socket(e->ai_family, e->ai_socktype,
+ e->ai_protocol))) {
+ if (tcp_verbose)
+ fprintf(stderr,"socket (%s): %s\n",
+ strfamily(e->ai_family),strerror(errno));
+ continue;
+ }
+ opt = 1;
+ setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
+ if (-1 == bind(slisten, e->ai_addr, e->ai_addrlen)) {
+ if (tcp_verbose)
+ fprintf(stderr,"%s [%s] %s bind: %s\n",
+ strfamily(e->ai_family),uaddr,uport,
+ strerror(errno));
+ continue;
+ }
+ listen(slisten,1);
+ break;
+ }
+ if (NULL == e)
+ return -1;
+
+ /* wait for a incoming connection */
+ if (tcp_verbose)
+ fprintf(stderr,"listen on %s [%s] %s ...\n",
+ strfamily(e->ai_family),uaddr,uport);
+ fcntl(slisten,F_SETFL,O_NONBLOCK);
+ return slisten;
+}
diff --git a/tcp.h b/tcp.h
new file mode 100644
index 0000000..f0224c0
--- /dev/null
+++ b/tcp.h
@@ -0,0 +1,11 @@
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+extern int tcp_verbose;
+
+int tcp_connect(struct addrinfo *ai,
+ char *addr, char *port,
+ char *host, char *serv);
+
+int tcp_listen(struct addrinfo *ai, char *addr, char *port);