Add support for the old RFCOMM based EPoX presenter
diff --git a/hidd/Makefile.am b/hidd/Makefile.am
index cc04345..ba01cae 100644
--- a/hidd/Makefile.am
+++ b/hidd/Makefile.am
@@ -1,8 +1,8 @@
 
 bin_PROGRAMS = hidd
 
-hidd_SOURCES = main.c hidd.h sdp.c fakehid.c
-hidd_LDADD = @BLUEZ_LIBS@ $(top_builddir)/common/libtextfile.a
+hidd_SOURCES = main.c hidd.h sdp.c uinput.h fakehid.c
+hidd_LDADD = @BLUEZ_LIBS@ -lm $(top_builddir)/common/libtextfile.a
 
 AM_CFLAGS = @BLUEZ_CFLAGS@
 
diff --git a/hidd/fakehid.c b/hidd/fakehid.c
index 1483f02..b9fbc20 100644
--- a/hidd/fakehid.c
+++ b/hidd/fakehid.c
@@ -27,6 +27,12 @@
 
 #include <stdio.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/poll.h>
+#include <sys/ioctl.h>
 #include <sys/socket.h>
 
 #include <bluetooth/bluetooth.h>
@@ -34,16 +40,300 @@
 #include <bluetooth/hidp.h>
 
 #include "hidd.h"
-
-#include <X11/Xlib.h>
-#include <X11/extensions/XTest.h>
+#include "uinput.h"
 
 #include <math.h>
 
