rpms/kernel/devel kernel.spec, 1.1570, 1.1571 linux-2.6.29-lirc.patch, 1.6, 1.7

Jarod Wilson jwilson at fedoraproject.org
Mon Jun 15 13:53:50 UTC 2009


Author: jwilson

Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv26296

Modified Files:
	kernel.spec linux-2.6.29-lirc.patch 
Log Message:
* Mon Jun 15 2009 Jarod Wilson <jarod at redhat.com>
- Update lirc patches w/new imon hotness



Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.1570
retrieving revision 1.1571
diff -u -p -r1.1570 -r1.1571
--- kernel.spec	12 Jun 2009 21:18:47 -0000	1.1570
+++ kernel.spec	15 Jun 2009 13:53:19 -0000	1.1571
@@ -1827,6 +1827,9 @@ fi
 # and build.
 
 %changelog
+* Mon Jun 15 2009 Jarod Wilson <jarod at redhat.com>
+- Update lirc patches w/new imon hotness
+
 * Fri Jun 12 2009 Chuck Ebbert <cebbert at redhat.com>
 - Update VIA temp sensor and mmc drivers.
 

linux-2.6.29-lirc.patch:

Index: linux-2.6.29-lirc.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6.29-lirc.patch,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -p -r1.6 -r1.7
--- linux-2.6.29-lirc.patch	12 Mar 2009 04:37:05 -0000	1.6
+++ linux-2.6.29-lirc.patch	15 Jun 2009 13:53:19 -0000	1.7
@@ -8,29 +8,29 @@ Signed-off-by: Jarod Wilson <jarod at redha
  MAINTAINERS                           |    9 +
  drivers/input/Kconfig                 |    2 +
  drivers/input/Makefile                |    2 +
- drivers/input/lirc/Kconfig            |  118 +++
+ drivers/input/lirc/Kconfig            |  118 ++
  drivers/input/lirc/Makefile           |   21 +
- drivers/input/lirc/lirc.h             |  100 +++
- drivers/input/lirc/lirc_bt829.c       |  383 +++++++++
- drivers/input/lirc/lirc_dev.c         |  848 +++++++++++++++++++
- drivers/input/lirc/lirc_dev.h         |  180 ++++
- drivers/input/lirc/lirc_i2c.c         |  649 ++++++++++++++
- drivers/input/lirc/lirc_igorplugusb.c |  556 ++++++++++++
- drivers/input/lirc/lirc_imon.c        | 1487 +++++++++++++++++++++++++++++++++
- drivers/input/lirc/lirc_it87.c        |  984 ++++++++++++++++++++++
- drivers/input/lirc/lirc_it87.h        |  116 +++
- drivers/input/lirc/lirc_ite8709.c     |  539 ++++++++++++
- drivers/input/lirc/lirc_mceusb.c      |  749 +++++++++++++++++
- drivers/input/lirc/lirc_mceusb2.c     | 1098 ++++++++++++++++++++++++
- drivers/input/lirc/lirc_parallel.c    |  709 ++++++++++++++++
+ drivers/input/lirc/lirc.h             |  100 ++
+ drivers/input/lirc/lirc_bt829.c       |  383 +++++++
+ drivers/input/lirc/lirc_dev.c         |  849 ++++++++++++++
+ drivers/input/lirc/lirc_dev.h         |  184 ++++
+ drivers/input/lirc/lirc_i2c.c         |  649 +++++++++++
+ drivers/input/lirc/lirc_igorplugusb.c |  556 ++++++++++
+ drivers/input/lirc/lirc_imon.c        | 1941 +++++++++++++++++++++++++++++++++
+ drivers/input/lirc/lirc_it87.c        |  986 +++++++++++++++++
+ drivers/input/lirc/lirc_it87.h        |  116 ++
+ drivers/input/lirc/lirc_ite8709.c     |  539 +++++++++
+ drivers/input/lirc/lirc_mceusb.c      |  749 +++++++++++++
+ drivers/input/lirc/lirc_mceusb2.c     | 1101 +++++++++++++++++++
+ 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      | 1321 +++++++++++++++++++++++++++++
- drivers/input/lirc/lirc_sir.c         | 1294 ++++++++++++++++++++++++++++
- drivers/input/lirc/lirc_streamzap.c   |  777 +++++++++++++++++
- drivers/input/lirc/lirc_ttusbir.c     |  398 +++++++++
- drivers/input/lirc/lirc_zilog.c       | 1382 ++++++++++++++++++++++++++++++
- 25 files changed, 14679 insertions(+), 0 deletions(-)
+ drivers/input/lirc/lirc_sasem.c       |  931 ++++++++++++++++
+ drivers/input/lirc/lirc_serial.c      | 1316 ++++++++++++++++++++++
+ drivers/input/lirc/lirc_sir.c         | 1294 ++++++++++++++++++++++
+ drivers/input/lirc/lirc_streamzap.c   |  777 +++++++++++++
+ drivers/input/lirc/lirc_ttusbir.c     |  397 +++++++
+ drivers/input/lirc/lirc_zilog.c       | 1385 +++++++++++++++++++++++
+ 25 files changed, 15140 insertions(+), 0 deletions(-)
 
 diff --git a/MAINTAINERS b/MAINTAINERS
 index 59fd2d1..ad1b16c 100644
@@ -723,10 +723,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..6829268
+index 0000000..8848d8e
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_dev.c
-@@ -0,0 +1,848 @@
+@@ -0,0 +1,849 @@
 +/*
 + * LIRC base driver
 + *
@@ -979,8 +979,8 @@ index 0000000..6829268
 +		err = -EBADRQC;
 +		goto out;
 +	} else if (!d->rbuf) {
-+		if (!(d->fops && d->fops->read && d->fops->poll)
-+		    || (!d->fops->ioctl)) {
++		if (!(d->fops && d->fops->read && d->fops->poll &&
++		      d->fops->ioctl)) {
 +			printk(KERN_ERR "lirc_dev: lirc_register_driver: "
 +			       "neither read, poll nor ioctl can be NULL!\n");
 +			err = -EBADRQC;
@@ -1182,8 +1182,6 @@ index 0000000..6829268
 +		goto error;
 +	}
 +
-+	lirc_buffer_clear(ir->buf);
-+
 +	if (ir->d.owner != NULL && try_module_get(ir->d.owner)) {
 +		++ir->open;
 +		retval = ir->d.set_use_inc(ir->d.data);
@@ -1191,6 +1189,8 @@ index 0000000..6829268
 +		if (retval) {
 +			module_put(ir->d.owner);
 +			--ir->open;
++		} else {
++			lirc_buffer_clear(ir->buf);
 +		}
 +		if (ir->task)
 +			wake_up_process(ir->task);
@@ -1563,6 +1563,7 @@ index 0000000..6829268
 +static void __exit lirc_dev_exit(void)
 +{
 +	class_destroy(lirc_class);
++	unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES);
 +	dprintk("lirc_dev: module unloaded\n");
 +}
 +
@@ -1577,10 +1578,10 @@ index 0000000..6829268
 +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..41d0d04
+index 0000000..69828a8
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_dev.h
-@@ -0,0 +1,180 @@
+@@ -0,0 +1,184 @@
 +/*
 + * LIRC base driver
 + *
@@ -1722,6 +1723,10 @@ index 0000000..41d0d04
 + * fops:
 + * file_operations for drivers which don't fit the current driver model.
 + *
++ * Some ioctl's can be directly handled by lirc_dev if the driver's
++ * ioctl function is NULL or if it returns -ENOIOCTLCMD (see also
++ * lirc_serial.c).
++ *
 + * owner:
 + * the module owning this struct
 + *
@@ -2980,12 +2985,12 @@ index 0000000..ff49bdd
 +
 diff --git a/drivers/input/lirc/lirc_imon.c b/drivers/input/lirc/lirc_imon.c
 new file mode 100644
-index 0000000..05cb293
+index 0000000..adf2c2f
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_imon.c
-@@ -0,0 +1,1487 @@
+@@ -0,0 +1,1941 @@
 +/*
-+ *   lirc_imon.c:  LIRC/VFD/LCD driver for Ahanix/Soundgraph iMON IR/VFD/LCD
++ *   lirc_imon.c:  LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD
 + *		   including the iMON PAD model
 + *
 + *   Copyright(C) 2004  Venky Raju(dev at venky.ws)
@@ -3012,16 +3017,18 @@ index 0000000..05cb293
 +#include <linux/slab.h>
 +#include <linux/uaccess.h>
 +#include <linux/usb.h>
++#include <linux/usb/input.h>
 +#include <linux/time.h>
++#include <linux/timer.h>
 +
 +#include "lirc.h"
 +#include "lirc_dev.h"
 +
 +
 +#define MOD_AUTHOR	"Venky Raju <dev at venky.ws>"
-+#define MOD_DESC	"Driver for Soundgraph iMON MultiMedia IR/Display"
++#define MOD_DESC	"Driver for SoundGraph iMON MultiMedia IR/Display"
 +#define MOD_NAME	"lirc_imon"
-+#define MOD_VERSION	"0.5"
++#define MOD_VERSION	"0.6"
 +
 +#define DISPLAY_MINOR_BASE	144
 +#define DEVICE_NAME	"lcd%d"
@@ -3037,7 +3044,8 @@ index 0000000..05cb293
 +static int imon_probe(struct usb_interface *interface,
 +		      const struct usb_device_id *id);
 +static void imon_disconnect(struct usb_interface *interface);
-+static void usb_rx_callback(struct urb *urb);
++static void usb_rx_callback_intf0(struct urb *urb);
++static void usb_rx_callback_intf1(struct urb *urb);
 +static void usb_tx_callback(struct urb *urb);
 +
 +/* suspend/resume support */
