[kernel/f13/master: 1/2] lirc: restore patch from 2.6.33.x F13 kernels

Jarod Wilson jwilson at fedoraproject.org
Sun Sep 5 16:45:29 UTC 2010


commit 3ebffba4f63a0c0289ac452c50b3d3f9c32b5cbc
Author: Jarod Wilson <jarod at redhat.com>
Date:   Sun Sep 5 12:40:37 2010 -0400

    lirc: restore patch from 2.6.33.x F13 kernels
    
    Signed-off-by: Jarod Wilson <jarod at redhat.com>

 kernel.spec       |    3 +
 lirc-2.6.33.patch | 1261 +++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 891 insertions(+), 373 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index cacb346..77b0279 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -2101,6 +2101,9 @@ fi
 
 
 %changelog
+* Sun Sep 05 2010 Jarod Wilson <jarod at redhat.com> 2.6.34.6-54
+- Restore lirc patch from 2.6.33.x F13 kernels, re-fixes multiple issues
+
 * Sat Sep 04 2010 Chuck Ebbert <cebbert at redhat.com> 2.6.34.6-53
 - Disable asynchronous suspend, a new feature in 2.6.34
 
diff --git a/lirc-2.6.33.patch b/lirc-2.6.33.patch
index 70e3016..ea4f28d 100644
--- a/lirc-2.6.33.patch
+++ b/lirc-2.6.33.patch
@@ -1,133 +1,64 @@
- include/linux/lirc.h                  |   94 ++
+lirc drivers, 2010.04.05
+
+Generated against linus/master from the linux-2.6-lirc.git tree at
+http://git.kernel.org/?p=linux/kernel/git/jarod/linux-2.6-lirc.git;a=summary
+
+Also includes a pure input imon driver, which used to be part of lirc_imon...
+
+Signed-off-by: Jarod Wilson <jarod at redhat.com>
+
+---
+ MAINTAINERS                           |    9 +
  drivers/input/Kconfig                 |    2 +
  drivers/input/Makefile                |    2 +
  drivers/input/lirc/Kconfig            |  116 ++
  drivers/input/lirc/Makefile           |   21 +
- drivers/input/lirc/lirc_bt829.c       |  383 ++++++
- drivers/input/lirc/lirc_dev.c         |  736 ++++++++++
- drivers/input/lirc/lirc_dev.h         |  225 +++
+ drivers/input/lirc/lirc_bt829.c       |  383 +++++
+ drivers/input/lirc/lirc_dev.c         |  850 +++++++++++
+ drivers/input/lirc/lirc_dev.h         |  228 +++
  drivers/input/lirc/lirc_ene0100.c     |  646 +++++++++
  drivers/input/lirc/lirc_ene0100.h     |  169 +++
- drivers/input/lirc/lirc_i2c.c         |  536 ++++++++
- drivers/input/lirc/lirc_igorplugusb.c |  556 ++++++++
- drivers/input/lirc/lirc_imon.c        | 1054 ++++++++++++++
- drivers/input/lirc/lirc_it87.c        |  991 ++++++++++++++
+ drivers/input/lirc/lirc_i2c.c         |  536 +++++++
+ drivers/input/lirc/lirc_igorplugusb.c |  555 ++++++++
+ drivers/input/lirc/lirc_imon.c        | 1053 ++++++++++++++
+ drivers/input/lirc/lirc_it87.c        | 1021 +++++++++++++
  drivers/input/lirc/lirc_it87.h        |  116 ++
- drivers/input/lirc/lirc_ite8709.c     |  540 ++++++++
- drivers/input/lirc/lirc_mceusb.c      | 1222 +++++++++++++++++
- drivers/input/lirc/lirc_parallel.c    |  709 ++++++++++
+ drivers/input/lirc/lirc_ite8709.c     |  540 +++++++
+ drivers/input/lirc/lirc_mceusb.c      | 1385 ++++++++++++++++++
+ drivers/input/lirc/lirc_parallel.c    |  709 +++++++++
  drivers/input/lirc/lirc_parallel.h    |   26 +
- drivers/input/lirc/lirc_sasem.c       |  931 +++++++++++++
- drivers/input/lirc/lirc_serial.c      | 1317 ++++++++++++++++++
+ drivers/input/lirc/lirc_sasem.c       |  931 ++++++++++++
+ drivers/input/lirc/lirc_serial.c      | 1317 +++++++++++++++++
  drivers/input/lirc/lirc_sir.c         | 1283 +++++++++++++++++
- drivers/input/lirc/lirc_streamzap.c   |  794 +++++++++++
+ drivers/input/lirc/lirc_streamzap.c   |  821 +++++++++++
  drivers/input/lirc/lirc_ttusbir.c     |  397 ++++++
- drivers/input/lirc/lirc_zilog.c       | 1396 +++++++++++++++++++
+ drivers/input/lirc/lirc_zilog.c       | 1388 ++++++++++++++++++
  drivers/input/misc/Kconfig            |   12 +
  drivers/input/misc/Makefile           |    1 +
- drivers/input/misc/imon.c             | 2430 +++++++++++++++++++++++++++++++++
- 28 files changed, 16705 insertions(+), 0 deletions(-)
+ drivers/input/misc/imon.c             | 2523 +++++++++++++++++++++++++++++++++
+ include/linux/lirc.h                  |  159 +++
+ 29 files changed, 17199 insertions(+), 0 deletions(-)
 
