diff --git a/configure.ac b/configure.ac
index 6c07e0d..9af2a96 100644
--- a/configure.ac
+++ b/configure.ac
@@ -172,7 +172,8 @@ if test x${no_kernel} != xyes; then
 	(lirc_dev lirc_sasem) \
 	(lirc_dev lirc_serial) \
 	(lirc_dev lirc_sir) \
-	(lirc_dev lirc_wpc8769l)"
+	(lirc_dev lirc_wpc8769l) \
+	(lirc_dev lirc_xbox)"
 fi
 
 AH_TEMPLATE([DAEMONIZE],
@@ -446,7 +447,7 @@ AC_ARG_WITH(driver,
                           srm7500libusb, tekram,
                           tekram_bt829, tira, tira_raw, ttusbir,
                           tuxbox, tvbox, udp, uirt2, uirt2_raw,
-                          usb_uirt_raw, usbx, wpc8769l],
+                          usb_uirt_raw, usbx, wpc8769l, xbox],
 driver=${withval},
 driver="unset"
 )
@@ -611,6 +612,8 @@ if test "$driver" = "userspace" -o "$driver" = "all"; then
 		;;
 	lirc_dev-lirc_wpc8769l)
 		;;
+	lirc_dev-lirc_xbox)
+  		;;
 	lirc_flyvideo)
 		;;
 	livedrive_midi)
@@ -1408,6 +1411,10 @@ if test "$driver" = "wpc8769l"; then
   lircd_conf="acer/lircd.conf.Aspire_6530G"
 fi
 
+if test "$driver" = "xbox"; then
+  lirc_driver="lirc_dev lirc_xbox"
+  lircd_conf="xbox/lircd.conf.xbox"
+fi
 
 #END HARDWARE HEURISTIC
 
@@ -1514,7 +1521,8 @@ elif test "$lirc_driver" = "all"; then
 	lirc_serial \
 	lirc_sir \
 	lirc_ttusbir \
-	lirc_wpc8769l"
+	lirc_wpc8769l \
+	lirc_xbox"
 fi
 if kernel_module=$(expr "$lirc_driver" : 'lirc_dev \(.*\)'); then
   :