@@ -3067,22 +3075,28 @@ index 0000000..05cb293
 +/*** G L O B A L S ***/
 +
 +struct imon_context {
-+	struct usb_device *usbdev;
++	struct usb_device *usbdev_intf0;
++	/* Newer devices have two interfaces */
++	struct usb_device *usbdev_intf1;
 +	int display_supported;		/* not all controllers do */
 +	int display_isopen;		/* display port has been opened */
 +	int ir_isopen;			/* IR port open	*/
 +	int ir_isassociating;		/* IR port open for association */
-+	int dev_present;		/* USB device presence */
++	int dev_present_intf0;		/* USB device presence, interface 0 */
++	int dev_present_intf1;		/* USB device presence, interface 1 */
 +	struct mutex lock;		/* to lock this object */
 +	wait_queue_head_t remove_ok;	/* For unexpected USB disconnects */
 +
++	int has_touchscreen;		/* touchscreen present? */
 +	int display_proto_6p;		/* display requires 6th packet */
 +	int ir_onboard_decode;		/* IR signals decoded onboard */
 +
 +	struct lirc_driver *driver;
-+	struct usb_endpoint_descriptor *rx_endpoint;
++	struct usb_endpoint_descriptor *rx_endpoint_intf0;
++	struct usb_endpoint_descriptor *rx_endpoint_intf1;
 +	struct usb_endpoint_descriptor *tx_endpoint;
-+	struct urb *rx_urb;
++	struct urb *rx_urb_intf0;
++	struct urb *rx_urb_intf1;
 +	struct urb *tx_urb;
 +	int tx_control;
 +	unsigned char usb_rx_buf[8];
@@ -3100,8 +3114,19 @@ index 0000000..05cb293
 +		atomic_t busy;			/* write in progress */
 +		int status;			/* status of tx completion */
 +	} tx;
++
++	struct input_dev *mouse;	/* input device for iMON PAD remote */
++	struct input_dev *touch;	/* input device for touchscreen */
++	int is_mouse;			/* toggle between mouse/remote mode */
++	int touch_x;			/* x coordinate on touchscreen */
++	int touch_y;			/* y coordinate on touchscreen */
++	char name[128];
++	char phys[64];
++	struct timer_list timer;
 +};
 +
++#define TOUCH_TIMEOUT	(HZ/30)
++
 +/* display file operations. Nb: lcd_write will be subbed in as needed later */
 +static struct file_operations display_fops = {
 +	.owner		= THIS_MODULE,
@@ -3117,24 +3142,68 @@ index 0000000..05cb293
 +	IMON_DISPLAY_TYPE_NONE,
 +};
 +
-+/* USB Device ID for iMON USB Control Board */
++/*
++ * USB Device ID for iMON USB Control Boards
++ *
++ * The Windows drivers contain 6 different inf files, more or less one for
++ * each new device until the 0x0034-0x0046 devices, which all use the same
++ * driver. Some of the devices in the 34-46 range haven't been definitively
++ * identified yet. Early devices have either a TriGem Computer, Inc. or a
++ * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later
++ * devices use the SoundGraph vendor ID (0x15c2).
++ */
 +static struct usb_device_id imon_usb_id_table[] = {
-+	/* iMON USB Control Board (IR & VFD) */
-+	{ USB_DEVICE(0x0aa8, 0xffda) },
-+	/* iMON USB Control Board (IR only) */
++	/* TriGem iMON (IR only) -- TG_iMON.inf */
 +	{ USB_DEVICE(0x0aa8, 0x8001) },
-+	/* iMON USB Control Board (ext IR only) */
++
++	/* SoundGraph iMON (IR only) -- sg_imon.inf */
 +	{ USB_DEVICE(0x04e8, 0xff30) },
-+	/* iMON USB Control Board (IR & VFD) */
++
++	/* SoundGraph iMON VFD (IR & VFD) -- iMON_VFD.inf */
++	{ USB_DEVICE(0x0aa8, 0xffda) },
++
++	/* SoundGraph iMON SS (IR & VFD) -- iMON_SS.inf */
 +	{ USB_DEVICE(0x15c2, 0xffda) },
-+	/* iMON USB Control Board (IR & LCD) *and* iMON Knob (IR only) */
++
++	/*
++	 * Several devices with this same device ID, all use iMON_PAD.inf
++	 * SoundGraph iMON PAD (IR & VFD)
++	 * SoundGraph iMON PAD (IR & LCD)
++	 * SoundGraph iMON Knob (IR only)
++	 */
 +	{ USB_DEVICE(0x15c2, 0xffdc) },
-+	/* iMON USB Control Board (IR & LCD) */
++
++	/*
++	 * Newer devices, all driven by the latest iMON Windows driver, full
++	 * list of device IDs extracted via 'strings Setup/data1.hdr |grep 15c2'
++	 * Need user input to fill in details on unknown devices.
++	 */
++	/* SoundGraph iMON OEM Touch LCD (IR & 7" VGA LCD) */
 +	{ USB_DEVICE(0x15c2, 0x0034) },
-+	/* iMON USB Control Board (IR & VFD) */
++	/* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */
++	{ USB_DEVICE(0x15c2, 0x0035) },
++	/* SoundGraph iMON OEM VFD (IR & VFD) */
 +	{ USB_DEVICE(0x15c2, 0x0036) },
-+	/* iMON USB Control Board (IR & LCD) */
++	/* device specifics unknown */
++	{ USB_DEVICE(0x15c2, 0x0037) },
++	/* SoundGraph iMON OEM LCD (IR & LCD) */
 +	{ USB_DEVICE(0x15c2, 0x0038) },
++	/* device specifics unknown */
++	{ USB_DEVICE(0x15c2, 0x0039) },
++	/* device specifics unknown */
++	{ USB_DEVICE(0x15c2, 0x003a) },
++	/* device specifics unknown */
++	{ USB_DEVICE(0x15c2, 0x003b) },
++	/* SoundGraph iMON OEM Inside (IR only) */
++	{ USB_DEVICE(0x15c2, 0x003c) },
++	/* device specifics unknown */
++	{ USB_DEVICE(0x15c2, 0x003d) },
++	/* device specifics unknown */
++	{ USB_DEVICE(0x15c2, 0x003e) },
++	/* device specifics unknown */
++	{ USB_DEVICE(0x15c2, 0x003f) },
++	/* device specifics unknown */
++	{ USB_DEVICE(0x15c2, 0x0040) },
 +	/* SoundGraph iMON MINI (IR only) */
 +	{ USB_DEVICE(0x15c2, 0x0041) },
 +	/* Antec Veris Multimedia Station EZ External (IR only) */
@@ -3145,6 +3214,8 @@ index 0000000..05cb293
 +	{ USB_DEVICE(0x15c2, 0x0044) },
 +	/* Antec Veris Multimedia Station Premiere (IR & LCD) */
 +	{ USB_DEVICE(0x15c2, 0x0045) },
++	/* device specifics unknown */
++	{ USB_DEVICE(0x15c2, 0x0046) },
 +	{}
 +};
 +
@@ -3153,13 +3224,24 @@ index 0000000..05cb293
 +	{ USB_DEVICE(0x15c2, 0xffda) },
 +	{ USB_DEVICE(0x15c2, 0xffdc) },
 +	{ USB_DEVICE(0x15c2, 0x0034) },
++	{ USB_DEVICE(0x15c2, 0x0035) },
 +	{ USB_DEVICE(0x15c2, 0x0036) },
++	{ USB_DEVICE(0x15c2, 0x0037) },
 +	{ USB_DEVICE(0x15c2, 0x0038) },
++	{ USB_DEVICE(0x15c2, 0x0039) },
++	{ USB_DEVICE(0x15c2, 0x003a) },
++	{ USB_DEVICE(0x15c2, 0x003b) },
++	{ USB_DEVICE(0x15c2, 0x003c) },
++	{ USB_DEVICE(0x15c2, 0x003d) },
++	{ USB_DEVICE(0x15c2, 0x003e) },
++	{ USB_DEVICE(0x15c2, 0x003f) },
++	{ USB_DEVICE(0x15c2, 0x0040) },
 +	{ USB_DEVICE(0x15c2, 0x0041) },
 +	{ USB_DEVICE(0x15c2, 0x0042) },
 +	{ USB_DEVICE(0x15c2, 0x0043) },
 +	{ USB_DEVICE(0x15c2, 0x0044) },
 +	{ USB_DEVICE(0x15c2, 0x0045) },