-diff --git a/include/linux/lirc.h b/include/linux/lirc.h
-new file mode 100644
-index 0000000..8ae64fa
---- /dev/null
-+++ b/include/linux/lirc.h
-@@ -0,0 +1,94 @@
-+/*
-+ * lirc.h - linux infrared remote control header file
-+ * last modified 2007/09/27
-+ */
-+
-+#ifndef _LINUX_LIRC_H
-+#define _LINUX_LIRC_H
-+
-+#include <linux/types.h>
-+#include <linux/ioctl.h>
-+
-+#define PULSE_BIT  0x01000000
-+#define PULSE_MASK 0x00FFFFFF
-+
-+/*** lirc compatible hardware features ***/
-+
-+#define LIRC_MODE2SEND(x) (x)
-+#define LIRC_SEND2MODE(x) (x)
-+#define LIRC_MODE2REC(x) ((x) << 16)
-+#define LIRC_REC2MODE(x) ((x) >> 16)
-+
-+#define LIRC_MODE_RAW                  0x00000001
-+#define LIRC_MODE_PULSE                0x00000002
-+#define LIRC_MODE_MODE2                0x00000004
-+#define LIRC_MODE_LIRCCODE             0x00000010
-+
-+
-+#define LIRC_CAN_SEND_RAW              LIRC_MODE2SEND(LIRC_MODE_RAW)
-+#define LIRC_CAN_SEND_PULSE            LIRC_MODE2SEND(LIRC_MODE_PULSE)
-+#define LIRC_CAN_SEND_MODE2            LIRC_MODE2SEND(LIRC_MODE_MODE2)
-+#define LIRC_CAN_SEND_LIRCCODE         LIRC_MODE2SEND(LIRC_MODE_LIRCCODE)
-+
-+#define LIRC_CAN_SEND_MASK             0x0000003f
-+
-+#define LIRC_CAN_SET_SEND_CARRIER      0x00000100
-+#define LIRC_CAN_SET_SEND_DUTY_CYCLE   0x00000200
-+#define LIRC_CAN_SET_TRANSMITTER_MASK  0x00000400
-+
-+#define LIRC_CAN_REC_RAW               LIRC_MODE2REC(LIRC_MODE_RAW)
-+#define LIRC_CAN_REC_PULSE             LIRC_MODE2REC(LIRC_MODE_PULSE)
-+#define LIRC_CAN_REC_MODE2             LIRC_MODE2REC(LIRC_MODE_MODE2)
-+#define LIRC_CAN_REC_LIRCCODE          LIRC_MODE2REC(LIRC_MODE_LIRCCODE)
-+
-+#define LIRC_CAN_REC_MASK              LIRC_MODE2REC(LIRC_CAN_SEND_MASK)
-+
-+#define LIRC_CAN_SET_REC_CARRIER       (LIRC_CAN_SET_SEND_CARRIER << 16)
-+#define LIRC_CAN_SET_REC_DUTY_CYCLE    (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16)
-+
-+#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000
-+#define LIRC_CAN_SET_REC_CARRIER_RANGE    0x80000000
-+#define LIRC_CAN_GET_REC_RESOLUTION       0x20000000
-+
-+#define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK)
-+#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK)
-+
-+#define LIRC_CAN_NOTIFY_DECODE            0x01000000
-+
-+/*** IOCTL commands for lirc driver ***/
-+
-+#define LIRC_GET_FEATURES              _IOR('i', 0x00000000, unsigned long)
-+
-+#define LIRC_GET_SEND_MODE             _IOR('i', 0x00000001, unsigned long)
-+#define LIRC_GET_REC_MODE              _IOR('i', 0x00000002, unsigned long)
-+#define LIRC_GET_SEND_CARRIER          _IOR('i', 0x00000003, unsigned int)
-+#define LIRC_GET_REC_CARRIER           _IOR('i', 0x00000004, unsigned int)
-+#define LIRC_GET_SEND_DUTY_CYCLE       _IOR('i', 0x00000005, unsigned int)
-+#define LIRC_GET_REC_DUTY_CYCLE        _IOR('i', 0x00000006, unsigned int)
-+#define LIRC_GET_REC_RESOLUTION        _IOR('i', 0x00000007, unsigned int)
-+
-+/* code length in bits, currently only for LIRC_MODE_LIRCCODE */
-+#define LIRC_GET_LENGTH                _IOR('i', 0x0000000f, unsigned long)
-+
-+#define LIRC_SET_SEND_MODE             _IOW('i', 0x00000011, unsigned long)
-+#define LIRC_SET_REC_MODE              _IOW('i', 0x00000012, unsigned long)
-+/* Note: these can reset the according pulse_width */
-+#define LIRC_SET_SEND_CARRIER          _IOW('i', 0x00000013, unsigned int)
-+#define LIRC_SET_REC_CARRIER           _IOW('i', 0x00000014, unsigned int)
-+#define LIRC_SET_SEND_DUTY_CYCLE       _IOW('i', 0x00000015, unsigned int)
-+#define LIRC_SET_REC_DUTY_CYCLE        _IOW('i', 0x00000016, unsigned int)
-+#define LIRC_SET_TRANSMITTER_MASK      _IOW('i', 0x00000017, unsigned int)
-+
-+/*
-+ * to set a range use
-+ * LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the
-+ * lower bound first and later
-+ * LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER with the upper bound
-+ */
-+
-+#define LIRC_SET_REC_DUTY_CYCLE_RANGE  _IOW('i', 0x0000001e, unsigned int)
-+#define LIRC_SET_REC_CARRIER_RANGE     _IOW('i', 0x0000001f, unsigned int)
-+
-+#define LIRC_NOTIFY_DECODE             _IO('i', 0x00000020)
-+
-+#endif
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 47cc449..ae38439 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -3427,6 +3427,15 @@ F:	arch/powerpc/platforms/pasemi/
+ F:	drivers/*/*pasemi*
+ F:	drivers/*/*/*pasemi*
+ 
++LINUX INFRARED REMOTE CONTROL DRIVERS (LIRC)
++P:	Jarod Wilson
++M:	jarod at redhat.com
++P:	Christoph Bartelmus
++M:	lirc at bartelmus.de
++W:	http://www.lirc.org/
++L:	lirc-list at lists.sourceforge.net
++S:	Maintained
++
+ LINUX SECURITY MODULE (LSM) FRAMEWORK
+ M:	Chris Wright <chrisw at sous-sol.org>
+ L:	linux-security-module at vger.kernel.org
 diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
 index 07c2cd4..ebc8743 100644
 --- a/drivers/input/Kconfig
@@ -691,10 +622,10 @@ index 0000000..0485884
 +MODULE_PARM_DESC(debug, "Debug enabled or not");
 diff --git a/drivers/input/lirc/lirc_dev.c b/drivers/input/lirc/lirc_dev.c
 new file mode 100644
-index 0000000..504e122
+index 0000000..cd5d75a
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_dev.c
-@@ -0,0 +1,736 @@
+@@ -0,0 +1,850 @@
 +/*
 + * LIRC base driver
 + *
@@ -733,6 +664,9 @@ index 0000000..504e122
 +#include <linux/device.h>
 +#include <linux/cdev.h>
 +#include <linux/smp_lock.h>
++#ifdef CONFIG_COMPAT
++#include <linux/compat.h>
++#endif
 +
 +#include <linux/lirc.h>
 +#include "lirc_dev.h"
@@ -859,6 +793,9 @@ index 0000000..504e122
 +	.write		= lirc_dev_fop_write,
 +	.poll		= lirc_dev_fop_poll,
 +	.ioctl		= lirc_dev_fop_ioctl,
++#ifdef CONFIG_COMPAT
++	.compat_ioctl	= lirc_dev_fop_compat_ioctl,
++#endif
 +	.open		= lirc_dev_fop_open,
 +	.release	= lirc_dev_fop_close,
 +};
@@ -1257,6 +1194,20 @@ index 0000000..504e122
 +	case LIRC_GET_LENGTH:
 +		result = put_user(ir->d.code_length, (unsigned long *)arg);
 +		break;
++	case LIRC_GET_MIN_TIMEOUT:
++		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
++		    ir->d.min_timeout == 0)
++			return -ENOSYS;
++
++		result = put_user(ir->d.min_timeout, (int *) arg);
++		break;
++	case LIRC_GET_MAX_TIMEOUT:
++		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
++		    ir->d.max_timeout == 0)
++			return -ENOSYS;
++
++		result = put_user(ir->d.max_timeout, (int *) arg);
++		break;
 +	default:
 +		result = -EINVAL;
 +	}
@@ -1268,6 +1219,100 @@ index 0000000..504e122
 +}
 +EXPORT_SYMBOL(lirc_dev_fop_ioctl);
 +
++#ifdef CONFIG_COMPAT
++#define LIRC_GET_FEATURES_COMPAT32     _IOR('i', 0x00000000, __u32)
++
++#define LIRC_GET_SEND_MODE_COMPAT32    _IOR('i', 0x00000001, __u32)
++#define LIRC_GET_REC_MODE_COMPAT32     _IOR('i', 0x00000002, __u32)
++
++#define LIRC_GET_LENGTH_COMPAT32       _IOR('i', 0x0000000f, __u32)
++
++#define LIRC_SET_SEND_MODE_COMPAT32    _IOW('i', 0x00000011, __u32)
++#define LIRC_SET_REC_MODE_COMPAT32     _IOW('i', 0x00000012, __u32)
++
++long lirc_dev_fop_compat_ioctl(struct file *file,
++			       unsigned int cmd32,
++			       unsigned long arg)
++{
++	mm_segment_t old_fs;
++	int ret;
++	unsigned long val;
++	unsigned int cmd;
++
++	switch (cmd32) {
++	case LIRC_GET_FEATURES_COMPAT32:
++	case LIRC_GET_SEND_MODE_COMPAT32:
++	case LIRC_GET_REC_MODE_COMPAT32:
++	case LIRC_GET_LENGTH_COMPAT32:
++	case LIRC_SET_SEND_MODE_COMPAT32:
++	case LIRC_SET_REC_MODE_COMPAT32:
++		/*
++		 * These commands expect (unsigned long *) arg
++		 * but the 32-bit app supplied (__u32 *).
++		 * Conversion is required.
++		 */
++		if (get_user(val, (__u32 *)compat_ptr(arg)))
++			return -EFAULT;
++		lock_kernel();
++		/*
++		 * tell lirc_dev_fop_ioctl that it's safe to use the pointer
++		 * to val which is in kernel address space and not in
++		 * user address space.
++		 */
++		old_fs = get_fs();
++		set_fs(KERNEL_DS);
++
++		cmd = _IOC(_IOC_DIR(cmd32), _IOC_TYPE(cmd32), _IOC_NR(cmd32),
++		(_IOC_TYPECHECK(unsigned long)));
++		ret = lirc_dev_fop_ioctl(file->f_path.dentry->d_inode, file,
++					 cmd, (unsigned long)(&val));
++
++		set_fs(old_fs);
++		unlock_kernel();
++	switch (cmd) {
++	case LIRC_GET_FEATURES:
++	case LIRC_GET_SEND_MODE:
++	case LIRC_GET_REC_MODE:
++	case LIRC_GET_LENGTH:
++		if (!ret && put_user(val, (__u32 *)compat_ptr(arg)))
++			return -EFAULT;
++		break;
++	}
++	return ret;
++
++	case LIRC_GET_SEND_CARRIER:
++	case LIRC_GET_REC_CARRIER:
++	case LIRC_GET_SEND_DUTY_CYCLE:
++	case LIRC_GET_REC_DUTY_CYCLE:
++	case LIRC_GET_REC_RESOLUTION:
++	case LIRC_SET_SEND_CARRIER:
++	case LIRC_SET_REC_CARRIER:
++	case LIRC_SET_SEND_DUTY_CYCLE:
++	case LIRC_SET_REC_DUTY_CYCLE:
++	case LIRC_SET_TRANSMITTER_MASK:
++	case LIRC_SET_REC_DUTY_CYCLE_RANGE:
++	case LIRC_SET_REC_CARRIER_RANGE:
++		/*
++		 * These commands expect (unsigned int *)arg
++		 * so no problems here. Just handle the locking.
++		 */
++		lock_kernel();
++		cmd = cmd32;
++		ret = lirc_dev_fop_ioctl(file->f_path.dentry->d_inode,
++					 file, cmd, arg);
++		unlock_kernel();
++		return ret;
++	default:
++		/* unknown */
++		printk(KERN_ERR "lirc_dev: %s(%s:%d): Unknown cmd %08x\n",
++		       __func__, current->comm, current->pid, cmd32);
++		return -ENOIOCTLCMD;
++	}
++}
++EXPORT_SYMBOL(lirc_dev_fop_compat_ioctl);
++#endif
++
++
 +ssize_t lirc_dev_fop_read(struct file *file,
 +			  char *buffer,
 +			  size_t length,
@@ -1433,10 +1478,10 @@ index 0000000..504e122
 +MODULE_PARM_DESC(debug, "Enable debugging messages");
 diff --git a/drivers/input/lirc/lirc_dev.h b/drivers/input/lirc/lirc_dev.h
 new file mode 100644
-index 0000000..99d0442
+index 0000000..56020e8
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_dev.h
-@@ -0,0 +1,225 @@
+@@ -0,0 +1,228 @@
 +/*
 + * LIRC base driver
 + *
@@ -1458,6 +1503,7 @@ index 0000000..99d0442
 +#include <linux/ioctl.h>
 +#include <linux/poll.h>
 +#include <linux/kfifo.h>
++#include <linux/lirc.h>
 +
 +struct lirc_buffer {
 +	wait_queue_head_t wait_poll;
@@ -1571,6 +1617,8 @@ index 0000000..99d0442
 +	unsigned int chunk_size;
 +
 +	void *data;
++	int min_timeout;
++	int max_timeout;
 +	int (*add_to_buf) (void *data, struct lirc_buffer *buf);
 +	struct lirc_buffer *rbuf;
 +	int (*set_use_inc) (void *data);
@@ -3033,10 +3081,10 @@ index 0000000..f3f8c2e
 +module_exit(lirc_i2c_exit);
 diff --git a/drivers/input/lirc/lirc_igorplugusb.c b/drivers/input/lirc/lirc_igorplugusb.c
 new file mode 100644
-index 0000000..599037d
+index 0000000..d1c02c2
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_igorplugusb.c
-@@ -0,0 +1,556 @@
+@@ -0,0 +1,555 @@
 +/*
 + * lirc_igorplugusb - USB remote support for LIRC
 + *
@@ -3086,7 +3134,6 @@ index 0000000..599037d
 +#include <linux/errno.h>
 +#include <linux/fs.h>
 +#include <linux/usb.h>
-+#include <linux/smp_lock.h>
 +#include <linux/time.h>
 +
 +#include <linux/lirc.h>
@@ -3595,10 +3642,10 @@ index 0000000..599037d
 +
 diff --git a/drivers/input/lirc/lirc_imon.c b/drivers/input/lirc/lirc_imon.c
 new file mode 100644
-index 0000000..5bea43b
+index 0000000..af5eec8
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_imon.c
-@@ -0,0 +1,1055 @@
+@@ -0,0 +1,1053 @@
 +/*
 + *   lirc_imon.c:  LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD
 + *		   including the iMON PAD model
@@ -3790,6 +3837,7 @@ index 0000000..5bea43b
 +
 +static void free_imon_context(struct imon_context *context)
 +{
++	struct device *dev = context->driver->dev;
 +	usb_free_urb(context->tx_urb);
 +	usb_free_urb(context->rx_urb);
 +	lirc_buffer_free(context->driver->rbuf);
@@ -3797,7 +3845,7 @@ index 0000000..5bea43b
 +	kfree(context->driver);
 +	kfree(context);
 +
-+	dev_dbg(context->driver->dev, "%s: iMON context freed\n", __func__);
++	dev_dbg(dev, "%s: iMON context freed\n", __func__);
 +}
 +
 +static void deregister_from_lirc(struct imon_context *context)
@@ -4315,7 +4363,6 @@ index 0000000..5bea43b
 +	struct urb *tx_urb = NULL;
 +	struct lirc_driver *driver = NULL;
 +	struct lirc_buffer *rbuf = NULL;
-+	struct usb_interface *first_if;
 +	struct device *dev = &interface->dev;
 +	int ifnum;
 +	int lirc_minor = 0;
@@ -4327,7 +4374,6 @@ index 0000000..5bea43b
 +	int vfd_proto_6p = 0;
 +	int code_length;
 +	struct imon_context *context = NULL;
-+	struct imon_context *first_if_context = NULL;
 +	int i;
 +	u16 vendor, product;
 +
@@ -4362,9 +4408,6 @@ index 0000000..5bea43b
 +	/* prevent races probing devices w/multiple interfaces */
 +	mutex_lock(&driver_lock);
 +
-+	first_if = usb_ifnum_to_if(usbdev, 0);
-+	first_if_context = (struct imon_context *)usb_get_intfdata(first_if);
-+
 +	/*
 +	 * Scan the endpoint list and set:
 +	 *	first input endpoint = IR endpoint
@@ -4408,7 +4451,8 @@ index 0000000..5bea43b
 +	if (!ir_ep_found) {
 +		err("%s: no valid input (IR) endpoint found.", __func__);
 +		retval = -ENODEV;
-+		goto exit;
++		alloc_status = 2;
++		goto alloc_status_switch;
 +	}
 +
 +	/* Determine if display requires 6 packets */
@@ -4550,7 +4594,8 @@ index 0000000..5bea43b
 +		kfree(context);
 +		context = NULL;
 +	case 1:
-+		retval = -ENOMEM;
++		if (retval != -ENODEV)
++			retval = -ENOMEM;
 +		break;
 +	case 0:
 +		retval = 0;
@@ -4656,10 +4701,10 @@ index 0000000..5bea43b
 +module_exit(imon_exit);
 diff --git a/drivers/input/lirc/lirc_it87.c b/drivers/input/lirc/lirc_it87.c
 new file mode 100644
-index 0000000..c69662d
+index 0000000..a899d00
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_it87.c
-@@ -0,0 +1,991 @@
+@@ -0,0 +1,1021 @@
 +/*
 + * LIRC driver for ITE IT8712/IT8705 CIR port
 + *
@@ -4703,7 +4748,6 @@ index 0000000..c69662d
 +#include <linux/interrupt.h>
 +#include <linux/ioport.h>
 +#include <linux/kernel.h>
-+#include <linux/serial_reg.h>
 +#include <linux/time.h>
 +#include <linux/string.h>
 +#include <linux/types.h>
@@ -4717,6 +4761,7 @@ index 0000000..c69662d
 +#include <linux/fcntl.h>
 +
 +#include <linux/timer.h>
++#include <linux/pnp.h>
 +
 +#include <linux/lirc.h>
 +#include "lirc_dev.h"
@@ -4777,6 +4822,8 @@ index 0000000..c69662d
 +unsigned int rx_tail, rx_head;
 +static int tx_buf[WBUF_LEN];
 +
++static struct pnp_driver it87_pnp_driver;
++
 +/* SECTION: Prototypes */
 +
 +/* Communication with user-space */
@@ -5584,20 +5631,32 @@ index 0000000..c69662d
 +	return 0;
 +}
 +
