diff -Naur lirc-0.8.3/drivers/lirc_atiusb/lirc_atiusb.c lirc-0.8.3.new/drivers/lirc_atiusb/lirc_atiusb.c
--- lirc-0.8.3/drivers/lirc_atiusb/lirc_atiusb.c	2008-04-28 16:47:29.000000000 +1000
+++ lirc-0.8.3.new/drivers/lirc_atiusb/lirc_atiusb.c	2008-10-18 04:55:47.000000000 +1100
@@ -16,7 +16,7 @@
  *   Vassilis Virvilis <vasvir@iit.demokritos.gr> 2006
  *      reworked the patch for lirc submission
  *
- * $Id: lirc_atiusb.c,v 1.69 2008/04/28 06:47:29 lirc Exp $
+ * $Id: lirc_atiusb.c,v 1.71 2008/05/19 08:10:35 uzuul Exp $
  */
 
 /*
@@ -67,7 +67,7 @@
 #include "drivers/kcompat.h"
 #include "drivers/lirc_dev/lirc_dev.h"
 
-#define DRIVER_VERSION		"$Revision: 1.69 $"
+#define DRIVER_VERSION		"$Revision: 1.71 $"
 #define DRIVER_AUTHOR		"Paul Miller <pmiller9@users.sourceforge.net>"
 #define DRIVER_DESC		"USB remote driver for LIRC"
 #define DRIVER_NAME		"lirc_atiusb"
@@ -180,8 +180,8 @@
 	/* Microsoft Xbox DVD Movie Playback Kit IR */
 	{ USB_DEVICE(VENDOR_MS2, 0x0284) },
 
-	/* Some chinese manufacterer -- conflicts with the joystick from the
-	 * same manufacterer */
+	/* Some chinese manufacturer -- conflicts with the joystick from the
+	 * same manufacturer */
 	{ USB_DEVICE(VENDOR_MS3, 0xFFFF) },
 
 	/* Terminating entry */
@@ -1357,7 +1357,7 @@
 	       DRIVER_VERSION "\n");
 	printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n");
 	dprintk(DRIVER_NAME ": debug mode enabled: "
-		"$Id: lirc_atiusb.c,v 1.69 2008/04/28 06:47:29 lirc Exp $\n");
+		"$Id: lirc_atiusb.c,v 1.71 2008/05/19 08:10:35 uzuul Exp $\n");
 
 	request_module("lirc_dev");
 
diff -Naur lirc-0.8.3/drivers/lirc_cmdir/commandir.c lirc-0.8.3.new/drivers/lirc_cmdir/commandir.c
--- lirc-0.8.3/drivers/lirc_cmdir/commandir.c	2008-09-25 07:31:28.000000000 +1000
+++ lirc-0.8.3.new/drivers/lirc_cmdir/commandir.c	2008-10-18 04:55:47.000000000 +1100
@@ -54,8 +54,10 @@
 /* table of devices that work with this driver */
 static struct usb_device_id cmdir_table [] =
 {
+	/* COMMANDIR USB Transceiver */
 	{ USB_DEVICE(USB_CMDIR_VENDOR_ID, USB_CMDIR_PRODUCT_ID) },
-	{ }			/* Terminating entry */
+	/* Terminating entry */
+	{ }
 };
 MODULE_DEVICE_TABLE(usb, cmdir_table);
 
@@ -865,7 +867,6 @@
 {
 	struct usb_skel *dev;
 	int retval = 0;
-	int len;
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
 	if (minor_table[rx_device] == NULL)
@@ -876,7 +877,7 @@
 	down(&dev->sem);
 	retval = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev,
 						dev->bulk_in_endpointAddr),
-		 dev->bulk_in_buffer, dev->bulk_in_size, &len, HZ*100);
+		 dev->bulk_in_buffer, dev->bulk_in_size, &count, HZ*100);
 #else
 	struct usb_interface *interface;
 	interface = usb_find_interface(&cmdir_driver,
@@ -893,15 +894,15 @@
 	retval = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev,
 						dev->bulk_in_endpointAddr),
 		 dev->bulk_in_buffer, min(dev->bulk_in_size, count),