+static void event(int fd, uint16_t type, uint16_t code, int32_t value)
+{
+	struct uinput_event event;
+
+	if (fd <= fileno(stderr))
+		return;
+
+	memset(&event, 0, sizeof(event));
+	event.type = type;
+	event.code = code;
+	event.value = value;
+
+	write(fd, &event, sizeof(event));
+}
+
+static void func(int fd)
+{
+}
+
+static void back(int fd)
+{
+}
+
+static void next(int fd)
+{
+}
+
+static void button(int fd, unsigned int button, int is_press)
+{
+	switch (button) {
+	case 1:
+		event(fd, EV_KEY, BTN_LEFT, is_press);
+		break;
+	case 3:
+		event(fd, EV_KEY, BTN_RIGHT, is_press);
+		break;
+	}
+
+	event(fd, EV_SYN, SYN_REPORT, 0);
+}
+
+static void move(int fd, unsigned int direction)
+{
+	double angle;
+	int32_t x, y;
+
+	angle = (direction * 22.5) * 3.1415926 / 180;
+	x = (int) (sin(angle) * 8);
+	y = (int) (cos(angle) * -8);
+
+	event(fd, EV_REL, REL_X, x);
+	event(fd, EV_REL, REL_Y, y);
+
+	event(fd, EV_SYN, SYN_REPORT, 0);
+}
+
+static void epox_decode(int fd, unsigned char event)
+{
+	switch (event) {
+	case 48:
+		func(fd); break;
+	case 55:
+		back(fd); break;
+	case 56:
+		next(fd); break;
+	case 53:
+		button(fd, 1, 1); break;
+	case 121:
+		button(fd, 1, 0); break;
+	case 113:
+		break;
+	case 54:
+		button(fd, 3, 1); break;
+	case 120:
+		button(fd, 3, 0); break;
+	case 112:
+		break;
+	case 51:
+		move(fd, 0); break;
+	case 97:
+		move(fd, 1); break;
+	case 65:
+		move(fd, 2); break;
+	case 98:
+		move(fd, 3); break;
+	case 50:
+		move(fd, 4); break;
+	case 99:
+		move(fd, 5); break;
+	case 67:
+		move(fd, 6); break;
+	case 101:
+		move(fd, 7); break;
+	case 52:
+		move(fd, 8); break;
+	case 100:
+		move(fd, 9); break;
+	case 66:
+		move(fd, 10); break;
+	case 102:
+		move(fd, 11); break;
+	case 49:
+		move(fd, 12); break;
+	case 103:
+		move(fd, 13); break;
+	case 57:
+		move(fd, 14); break;
+	case 104:
+		move(fd, 15); break;
+	case 69:
+		break;
+	default:
+		printf("Unknown event code %d\n", event);
+		break;
+	}
+}
+
+static int uinput_create(int keyboard, int mouse)
+{
+	struct uinput_dev dev;
+	int fd, aux;
+
+	fd = open("/dev/uinput", O_RDWR);
+	if (fd < 0) {
+		fd = open("/dev/input/uinput", O_RDWR);
+		if (fd < 0) {
+			fd = open("/dev/misc/uinput", O_RDWR);
+			if (fd < 0) {
+				fprintf(stderr, "Can't open input device: %s (%d)",
+							strerror(errno), errno);
+				return -1;
+			}
+		}
+	}
+
+	memset(&dev, 0, sizeof(dev));
+	strncpy(dev.name, "Bluetooth FakeHID", UINPUT_MAX_NAME_SIZE);
+	dev.id.bustype = BUS_BLUETOOTH;
+	dev.id.vendor = 0x0000;
+	dev.id.product = 0x0000;
+	dev.id.version = 0x0000;
+
+	if (write(fd, &dev, sizeof(dev)) < 0) {
+		fprintf(stderr, "Can't write device information: %s (%d)",
+							strerror(errno), errno);
+		close(fd);
+		return -1;
+	}
+
+	if (mouse) {
+		ioctl(fd, UI_SET_EVBIT, EV_REL);
+
+		for (aux = REL_X; aux <= REL_MISC; aux++)
+			ioctl(fd, UI_SET_RELBIT, aux);
+	}
+
+	if (keyboard) {
+		ioctl(fd, UI_SET_EVBIT, EV_KEY);
+		ioctl(fd, UI_SET_EVBIT, EV_LED);
+		ioctl(fd, UI_SET_EVBIT, EV_REP);
+
+		for (aux = KEY_RESERVED; aux <= KEY_UNKNOWN; aux++)
+			ioctl(fd, UI_SET_KEYBIT, aux);
+
+		//for (aux = LED_NUML; aux <= LED_MISC; aux++)
+		//	ioctl(fd, UI_SET_LEDBIT, aux);
+	}
+
+	if (mouse) {
+		ioctl(fd, UI_SET_EVBIT, EV_KEY);
+
+		for (aux = BTN_LEFT; aux <= BTN_BACK; aux++)
+			ioctl(fd, UI_SET_KEYBIT, aux);
+	}
+
+	ioctl(fd, UI_DEV_CREATE);
+
+	return fd;
+}
+
+static int rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
+{
+	struct sockaddr_rc addr;
+	int sk;
+
+	sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+	if (sk < 0) {
+		fprintf(stderr, "Can't create socket: %s (%d)\n",
+							strerror(errno), errno);
+		return -1;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.rc_family = AF_BLUETOOTH;
+	bacpy(&addr.rc_bdaddr, src);
+
+	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		fprintf(stderr, "Can't bind socket: %s (%d)\n",
+							strerror(errno), errno);
+		close(sk);
+		return -1;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.rc_family = AF_BLUETOOTH;
+	bacpy(&addr.rc_bdaddr, dst);
+	addr.rc_channel = channel;
+
+	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		fprintf(stderr, "Can't connect: %s (%d)\n",
+							strerror(errno), errno);
+		close(sk);
+		return -1;
+	}
+
+	return sk;
+}
+
+static volatile sig_atomic_t __io_canceled = 0;
+
+static void sig_hup(int sig)
+{
+}
+
+static void sig_term(int sig)
+{
+	__io_canceled = 1;
+}
+
 void epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
 {
+	unsigned char buf[16];
+	struct sigaction sa;
+	struct pollfd p;
+	char addr[18];
+	int i, fd, sk, len;
+
+	sk = rfcomm_connect(src, dst, channel);
+	if (sk < 0)
+		return;
+
+	fd = uinput_create(1, 1);
+	if (fd < 0) {
+		close(sk);
+		return;
+	}
+
+	ba2str(dst, addr);
+
+	printf("Connected to %s on channel %d\n", addr, channel);
+	printf("Press CTRL-C for hangup\n");
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_flags   = SA_NOCLDSTOP;
+	sa.sa_handler = SIG_IGN;
+	sigaction(SIGCHLD, &sa, NULL);
+	sigaction(SIGPIPE, &sa, NULL);
+
+	sa.sa_handler = sig_term;
+	sigaction(SIGTERM, &sa, NULL);
+	sigaction(SIGINT,  &sa, NULL);
+
+	sa.sa_handler = sig_hup;
+	sigaction(SIGHUP, &sa, NULL);
+
+	p.fd = sk;
+	p.events = POLLIN | POLLERR | POLLHUP;
+
+	while (!__io_canceled) {
+		p.revents = 0;
+		if (poll(&p, 1, 100) < 1)
+			continue;
+
+		len = read(sk, buf, sizeof(buf));
+		if (len < 0)
+			break;
+
+		for (i = 0; i < len; i++)
+			epox_decode(fd, buf[i]);
+	}
+
+	printf("Disconnected\n");
+
+	ioctl(fd, UI_DEV_DESTROY);
+
+	close(fd);
+	close(sk);
 }
 
 void headset_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
 {
+	printf("Not implemented\n");
 }