++	{ USB_DEVICE(0x15c2, 0x0046) },
 +	{}
 +};
 +static unsigned char display_packet6[] = {
@@ -3168,27 +3250,39 @@ index 0000000..05cb293
 +/* newer iMON models use control endpoints */
 +static struct usb_device_id ctl_ep_device_list[] = {
 +	{ USB_DEVICE(0x15c2, 0x0034) },
++	{ USB_DEVICE(0x15c2, 0x0035) },
 +	{ USB_DEVICE(0x15c2, 0x0036) },
++	{ USB_DEVICE(0x15c2, 0x0037) },
 +	{ USB_DEVICE(0x15c2, 0x0038) },
++	{ USB_DEVICE(0x15c2, 0x0039) },
++	{ USB_DEVICE(0x15c2, 0x003a) },
++	{ USB_DEVICE(0x15c2, 0x003b) },
++	{ USB_DEVICE(0x15c2, 0x003c) },
++	{ USB_DEVICE(0x15c2, 0x003d) },
++	{ USB_DEVICE(0x15c2, 0x003e) },
++	{ USB_DEVICE(0x15c2, 0x003f) },
++	{ USB_DEVICE(0x15c2, 0x0040) },
 +	{ USB_DEVICE(0x15c2, 0x0041) },
 +	{ USB_DEVICE(0x15c2, 0x0042) },
 +	{ USB_DEVICE(0x15c2, 0x0043) },
 +	{ USB_DEVICE(0x15c2, 0x0044) },
 +	{ USB_DEVICE(0x15c2, 0x0045) },
++	{ USB_DEVICE(0x15c2, 0x0046) },
 +	{}
 +};
 +
 +/* iMON LCD models user a different write op */
 +static struct usb_device_id lcd_device_list[] = {
 +	{ USB_DEVICE(0x15c2, 0xffdc) },
-+	{ USB_DEVICE(0x15c2, 0x0034) },
 +	{ USB_DEVICE(0x15c2, 0x0038) },
 +	{ USB_DEVICE(0x15c2, 0x0045) },
 +	{}
 +};
 +
-+/* iMON devices with front panel buttons need a larger buffer */
++/* iMON devices with front panel buttons or touchscreen need a larger buffer */
 +static struct usb_device_id large_buffer_list[] = {
++	{ USB_DEVICE(0x15c2, 0x0034) },
++	{ USB_DEVICE(0x15c2, 0x0035) },
 +	{ USB_DEVICE(0x15c2, 0x0038) },
 +	{ USB_DEVICE(0x15c2, 0x0045) },
 +};
@@ -3197,13 +3291,24 @@ index 0000000..05cb293
 +static struct usb_device_id ir_onboard_decode_list[] = {
 +	{ USB_DEVICE(0x15c2, 0xffdc) },
 +	{ USB_DEVICE(0x15c2, 0x0034) },
++	{ USB_DEVICE(0x15c2, 0x0035) },
 +	{ USB_DEVICE(0x15c2, 0x0036) },
++	{ USB_DEVICE(0x15c2, 0x0037) },
 +	{ USB_DEVICE(0x15c2, 0x0038) },
++	{ USB_DEVICE(0x15c2, 0x0039) },
++	{ USB_DEVICE(0x15c2, 0x003a) },
++	{ USB_DEVICE(0x15c2, 0x003b) },
++	{ USB_DEVICE(0x15c2, 0x003c) },
++	{ USB_DEVICE(0x15c2, 0x003d) },
++	{ USB_DEVICE(0x15c2, 0x003e) },
++	{ USB_DEVICE(0x15c2, 0x003f) },
++	{ USB_DEVICE(0x15c2, 0x0040) },
 +	{ USB_DEVICE(0x15c2, 0x0041) },
 +	{ USB_DEVICE(0x15c2, 0x0042) },
 +	{ USB_DEVICE(0x15c2, 0x0043) },
 +	{ USB_DEVICE(0x15c2, 0x0044) },
 +	{ USB_DEVICE(0x15c2, 0x0045) },
++	{ USB_DEVICE(0x15c2, 0x0046) },
 +	{}
 +};
 +
@@ -3213,12 +3318,20 @@ index 0000000..05cb293
 +	{ USB_DEVICE(0x04e8, 0xff30) },
 +	/* the first imon lcd and the knob share this device id. :\ */
 +	/*{ USB_DEVICE(0x15c2, 0xffdc) },*/
++	{ USB_DEVICE(0x15c2, 0x003c) },
 +	{ USB_DEVICE(0x15c2, 0x0041) },
 +	{ USB_DEVICE(0x15c2, 0x0042) },
 +	{ USB_DEVICE(0x15c2, 0x0043) },
 +	{}
 +};
 +
++/* iMON devices with VGA touchscreens */
++static struct usb_device_id imon_touchscreen_list[] = {
++	{ USB_DEVICE(0x15c2, 0x0034) },
++	{ USB_DEVICE(0x15c2, 0x0035) },
++	{}
++};
++
 +/* USB Device data */
 +static struct usb_driver imon_driver = {
 +	.name		= MOD_NAME,
@@ -3235,8 +3348,8 @@ index 0000000..05cb293
 +	.minor_base	= DISPLAY_MINOR_BASE,
 +};
 +
-+/* to prevent races between open() and disconnect() */
-+static DEFINE_MUTEX(disconnect_lock);
++/* to prevent races between open() and disconnect(), probing, etc */
++static DEFINE_MUTEX(driver_lock);
 +
 +static int debug;
 +
@@ -3257,18 +3370,19 @@ index 0000000..05cb293
 +MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, "
 +		 "1=vfd, 2=lcd, 3=none (default: autodetect)");
 +
-+static void delete_context(struct imon_context *context)
++static void free_imon_context(struct imon_context *context)
 +{
 +	if (context->display_supported)
 +		usb_free_urb(context->tx_urb);
-+	usb_free_urb(context->rx_urb);
++	usb_free_urb(context->rx_urb_intf0);
++	usb_free_urb(context->rx_urb_intf1);
 +	lirc_buffer_free(context->driver->rbuf);
 +	kfree(context->driver->rbuf);
 +	kfree(context->driver);
 +	kfree(context);
 +
 +	if (debug)
-+		printk(KERN_INFO "%s: context deleted\n", __func__);
++		printk(KERN_INFO "%s: iMON context freed\n", __func__);
 +}
 +
 +static void deregister_from_lirc(struct imon_context *context)
@@ -3281,7 +3395,8 @@ index 0000000..05cb293
 +		err("%s: unable to deregister from lirc(%d)",
 +			__func__, retval);
 +	else
-+		printk(KERN_INFO "Deregistered iMON driver(minor:%d)\n", minor);
++		printk(KERN_INFO MOD_NAME ": Deregistered iMON driver "
++		       "(minor:%d)\n", minor);
 +
 +}
 +
@@ -3297,7 +3412,7 @@ index 0000000..05cb293
 +	int retval = 0;
 +
 +	/* prevent races with disconnect */
-+	mutex_lock(&disconnect_lock);
++	mutex_lock(&driver_lock);
 +
 +	subminor = iminor(inode);
 +	interface = usb_find_interface(&imon_driver, subminor);
@@ -3333,7 +3448,7 @@ index 0000000..05cb293
 +	mutex_unlock(&context->lock);
 +
 +exit:
-+	mutex_unlock(&disconnect_lock);
++	mutex_unlock(&driver_lock);
 +	return retval;
 +}
 +
@@ -3346,7 +3461,7 @@ index 0000000..05cb293
 +	struct imon_context *context = NULL;
 +	int retval = 0;
 +
