diff -X /home/azz/Code/misccode/diff-ignore -Naur lirc-0.8.2.orig/configure.in lirc-0.8.2/configure.in
--- lirc-0.8.2.orig/configure.in	2007-06-09 19:54:09.000000000 +0100
+++ lirc-0.8.2/configure.in	2007-06-24 17:00:57.000000000 +0100
@@ -253,6 +253,11 @@
   possible_drivers="${possible_drivers} (dsp)"
   ]
 )
+dnl i2cuser driver requires the Linux I2C API
+AC_CHECK_HEADERS(linux/i2c-dev.h,[
+  possible_drivers="${possible_drivers} (i2cuser)"
+  ]
+)
 
 dnl here we see what driver the user wants.
 
@@ -267,7 +272,7 @@
                           creative_infracd, devinput, digimatrix, dsp,
                           dvico, ea65, exaudio, flyvideo, gvbctv5pci,
                           hauppauge, hauppauge_dvb,
-                          hercules_smarttv_stereo, igorplugusb,
+                          hercules_smarttv_stereo, i2cuser, igorplugusb,
                           iguanaIR, imon, imon_24g, imon_knob,
                           imon_pad, imon_rsc, irdeo, irdeo_remote,
                           irman, irreal, it87, knc_one, kworld,
@@ -370,6 +375,9 @@
 		;;
 	exaudio)
 		;;
+	i2cuser)
+		hw_module="${hw_module} hw_i2cuser.o"
+		;;
 	iguanaIR)
 		hw_module="${hw_module} hw_iguanaIR.o transmit.o receive.o"
 		iguanaIR_lib=-liguanaIR
@@ -757,6 +765,12 @@
   lircd_conf="hercules/lircd.conf.smarttv_stereo"
 fi
 
+if test "$driver" = "i2cuser"; then
+  lirc_driver="none"
+  hw_module="hw_i2cuser.o"
+  HW_DEFAULT="hw_i2cuser"
+fi
+
 if test "$driver" = "igorplugusb"; then
   lirc_driver="lirc_dev lirc_igorplugusb"
 fi
diff -X /home/azz/Code/misccode/diff-ignore -Naur lirc-0.8.2.orig/daemons/Makefile.am lirc-0.8.2/daemons/Makefile.am
--- lirc-0.8.2.orig/daemons/Makefile.am	2007-05-06 10:46:59.000000000 +0100
+++ lirc-0.8.2/daemons/Makefile.am	2007-06-24 17:00:43.000000000 +0100
@@ -30,6 +30,7 @@
 			hw_dsp.c \
 			hw_ea65.c hw_ea65.h \
 			hw_hiddev.c \
+			hw_i2cuser.c \
 			hw_iguanaIR.c \
 			hw_irman.c hw_irman.h \
 			hw_livedrive_common.c hw_livedrive_common.h \
@@ -78,6 +79,7 @@
 			hw_dsp.c \
 			hw_ea65.c hw_ea65.h \
 			hw_hiddev.c \
+			hw_i2cuser.c \
 			hw_iguanaIR.c \
 			hw_irman.c hw_irman.h \
 			hw_livedrive_common.c hw_livedrive_common.h \
diff -X /home/azz/Code/misccode/diff-ignore -Naur lirc-0.8.2.orig/daemons/hw-types.c lirc-0.8.2/daemons/hw-types.c
--- lirc-0.8.2.orig/daemons/hw-types.c	2007-05-05 13:20:03.000000000 +0100
+++ lirc-0.8.2/daemons/hw-types.c	2007-06-24 17:00:43.000000000 +0100
@@ -21,6 +21,7 @@
 extern struct hardware hw_dsp;
 extern struct hardware hw_dvico;
 extern struct hardware hw_ea65;
+extern struct hardware hw_i2cuser;
 extern struct hardware hw_iguanaIR;
 extern struct hardware hw_irman;
 extern struct hardware hw_livedrive_midi;
@@ -100,6 +101,7 @@
 #endif
 	&hw_dvico,
 	&hw_ea65,
+	&hw_i2cuser,
 #ifdef HAVE_IGUANAIR
 	&hw_iguanaIR,
 #endif