diff --git a/hidd/sdp.c b/hidd/sdp.c
index 285438e..c86fb2f 100644
--- a/hidd/sdp.c
+++ b/hidd/sdp.c
@@ -175,19 +175,21 @@
 	search = sdp_list_append(NULL, &svclass);
 	attrid = sdp_list_append(NULL, &range);
 
-	err = sdp_service_search_attr_req(s, search, SDP_ATTR_REQ_RANGE, attrid, &pnp_rsp);
+	err = sdp_service_search_attr_req(s, search,
+					SDP_ATTR_REQ_RANGE, attrid, &pnp_rsp);
 
-	sdp_list_free(search, 0);
-	sdp_list_free(attrid, 0);
+	sdp_list_free(search, NULL);
+	sdp_list_free(attrid, NULL);
 
 	sdp_uuid16_create(&svclass, HID_SVCLASS_ID);
 	search = sdp_list_append(NULL, &svclass);
 	attrid = sdp_list_append(NULL, &range);
 
-	err = sdp_service_search_attr_req(s, search, SDP_ATTR_REQ_RANGE, attrid, &hid_rsp);
+	err = sdp_service_search_attr_req(s, search,
+					SDP_ATTR_REQ_RANGE, attrid, &hid_rsp);
 
-	sdp_list_free(search, 0);
-	sdp_list_free(attrid, 0);
+	sdp_list_free(search, NULL);
+	sdp_list_free(attrid, NULL);
 
 	memset(&addr, 0, sizeof(addr));
 	addrlen = sizeof(addr);
@@ -270,19 +272,66 @@
 
 int get_alternate_device_info(const bdaddr_t *src, const bdaddr_t *dst, uint16_t *uuid, uint8_t *channel)
 {
+	uint16_t attr = SDP_ATTR_PROTO_DESC_LIST;
 	sdp_session_t *s;
+	sdp_list_t *search, *attrid, *rsp;
+	uuid_t svclass;
+	int err;
 
 	s = sdp_connect(src, dst, SDP_RETRY_IF_BUSY | SDP_WAIT_ON_CLOSE);
 	if (!s)
 		return -1;
 
+	sdp_uuid16_create(&svclass, HEADSET_SVCLASS_ID);
+	search = sdp_list_append(NULL, &svclass);
+	attrid = sdp_list_append(NULL, &attr);
+
+	err = sdp_service_search_attr_req(s, search,
+					SDP_ATTR_REQ_INDIVIDUAL, attrid, &rsp);
+
+	sdp_list_free(search, NULL);
+	sdp_list_free(attrid, NULL);
+
+	if (err <= 0) {
+		sdp_uuid16_create(&svclass, SERIAL_PORT_SVCLASS_ID);
+		search = sdp_list_append(NULL, &svclass);
+		attrid = sdp_list_append(NULL, &attr);
+
+		err = sdp_service_search_attr_req(s, search,
+					SDP_ATTR_REQ_INDIVIDUAL, attrid, &rsp);
+
+		sdp_list_free(search, NULL);
+		sdp_list_free(attrid, NULL);
+
+		if (err < 0) {
+			sdp_close(s);
+			return err;
+		}
+
+		if (uuid)
+			*uuid = SERIAL_PORT_SVCLASS_ID;
+	} else {
+		if (uuid)
+			*uuid = HEADSET_SVCLASS_ID;
+	}
+
 	sdp_close(s);
 
-	if (uuid)
-		*uuid = 0x0000;
+	for (; rsp; rsp = rsp->next) {
+		sdp_record_t *rec = (sdp_record_t *) rsp->data;
+		sdp_list_t *protos;
 
-	if (channel)
-		*channel = 0;
+		if (!sdp_get_access_protos(rec, &protos)) {
+			uint8_t ch = sdp_get_proto_port(protos, RFCOMM_UUID);
+			if (ch > 0) {
+				if (channel)
+					*channel = ch;
+				return 0;
+			}
+		}
 
-	return 0;
+		sdp_record_free(rec);
+	}
+
+	return -EIO;
 }