-+
-+static int __init lirc_it87_init(void)
++static int it87_probe(struct pnp_dev *pnp_dev,
++		      const struct pnp_device_id *dev_id)
 +{
 +	int retval;
 +
++	driver.dev = &pnp_dev->dev;
++
 +	retval = init_chrdev();
 +	if (retval < 0)
 +		return retval;
++
 +	retval = init_lirc_it87();
-+	if (retval) {
-+		drop_chrdev();
-+		return retval;
-+	}
++	if (retval)
++		goto init_lirc_it87_failed;
++
 +	return 0;
++
++init_lirc_it87_failed:
++	drop_chrdev();
++
++	return retval;
++}
++
++static int __init lirc_it87_init(void)
++{
++	return pnp_register_driver(&it87_pnp_driver);
 +}
 +
 +
@@ -5606,9 +5665,25 @@ index 0000000..c69662d
 +	drop_hardware();
 +	drop_chrdev();
 +	drop_port();
++	pnp_unregister_driver(&it87_pnp_driver);
 +	printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");
 +}
 +
++/* SECTION: PNP for ITE8704/18 */
++
++static const struct pnp_device_id pnp_dev_table[] = {
++	{"ITE8704", 0},
++	{}
++};
++
++MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
++
++static struct pnp_driver it87_pnp_driver = {
++	.name           = LIRC_DRIVER_NAME,
++	.id_table       = pnp_dev_table,
++	.probe		= it87_probe,
++};
++
 +module_init(lirc_it87_init);
 +module_exit(lirc_it87_exit);
 +
@@ -5775,7 +5850,7 @@ index 0000000..cf021c8
 +/********************************* ITE IT87xx ************************/
 diff --git a/drivers/input/lirc/lirc_ite8709.c b/drivers/input/lirc/lirc_ite8709.c
 new file mode 100644
-index 0000000..6210847
+index 0000000..4c3d3ad
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_ite8709.c
 @@ -0,0 +1,540 @@
@@ -6188,8 +6263,8 @@ index 0000000..6210847
 +	ite8709_dev->use_count = 0;
 +	ite8709_dev->irq = pnp_irq(dev, 0);
 +	ite8709_dev->io = pnp_port_start(dev, 2);
-+	ite8709_dev->hardware_lock = __SPIN_LOCK_UNLOCKED(
-+					ite8709_dev->hardware_lock);
++	ite8709_dev->hardware_lock =
++		__SPIN_LOCK_UNLOCKED(ite8709_dev->hardware_lock);
 +	ite8709_dev->acc_pulse = 0;
 +	ite8709_dev->acc_space = 0;
 +	ite8709_dev->lastbit = 0;
@@ -6321,10 +6396,10 @@ index 0000000..6210847
 +MODULE_PARM_DESC(debug, "Enable debugging messages");
 diff --git a/drivers/input/lirc/lirc_mceusb.c b/drivers/input/lirc/lirc_mceusb.c
 new file mode 100644
-index 0000000..8b404e2
+index 0000000..c0869d8
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_mceusb.c
-@@ -0,0 +1,1222 @@
+@@ -0,0 +1,1385 @@
 +/*
 + * LIRC driver for Windows Media Center Edition USB Infrared Transceivers
 + *
@@ -6489,6 +6564,8 @@ index 0000000..8b404e2
 +	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
 +	/* Topseed eHome Infrared Transceiver */
 +	{ USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
++	/* Topseed eHome Infrared Transceiver */
++	{ USB_DEVICE(VENDOR_TOPSEED, 0x0011) },
 +	/* Ricavision internal Infrared Transceiver */
 +	{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
 +	/* Itron ione Libra Q-11 */
@@ -6533,6 +6610,12 @@ index 0000000..8b404e2
 +	{ }
 +};
 +
++static struct usb_device_id gen3_list[] = {
++	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
++	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
++	{}
++};
++
 +static struct usb_device_id pinnacle_list[] = {
 +	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
 +	{}
@@ -6554,6 +6637,7 @@ index 0000000..8b404e2
 +	{ USB_DEVICE(VENDOR_TOPSEED, 0x0007) },
 +	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
 +	{ USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
++	{ USB_DEVICE(VENDOR_TOPSEED, 0x0011) },
 +	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
 +	{}
 +};
@@ -6581,7 +6665,7 @@ index 0000000..8b404e2
 +	unsigned char is_pulse;
 +	struct {
 +		u32 connected:1;
-+		u32 pinnacle:1;
++		u32 gen3:1;
 +		u32 transmitter_mask_inverted:1;
 +		u32 microsoft_gen1:1;
 +		u32 reserved:28;
@@ -6597,18 +6681,49 @@ index 0000000..8b404e2
 +	struct mutex dev_lock;
 +};
 +
-+/* init strings */
-+static char init1[] = {0x00, 0xff, 0xaa, 0xff, 0x0b};
-+static char init2[] = {0xff, 0x18};
-+
-+static char pin_init1[] = { 0x9f, 0x07};
-+static char pin_init2[] = { 0x9f, 0x13};
-+static char pin_init3[] = { 0x9f, 0x0d};
-+
-+static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, int len)
++/*
++ * MCE Device Command Strings
++ * Device command responses vary from device to device...
++ * - DEVICE_RESET resets the hardware to its default state
++ * - GET_REVISION fetches the hardware/software revision, common
++ *   replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42
++ * - GET_CARRIER_FREQ gets the carrier mode and frequency of the
++ *   device, with replies in the form of 9f 06 MM FF, where MM is 0-3,
++ *   meaning clk of 10000000, 2500000, 625000 or 156250, and FF is
++ *   ((clk / frequency) - 1)
++ * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us,
++ *   response in the form of 9f 0c msb lsb
++ * - GET_TX_BITMASK fetches the transmitter bitmask, replies in
++ *   the form of 9f 08 bm, where bm is the bitmask
++ * - GET_RX_SENSOR fetches the RX sensor setting -- long-range
++ *   general use one or short-range learning one, in the form of
++ *   9f 14 ss, where ss is either 01 for long-range or 02 for short
++ * - SET_CARRIER_FREQ sets a new carrier mode and frequency
++ * - SET_TX_BITMASK sets the transmitter bitmask
++ * - SET_RX_TIMEOUT sets the receiver timeout
++ * - SET_RX_SENSOR sets which receiver sensor to use
++ */
++static char DEVICE_RESET[]	= {0x00, 0xff, 0xaa};
++static char GET_REVISION[]	= {0xff, 0x0b};
++static char GET_UNKNOWN[]	= {0xff, 0x18};
++static char GET_CARRIER_FREQ[]	= {0x9f, 0x07};
++static char GET_RX_TIMEOUT[]	= {0x9f, 0x0d};
++static char GET_TX_BITMASK[]	= {0x9f, 0x13};
++static char GET_RX_SENSOR[]	= {0x9f, 0x15};
++/* sub in desired values in lower byte or bytes for full command */
++//static char SET_CARRIER_FREQ[]	= {0x9f, 0x06, 0x00, 0x00};
++//static char SET_TX_BITMASK[]	= {0x9f, 0x08, 0x00};
++//static char SET_RX_TIMEOUT[]	= {0x9f, 0x0c, 0x00, 0x00};
++//static char SET_RX_SENSOR[]	= {0x9f, 0x14, 0x00};
++
++static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
++				 int len, bool out)
 +{
 +	char codes[USB_BUFLEN * 3 + 1];
++	char inout[9];
 +	int i;
++	u8 cmd, subcmd, data1, data2;
++	struct device *dev = ir->d->dev;
 +
 +	if (len <= 0)
 +		return;
@@ -6619,7 +6734,108 @@ index 0000000..8b404e2
 +	for (i = 0; i < len && i < USB_BUFLEN; i++)
 +		snprintf(codes + i * 3, 4, "%02x ", buf[i] & 0xFF);
 +
-+	dev_info(ir->d->dev, "data received %s (length=%d)\n", codes, len);
++	dev_info(dev, "%sbound data: %s (length=%d)\n",
++		 (out ? "out" : " in"), codes, len);
++
++	if (out)
++		strcpy(inout, "Request\0");
++	else
++		strcpy(inout, "Got\0");
++
++	cmd    = buf[0] & 0xff;
++	subcmd = buf[1] & 0xff;
++	data1  = buf[2] & 0xff;
++	data2  = buf[3] & 0xff;
++
++	switch (cmd) {
++	case 0x00:
++		if (subcmd == 0xff && data1 == 0xaa)
++			dev_info(dev, "Device reset requested\n");
++		else
++			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
++				 cmd, subcmd);
++		break;
++	case 0xff:
++		switch (subcmd) {
++		case 0x0b:
++			if (len == 2)
++				dev_info(dev, "Get hw/sw rev?\n");
++			else
++				dev_info(dev, "hw/sw rev 0x%02x 0x%02x "
++					 "0x%02x 0x%02x\n", data1, data2,
++					 buf[4], buf[5]);
++			break;
++		case 0xaa:
++			dev_info(dev, "Device reset requested\n");
++			break;
++		case 0xfe:
++			dev_info(dev, "Previous command not supported\n");
++			break;
++		case 0x18:
++		case 0x1b:
++		default:
++			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
++				 cmd, subcmd);
++			break;
++		}
++		break;
++	case 0x9f:
++		switch (subcmd) {
++		case 0x03:
++			dev_info(dev, "Ping\n");
++			break;
++		case 0x04:
++			dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n",
++				 data1, data2);
++			break;
++		case 0x06:
++			dev_info(dev, "%s carrier mode and freq of 0x%02x 0x%02x\n",
++				 inout, data1, data2);
++			break;
++		case 0x07:
++			dev_info(dev, "Get carrier mode and freq\n");
++			break;
++		case 0x08:
++			dev_info(dev, "%s transmit blaster mask of 0x%02x\n",
++				 inout, data1);
++			break;
++		case 0x0c:
++			/* value is in units of 50us, so x*50/100 or x/2 ms */
++			dev_info(dev, "%s receive timeout of %d ms\n",
++				 inout, ((data1 << 8) | data2) / 2);
++			break;
++		case 0x0d:
++			dev_info(dev, "Get receive timeout\n");
++			break;
++		case 0x13:
++			dev_info(dev, "Get transmit blaster mask\n");
++			break;
++		case 0x14:
++			dev_info(dev, "%s %s-range receive sensor in use\n",
++				 inout, data1 == 0x02 ? "short" : "long");
++			break;
++		case 0x15:
++			if (len == 2)
++				dev_info(dev, "Get receive sensor\n");
++			else
++				dev_info(dev, "Received pulse count is %d\n",
++					 ((data1 << 8) | data2));
++			break;
++		case 0xfe:
++			dev_info(dev, "Error! Hardware is likely wedged...\n");
++			break;
++		case 0x05:
++		case 0x09:
++		case 0x0f:
++		default:
++			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
++				 cmd, subcmd);
++			break;
++		}
++		break;
++	default:
++		break;
++	}
 +}
 +
 +static void usb_async_callback(struct urb *urb, struct pt_regs *regs)