diff -X /home/azz/Code/misccode/diff-ignore -Naur lirc-0.8.2.orig/daemons/hw_i2cuser.c lirc-0.8.2/daemons/hw_i2cuser.c
--- lirc-0.8.2.orig/daemons/hw_i2cuser.c	1970-01-01 01:00:00.000000000 +0100
+++ lirc-0.8.2/daemons/hw_i2cuser.c	2007-06-24 17:00:43.000000000 +0100
@@ -0,0 +1,264 @@
+/*      $Id: $      */
+
+/*
+ * Remote control driver for I2C-attached devices from userspace
+ *
+ * Copyright 2006, 2007 Adam Sampson <ats@offog.org>
+ *
+ * This does the same job as the lirc_i2c kernel driver and hw_default, but
+ * entirely in userspace -- which avoids the need to build the kernel module,
+ * and should make this easier to port to other OSs in the future.
+ *
+ * At the moment, this only supports plain Hauppauge cards, since that's what
+ * I've got. To add support for more types of devices, look at lirc_i2c.
+ *
+ * Based on:
+ * Remote control driver for the Creative iNFRA CDrom
+ *   by Leonid Froenchenko <lfroen@il.marvell.com>
+ * i2c IR lirc plugin for Hauppauge and Pixelview cards
+ *   Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ *  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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <time.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+#include "hardware.h"
+#include "ir_remote.h"
+#include "lircd.h"
+
+/* The I2C address of the device to use. */
+#define IR_ADDR 0x1a
+
+/* The time that a key must be held down before it repeats (in seconds). */
+#define REPEAT_TIME 0.3
+
+int i2cuser_init(void);
+int i2cuser_deinit(void);
+int i2cuser_decode(struct ir_remote *remote,
+                   ir_code *prep, ir_code *codep, ir_code *postp,
+                   int *repeat_flagp, lirc_t *remaining_gapp);
+char *i2cuser_rec(struct ir_remote *remotes);
+
+struct hardware hw_i2cuser = {
+	0,                      /* determine device by probing */
+	-1,                     /* fd */
+	LIRC_CAN_REC_CODE,      /* features */
+	0,                      /* send_mode */
+	LIRC_MODE_LIRCCODE,     /* rec_mode */
+	13,                     /* code_length */
+	i2cuser_init,           /* init_func */
+	NULL,                   /* config_func */
+	i2cuser_deinit,         /* deinit_func */
+	NULL,                   /* send_func */
+	i2cuser_rec,            /* rec_func */
+	i2cuser_decode,         /* decode_func */
+	NULL,                   /* ioctl_func */
+	NULL,
+	"i2cuser"
+};
+
+/* FD of the i2c device. Since it's not selectable, we give the lircd core a
+   dummy device and poll it ourself. */
+static int i2c_fd = -1;
+/* The last code seen. */
+static ir_code code = 0;
+/* The time the last code was seen. */
+static double code_time = 0.0;
+/* The device name. */
+char device_name[256];
+
+/* Hunt for the appropriate i2c device and open it. */
+static int open_i2c_device(void) {
+	const char *adapter_dir = "/sys/class/i2c-adapter";
+	DIR *dir;
+	int found;
+
+	dir = opendir(adapter_dir);
+	if (dir == NULL) {
+		LOGPRINTF(1, "Cannot list i2c-adapter dir %s", adapter_dir);
+		return -1;
+	}
+	found = -1;
+
+	while (1) {
+		char s[256];
+		FILE *f;
+		struct dirent *de;
+
+		de = readdir(dir);
+		if (de == NULL)
+			break;
+		if (de->d_name[0] == '.')
+			continue;
+
+		/* Kernels prior to 2.6.22 had the name here: */
+		snprintf(s, sizeof s, "%s/%s/device/name", adapter_dir, de->d_name);
+
+		f = fopen(s, "r");
+		if (f == NULL) {
+			/* ... and 2.6.22 and later have it here: */
+			snprintf(s, sizeof s, "%s/%s/name", adapter_dir, de->d_name);
+
+			f = fopen(s, "r");
+		}
+		if (f == NULL) {
+			LOGPRINTF(1, "Cannot open i2c name file %s", s);
+			return -1;
+		}
+		memset(s, 0, sizeof s);
+		fread(s, 1, sizeof s, f);
+		fclose(f);
+
+		if (strncmp(s, "bt878", 5) == 0) {
+			if (strncmp(de->d_name, "i2c-", 4) != 0) {
+				LOGPRINTF(1, "i2c adapter dir %s has unexpected name", de->d_name);
+				return -1;
+			}
+			found = atoi(de->d_name + 4);
+			break;
+		}
+	}
+
+	closedir(dir);
+	if (found == -1) {
+		LOGPRINTF(1, "Cannot find i2c adapter");
+		return -1;
+	}
+
+	snprintf(device_name, sizeof device_name, "/dev/i2c-%d", found);
+	LOGPRINTF(1, "Using i2c device %s", device_name);
+	hw.device = device_name;
+	return open(device_name, O_RDWR);
+}
+
+int i2cuser_init(void) {
+	i2c_fd = open_i2c_device();
+	if (i2c_fd == -1) {
+		LOGPRINTF(1, "i2c device cannot be opened");
+		goto out;
+	}
+
+	if (ioctl(i2c_fd, I2C_SLAVE, IR_ADDR) < 0) {
+		LOGPRINTF(1, "Cannot set i2c address %02x", IR_ADDR);
+		goto out;
+	}
+
+	hw.fd = open("/dev/null", O_RDONLY);
+	if (hw.fd == -1) {
+		LOGPRINTF(1, "Failed to open /dev/null");
+		goto out;
+	}
+
+	LOGPRINTF(1, "i2cuser driver: i2c device found and ready to go");
+	return 1;
+
+out:
+	if (i2c_fd != -1)
+		close(i2c_fd);
+	if (hw.fd != -1)
+		close(hw.fd);
+	return 0;
+}
+
+int i2cuser_deinit(void) {
+	if (i2c_fd != -1)
+		close(i2c_fd);
+	if (hw.fd != -1)
+		close(hw.fd);
+	return 1;
+}
+
+char *i2cuser_rec(struct ir_remote *remotes) {
+	unsigned char buf[3];
+	int rc, count = 0;
+	ir_code new_code;
+	struct timeval tv;
+	double new_time;
+
+	do {
+		/* Poll 20 times per second. If we're interrupted while
+		   sleeping, exit the loop (so that the rest of lircd
+		   gets a chance to handle the signal). */
+		struct timespec ts = {0, 50000000};
+		if (nanosleep(&ts, NULL) == -1)
+			return NULL;
+
+		/* And similarly, if we've been looping for a while without
+		   seeing anything, head back out to the main loop for a bit. */
+		if (++count == 50)
+			return NULL;
+
+		rc = read(i2c_fd, &buf, sizeof buf);
+		if (rc < 0 && errno != EREMOTEIO) {
+			LOGPRINTF(1, "Error reading from i2c device: %s",
+			          strerror(errno));
+			return NULL;
+		} else if (rc != sizeof buf) {
+			continue;
+		}
+	} while ((buf[0] & 0x80) == 0);
+
+	gettimeofday(&tv, NULL);
+	new_time = tv.tv_sec + (0.000001L * tv.tv_usec);
+
+	new_code = ((buf[0] & 0x7f) << 6) | (buf[1] >> 2);
+	if (new_code == code) {
+		/* Same code as last time -- so we need to see whether it
+		   should be repeated or not. (The Hauppauge remote control
+		   will send a different code if you release and press the
+		   same key.) */
+		if (new_time - code_time < REPEAT_TIME)
+			return NULL;
+	}
+
+	code = new_code;
+	code_time = new_time;
+
+	LOGPRINTF(1, "Read input code: %08x", code);
+
+	return decode_all(remotes);
+}
+
+int i2cuser_decode(struct ir_remote *remote,
+                   ir_code *prep, ir_code *codep, ir_code *postp,
+                   int *repeat_flagp, lirc_t *remaining_gapp) {
+	/* No need to do any decoding. */
+
+	if (!map_code(remote, prep, codep, postp, 0, 0,
+	              hw_i2cuser.code_length, code, 0, 0)) {
+		return 0;
+	}
+
+	*repeat_flagp = 0;
+	*remaining_gapp = 0;
+	return 1;
+}