diff --git a/hidd/uinput.h b/hidd/uinput.h
new file mode 100644
index 0000000..3a4d686
--- /dev/null
+++ b/hidd/uinput.h
@@ -0,0 +1,516 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2003-2005  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __UINPUT_H
+#define __UINPUT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+/* Events */
+
+#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_UNKNOWN		220
+
+#define KEY_BRIGHTNESSDOWN	224
+#define KEY_BRIGHTNESSUP	225
+
+#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_TOOL_DOUBLETAP	0x14d
+#define BTN_TOOL_TRIPLETAP	0x14e
+
+#define BTN_WHEEL		0x150
+#define BTN_GEAR_DOWN		0x150
+#define BTN_GEAR_UP		0x151
+
+#define KEY_MAX			0x1ff
+
+/* Relative axes */
+
+#define REL_X			0x00
+#define REL_Y			0x01
+#define REL_Z			0x02
+#define REL_RX			0x03
+#define REL_RY			0x04
+#define REL_RZ			0x05
+#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_TOOL_WIDTH		0x1c
+#define ABS_VOLUME		0x20
+#define ABS_MISC		0x28
+#define ABS_MAX			0x3f
+
+/* Switch events */
+
+#define SW_0			0x00
+#define SW_1			0x01
+#define SW_2			0x02
+#define SW_3			0x03
+#define SW_4			0x04
+#define SW_5			0x05
+#define SW_6			0x06
+#define SW_7			0x07
+#define SW_MAX			0x0f
+
+/* Misc events */
+
+#define MSC_SERIAL		0x00
+#define MSC_PULSELED		0x01
+#define MSC_GESTURE		0x02
+#define MSC_RAW			0x03
+#define MSC_SCAN		0x04
+#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_MAIL		0x09
+#define LED_CHARGING		0x0a
+#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
+
+/* Identifiers */
+
+#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_BLUETOOTH		0x05
+
+#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
+#define BUS_GSC			0x1A
+
+/* User input interface */
+
+#define UINPUT_IOCTL_BASE	'U'
+
+#define UI_DEV_CREATE		_IO(UINPUT_IOCTL_BASE, 1)
+#define UI_DEV_DESTROY		_IO(UINPUT_IOCTL_BASE, 2)
+
+#define UI_SET_EVBIT		_IOW(UINPUT_IOCTL_BASE, 100, int)
+#define UI_SET_KEYBIT		_IOW(UINPUT_IOCTL_BASE, 101, int)
+#define UI_SET_RELBIT		_IOW(UINPUT_IOCTL_BASE, 102, int)
+#define UI_SET_ABSBIT		_IOW(UINPUT_IOCTL_BASE, 103, int)
+#define UI_SET_MSCBIT		_IOW(UINPUT_IOCTL_BASE, 104, int)
+#define UI_SET_LEDBIT		_IOW(UINPUT_IOCTL_BASE, 105, int)
+#define UI_SET_SNDBIT		_IOW(UINPUT_IOCTL_BASE, 106, int)
+#define UI_SET_FFBIT		_IOW(UINPUT_IOCTL_BASE, 107, int)
+#define UI_SET_PHYS		_IOW(UINPUT_IOCTL_BASE, 108, char*)
+#define UI_SET_SWBIT		_IOW(UINPUT_IOCTL_BASE, 109, int)
+
+#ifndef NBITS
+#define NBITS(x) ((((x) - 1) / (sizeof(long) * 8)) + 1)
+#endif
+
+#define UINPUT_MAX_NAME_SIZE	80
+
+struct uinput_id {
+	uint16_t bustype;
+	uint16_t vendor;
+	uint16_t product;
+	uint16_t version;
+};
+
+struct uinput_dev {
+	char name[UINPUT_MAX_NAME_SIZE];
+	struct uinput_id id;
+	int ff_effects_max;
+	int absmax[ABS_MAX + 1];
+	int absmin[ABS_MAX + 1];
+	int absfuzz[ABS_MAX + 1];
+	int absflat[ABS_MAX + 1];
+};
+
+struct uinput_event {
+	struct timeval time;
+	uint16_t type;
+	uint16_t code;
+	int32_t value;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UINPUT_H */