@@ -6638,54 +6854,49 @@ index 0000000..8b404e2
 +			urb->status, len);
 +
 +		if (debug)
-+			mceusb_dev_printdata(ir, urb->transfer_buffer, len);
++			mceusb_dev_printdata(ir, urb->transfer_buffer, len, true);
 +	}
 +
 +}
 +
 +/* request incoming or send outgoing usb packet - used to initialize remote */
-+static void request_packet_async(struct mceusb_dev *ir,
-+				 struct usb_endpoint_descriptor *ep,
-+				 unsigned char *data, int size, int urb_type)
++static void mce_request_packet(struct mceusb_dev *ir,
++			       struct usb_endpoint_descriptor *ep,
++			       unsigned char *data, int size, int urb_type)
 +{
 +	int res;
 +	struct urb *async_urb;
 +	unsigned char *async_buf;
 +
-+	if (urb_type) {
++	if (urb_type == MCEUSB_OUTBOUND) {
 +		async_urb = usb_alloc_urb(0, GFP_KERNEL);
-+		if (unlikely(!async_urb))
++		if (unlikely(!async_urb)) {
++			dev_err(ir->d->dev, "Error, couldn't allocate urb!\n");
 +			return;
++		}
 +
 +		async_buf = kzalloc(size, GFP_KERNEL);
 +		if (!async_buf) {
++			dev_err(ir->d->dev, "Error, couldn't allocate buf!\n");
 +			usb_free_urb(async_urb);
 +			return;
 +		}
 +
-+		if (urb_type == MCEUSB_OUTBOUND) {
-+			/* outbound data */
-+			usb_fill_int_urb(async_urb, ir->usbdev,
-+				usb_sndintpipe(ir->usbdev,
-+					       ep->bEndpointAddress),
-+				async_buf, size,
-+				(usb_complete_t) usb_async_callback,
-+				ir, ep->bInterval);
-+			memcpy(async_buf, data, size);
-+		} else {
-+			/* inbound data */
-+			usb_fill_int_urb(async_urb, ir->usbdev,
-+				usb_rcvintpipe(ir->usbdev,
-+					       ep->bEndpointAddress),
-+				async_buf, size,
-+				(usb_complete_t) usb_async_callback,
-+				ir, ep->bInterval);
-+		}
++		/* outbound data */
++		usb_fill_int_urb(async_urb, ir->usbdev,
++			usb_sndintpipe(ir->usbdev, ep->bEndpointAddress),
++			async_buf, size, (usb_complete_t) usb_async_callback,
++			ir, ep->bInterval);
++		memcpy(async_buf, data, size);
 +
-+	} else {
++	} else if (urb_type == MCEUSB_INBOUND) {
 +		/* standard request */
 +		async_urb = ir->urb_in;
 +		ir->send_flags = RECV_FLAG_IN_PROGRESS;
++
++	} else {
++		dev_err(ir->d->dev, "Error! Unknown urb type %d\n", urb_type);
++		return;
 +	}
 +
 +	dev_dbg(ir->d->dev, "receive request called (size=%#x)\n", size);
@@ -6701,6 +6912,16 @@ index 0000000..8b404e2
 +	dev_dbg(ir->d->dev, "receive request complete (res=%d)\n", res);
 +}
 +
++static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
++{
++	mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_OUTBOUND);
++}
++
++static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size)
++{
++	mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_INBOUND);
++}
++
 +static int unregister_from_lirc(struct mceusb_dev *ir)
 +{
 +	struct lirc_driver *d = ir->d;
@@ -6895,7 +7116,7 @@ index 0000000..8b404e2
 +	buf_len = urb->actual_length;
 +
 +	if (debug)
-+		mceusb_dev_printdata(ir, urb->transfer_buffer, buf_len);
++		mceusb_dev_printdata(ir, urb->transfer_buffer, buf_len, false);
 +
 +	if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
 +		ir->send_flags = SEND_FLAG_COMPLETE;
@@ -6993,8 +7214,7 @@ index 0000000..8b404e2
 +	cmdbuf[cmdcount++] = 0x80;
 +
 +	/* Transmit the command to the mce device */
-+	request_packet_async(ir, ir->usb_ep_out, cmdbuf,
-+			     cmdcount, MCEUSB_OUTBOUND);
++	mce_async_out(ir, cmdbuf, cmdcount);
 +
 +	/*
 +	 * The lircd gap calculation expects the write function to
@@ -7035,9 +7255,7 @@ index 0000000..8b404e2
 +			ir->carrier_freq = carrier;
 +			dev_dbg(ir->d->dev, "SET_CARRIER disabling carrier "
 +				"modulation\n");
-+			request_packet_async(ir, ir->usb_ep_out,
-+					     cmdbuf, sizeof(cmdbuf),
-+					     MCEUSB_OUTBOUND);
++			mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
 +			return carrier;
 +		}
 +
@@ -7051,9 +7269,7 @@ index 0000000..8b404e2
 +					"%d Hz\n", carrier);
 +
 +				/* Transmit new carrier to mce device */
-+				request_packet_async(ir, ir->usb_ep_out,
-+						     cmdbuf, sizeof(cmdbuf),
-+						     MCEUSB_OUTBOUND);
++				mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
 +				return carrier;
 +			}
 +		}
@@ -7230,8 +7446,9 @@ index 0000000..8b404e2
 +	int i;
 +	char buf[63], name[128] = "";
 +	int mem_failure = 0;
-+	int is_pinnacle;
-+	int is_microsoft_gen1;
++	bool is_gen3;
++	bool is_microsoft_gen1;
++	bool is_pinnacle;
 +
 +	dev_dbg(&intf->dev, ": %s called\n", __func__);
 +
@@ -7241,10 +7458,12 @@ index 0000000..8b404e2
 +
 +	idesc = intf->cur_altsetting;
 +
-+	is_pinnacle = usb_match_id(intf, pinnacle_list) ? 1 : 0;
++	is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0;
 +
 +	is_microsoft_gen1 = usb_match_id(intf, microsoft_gen1_list) ? 1 : 0;
 +
++	is_pinnacle = usb_match_id(intf, pinnacle_list) ? 1 : 0;
++
 +	/* step through the endpoints to find first bulk in and out endpoint */
 +	for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
 +		ep = &idesc->endpoint[i].desc;
@@ -7261,13 +7480,14 @@ index 0000000..8b404e2
 +				"found\n");
 +			ep_in = ep;
 +			ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
-+			if (is_pinnacle)
++			if (!is_pinnacle)
 +				/*
-+				 * setting seems to 1 seem to cause issues with
-+				 * Pinnacle timing out on transfer.
++				 * Ideally, we'd use what the device offers up,
++				 * but that leads to non-functioning first and
++				 * second-gen devices, and many devices have an
++				 * invalid bInterval of 0. Pinnacle devices
++				 * don't work witha  bInterval of 1 though.
 +				 */
-+				ep_in->bInterval = ep->bInterval;
-+			else
 +				ep_in->bInterval = 1;
 +		}
 +
@@ -7283,13 +7503,14 @@ index 0000000..8b404e2
 +				"found\n");
 +			ep_out = ep;
 +			ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
-+			if (is_pinnacle)
++			if (!is_pinnacle)
 +				/*
-+				 * setting seems to 1 seem to cause issues with
-+				 * Pinnacle timing out on transfer.
++				 * Ideally, we'd use what the device offers up,
++				 * but that leads to non-functioning first and
++				 * second-gen devices, and many devices have an
++				 * invalid bInterval of 0. Pinnacle devices
++				 * don't work witha  bInterval of 1 though.
 +				 */
-+				ep_out->bInterval = ep->bInterval;
-+			else
 +				ep_out->bInterval = 1;
 +		}
 +	}
@@ -7355,7 +7576,7 @@ index 0000000..8b404e2
 +	ir->len_in = maxp;
 +	ir->overflow_len = 0;
 +	ir->flags.connected = 0;
-+	ir->flags.pinnacle = is_pinnacle;
++	ir->flags.gen3 = is_gen3;
 +	ir->flags.microsoft_gen1 = is_microsoft_gen1;
 +	ir->flags.transmitter_mask_inverted =
 +		usb_match_id(intf, transmitter_mask_list) ? 0 : 1;
@@ -7385,8 +7606,7 @@ index 0000000..8b404e2
 +	ir->urb_in->transfer_dma = ir->dma_in;
 +	ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 +
-+	/* initialize device */
-+	if (ir->flags.pinnacle) {
++	if (is_pinnacle) {
 +		int usbret;
 +
 +		/*
@@ -7397,46 +7617,64 @@ index 0000000..8b404e2
 +		 * interpreted by the device and the host never does the
 +		 * completion routine
 +		 */
-+
 +		usbret = usb_reset_configuration(dev);
 +		dev_info(ir->d->dev, "usb reset config ret %x\n", usbret);
++	}
++
++	/* initialize device */
++	if (ir->flags.gen3) {
++		mce_sync_in(ir, NULL, maxp);
++
++		/* device reset */
++		mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
++		mce_sync_in(ir, NULL, maxp);
++
++		/* get the carrier and frequency */
++		mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
++		mce_sync_in(ir, NULL, maxp);
++
++		/* get the transmitter bitmask */
++		mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
++		mce_sync_in(ir, NULL, maxp);
++
++		/* get receiver timeout value */
++		mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
++		mce_sync_in(ir, NULL, maxp);
++
++		/* get receiver sensor setting */
++		mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR));
++		mce_sync_in(ir, NULL, maxp);
 +
-+		/*
-+		 * its possible we really should wait for a return
-+		 * for each of these...
-+		 */
-+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
-+		request_packet_async(ir, ep_out, pin_init1, sizeof(pin_init1),
-+				     MCEUSB_OUTBOUND);
-+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
-+		request_packet_async(ir, ep_out, pin_init2, sizeof(pin_init2),
-+				     MCEUSB_OUTBOUND);
-+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
-+		request_packet_async(ir, ep_out, pin_init3, sizeof(pin_init3),
-+				     MCEUSB_OUTBOUND);
 +	} else if (ir->flags.microsoft_gen1) {
 +		/* original ms mce device requires some additional setup */
 +		mceusb_gen1_init(ir);
++
 +	} else {
++		mce_sync_in(ir, NULL, maxp);
++		mce_sync_in(ir, NULL, maxp);
++
++		/* device reset */
++		mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
++		mce_sync_in(ir, NULL, maxp);
 +
-+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
-+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
-+		request_packet_async(ir, ep_out, init1,
-+				     sizeof(init1), MCEUSB_OUTBOUND);
-+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
-+		request_packet_async(ir, ep_out, init2,
-+				     sizeof(init2), MCEUSB_OUTBOUND);
++		/* get hw/sw revision? */
++		mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
++		mce_sync_in(ir, NULL, maxp);
++
++		/* unknown what this actually returns... */
++		mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN));
++		mce_sync_in(ir, NULL, maxp);
 +	}
 +
 +	/*
-+	 * if we don't issue the correct number of receives (MCEUSB_INBOUND)
++	 * if we don't issue the correct number of receives (mce_sync_in())
 +	 * for each outbound, then the first few ir pulses will be interpreted
 +	 * by the usb_async_callback routine - we should ensure we have the
 +	 * right amount OR less - as the mceusb_dev_recv routine will handle
 +	 * the control packets OK - they start with 0x9f - but the async
 +	 * callback doesn't handle ir pulse packets
 +	 */