-		 &len, HZ*10);
+		 &count, HZ*10);
 #endif
 	if (!retval) {
-		if (!memcpy(buffer, dev->bulk_in_buffer, len))
+		if (!memcpy(buffer, dev->bulk_in_buffer, count))
 			retval = -EFAULT;
 		else {
 			/* current status of the TX buffer */
 			curTXFill = buffer[2];
-			retval = len;
+			retval = count;
 		}
 	}
 	/* suppress errors */
diff -Naur lirc-0.8.3/drivers/lirc_dev/lirc_dev.c lirc-0.8.3.new/drivers/lirc_dev/lirc_dev.c
--- lirc-0.8.3/drivers/lirc_dev/lirc_dev.c	2008-09-25 07:31:28.000000000 +1000
+++ lirc-0.8.3.new/drivers/lirc_dev/lirc_dev.c	2008-10-18 04:55:47.000000000 +1100
@@ -17,7 +17,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: lirc_dev.c,v 1.58 2008/05/14 16:37:49 lirc Exp $
+ * $Id: lirc_dev.c,v 1.61 2008/09/27 08:16:15 lirc Exp $
  *
  */
 
@@ -49,7 +49,11 @@
 #include <linux/uaccess.h>
 #include <linux/errno.h>
 #endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
+#include <asm/semaphore.h>
+#else
 #include <linux/semaphore.h>
+#endif
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
 #include <linux/wrapper.h>
 #endif
@@ -139,15 +143,6 @@
 {
 	dprintk(LOGHEAD "cleaning up\n", ir->p.name, ir->p.minor);
 
-#ifdef LIRC_HAVE_DEVFS_24
-	devfs_unregister(ir->devfs_handle);
-#endif
-#ifdef LIRC_HAVE_DEVFS_26
-	devfs_remove(DEV_LIRC "/%u", ir->p.minor);
-#endif
-	lirc_device_destroy(lirc_class,
-			    MKDEV(IRCTL_DEV_MAJOR, ir->p.minor));
-
 	if (ir->buf != ir->p.rbuf) {
 		lirc_buffer_free(ir->buf);
 		kfree(ir->buf);
@@ -401,9 +396,9 @@
 			S_IFCHR|S_IRUSR|S_IWUSR,
 			DEV_LIRC "/%u", ir->p.minor);
 #endif
-	(void) device_create(lirc_class, ir->p.dev,
-				  MKDEV(IRCTL_DEV_MAJOR, ir->p.minor),
-				  NULL, "lirc%u", ir->p.minor);
+	(void) lirc_device_create(lirc_class, ir->p.dev,
+				  MKDEV(IRCTL_DEV_MAJOR, ir->p.minor), NULL,
+				  "lirc%u", ir->p.minor);
 
 	if (p->sample_rate || p->get_queue) {
 		/* try to fire up polling thread */
@@ -522,7 +517,18 @@
 		ir->p.set_use_dec(ir->p.data);
 		module_put(ir->p.owner);
 		up(&ir->buffer_sem);
-	} else
+	}
+
+#ifdef LIRC_HAVE_DEVFS_24
+	devfs_unregister(ir->devfs_handle);
+#endif
+#ifdef LIRC_HAVE_DEVFS_26
+	devfs_remove(DEV_LIRC "/%u", ir->p.minor);
+#endif
+	lirc_device_destroy(lirc_class,
+			    MKDEV(IRCTL_DEV_MAJOR, ir->p.minor));
+
+	if (!ir->open)
 		cleanup(ir);
 	up(&plugin_lock);
 
diff -Naur lirc-0.8.3/drivers/lirc_imon/lirc_imon.c lirc-0.8.3.new/drivers/lirc_imon/lirc_imon.c
--- lirc-0.8.3/drivers/lirc_imon/lirc_imon.c	2008-09-25 07:31:28.000000000 +1000
+++ lirc-0.8.3.new/drivers/lirc_imon/lirc_imon.c	2008-10-18 04:55:47.000000000 +1100
@@ -1,7 +1,7 @@
 /*
  *   lirc_imon.c:  LIRC plugin/VFD driver for Ahanix/Soundgraph IMON IR/VFD
  *
- *   $Id: lirc_imon.c,v 1.23 2008/01/19 10:06:46 lirc Exp $
+ *   $Id: lirc_imon.c,v 1.31 2008/10/15 21:10:52 jarodwilson Exp $
  *
  *   Version 0.3
  *		Supports newer iMON models that send decoded IR signals.
@@ -73,9 +73,9 @@
 
 
 #define MOD_AUTHOR	"Venky Raju <dev@venky.ws>"
-#define MOD_DESC	"Driver for Soundgraph iMON MultiMedia IR/VFD w/imon pad2keys patch"
+#define MOD_DESC	"Driver for Soundgraph iMON MultiMedia IR/VFD"
 #define MOD_NAME	"lirc_imon"
-#define MOD_VERSION	"0.3p2k"
+#define MOD_VERSION	"0.4"
 
 #define VFD_MINOR_BASE	144	/* Same as LCD */
 #define DEVFS_MODE	(S_IFCHR | S_IRUSR | S_IWUSR | \