-+	context = (struct imon_context *) file->private_data;
++	context = (struct imon_context *)file->private_data;
 +
 +	if (!context) {
 +		err("%s: no context for device", __func__);
@@ -3364,14 +3479,14 @@ index 0000000..05cb293
 +	} else {
 +		context->display_isopen = 0;
 +		printk(KERN_INFO "display port closed\n");
-+		if (!context->dev_present && !context->ir_isopen) {
++		if (!context->dev_present_intf0 && !context->ir_isopen) {
 +			/*
 +			 * Device disconnected before close and IR port is not
 +			 * open. If IR port is open, context will be deleted by
 +			 * ir_close.
 +			 */
 +			mutex_unlock(&context->lock);
-+			delete_context(context);
++			free_imon_context(context);
 +			return retval;
 +		}
 +	}
@@ -3381,7 +3496,7 @@ index 0000000..05cb293
 +}
 +
 +/**
-+ * Sends a packet to the display.
++ * Sends a packet to the device
 + */
 +static int send_packet(struct imon_context *context)
 +{
@@ -3392,11 +3507,11 @@ index 0000000..05cb293
 +
 +	/* Check if we need to use control or interrupt urb */
 +	if (!context->tx_control) {
-+		pipe = usb_sndintpipe(context->usbdev,
++		pipe = usb_sndintpipe(context->usbdev_intf0,
 +				      context->tx_endpoint->bEndpointAddress);
 +		interval = context->tx_endpoint->bInterval;
 +
-+		usb_fill_int_urb(context->tx_urb, context->usbdev, pipe,
++		usb_fill_int_urb(context->tx_urb, context->usbdev_intf0, pipe,
 +				 context->usb_tx_buf,
 +				 sizeof(context->usb_tx_buf),
 +				 usb_tx_callback, context, interval);
@@ -3417,10 +3532,10 @@ index 0000000..05cb293
 +		control_req->wLength = cpu_to_le16(0x0008);
 +
 +		/* control pipe is endpoint 0x00 */
-+		pipe = usb_sndctrlpipe(context->usbdev, 0);
++		pipe = usb_sndctrlpipe(context->usbdev_intf0, 0);
 +
 +		/* build the control urb */
-+		usb_fill_control_urb(context->tx_urb, context->usbdev, pipe,
++		usb_fill_control_urb(context->tx_urb, context->usbdev_intf0, pipe,
 +				     (unsigned char *)control_req,
 +				     context->usb_tx_buf,
 +				     sizeof(context->usb_tx_buf),
@@ -3475,7 +3590,7 @@ index 0000000..05cb293
 +
 +	mutex_lock(&context->lock);
 +
-+	if (!context->dev_present) {
++	if (!context->dev_present_intf0) {
 +		err("%s: no iMON device present", __func__);
 +		retval = -ENODEV;
 +		goto exit;
@@ -3493,7 +3608,6 @@ index 0000000..05cb293
 +/**
 + * These are the sysfs functions to handle the association on the iMON 2.4G LT.
 + */
-+
 +static ssize_t show_associate_remote(struct device *d,
 +				     struct device_attribute *attr,
 +				     char *buf)
@@ -3556,9 +3670,6 @@ index 0000000..05cb293
 +	.attrs = imon_sysfs_entries
 +};
 +
-+
-+
-+
 +/**
 + * Writes data to the VFD.  The iMON VFD is 2x16 characters
 + * and requires data in 5 consecutive USB interrupt packets,
@@ -3579,7 +3690,7 @@ index 0000000..05cb293
 +	int retval = 0;
 +	struct imon_context *context;
 +
-+	context = (struct imon_context *) file->private_data;
++	context = (struct imon_context *)file->private_data;
 +	if (!context) {
 +		err("%s: no context for device", __func__);
 +		return -ENODEV;
@@ -3587,7 +3698,7 @@ index 0000000..05cb293
 +
 +	mutex_lock(&context->lock);
 +
-+	if (!context->dev_present) {
++	if (!context->dev_present_intf0) {
 +		err("%s: no iMON device present", __func__);
 +		retval = -ENODEV;
 +		goto exit;
@@ -3665,7 +3776,7 @@ index 0000000..05cb293
 +	int retval = 0;
 +	struct imon_context *context;
 +
-+	context = (struct imon_context *) file->private_data;
++	context = (struct imon_context *)file->private_data;
 +	if (!context) {
 +		err("%s: no context for device", __func__);
 +		return -ENODEV;
@@ -3673,8 +3784,8 @@ index 0000000..05cb293
 +
 +	mutex_lock(&context->lock);
 +
-+	if (!context->dev_present) {
-+		err("%s: no iMON device present", __func__);
++	if (!context->display_supported) {
++		err("%s: no iMON display present", __func__);
 +		retval = -ENODEV;
 +		goto exit;
 +	}
@@ -3713,7 +3824,7 @@ index 0000000..05cb293
 +
 +	if (!urb)
 +		return;
-+	context = (struct imon_context *) urb->context;
++	context = (struct imon_context *)urb->context;
 +	if (!context)
 +		return;
 +
@@ -3735,32 +3846,52 @@ index 0000000..05cb293
 +	struct imon_context *context;
 +
 +	/* prevent races with disconnect */
-+	mutex_lock(&disconnect_lock);
++	mutex_lock(&driver_lock);
 +
-+	context = (struct imon_context *) data;
++	context = (struct imon_context *)data;
 +
 +	/* initial IR protocol decode variables */
 +	context->rx.count = 0;
 +	context->rx.initial_space = 1;
 +	context->rx.prev_bit = 0;
 +
-+	usb_fill_int_urb(context->rx_urb, context->usbdev,
-+		usb_rcvintpipe(context->usbdev,
-+				context->rx_endpoint->bEndpointAddress),
++	usb_fill_int_urb(context->rx_urb_intf0, context->usbdev_intf0,
++		usb_rcvintpipe(context->usbdev_intf0,
++				context->rx_endpoint_intf0->bEndpointAddress),
 +		context->usb_rx_buf, sizeof(context->usb_rx_buf),
-+		usb_rx_callback, context, context->rx_endpoint->bInterval);
++		usb_rx_callback_intf0, context,
++		context->rx_endpoint_intf0->bInterval);
 +
-+	retval = usb_submit_urb(context->rx_urb, GFP_KERNEL);
++	retval = usb_submit_urb(context->rx_urb_intf0, GFP_KERNEL);
 +
-+	if (retval)
-+		err("%s: usb_submit_urb failed for ir_open(%d)",
++	if (retval) {
++		err("%s: usb_submit_urb failed for intf0 (%d)",
 +		    __func__, retval);
-+	else {
-+		context->ir_isopen = 1;
-+		printk(KERN_INFO "IR port opened\n");
++		goto out;
 +	}
 +
-+	mutex_unlock(&disconnect_lock);
++	if (context->dev_present_intf1) {
++		usb_fill_int_urb(context->rx_urb_intf1, context->usbdev_intf1,
++			usb_rcvintpipe(context->usbdev_intf1,
++				context->rx_endpoint_intf1->bEndpointAddress),
++			context->usb_rx_buf, sizeof(context->usb_rx_buf),
++			usb_rx_callback_intf1, context,
++			context->rx_endpoint_intf1->bInterval);
++
++		retval = usb_submit_urb(context->rx_urb_intf1, GFP_KERNEL);
++
++		if (retval) {
++			err("%s: usb_submit_urb failed for intf1 (%d)",
++			    __func__, retval);
++			goto out;
++		}
++	}
++
++	context->ir_isopen = 1;
++	printk(KERN_INFO MOD_NAME ": IR port opened\n");
++
++out:
++	mutex_unlock(&driver_lock);
 +	return retval;
 +}
 +
@@ -3779,12 +3910,14 @@ index 0000000..05cb293
 +
 +	mutex_lock(&context->lock);
 +
-+	usb_kill_urb(context->rx_urb);
++	usb_kill_urb(context->rx_urb_intf0);
++	if (context->dev_present_intf1)
++		usb_kill_urb(context->rx_urb_intf1);
 +	context->ir_isopen = 0;
 +	context->ir_isassociating = 0;
-+	printk(KERN_INFO "IR port closed\n");
++	printk(KERN_INFO MOD_NAME ": IR port closed\n");
 +
-+	if (!context->dev_present) {
++	if (!context->dev_present_intf0) {
 +		/*
 +		 * Device disconnected while IR port was still open. Driver
 +		 * was not deregistered at disconnect time, so do it now.
@@ -3793,7 +3926,7 @@ index 0000000..05cb293
 +
 +		if (!context->display_isopen) {
 +			mutex_unlock(&context->lock);
-+			delete_context(context);
++			free_imon_context(context);
 +			return;
 +		}
 +		/*
@@ -3807,7 +3940,7 @@ index 0000000..05cb293
 +}
 +
 +/**
-+ * Convert bit count to time duration(in us) and submit
++ * Convert bit count to time duration (in us) and submit
 + * the value to lirc_dev.
 + */
 +static void submit_data(struct imon_context *context)
@@ -3817,7 +3950,7 @@ index 0000000..05cb293
 +	int i;
 +
 +	if (debug)
-+		printk(KERN_INFO "submitting data to LIRC\n");
++		printk(KERN_INFO MOD_NAME ": submitting data to LIRC\n");
 +
 +	value *= BIT_DURATION;
 +	value &= PULSE_MASK;
@@ -3931,14 +4064,16 @@ index 0000000..05cb293
 +/**
 + * Process the incoming packet
 + */
-+static void incoming_packet(struct imon_context *context,
-+			    struct urb *urb)
++static void imon_incoming_lirc_packet(struct imon_context *context,
++				      struct urb *urb, int intf)
 +{
 +	int len = urb->actual_length;
 +	unsigned char *buf = urb->transfer_buffer;
++	char rel_x, rel_y;
 +	int octet, bit;
 +	unsigned char mask;
 +	int i, chunk_num, dir;
++	int ts_input = 0;
 +
 +	/*
 +	 * we need to add some special handling for
@@ -3948,6 +4083,8 @@ index 0000000..05cb293
 +		/* first, pad to 8 bytes so it conforms with everything else */
 +		buf[5] = buf[6] = buf[7] = 0;
 +		len = 8;
++		rel_x = buf[2];
++		rel_y = buf[3];
 +
 +		/*
 +		 * the imon directional pad functions more like a touchpad.
@@ -3959,18 +4096,69 @@ index 0000000..05cb293
 +		 * 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))) {
-+			dir = stabilize((int)(char)buf[2], (int)(char)buf[3]);
++		if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
++			dir = stabilize((int)rel_x, (int)rel_y);
 +			if (!dir)
 +				return;
 +			buf[2] = dir & 0xFF;
 +			buf[3] = (dir >> 8) & 0xFF;
 +		}
++
++	} else if ((len == 8) && (buf[0] & 0x40) &&
++		   !(buf[1] & 0x01 || buf[1] >> 2 & 0x01)) {
++		/*
++		 * Handle on-board decoded pad events for e.g. older
++		 * VFD/iMON-Pad (15c2:ffdc). The remote generates various codes
++		 * from 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button
++		 * generates 0x688301b7 and the right one 0x688481b7. All other
++		 * keys generate 0x2nnnnnnn. Length has been padded to 8
++		 * already, position coordinate is encoded in buf[1] and buf[2]
++		 * with reversed endianess. Extract direction from buffer,
++		 * rotate endianess, adjust sign and feed the values into
++		 * stabilize(). The resulting codes will be 0x01008000,
++		 * 0x01007F00, ..., so one can use the normal imon-pad config
++		 * from the remotes dir.
++		 */
++
++		/* buf[1] is x */
++		rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
++			(buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
++		if(buf[0] & 0x02)
++			rel_x |= ~0x10+1;
++		/* buf[2] is y */
++		rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 |
++			(buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
++		if(buf[0] & 0x01)
++			rel_y |= ~0x10+1;
++
++		buf[0] = 0x01;
++		buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0;
++
++		dir = stabilize((int)rel_x, (int)rel_y);
++		if (!dir)
++			return;
++		buf[2] = dir & 0xFF;
++		buf[3] = (dir >> 8) & 0xFF;
++
++	} else if (buf[6] == 0x14 && buf[7] == 0x86 && intf == 1) {
++		/*
++		 * this is touchscreen input, which we need to down-sample
++		 * to a 64 button matrix at the moment...
++		 */
++		buf[0] = buf[0] >> 5;
++		buf[1] = 0x00;
++		buf[2] = buf[2] >> 5;
++		buf[3] = 0x00;
++		buf[4] = 0x00;
++		buf[5] = 0x00;
++		buf[6] = 0x14;
++		buf[7] = 0xff;
++		ts_input = 1;
 +	}
 +
 +	if (len != 8) {
-+		printk(KERN_WARNING "%s: invalid incoming packet size(%d)\n",
-+		     __func__, len);
++		printk(KERN_WARNING "imon %s: invalid incoming packet "
++		       "size (len = %d, intf%d)\n", __func__, len, intf);
 +		return;
 +	}
 +
@@ -3989,7 +4177,7 @@ index 0000000..05cb293
 +
 +	chunk_num = buf[7];
 +
-+	if (chunk_num == 0xFF)
++	if (chunk_num == 0xFF && !ts_input)
 +		return;		/* filler frame, no data here */
 +
 +	if (buf[0] == 0xFF &&
@@ -4004,7 +4192,7 @@ index 0000000..05cb293
 +
 +	if (debug) {
 +		if (context->ir_onboard_decode)
-+			printk("decoded packet: ");
++			printk("intf%d decoded packet: ", intf);
 +		else
 +			printk("raw packet: ");
 +		for (i = 0; i < len; ++i)
@@ -4067,36 +4255,149 @@ index 0000000..05cb293
 +}
 +
 +/**
++ * report touchscreen input
++ */
++static void imon_touch_display_timeout(unsigned long data)
++{
++	struct imon_context *context = (struct imon_context *)data;
++	struct input_dev *touch;
++
++	if (!context->has_touchscreen)
++		return;
++
++	touch = context->touch;
++	input_report_abs(touch, ABS_X, context->touch_x);
++	input_report_abs(touch, ABS_Y, context->touch_y);
++	input_report_key(touch, BTN_TOUCH, 0x00);
++	input_sync(touch);
++
++	return;
++}
++
++/**
 + * Callback function for USB core API: receive data
 + */
-+static void usb_rx_callback(struct urb *urb)
++static void usb_rx_callback_intf0(struct urb *urb)
 +{
 +	struct imon_context *context;
++	struct input_dev *mouse = NULL;
++	unsigned char *buf;
++	int len;
++	int intfnum = 0;
++	char rel_x, rel_y;
 +
 +	if (!urb)
 +		return;
-+	context = (struct imon_context *) urb->context;
++
++	context = (struct imon_context *)urb->context;
 +	if (!context)
 +		return;
 +
++	buf = urb->transfer_buffer;
++	len = urb->actual_length;
++
++	mouse = context->mouse;
++	if (!context->mouse)
++		return;
++
 +	switch (urb->status) {
 +	case -ENOENT:		/* usbcore unlink successful! */
 +		return;
++
 +	case 0:
-+		if (context->ir_isopen)
-+			incoming_packet(context, urb);
++		/* if we're in mouse mode, send input events */
++		if (context->is_mouse && buf[0] & 0x01) {
++			if (debug)
++				printk(KERN_INFO MOD_NAME ": sending mouse "
++				       "data via input subsystem\n");
++			input_report_key(mouse, BTN_LEFT, buf[1] & 0x01);
++			input_report_key(mouse, BTN_RIGHT, buf[1] >> 2 & 0x01);
++			rel_x = buf[2];
++			rel_y = buf[3];
++			input_report_rel(mouse, REL_X, rel_x);
++			input_report_rel(mouse, REL_Y, rel_y);
++			input_sync(mouse);
++		/* otherwise, we're in IR mode, process lirc packets */
++		} else if (context->ir_isopen)
++			imon_incoming_lirc_packet(context, urb, intfnum);
 +		break;
++
 +	default:
-+		printk(KERN_WARNING "%s: status(%d): ignored\n",
++		printk(KERN_WARNING "imon %s: status(%d): ignored\n",
 +		       __func__, urb->status);
 +		break;
 +	}
 +
-+	usb_submit_urb(context->rx_urb, GFP_ATOMIC);
++	usb_submit_urb(context->rx_urb_intf0, GFP_ATOMIC);
++
 +	return;
 +}
 +
++static void usb_rx_callback_intf1(struct urb *urb)
++{
++	struct imon_context *context;
++	unsigned char *buf;
++	int len;
++	struct input_dev *touch = NULL;
++	int intfnum = 1;
++	static unsigned char toggle_button[] = { 0x29, 0x91, 0x15, 0xb7 };
++
++	if (!urb)
++		return;
++
++	context = (struct imon_context *)urb->context;
++	if (!context)
++		return;
++
++	buf = urb->transfer_buffer;
++	len = urb->actual_length;
++
++	if (context->has_touchscreen) {
++		touch = context->touch;
++		if (!context->touch)
++			return;
++	}
++
++	switch (urb->status) {
++	case -ENOENT:		/* usbcore unlink successful! */
++		return;
 +
++	case 0:
++		/* keyboard/mouse mode toggle button */
++		if (memcmp(buf, toggle_button, 4) == 0) {
++			if (debug)
++				printk(KERN_INFO MOD_NAME ": toggling "
++				       "keyboard/mouse mode (%d)\n",
++				       context->is_mouse);
++			context->is_mouse = ~(context->is_mouse) & 0x1;
++			break;
++		}
++		/* handle touchscreen input */
++		if (context->has_touchscreen &&
++		    buf[6] == 0x14 && buf[7] == 0x86) {
++			mod_timer(&context->timer, jiffies + TOUCH_TIMEOUT);
++			context->touch_x = (buf[0] << 4) | (buf[1] >> 4);
++			context->touch_y = 0xfff - ((buf[2] << 4) |
++					   (buf[1] & 0xf));
++			input_report_abs(touch, ABS_X, context->touch_x);
++			input_report_abs(touch, ABS_Y, context->touch_y);
++			input_report_key(touch, BTN_TOUCH, 0x01);
++			input_sync(touch);
++		/* otherwise, process lirc packets */
++		} else if (context->ir_isopen)
++			imon_incoming_lirc_packet(context, urb, intfnum);
++		break;
++
++	default:
++		printk(KERN_WARNING "imon %s: status(%d): ignored\n",
++		       __func__, urb->status);
++		break;
++	}
++
++	usb_submit_urb(context->rx_urb_intf1, GFP_ATOMIC);
++
++	return;
++}
 +
 +/**
 + * Callback function for USB core API: Probe
@@ -4112,21 +4413,26 @@ index 0000000..05cb293
 +	struct urb *tx_urb = NULL;
 +	struct lirc_driver *driver = NULL;
 +	struct lirc_buffer *rbuf = NULL;
++	struct usb_interface *first_if;
++	int ifnum;
 +	int lirc_minor = 0;
 +	int num_endpts;
 +	int retval = 0;
 +	int display_ep_found = 0;
 +	int ir_ep_found = 0;
-+	int alloc_status;
++	int alloc_status = 0;
 +	int display_proto_6p = 0;
 +	int ir_onboard_decode = 0;
++	int has_touchscreen = 0;
 +	int buf_chunk_size = BUF_CHUNK_SIZE;
 +	int code_length;
 +	int tx_control = 0;
 +	struct imon_context *context = NULL;
++	struct imon_context *first_if_context = NULL;
 +	int i;
-+
-+	printk(KERN_INFO "%s: found iMON device\n", __func__);
++	u16 vendor, product;
++	static unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
++					     0x00, 0x00, 0x00, 0x88 };
 +
 +	/*
 +	 * If it's the LCD, as opposed to the VFD, we just need to replace
@@ -4146,9 +4452,22 @@ index 0000000..05cb293
 +
 +	code_length = buf_chunk_size * 8;
 +
-+	usbdev = usb_get_dev(interface_to_usbdev(interface));
++	usbdev     = usb_get_dev(interface_to_usbdev(interface));
 +	iface_desc = interface->cur_altsetting;
 +	num_endpts = iface_desc->desc.bNumEndpoints;
++	ifnum      = iface_desc->desc.bInterfaceNumber;
++	vendor     = le16_to_cpu(usbdev->descriptor.idVendor);
++	product    = le16_to_cpu(usbdev->descriptor.idProduct);
++
++	if (debug)
++		printk(KERN_INFO "%s: found iMON device (%04x:%04x, intf%d)\n",
++		       __func__, vendor, product, ifnum);
++
++	/* 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:
@@ -4214,6 +4533,19 @@ index 0000000..05cb293
 +			       __func__);
 +	}
 +
++	/*
++	 * iMON Touch devices have a VGA touchscreen, but no "display", as
++	 * that refers to e.g. /dev/lcd0 (a character device LCD or VFD).
++	 */
++	if (usb_match_id(interface, imon_touchscreen_list)) {
++		tx_control = 0;
++		display_ep_found = 0;
++		has_touchscreen = 1;
++		if (debug)
++			printk(KERN_INFO "%s: iMON Touch device found\n",
++			       __func__);
++	}
++
 +	/* Input endpoint is mandatory */
 +	if (!ir_ep_found) {
 +		err("%s: no valid input (IR) endpoint found.", __func__);
@@ -4225,8 +4557,8 @@ index 0000000..05cb293
 +			ir_onboard_decode = 1;
 +
 +		if (debug)
-+			printk(KERN_INFO "ir_onboard_decode: %d\n",
-+			       ir_onboard_decode);
++			printk(KERN_INFO "%s: ir_onboard_decode: %d\n",
++			       __func__, ir_onboard_decode);
 +	}
 +
 +	/* Determine if display requires 6 packets */
@@ -4235,98 +4567,193 @@ index 0000000..05cb293
 +			display_proto_6p = 1;
 +
 +		if (debug)
-+			printk(KERN_INFO "display_proto_6p: %d\n",
-+			       display_proto_6p);
++			printk(KERN_INFO "%s: display_proto_6p: %d\n",
++			       __func__, display_proto_6p);
 +	}
 +
-+	alloc_status = 0;
-+
-+	context = kzalloc(sizeof(struct imon_context), GFP_KERNEL);
-+	if (!context) {
-+		err("%s: kzalloc failed for context", __func__);
-+		alloc_status = 1;
-+		goto alloc_status_switch;
-+	}
-+	driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
-+	if (!driver) {
-+		err("%s: kzalloc failed for lirc_driver", __func__);
-+		alloc_status = 2;
-+		goto alloc_status_switch;
-+	}
-+	rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
-+	if (!rbuf) {
-+		err("%s: kmalloc failed for lirc_buffer", __func__);
-+		alloc_status = 3;
-+		goto alloc_status_switch;
-+	}
-+	if (lirc_buffer_init(rbuf, buf_chunk_size, BUF_SIZE)) {
-+		err("%s: lirc_buffer_init failed", __func__);
-+		alloc_status = 4;
-+		goto alloc_status_switch;
-+	}
-+	rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+	if (!rx_urb) {
-+		err("%s: usb_alloc_urb failed for IR urb", __func__);
-+		alloc_status = 5;
-+		goto alloc_status_switch;
-+	}
-+	if (display_ep_found) {
-+		tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+		if (!tx_urb) {
-+			err("%s: usb_alloc_urb failed for display urb",
-+			    __func__);
-+			alloc_status = 6;
++	if (ifnum == 0) {
++		context = kzalloc(sizeof(struct imon_context), GFP_KERNEL);
++		if (!context) {
++			err("%s: kzalloc failed for context", __func__);
++			alloc_status = 1;
 +			goto alloc_status_switch;
 +		}
-+	}
++		driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
++		if (!driver) {
++			err("%s: kzalloc failed for lirc_driver", __func__);
++			alloc_status = 2;
++			goto alloc_status_switch;
++		}
++		rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
++		if (!rbuf) {
++			err("%s: kmalloc failed for lirc_buffer", __func__);
++			alloc_status = 3;
++			goto alloc_status_switch;
++		}
++		if (lirc_buffer_init(rbuf, buf_chunk_size, BUF_SIZE)) {
++			err("%s: lirc_buffer_init failed", __func__);
++			alloc_status = 4;
++			goto alloc_status_switch;
++		}
++		rx_urb = usb_alloc_urb(0, GFP_KERNEL);
++		if (!rx_urb) {
++			err("%s: usb_alloc_urb failed for IR urb", __func__);
++			alloc_status = 5;
++			goto alloc_status_switch;
++		}
++		if (display_ep_found) {
++			tx_urb = usb_alloc_urb(0, GFP_KERNEL);
++			if (!tx_urb) {
++				err("%s: usb_alloc_urb failed for display urb",
++				    __func__);
++				alloc_status = 6;
++				goto alloc_status_switch;
++			}
++		}
 +
-+	mutex_init(&context->lock);
-+	context->display_proto_6p = display_proto_6p;
-+	context->ir_onboard_decode = ir_onboard_decode;
++		mutex_init(&context->lock);
++		context->display_proto_6p = display_proto_6p;
++		context->ir_onboard_decode = ir_onboard_decode;
++
++		strcpy(driver->name, MOD_NAME);
++		driver->minor = -1;
++		driver->code_length = ir_onboard_decode ?
++			code_length : sizeof(int) * 8;
++		driver->sample_rate = 0;
++		driver->features = (ir_onboard_decode) ?
++			LIRC_CAN_REC_LIRCCODE : LIRC_CAN_REC_MODE2;
++		driver->data = context;
++		driver->rbuf = rbuf;
++		driver->set_use_inc = ir_open;
++		driver->set_use_dec = ir_close;
++		driver->dev = &interface->dev;
++		driver->owner = THIS_MODULE;
 +
-+	strcpy(driver->name, MOD_NAME);
-+	driver->minor = -1;
-+	driver->code_length = ir_onboard_decode ? code_length : sizeof(int) * 8;
-+	driver->sample_rate = 0;
-+	driver->features = (ir_onboard_decode) ?
-+		LIRC_CAN_REC_LIRCCODE : LIRC_CAN_REC_MODE2;
-+	driver->data = context;
-+	driver->rbuf = rbuf;
-+	driver->set_use_inc = ir_open;
-+	driver->set_use_dec = ir_close;
-+	driver->dev = &interface->dev;
-+	driver->owner = THIS_MODULE;
++		mutex_lock(&context->lock);
 +
-+	mutex_lock(&context->lock);
++		context->driver = driver;
++		/* start out in keyboard mode */
++		context->is_mouse = 0;
++
++		init_timer(&context->timer);
++		context->timer.data = (unsigned long)context;
++		context->timer.function = imon_touch_display_timeout;
++
++		lirc_minor = lirc_register_driver(driver);
++		if (lirc_minor < 0) {
++			err("%s: lirc_register_driver failed", __func__);
++			alloc_status = 7;
++			goto alloc_status_switch;
++		} else
++			printk(KERN_INFO MOD_NAME ": Registered iMON driver "
++			       "(lirc minor: %d)\n", lirc_minor);
 +
-+	lirc_minor = lirc_register_driver(driver);
-+	if (lirc_minor < 0) {
-+		err("%s: lirc_register_driver failed", __func__);
-+		alloc_status = 7;
-+		mutex_unlock(&context->lock);
-+		goto alloc_status_switch;
-+	} else
-+		printk(KERN_INFO "%s: Registered iMON driver(minor:%d)\n",
-+		     __func__, lirc_minor);
++		/* Needed while unregistering! */
++		driver->minor = lirc_minor;
 +
-+	/* Needed while unregistering! */
-+	driver->minor = lirc_minor;
++	} else {
++	/* this is the secondary interface on the device */
++		if (first_if_context->driver) {
++			rx_urb = usb_alloc_urb(0, GFP_KERNEL);
++			if (!rx_urb) {
++				err("%s: usb_alloc_urb failed for IR urb",
++				    __func__);
++				alloc_status = 5;
++				goto alloc_status_switch;
++			}
 +
-+	context->usbdev = usbdev;
-+	context->dev_present = 1;
-+	context->rx_endpoint = rx_endpoint;
-+	context->rx_urb = rx_urb;
-+	if (display_ep_found) {
-+		context->display_supported = 1;
-+		context->tx_endpoint = tx_endpoint;
-+		context->tx_urb = tx_urb;
-+		context->tx_control = tx_control;
++			context = first_if_context;
++		}
++		mutex_lock(&context->lock);
++	}
++
++
++	if (ifnum == 0) {
++		context->usbdev_intf0 = usbdev;
++		context->dev_present_intf0 = 1;
++		context->rx_endpoint_intf0 = rx_endpoint;
++		context->rx_urb_intf0 = rx_urb;
++		if (display_ep_found) {
++			context->display_supported = 1;
++			context->tx_endpoint = tx_endpoint;
++			context->tx_urb = tx_urb;
++			context->tx_control = tx_control;
++		}
++		context->has_touchscreen = has_touchscreen;
++
++		context->mouse = input_allocate_device();
++
++		snprintf(context->name, sizeof(context->name),
++			 "iMON PAD IR Mouse (%04x:%04x)",
++			 vendor, product);
++		context->mouse->name = context->name;
++
++		usb_make_path(usbdev, context->phys, sizeof(context->phys));
++		strlcat(context->phys, "/input0", sizeof(context->phys));
++		context->mouse->phys = context->phys;
++
++		context->mouse->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
++		context->mouse->keybit[BIT_WORD(BTN_MOUSE)] =
++			BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) |
++			BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_SIDE) |
++			BIT_MASK(BTN_EXTRA);
++		context->mouse->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) |
++			BIT_MASK(REL_WHEEL);
++
++		input_set_drvdata(context->mouse, context);
++
++		usb_to_input_id(usbdev, &context->mouse->id);
++		context->mouse->dev.parent = &interface->dev;
++		retval = input_register_device(context->mouse);
++
++	} else {
++		context->usbdev_intf1 = usbdev;
++		context->dev_present_intf1 = 1;
++		context->rx_endpoint_intf1 = rx_endpoint;
++		context->rx_urb_intf1 = rx_urb;
++
++		if (context->has_touchscreen) {
++			context->touch = input_allocate_device();
++
++			snprintf(context->name, sizeof(context->name),
++				 "iMON USB Touchscreen %04x:%04x",
++				 vendor, product);
++			context->touch->name = context->name;
++
++			usb_make_path(usbdev, context->phys,
++				      sizeof(context->phys));
++			strlcat(context->phys, "/input0",
++				sizeof(context->phys));
++			context->touch->phys = context->phys;
++
++			context->touch->evbit[0] =
++				BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
++			context->touch->keybit[BIT_WORD(BTN_TOUCH)] =
++				BIT_MASK(BTN_TOUCH);
++			input_set_abs_params(context->touch, ABS_X,
++					     0x00, 0xfff, 0, 0);
++			input_set_abs_params(context->touch, ABS_Y,
++					     0x00, 0xfff, 0, 0);
++
++			input_set_drvdata(context->touch, context);
++
++			usb_to_input_id(usbdev, &context->touch->id);
++			context->touch->dev.parent = &interface->dev;
++			retval = input_register_device(context->touch);
++		} else {
++			context->touch = NULL;
++			retval = 0;
++		}
 +	}
-+	context->driver = driver;
++
++	if (retval)
++		printk(KERN_INFO "%s: input device setup on intf%d failed\n",
++		       __func__, ifnum);
 +
 +	usb_set_intfdata(interface, context);
 +
-+	if (cpu_to_le16(usbdev->descriptor.idProduct) == 0xffdc) {
++	/* RF products *also* use 0xffdc... sigh... */
++	if (product == 0xffdc) {
 +		int err;
 +
 +		err = sysfs_create_group(&interface->dev.kobj,
@@ -4336,22 +4763,31 @@ index 0000000..05cb293
 +			    __func__, err);
 +	}
 +
-+	if (display_ep_found && context->display_supported) {
++	if (context->display_supported && ifnum == 0) {
 +		if (debug)
-+			printk(KERN_INFO "Registering display with sysfs\n");
++			printk(KERN_INFO "%s: Registering iMON display with "
++			       "sysfs\n", __func__);
 +		if (usb_register_dev(interface, &imon_class)) {
 +			/* Not a fatal error, so ignore */
 +			printk(KERN_INFO "%s: could not get a minor number for "
 +			       "display\n", __func__);
 +		}
-+	}
 +
-+	printk(KERN_INFO "%s: iMON device on usb<%d:%d> initialized\n",
-+			__func__, usbdev->bus->busnum, usbdev->devnum);
++		/* Enable front-panel buttons and/or knobs */
++		memcpy(context->usb_tx_buf, &fp_packet, sizeof(fp_packet));
++		retval = send_packet(context);
++		/* Not fatal, but warn about it */
++		if (retval)
++			printk(KERN_INFO "%s: failed to enable front-panel "
++			       "buttons and/or knobs\n", __func__);
++	}
 +
-+	mutex_unlock(&context->lock);
++	printk(KERN_INFO MOD_NAME ": iMON device (%04x:%04x, intf%d) on "
++	       "usb<%d:%d> initialized\n", vendor, product, ifnum,
++	       usbdev->bus->busnum, usbdev->devnum);
 +
 +alloc_status_switch:
++	mutex_unlock(&context->lock);
 +
 +	switch (alloc_status) {
 +	case 7:
@@ -4371,10 +4807,12 @@ index 0000000..05cb293
 +	case 1:
 +		retval = -ENOMEM;
 +	case 0:
-+		;
++		retval = 0;
 +	}
 +
 +exit:
++	mutex_unlock(&driver_lock);
++
 +	return retval;
 +}
 +
@@ -4384,11 +4822,14 @@ index 0000000..05cb293
 +static void imon_disconnect(struct usb_interface *interface)
 +{
 +	struct imon_context *context;
++	int ifnum;
 +
 +	/* prevent races with ir_open()/display_open() */
-+	mutex_lock(&disconnect_lock);
++	mutex_lock(&driver_lock);
 +
 +	context = usb_get_intfdata(interface);
++	ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
++
 +	mutex_lock(&context->lock);
 +
 +	/*
@@ -4397,11 +4838,8 @@ index 0000000..05cb293
 +	 */
 +	sysfs_remove_group(&interface->dev.kobj,
 +			   &imon_attribute_group);
-+	usb_set_intfdata(interface, NULL);
-+	context->dev_present = 0;
 +
-+	/* Stop reception */
-+	usb_kill_urb(context->rx_urb);
++	usb_set_intfdata(interface, NULL);
 +
 +	/* Abort ongoing write */
 +	if (atomic_read(&context->tx.busy)) {
@@ -4409,29 +4847,46 @@ index 0000000..05cb293
 +		complete_all(&context->tx.finished);
 +	}
 +
-+	/* De-register from lirc_dev if IR port is not open */
-+	if (!context->ir_isopen)
-+		deregister_from_lirc(context);
-+
-+	if (context->display_supported)
-+		usb_deregister_dev(interface, &imon_class);
-+
-+	mutex_unlock(&context->lock);
++	if (ifnum == 0) {
++		context->dev_present_intf0 = 0;
++		usb_kill_urb(context->rx_urb_intf0);
++		input_unregister_device(context->mouse);
++		if (context->display_supported)
++			usb_deregister_dev(interface, &imon_class);
++	} else {
++		context->dev_present_intf1 = 0;
++		usb_kill_urb(context->rx_urb_intf1);
++		if (context->has_touchscreen)
++			input_unregister_device(context->touch);
++	}
 +
-+	if (!context->ir_isopen && !context->display_isopen)
-+		delete_context(context);
++	if (!context->ir_isopen && !context->dev_present_intf0 &&
++	    !context->dev_present_intf1) {
++		del_timer_sync(&context->timer);
++		deregister_from_lirc(context);
++		mutex_unlock(&context->lock);
++		if (!context->display_isopen)
++			free_imon_context(context);
++	} else
++		mutex_unlock(&context->lock);
 +
-+	mutex_unlock(&disconnect_lock);
++	mutex_unlock(&driver_lock);
 +
-+	printk(KERN_INFO "%s: iMON device disconnected\n", __func__);
++	printk(KERN_INFO "%s: iMON device (intf%d) disconnected\n",
++	       __func__, ifnum);
 +}
 +
 +static int imon_suspend(struct usb_interface *intf, pm_message_t message)
 +{
 +	struct imon_context *context = usb_get_intfdata(intf);
++	int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
 +
-+	if (context->ir_isopen)
-+		usb_kill_urb(context->rx_urb);
++	if (context->ir_isopen) {
++		if (ifnum == 0)
++			usb_kill_urb(context->rx_urb_intf0);
++		else
++			usb_kill_urb(context->rx_urb_intf1);
++	}
 +
 +	return 0;
 +}
@@ -4440,9 +4895,14 @@ index 0000000..05cb293
 +{
 +	int rc = 0;
 +	struct imon_context *context = usb_get_intfdata(intf);
++	int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
 +
-+	if (context->ir_isopen)
-+		rc = usb_submit_urb(context->rx_urb, GFP_ATOMIC);
++	if (context->ir_isopen) {
++		if (ifnum == 0)
++			rc = usb_submit_urb(context->rx_urb_intf0, GFP_ATOMIC);
++		else
++			rc = usb_submit_urb(context->rx_urb_intf1, GFP_ATOMIC);
++	}
 +
 +	return rc;
 +}
@@ -4451,8 +4911,7 @@ index 0000000..05cb293
 +{
 +	int rc;
 +
-+	printk(KERN_INFO MOD_DESC ", v" MOD_VERSION "\n");
-+	printk(KERN_INFO MOD_AUTHOR "\n");
++	printk(KERN_INFO MOD_NAME ": " MOD_DESC ", v" MOD_VERSION "\n");
 +
 +	rc = usb_register(&imon_driver);
 +	if (rc) {
@@ -4466,17 +4925,17 @@ index 0000000..05cb293
 +static void __exit imon_exit(void)
 +{
 +	usb_deregister(&imon_driver);
-+	printk(KERN_INFO "module removed. Goodbye!\n");
++	printk(KERN_INFO MOD_NAME ": module removed. Goodbye!\n");
 +}
 +
 +module_init(imon_init);
 +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..232ba97
+index 0000000..f363727
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_it87.c
-@@ -0,0 +1,984 @@
+@@ -0,0 +1,986 @@
 +/*
 + * LIRC driver for ITE IT8712/IT8705 CIR port
 + *
@@ -4497,7 +4956,7 @@ index 0000000..232ba97
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 + * USA
 + *
-+ * ITE IT8705 and IT8712(not tested) CIR-port support for lirc based
++ * ITE IT8705 and IT8712(not tested) and IT8720 CIR-port support for lirc based
 + * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula
 + *
 + * Attention: Sendmode only tested with debugging logs
@@ -5270,9 +5729,11 @@ index 0000000..232ba97
 +		return retval;
 +	}
 +	it87_chipid = it87_read(IT87_CHIP_ID2);
-+	if ((it87_chipid != 0x12) && (it87_chipid != 0x05)) {
++	if ((it87_chipid != 0x12) &&
++		(it87_chipid != 0x05) &&
++		(it87_chipid != 0x20)) {
 +		printk(KERN_INFO LIRC_DRIVER_NAME
-+		       ": no IT8705/12 found, exiting..\n");
++		       ": no IT8705/12/20 found, exiting..\n");
 +		retval = -ENXIO;
 +		return retval;
 +	}
@@ -5362,16 +5823,16 @@ index 0000000..232ba97
 +#if 0
 +	unsigned char init_bytes[4] = IT87_INIT;
 +
-+	/ * Enter MB PnP Mode * /
++	/* Enter MB PnP Mode */
 +	outb(init_bytes[0], IT87_ADRPORT);
 +	outb(init_bytes[1], IT87_ADRPORT);
 +	outb(init_bytes[2], IT87_ADRPORT);
 +	outb(init_bytes[3], IT87_ADRPORT);
 +
-+	/ * deactivate CIR-Device * /
++	/* deactivate CIR-Device */
 +	it87_write(IT87_CIR_ACT, 0x0);
 +
-+	/ * Leaving MB PnP Mode * /
++	/* Leaving MB PnP Mode */
 +	it87_write(IT87_CFGCTRL, 0x2);
 +#endif
 +
@@ -6885,13 +7346,13 @@ index 0000000..12d9723
 +MODULE_PARM_DESC(debug, "Debug enabled or not");
 diff --git a/drivers/input/lirc/lirc_mceusb2.c b/drivers/input/lirc/lirc_mceusb2.c
 new file mode 100644
-index 0000000..4c24b79
+index 0000000..3af45dd
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_mceusb2.c
-@@ -0,0 +1,1098 @@
+@@ -0,0 +1,1101 @@
 +/*
 + * LIRC driver for Philips eHome USB Infrared Transceiver
-+ * and the Microsoft MCE 2005 Remote Control
++ * and the Microsoft Media Center Edition Remote Control
 + *
 + * (C) by Martin A. Blatter <martin_a_blatter at yahoo.com>
 + *
@@ -6899,9 +7360,7 @@ index 0000000..4c24b79
 + * (C) by Daniel Melander <lirc at rajidae.se>
 + *
 + * Derived from ATI USB driver by Paul Miller and the original
-+ * MCE USB driver by Dan Corti
-+ *
-+ *
++ * MCE USB driver by Dan Conti
 + *
 + *
 + * This program is free software; you can redistribute it and/or modify
@@ -6980,8 +7439,8 @@ index 0000000..4c24b79
 +#define RECV_FLAG_IN_PROGRESS	3
 +#define RECV_FLAG_COMPLETE	4
 +
-+#define PHILUSB_INBOUND		1
-+#define PHILUSB_OUTBOUND	2
++#define MCEUSB_INBOUND		1
++#define MCEUSB_OUTBOUND	2
 +
 +#define VENDOR_PHILIPS		0x0471
 +#define VENDOR_SMK		0x0609
@@ -7002,6 +7461,7 @@ index 0000000..4c24b79
 +#define VENDOR_ECS		0x1019
 +#define VENDOR_WISTRON		0x0fb8
 +#define VENDOR_COMPRO		0x185b
++#define VENDOR_NORTHSTAR	0x04eb
 +
 +static struct usb_device_id mceusb_dev_table[] = {
 +	/* Philips Infrared Transceiver - Sahara branded */
@@ -7040,6 +7500,8 @@ index 0000000..4c24b79
 +	{ USB_DEVICE(VENDOR_TOPSEED, 0x0007) },
 +	/* Topseed eHome Infrared Transceiver */
 +	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
++	/* Topseed eHome Infrared Transceiver */
++	{ USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
 +	/* Ricavision internal Infrared Transceiver */
 +	{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
 +	/* Itron ione Libra Q-11 */
@@ -7070,6 +7532,8 @@ index 0000000..4c24b79
 +	{ USB_DEVICE(VENDOR_WISTRON, 0x0002) },
 +	/* Compro K100 */
 +	{ USB_DEVICE(VENDOR_COMPRO, 0x3020) },
++	/* Northstar Systems, Inc. eHome Infrared Transceiver */
++	{ USB_DEVICE(VENDOR_NORTHSTAR, 0xe0004) },
 +	/* Terminating entry */
 +	{ }
 +};
@@ -7188,7 +7652,7 @@ index 0000000..4c24b79
 +			/* alloc buffer */
 +			async_buf = kmalloc(size, GFP_KERNEL);
 +			if (async_buf) {
-+				if (urb_type == PHILUSB_OUTBOUND) {
++				if (urb_type == MCEUSB_OUTBOUND) {
 +					/* outbound data */
 +					usb_fill_int_urb(async_urb, ir->usbdev,
 +						usb_sndintpipe(ir->usbdev,
@@ -7494,7 +7958,7 @@ index 0000000..4c24b79
 +
 +	/* Transmit the command to the mce device */
 +	request_packet_async(ir, ir->usb_ep_out, cmdbuf,
-+			     cmdcount, PHILUSB_OUTBOUND);
++			     cmdcount, MCEUSB_OUTBOUND);
 +
 +	/*
 +	 * The lircd gap calculation expects the write function to
@@ -7537,7 +8001,7 @@ index 0000000..4c24b79
 +				"carrier modulation\n", ir->devnum);
 +			request_packet_async(ir, ir->usb_ep_out,
 +					     cmdbuf, sizeof(cmdbuf),
-+					     PHILUSB_OUTBOUND);
++					     MCEUSB_OUTBOUND);
 +			return carrier;
 +		}
 +
@@ -7554,7 +8018,7 @@ index 0000000..4c24b79
 +				/* Transmit new carrier to mce device */
 +				request_packet_async(ir, ir->usb_ep_out,
 +						     cmdbuf, sizeof(cmdbuf),
-+						     PHILUSB_OUTBOUND);
++						     MCEUSB_OUTBOUND);
 +				return carrier;
 +			}
 +		}
@@ -7871,17 +8335,17 @@ index 0000000..4c24b79
 +		 * its possible we really should wait for a return
 +		 * for each of these...
 +		 */
-+		request_packet_async(ir, ep_in, NULL, maxp, PHILUSB_INBOUND);
++		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
 +		request_packet_async(ir, ep_out, pin_init1, sizeof(pin_init1),
-+				     PHILUSB_OUTBOUND);
-+		request_packet_async(ir, ep_in, NULL, maxp, PHILUSB_INBOUND);
++				     MCEUSB_OUTBOUND);
++		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
 +		request_packet_async(ir, ep_out, pin_init2, sizeof(pin_init2),
-+				     PHILUSB_OUTBOUND);
-+		request_packet_async(ir, ep_in, NULL, maxp, PHILUSB_INBOUND);
++				     MCEUSB_OUTBOUND);
++		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
 +		request_packet_async(ir, ep_out, pin_init3, sizeof(pin_init3),
-+				     PHILUSB_OUTBOUND);
++				     MCEUSB_OUTBOUND);
 +		/* if we don't issue the correct number of receives
-+		 * (PHILUSB_INBOUND) for each outbound, then the first few ir
++		 * (MCEUSB_INBOUND) 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 -
@@ -7890,13 +8354,13 @@ index 0000000..4c24b79
 +		 */
 +		request_packet_async(ir, ep_in, NULL, maxp, 0);
 +	} else {
-+		request_packet_async(ir, ep_in, NULL, maxp, PHILUSB_INBOUND);
-+		request_packet_async(ir, ep_in, NULL, maxp, PHILUSB_INBOUND);
++		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), PHILUSB_OUTBOUND);
-+		request_packet_async(ir, ep_in, NULL, maxp, PHILUSB_INBOUND);
++				     sizeof(init1), MCEUSB_OUTBOUND);
++		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
 +		request_packet_async(ir, ep_out, init2,
-+				     sizeof(init2), PHILUSB_OUTBOUND);
++				     sizeof(init2), MCEUSB_OUTBOUND);
 +		request_packet_async(ir, ep_in, NULL, maxp, 0);
 +	}
 +
@@ -9673,10 +10137,10 @@ index 0000000..270f8ff
 +module_exit(sasem_exit);
 diff --git a/drivers/input/lirc/lirc_serial.c b/drivers/input/lirc/lirc_serial.c
 new file mode 100644
-index 0000000..01cc8b7
+index 0000000..1b79ced
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_serial.c
-@@ -0,0 +1,1321 @@
+@@ -0,0 +1,1316 @@
 +/*
 + * lirc_serial.c
 + *
@@ -10433,11 +10897,8 @@ index 0000000..01cc8b7
 +
 +static int hardware_init_port(void)
 +{
-+	unsigned long flags;
 +	u8 scratch, scratch2, scratch3;
 +
-+	spin_lock_irqsave(&hardware[type].lock, flags);
-+
 +	/*
 +	 * This is a simple port existence test, borrowed from the autoconfig
 +	 * function in drivers/serial/8250.c
@@ -10518,8 +10979,6 @@ index 0000000..01cc8b7
 +		break;
 +	}
 +
-+	spin_unlock_irqrestore(&hardware[type].lock, flags);
-+
 +	return 0;
 +}
 +
@@ -10588,6 +11047,11 @@ index 0000000..01cc8b7
 +	int result;
 +	unsigned long flags;
 +
++	/* Init read buffer. */
++	result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);
++	if (result < 0)
++		return -ENOMEM;
++
 +	/* initialize timestamp */
 +	do_gettimeofday(&lasttv);
 +
@@ -10837,11 +11301,6 @@ index 0000000..01cc8b7
 +{
 +	int result;
 +
-+	/* Init read buffer. */
-+	result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);
-+	if (result < 0)
-+		return -ENOMEM;
-+
 +	result = platform_driver_register(&lirc_serial_driver);
 +	if (result) {
 +		printk("lirc register returned %d\n", result);
@@ -13083,10 +13542,10 @@ index 0000000..d1ce354
 +MODULE_PARM_DESC(debug, "Enable debugging messages");
 diff --git a/drivers/input/lirc/lirc_ttusbir.c b/drivers/input/lirc/lirc_ttusbir.c
 new file mode 100644
-index 0000000..4d18084
+index 0000000..2955bad
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_ttusbir.c
-@@ -0,0 +1,398 @@
+@@ -0,0 +1,397 @@
 +/*
 + * lirc_ttusbir.c
 + *
@@ -13396,7 +13855,6 @@ index 0000000..4d18084
 +	ttusbir->driver.rbuf = &ttusbir->rbuf;
 +	ttusbir->driver.set_use_inc = set_use_inc;
 +	ttusbir->driver.set_use_dec = set_use_dec;
-+	ttusbir->driver.fops = NULL;
 +	ttusbir->driver.dev = &intf->dev;
 +	ttusbir->driver.owner = THIS_MODULE;
 +	ttusbir->driver.features = LIRC_CAN_REC_MODE2;
@@ -13487,10 +13945,10 @@ index 0000000..4d18084
 +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..38fddec
+index 0000000..ec503d7
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_zilog.c
-@@ -0,0 +1,1382 @@
+@@ -0,0 +1,1385 @@
 +/*
 + * i2c IR lirc driver for devices with zilog IR processors
 + *
@@ -14670,10 +15128,10 @@ index 0000000..38fddec
 +		/* try to fire up polling thread */
 +		ir->t_notify = &tn;
 +		ir->task = kthread_run(lirc_thread, ir, "lirc_zilog");
-+		ret = PTR_ERR(ir->task);
-+		if (ret <= 0) {
++		if (IS_ERR(ir->task)) {
++			ret = PTR_ERR(ir->task);
 +			zilog_error("lirc_register_driver: cannot run "
-+				    "poll thread\n");
++				    "poll thread %d\n", ret);
 +			goto err;
 +		}
 +		wait_for_completion(&tn);
@@ -14794,6 +15252,9 @@ index 0000000..38fddec
 +	memset(&c, 0, sizeof(c));
 +
 +	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) {
 +		int have_rx = 0, have_tx = 0;
 +




More information about the fedora-extras-commits mailing list