-+	request_packet_async(ir, ep_in, NULL, maxp, 0);
++	mce_sync_in(ir, NULL, maxp);
 +
 +	usb_set_intfdata(intf, ir);
 +
@@ -11845,10 +12083,10 @@ index 0000000..4a471d6
 +MODULE_PARM_DESC(debug, "Enable debugging messages");
 diff --git a/drivers/input/lirc/lirc_streamzap.c b/drivers/input/lirc/lirc_streamzap.c
 new file mode 100644
-index 0000000..f4374e8
+index 0000000..87db864
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_streamzap.c
-@@ -0,0 +1,794 @@
+@@ -0,0 +1,821 @@
 +/*
 + * Streamzap Remote Control driver
 + *
@@ -11921,6 +12159,7 @@ index 0000000..f4374e8
 +
 +#define STREAMZAP_PULSE_MASK 0xf0
 +#define STREAMZAP_SPACE_MASK 0x0f
++#define STREAMZAP_TIMEOUT    0xff
 +#define STREAMZAP_RESOLUTION 256
 +
 +/* number of samples buffered */
@@ -11991,6 +12230,7 @@ index 0000000..f4374e8
 +	struct timer_list	flush_timer;
 +	int			flush;
 +	int			in_use;
++	int			timeout_enabled;
 +};
 +
 +
@@ -12139,12 +12379,14 @@ index 0000000..f4374e8
 +
 +		deltv = sz->signal_start.tv_sec-sz->signal_last.tv_sec;
 +		if (deltv > 15) {
-+			tmp = PULSE_MASK; /* really long time */
++			/* really long time */
++			tmp = LIRC_SPACE(LIRC_VALUE_MASK);
 +		} else {
 +			tmp = (int) (deltv*1000000+
 +					sz->signal_start.tv_usec -
 +					sz->signal_last.tv_usec);
 +			tmp -= sz->sum;
++			tmp = LIRC_SPACE(tmp);
 +		}
 +		dprintk("ls %u", sz->driver->minor, tmp);
 +		push(sz, (char *)&tmp);
@@ -12156,7 +12398,7 @@ index 0000000..f4374e8
 +	pulse = ((int) value) * STREAMZAP_RESOLUTION;
 +	pulse += STREAMZAP_RESOLUTION / 2;
 +	sz->sum += pulse;
-+	pulse |= PULSE_BIT;
++	pulse = LIRC_PULSE(pulse);
 +
 +	dprintk("p %u", sz->driver->minor, pulse & PULSE_MASK);
 +	push(sz, (char *)&pulse);
@@ -12176,6 +12418,7 @@ index 0000000..f4374e8
 +	space = ((int) value)*STREAMZAP_RESOLUTION;
 +	space += STREAMZAP_RESOLUTION/2;
 +	sz->sum += space;
++	space = LIRC_SPACE(space);
 +	dprintk("s %u", sz->driver->minor, space);
 +	push(sz, (char *)&space);
 +}
@@ -12244,9 +12487,16 @@ index 0000000..f4374e8
 +				sz->decoder_state = IgnorePulse;
 +				break;
 +			case FullSpace:
-+				if (sz->buf_in[i] == 0xff) {
++				if (sz->buf_in[i] == STREAMZAP_TIMEOUT) {
 +					sz->idle = 1;
 +					stop_timer(sz);
++					if (sz->timeout_enabled) {
++						int timeout =
++							LIRC_TIMEOUT
++							(STREAMZAP_TIMEOUT *
++							STREAMZAP_RESOLUTION);
++						push(sz, (char *)&timeout);
++					}
 +					flush_delay_buffer(sz);
 +				} else
 +					push_full_space(sz, sz->buf_in[i]);
@@ -12376,8 +12626,12 @@ index 0000000..f4374e8
 +	sz->driver->minor = -1;
 +	sz->driver->sample_rate = 0;
 +	sz->driver->code_length = sizeof(int) * 8;
-+	sz->driver->features = LIRC_CAN_REC_MODE2 | LIRC_CAN_GET_REC_RESOLUTION;
++	sz->driver->features = LIRC_CAN_REC_MODE2 |
++		LIRC_CAN_GET_REC_RESOLUTION |
++		LIRC_CAN_SET_REC_TIMEOUT;
 +	sz->driver->data = sz;
++	sz->driver->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION;
++	sz->driver->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION;
 +	sz->driver->rbuf = lirc_buf;
 +	sz->delay_buf = delay_buf;
 +	sz->driver->set_use_inc = &streamzap_use_inc;
@@ -12508,18 +12762,29 @@ index 0000000..f4374e8
 +static int streamzap_ioctl(struct inode *node, struct file *filep,
 +			   unsigned int cmd, unsigned long arg)
 +{
-+	int result;
++	int result = 0;
++	int val;
++	struct usb_streamzap *sz = lirc_get_pdata(filep);
 +
 +	switch (cmd) {
 +	case LIRC_GET_REC_RESOLUTION:
 +		result = put_user(STREAMZAP_RESOLUTION, (unsigned int *) arg);
-+		if (result)
-+			return result;
++		break;
++	case LIRC_SET_REC_TIMEOUT:
++		result = get_user(val, (int *)arg);
++		if (result == 0) {
++			if (val == STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION)
++				sz->timeout_enabled = 1;
++			else if (val == 0)
++				sz->timeout_enabled = 0;
++			else
++				result = -EINVAL;
++		}
 +		break;
 +	default:
 +		return lirc_dev_fop_ioctl(node, filep, cmd, arg);
 +	}
-+	return 0;
++	return result;
 +}
 +
 +/**
@@ -13048,10 +13313,10 @@ index 0000000..b0a4e8b
 +module_exit(ttusbir_exit_module);
 diff --git a/drivers/input/lirc/lirc_zilog.c b/drivers/input/lirc/lirc_zilog.c
 new file mode 100644
-index 0000000..3a5bc34
+index 0000000..9f73430
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_zilog.c
-@@ -0,0 +1,1396 @@
+@@ -0,0 +1,1388 @@
 +/*
 + * i2c IR lirc driver for devices with zilog IR processors
 + *
@@ -14252,14 +14517,6 @@ index 0000000..3a5bc34
 +	dprintk("%s: adapter id=0x%x, client addr=0x%02x\n",
 +		__func__, adap->id, client->addr);
 +
-+	/* if this isn't an appropriate device, bail w/-ENODEV now */
-+	if (!(adap->id == I2C_HW_B_BT848 ||
-+#ifdef I2C_HW_B_HDPVR
-+	      adap->id == I2C_HW_B_HDPVR ||
-+#endif
-+	      adap->id == I2C_HW_B_CX2341X))
-+		goto out_nodev;
-+
 +	/*
 +	 * The external IR receiver is at i2c address 0x71.
 +	 * The IR transmitter is at 0x70.
@@ -14315,7 +14572,7 @@ index 0000000..3a5bc34
 +		memcpy(&ir->c_rx, client, sizeof(struct i2c_client));
 +
 +		ir->c_rx.addr = 0x71;
-+		strncpy(ir->c_rx.name, ZILOG_HAUPPAUGE_IR_RX_NAME,
++		strlcpy(ir->c_rx.name, ZILOG_HAUPPAUGE_IR_RX_NAME,
 +			I2C_NAME_SIZE);
 +
 +		/* try to fire up polling thread */
@@ -14336,7 +14593,7 @@ index 0000000..3a5bc34
 +	if (have_tx) {
 +		memcpy(&ir->c_tx, client, sizeof(struct i2c_client));
 +		ir->c_tx.addr = 0x70;
-+		strncpy(ir->c_tx.name, ZILOG_HAUPPAUGE_IR_TX_NAME,
++		strlcpy(ir->c_tx.name, ZILOG_HAUPPAUGE_IR_TX_NAME,
 +			I2C_NAME_SIZE);
 +		ir->have_tx = 1;
 +	}
@@ -14449,10 +14706,10 @@ index 0000000..3a5bc34
 +module_param(disable_tx, bool, 0644);
 +MODULE_PARM_DESC(disable_tx, "Disable the IR transmitter device");
 diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
-index 16ec523..1196110 100644
+index 23140a3..7085225 100644
 --- a/drivers/input/misc/Kconfig
 +++ b/drivers/input/misc/Kconfig
-@@ -319,4 +319,16 @@ config INPUT_PCAP
+@@ -340,4 +340,16 @@ config INPUT_PCAP
  	  To compile this driver as a module, choose M here: the
  	  module will be called pcap_keys.
  
@@ -14470,10 +14727,10 @@ index 16ec523..1196110 100644
 +
  endif
 diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
-index a8b8485..79358ff 100644
+index 7e95a5d..8918ce7 100644
 --- a/drivers/input/misc/Makefile
 +++ b/drivers/input/misc/Makefile
-@@ -13,6 +13,7 @@ obj-$(CONFIG_INPUT_CM109)		+= cm109.o
+@@ -14,6 +14,7 @@ obj-$(CONFIG_INPUT_CM109)		+= cm109.o
  obj-$(CONFIG_INPUT_COBALT_BTNS)		+= cobalt_btns.o
  obj-$(CONFIG_INPUT_DM355EVM)		+= dm355evm_keys.o
  obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
@@ -14483,10 +14740,10 @@ index a8b8485..79358ff 100644
  obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
 diff --git a/drivers/input/misc/imon.c b/drivers/input/misc/imon.c
 new file mode 100644
-index 0000000..71223e2
+index 0000000..58a2130
 --- /dev/null
 +++ b/drivers/input/misc/imon.c
-@@ -0,0 +1,2430 @@
+@@ -0,0 +1,2523 @@
 +/*
 + *   imon.c:	input and display driver for SoundGraph iMON IR/VFD/LCD
 + *
@@ -14771,7 +15028,11 @@ index 0000000..71223e2
 +	.minor_base	= DISPLAY_MINOR_BASE,
 +};
 +
-+/* standard imon remote key table */
++/*
++ * standard imon remote key table, which isn't really entirely
++ * "standard", as different receivers decode the same key on the
++ * same remote to different hex codes... ugh.
++ */
 +static const struct key_entry imon_remote_key_table[] = {
 +	/* keys sorted mostly by frequency of use to optimize lookups */
 +	{ KE_KEY, 0x2a8195b7, { KEY_REWIND } },
@@ -14798,10 +15059,14 @@ index 0000000..71223e2
 +	{ KE_KEY, 0x2ba515b7, { KEY_RIGHT } },
 +
 +	{ KE_KEY, 0x0200002c, { KEY_SPACE } }, /* Select/Space */
++	{ KE_KEY, 0x2a9315b7, { KEY_SPACE } }, /* Select/Space */
 +	{ KE_KEY, 0x02000028, { KEY_ENTER } },
++	{ KE_KEY, 0x28a195b7, { KEY_ENTER } },
 +	{ KE_KEY, 0x288195b7, { KEY_EXIT } },
 +	{ KE_KEY, 0x02000029, { KEY_ESC } },
++	{ KE_KEY, 0x2bb715b7, { KEY_ESC } },
 +	{ KE_KEY, 0x0200002a, { KEY_BACKSPACE } },
++	{ KE_KEY, 0x28a115b7, { KEY_BACKSPACE } },
 +
 +	{ KE_KEY, 0x2b9595b7, { KEY_MUTE } },
 +	{ KE_KEY, 0x28a395b7, { KEY_VOLUMEUP } },
@@ -14820,8 +15085,21 @@ index 0000000..71223e2
 +	{ KE_KEY, 0x02000026, { KEY_NUMERIC_9 } },
 +	{ KE_KEY, 0x02000027, { KEY_NUMERIC_0 } },
 +
++	{ KE_KEY, 0x28b595b7, { KEY_NUMERIC_1 } },
++	{ KE_KEY, 0x2bb195b7, { KEY_NUMERIC_2 } },
++	{ KE_KEY, 0x28b195b7, { KEY_NUMERIC_3 } },
++	{ KE_KEY, 0x2a8595b7, { KEY_NUMERIC_4 } },
++	{ KE_KEY, 0x299595b7, { KEY_NUMERIC_5 } },
++	{ KE_KEY, 0x2aa595b7, { KEY_NUMERIC_6 } },
++	{ KE_KEY, 0x2b9395b7, { KEY_NUMERIC_7 } },
++	{ KE_KEY, 0x2a8515b7, { KEY_NUMERIC_8 } },
++	{ KE_KEY, 0x2aa115b7, { KEY_NUMERIC_9 } },
++	{ KE_KEY, 0x2ba595b7, { KEY_NUMERIC_0 } },
++
 +	{ KE_KEY, 0x02200025, { KEY_NUMERIC_STAR } },
++	{ KE_KEY, 0x28b515b7, { KEY_NUMERIC_STAR } },
 +	{ KE_KEY, 0x02200020, { KEY_NUMERIC_POUND } },
++	{ KE_KEY, 0x29a115b7, { KEY_NUMERIC_POUND } },
 +
 +	{ KE_KEY, 0x2b8515b7, { KEY_VIDEO } },
 +	{ KE_KEY, 0x299195b7, { KEY_AUDIO } },
@@ -14849,6 +15127,8 @@ index 0000000..71223e2
 +	{ KE_KEY, 0x01020000, { BTN_RIGHT } },
 +	{ KE_KEY, 0x01010080, { BTN_LEFT } },
 +	{ KE_KEY, 0x01020080, { BTN_RIGHT } },
++	{ KE_KEY, 0x688301b7, { BTN_LEFT } },
++	{ KE_KEY, 0x688481b7, { BTN_RIGHT } },
 +
 +	{ KE_KEY, 0x2a9395b7, { KEY_CYCLEWINDOWS } }, /* TaskSwitcher */
 +	{ KE_KEY, 0x2b8395b7, { KEY_TIME } }, /* Timer */
@@ -14857,9 +15137,11 @@ index 0000000..71223e2
 +	{ KE_KEY, 0x29b195b7, { KEY_EJECTCD } }, /* the one next to play */
 +	{ KE_KEY, 0x299395b7, { KEY_EJECTCLOSECD } }, /* eject (by TaskSw) */
 +
-+	{ KE_KEY, 0x02800000, { KEY_MENU } }, /* Left Menu */
++	{ KE_KEY, 0x02800000, { KEY_CONTEXT_MENU } }, /* Left Menu */
++	{ KE_KEY, 0x2b8195b7, { KEY_CONTEXT_MENU } }, /* Left Menu*/
 +	{ KE_KEY, 0x02000065, { KEY_COMPOSE } }, /* RightMenu */
-+	{ KE_KEY, 0x2ab195b7, { KEY_PROG1 } }, /* Go */
++	{ KE_KEY, 0x28b715b7, { KEY_COMPOSE } }, /* RightMenu */
++	{ KE_KEY, 0x2ab195b7, { KEY_PROG1 } }, /* Go or MultiMon */
 +	{ KE_KEY, 0x29b715b7, { KEY_DASHBOARD } }, /* AppLauncher */
 +	{ KE_END, 0 }
 +};
@@ -14867,33 +15149,43 @@ index 0000000..71223e2
 +/* mce-mode imon mce remote key table */
 +static const struct key_entry imon_mce_key_table[] = {
 +	/* keys sorted mostly by frequency of use to optimize lookups */
-+	{ KE_KEY, 0x800f8415, { KEY_REWIND } },
-+	{ KE_KEY, 0x800f8414, { KEY_FASTFORWARD } },
-+	{ KE_KEY, 0x800f841b, { KEY_PREVIOUS } },
-+	{ KE_KEY, 0x800f841a, { KEY_NEXT } },
++	{ KE_KEY, 0x800ff415, { KEY_REWIND } },
++	{ KE_KEY, 0x800ff414, { KEY_FASTFORWARD } },
++	{ KE_KEY, 0x800ff41b, { KEY_PREVIOUS } },
++	{ KE_KEY, 0x800ff41a, { KEY_NEXT } },
 +
-+	{ KE_KEY, 0x800f8416, { KEY_PLAY } },
-+	{ KE_KEY, 0x800f8418, { KEY_PAUSE } },
-+	{ KE_KEY, 0x800f8418, { KEY_PAUSE } },
-+	{ KE_KEY, 0x800f8419, { KEY_STOP } },
-+	{ KE_KEY, 0x800f8417, { KEY_RECORD } },
++	{ KE_KEY, 0x800ff416, { KEY_PLAY } },
++	{ KE_KEY, 0x800ff418, { KEY_PAUSE } },
++	{ KE_KEY, 0x800ff419, { KEY_STOP } },
++	{ KE_KEY, 0x800ff417, { KEY_RECORD } },
 +
 +	{ KE_KEY, 0x02000052, { KEY_UP } },
 +	{ KE_KEY, 0x02000051, { KEY_DOWN } },
 +	{ KE_KEY, 0x02000050, { KEY_LEFT } },
 +	{ KE_KEY, 0x0200004f, { KEY_RIGHT } },
 +
++	{ KE_KEY, 0x800ff41e, { KEY_UP } },
++	{ KE_KEY, 0x800ff41f, { KEY_DOWN } },
++	{ KE_KEY, 0x800ff420, { KEY_LEFT } },
++	{ KE_KEY, 0x800ff421, { KEY_RIGHT } },
++
++	/* 0x800ff40b also KEY_NUMERIC_POUND on some receivers */
++	{ KE_KEY, 0x800ff40b, { KEY_ENTER } },
 +	{ KE_KEY, 0x02000028, { KEY_ENTER } },
-+/* the OK and Enter buttons decode to the same value
++/* the OK and Enter buttons decode to the same value on some remotes
 +	{ KE_KEY, 0x02000028, { KEY_OK } }, */
++	{ KE_KEY, 0x800ff422, { KEY_OK } },
 +	{ KE_KEY, 0x0200002a, { KEY_EXIT } },
++	{ KE_KEY, 0x800ff423, { KEY_EXIT } },
 +	{ KE_KEY, 0x02000029, { KEY_DELETE } },
++	/* 0x800ff40a also KEY_NUMERIC_STAR on some receivers */
++	{ KE_KEY, 0x800ff40a, { KEY_DELETE } },
 +
-+	{ KE_KEY, 0x800f840e, { KEY_MUTE } },
-+	{ KE_KEY, 0x800f8410, { KEY_VOLUMEUP } },
-+	{ KE_KEY, 0x800f8411, { KEY_VOLUMEDOWN } },
-+	{ KE_KEY, 0x800f8412, { KEY_CHANNELUP } },
-+	{ KE_KEY, 0x800f8413, { KEY_CHANNELDOWN } },
++	{ KE_KEY, 0x800ff40e, { KEY_MUTE } },
++	{ KE_KEY, 0x800ff410, { KEY_VOLUMEUP } },
++	{ KE_KEY, 0x800ff411, { KEY_VOLUMEDOWN } },
++	{ KE_KEY, 0x800ff412, { KEY_CHANNELUP } },
++	{ KE_KEY, 0x800ff413, { KEY_CHANNELDOWN } },
 +
 +	{ KE_KEY, 0x0200001e, { KEY_NUMERIC_1 } },
 +	{ KE_KEY, 0x0200001f, { KEY_NUMERIC_2 } },
@@ -14906,28 +15198,55 @@ index 0000000..71223e2
 +	{ KE_KEY, 0x02000026, { KEY_NUMERIC_9 } },
 +	{ KE_KEY, 0x02000027, { KEY_NUMERIC_0 } },
 +
++	{ KE_KEY, 0x800ff401, { KEY_NUMERIC_1 } },
++	{ KE_KEY, 0x800ff402, { KEY_NUMERIC_2 } },
++	{ KE_KEY, 0x800ff403, { KEY_NUMERIC_3 } },
++	{ KE_KEY, 0x800ff404, { KEY_NUMERIC_4 } },
++	{ KE_KEY, 0x800ff405, { KEY_NUMERIC_5 } },
++	{ KE_KEY, 0x800ff406, { KEY_NUMERIC_6 } },
++	{ KE_KEY, 0x800ff407, { KEY_NUMERIC_7 } },
++	{ KE_KEY, 0x800ff408, { KEY_NUMERIC_8 } },
++	{ KE_KEY, 0x800ff409, { KEY_NUMERIC_9 } },
++	{ KE_KEY, 0x800ff400, { KEY_NUMERIC_0 } },
++
 +	{ KE_KEY, 0x02200025, { KEY_NUMERIC_STAR } },
 +	{ KE_KEY, 0x02200020, { KEY_NUMERIC_POUND } },
-+
-+	{ KE_KEY, 0x800f8446, { KEY_TV } },
-+	{ KE_KEY, 0x800f8447, { KEY_AUDIO } },
-+	{ KE_KEY, 0x800f8448, { KEY_PVR } }, /* RecordedTV */
-+	{ KE_KEY, 0x800f8449, { KEY_CAMERA } },
-+	{ KE_KEY, 0x800f844a, { KEY_VIDEO } },
-+	{ KE_KEY, 0x800f8424, { KEY_DVD } },
-+	{ KE_KEY, 0x800f8425, { KEY_TUNER } }, /* LiveTV */
-+
-+	{ KE_KEY, 0x800f845b, { KEY_RED } },
-+	{ KE_KEY, 0x800f845c, { KEY_GREEN } },
-+	{ KE_KEY, 0x800f845d, { KEY_YELLOW } },
-+	{ KE_KEY, 0x800f845e, { KEY_BLUE } },
-+
-+	{ KE_KEY, 0x800f840f, { KEY_INFO } },
-+	{ KE_KEY, 0x800f8426, { KEY_EPG } }, /* Guide */
-+	{ KE_KEY, 0x800f845a, { KEY_SUBTITLE } }, /* Caption */
-+
-+	{ KE_KEY, 0x800f840c, { KEY_POWER } },
-+	{ KE_KEY, 0x800f840d, { KEY_PROG1 } }, /* Windows MCE button */
++	/* 0x800ff41d also KEY_BLUE on some receivers */
++	{ KE_KEY, 0x800ff41d, { KEY_NUMERIC_STAR } },
++	/* 0x800ff41c also KEY_PREVIOUS on some receivers */
++	{ KE_KEY, 0x800ff41c, { KEY_NUMERIC_POUND } },
++
++	{ KE_KEY, 0x800ff446, { KEY_TV } },
++	{ KE_KEY, 0x800ff447, { KEY_AUDIO } }, /* My Music */
++	{ KE_KEY, 0x800ff448, { KEY_PVR } }, /* RecordedTV */
++	{ KE_KEY, 0x800ff449, { KEY_CAMERA } },
++	{ KE_KEY, 0x800ff44a, { KEY_VIDEO } },
++	/* 0x800ff424 also KEY_MENU on some receivers */
++	{ KE_KEY, 0x800ff424, { KEY_DVD } },
++	/* 0x800ff425 also KEY_GREEN on some receivers */
++	{ KE_KEY, 0x800ff425, { KEY_TUNER } }, /* LiveTV */
++	{ KE_KEY, 0x800ff450, { KEY_RADIO } },
++
++	{ KE_KEY, 0x800ff44c, { KEY_LANGUAGE } },
++	{ KE_KEY, 0x800ff427, { KEY_ZOOM } }, /* Aspect */
++
++	{ KE_KEY, 0x800ff45b, { KEY_RED } },
++	{ KE_KEY, 0x800ff45c, { KEY_GREEN } },
++	{ KE_KEY, 0x800ff45d, { KEY_YELLOW } },
++	{ KE_KEY, 0x800ff45e, { KEY_BLUE } },
++
++	{ KE_KEY, 0x800ff466, { KEY_RED } },
++	/* { KE_KEY, 0x800ff425, { KEY_GREEN } }, */
++	{ KE_KEY, 0x800ff468, { KEY_YELLOW } },
++	/* { KE_KEY, 0x800ff41d, { KEY_BLUE } }, */
++
++	{ KE_KEY, 0x800ff40f, { KEY_INFO } },
++	{ KE_KEY, 0x800ff426, { KEY_EPG } }, /* Guide */
++	{ KE_KEY, 0x800ff45a, { KEY_SUBTITLE } }, /* Caption/Teletext */
++	{ KE_KEY, 0x800ff44d, { KEY_TITLE } },
++
++	{ KE_KEY, 0x800ff40c, { KEY_POWER } },
++	{ KE_KEY, 0x800ff40d, { KEY_PROG1 } }, /* Windows MCE button */
 +	{ KE_END, 0 }
 +
 +};
@@ -14937,25 +15256,28 @@ index 0000000..71223e2
 +	u64 hw_code;
 +	u16 keycode;
 +} imon_panel_key_table[] = {
-+	{ 0x000000000f000fee, KEY_PROG1 }, /* Go */
-+	{ 0x000000001f000fee, KEY_AUDIO },
-+	{ 0x0000000020000fee, KEY_VIDEO },
-+	{ 0x0000000021000fee, KEY_CAMERA },
-+	{ 0x0000000027000fee, KEY_DVD },
-+/* the TV key on my panel is broken, doesn't work under any OS
-+	{ 0x0000000000000fee, KEY_TV }, */
-+	{ 0x0000000005000fee, KEY_PREVIOUS },
-+	{ 0x0000000007000fee, KEY_REWIND },
-+	{ 0x0000000004000fee, KEY_STOP },
-+	{ 0x000000003c000fee, KEY_PLAYPAUSE },
-+	{ 0x0000000008000fee, KEY_FASTFORWARD },
-+	{ 0x0000000006000fee, KEY_NEXT },
-+	{ 0x0000000100000fee, KEY_RIGHT },
-+	{ 0x0000010000000fee, KEY_LEFT },
-+	{ 0x000000003d000fee, KEY_SELECT },
-+	{ 0x0001000000000fee, KEY_VOLUMEUP },
-+	{ 0x0100000000000fee, KEY_VOLUMEDOWN },
-+	{ 0x0000000001000fee, KEY_MUTE },
++	{ 0x000000000f00ffee, KEY_PROG1 }, /* Go */
++	{ 0x000000001f00ffee, KEY_AUDIO },
++	{ 0x000000002000ffee, KEY_VIDEO },
++	{ 0x000000002100ffee, KEY_CAMERA },
++	{ 0x000000002700ffee, KEY_DVD },
++	{ 0x000000002300ffee, KEY_TV },
++	{ 0x000000000500ffee, KEY_PREVIOUS },
++	{ 0x000000000700ffee, KEY_REWIND },
++	{ 0x000000000400ffee, KEY_STOP },
++	{ 0x000000003c00ffee, KEY_PLAYPAUSE },
++	{ 0x000000000800ffee, KEY_FASTFORWARD },
++	{ 0x000000000600ffee, KEY_NEXT },
++	{ 0x000000010000ffee, KEY_RIGHT },
++	{ 0x000001000000ffee, KEY_LEFT },
++	{ 0x000000003d00ffee, KEY_SELECT },
++	{ 0x000100000000ffee, KEY_VOLUMEUP },
++	{ 0x010000000000ffee, KEY_VOLUMEDOWN },
++	{ 0x000000000100ffee, KEY_MUTE },
++	/* iMON Knob values */
++	{ 0x000100ffffffffee, KEY_VOLUMEUP },
++	{ 0x010000ffffffffee, KEY_VOLUMEDOWN },
++	{ 0x000008ffffffffee, KEY_MUTE },
 +};
 +
 +/* to prevent races between open() and disconnect(), probing, etc */
@@ -15613,6 +15935,33 @@ index 0000000..71223e2
 +}
 +
 +/**
++ * mce/rc6 keypresses have no distinct release code, use timer
++ */
++static void imon_mce_timeout(unsigned long data)
++{
++	struct imon_context *ictx = (struct imon_context *)data;
++
++	input_report_key(ictx->idev, ictx->last_keycode, 0);
++	input_sync(ictx->idev);
++}
++
++/**
++ * report touchscreen input
++ */
++static void imon_touch_display_timeout(unsigned long data)
++{
++	struct imon_context *ictx = (struct imon_context *)data;
++
++	if (!ictx->display_type == IMON_DISPLAY_TYPE_VGA)
++		return;
++
++	input_report_abs(ictx->touch, ABS_X, ictx->touch_x);
++	input_report_abs(ictx->touch, ABS_Y, ictx->touch_y);
++	input_report_key(ictx->touch, BTN_TOUCH, 0x00);
++	input_sync(ictx->touch);
++}
++
++/**
 + * iMON IR receivers support two different signal sets -- those used by
 + * the iMON remotes, and those used by the Windows MCE remotes (which is
 + * really just RC-6), but only one or the other at a time, as the signals
@@ -15631,6 +15980,9 @@ index 0000000..71223e2
 +		ir_proto_packet[0] = 0x01;
 +		ictx->ir_protocol = IMON_IR_PROTOCOL_MCE;
 +		ictx->pad_mouse = 0;
++		init_timer(&ictx->itimer);
++		ictx->itimer.data = (unsigned long)ictx;
++		ictx->itimer.function = imon_mce_timeout;
 +		break;
 +	case IMON_IR_PROTOCOL_IMON:
 +		dev_dbg(dev, "Configuring IR receiver for iMON protocol\n");
@@ -15785,12 +16137,22 @@ index 0000000..71223e2
 +	int i;
 +	u32 code = be32_to_cpu(hw_code);
 +
-+	for (i = 0; i < ARRAY_SIZE(imon_mce_key_table); i++)
-+		if (imon_mce_key_table[i].code == code)
-+			return i;
++#define MCE_KEY_MASK 0x7000
++#define MCE_TOGGLE_BIT 0x8000
++
++	/*
++	 * On some receivers, mce keys decode to 0x8000f04xx and 0x8000f84xx
++	 * (the toggle bit flipping between alternating key presses), while
++	 * on other receivers, we see 0x8000f74xx and 0x8000ff4xx. To keep
++	 * the table trim, we always or in the bits to look up 0x8000ff4xx,
++	 * but we can't or them into all codes, as some keys are decoded in
++	 * a different way w/o the same use of the toggle bit...
++	 */
++	if ((code >> 24) & 0x80)
++		code = code | MCE_KEY_MASK | MCE_TOGGLE_BIT;
 +
 +	for (i = 0; i < ARRAY_SIZE(imon_mce_key_table); i++)