@@ -91,7 +91,6 @@
 #define	TRUE		1
 #define FALSE		0
 
-#define CURSOR_LIMIT	16
 
 /* ------------------------------------------------------------
  *		     P R O T O T Y P E S
@@ -163,6 +162,7 @@
 	struct usb_endpoint_descriptor *tx_endpoint;
 	struct urb *rx_urb;
 	struct urb *tx_urb;
+	int tx_control;
 	unsigned char usb_rx_buf[8];
 	unsigned char usb_tx_buf[8];
 
@@ -178,10 +178,6 @@
 		atomic_t busy;			/* write in progress */
 		int status;			/* status of tx completion */
 	} tx;
-
-	int key_x;
-	int key_y;
-	int last_count;				/* number of times pressed   */
 };
 
 #define LOCK_CONTEXT	down(&context->sem)
@@ -195,29 +191,71 @@
 	.release	= &vfd_close
 };
 
+enum {
+	IMON_DISPLAY_TYPE_AUTO,
+	IMON_DISPLAY_TYPE_VFD,
+	IMON_DISPLAY_TYPE_LCD,
+	IMON_DISPLAY_TYPE_NONE,
+};
+
 /* USB Device ID for IMON USB Control Board */
 static struct usb_device_id imon_usb_id_table[] = {
-	{ USB_DEVICE(0x0aa8, 0xffda) },		/* IR & VFD    */
-	{ USB_DEVICE(0x0aa8, 0x8001) },		/* IR only     */
-	{ USB_DEVICE(0x15c2, 0xffda) },		/* IR & VFD    */
-	{ USB_DEVICE(0x15c2, 0xffdc) },		/* IR & VFD    */
-	{ USB_DEVICE(0x04e8, 0xff30) },		/* ext IR only */
+	/* IMON USB Control Board (IR & VFD) */
+	{ USB_DEVICE(0x0aa8, 0xffda) },
+	/* IMON USB Control Board (IR only) */
+	{ USB_DEVICE(0x0aa8, 0x8001) },
+	/* IMON USB Control Board (IR & VFD) */
+	{ USB_DEVICE(0x15c2, 0xffda) },
+	/* IMON USB Control Board (IR & VFD) */
+	{ USB_DEVICE(0x15c2, 0xffdc) },
+	/* IMON USB Control Board (IR & LCD) */
+	{ USB_DEVICE(0x15c2, 0x0034) },
+	/* IMON USB Control Board (IR & LCD) */
+	{ USB_DEVICE(0x15c2, 0x0036) },
+	/* IMON USB Control Board (IR & LCD) */
+	{ USB_DEVICE(0x15c2, 0x0038) },
+	/* IMON USB Control Board (ext IR only) */
+	{ USB_DEVICE(0x04e8, 0xff30) },
 	{}
 };
 
 /* Some iMON VFD models requires a 6th packet */