@@ -1779,6 +1787,7 @@ AC_CONFIG_FILES([
   drivers/lirc_serial/Makefile
   drivers/lirc_sir/Makefile
   drivers/lirc_wpc8769l/Makefile
+  drivers/lirc_xbox/Makefile
   daemons/Makefile
   tools/Makefile
   doc/Makefile
diff --git a/drivers/lirc_xbox/Makefile.am b/drivers/lirc_xbox/Makefile.am
new file mode 100644
index 0000000..907aa82
--- /dev/null
+++ b/drivers/lirc_xbox/Makefile.am
@@ -0,0 +1,13 @@
+## $Id: Makefile.am,v 1.3 2004/04/25 16:29:24 lirc Exp $
+
+## Process this file with automake to produce Makefile.in
+
+## this is so that Automake includes the C compiling definitions, and
+## includes the source files in the distribution.
+EXTRA_PROGRAMS = automake_dummy
+automake_dummy_SOURCES = lirc_xbox.c
+
+## there is no *just* object file support in automake.  This is close enough
+module_DATA = lirc_xbox.o
+
+include ../Makefile.common
\ No newline at end of file
diff --git a/drivers/lirc_xbox/lirc_xbox.c b/drivers/lirc_xbox/lirc_xbox.c
new file mode 100644
index 0000000..d873455
--- /dev/null
+++ b/drivers/lirc_xbox/lirc_xbox.c
@@ -0,0 +1,993 @@
+/*
+ * lirc_xbox - USB remote support for LIRC
+ * (supports Microsoft XBOX DVD Dongle)
+ *
+ * Copyright (C) 2003-2004 Paul Miller <pmiller9@users.sourceforge.net>
+ *
+ * This driver was derived from:
+ *   Vladimir Dergachev <volodya@minspring.com>'s 2002
+ *      "USB ATI Remote support" (input device)
+ *   Adrian Dewhurst <sailor-lk@sailorfrag.net>'s 2002
+ *      "USB StreamZap remote driver" (LIRC)
+ *   Artur Lipowski <alipowski@kki.net.pl>'s 2002
+ *      "lirc_dev" and "lirc_gpio" LIRC modules
+ *   Michael Wojciechowski
+ *      initial xbox support
+ *   Vassilis Virvilis <vasvir@iit.demokritos.gr> 2006
+ *      reworked the patch for lirc submission
+ *   Paul Miller's <pmiller9@users.sourceforge.net> 2004
+ *      lirc_atiusb - removed all ati remote support
+ * $Id: lirc_xbox.c,v 1.88 2011/06/03 11:11:11 jmartin Exp $
+ */
+
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
+#include <linux/autoconf.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/smp_lock.h>
+#include <linux/completion.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+
+#include "drivers/kcompat.h"
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+#include <media/lirc.h>
+#include <media/lirc_dev.h>
+#else
+#include "drivers/lirc.h"
+#include "drivers/lirc_dev/lirc_dev.h"
+#endif
+
+#define DRIVER_VERSION		"$Revision: 0.01 $"
+#define DRIVER_AUTHOR		"Jason Martin <austinspartan@users.sourceforge.net>"
+#define DRIVER_DESC		"XBOX DVD Dongle USB remote driver for LIRC"
+#define DRIVER_NAME		"lirc_xbox"
+
+#define CODE_LENGTH		6
+#define CODE_MIN_LENGTH		6
+#define DECODE_LENGTH		1
+
+/* module parameters */
+#ifdef CONFIG_USB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG fmt, ## args);	\
+	} while (0)
+
+/*
+ * USB_BUFF_LEN must be the maximum value of the code_length array.
+ * It is used for static arrays.
+ */
+#define USB_BUFF_LEN 6
+
+static int mask = 0xFFFF;	/* channel acceptance bit mask */
+static int unique;		/* enable channel-specific codes */
+static int repeat = 10;		/* repeat time in 1/100 sec */
+static unsigned long repeat_jiffies; /* repeat timeout */
+
+/* get hi and low bytes of a 16-bits int */
+#define HI(a)			((unsigned char)((a) >> 8))
+#define LO(a)			((unsigned char)((a) & 0xff))
+
+/* general constants */
+#define SEND_FLAG_IN_PROGRESS	1
+#define SEND_FLAG_COMPLETE	2
+#define FREE_ALL		0xFF
+
+/* endpoints */
+#define EP_KEYS			0
+#define EP_MOUSE		1
+#define EP_MOUSE_ADDR		0x81
+#define EP_KEYS_ADDR		0x82
+
+/* USB vendor ids for XBOX DVD Dongles */
+#define VENDOR_MS1		0x040b
+#define VENDOR_MS2		0x045e
+#define VENDOR_MS3		0xFFFF
+
+static struct usb_device_id usb_remote_table[] = {
+	/* Gamester Xbox DVD Movie Playback Kit IR */
+	{ USB_DEVICE(VENDOR_MS1, 0x6521) },
+
+	/* Microsoft Xbox DVD Movie Playback Kit IR */
+	{ USB_DEVICE(VENDOR_MS2, 0x0284) },
+
+	/*
+	 * Some Chinese manufacturer -- conflicts with the joystick from the
+	 * same manufacturer
+	 */
+	{ USB_DEVICE(VENDOR_MS3, 0xFFFF) },
+
+	/* Terminating entry */
+	{ }
+};
+
+/* init strings */
+#define USB_OUTLEN		7
+
+static char init1[] = {0x01, 0x00, 0x20, 0x14};
+static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20};
+
+struct in_endpt {
+	/* inner link in list of endpoints for the remote specified by ir */
+	struct list_head iep_list_link;
+	struct xbox_dev *ir;
+	struct urb *urb;
+	struct usb_endpoint_descriptor *ep;
+
+	/* buffers and dma */
+	unsigned char *buf;
+	unsigned int len;
+	dma_addr_t dma;
+
+	/* handle repeats */
+	unsigned char old[USB_BUFF_LEN];
+	unsigned long old_jiffies;
+};
+
+struct out_endpt {
+	struct xbox_dev *ir;
+	struct urb *urb;
+	struct usb_endpoint_descriptor *ep;
+
+	/* buffers and dma */
+	unsigned char *buf;
+	dma_addr_t dma;
+
+	/* handle sending (init strings) */
+	int send_flags;
+	wait_queue_head_t wait;
+};
+
+
+/* data structure for each usb remote */
+struct xbox_dev {
+	/* inner link in list of all remotes managed by this module */
+	struct list_head remote_list_link;
+	/* Number of usb interfaces associated with this device */
+	int dev_refcount;
+
+	/* usb */
+	struct usb_device *usbdev;
+	/* Head link to list of all inbound endpoints in this remote */
+	struct list_head iep_listhead;
+	struct out_endpt *out_init;
+	int devnum;
+
+	/* lirc */
+	struct lirc_driver *d;
+	int connected;
+
+	/* locking */
+	struct mutex lock;
+};
+
+/* list of all registered devices via the remote_list_link in xbox_dev */
+static struct list_head remote_list;
+
+/*
+ * Convenience macros to retrieve a pointer to the surrounding struct from
+ * the given list_head reference within, pointed at by link.
+ */
+#define get_iep_from_link(link) \
+		list_entry((link), struct in_endpt, iep_list_link);
+#define get_irctl_from_link(link) \
+		list_entry((link), struct xbox_dev, remote_list_link);
+
+/* send packet - used to initialize remote */
+static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data)
+{
+	struct xbox_dev *ir = oep->ir;
+	DECLARE_WAITQUEUE(wait, current);
+	int timeout = HZ; /* 1 second */
+	unsigned char buf[USB_OUTLEN];
+
+	dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd);
+
+	mutex_lock(&ir->lock);
+	oep->urb->transfer_buffer_length = LO(cmd) + 1;
+	oep->urb->dev = oep->ir->usbdev;
+	oep->send_flags = SEND_FLAG_IN_PROGRESS;
+
+	memcpy(buf+1, data, LO(cmd));
+	buf[0] = HI(cmd);
+	memcpy(oep->buf, buf, LO(cmd)+1);
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&oep->wait, &wait);
+
+	if (usb_submit_urb(oep->urb, GFP_ATOMIC)) {
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&oep->wait, &wait);
+		mutex_unlock(&ir->lock);
+		return;
+	}
+	mutex_unlock(&ir->lock);
+
+	while (timeout && (oep->urb->status == -EINPROGRESS)
+	       && !(oep->send_flags & SEND_FLAG_COMPLETE)) {
+		timeout = schedule_timeout(timeout);
+		rmb();
+	}
+
+	dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd);
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&oep->wait, &wait);
+	oep->urb->transfer_flags |= URB_ASYNC_UNLINK;
+	usb_unlink_urb(oep->urb);
+}
+
+static int unregister_from_lirc(struct xbox_dev *ir)
+{
+	struct lirc_driver *d = ir->d;
+	int devnum;
+
+	devnum = ir->devnum;
+	dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum);
+
+	lirc_unregister_driver(d->minor);
+
+	printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum);
+	return 0;
+}
+
+static int set_use_inc(void *data)
+{
+	struct xbox_dev *ir = data;
+	struct list_head *pos, *n;
+	struct in_endpt *iep;
+	int rtn;
+
+	if (!ir) {
+		printk(DRIVER_NAME "[?]: set_use_inc called with no context\n");
+		return -EIO;
+	}
+	dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum);
+
+	mutex_lock(&ir->lock);
+	if (!ir->connected) {
+		if (!ir->usbdev) {
+			mutex_unlock(&ir->lock);
+			dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum);
+			return -ENOENT;
+		}
+
+		/* Iterate through the inbound endpoints */
+		list_for_each_safe(pos, n, &ir->iep_listhead) {
+			/* extract the current in_endpt */
+			iep = get_iep_from_link(pos);
+			iep->urb->dev = ir->usbdev;
+			dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n",
+				ir->devnum, iep->ep->bEndpointAddress, iep);
+			rtn = usb_submit_urb(iep->urb, GFP_ATOMIC);
+			if (rtn) {
+				printk(DRIVER_NAME "[%d]: open result = %d "
+				       "error submitting urb\n",
+				       ir->devnum, rtn);
+				mutex_unlock(&ir->lock);
+				return -EIO;
+			}
+		}
+		ir->connected = 1;
+	}
+	mutex_unlock(&ir->lock);
+
+	return 0;
+}
+
+static void set_use_dec(void *data)
+{
+	struct xbox_dev *ir = data;
+	struct list_head *pos, *n;
+	struct in_endpt *iep;
+
+	if (!ir) {
+		printk(DRIVER_NAME "[?]: set_use_dec called with no context\n");
+		return;
+	}
+	dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum);
+
+	mutex_lock(&ir->lock);
+	if (ir->connected) {
+		/* Free inbound usb urbs */
+		list_for_each_safe(pos, n, &ir->iep_listhead) {
+			iep = get_iep_from_link(pos);
+			dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n",
+				ir->devnum, iep->ep->bEndpointAddress, iep);
+			usb_kill_urb(iep->urb);
+		}
+		ir->connected = 0;
+	}
+	mutex_unlock(&ir->lock);
+}
+
+static void print_data(struct in_endpt *iep, char *buf, int len)
+{
+        const int clen = CODE_LENGTH;
+	char codes[clen * 3 + 1];
+	int i;
+
+	if (len <= 0)
+		return;
+
+	for (i = 0; i < len && i < clen; i++)
+		snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF);
+	printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n",
+		iep->ir->devnum, codes, iep->ep->bEndpointAddress, len);
+}
+
+static int code_check_xbox(struct in_endpt *iep, int len)
+{
+  //	struct xbox_dev *ir = iep->ir;
+	const int clen = CODE_LENGTH;
+
+	if (len != clen) {
+		dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox "
+			"ir.. ?\n", len, clen);
+		return -1;
+	}
+
+	/* check for repeats */
+	if (memcmp(iep->old, iep->buf, len) == 0) {
+		if (iep->old_jiffies + repeat_jiffies > jiffies)
+			return -1;
+	} else {
+		/*
+		 * the third byte of xbox ir packet seems to contain key info
+		 * the last two bytes are.. some kind of clock?
+		 */
+		iep->buf[0] = iep->buf[2];
+		memset(iep->buf + 1, 0, len - 1);
+		memcpy(iep->old, iep->buf, len);
+	}
+	iep->old_jiffies = jiffies;
+
+	return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_remote_recv(struct urb *urb, struct pt_regs *regs)
+#else
+static void usb_remote_recv(struct urb *urb)
+#endif
+{
+	struct in_endpt *iep;
+	int len, result = -1;
+
+	if (!urb)
+		return;
+	iep = urb->context;
+	if (!iep) {
+		urb->transfer_flags |= URB_ASYNC_UNLINK;
+		usb_unlink_urb(urb);
+		return;
+	}
+	if (!iep->ir->usbdev)
+		return;
+
+	len = urb->actual_length;
+	if (debug)
+		print_data(iep, urb->transfer_buffer, len);
+
+	switch (urb->status) {
+
+	case 0:
+	        result = code_check_xbox(iep, len);
+	  
+	        if (result < 0)
+	        break;
+
+		lirc_buffer_write(iep->ir->d->rbuf, iep->buf);
+		wake_up(&iep->ir->d->rbuf->wait_poll);
+		break;
+
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		urb->transfer_flags |= URB_ASYNC_UNLINK;
+		usb_unlink_urb(urb);
+		return;
+
+	case -EPIPE:
+	default:
+		break;
+	}
+
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_remote_send(struct urb *urb, struct pt_regs *regs)
+#else
+static void usb_remote_send(struct urb *urb)
+#endif
+{
+	struct out_endpt *oep;
+
+	if (!urb)
+		return;
+	oep = urb->context;
+	if (!oep) {
+		urb->transfer_flags |= URB_ASYNC_UNLINK;
+		usb_unlink_urb(urb);
+		return;
+	}
+	if (!oep->ir->usbdev)
+		return;
+
+	dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum);
+
+	if (urb->status)
+		return;
+
+	oep->send_flags |= SEND_FLAG_COMPLETE;
+	wmb();
+	if (waitqueue_active(&oep->wait))
+		wake_up(&oep->wait);
+}
+
+
+/*
+ * Initialization and removal
+ */
+
+/*
+ * Free iep according to mem_failure which specifies a checkpoint into the
+ * initialization sequence for rollback recovery.
+ */
+static void free_in_endpt(struct in_endpt *iep, int mem_failure)
+{
+	struct xbox_dev *ir;
+	dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure);
+	if (!iep)
+		return;
+
+	ir = iep->ir;
+	if (!ir) {
+		dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n");
+		return;
+	}
+	mutex_lock(&ir->lock);
+	switch (mem_failure) {
+	case FREE_ALL:
+	case 5:
+		list_del(&iep->iep_list_link);
+		dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x "
+			"from list\n", ir->devnum, iep->ep->bEndpointAddress);
+	case 4:
+		if (iep->urb) {
+			iep->urb->transfer_flags |= URB_ASYNC_UNLINK;
+			usb_unlink_urb(iep->urb);
+			usb_free_urb(iep->urb);
+			iep->urb = 0;
+		} else
+			dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n",
+				ir->devnum);
+	case 3:
+		usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma);
+		iep->buf = 0;
+	case 2:
+		kfree(iep);
+	}
+	mutex_unlock(&ir->lock);
+}
+
+/*
+ * Construct a new inbound endpoint for this remote, and add it to the list of
+ * in_epts in ir.
+ */
+static struct in_endpt *new_in_endpt(struct xbox_dev *ir,
+				     struct usb_endpoint_descriptor *ep)
+{
+	struct usb_device *dev = ir->usbdev;
+	struct in_endpt *iep;
+	int pipe, maxp, len, addr;
+	int mem_failure;
+
+	addr = ep->bEndpointAddress;
+	pipe = usb_rcvintpipe(dev, addr);
+	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+/*	len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp;
+ *	len -= (len % CODE_LENGTH); */
+	len = CODE_LENGTH;
+
+	dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found "
+		"(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len);
+
+	mem_failure = 0;
+	iep = kzalloc(sizeof(*iep), GFP_KERNEL);
+	if (!iep) {
+		mem_failure = 1;
+		goto new_in_endpt_failure_check;
+	}
+	iep->ir = ir;
+	iep->ep = ep;
+	iep->len = len;
+
+	iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma);
+	if (!iep->buf) {
+		mem_failure = 2;
+		goto new_in_endpt_failure_check;
+	}
+
+	iep->urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!iep->urb)
+		mem_failure = 3;
+
+new_in_endpt_failure_check:
+
+	if (mem_failure) {
+		free_in_endpt(iep, mem_failure);
+		printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n",
+		       ir->devnum, addr, mem_failure);
+		return NULL;
+	}
+	list_add_tail(&iep->iep_list_link, &ir->iep_listhead);
+	dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n",
+		ir->devnum, iep->ep->bEndpointAddress);
+	return iep;
+}
+
+static void free_out_endpt(struct out_endpt *oep, int mem_failure)
+{
+	struct xbox_dev *ir;
+	dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure);
+	if (!oep)
+		return;
+
+	wake_up_all(&oep->wait);
+
+	ir = oep->ir;
+	if (!ir) {
+		dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n");
+		return;
+	}
+	mutex_lock(&ir->lock);
+	switch (mem_failure) {
+	case FREE_ALL:
+	case 4:
+		if (oep->urb) {
+			oep->urb->transfer_flags |= URB_ASYNC_UNLINK;
+			usb_unlink_urb(oep->urb);
+			usb_free_urb(oep->urb);
+			oep->urb = 0;
+		} else {
+			dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n",
+				ir->devnum);
+		}
+	case 3:
+		usb_free_coherent(oep->ir->usbdev, USB_OUTLEN,
+				  oep->buf, oep->dma);
+		oep->buf = 0;
+	case 2:
+		kfree(oep);
+	}
+	mutex_unlock(&ir->lock);
+}
+
+static struct out_endpt *new_out_endpt(struct xbox_dev *ir,
+				       struct usb_endpoint_descriptor *ep)
+{
+	struct usb_device *dev = ir->usbdev;
+	struct out_endpt *oep;
+	int mem_failure;
+
+	dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n",
+		ir->devnum, ep->bEndpointAddress);
+
+	mem_failure = 0;
+	oep = kzalloc(sizeof(*oep), GFP_KERNEL);
+	if (!oep)
+		mem_failure = 1;
+	else {
+		oep->ir = ir;
+		oep->ep = ep;
+		init_waitqueue_head(&oep->wait);
+
+		oep->buf = usb_alloc_coherent(dev, USB_OUTLEN,
+					      GFP_ATOMIC, &oep->dma);
+		if (!oep->buf)
+			mem_failure = 2;
+		else {
+			oep->urb = usb_alloc_urb(0, GFP_KERNEL);
+			if (!oep->urb)
+				mem_failure = 3;
+		}
+	}
+	if (mem_failure) {
+		free_out_endpt(oep, mem_failure);
+		printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n",
+		       ir->devnum, ep->bEndpointAddress, mem_failure);
+		return NULL;
+	}
+	return oep;
+}
+
+static void free_irctl(struct xbox_dev *ir, int mem_failure)
+{
+	struct list_head *pos, *n;
+	struct in_endpt *in;
+	dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure);
+
+	if (!ir)
+		return;
+
+	list_for_each_safe(pos, n, &ir->iep_listhead) {
+		in = get_iep_from_link(pos);
+		free_in_endpt(in, FREE_ALL);
+	}
+	if (ir->out_init) {
+		free_out_endpt(ir->out_init, FREE_ALL);
+		ir->out_init = NULL;
+	}
+
+	mutex_lock(&ir->lock);
+	switch (mem_failure) {
+	case FREE_ALL:
+	case 6:
+		if (!--ir->dev_refcount) {
+			list_del(&ir->remote_list_link);
+			dprintk(DRIVER_NAME "[%d]: free_irctl: removing "
+				"remote from list\n", ir->devnum);
+		} else {
+			dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d,"
+				"aborting free_irctl\n",
+				ir->devnum, ir->dev_refcount);
+			mutex_unlock(&ir->lock);
+			return;
+		}
+	case 5:
+	case 4:
+	case 3:
+		if (ir->d) {
+			switch (mem_failure) {
+			case 5:
+				lirc_buffer_free(ir->d->rbuf);
+			case 4:
+				kfree(ir->d->rbuf);
+			case 3:
+				kfree(ir->d);
+			}
+		} else
+			printk(DRIVER_NAME "[%d]: ir->d is a null pointer!\n",
+			       ir->devnum);
+	case 2:
+		mutex_unlock(&ir->lock);
+		kfree(ir);
+		return;
+	}
+	mutex_unlock(&ir->lock);
+}
+
+static struct xbox_dev *new_irctl(struct usb_interface *intf)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct xbox_dev *ir;
+	struct lirc_driver *driver;
+	int devnum, dclen;
+	int mem_failure;
+
+	devnum = dev->devnum;
+
+	dprintk(DRIVER_NAME "[%d]: remote type = XBOX DVD Dongle\n", devnum);
+
+	mem_failure = 0;
+	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+	if (!ir) {
+		mem_failure = 1;
+		goto new_irctl_failure_check;
+	}
+
+	dclen = DECODE_LENGTH;
+
+	/*
+	 * add this infrared remote struct to remote_list, keeping track
+	 * of the number of drivers registered.
+	 */
+	dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum);
+	list_add_tail(&ir->remote_list_link, &remote_list);
+	ir->dev_refcount = 1;
+
+	driver = kzalloc(sizeof(*driver), GFP_KERNEL);
+	if (!driver) {
+		mem_failure = 2;
+		goto new_irctl_failure_check;
+	}
+
+	ir->d = driver;
+	driver->rbuf = kmalloc(sizeof(*(driver->rbuf)), GFP_KERNEL);
+	if (!driver->rbuf) {
+		mem_failure = 3;
+		goto new_irctl_failure_check;
+	}
+
+	if (lirc_buffer_init(driver->rbuf, dclen, 2)) {
+		mem_failure = 4;
+		goto new_irctl_failure_check;
+	}
+
+	strcpy(driver->name, DRIVER_NAME " ");
+	driver->minor = -1;
+	driver->code_length = dclen * 8;
+	driver->features = LIRC_CAN_REC_LIRCCODE;
+	driver->data = ir;
+	driver->set_use_inc = &set_use_inc;
+	driver->set_use_dec = &set_use_dec;
+	driver->dev = &intf->dev;
+	driver->owner = THIS_MODULE;
+	ir->usbdev = dev;
+	ir->devnum = devnum;
+
+	mutex_init(&ir->lock);
+	INIT_LIST_HEAD(&ir->iep_listhead);
+
+new_irctl_failure_check:
+
+	if (mem_failure) {
+		free_irctl(ir, mem_failure);
+		printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n",
+		       devnum, mem_failure);
+		return NULL;
+	}
+	return ir;
+}
+
+/*
+ * Scan the global list of remotes to see if the device listed is one of them.
+ * If it is, the corresponding xbox_dev is returned, with its dev_refcount
+ * incremented.  Otherwise, returns null.
+ */
+static struct xbox_dev *get_prior_reg_ir(struct usb_device *dev)
+{
+	struct list_head *pos;
+	struct xbox_dev *ir = NULL;
+
+	dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum);
+	list_for_each(pos, &remote_list) {
+		ir = get_irctl_from_link(pos);
+		if (ir->usbdev != dev) {
+			dprintk(DRIVER_NAME "[%d]: device %d isn't it...",
+				dev->devnum, ir->devnum);
+		    ir = NULL;
+		} else {
+			dprintk(DRIVER_NAME "[%d]: prior instance found.\n",
+				dev->devnum);
+			ir->dev_refcount++;
+			break;
+		}
+	}
+	return ir;
+}
+
+/*
+ * If the USB interface has an out endpoint for control. 
+ */
+static void send_outbound_init(struct xbox_dev *ir)
+{
+	if (ir->out_init) {
+		struct out_endpt *oep = ir->out_init;
+		dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing "
+			"outbound ep\n", ir->devnum);
+		usb_fill_int_urb(oep->urb, ir->usbdev,
+			usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress),
+			oep->buf, USB_OUTLEN, usb_remote_send,
+			oep, oep->ep->bInterval);
+		oep->urb->transfer_dma = oep->dma;
+		oep->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+		send_packet(oep, 0x8004, init1);
+		send_packet(oep, 0x8007, init2);
+	}
+}
+
+/* Log driver and usb info */
+static void log_usb_dev_info(struct usb_device *dev)
+{
+	char buf[63], name[128] = "";
+
+	if (dev->descriptor.iManufacturer
+	    && usb_string(dev, dev->descriptor.iManufacturer,
+			  buf, sizeof(buf)) > 0)
+		strlcpy(name, buf, sizeof(name));
+	if (dev->descriptor.iProduct
+	    && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0)
+		snprintf(name + strlen(name), sizeof(name) - strlen(name),
+			 " %s", buf);
+	printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name,
+	       dev->bus->busnum, dev->devnum);
+}
+
+
+static int usb_remote_probe(struct usb_interface *intf,
+				const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_host_interface *idesc;
+	struct usb_endpoint_descriptor *ep;
+	struct in_endpt *iep;
+	struct xbox_dev *ir;
+	int i;
+
+	dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n",
+		dev->devnum, dev, intf, id);
+
+	idesc = intf->cur_altsetting;
+
+	/* Check if a usb remote has already been registered for this device */
+	ir = get_prior_reg_ir(dev);
+
+	if (!ir) {
+		ir = new_irctl(intf);
+		if (!ir)
+			return -ENOMEM;
+	}
+
+	/*
+	 * step through the endpoints to find first in and first out endpoint
+	 * of type interrupt transfer
+	 */
+	for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
+		ep = &idesc->endpoint[i].desc;
+		dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n",
+			dev->devnum, i);
+		if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
+		     USB_DIR_IN) &&
+		     ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		      USB_ENDPOINT_XFER_INT)) {
+
+			iep = new_in_endpt(ir, ep);
+			if (iep)
+			{
+				usb_fill_int_urb(iep->urb, dev,
+					usb_rcvintpipe(dev,
+						iep->ep->bEndpointAddress),
+					iep->buf, iep->len, usb_remote_recv,
+					iep, iep->ep->bInterval);
+				iep->urb->transfer_dma = iep->dma;
+				iep->urb->transfer_flags |=
+					URB_NO_TRANSFER_DMA_MAP;
+			}
+		}
+
+		if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
+		     USB_DIR_OUT) &&
+		     ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		      USB_ENDPOINT_XFER_INT) &&
+		      (ir->out_init == NULL))
+			ir->out_init = new_out_endpt(ir, ep);
+	}
+	if (list_empty(&ir->iep_listhead)) {
+		printk(DRIVER_NAME "[%d]: inbound endpoint not found\n",
+		       ir->devnum);
+		free_irctl(ir, FREE_ALL);
+		return -ENODEV;
+	}
+	if (ir->dev_refcount == 1) {
+		ir->d->minor = lirc_register_driver(ir->d);
+		if (ir->d->minor < 0) {
+			free_irctl(ir, FREE_ALL);
+			return -ENODEV;
+		}
+
+		/* Note new driver registration in kernel logs */
+		log_usb_dev_info(dev);
+
+		/* outbound data (initialization) */
+		send_outbound_init(ir);
+	}
+
+	usb_set_intfdata(intf, ir);
+	return 0;
+}
+
+static void usb_remote_disconnect(struct usb_interface *intf)
+{
+	/* struct usb_device *dev = interface_to_usbdev(intf); */
+	struct xbox_dev *ir = usb_get_intfdata(intf);
+	usb_set_intfdata(intf, NULL);
+
+	dprintk(DRIVER_NAME ": disconnecting remote %d:\n",
+		(ir ? ir->devnum : -1));
+	if (!ir || !ir->d)
+		return;
+
+	if (ir->usbdev) {
+		/* Only unregister once */
+		ir->usbdev = NULL;
+		unregister_from_lirc(ir);
+	}
+
+	/* This also removes the current remote from remote_list */
+	free_irctl(ir, FREE_ALL);
+}
+
+static struct usb_driver usb_remote_driver = {
+	LIRC_THIS_MODULE(.owner = THIS_MODULE)
+	.name		= DRIVER_NAME,
+	.probe		= usb_remote_probe,
+	.disconnect	= usb_remote_disconnect,
+	.id_table	= usb_remote_table
+};
+
+static int __init usb_remote_init(void)
+{
+	int i;
+
+	INIT_LIST_HEAD(&remote_list);
+
+	printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " "
+	       DRIVER_VERSION "\n");
+	printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n");
+	dprintk(DRIVER_NAME ": debug mode enabled: "
+		"$Id: lirc_xbox.c,v 1.88 2011/06/05 11:11:11 jmartin Exp $\n");
+
+	repeat_jiffies = repeat*HZ/100;
+
+	i = usb_register(&usb_remote_driver);
+	if (i) {
+		printk(DRIVER_NAME ": usb register failed, result = %d\n", i);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit usb_remote_exit(void)
+{
+	usb_deregister(&usb_remote_driver);
+}
+
+module_init(usb_remote_init);
+module_exit(usb_remote_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, usb_remote_table);
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)");
+
+module_param(mask, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)");
+
+module_param(unique, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)");
+
+module_param(repeat, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)");
diff --git a/remotes/xbox/lircd.conf.xbox b/remotes/xbox/lircd.conf.xbox
new file mode 100644
index 0000000..d49cb80
--- /dev/null
+++ b/remotes/xbox/lircd.conf.xbox
@@ -0,0 +1,58 @@
+#lirc.conf.xbox
+# Please make this file available to others
+# by sending it to <lirc@bartelmus.de>
+#
+# this config file was automatically generated
+# using lirc-0.8.2-CVS(default) on Mon Aug 25 09:04:22 2008
+#
+# contributed by 
+#
+# brand:                       xbox.conf
+# model no. of remote control: 
+# devices being controlled by this remote:
+#
+
+begin remote
+
+  name  xbox.conf
+  bits            8
+  eps            30
+  aeps          100
+
+  one             0     0
+  zero            0     0
+  gap          163983
+  min_repeat      15
+  toggle_bit_mask 0x0
+
+      begin codes
+          MENU                     0xF7
+          DISPLAY                  0xD5
+          TITLE                    0xE5
+          INFO                     0xC3
+          EXIT                     0xD8
+          UP                       0xA6
+          DOWN                     0xA7
+          LEFT                     0xA9
+          RIGHT                    0xA8
+          SELECT                   0x0B
+          SKIP-                    0xDD
+          SKIP+                    0xDF
+          REW                      0xE2
+          FF                       0xE3
+          STOP                     0xE0
+          1                        0xCE
+          2                        0xCD
+          PAUSE                    0xE6
+          PLAY                     0xEA
+          3                        0xCC
+          4                        0xCB
+          5                        0xCA
+          6                        0xC9
+          7                        0xC8
+          8                        0xC7
+          9                        0xC6
+          0                        0xCF
+      end codes
+
+end remote
diff --git a/setup.data b/setup.data
index 407d6b2..e9e9ee0 100644
--- a/setup.data
+++ b/setup.data
@@ -146,7 +146,8 @@ hw_menu_entry: @hw-usb
 	usb_uirt_raw: "USB-UIRT"
 	mplay: "VLSystem MPlay Blast"
 	mplay: "VLSystem MPlay Mini"
-
+ 	xbox: "XBOX DVD Dongle"
+    
 param_type: \
 	act200l \
 	act220l \
@@ -260,7 +261,8 @@ param_type: \
 	ttusbir \
 	tvbox \
 	udp \
-	wpc8769l
+	wpc8769l \
+	xbox
 	none:
 
 default_param: \
@@ -331,7 +333,8 @@ default_param: \
 	ttusbir \
 	tvbox \
 	udp \
-	wpc8769l
+	wpc8769l \
+ 	xbox
 	none:
 
 default_param: \