-+		if (imon_mce_key_table[i].code == (code | 0x8000))
++		if (imon_mce_key_table[i].code == code)
 +			return i;
 +
 +	return -1;
@@ -15802,7 +16164,7 @@ index 0000000..71223e2
 +	u64 code = be64_to_cpu(hw_code);
 +
 +	for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++)
-+		if (imon_panel_key_table[i].hw_code == (code | 0xfee))
++		if (imon_panel_key_table[i].hw_code == (code | 0xffee))
 +			return i;
 +
 +	return -1;
@@ -16000,6 +16362,16 @@ index 0000000..71223e2
 +	if (ictx->ki == -1 && buf[0] == 0x02 && buf[3] == 0x00)
 +		ictx->kc = ictx->last_keycode;
 +
++	/* mouse button release on (some) 0xffdc devices */
++	else if (ictx->ki == -1 && buf[0] == 0x68 && buf[1] == 0x82 &&
++		 buf[2] == 0x81 && buf[3] == 0xb7)
++		ictx->kc = ictx->last_keycode;
++
++	/* mouse button release on (some other) 0xffdc devices */
++	else if (ictx->ki == -1 && buf[0] == 0x01 && buf[1] == 0x00 &&
++		 buf[2] == 0x81 && buf[3] == 0xb7)
++		ictx->kc = ictx->last_keycode;
++
 +	/* mce-specific button handling */
 +	else if (ksrc == IMON_BUTTON_MCE) {
 +		/* initial press */
@@ -16047,7 +16419,7 @@ index 0000000..71223e2
 +	int offset = IMON_KEY_RELEASE_OFFSET;
 +	u64 temp_key;
 +	u64 panel_key = 0;
-+	u32 remote_key;
++	u32 remote_key = 0;
 +	struct input_dev *idev = NULL;
 +	int press_type = 0;
 +	int msec;
@@ -16057,38 +16429,51 @@ index 0000000..71223e2
 +
 +	idev = ictx->idev;
 +
++	/* filter out junk data on the older 0xffdc imon devices */
++	if ((buf[0] == 0xff) && (buf[7] == 0xff))
++		return;
++
 +	/* Figure out what key was pressed */
 +	memcpy(&temp_key, buf, sizeof(temp_key));
 +	if (len == 8 && buf[7] == 0xee) {
 +		ksrc = IMON_BUTTON_PANEL;
 +		panel_key = le64_to_cpu(temp_key);
 +		ki = imon_panel_key_lookup(panel_key);
-+		kc = imon_panel_key_table[ki].keycode;
++		if (ki < 0)
++			kc = KEY_UNKNOWN;
++		else
++			kc = imon_panel_key_table[ki].keycode;
 +	} else {
 +		remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff);
 +		if (ictx->ir_protocol == IMON_IR_PROTOCOL_MCE) {
 +			if (buf[0] == 0x80)
 +				ksrc = IMON_BUTTON_MCE;
 +			ki = imon_mce_key_lookup(remote_key);
-+			kc = imon_mce_key_table[ki].keycode;
++			if (ki < 0)
++				kc = KEY_UNKNOWN;
++			else
++				kc = imon_mce_key_table[ki].keycode;
 +		} else {
 +			ki = imon_remote_key_lookup(remote_key);
-+			kc = imon_remote_key_table[ki % offset].keycode;
++			if (ki < 0)
++				kc = KEY_UNKNOWN;
++			else
++				kc = imon_remote_key_table[ki % offset].keycode;
 +		}
 +	}
 +
 +	/* keyboard/mouse mode toggle button */
 +	if (kc == KEY_KEYBOARD && ki < offset) {
++		ictx->last_keycode = kc;
 +		if (!nomouse) {
 +			ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1;
 +			dev_dbg(dev, "toggling to %s mode\n",
 +				ictx->pad_mouse ? "mouse" : "keyboard");
++			return;
 +		} else {
 +			ictx->pad_mouse = 0;
-+			dev_dbg(dev, "mouse mode was disabled by modparam\n");
++			dev_dbg(dev, "mouse mode disabled, passing key value\n");
 +		}
-+		ictx->last_keycode = kc;
-+		return;
 +	}
 +
 +	ictx->ki = ki;
@@ -16125,6 +16510,9 @@ index 0000000..71223e2
 +	if (press_type < 0)
 +		goto not_input_data;
 +