-static unsigned short vfd_proto_6p_vendor_list[] = {
-			/* terminate this list with a 0 */
-			0x15c2,
-			0 };
+static struct usb_device_id vfd_proto_6p_list[] = {
+	{ USB_DEVICE(0x15c2, 0xffda) },
+	{ USB_DEVICE(0x15c2, 0xffdc) },
+	{ USB_DEVICE(0x15c2, 0x0038) },
+	{}
+};
 static unsigned char vfd_packet6[] = {
-		0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
+	0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
+
+/* iMON LCD models use control endpoints and a larger buffer */
+static struct usb_device_id lcd_device_list[] = {
+	{ USB_DEVICE(0x15c2, 0x0034) },
+	{ USB_DEVICE(0x15c2, 0x0036) },
+	{ USB_DEVICE(0x15c2, 0x0038) },
+	{}
+};
 
 /* Newer iMON models decode the signal onboard */
-static unsigned short ir_onboard_decode_product_list[] = {
-			/* terminate this list with a 0 */
-			0xffdc,
-			0 };
+static struct usb_device_id ir_onboard_decode_list[] = {
+	{ USB_DEVICE(0x15c2, 0xffdc) },
+	{ USB_DEVICE(0x15c2, 0x0034) },
+	{ USB_DEVICE(0x15c2, 0x0036) },
+	{ USB_DEVICE(0x15c2, 0x0038) },
+	{}
+};
+
+/* Some iMon devices have no lcd/vfd */
+static struct usb_device_id ir_only_list[] = {
+	{ USB_DEVICE(0x0aa8, 0x8001) },
+	/*
+	 * Nb: this device ID might actually be used by multiple devices, some
+	 * with a display, some without. iMon Knob has this ID, is w/o.
+	 */
+	{ USB_DEVICE(0x15c2, 0xffdc) },
+	{}
+};
 
 /* USB Device data */
 static struct usb_driver imon_driver = {
@@ -247,14 +285,9 @@
 static DECLARE_MUTEX(disconnect_sem);
 
 static int debug;
-#ifdef LIRC_IMON_LCD
-static int is_lcd = 1;
-#else
-static int is_lcd; /* If LIRC_IMON_LCD not defined, default to non-LCD */
-#endif
 
-/* pad2keys module parameter. pad2keys patch active? */
-static int pad2keys_active = 0;
+/* lcd, vfd or none? should be auto-detected, but can be overridden... */
+static int display_type;
 
 #if !defined(KERNEL_2_5)
 
@@ -279,24 +312,15 @@
 
 MODULE_AUTHOR(MOD_AUTHOR);
 MODULE_DESCRIPTION(MOD_DESC);
-MODULE_VERSION(MOD_VERSION);  /* MBr: was missing */
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(usb, imon_usb_id_table);
 
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)");
 
-#ifdef LIRC_IMON_LCD
-module_param(is_lcd, int, 1);
-MODULE_PARM_DESC(is_lcd, "The device is an LCD: 0=no (it's a VFD), "
-		 "1=yes (default:yes)");
-#else
-module_param(is_lcd, int, 0);
-MODULE_PARM_DESC(is_lcd, "The device is an LCD: 0=no (it's a VFD), "
-		 "1=yes (default:no)");
-#endif
-module_param (pad2keys_active, int, 0);
-MODULE_PARM_DESC (pad2keys_active, "pad2keys patch active: 0=no, 1=yes (default: no)");
+module_param(display_type, int, 0);
+MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, "
+		 "1=vfd, 2=lcd, 3=none (default: autodetect)");
 
 static inline void delete_context(struct imon_context *context)
 {
@@ -441,18 +465,45 @@
 	unsigned int pipe;
 	int interval = 0;
 	int retval = SUCCESS;
+	struct usb_ctrlrequest *control_req = NULL;
 
-	pipe = usb_sndintpipe(context->dev,
-			context->tx_endpoint->bEndpointAddress);
+	/* Check if we need to use control or interrupt urb */
+	if (!context->tx_control) {
+		pipe = usb_sndintpipe(context->dev,
+				context->tx_endpoint->bEndpointAddress);
 #ifdef KERNEL_2_5
-	interval = context->tx_endpoint->bInterval;
+		interval = context->tx_endpoint->bInterval;
 #endif	/* Use 0 for 2.4 kernels */
 
-	usb_fill_int_urb(context->tx_urb, context->dev, pipe,
-		context->usb_tx_buf, sizeof(context->usb_tx_buf),
-		usb_tx_callback, context, interval);
+		usb_fill_int_urb(context->tx_urb, context->dev, pipe,
+			context->usb_tx_buf, sizeof(context->usb_tx_buf),
+			usb_tx_callback, context, interval);
 
-	context->tx_urb->actual_length = 0;
+		context->tx_urb->actual_length = 0;
+	} else {
+		/* fill request into kmalloc'ed space: */
+		control_req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
+		if (control_req == NULL)
+			return -ENOMEM;
+
+		/* setup packet is '21 09 0200 0001 0008' */
+		control_req->bRequestType = 0x21;
+		control_req->bRequest = 0x09;
+		control_req->wValue = cpu_to_le16(0x0200);
+		control_req->wIndex = cpu_to_le16(0x0001);
+		control_req->wLength = cpu_to_le16(0x0008);
+
+		/* control pipe is endpoint 0x00 */
+		pipe = usb_sndctrlpipe(context->dev, 0);
+
+		/* build the control urb */
+		usb_fill_control_urb(context->tx_urb, context->dev, pipe,
+			(unsigned char *)control_req,
+			context->usb_tx_buf, sizeof(context->usb_tx_buf),
+			usb_tx_callback, context);
+
+		context->tx_urb->actual_length = 0;
+	}
 
 	init_completion(&context->tx.finished);
 	atomic_set(&(context->tx.busy), 1);
@@ -476,6 +527,8 @@
 			err("%s: packet tx failed(%d)", __FUNCTION__, retval);
 	}
 
