diff --git a/kernel.spec b/kernel.spec index cacb346f1..77b0279d7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2101,6 +2101,9 @@ fi %changelog +* Sun Sep 05 2010 Jarod Wilson 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 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 70e30160a..ea4f28dba 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 + +--- + 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 -+ */ +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@redhat.com ++P: Christoph Bartelmus ++M: lirc@bartelmus.de ++W: http://www.lirc.org/ ++L: lirc-list@lists.sourceforge.net ++S: Maintained + -+#ifndef _LINUX_LIRC_H -+#define _LINUX_LIRC_H -+ -+#include -+#include -+ -+#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 + LINUX SECURITY MODULE (LSM) FRAMEWORK + M: Chris Wright + L: linux-security-module@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 +#include +#include ++#ifdef CONFIG_COMPAT ++#include ++#endif + +#include +#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 +#include +#include ++#include + +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 +#include +#include -+#include +#include + +#include @@ -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 +#include +#include -+#include +#include +#include +#include @@ -4717,6 +4761,7 @@ index 0000000..c69662d +#include + +#include ++#include + +#include +#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}; ++/* ++ * 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 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) ++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 { + -+ 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); ++ } 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); ++ ++ /* 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, 0x02000028, { KEY_ENTER } }, -+/* the OK and Enter buttons decode to the same value -+ { KE_KEY, 0x02000028, { KEY_OK } }, */ -+ { KE_KEY, 0x0200002a, { KEY_EXIT } }, -+ { KE_KEY, 0x02000029, { KEY_DELETE } }, ++ { KE_KEY, 0x800ff41e, { KEY_UP } }, ++ { KE_KEY, 0x800ff41f, { KEY_DOWN } }, ++ { KE_KEY, 0x800ff420, { KEY_LEFT } }, ++ { KE_KEY, 0x800ff421, { KEY_RIGHT } }, + -+ { 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 } }, ++ /* 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 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, 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 } }, ++ /* 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, 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, 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, 0x800f845b, { KEY_RED } }, -+ { KE_KEY, 0x800f845c, { KEY_GREEN } }, -+ { KE_KEY, 0x800f845d, { KEY_YELLOW } }, -+ { KE_KEY, 0x800f845e, { KEY_BLUE } }, ++ { KE_KEY, 0x800ff44c, { KEY_LANGUAGE } }, ++ { KE_KEY, 0x800ff427, { KEY_ZOOM } }, /* Aspect */ + -+ { KE_KEY, 0x800f840f, { KEY_INFO } }, -+ { KE_KEY, 0x800f8426, { KEY_EPG } }, /* Guide */ -+ { KE_KEY, 0x800f845a, { KEY_SUBTITLE } }, /* Caption */ ++ { KE_KEY, 0x800ff45b, { KEY_RED } }, ++ { KE_KEY, 0x800ff45c, { KEY_GREEN } }, ++ { KE_KEY, 0x800ff45d, { KEY_YELLOW } }, ++ { KE_KEY, 0x800ff45e, { KEY_BLUE } }, + -+ { KE_KEY, 0x800f840c, { KEY_POWER } }, -+ { KE_KEY, 0x800f840d, { KEY_PROG1 } }, /* Windows MCE button */ ++ { 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 ++#include ++ ++/* */ ++#define PULSE_BIT 0x01000000 ++#define PULSE_MASK 0x00FFFFFF ++/* */ ++ ++#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