++	if (ictx->kc == KEY_UNKNOWN)
++		goto unknown_key;
++
 +	/* KEY_MUTE repeats from MCE and knob need to be suppressed */
 +	if ((ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode)
 +	    && (buf[7] == 0xee || ksrc == IMON_BUTTON_MCE)) {
@@ -16148,6 +16536,12 @@ index 0000000..71223e2
 +
 +	return;
 +
++unknown_key:
++	dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__,
++		 (panel_key ? be64_to_cpu(panel_key) :
++			      be32_to_cpu(remote_key)));
++	return;
++
 +not_input_data:
 +	if (len != 8) {
 +		dev_warn(dev, "imon %s: invalid incoming packet "
@@ -16170,40 +16564,11 @@ index 0000000..71223e2
 +}
 +
 +/**
-+ * mce/rc6 keypresses have no distinct release code, use timer
-+ */
-+static void imon_mce_timeout(unsigned long data)
-+{
-+	struct imon_context *ictx = (struct imon_context *)data;
-+
-+	input_report_key(ictx->idev, ictx->last_keycode, 0);
-+	input_sync(ictx->idev);
-+}
-+
-+/**
-+ * report touchscreen input
-+ */
-+static void imon_touch_display_timeout(unsigned long data)
-+{
-+	struct imon_context *ictx = (struct imon_context *)data;
-+
-+	if (!ictx->display_type == IMON_DISPLAY_TYPE_VGA)
-+		return;
-+
-+	input_report_abs(ictx->touch, ABS_X, ictx->touch_x);
-+	input_report_abs(ictx->touch, ABS_Y, ictx->touch_y);
-+	input_report_key(ictx->touch, BTN_TOUCH, 0x00);
-+	input_sync(ictx->touch);
-+}
-+
-+/**
 + * Callback function for USB core API: receive data
 + */
 +static void usb_rx_callback_intf0(struct urb *urb)
 +{
 +	struct imon_context *ictx;
-+	unsigned char *buf;
-+	int len;
 +	int intfnum = 0;
 +
 +	if (!urb)
@@ -16213,9 +16578,6 @@ index 0000000..71223e2
 +	if (!ictx)
 +		return;
 +
-+	buf = urb->transfer_buffer;
-+	len = urb->actual_length;
-+
 +	switch (urb->status) {
 +	case -ENOENT:		/* usbcore unlink successful! */
 +		return;
@@ -16239,8 +16601,6 @@ index 0000000..71223e2
 +static void usb_rx_callback_intf1(struct urb *urb)
 +{
 +	struct imon_context *ictx;
-+	unsigned char *buf;
-+	int len;
 +	int intfnum = 1;
 +
 +	if (!urb)
@@ -16250,9 +16610,6 @@ index 0000000..71223e2
 +	if (!ictx)
 +		return;
 +
-+	buf = urb->transfer_buffer;
-+	len = urb->actual_length;
-+
 +	switch (urb->status) {
 +	case -ENOENT:		/* usbcore unlink successful! */
 +		return;
@@ -16506,12 +16863,6 @@ index 0000000..71223e2
 +
 +	mutex_lock(&ictx->lock);
 +
-+	if (ir_protocol == IMON_IR_PROTOCOL_MCE) {
-+		init_timer(&ictx->itimer);
-+		ictx->itimer.data = (unsigned long)ictx;
-+		ictx->itimer.function = imon_mce_timeout;
-+	}
-+
 +	ictx->dev = dev;
 +	ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf));
 +	ictx->dev_present_intf0 = 1;
@@ -16728,7 +17079,6 @@ index 0000000..71223e2
 +	first_if = usb_ifnum_to_if(usbdev, 0);
 +	first_if_ctx = (struct imon_context *)usb_get_intfdata(first_if);
 +
-+
 +	if (ifnum == 0) {
 +		ictx = imon_init_intf0(interface);
 +		if (!ictx) {
@@ -16917,3 +17267,168 @@ index 0000000..71223e2
 +
 +module_init(imon_init);
 +module_exit(imon_exit);
+diff --git a/include/linux/lirc.h b/include/linux/lirc.h
+new file mode 100644
+index 0000000..9ca6876
+--- /dev/null
++++ b/include/linux/lirc.h
+@@ -0,0 +1,159 @@
++/*
++ * lirc.h - linux infrared remote control header file
++ * last modified 2007/09/27
++ */
++
++#ifndef _LINUX_LIRC_H
++#define _LINUX_LIRC_H
++
++#include <linux/types.h>
++#include <linux/ioctl.h>
++
++/* <obsolete> */
++#define PULSE_BIT       0x01000000
++#define PULSE_MASK      0x00FFFFFF
++/* </obsolete> */
++
++#define LIRC_MODE2_SPACE     0x00000000
++#define LIRC_MODE2_PULSE     0x01000000
++#define LIRC_MODE2_FREQUENCY 0x02000000
++#define LIRC_MODE2_TIMEOUT   0x03000000
++
++#define LIRC_VALUE_MASK      0x00FFFFFF
++#define LIRC_MODE2_MASK      0xFF000000
++
++#define LIRC_SPACE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_SPACE)
++#define LIRC_PULSE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_PULSE)
++#define LIRC_FREQUENCY(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY)
++#define LIRC_TIMEOUT(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT)
++
++#define LIRC_VALUE(val) ((val)&LIRC_VALUE_MASK)
++#define LIRC_MODE2(val) ((val)&LIRC_MODE2_MASK)
++
++#define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE)
++#define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE)
++#define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY)
++#define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT)
++
++/*** lirc compatible hardware features ***/
++
++#define LIRC_MODE2SEND(x) (x)
++#define LIRC_SEND2MODE(x) (x)
++#define LIRC_MODE2REC(x) ((x) << 16)
++#define LIRC_REC2MODE(x) ((x) >> 16)
++
++#define LIRC_MODE_RAW                  0x00000001
++#define LIRC_MODE_PULSE                0x00000002
++#define LIRC_MODE_MODE2                0x00000004
++#define LIRC_MODE_LIRCCODE             0x00000010
++
++
++#define LIRC_CAN_SEND_RAW              LIRC_MODE2SEND(LIRC_MODE_RAW)
++#define LIRC_CAN_SEND_PULSE            LIRC_MODE2SEND(LIRC_MODE_PULSE)
++#define LIRC_CAN_SEND_MODE2            LIRC_MODE2SEND(LIRC_MODE_MODE2)
++#define LIRC_CAN_SEND_LIRCCODE         LIRC_MODE2SEND(LIRC_MODE_LIRCCODE)
++
++#define LIRC_CAN_SEND_MASK             0x0000003f
++
++#define LIRC_CAN_SET_SEND_CARRIER      0x00000100
++#define LIRC_CAN_SET_SEND_DUTY_CYCLE   0x00000200
++#define LIRC_CAN_SET_TRANSMITTER_MASK  0x00000400
++
++#define LIRC_CAN_REC_RAW               LIRC_MODE2REC(LIRC_MODE_RAW)
++#define LIRC_CAN_REC_PULSE             LIRC_MODE2REC(LIRC_MODE_PULSE)
++#define LIRC_CAN_REC_MODE2             LIRC_MODE2REC(LIRC_MODE_MODE2)
++#define LIRC_CAN_REC_LIRCCODE          LIRC_MODE2REC(LIRC_MODE_LIRCCODE)
++
++#define LIRC_CAN_REC_MASK              LIRC_MODE2REC(LIRC_CAN_SEND_MASK)
++
++#define LIRC_CAN_SET_REC_CARRIER       (LIRC_CAN_SET_SEND_CARRIER << 16)
++#define LIRC_CAN_SET_REC_DUTY_CYCLE    (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16)
++
++#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000
++#define LIRC_CAN_SET_REC_CARRIER_RANGE    0x80000000
++#define LIRC_CAN_GET_REC_RESOLUTION       0x20000000
++#define LIRC_CAN_SET_REC_TIMEOUT          0x10000000
++#define LIRC_CAN_SET_REC_FILTER           0x08000000
++
++#define LIRC_CAN_MEASURE_CARRIER          0x02000000
++
++#define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK)
++#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK)
++
++#define LIRC_CAN_NOTIFY_DECODE            0x01000000
++
++/*** IOCTL commands for lirc driver ***/
++
++#define LIRC_GET_FEATURES              _IOR('i', 0x00000000, unsigned long)
++
++#define LIRC_GET_SEND_MODE             _IOR('i', 0x00000001, unsigned long)
++#define LIRC_GET_REC_MODE              _IOR('i', 0x00000002, unsigned long)
++#define LIRC_GET_SEND_CARRIER          _IOR('i', 0x00000003, unsigned int)
++#define LIRC_GET_REC_CARRIER           _IOR('i', 0x00000004, unsigned int)
++#define LIRC_GET_SEND_DUTY_CYCLE       _IOR('i', 0x00000005, unsigned int)
++#define LIRC_GET_REC_DUTY_CYCLE        _IOR('i', 0x00000006, unsigned int)
++#define LIRC_GET_REC_RESOLUTION        _IOR('i', 0x00000007, unsigned int)
++
++#define LIRC_GET_MIN_TIMEOUT           _IOR('i', 0x00000008, uint32_t)
++#define LIRC_GET_MAX_TIMEOUT           _IOR('i', 0x00000009, uint32_t)
++
++#define LIRC_GET_MIN_FILTER_PULSE      _IOR('i', 0x0000000a, uint32_t)
++#define LIRC_GET_MAX_FILTER_PULSE      _IOR('i', 0x0000000b, uint32_t)
++#define LIRC_GET_MIN_FILTER_SPACE      _IOR('i', 0x0000000c, uint32_t)
++#define LIRC_GET_MAX_FILTER_SPACE      _IOR('i', 0x0000000d, uint32_t)
++
++/* code length in bits, currently only for LIRC_MODE_LIRCCODE */
++#define LIRC_GET_LENGTH                _IOR('i', 0x0000000f, unsigned long)
++
++#define LIRC_SET_SEND_MODE             _IOW('i', 0x00000011, unsigned long)
++#define LIRC_SET_REC_MODE              _IOW('i', 0x00000012, unsigned long)
++/* Note: these can reset the according pulse_width */
++#define LIRC_SET_SEND_CARRIER          _IOW('i', 0x00000013, unsigned int)
++#define LIRC_SET_REC_CARRIER           _IOW('i', 0x00000014, unsigned int)
++#define LIRC_SET_SEND_DUTY_CYCLE       _IOW('i', 0x00000015, unsigned int)
++#define LIRC_SET_REC_DUTY_CYCLE        _IOW('i', 0x00000016, unsigned int)
++#define LIRC_SET_TRANSMITTER_MASK      _IOW('i', 0x00000017, unsigned int)
++
++/*
++ * when a timeout != 0 is set the driver will send a
++ * LIRC_MODE2_TIMEOUT data packet, otherwise LIRC_MODE2_TIMEOUT is
++ * never sent, timeout is disabled by default
++ */
++#define LIRC_SET_REC_TIMEOUT           _IOW('i', 0x00000018, uint32_t)
++
++/*
++ * pulses shorter than this are filtered out by hardware (software
++ * emulation in lirc_dev?)
++ */
++#define LIRC_SET_REC_FILTER_PULSE      _IOW('i', 0x00000019, uint32_t)
++/*
++ * spaces shorter than this are filtered out by hardware (software
++ * emulation in lirc_dev?)
++ */
++#define LIRC_SET_REC_FILTER_SPACE      _IOW('i', 0x0000001a, uint32_t)
++/*
++ * if filter cannot be set independantly for pulse/space, this should
++ * be used
++ */
++#define LIRC_SET_REC_FILTER            _IOW('i', 0x0000001b, uint32_t)
++
++/*
++ * to set a range use
++ * LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the
++ * lower bound first and later
++ * LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER with the upper bound
++ */
++
++#define LIRC_SET_REC_DUTY_CYCLE_RANGE  _IOW('i', 0x0000001e, unsigned int)
++#define LIRC_SET_REC_CARRIER_RANGE     _IOW('i', 0x0000001f, unsigned int)
++
++#define LIRC_NOTIFY_DECODE             _IO('i', 0x00000020)
++
++/*
++ * from the next key press on the driver will send
++ * LIRC_MODE2_FREQUENCY packets
++ */
++#define LIRC_MEASURE_CARRIER_ENABLE    _IO('i', 0x00000021)
++#define LIRC_MEASURE_CARRIER_DISABLE   _IO('i', 0x00000022)
++
++#endif


More information about the scm-commits mailing list