+	kfree(control_req);
+
 	return retval;
 }
 
@@ -709,8 +762,10 @@
 		goto exit;
 	}
 
-	if (copy_from_user(context->usb_tx_buf, buf, 8))
-		return -EFAULT;
+	if (copy_from_user(context->usb_tx_buf, buf, 8)) {
+		retval = -EFAULT;
+		goto exit;
+	}
 
 	retval = send_packet(context);
 	if (retval != SUCCESS) {
@@ -777,11 +832,6 @@
 	context->rx.initial_space = 1;
 	context->rx.prev_bit = 0;
 
-	/* init pad context for pad2keys */
-	context ->key_x = 0;
-	context ->key_y = 0;
-	context ->last_count = 0;
- 
 	usb_fill_int_urb(context->rx_urb, context->dev,
 		usb_rcvintpipe(context->dev,
 				context->rx_endpoint->bEndpointAddress),
@@ -890,6 +940,40 @@
 	int i;
 #endif
 
+	/*
+	 * we need to add some special handling for
+	 * the imon's IR mouse events
+	 */
+	if ((len == 5) && (buf[0] == 0x01) && (buf[4] == 0x00)) {
+		/* first, pad to 8 bytes so it conforms with everything else */
+		buf[5] = buf[6] = buf[7] = 0;
+		len = 8;
+
+		/*
+		 * the imon directional pad functions more like a touchpad.
+		 * Bytes 3 & 4 contain a position coordinate (x,y), with each
+		 * component ranging from -14 to 14. Since this doesn't
+		 * cooperate well with the way lirc works (it would appear to
+		 * lirc as more than 100 different buttons) we need to map it
+		 * to 4 discrete values. Also, when you get too close to
+		 * diagonals, it has a tendancy to jump back and forth, so lets
+		 * try to ignore when they get too close
+		 */
+		if ((buf[1] == 0) && ((buf[2] != 0) || (buf[3] != 0))) {
+			int y = (int)(char)buf[2];
+			int x = (int)(char)buf[3];
+			if (abs(abs(x) - abs(y)) < 3) {
+				return;
+			} else if (abs(y) > abs(x)) {
+				buf[2] = 0x00;
+				buf[3] = (y > 0) ? 0x7f : 0x80;
+			} else {
+				buf[3] = 0x00;
+				buf[2] = (x > 0) ? 0x7f : 0x80;
+			}
+		}
+	}
+
 	if (len != 8) {
 		warn("%s: invalid incoming packet size(%d)",
 		     __FUNCTION__, len);
@@ -931,94 +1015,6 @@
 
 	if (context->ir_onboard_decode) {
 		/* The signals have been decoded onboard the iMON controller */
-                
-                if (pad2keys_active)
-                {
-                   /* imon pad2keys patch
-                    *
-                    * make PAD and mouse buttons available for use with VDR,
-                    * based on pad-mouse-emu patch from venky's forum
-                    *
-                    * last change: M.Brakemeier 2007-10-14
-                    *
-                    * generated PAD key codes:
-                    * Mouse_N                  0x690281B7
-                    * Mouse_S                  0x688291B7
-                    * Mouse_W                  0x6A8281B7
-                    * Mouse_E                  0x688A81B7
-                    *
-                    * mouse buttons (non-synthetic):
-                    * MouseRightClick          0x688481B7
-                    * MouseLeftClick           0x688301B7
-                    */
-                    if((buf[0] & 0x40) &&
-                        !(buf[1] & 0x01 || buf[1] >> 2 & 0x01))
-                    {
-                        int rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
-                        int rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
-        
-                        if(buf[0] & 0x02)
-                            rel_x |= ~0x10+1;
-                        if(buf[0] & 0x01)
-                            rel_y |= ~0x10+1;
-        
-                        /* keyboard direction key emulation */
-                        if( context->last_count > 32 )
-                        {  /* Hopefully eliminate drift*/
-                            context->last_count=0;
-                            context->key_y=0;
-                            context->key_x=0;
-                        }
-                        context->last_count++;
-        
-                        /* limit decoded events */
-                        if(abs(context->key_x) > CURSOR_LIMIT || abs(context->key_y) > CURSOR_LIMIT )
-                        {
-                            if(abs(context->key_y ) > abs(context->key_x))
-                            { /* mouse s/n */
-                                if(context->key_y > 0 && rel_y > 0)
-                                { /* mouse s */
-                                    buf[0] = 0x68;
-                                    buf[1] = 0x82;
-                                    buf[2] = 0x91;
-                                }
-                                else if(context->key_y < 0 && rel_y < 0)
-                                { /* mouse n */
-                                    buf[0] = 0x69;
-                                    buf[1] = 0x02;
-                                    buf[2] = 0x81;
-                                }
-                            }
-                            else
-                            { /* mouse e/w*/
-                                if(context->key_x > 0 && rel_x > 0 )
-                                { /* mouse e */
-                                    buf[0] = 0x68;
-                                    buf[1] = 0x8A;
-                                    buf[2] = 0x81;
-                                }
-                                else if(context->key_x < 0 && rel_x < 0  )
-                                { /* mouse w */
-                                    buf[0] = 0x6A;
-                                    buf[1] = 0x82;
-                                    buf[2] = 0x81;
-                                }
-                            }
-                        }
-                        else
-                        {
-                            context->key_x += rel_x;
-                            context->key_y += rel_y;
-        
-                            return; /* discard those key codes */
-                        }
-                    }
-                    /* a key was pressed, reset count */
-                    context->key_x = 0;
-                    context->key_y = 0;
-                    context->last_count = 0;
-                }
-                
 		lirc_buffer_write_1(context->plugin->rbuf, buf);
 		wake_up(&context->plugin->rbuf->wait_poll);
 		return;
@@ -1140,6 +1136,10 @@
 	int alloc_status;
 	int vfd_proto_6p = FALSE;
 	int ir_onboard_decode = FALSE;
+	int tx_control = FALSE;
+	int is_lcd = 0;
+	int buf_chunk_size = BUF_CHUNK_SIZE;
+	int code_length;
 	struct imon_context *context = NULL;
 	int i;
 
@@ -1147,10 +1147,18 @@
 
 	/*
 	 * If it's the LCD, as opposed to the VFD, we just need to replace
-	 * the "write" file op.
+	 * the "write" file op and use a larger buffer.
 	 */
-	if (is_lcd)
+	if ((display_type == IMON_DISPLAY_TYPE_AUTO &&
+	     usb_match_id(interface, lcd_device_list)) ||
+	    display_type == IMON_DISPLAY_TYPE_LCD) {
 		vfd_fops.write = &lcd_write;
+		is_lcd = 1;
+		/* this should be unnecessary, per Christoph */
+		//buf_chunk_size = 8;
+	}
+
+	code_length = buf_chunk_size * 8;
 
 #if !defined(KERNEL_2_5)
 	for (subminor = 0; subminor < MAX_DEVICES; ++subminor) {
@@ -1215,6 +1223,34 @@
 		}
 	}
 
+	/*
+	 * If we didn't find a vfd endpoint, and we have a next-gen LCD,
+	 * use control urb instead of interrupt
+	 */
+	if (!vfd_ep_found) {
+		if (is_lcd) {
+			tx_control = 1;
+			vfd_ep_found = TRUE;
+			if (debug)
+				info("%s: LCD device uses control endpoint, "
+				     "not interface OUT endpoint", __func__);
+		}
+	}
+
+	/*
+	 * Some iMon receivers have no display. Unfortunately, it seems
+	 * that SoundGraph recycles device IDs between devices both with
+	 * and without... :\
+	 */
+	if ((display_type == IMON_DISPLAY_TYPE_AUTO &&
+	     usb_match_id(interface, ir_only_list)) ||
+	    display_type == IMON_DISPLAY_TYPE_NONE) {
+		tx_control = 0;
+		vfd_ep_found = 0;
+		if (debug)
+			info("%s: device has no display", __func__);
+	}
+
 	/* Input endpoint is mandatory */
 	if (!ir_ep_found) {
 		err("%s: no valid input(IR) endpoint found.", __FUNCTION__);
@@ -1222,17 +1258,8 @@
 		goto exit;
 	} else {
 		/* Determine if the IR signals are decoded onboard */
-		unsigned short product_id;
-		unsigned short *id_list_item;
-
-		product_id = cpu_to_le16(dev->descriptor.idProduct);
-		id_list_item = ir_onboard_decode_product_list;
-		while (*id_list_item) {
-			if (*id_list_item++ == product_id) {
-				ir_onboard_decode = TRUE;
-				break;
-			}
-		}
+		if (usb_match_id(interface, ir_onboard_decode_list))
+			ir_onboard_decode = TRUE;
 
 		if (debug)
 			info("ir_onboard_decode: %d", ir_onboard_decode);
@@ -1240,23 +1267,13 @@
 
 	/* Determine if VFD requires 6 packets */
 	if (vfd_ep_found) {
-		unsigned short vendor_id;
-		unsigned short *id_list_item;
-
-		vendor_id = cpu_to_le16(dev->descriptor.idVendor);
-		id_list_item = vfd_proto_6p_vendor_list;
-		while (*id_list_item) {
-			if (*id_list_item++ == vendor_id) {
-				vfd_proto_6p = TRUE;
-				break;
-			}
-		}
+		if (usb_match_id(interface, vfd_proto_6p_list))
+			vfd_proto_6p = TRUE;
 
 		if (debug)
 			info("vfd_proto_6p: %d", vfd_proto_6p);
 	}
 
-
 	/* Allocate memory */
 
 	alloc_status = SUCCESS;
@@ -1279,7 +1296,7 @@
 		alloc_status = 3;
 		goto alloc_status_switch;
 	}
-	if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) {
+	if (lirc_buffer_init(rbuf, buf_chunk_size, BUF_SIZE)) {
 		err("%s: lirc_buffer_init failed", __FUNCTION__);
 		alloc_status = 4;
 		goto alloc_status_switch;
@@ -1318,8 +1335,8 @@
 
 	strcpy(plugin->name, MOD_NAME);
 	plugin->minor = -1;
-	plugin->code_length = (ir_onboard_decode) ?
-		32 : sizeof(lirc_t) * 8;
+	plugin->code_length = ir_onboard_decode ?
+			      code_length : sizeof(lirc_t) * 8;
 	plugin->sample_rate = 0;
 	plugin->features = (ir_onboard_decode) ?
 		LIRC_CAN_REC_LIRCCODE : LIRC_CAN_REC_MODE2;
@@ -1344,27 +1361,6 @@
 		info("%s: Registered iMON plugin(minor:%d)",
 		     __FUNCTION__, lirc_minor);
 
-alloc_status_switch:
-
-	switch (alloc_status) {
-	case 7:
-		if (vfd_ep_found)
-			usb_free_urb(tx_urb);
-	case 6:
-		usb_free_urb(rx_urb);
-	case 5:
-		lirc_buffer_free(rbuf);
-	case 4:
-		kfree(rbuf);
-	case 3:
-		kfree(plugin);
-	case 2:
-		kfree(context);
-		context = NULL;
-	case 1:
-		retval = -ENOMEM;
-	}
-
 	/* Needed while unregistering! */
 	plugin->minor = lirc_minor;
 
@@ -1376,6 +1372,7 @@
 		context->vfd_supported = TRUE;
 		context->tx_endpoint = tx_endpoint;
 		context->tx_urb = tx_urb;
+		context->tx_control = tx_control;
 	}
 	context->plugin = plugin;
 
@@ -1423,6 +1420,29 @@
 
 	UNLOCK_CONTEXT;
 
+alloc_status_switch:
+
+	switch (alloc_status) {
+	case 7:
+		if (vfd_ep_found)
+			usb_free_urb(tx_urb);
+	case 6:
+		usb_free_urb(rx_urb);
+	case 5:
+		lirc_buffer_free(rbuf);
+	case 4:
+		kfree(rbuf);
+	case 3:
+		kfree(plugin);
+	case 2:
+		kfree(context);
+		context = NULL;
+	case 1:
+		retval = -ENOMEM;
+	case SUCCESS:
+		;
+	}
+
  exit:
 #ifdef KERNEL_2_5
 	return retval;
