This here is a second go at submitting linux infrared remote control
(lirc) drivers for kernel inclusion, with a much smaller patch set that
includes only the core lirc driver and two device drivers, all three of
which have been heavily updated since the last submission, based on
feedback received.
Never meant for it to be more than a year before the second attempt at
submitting lirc drivers, but day jobs and life tend to get in the way.
Development work has been ongoing despite all that, just took a bit
longer than anticipated to address as much of the review comments as
possible and get up the guts for another submission. ;)
For those not in the know, lirc has existed out-of-tree at lirc.org for
years and years, and is currently patched into the kernels or provided
as add-on kernel module packages in a number of distributions (its been
patched into Fedora kernels going on 2.5 years now), so the code is in
fairly wide use and is reasonably well tested, despite not being in the
upstream kernel itself.
The drivers included in this submission are for the Windows MCE USB IR
transceivers and the SoundGraph iMON USB receivers/displays. I have
multiple devices driven by each of these drivers, and have done fairly
extensive testing on them, currently primarily on 2.6.31 and 2.6.32.
The MCE transceiver can handle just about any IR protocol you can throw
at it on the RX side, thus it passes raw IR through to the userspace
lircd daemon for processing. An lircd.conf file maps IR codes to key
codes, and they can be consumed by the system either via applications
with lirc client support, or they can be fed back into the input subsys
via uinput. The transmit side has no input subsys interaction. Note
that this driver now handles both generations of MCE transceivers.
The iMON receivers come in two flavors, an early version that passes
raw IR, and all more recent versions that do onboard decoding of IR
signals. The iMON driver now supports running as a pure input device on
devices with onboard decoding, as well as "classic" lirc mode for the
ones that don't decode onboard and includes a modparam option to let
the onboard decode devices continue to operate in "classic" mode, for
those who prefer it.
There's been talk about a raw IR input device type/ioctls/whatever. But
it doesn't yet exist, and I know *I* don't have time to write it up...
lircd and lirc drivers could be adapted to use such a thing if/when it
sees the light of day, but for now, the lirc_dev ("classic" lirc mode)
interface is quite well battle-tested, and very capable for both raw IR
receive and transmit. There's also been a patchset proposed to do raw
IR decoding in the kernel. I'm fine with that idea too, but only if
there is *also* a way to get the raw IR out to userspace (lircd), as
there are some esoteric IR protocols out there and we can be a lot more
nimble about adding support for decoding new and different protocols
in userspace than we can in the kernel -- and lircd can now feed all
the resulting key codes back into the input subsystem via uinput too.
The hope is that we can get lirc_dev (upon which all other lirc drivers
depend) merged, along with these initial two drivers, then we can start
reviewing the additional 15 or so lirc drivers for inclusion as well.
Combined diffstat:
MAINTAINERS | 9 +
drivers/input/Kconfig | 2 +
drivers/input/Makefile | 1 +
drivers/input/lirc/Kconfig | 26 +
drivers/input/lirc/Makefile | 8 +
drivers/input/lirc/lirc.h | 100 ++
drivers/input/lirc/lirc_dev.c | 837 +++++++++++++
drivers/input/lirc/lirc_dev.h | 194 +++
drivers/input/lirc/lirc_imon.c | 2471 ++++++++++++++++++++++++++++++++++++++
drivers/input/lirc/lirc_imon.h | 209 ++++
drivers/input/lirc/lirc_mceusb.c | 1235 +++++++++++++++++++
11 files changed, 5092 insertions(+), 0 deletions(-)
Git tree:
* git://git.wilsonet.com/linux-2.6-lirc.git/
Git web:
* http://git.wilsonet.com/linux-2.6-lirc.git/
Upstream lirc project:
* http://www.lirc.org/
(If you're going to clone, I'd highly suggest adding it as a remote
to a linus' tree checkout rather than clone'ing directly, as I don't
have nearly as much bandwidth at home as kernel.org... ;)
--
Jarod Wilson
[email protected]
Core Linux Infrared Remote Control driver and infrastructure
-Add Kconfig and Makefile bits
-Add device driver interface and headers
The initial Kconfig and Makefile bits were done by Mario Limonciello for
the Ubuntu kernel, but have been tweaked a bit since then. Any errors are
probably my doing.
Changes from prior submission:
- Now uses dev_dbg instead of its own dprintk
- Dynamic device numbers used
- sleep_on() ripped out in favor of wake bits
- Kconfig text improved and simplified
- All inline keywords removed where possible
- Obfuscating #defines and wrapper functions removed
- We call 'em lirc drivers now instead of lirc plugins
Signed-off-by: Jarod Wilson <[email protected]>
Signed-off-by: Janne Grunau <[email protected]>
CC: Christoph Bartelmus <[email protected]>
CC: Mario Limonciello <[email protected]>
---
MAINTAINERS | 9
drivers/input/Kconfig | 2
drivers/input/Makefile | 1
drivers/input/lirc/Kconfig | 16
drivers/input/lirc/Makefile | 6
drivers/input/lirc/lirc.h | 100 +++++
drivers/input/lirc/lirc_dev.c | 837 ++++++++++++++++++++++++++++++++++++++++++
drivers/input/lirc/lirc_dev.h | 194 +++++++++
8 files changed, 1165 insertions(+)
Index: b/MAINTAINERS
===================================================================
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3219,6 +3219,15 @@ W: http://www.pasemi.com/
L: [email protected]
S: Supported
+LINUX INFRARED REMOTE CONTROL DRIVERS (LIRC)
+P: Jarod Wilson
+M: [email protected]
+P: Christoph Bartelmus
+M: [email protected]
+W: http://www.lirc.org/
+L: [email protected]
+S: Maintained
+
LINUX SECURITY MODULE (LSM) FRAMEWORK
M: Chris Wright <[email protected]>
L: [email protected]
Index: b/drivers/input/Kconfig
===================================================================
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -170,6 +170,8 @@ source "drivers/input/tablet/Kconfig"
source "drivers/input/touchscreen/Kconfig"
+source "drivers/input/lirc/Kconfig"
+
source "drivers/input/misc/Kconfig"
endif
Index: b/drivers/input/Makefile
===================================================================
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_INPUT_MOUSE) += mouse/
obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
obj-$(CONFIG_INPUT_TABLET) += tablet/
obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
+obj-$(CONFIG_INPUT_LIRC) += lirc/
obj-$(CONFIG_INPUT_MISC) += misc/
obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
Index: b/drivers/input/lirc/Kconfig
===================================================================
--- /dev/null
+++ b/drivers/input/lirc/Kconfig
@@ -0,0 +1,16 @@
+#
+# LIRC driver(s) configuration
+#
+menuconfig INPUT_LIRC
+ bool "Linux Infrared Remote Control IR receiver/transmitter drivers"
+ help
+ Say Y here, and all supported Linux Infrared Remote Control IR and
+ RF receiver and transmitter drivers will be displayed. When paired
+ with a remote control and the lirc daemon, the receiver drivers
+ allow control of your Linux system via remote control.
+
+if INPUT_LIRC
+
+# Device-specific drivers go here
+
+endif
Index: b/drivers/input/lirc/Makefile
===================================================================
--- /dev/null
+++ b/drivers/input/lirc/Makefile
@@ -0,0 +1,6 @@
+# Makefile for the lirc drivers.
+#
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_INPUT_LIRC) += lirc_dev.o
Index: b/drivers/input/lirc/lirc.h
===================================================================
--- /dev/null
+++ b/drivers/input/lirc/lirc.h
@@ -0,0 +1,100 @@
+/*
+ * lirc.h - linux infrared remote control header file
+ * last modified 2007/09/27
+ */
+
+#ifndef _LINUX_LIRC_H
+#define _LINUX_LIRC_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define PULSE_BIT 0x01000000
+#define PULSE_MASK 0x00FFFFFF
+
+/*** lirc compatible hardware features ***/
+
+#define LIRC_MODE2SEND(x) (x)
+#define LIRC_SEND2MODE(x) (x)
+#define LIRC_MODE2REC(x) ((x) << 16)
+#define LIRC_REC2MODE(x) ((x) >> 16)
+
+#define LIRC_MODE_RAW 0x00000001
+#define LIRC_MODE_PULSE 0x00000002
+#define LIRC_MODE_MODE2 0x00000004
+#define LIRC_MODE_CODE 0x00000008
+#define LIRC_MODE_LIRCCODE 0x00000010
+#define LIRC_MODE_STRING 0x00000020
+
+
+#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_CODE LIRC_MODE2SEND(LIRC_MODE_CODE)
+#define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE)
+#define LIRC_CAN_SEND_STRING LIRC_MODE2SEND(LIRC_MODE_STRING)
+
+#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_CODE LIRC_MODE2REC(LIRC_MODE_CODE)
+#define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE)
+#define LIRC_CAN_REC_STRING LIRC_MODE2REC(LIRC_MODE_STRING)
+
+#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
Index: b/drivers/input/lirc/lirc_dev.c
===================================================================
--- /dev/null
+++ b/drivers/input/lirc/lirc_dev.c
@@ -0,0 +1,837 @@
+/*
+ * LIRC base driver
+ *
+ * by Artur Lipowski <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/completion.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/unistd.h>
+#include <linux/kthread.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/smp_lock.h>
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif
+
+#include "lirc.h"
+#include "lirc_dev.h"
+
+static int debug;
+
+#define IRCTL_DEV_NAME "BaseRemoteCtl"
+#define NOPLUG -1
+#define LOGHEAD "lirc_dev (%s[%d]): "
+
+static dev_t lirc_base_dev;
+
+struct irctl {
+ struct lirc_driver d;
+ int attached;
+ int open;
+
+ struct mutex buffer_lock;
+ struct lirc_buffer *buf;
+ unsigned int chunk_size;
+
+ struct task_struct *task;
+ long jiffies_to_wait;
+
+ struct cdev cdev;
+};
+
+static DEFINE_MUTEX(lirc_dev_lock);
+
+static struct irctl *irctls[MAX_IRCTL_DEVICES];
+
+/* Only used for sysfs but defined to void otherwise */
+static struct class *lirc_class;
+
+/* helper function
+ * initializes the irctl structure
+ */
+static void init_irctl(struct irctl *ir)
+{
+ dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n",
+ ir->d.name, ir->d.minor);
+ mutex_init(&ir->buffer_lock);
+ ir->d.minor = NOPLUG;
+}
+
+static void cleanup(struct irctl *ir)
+{
+ dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
+
+ device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
+
+ if (ir->buf != ir->d.rbuf) {
+ lirc_buffer_free(ir->buf);
+ kfree(ir->buf);
+ }
+ ir->buf = NULL;
+}
+
+/* helper function
+ * reads key codes from driver and puts them into buffer
+ * returns 0 on success
+ */
+static int add_to_buf(struct irctl *ir)
+{
+ if (ir->d.add_to_buf) {
+ int res = -ENODATA;
+ int got_data = 0;
+
+ /*
+ * service the device as long as it is returning
+ * data and we have space
+ */
+get_data:
+ res = ir->d.add_to_buf(ir->d.data, ir->buf);
+ if (res == 0) {
+ got_data++;
+ goto get_data;
+ }
+
+ if (res == -ENODEV)
+ kthread_stop(ir->task);
+
+ return got_data ? 0 : res;
+ }
+
+ return 0;
+}
+
+/* main function of the polling thread
+ */
+static int lirc_thread(void *irctl)
+{
+ struct irctl *ir = irctl;
+
+ dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n",
+ ir->d.name, ir->d.minor);
+
+ do {
+ if (ir->open) {
+ if (ir->jiffies_to_wait) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(ir->jiffies_to_wait);
+ }
+ if (kthread_should_stop())
+ break;
+ if (!add_to_buf(ir))
+ wake_up_interruptible(&ir->buf->wait_poll);
+ } else {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ }
+ } while (!kthread_should_stop());
+
+ dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n",
+ ir->d.name, ir->d.minor);
+
+ return 0;
+}
+
+
+static struct file_operations fops = {
+ .owner = THIS_MODULE,
+ .read = lirc_dev_fop_read,
+ .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,
+};
+
+static int lirc_cdev_add(struct irctl *ir)
+{
+ int retval;
+ struct lirc_driver *d = &ir->d;
+
+ if (d->fops) {
+ cdev_init(&ir->cdev, d->fops);
+ ir->cdev.owner = d->owner;
+ } else {
+ cdev_init(&ir->cdev, &fops);
+ ir->cdev.owner = THIS_MODULE;
+ }
+ kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor);
+
+ retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
+ if (retval)
+ kobject_put(&ir->cdev.kobj);
+
+ return retval;
+}
+
+int lirc_register_driver(struct lirc_driver *d)
+{
+ struct irctl *ir;
+ int minor;
+ int bytes_in_key;
+ unsigned int chunk_size;
+ unsigned int buffer_size;
+ int err;
+
+ if (!d) {
+ printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+ "driver pointer must be not NULL!\n");
+ err = -EBADRQC;
+ goto out;
+ }
+
+ if (MAX_IRCTL_DEVICES <= d->minor) {
+ dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+ "\"minor\" must be between 0 and %d (%d)!\n",
+ MAX_IRCTL_DEVICES-1, d->minor);
+ err = -EBADRQC;
+ goto out;
+ }
+
+ if (1 > d->code_length || (BUFLEN * 8) < d->code_length) {
+ dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+ "code length in bits for minor (%d) "
+ "must be less than %d!\n",
+ d->minor, BUFLEN * 8);
+ err = -EBADRQC;
+ goto out;
+ }
+
+ dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n",
+ d->sample_rate);
+ if (d->sample_rate) {
+ if (2 > d->sample_rate || HZ < d->sample_rate) {
+ dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+ "sample_rate must be between 2 and %d!\n", HZ);
+ err = -EBADRQC;
+ goto out;
+ }
+ if (!d->add_to_buf) {
+ dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+ "add_to_buf cannot be NULL when "
+ "sample_rate is set\n");
+ err = -EBADRQC;
+ goto out;
+ }
+ } else if (!(d->fops && d->fops->read) && !d->rbuf) {
+ dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+ "fops->read and rbuf cannot all be NULL!\n");
+ err = -EBADRQC;
+ goto out;
+ } else if (!d->rbuf) {
+ if (!(d->fops && d->fops->read && d->fops->poll &&
+ d->fops->ioctl)) {
+ dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+ "neither read, poll nor ioctl can be NULL!\n");
+ err = -EBADRQC;
+ goto out;
+ }
+ }
+
+ mutex_lock(&lirc_dev_lock);
+
+ minor = d->minor;
+
+ if (minor < 0) {
+ /* find first free slot for driver */
+ for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++)
+ if (!irctls[minor])
+ break;
+ if (MAX_IRCTL_DEVICES == minor) {
+ dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+ "no free slots for drivers!\n");
+ err = -ENOMEM;
+ goto out_lock;
+ }
+ } else if (irctls[minor]) {
+ dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+ "minor (%d) just registered!\n", minor);
+ err = -EBUSY;
+ goto out_lock;
+ }
+
+ ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
+ if (!ir) {
+ err = -ENOMEM;
+ goto out_lock;
+ }
+ init_irctl(ir);
+ irctls[minor] = ir;
+ d->minor = minor;
+
+ if (d->sample_rate) {
+ ir->jiffies_to_wait = HZ / d->sample_rate;
+ } else {
+ /* it means - wait for external event in task queue */
+ ir->jiffies_to_wait = 0;
+ }
+
+ /* some safety check 8-) */
+ d->name[sizeof(d->name)-1] = '\0';
+
+ bytes_in_key = BITS_TO_LONGS(d->code_length) +
+ (d->code_length % 8 ? 1 : 0);
+ buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key;
+ chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key;
+
+ if (d->rbuf) {
+ ir->buf = d->rbuf;
+ } else {
+ ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+ if (!ir->buf) {
+ err = -ENOMEM;
+ goto out_lock;
+ }
+ err = lirc_buffer_init(ir->buf, chunk_size, buffer_size);
+ if (err) {
+ kfree(ir->buf);
+ goto out_lock;
+ }
+ }
+ ir->chunk_size = ir->buf->chunk_size;
+
+ if (d->features == 0)
+ d->features = (d->code_length > 8) ?
+ LIRC_CAN_REC_LIRCCODE : LIRC_CAN_REC_CODE;
+
+ ir->d = *d;
+ ir->d.minor = minor;
+
+ device_create(lirc_class, ir->d.dev,
+ MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
+ "lirc%u", ir->d.minor);
+
+ if (d->sample_rate) {
+ /* try to fire up polling thread */
+ ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev");
+ if (IS_ERR(ir->task)) {
+ dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+ "cannot run poll thread for minor = %d\n",
+ d->minor);
+ err = -ECHILD;
+ goto out_sysfs;
+ }
+ }
+
+ err = lirc_cdev_add(ir);
+ if (err)
+ goto out_sysfs;
+
+ ir->attached = 1;
+ mutex_unlock(&lirc_dev_lock);
+
+ dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
+ ir->d.name, ir->d.minor);
+ return minor;
+
+out_sysfs:
+ device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
+out_lock:
+ mutex_unlock(&lirc_dev_lock);
+out:
+ return err;
+}
+EXPORT_SYMBOL(lirc_register_driver);
+
+int lirc_unregister_driver(int minor)
+{
+ struct irctl *ir;
+
+ if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
+ printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
+ "\"minor (%d)\" must be between 0 and %d!\n",
+ minor, MAX_IRCTL_DEVICES-1);
+ return -EBADRQC;
+ }
+
+ ir = irctls[minor];
+
+ mutex_lock(&lirc_dev_lock);
+
+ if (ir->d.minor != minor) {
+ printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
+ "minor (%d) device not registered!", minor);
+ mutex_unlock(&lirc_dev_lock);
+ return -ENOENT;
+ }
+
+ /* end up polling thread */
+ if (ir->task)
+ kthread_stop(ir->task);
+
+ dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
+ ir->d.name, ir->d.minor);
+
+ ir->attached = 0;
+ if (ir->open) {
+ dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
+ ir->d.name, ir->d.minor);
+ wake_up_interruptible(&ir->buf->wait_poll);
+ mutex_lock(&ir->buffer_lock);
+ ir->d.set_use_dec(ir->d.data);
+ module_put(ir->d.owner);
+ mutex_unlock(&ir->buffer_lock);
+ cdev_del(&ir->cdev);
+ } else {
+ cleanup(ir);
+ cdev_del(&ir->cdev);
+ kfree(ir);
+ irctls[minor] = NULL;
+ }
+
+ mutex_unlock(&lirc_dev_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(lirc_unregister_driver);
+
+int lirc_dev_fop_open(struct inode *inode, struct file *file)
+{
+ struct irctl *ir;
+ int retval = 0;
+
+ if (iminor(inode) >= MAX_IRCTL_DEVICES) {
+ printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n",
+ iminor(inode));
+ return -ENODEV;
+ }
+
+ if (mutex_lock_interruptible(&lirc_dev_lock))
+ return -ERESTARTSYS;
+
+ ir = irctls[iminor(inode)];
+ if (!ir) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
+
+ if (ir->d.minor == NOPLUG) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ if (ir->open) {
+ retval = -EBUSY;
+ goto error;
+ }
+
+ if (try_module_get(ir->d.owner)) {
+ ++ir->open;
+ retval = ir->d.set_use_inc(ir->d.data);
+
+ if (retval) {
+ module_put(ir->d.owner);
+ --ir->open;
+ } else {
+ lirc_buffer_clear(ir->buf);
+ }
+ if (ir->task)
+ wake_up_process(ir->task);
+ }
+
+error:
+ if (ir)
+ dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n",
+ ir->d.name, ir->d.minor, retval);
+
+ mutex_unlock(&lirc_dev_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(lirc_dev_fop_open);
+
+int lirc_dev_fop_close(struct inode *inode, struct file *file)
+{
+ struct irctl *ir = irctls[iminor(inode)];
+
+ dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
+
+ WARN_ON(mutex_lock_killable(&lirc_dev_lock));
+
+ --ir->open;
+ if (ir->attached) {
+ ir->d.set_use_dec(ir->d.data);
+ module_put(ir->d.owner);
+ } else {
+ cleanup(ir);
+ irctls[ir->d.minor] = NULL;
+ kfree(ir);
+ }
+
+ mutex_unlock(&lirc_dev_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(lirc_dev_fop_close);
+
+unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
+{
+ struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+ unsigned int ret;
+
+ dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
+
+ if (!ir->attached) {
+ mutex_unlock(&ir->buffer_lock);
+ return POLLERR;
+ }
+
+ poll_wait(file, &ir->buf->wait_poll, wait);
+
+ if (ir->buf)
+ if (lirc_buffer_empty(ir->buf))
+ ret = 0;
+ else
+ ret = POLLIN | POLLRDNORM;
+ else
+ ret = POLLERR;
+
+ dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
+ ir->d.name, ir->d.minor, ret);
+
+ return ret;
+}
+EXPORT_SYMBOL(lirc_dev_fop_poll);
+
+int lirc_dev_fop_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ unsigned long mode;
+ int result = 0;
+ struct irctl *ir = irctls[iminor(inode)];
+
+ dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
+ ir->d.name, ir->d.minor, cmd);
+
+ if (ir->d.minor == NOPLUG || !ir->attached) {
+ dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
+ ir->d.name, ir->d.minor);
+ return -ENODEV;
+ }
+
+ switch (cmd) {
+ case LIRC_GET_FEATURES:
+ result = put_user(ir->d.features, (unsigned long *)arg);
+ break;
+ case LIRC_GET_REC_MODE:
+ if (!(ir->d.features & LIRC_CAN_REC_MASK))
+ return -ENOSYS;
+
+ result = put_user(LIRC_REC2MODE
+ (ir->d.features & LIRC_CAN_REC_MASK),
+ (unsigned long *)arg);
+ break;
+ case LIRC_SET_REC_MODE:
+ if (!(ir->d.features & LIRC_CAN_REC_MASK))
+ return -ENOSYS;
+
+ result = get_user(mode, (unsigned long *)arg);
+ if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
+ result = -EINVAL;
+ /*
+ * FIXME: We should actually set the mode somehow but
+ * for now, lirc_serial doesn't support mode changing either
+ */
+ break;
+ case LIRC_GET_LENGTH:
+ result = put_user(ir->d.code_length, (unsigned long *)arg);
+ break;
+ default:
+ result = -EINVAL;
+ }
+
+ dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n",
+ ir->d.name, ir->d.minor, result);
+
+ return result;
+}
+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,
+ loff_t *ppos)
+{
+ struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+ unsigned char buf[ir->chunk_size];
+ int ret = 0, written = 0;
+ DECLARE_WAITQUEUE(wait, current);
+
+ dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
+
+ if (mutex_lock_interruptible(&ir->buffer_lock))
+ return -ERESTARTSYS;
+ if (!ir->attached) {
+ mutex_unlock(&ir->buffer_lock);
+ return -ENODEV;
+ }
+
+ if (length % ir->chunk_size) {
+ dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n",
+ ir->d.name, ir->d.minor);
+ mutex_unlock(&ir->buffer_lock);
+ return -EINVAL;
+ }
+
+ /*
+ * we add ourselves to the task queue before buffer check
+ * to avoid losing scan code (in case when queue is awaken somewhere
+ * between while condition checking and scheduling)
+ */
+ add_wait_queue(&ir->buf->wait_poll, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ /*
+ * while we didn't provide 'length' bytes, device is opened in blocking
+ * mode and 'copy_to_user' is happy, wait for data.
+ */
+ while (written < length && ret == 0) {
+ if (lirc_buffer_empty(ir->buf)) {
+ /* According to the read(2) man page, 'written' can be
+ * returned as less than 'length', instead of blocking
+ * again, returning -EWOULDBLOCK, or returning
+ * -ERESTARTSYS */
+ if (written)
+ break;
+ if (file->f_flags & O_NONBLOCK) {
+ ret = -EWOULDBLOCK;
+ break;
+ }
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ mutex_unlock(&ir->buffer_lock);
+ schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (mutex_lock_interruptible(&ir->buffer_lock)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ if (!ir->attached) {
+ ret = -ENODEV;
+ break;
+ }
+ } else {
+ lirc_buffer_read(ir->buf, buf);
+ ret = copy_to_user((void *)buffer+written, buf,
+ ir->buf->chunk_size);
+ written += ir->buf->chunk_size;
+ }
+ }
+
+ remove_wait_queue(&ir->buf->wait_poll, &wait);
+ set_current_state(TASK_RUNNING);
+ mutex_unlock(&ir->buffer_lock);
+
+ dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
+ ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
+
+ return ret ? ret : written;
+}
+EXPORT_SYMBOL(lirc_dev_fop_read);
+
+void *lirc_get_pdata(struct file *file)
+{
+ void *data = NULL;
+
+ if (file && file->f_dentry && file->f_dentry->d_inode &&
+ file->f_dentry->d_inode->i_rdev) {
+ struct irctl *ir;
+ ir = irctls[iminor(file->f_dentry->d_inode)];
+ data = ir->d.data;
+ }
+
+ return data;
+}
+EXPORT_SYMBOL(lirc_get_pdata);
+
+
+ssize_t lirc_dev_fop_write(struct file *file, const char *buffer,
+ size_t length, loff_t *ppos)
+{
+ struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+
+ dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
+
+ if (!ir->attached)
+ return -ENODEV;
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(lirc_dev_fop_write);
+
+
+static int __init lirc_dev_init(void)
+{
+ int retval;
+
+ lirc_class = class_create(THIS_MODULE, "lirc");
+ if (IS_ERR(lirc_class)) {
+ retval = PTR_ERR(lirc_class);
+ printk(KERN_ERR "lirc_dev: class_create failed\n");
+ goto error;
+ }
+
+ retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES,
+ IRCTL_DEV_NAME);
+ if (retval) {
+ class_destroy(lirc_class);
+ printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n");
+ goto error;
+ }
+
+
+ printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, "
+ "major %d \n", MAJOR(lirc_base_dev));
+
+error:
+ return retval;
+}
+
+
+
+static void __exit lirc_dev_exit(void)
+{
+ class_destroy(lirc_class);
+ unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES);
+ printk(KERN_INFO "lirc_dev: module unloaded\n");
+}
+
+module_init(lirc_dev_init);
+module_exit(lirc_dev_exit);
+
+MODULE_DESCRIPTION("LIRC base driver module");
+MODULE_AUTHOR("Artur Lipowski");
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
Index: b/drivers/input/lirc/lirc_dev.h
===================================================================
--- /dev/null
+++ b/drivers/input/lirc/lirc_dev.h
@@ -0,0 +1,194 @@
+/*
+ * LIRC base driver
+ *
+ * by Artur Lipowski <[email protected]>
+ * This code is licensed under GNU GPL
+ *
+ */
+
+#ifndef _LINUX_LIRC_DEV_H
+#define _LINUX_LIRC_DEV_H
+
+#define MAX_IRCTL_DEVICES 4
+#define BUFLEN 16
+
+#define mod(n, div) ((n) % (div))
+
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+#include <linux/kfifo.h>
+
+struct lirc_buffer {
+ wait_queue_head_t wait_poll;
+ spinlock_t lock;
+ unsigned int chunk_size;
+ unsigned int size; /* in chunks */
+ /* Using chunks instead of bytes pretends to simplify boundary checking
+ * And should allow for some performance fine tunning later */
+ struct kfifo *fifo;
+};
+
+static inline void lirc_buffer_clear(struct lirc_buffer *buf)
+{
+ if (buf->fifo)
+ kfifo_reset(buf->fifo);
+ else
+ WARN(1, "calling %s on an uninitialized lirc_buffer\n",
+ __func__);
+}
+
+static inline int lirc_buffer_init(struct lirc_buffer *buf,
+ unsigned int chunk_size,
+ unsigned int size)
+{
+ init_waitqueue_head(&buf->wait_poll);
+ spin_lock_init(&buf->lock);
+ buf->chunk_size = chunk_size;
+ buf->size = size;
+ buf->fifo = kfifo_alloc(size*chunk_size, GFP_KERNEL, &buf->lock);
+ if (!buf->fifo)
+ return -ENOMEM;
+ return 0;
+}
+
+static inline void lirc_buffer_free(struct lirc_buffer *buf)
+{
+ if (buf->fifo)
+ kfifo_free(buf->fifo);
+ else
+ WARN(1, "calling %s on an uninitialized lirc_buffer\n",
+ __func__);
+}
+
+static inline int lirc_buffer_full(struct lirc_buffer *buf)
+{
+ return kfifo_len(buf->fifo) == buf->size * buf->chunk_size;
+}
+
+static inline int lirc_buffer_empty(struct lirc_buffer *buf)
+{
+ return !kfifo_len(buf->fifo);
+}
+
+static inline int lirc_buffer_available(struct lirc_buffer *buf)
+{
+ return buf->size - (kfifo_len(buf->fifo) / buf->chunk_size);
+}
+
+static inline void lirc_buffer_read(struct lirc_buffer *buf,
+ unsigned char *dest)
+{
+ if (kfifo_len(buf->fifo) >= buf->chunk_size)
+ kfifo_get(buf->fifo, dest, buf->chunk_size);
+}
+
+static inline void lirc_buffer_write(struct lirc_buffer *buf,
+ unsigned char *orig)
+{
+ kfifo_put(buf->fifo, orig, buf->chunk_size);
+}
+
+struct lirc_driver {
+ char name[40];
+ int minor;
+ unsigned long code_length;
+ unsigned int buffer_size; /* in chunks holding one code each */
+ int sample_rate;
+ unsigned long features;
+
+ unsigned int chunk_size;
+
+ void *data;
+ int (*add_to_buf) (void *data, struct lirc_buffer *buf);
+ struct lirc_buffer *rbuf;
+ int (*set_use_inc) (void *data);
+ void (*set_use_dec) (void *data);
+ struct file_operations *fops;
+ struct device *dev;
+ struct module *owner;
+};
+
+/* name:
+ * this string will be used for logs
+ *
+ * minor:
+ * indicates minor device (/dev/lirc) number for registered driver
+ * if caller fills it with negative value, then the first free minor
+ * number will be used (if available)
+ *
+ * code_length:
+ * length of the remote control key code expressed in bits
+ *
+ * sample_rate:
+ *
+ * data:
+ * it may point to any driver data and this pointer will be passed to
+ * all callback functions
+ *
+ * add_to_buf:
+ * add_to_buf will be called after specified period of the time or
+ * triggered by the external event, this behavior depends on value of
+ * the sample_rate this function will be called in user context. This
+ * routine should return 0 if data was added to the buffer and
+ * -ENODATA if none was available. This should add some number of bits
+ * evenly divisible by code_length to the buffer
+ *
+ * rbuf:
+ * if not NULL, it will be used as a read buffer, you will have to
+ * write to the buffer by other means, like irq's (see also
+ * lirc_serial.c).
+ *
+ * set_use_inc:
+ * set_use_inc will be called after device is opened
+ *
+ * set_use_dec:
+ * set_use_dec will be called after device is closed
+ *
+ * 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
+ *
+ */
+
+
+/* following functions can be called ONLY from user context
+ *
+ * returns negative value on error or minor number
+ * of the registered device if success
+ * contents of the structure pointed by p is copied
+ */
+extern int lirc_register_driver(struct lirc_driver *d);
+
+/* returns negative value on error or 0 if success
+*/
+extern int lirc_unregister_driver(int minor);
+
+/* Returns the private data stored in the lirc_driver
+ * associated with the given device file pointer.
+ */
+void *lirc_get_pdata(struct file *file);
+
+/* default file operations
+ * used by drivers if they override only some operations
+ */
+int lirc_dev_fop_open(struct inode *inode, struct file *file);
+int lirc_dev_fop_close(struct inode *inode, struct file *file);
+unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait);
+int lirc_dev_fop_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg);
+ssize_t lirc_dev_fop_read(struct file *file, char *buffer, size_t length,
+ loff_t *ppos);
+ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, size_t length,
+ loff_t *ppos);
+long lirc_dev_fop_compat_ioctl(struct file *file, unsigned int cmd32,
+ unsigned long arg);
+
+#endif
lirc driver for Windows Media Center Ed. IR transceivers
Successfully tested with the mce v2 transceiver and remote that shipped with a
Hauppauge HVR-1500 expresscard tuner and an mce v1 transceiver from an old HP
Media Center system.
Changes from prior submission:
- both v1 and v2 transceivers supported by one driver now
- transmit works on the v1 devices
- support for several new devices
- now uses dev_dbg (and friends) instead of its own dprintk
Signed-off-by: Jarod Wilson <[email protected]>
Signed-off-by: Janne Grunau <[email protected]>
CC: Christoph Bartelmus <[email protected]>
Tested-by: Jarod Wilson <[email protected]>
---
drivers/input/lirc/Kconfig | 6
drivers/input/lirc/Makefile | 1
drivers/input/lirc/lirc_mceusb.c | 1235 +++++++++++++++++++++++++++++++++++++++
3 files changed, 1241 insertions(+), 1 deletion(-)
Index: b/drivers/input/lirc/Kconfig
===================================================================
--- a/drivers/input/lirc/Kconfig
+++ b/drivers/input/lirc/Kconfig
@@ -11,6 +11,10 @@ menuconfig INPUT_LIRC
if INPUT_LIRC
-# Device-specific drivers go here
+config LIRC_MCEUSB
+ tristate "Windows Media Center Ed. USB IR Transceiver"
+ depends on LIRC_DEV && USB
+ help
+ Driver for Windows Media Center Ed. USB IR Transceivers
endif
Index: b/drivers/input/lirc/Makefile
===================================================================
--- a/drivers/input/lirc/Makefile
+++ b/drivers/input/lirc/Makefile
@@ -4,3 +4,4 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_INPUT_LIRC) += lirc_dev.o
+obj-$(CONFIG_LIRC_MCEUSB) += lirc_mceusb.o
Index: b/drivers/input/lirc/lirc_mceusb.c
===================================================================
--- /dev/null
+++ b/drivers/input/lirc/lirc_mceusb.c
@@ -0,0 +1,1235 @@
+/*
+ * LIRC driver for Windows Media Center Edition USB Infrared Transceivers
+ *
+ * (C) by Martin A. Blatter <[email protected]>
+ *
+ * Transmitter support and reception code cleanup.
+ * (C) by Daniel Melander <[email protected]>
+ *
+ * Original lirc_mceusb driver for 1st-gen device:
+ * Copyright (c) 2003-2004 Dan Conti <[email protected]>
+ *
+ * Original lirc_mceusb driver deprecated in favor of this driver, which
+ * supports the 1st-gen device now too. Transmitting on the 1st-gen device
+ * only functions on port #2 at the moment.
+ *
+ * Support for 1st-gen device added June 2009,
+ * by Jarod Wilson <[email protected]>
+ *
+ * Initial transmission support for 1st-gen device added August 2009,
+ * by Patrick Calhoun <[email protected]>
+ *
+ * Derived from ATI USB driver by Paul Miller and the original
+ * MCE USB driver by Dan Conti (and now including chunks of the latter
+ * relevant to the 1st-gen device initialization)
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/smp_lock.h>
+#include <linux/completion.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+
+#include "lirc.h"
+#include "lirc_dev.h"
+
+#define DRIVER_VERSION "1.90"
+#define DRIVER_AUTHOR "Daniel Melander <[email protected]>, " \
+ "Martin Blatter <[email protected]>, " \
+ "Dan Conti <[email protected]>"
+#define DRIVER_DESC "Windows Media Center Edition USB IR Transceiver " \
+ "driver for LIRC"
+#define DRIVER_NAME "lirc_mceusb"
+
+#define USB_BUFLEN 32 /* USB reception buffer length */
+#define LIRCBUF_SIZE 256 /* LIRC work buffer length */
+
+/* MCE constants */
+#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */
+#define MCE_TIME_UNIT 50 /* Approx 50us resolution */
+#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */
+#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */
+#define MCE_PACKET_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */
+#define MCE_CONTROL_HEADER 0x9F /* MCE status header */
+#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */
+#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */
+#define MCE_DEFAULT_TX_MASK 0x03 /* Val opts: TX1=0x01, TX2=0x02, ALL=0x03 */
+#define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */
+#define MCE_PULSE_MASK 0x7F /* Pulse mask */
+#define MCE_MAX_PULSE_LENGTH 0x7F /* Longest transmittable pulse symbol */
+#define MCE_PACKET_LENGTH_MASK 0x7F /* Pulse mask */
+
+
+/* module parameters */
+#ifdef CONFIG_USB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+
+/* general constants */
+#define SEND_FLAG_IN_PROGRESS 1
+#define SEND_FLAG_COMPLETE 2
+#define RECV_FLAG_IN_PROGRESS 3
+#define RECV_FLAG_COMPLETE 4
+
+#define MCEUSB_INBOUND 1
+#define MCEUSB_OUTBOUND 2
+
+#define VENDOR_PHILIPS 0x0471
+#define VENDOR_SMK 0x0609
+#define VENDOR_TATUNG 0x1460
+#define VENDOR_GATEWAY 0x107b
+#define VENDOR_SHUTTLE 0x1308
+#define VENDOR_SHUTTLE2 0x051c
+#define VENDOR_MITSUMI 0x03ee
+#define VENDOR_TOPSEED 0x1784
+#define VENDOR_RICAVISION 0x179d
+#define VENDOR_ITRON 0x195d
+#define VENDOR_FIC 0x1509
+#define VENDOR_LG 0x043e
+#define VENDOR_MICROSOFT 0x045e
+#define VENDOR_FORMOSA 0x147a
+#define VENDOR_FINTEK 0x1934
+#define VENDOR_PINNACLE 0x2304
+#define VENDOR_ECS 0x1019
+#define VENDOR_WISTRON 0x0fb8
+#define VENDOR_COMPRO 0x185b
+#define VENDOR_NORTHSTAR 0x04eb
+
+static struct usb_device_id mceusb_dev_table[] = {
+ /* Original Microsoft MCE IR Transceiver (often HP-branded) */
+ { USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
+ /* Philips Infrared Transceiver - Sahara branded */
+ { USB_DEVICE(VENDOR_PHILIPS, 0x0608) },
+ /* Philips Infrared Transceiver - HP branded */
+ { USB_DEVICE(VENDOR_PHILIPS, 0x060c) },
+ /* Philips SRM5100 */
+ { USB_DEVICE(VENDOR_PHILIPS, 0x060d) },
+ /* Philips Infrared Transceiver - Omaura */
+ { USB_DEVICE(VENDOR_PHILIPS, 0x060f) },
+ /* Philips Infrared Transceiver - Spinel plus */
+ { USB_DEVICE(VENDOR_PHILIPS, 0x0613) },
+ /* Philips eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_PHILIPS, 0x0815) },
+ /* SMK/Toshiba G83C0004D410 */
+ { USB_DEVICE(VENDOR_SMK, 0x031d) },
+ /* SMK eHome Infrared Transceiver (Sony VAIO) */
+ { USB_DEVICE(VENDOR_SMK, 0x0322) },
+ /* bundled with Hauppauge PVR-150 */
+ { USB_DEVICE(VENDOR_SMK, 0x0334) },
+ /* Tatung eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_TATUNG, 0x9150) },
+ /* Shuttle eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_SHUTTLE, 0xc001) },
+ /* Shuttle eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) },
+ /* Gateway eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_GATEWAY, 0x3009) },
+ /* Mitsumi */
+ { USB_DEVICE(VENDOR_MITSUMI, 0x2501) },
+ /* Topseed eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_TOPSEED, 0x0001) },
+ /* Topseed HP eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_TOPSEED, 0x0006) },
+ /* Topseed eHome Infrared Transceiver */
+ { 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 */
+ { USB_DEVICE(VENDOR_ITRON, 0x7002) },
+ /* FIC eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_FIC, 0x9242) },
+ /* LG eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_LG, 0x9803) },
+ /* Microsoft MCE Infrared Transceiver */
+ { USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) },
+ /* Formosa eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_FORMOSA, 0xe015) },
+ /* Formosa21 / eHome Infrared Receiver */
+ { USB_DEVICE(VENDOR_FORMOSA, 0xe016) },
+ /* Formosa aim / Trust MCE Infrared Receiver */
+ { USB_DEVICE(VENDOR_FORMOSA, 0xe017) },
+ /* Formosa Industrial Computing / Beanbag Emulation Device */
+ { USB_DEVICE(VENDOR_FORMOSA, 0xe018) },
+ /* Formosa21 / eHome Infrared Receiver */
+ { USB_DEVICE(VENDOR_FORMOSA, 0xe03a) },
+ /* Formosa Industrial Computing AIM IR605/A */
+ { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
+ /* Fintek eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_FINTEK, 0x0602) },
+ /* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
+ { USB_DEVICE(VENDOR_FINTEK, 0x0702) },
+ /* Pinnacle Remote Kit */
+ { USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
+ /* Elitegroup Computer Systems IR */
+ { USB_DEVICE(VENDOR_ECS, 0x0f38) },
+ /* Wistron Corp. eHome Infrared Receiver */
+ { USB_DEVICE(VENDOR_WISTRON, 0x0002) },
+ /* Compro K100 */
+ { USB_DEVICE(VENDOR_COMPRO, 0x3020) },
+ /* Compro K100 v2 */
+ { USB_DEVICE(VENDOR_COMPRO, 0x3082) },
+ /* Northstar Systems, Inc. eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
+ /* Terminating entry */
+ { }
+};
+
+static struct usb_device_id pinnacle_list[] = {
+ { USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
+ {}
+};
+
+static struct usb_device_id microsoft_gen1_list[] = {
+ { USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
+ {}
+};
+
+static struct usb_device_id transmitter_mask_list[] = {
+ { USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
+ { USB_DEVICE(VENDOR_SMK, 0x031d) },
+ { USB_DEVICE(VENDOR_SMK, 0x0322) },
+ { USB_DEVICE(VENDOR_SMK, 0x0334) },
+ { USB_DEVICE(VENDOR_TOPSEED, 0x0001) },
+ { USB_DEVICE(VENDOR_TOPSEED, 0x0006) },
+ { USB_DEVICE(VENDOR_TOPSEED, 0x0007) },
+ { USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
+ { USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
+ { USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
+ {}
+};
+
+/* data structure for each usb transceiver */
+struct mceusb_dev {
+
+ /* usb */
+ struct usb_device *usbdev;
+ struct urb *urb_in;
+ int devnum;
+ struct usb_endpoint_descriptor *usb_ep_in;
+ struct usb_endpoint_descriptor *usb_ep_out;
+
+ /* buffers and dma */
+ unsigned char *buf_in;
+ unsigned int len_in;
+ dma_addr_t dma_in;
+ dma_addr_t dma_out;
+ unsigned int overflow_len;
+
+ /* lirc */
+ struct lirc_driver *d;
+ int lircdata;
+ unsigned char is_pulse;
+ struct {
+ u32 connected:1;
+ u32 pinnacle:1;
+ u32 transmitter_mask_inverted:1;
+ u32 microsoft_gen1:1;
+ u32 reserved:28;
+ } flags;
+
+ unsigned char transmitter_mask;
+ unsigned int carrier_freq;
+
+ /* handle sending (init strings) */
+ int send_flags;
+ wait_queue_head_t wait_out;
+
+ struct mutex lock;
+};
+
+/* init strings */
+static char init1[] = {0x00, 0xff, 0xaa, 0xff, 0x0b};
+static char init2[] = {0xff, 0x18};
+
+static char pin_init1[] = { 0x9f, 0x07};
+static char pin_init2[] = { 0x9f, 0x13};
+static char pin_init3[] = { 0x9f, 0x0d};
+
+static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, int len)
+{
+ char codes[USB_BUFLEN * 3 + 1];
+ int i;
+
+ if (len <= 0)
+ return;
+
+ if (ir->flags.microsoft_gen1 && len <= 2)
+ return;
+
+ 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);
+}
+
+static void usb_async_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct mceusb_dev *ir;
+ int len;
+
+ if (!urb)
+ return;
+
+ ir = urb->context;
+ if (ir) {
+ len = urb->actual_length;
+
+ dev_dbg(ir->d->dev, "callback called (status=%d len=%d)\n",
+ urb->status, len);
+
+ if (debug)
+ mceusb_dev_printdata(ir, urb->transfer_buffer, len);
+ }
+
+}
+
+/* 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)
+{
+ int res;
+ struct urb *async_urb;
+ unsigned char *async_buf;
+
+ if (urb_type) {
+ async_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (unlikely(!async_urb))
+ return;
+
+ async_buf = kmalloc(size, GFP_KERNEL);
+ if (!async_buf) {
+ 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);
+ }
+
+ } else {
+ /* standard request */
+ async_urb = ir->urb_in;
+ ir->send_flags = RECV_FLAG_IN_PROGRESS;
+ }
+
+ dev_dbg(ir->d->dev, "receive request called (size=%#x)\n", size);
+
+ async_urb->transfer_buffer_length = size;
+ async_urb->dev = ir->usbdev;
+
+ res = usb_submit_urb(async_urb, GFP_ATOMIC);
+ if (res) {
+ dev_dbg(ir->d->dev, "receive request FAILED! (res=%d)\n", res);
+ return;
+ }
+ dev_dbg(ir->d->dev, "receive request complete (res=%d)\n", res);
+}
+
+static int unregister_from_lirc(struct mceusb_dev *ir)
+{
+ struct lirc_driver *d = ir->d;
+ int devnum;
+ int rtn;
+
+ devnum = ir->devnum;
+ dev_dbg(ir->d->dev, "unregister from lirc called\n");
+
+ rtn = lirc_unregister_driver(d->minor);
+ if (rtn > 0) {
+ dev_info(ir->d->dev, "error in lirc_unregister minor: %d\n"
+ "Trying again...\n", d->minor);
+ if (rtn == -EBUSY) {
+ dev_info(ir->d->dev, "device is opened, will "
+ "unregister on close\n");
+ return -EAGAIN;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+
+ rtn = lirc_unregister_driver(d->minor);
+ if (rtn > 0)
+ dev_info(ir->d->dev, "lirc_unregister failed\n");
+ }
+
+ if (rtn) {
+ dev_info(ir->d->dev, "didn't free resources\n");
+ return -EAGAIN;
+ }
+
+ dev_info(ir->d->dev, "usb remote disconnected\n");
+
+ lirc_buffer_free(d->rbuf);
+ kfree(d->rbuf);
+ kfree(d);
+ kfree(ir);
+ return 0;
+}
+
+static int mceusb_ir_open(void *data)
+{
+ struct mceusb_dev *ir = data;
+
+ if (!ir) {
+ printk(KERN_WARNING DRIVER_NAME
+ "[?]: %s called with no context\n", __func__);
+ return -EIO;
+ }
+
+ dev_dbg(ir->d->dev, "mceusb IR device opened\n");
+
+ if (!ir->flags.connected) {
+ if (!ir->usbdev)
+ return -ENOENT;
+ ir->flags.connected = 1;
+ }
+
+ return 0;
+}
+
+static void mceusb_ir_close(void *data)
+{
+ struct mceusb_dev *ir = data;
+
+ if (!ir) {
+ printk(KERN_WARNING DRIVER_NAME
+ "[?]: %s called with no context\n", __func__);
+ return;
+ }
+
+ dev_dbg(ir->d->dev, "mceusb IR device closed\n");
+
+ if (ir->flags.connected) {
+ mutex_lock(&ir->lock);
+ ir->flags.connected = 0;
+ mutex_unlock(&ir->lock);
+ }
+}
+
+static void send_packet_to_lirc(struct mceusb_dev *ir)
+{
+ if (ir->lircdata) {
+ lirc_buffer_write(ir->d->rbuf,
+ (unsigned char *) &ir->lircdata);
+ wake_up(&ir->d->rbuf->wait_poll);
+ ir->lircdata = 0;
+ }
+}
+
+static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
+{
+ int i, j;
+ int packet_len = 0;
+ int start_index = 0;
+
+ /* skip meaningless 0xb1 0x60 header bytes on orig receiver */
+ if (ir->flags.microsoft_gen1)
+ start_index = 2;
+
+ /* this should only trigger w/the 1st-gen mce receiver */
+ for (i = start_index; i < (start_index + ir->overflow_len) &&
+ i < buf_len; i++) {
+ /* rising/falling flank */
+ if (ir->is_pulse != (ir->buf_in[i] & MCE_PULSE_BIT)) {
+ send_packet_to_lirc(ir);
+ ir->is_pulse = ir->buf_in[i] & MCE_PULSE_BIT;
+ }
+
+ /* accumulate mce pulse/space values */
+ ir->lircdata += (ir->buf_in[i] & MCE_PULSE_MASK) *
+ MCE_TIME_UNIT;
+ ir->lircdata |= (ir->is_pulse ? PULSE_BIT : 0);
+ }
+ start_index += ir->overflow_len;
+ ir->overflow_len = 0;
+
+ for (i = start_index; i < buf_len; i++) {
+ /* decode mce packets of the form (84),AA,BB,CC,DD */
+
+ /* data headers */
+ if (ir->buf_in[i] >= 0x80 && ir->buf_in[i] <= 0x9e) {
+ /* decode packet data */
+ packet_len = ir->buf_in[i] & MCE_PACKET_LENGTH_MASK;
+ ir->overflow_len = i + 1 + packet_len - buf_len;
+ for (j = 1; j <= packet_len && (i + j < buf_len); j++) {
+ /* rising/falling flank */
+ if (ir->is_pulse !=
+ (ir->buf_in[i + j] & MCE_PULSE_BIT)) {
+ send_packet_to_lirc(ir);
+ ir->is_pulse =
+ ir->buf_in[i + j] &
+ MCE_PULSE_BIT;
+ }
+
+ /* accumulate mce pulse/space values */
+ ir->lircdata +=
+ (ir->buf_in[i + j] & MCE_PULSE_MASK) *
+ MCE_TIME_UNIT;
+ ir->lircdata |= (ir->is_pulse ? PULSE_BIT : 0);
+ }
+
+ i += packet_len;
+
+ /* status header (0x9F) */
+ } else if (ir->buf_in[i] == MCE_CONTROL_HEADER) {
+ /*
+ * A transmission containing one or more consecutive ir
+ * commands always ends with a GAP of 100ms followed by
+ * the sequence 0x9F 0x01 0x01 0x9F 0x15 0x00 0x00 0x80
+ */
+
+#if 0
+ Uncomment this if the last 100ms "infinity"-space should be transmitted
+ to lirc directly instead of at the beginning of the next transmission.
+ Changes pulse/space order.
+
+ if (++i < buf_len && ir->buf_in[i] == 0x01)
+ send_packet_to_lirc(ir);
+
+#endif
+
+ /* end decode loop */
+ dev_dbg(ir->d->dev, "[%d] %s: found control header\n",
+ ir->devnum, __func__);
+ ir->overflow_len = 0;
+ break;
+ } else {
+ dev_dbg(ir->d->dev, "[%d] %s: stray packet?\n",
+ ir->devnum, __func__);
+ ir->overflow_len = 0;
+ }
+ }
+
+ return;
+}
+
+static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
+{
+ struct mceusb_dev *ir;
+ int buf_len;
+
+ if (!urb)
+ return;
+
+ ir = urb->context;
+ if (!ir) {
+ usb_unlink_urb(urb);
+ return;
+ }
+
+ buf_len = urb->actual_length;
+
+ if (debug)
+ mceusb_dev_printdata(ir, urb->transfer_buffer, buf_len);
+
+ if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
+ ir->send_flags = SEND_FLAG_COMPLETE;
+ dev_dbg(ir->d->dev, "setup answer received %d bytes\n",
+ buf_len);
+ }
+
+ switch (urb->status) {
+ /* success */
+ case 0:
+ mceusb_process_ir_data(ir, buf_len);
+ break;
+
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ usb_unlink_urb(urb);
+ return;
+
+ case -EPIPE:
+ default:
+ break;
+ }
+
+ usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+
+static ssize_t mceusb_transmit_ir(struct file *file, const char *buf,
+ size_t n, loff_t *ppos)
+{
+ int i, count = 0, cmdcount = 0;
+ struct mceusb_dev *ir = NULL;
+ int wbuf[LIRCBUF_SIZE]; /* Workbuffer with values from lirc */
+ unsigned char cmdbuf[MCE_CMDBUF_SIZE]; /* MCE command buffer */
+ unsigned long signal_duration = 0; /* Singnal length in us */
+ struct timeval start_time, end_time;
+
+ do_gettimeofday(&start_time);
+
+ /* Retrieve lirc_driver data for the device */
+ ir = lirc_get_pdata(file);
+ if (!ir || !ir->usb_ep_out)
+ return -EFAULT;
+
+ if (n % sizeof(int))
+ return -EINVAL;
+ count = n / sizeof(int);
+
+ /* Check if command is within limits */
+ if (count > LIRCBUF_SIZE || count%2 == 0)
+ return -EINVAL;
+ if (copy_from_user(wbuf, buf, n))
+ return -EFAULT;
+
+ /* MCE tx init header */
+ cmdbuf[cmdcount++] = MCE_CONTROL_HEADER;
+ cmdbuf[cmdcount++] = 0x08;
+ cmdbuf[cmdcount++] = ir->transmitter_mask;
+
+ /* Generate mce packet data */
+ for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) {
+ signal_duration += wbuf[i];
+ wbuf[i] = wbuf[i] / MCE_TIME_UNIT;
+
+ do { /* loop to support long pulses/spaces > 127*50us=6.35ms */
+
+ /* Insert mce packet header every 4th entry */
+ if ((cmdcount < MCE_CMDBUF_SIZE) &&
+ (cmdcount - MCE_TX_HEADER_LENGTH) %
+ MCE_CODE_LENGTH == 0)
+ cmdbuf[cmdcount++] = MCE_PACKET_HEADER;
+
+ /* Insert mce packet data */
+ if (cmdcount < MCE_CMDBUF_SIZE)
+ cmdbuf[cmdcount++] =
+ (wbuf[i] < MCE_PULSE_BIT ?
+ wbuf[i] : MCE_MAX_PULSE_LENGTH) |
+ (i & 1 ? 0x00 : MCE_PULSE_BIT);
+ else
+ return -EINVAL;
+ } while ((wbuf[i] > MCE_MAX_PULSE_LENGTH) &&
+ (wbuf[i] -= MCE_MAX_PULSE_LENGTH));
+ }
+
+ /* Fix packet length in last header */
+ cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] =
+ 0x80 + (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH - 1;
+
+ /* Check if we have room for the empty packet at the end */
+ if (cmdcount >= MCE_CMDBUF_SIZE)
+ return -EINVAL;
+
+ /* All mce commands end with an empty packet (0x80) */
+ cmdbuf[cmdcount++] = 0x80;
+
+ /* Transmit the command to the mce device */
+ request_packet_async(ir, ir->usb_ep_out, cmdbuf,
+ cmdcount, MCEUSB_OUTBOUND);
+
+ /*
+ * The lircd gap calculation expects the write function to
+ * wait the time it takes for the ircommand to be sent before
+ * it returns.
+ */
+ do_gettimeofday(&end_time);
+ signal_duration -= (end_time.tv_usec - start_time.tv_usec) +
+ (end_time.tv_sec - start_time.tv_sec) * 1000000;
+
+ /* delay with the closest number of ticks */
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies(signal_duration));
+
+ return n;
+}
+
+static void set_transmitter_mask(struct mceusb_dev *ir, unsigned int mask)
+{
+ if (ir->flags.transmitter_mask_inverted)
+ ir->transmitter_mask = (mask != 0x03 ? mask ^ 0x03 : mask) << 1;
+ else
+ ir->transmitter_mask = mask;
+}
+
+
+/* Sets the send carrier frequency */
+static int set_send_carrier(struct mceusb_dev *ir, int carrier)
+{
+ int clk = 10000000;
+ int prescaler = 0, divisor = 0;
+ unsigned char cmdbuf[] = { 0x9F, 0x06, 0x01, 0x80 };
+
+ /* Carrier is changed */
+ if (ir->carrier_freq != carrier) {
+
+ if (carrier <= 0) {
+ 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);
+ return carrier;
+ }
+
+ for (prescaler = 0; prescaler < 4; ++prescaler) {
+ divisor = (clk >> (2 * prescaler)) / carrier;
+ if (divisor <= 0xFF) {
+ ir->carrier_freq = carrier;
+ cmdbuf[2] = prescaler;
+ cmdbuf[3] = divisor;
+ dev_dbg(ir->d->dev, "SET_CARRIER requesting "
+ "%d Hz\n", carrier);
+
+ /* Transmit new carrier to mce device */
+ request_packet_async(ir, ir->usb_ep_out,
+ cmdbuf, sizeof(cmdbuf),
+ MCEUSB_OUTBOUND);
+ return carrier;
+ }
+ }
+
+ return -EINVAL;
+
+ }
+
+ return carrier;
+}
+
+
+static int mceusb_lirc_ioctl(struct inode *node, struct file *filep,
+ unsigned int cmd, unsigned long arg)
+{
+ int result;
+ unsigned int ivalue;
+ unsigned long lvalue;
+ struct mceusb_dev *ir = NULL;
+
+ /* Retrieve lirc_driver data for the device */
+ ir = lirc_get_pdata(filep);
+ if (!ir || !ir->usb_ep_out)
+ return -EFAULT;
+
+
+ switch (cmd) {
+ case LIRC_SET_TRANSMITTER_MASK:
+
+ result = get_user(ivalue, (unsigned int *) arg);
+ if (result)
+ return result;
+ switch (ivalue) {
+ case 0x01: /* Transmitter 1 => 0x04 */
+ case 0x02: /* Transmitter 2 => 0x02 */
+ case 0x03: /* Transmitter 1 & 2 => 0x06 */
+ set_transmitter_mask(ir, ivalue);
+ break;
+
+ default: /* Unsupported transmitter mask */
+ return MCE_MAX_CHANNELS;
+ }
+
+ dev_dbg(ir->d->dev, ": SET_TRANSMITTERS mask=%d\n", ivalue);
+ break;
+
+ case LIRC_GET_SEND_MODE:
+
+ result = put_user(LIRC_SEND2MODE(LIRC_CAN_SEND_PULSE &
+ LIRC_CAN_SEND_MASK),
+ (unsigned long *) arg);
+
+ if (result)
+ return result;
+ break;
+
+ case LIRC_SET_SEND_MODE:
+
+ result = get_user(lvalue, (unsigned long *) arg);
+
+ if (result)
+ return result;
+ if (lvalue != (LIRC_MODE_PULSE&LIRC_CAN_SEND_MASK))
+ return -EINVAL;
+ break;
+
+ case LIRC_SET_SEND_CARRIER:
+
+ result = get_user(ivalue, (unsigned int *) arg);
+ if (result)
+ return result;
+
+ set_send_carrier(ir, ivalue);
+ break;
+
+ default:
+ return lirc_dev_fop_ioctl(node, filep, cmd, arg);
+ }
+
+ return 0;
+}
+
+static struct file_operations lirc_fops = {
+ .owner = THIS_MODULE,
+ .write = mceusb_transmit_ir,
+ .ioctl = mceusb_lirc_ioctl,
+ .read = lirc_dev_fop_read,
+ .poll = lirc_dev_fop_poll,
+ .open = lirc_dev_fop_open,
+ .release = lirc_dev_fop_close,
+};
+
+static int mceusb_gen1_init(struct mceusb_dev *ir)
+{
+ int i, ret;
+ char junk[64], data[8];
+ int partial = 0;
+
+ /*
+ * Clear off the first few messages. These look like calibration
+ * or test data, I can't really tell. This also flushes in case
+ * we have random ir data queued up.
+ */
+ for (i = 0; i < 40; i++)
+ usb_bulk_msg(ir->usbdev,
+ usb_rcvbulkpipe(ir->usbdev,
+ ir->usb_ep_in->bEndpointAddress),
+ junk, 64, &partial, HZ * 10);
+
+ ir->is_pulse = 1;
+
+ memset(data, 0, 8);
+
+ /* Get Status */
+ ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
+ USB_REQ_GET_STATUS, USB_DIR_IN,
+ 0, 0, data, 2, HZ * 3);
+
+ /* ret = usb_get_status( ir->usbdev, 0, 0, data ); */
+ dev_dbg(ir->d->dev, "%s - ret = %d status = 0x%x 0x%x\n", __func__,
+ ret, data[0], data[1]);
+
+ /*
+ * This is a strange one. They issue a set address to the device
+ * on the receive control pipe and expect a certain value pair back
+ */
+ memset(data, 0, 8);
+
+ ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
+ USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
+ data, 2, HZ * 3);
+ dev_dbg(ir->d->dev, "%s - ret = %d, devnum = %d\n",
+ __func__, ret, ir->usbdev->devnum);
+ dev_dbg(ir->d->dev, "%s - data[0] = %d, data[1] = %d\n",
+ __func__, data[0], data[1]);
+
+ /* set feature: bit rate 38400 bps */
+ ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+ USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
+ 0xc04e, 0x0000, NULL, 0, HZ * 3);
+
+ dev_dbg(ir->d->dev, "%s - ret = %d\n", __func__, ret);
+
+ /* bRequest 4: set char length to 8 bits */
+ ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+ 4, USB_TYPE_VENDOR,
+ 0x0808, 0x0000, NULL, 0, HZ * 3);
+ dev_dbg(ir->d->dev, "%s - retB = %d\n", __func__, ret);
+
+ /* bRequest 2: set handshaking to use DTR/DSR */
+ ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+ 2, USB_TYPE_VENDOR,
+ 0x0000, 0x0100, NULL, 0, HZ * 3);
+ dev_dbg(ir->d->dev, "%s - retC = %d\n", __func__, ret);
+
+ return ret;
+
+};
+
+static int mceusb_dev_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct usb_host_interface *idesc;
+ struct usb_endpoint_descriptor *ep = NULL;
+ struct usb_endpoint_descriptor *ep_in = NULL;
+ struct usb_endpoint_descriptor *ep_out = NULL;
+ struct usb_host_config *config;
+ struct mceusb_dev *ir = NULL;
+ struct lirc_driver *driver = NULL;
+ struct lirc_buffer *rbuf = NULL;
+ int devnum, pipe, maxp;
+ int minor = 0;
+ int i;
+ char buf[63], name[128] = "";
+ int mem_failure = 0;
+ int is_pinnacle;
+ int is_microsoft_gen1;
+
+ dev_dbg(&intf->dev, ": %s called\n", __func__);
+
+ usb_reset_device(dev);
+
+ config = dev->actconfig;
+
+ idesc = intf->cur_altsetting;
+
+ is_pinnacle = usb_match_id(intf, pinnacle_list) ? 1 : 0;
+
+ is_microsoft_gen1 = usb_match_id(intf, microsoft_gen1_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;
+
+ if ((ep_in == NULL)
+ && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+ == USB_DIR_IN)
+ && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_BULK)
+ || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_INT))) {
+
+ dev_dbg(&intf->dev, ": acceptable inbound endpoint "
+ "found\n");
+ ep_in = ep;
+ ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
+ if (is_pinnacle)
+ /*
+ * setting seems to 1 seem to cause issues with
+ * Pinnacle timing out on transfer.
+ */
+ ep_in->bInterval = ep->bInterval;
+ else
+ ep_in->bInterval = 1;
+ }
+
+ if ((ep_out == NULL)
+ && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+ == USB_DIR_OUT)
+ && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_BULK)
+ || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_INT))) {
+
+ dev_dbg(&intf->dev, ": acceptable outbound endpoint "
+ "found\n");
+ ep_out = ep;
+ ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
+ if (is_pinnacle)
+ /*
+ * setting seems to 1 seem to cause issues with
+ * Pinnacle timing out on transfer.
+ */
+ ep_out->bInterval = ep->bInterval;
+ else
+ ep_out->bInterval = 1;
+ }
+ }
+ if (ep_in == NULL) {
+ dev_dbg(&intf->dev, ": inbound and/or endpoint not found\n");
+ return -ENODEV;
+ }
+
+ devnum = dev->devnum;
+ pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress);
+ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+ mem_failure = 0;
+ ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL);
+ if (!ir) {
+ mem_failure = 1;
+ goto mem_failure_switch;
+ }
+
+ driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
+ if (!driver) {
+ mem_failure = 2;
+ goto mem_failure_switch;
+ }
+
+ rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+ if (!rbuf) {
+ mem_failure = 3;
+ goto mem_failure_switch;
+ }
+
+ if (lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE)) {
+ mem_failure = 4;
+ goto mem_failure_switch;
+ }
+
+ ir->buf_in = usb_buffer_alloc(dev, maxp, GFP_ATOMIC, &ir->dma_in);
+ if (!ir->buf_in) {
+ mem_failure = 5;
+ goto mem_failure_switch;
+ }
+
+ ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ir->urb_in) {
+ mem_failure = 7;
+ goto mem_failure_switch;
+ }
+
+ strcpy(driver->name, DRIVER_NAME);
+ driver->minor = -1;
+ driver->features = LIRC_CAN_SEND_PULSE |
+ LIRC_CAN_SET_TRANSMITTER_MASK |
+ LIRC_CAN_REC_MODE2 |
+ LIRC_CAN_SET_SEND_CARRIER;
+ driver->data = ir;
+ driver->rbuf = rbuf;
+ driver->set_use_inc = &mceusb_ir_open;
+ driver->set_use_dec = &mceusb_ir_close;
+ driver->code_length = sizeof(int) * 8;
+ driver->fops = &lirc_fops;
+ driver->dev = &intf->dev;
+ driver->owner = THIS_MODULE;
+
+ mutex_init(&ir->lock);
+ init_waitqueue_head(&ir->wait_out);
+
+ minor = lirc_register_driver(driver);
+ if (minor < 0)
+ mem_failure = 9;
+
+mem_failure_switch:
+
+ switch (mem_failure) {
+ case 9:
+ usb_free_urb(ir->urb_in);
+ case 7:
+ usb_buffer_free(dev, maxp, ir->buf_in, ir->dma_in);
+ case 5:
+ lirc_buffer_free(rbuf);
+ case 4:
+ kfree(rbuf);
+ case 3:
+ kfree(driver);
+ case 2:
+ kfree(ir);
+ case 1:
+ dev_info(&intf->dev, "out of memory (code=%d)\n", mem_failure);
+ return -ENOMEM;
+ }
+
+ driver->minor = minor;
+ ir->d = driver;
+ ir->devnum = devnum;
+ ir->usbdev = dev;
+ ir->len_in = maxp;
+ ir->overflow_len = 0;
+ ir->flags.connected = 0;
+ ir->flags.pinnacle = is_pinnacle;
+ ir->flags.microsoft_gen1 = is_microsoft_gen1;
+ ir->flags.transmitter_mask_inverted =
+ usb_match_id(intf, transmitter_mask_list) ? 0 : 1;
+
+ ir->lircdata = PULSE_MASK;
+ ir->is_pulse = 0;
+
+ /* ir->flags.transmitter_mask_inverted must be set */
+ set_transmitter_mask(ir, MCE_DEFAULT_TX_MASK);
+ /* Saving usb interface data for use by the transmitter routine */
+ ir->usb_ep_in = ep_in;
+ ir->usb_ep_out = ep_out;
+
+ if (dev->descriptor.iManufacturer
+ && usb_string(dev, dev->descriptor.iManufacturer,
+ buf, sizeof(buf)) > 0)
+ strlcpy(name, buf, sizeof(name));
+ if (dev->descriptor.iProduct
+ && usb_string(dev, dev->descriptor.iProduct,
+ buf, sizeof(buf)) > 0)
+ snprintf(name + strlen(name), sizeof(name) - strlen(name),
+ " %s", buf);
+
+ /* inbound data */
+ usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in,
+ maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval);
+ ir->urb_in->transfer_dma = ir->dma_in;
+ ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /* initialize device */
+ if (ir->flags.pinnacle) {
+ int usbret;
+
+ /*
+ * I have no idea why but this reset seems to be crucial to
+ * getting the device to do outbound IO correctly - without
+ * this the device seems to hang, ignoring all input - although
+ * IR signals are correctly sent from the device, no input is
+ * 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);
+
+ /*
+ * 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);
+ }
+
+ /*
+ * if we don't issue the correct number of receives (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 - they start with 0x9f - but the async
+ * callback doesn't handle ir pulse packets
+ */
+ request_packet_async(ir, ep_in, NULL, maxp, 0);
+
+ usb_set_intfdata(intf, ir);
+
+ dev_info(ir->d->dev, "Registered %s on usb%d:%d\n", name,
+ dev->bus->busnum, devnum);
+
+ return 0;
+}
+
+
+static void mceusb_dev_disconnect(struct usb_interface *intf)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct mceusb_dev *ir = usb_get_intfdata(intf);
+
+ usb_set_intfdata(intf, NULL);
+
+ if (!ir || !ir->d)
+ return;
+
+ ir->usbdev = NULL;
+ wake_up_all(&ir->wait_out);
+
+ mutex_lock(&ir->lock);
+ usb_kill_urb(ir->urb_in);
+ usb_free_urb(ir->urb_in);
+ usb_buffer_free(dev, ir->len_in, ir->buf_in, ir->dma_in);
+ mutex_unlock(&ir->lock);
+
+ unregister_from_lirc(ir);
+}
+
+static int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct mceusb_dev *ir = usb_get_intfdata(intf);
+ dev_info(ir->d->dev, "suspend\n");
+ usb_kill_urb(ir->urb_in);
+ return 0;
+}
+
+static int mceusb_dev_resume(struct usb_interface *intf)
+{
+ struct mceusb_dev *ir = usb_get_intfdata(intf);
+ dev_info(ir->d->dev, "resume\n");
+ if (usb_submit_urb(ir->urb_in, GFP_ATOMIC))
+ return -EIO;
+ return 0;
+}
+
+static struct usb_driver mceusb_dev_driver = {
+ .name = DRIVER_NAME,
+ .probe = mceusb_dev_probe,
+ .disconnect = mceusb_dev_disconnect,
+ .suspend = mceusb_dev_suspend,
+ .resume = mceusb_dev_resume,
+ .reset_resume = mceusb_dev_resume,
+ .id_table = mceusb_dev_table
+};
+
+static int __init mceusb_dev_init(void)
+{
+ int i;
+
+ printk(KERN_INFO DRIVER_NAME ": " DRIVER_DESC " " DRIVER_VERSION "\n");
+ printk(KERN_INFO DRIVER_NAME ": " DRIVER_AUTHOR "\n");
+ if (debug)
+ printk(KERN_DEBUG DRIVER_NAME ": debug mode enabled\n");
+
+ i = usb_register(&mceusb_dev_driver);
+ if (i < 0) {
+ printk(KERN_ERR DRIVER_NAME
+ ": usb register failed, result = %d\n", i);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void __exit mceusb_dev_exit(void)
+{
+ usb_deregister(&mceusb_dev_driver);
+}
+
+module_init(mceusb_dev_init);
+module_exit(mceusb_dev_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, mceusb_dev_table);
+/* this was originally lirc_mceusb2, lirc_mceusb and lirc_mceusb2 merged now */
+MODULE_ALIAS("lirc_mceusb2");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
lirc driver for SoundGraph iMON IR receivers and displays
Successfully tested with multiple devices with and without displays.
Changes from prior submission:
- dual-endpoint devices now appear as a single lirc device
- proper support for devices with touchscreens
- full input device support for mouse mode
- full input device support for onboard decoding devices,
with modparam fallback option for classic lirc mode
- auto-detection of lcd/vfd/vga display in most cases
- support for several new devices
- uses dev_foo printk macros
- able to decode both imon and mce protocol
Signed-off-by: Jarod Wilson <[email protected]>
Signed-off-by: Janne Grunau <[email protected]>
CC: Christoph Bartelmus <[email protected]>
Tested-by: Jarod Wilson <[email protected]>
Tested-by: Tom Horsley <[email protected]>
---
drivers/input/lirc/Kconfig | 6
drivers/input/lirc/Makefile | 1
drivers/input/lirc/lirc_imon.c | 2471 +++++++++++++++++++++++++++++++++++++++++
drivers/input/lirc/lirc_imon.h | 209 +++
4 files changed, 2687 insertions(+)
Index: b/drivers/input/lirc/Kconfig
===================================================================
--- a/drivers/input/lirc/Kconfig
+++ b/drivers/input/lirc/Kconfig
@@ -11,6 +11,12 @@ menuconfig INPUT_LIRC
if INPUT_LIRC
+config LIRC_IMON
+ tristate "SoundGraph iMON Receiver and Display"
+ depends on LIRC_DEV
+ help
+ Driver for the SoundGraph iMON IR Receiver and Display
+
config LIRC_MCEUSB
tristate "Windows Media Center Ed. USB IR Transceiver"
depends on LIRC_DEV && USB
Index: b/drivers/input/lirc/Makefile
===================================================================
--- a/drivers/input/lirc/Makefile
+++ b/drivers/input/lirc/Makefile
@@ -4,4 +4,5 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_INPUT_LIRC) += lirc_dev.o
+obj-$(CONFIG_LIRC_IMON) += lirc_imon.o
obj-$(CONFIG_LIRC_MCEUSB) += lirc_mceusb.o
Index: b/drivers/input/lirc/lirc_imon.c
===================================================================
--- /dev/null
+++ b/drivers/input/lirc/lirc_imon.c
@@ -0,0 +1,2471 @@
+/*
+ * lirc_imon.c: LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD
+ * including the iMON PAD model
+ *
+ * Copyright(C) 2004 Venky Raju([email protected])
+ * Copyright(C) 2009 Jarod Wilson <[email protected]>
+ *
+ * lirc_imon is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#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"
+#include "lirc_imon.h"
+
+
+#define MOD_AUTHOR "Venky Raju <[email protected]>"
+#define MOD_AUTHOR2 "Jarod Wilson <[email protected]>"
+#define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display"
+#define MOD_NAME "lirc_imon"
+#define MOD_VERSION "0.7"
+
+#define DISPLAY_MINOR_BASE 144
+#define DEVICE_NAME "lcd%d"
+
+#define BUF_CHUNK_SIZE 4
+#define BUF_SIZE 128
+
+#define BIT_DURATION 250 /* each bit received is 250us */
+
+#define IMON_CLOCK_ENABLE_PACKETS 2
+
+/*** P R O T O T Y P E S ***/
+
+/* USB Callback prototypes */
+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_intf0(struct urb *urb);
+static void usb_rx_callback_intf1(struct urb *urb);
+static void usb_tx_callback(struct urb *urb);
+
+/* suspend/resume support */
+static int imon_resume(struct usb_interface *intf);
+static int imon_suspend(struct usb_interface *intf, pm_message_t message);
+
+/* Display file_operations function prototypes */
+static int display_open(struct inode *inode, struct file *file);
+static int display_close(struct inode *inode, struct file *file);
+
+/* VFD write operation */
+static ssize_t vfd_write(struct file *file, const char *buf,
+ size_t n_bytes, loff_t *pos);
+
+/* LCD file_operations override function prototypes */
+static ssize_t lcd_write(struct file *file, const char *buf,
+ size_t n_bytes, loff_t *pos);
+
+/* LIRC driver function prototypes */
+static int ir_open(void *data);
+static void ir_close(void *data);
+
+/* Driver init/exit prototypes */
+static int __init imon_init(void);
+static void __exit imon_exit(void);
+
+/*** G L O B A L S ***/
+
+struct imon_context {
+ 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_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 vfd_proto_6p; /* some VFD require a 6th packet */
+ int ir_onboard_decode; /* IR signals decoded onboard */
+
+ struct lirc_driver *driver;
+ struct usb_endpoint_descriptor *rx_endpoint_intf0;
+ struct usb_endpoint_descriptor *rx_endpoint_intf1;
+ struct usb_endpoint_descriptor *tx_endpoint;
+ struct urb *rx_urb_intf0;
+ struct urb *rx_urb_intf1;
+ struct urb *tx_urb;
+ int tx_control;
+ unsigned char usb_rx_buf[8];
+ unsigned char usb_tx_buf[8];
+
+ struct rx_data {
+ int count; /* length of 0 or 1 sequence */
+ int prev_bit; /* logic level of sequence */
+ int initial_space; /* initial space flag */
+ } rx;
+
+ struct tx_t {
+ unsigned char data_buf[35]; /* user data buffer */
+ struct completion finished; /* wait for write to finish */
+ atomic_t busy; /* write in progress */
+ int status; /* status of tx completion */
+ } tx;
+
+ int ffdc_dev; /* is this the overused ffdc ID? */
+ int ir_protocol; /* iMON or MCE (RC6) IR protocol? */
+ struct input_dev *idev; /* input device for remote */
+ struct input_dev *touch; /* input device for touchscreen */
+ u16 last_keycode; /* last reported input keycode */
+ u8 last_mce_byte; /* last mce toggle byte */
+ int display_type; /* store the display type */
+ int pad_mouse; /* toggle kbd(0)/mouse(1) mode */
+ int touch_x; /* x coordinate on touchscreen */
+ int touch_y; /* y coordinate on touchscreen */
+ char name_idev[128];
+ char phys_idev[64];
+ char name_touch[128];
+ char phys_touch[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,
+ .open = &display_open,
+ .write = &vfd_write,
+ .release = &display_close
+};
+
+enum {
+ IMON_DISPLAY_TYPE_AUTO = 0,
+ IMON_DISPLAY_TYPE_VFD = 1,
+ IMON_DISPLAY_TYPE_LCD = 2,
+ IMON_DISPLAY_TYPE_VGA = 3,
+ IMON_DISPLAY_TYPE_NONE = 4,
+};
+
+enum {
+ IMON_IR_PROTOCOL_IMON = 0,
+ IMON_IR_PROTOCOL_MCE = 1,
+ IMON_IR_PROTOCOL_IMON_NOPAD = 2,
+};
+/*
+ * 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[] = {
+ /* TriGem iMON (IR only) -- TG_iMON.inf */
+ { USB_DEVICE(0x0aa8, 0x8001) },
+
+ /* SoundGraph iMON (IR only) -- sg_imon.inf */
+ { USB_DEVICE(0x04e8, 0xff30) },
+
+ /* SoundGraph iMON VFD (IR & VFD) -- iMON_VFD.inf */
+ { USB_DEVICE(0x0aa8, 0xffda) },
+
+ /* SoundGraph iMON SS (IR & VFD) -- iMON_SS.inf */
+ { USB_DEVICE(0x15c2, 0xffda) },
+
+ /*
+ * 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) },
+
+ /*
+ * 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) },
+ /* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */
+ { USB_DEVICE(0x15c2, 0x0035) },
+ /* SoundGraph iMON OEM VFD (IR & VFD) */
+ { USB_DEVICE(0x15c2, 0x0036) },
+ /* 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) */
+ { USB_DEVICE(0x15c2, 0x0042) },
+ /* Antec Veris Multimedia Station Basic Internal (IR only) */
+ { USB_DEVICE(0x15c2, 0x0043) },
+ /* Antec Veris Multimedia Station Elite (IR & VFD) */
+ { USB_DEVICE(0x15c2, 0x0044) },
+ /* Antec Veris Multimedia Station Premiere (IR & LCD) */
+ { USB_DEVICE(0x15c2, 0x0045) },
+ /* device specifics unknown */
+ { USB_DEVICE(0x15c2, 0x0046) },
+ {}
+};
+
+/* Some iMON VFD models requires a 6th packet for VFD writes */
+static struct usb_device_id vfd_proto_6p_list[] = {
+ { USB_DEVICE(0x15c2, 0xffda) },
+ { USB_DEVICE(0x15c2, 0xffdc) },
+ { USB_DEVICE(0x15c2, 0x0036) },
+ { USB_DEVICE(0x15c2, 0x0044) },
+ {}
+};
+
+/* 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 use a different write op */
+static struct usb_device_id lcd_device_list[] = {
+ { USB_DEVICE(0x15c2, 0xffdc) },
+ { USB_DEVICE(0x15c2, 0x0038) },
+ { USB_DEVICE(0x15c2, 0x0045) },
+ {}
+};
+
+/* 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) },
+};
+
+/* Newer iMON models decode the signal onboard */
+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) },
+ {}
+};
+
+/* Some iMON devices have no lcd/vfd, don't set one up */
+static struct usb_device_id ir_only_list[] = {
+ { USB_DEVICE(0x0aa8, 0x8001) },
+ { 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,
+ .probe = imon_probe,
+ .disconnect = imon_disconnect,
+ .suspend = imon_suspend,
+ .resume = imon_resume,
+ .id_table = imon_usb_id_table,
+};
+
+static struct usb_class_driver imon_class = {
+ .name = DEVICE_NAME,
+ .fops = &display_fops,
+ .minor_base = DISPLAY_MINOR_BASE,
+};
+
+/* to prevent races between open() and disconnect(), probing, etc */
+static DEFINE_MUTEX(driver_lock);
+
+static int debug;
+
+/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */
+static int display_type;
+
+/* IR protocol: native iMON, Windows MCE (RC-6), or iMON w/o PAD stabilize */
+static int ir_protocol;
+
+/*
+ * In certain use cases, mouse mode isn't really helpful, and could actually
+ * cause confusion, so allow disabling it when the IR device is open.
+ */
+static int nomouse;
+
+/* threshold at which a pad push registers as an arrow key in kbd mode */
+static int pad_thresh;
+
+/* run onboard decode device in lirc mode rather than as pure input device */
+static int lirc_mode;
+
+/*** M O D U L E C O D E ***/
+
+MODULE_AUTHOR(MOD_AUTHOR);
+MODULE_AUTHOR(MOD_AUTHOR2);
+MODULE_DESCRIPTION(MOD_DESC);
+MODULE_VERSION(MOD_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, imon_usb_id_table);
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)");
+module_param(display_type, int, S_IRUGO);
+MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, "
+ "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)");
+module_param(ir_protocol, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ir_protocol, "Which IR protocol to use. 0=native iMON, "
+ "1=Windows Media Center Ed. (RC-6), 2=iMON w/o PAD stabilize "
+ "(default: native iMON)");
+module_param(nomouse, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is "
+ "open. 0=don't disable, 1=disable. (default: don't disable)");
+module_param(pad_thresh, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an "
+ "arrow key in kbd mode (default: 28)");
+module_param(lirc_mode, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(lirc_mode, "Run onboard decoding receiver in lirc mode rather "
+ "than as a pure input device");
+
+static void free_imon_context(struct imon_context *context)
+{
+ usb_free_urb(context->tx_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);
+
+ dev_dbg(context->driver->dev, "%s: iMON context freed\n", __func__);
+}
+
+static void deregister_from_lirc(struct imon_context *context)
+{
+ int retval;
+ int minor = context->driver->minor;
+
+ retval = lirc_unregister_driver(minor);
+ if (retval)
+ err("%s: unable to deregister from lirc(%d)",
+ __func__, retval);
+ else
+ printk(KERN_INFO MOD_NAME ": Deregistered iMON driver "
+ "(minor:%d)\n", minor);
+
+}
+
+/**
+ * Called when the Display device (e.g. /dev/lcd0)
+ * is opened by the application.
+ */
+static int display_open(struct inode *inode, struct file *file)
+{
+ struct usb_interface *interface;
+ struct imon_context *context = NULL;
+ int subminor;
+ int retval = 0;
+
+ /* prevent races with disconnect */
+ mutex_lock(&driver_lock);
+
+ subminor = iminor(inode);
+ interface = usb_find_interface(&imon_driver, subminor);
+ if (!interface) {
+ err("%s: could not find interface for minor %d",
+ __func__, subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+ context = usb_get_intfdata(interface);
+
+ if (!context) {
+ err("%s: no context found for minor %d",
+ __func__, subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ mutex_lock(&context->lock);
+
+ if (!context->display_supported) {
+ err("%s: display not supported by device", __func__);
+ retval = -ENODEV;
+ } else if (context->display_isopen) {
+ err("%s: display port is already open", __func__);
+ retval = -EBUSY;
+ } else {
+ context->display_isopen = 1;
+ file->private_data = context;
+ dev_info(context->driver->dev, "display port opened\n");
+ }
+
+ mutex_unlock(&context->lock);
+
+exit:
+ mutex_unlock(&driver_lock);
+ return retval;
+}
+
+/**
+ * Called when the display device (e.g. /dev/lcd0)
+ * is closed by the application.
+ */
+static int display_close(struct inode *inode, struct file *file)
+{
+ struct imon_context *context = NULL;
+ int retval = 0;
+
+ context = (struct imon_context *)file->private_data;
+
+ if (!context) {
+ err("%s: no context for device", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&context->lock);
+
+ if (!context->display_supported) {
+ err("%s: display not supported by device", __func__);
+ retval = -ENODEV;
+ } else if (!context->display_isopen) {
+ err("%s: display is not open", __func__);
+ retval = -EIO;
+ } else {
+ context->display_isopen = 0;
+ dev_info(context->driver->dev, "display port closed\n");
+ 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);
+ free_imon_context(context);
+ return retval;
+ }
+ }
+
+ mutex_unlock(&context->lock);
+ return retval;
+}
+
+/**
+ * Sends a packet to the device -- this function must be called
+ * with context->lock held.
+ */
+static int send_packet(struct imon_context *context)
+{
+ unsigned int pipe;
+ int interval = 0;
+ int retval = 0;
+ struct usb_ctrlrequest *control_req = NULL;
+
+ /* Check if we need to use control or interrupt urb */
+ if (!context->tx_control) {
+ pipe = usb_sndintpipe(context->usbdev_intf0,
+ context->tx_endpoint->bEndpointAddress);
+ interval = context->tx_endpoint->bInterval;
+
+ 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);
+
+ context->tx_urb->actual_length = 0;
+ } else {
+ /* fill request into kmalloc'ed space: */
+ control_req = kmalloc(sizeof(struct usb_ctrlrequest),
+ GFP_KERNEL);
+ if (control_req == NULL)
+ return -ENOMEM;
+
+ /* setup packet is '21 09 0200 0001 0008' */
+ control_req->bRequestType = 0x21;
+ control_req->bRequest = 0x09;
+ control_req->wValue = cpu_to_le16(0x0200);
+ control_req->wIndex = cpu_to_le16(0x0001);
+ control_req->wLength = cpu_to_le16(0x0008);
+
+ /* control pipe is endpoint 0x00 */
+ pipe = usb_sndctrlpipe(context->usbdev_intf0, 0);
+
+ /* build the control urb */
+ usb_fill_control_urb(context->tx_urb, context->usbdev_intf0,
+ pipe, (unsigned char *)control_req,
+ context->usb_tx_buf,
+ sizeof(context->usb_tx_buf),
+ usb_tx_callback, context);
+ context->tx_urb->actual_length = 0;
+ }
+
+ init_completion(&context->tx.finished);
+ atomic_set(&(context->tx.busy), 1);
+
+ retval = usb_submit_urb(context->tx_urb, GFP_KERNEL);
+ if (retval) {
+ atomic_set(&(context->tx.busy), 0);
+ err("%s: error submitting urb(%d)", __func__, retval);
+ } else {
+ /* Wait for transmission to complete (or abort) */
+ mutex_unlock(&context->lock);
+ retval = wait_for_completion_interruptible(
+ &context->tx.finished);
+ if (retval)
+ err("%s: task interrupted", __func__);
+ mutex_lock(&context->lock);
+
+ retval = context->tx.status;
+ if (retval)
+ err("%s: packet tx failed (%d)", __func__, retval);
+ }
+
+ kfree(control_req);
+
+ return retval;
+}
+
+/**
+ * Sends an associate packet to the iMON 2.4G.
+ *
+ * This might not be such a good idea, since it has an id collision with
+ * some versions of the "IR & VFD" combo. The only way to determine if it
+ * is an RF version is to look at the product description string. (Which
+ * we currently do not fetch).
+ */
+static int send_associate_24g(struct imon_context *context)
+{
+ int retval;
+ const unsigned char packet[8] = { 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20 };
+
+ if (!context) {
+ err("%s: no context for device", __func__);
+ return -ENODEV;
+ }
+
+ if (!context->dev_present_intf0) {
+ err("%s: no iMON device present", __func__);
+ return -ENODEV;
+ }
+
+ memcpy(context->usb_tx_buf, packet, sizeof(packet));
+ retval = send_packet(context);
+
+ return retval;
+}
+
+/**
+ * Sends packets to setup and show clock on iMON display
+ *
+ * Arguments: year - last 2 digits of year, month - 1..12,
+ * day - 1..31, dow - day of the week (0-Sun...6-Sat),
+ * hour - 0..23, minute - 0..59, second - 0..59
+ */
+static int send_set_imon_clock(struct imon_context *context,
+ unsigned int year, unsigned int month,
+ unsigned int day, unsigned int dow,
+ unsigned int hour, unsigned int minute,
+ unsigned int second)
+{
+ unsigned char clock_enable_pkt[IMON_CLOCK_ENABLE_PACKETS][8];
+ int retval = 0;
+ int i;
+
+ if (!context) {
+ err("%s: no context for device", __func__);
+ return -ENODEV;
+ }
+
+ switch (context->display_type) {
+ case IMON_DISPLAY_TYPE_LCD:
+ clock_enable_pkt[0][0] = 0x80;
+ clock_enable_pkt[0][1] = year;
+ clock_enable_pkt[0][2] = month-1;
+ clock_enable_pkt[0][3] = day;
+ clock_enable_pkt[0][4] = hour;
+ clock_enable_pkt[0][5] = minute;
+ clock_enable_pkt[0][6] = second;
+
+ clock_enable_pkt[1][0] = 0x80;
+ clock_enable_pkt[1][1] = 0;
+ clock_enable_pkt[1][2] = 0;
+ clock_enable_pkt[1][3] = 0;
+ clock_enable_pkt[1][4] = 0;
+ clock_enable_pkt[1][5] = 0;
+ clock_enable_pkt[1][6] = 0;
+
+ if (context->ffdc_dev) {
+ clock_enable_pkt[0][7] = 0x50;
+ clock_enable_pkt[1][7] = 0x51;
+ } else {
+ clock_enable_pkt[0][7] = 0x88;
+ clock_enable_pkt[1][7] = 0x8a;
+ }
+
+ break;
+
+ case IMON_DISPLAY_TYPE_VFD:
+ clock_enable_pkt[0][0] = year;
+ clock_enable_pkt[0][1] = month-1;
+ clock_enable_pkt[0][2] = day;
+ clock_enable_pkt[0][3] = dow;
+ clock_enable_pkt[0][4] = hour;
+ clock_enable_pkt[0][5] = minute;
+ clock_enable_pkt[0][6] = second;
+ clock_enable_pkt[0][7] = 0x40;
+
+ clock_enable_pkt[1][0] = 0;
+ clock_enable_pkt[1][1] = 0;
+ clock_enable_pkt[1][2] = 1;
+ clock_enable_pkt[1][3] = 0;
+ clock_enable_pkt[1][4] = 0;
+ clock_enable_pkt[1][5] = 0;
+ clock_enable_pkt[1][6] = 0;
+ clock_enable_pkt[1][7] = 0x42;
+
+ break;
+
+ default:
+ return -ENODEV;
+ }
+
+ for (i = 0; i < IMON_CLOCK_ENABLE_PACKETS; i++) {
+ memcpy(context->usb_tx_buf, clock_enable_pkt[i], 8);
+ retval = send_packet(context);
+ if (retval) {
+ err("%s: send_packet failed for packet %d",
+ __func__, i);
+ break;
+ }
+ }
+
+ return retval;
+}
+
+/**
+ * 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)
+{
+ struct imon_context *context = dev_get_drvdata(d);
+
+ if (!context)
+ return -ENODEV;
+
+ mutex_lock(&context->lock);
+ if (context->ir_isassociating)
+ strcpy(buf, "associating\n");
+ else if (context->ir_isopen)
+ strcpy(buf, "open\n");
+ else
+ strcpy(buf, "closed\n");
+
+ dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for "
+ "instructions on how to associate your iMON 2.4G DT/LT "
+ "remote\n");
+ mutex_unlock(&context->lock);
+ return strlen(buf);
+}
+
+static ssize_t store_associate_remote(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct imon_context *context;
+
+ context = dev_get_drvdata(d);
+
+ if (!context)
+ return -ENODEV;
+
+ mutex_lock(&context->lock);
+ if (!context->ir_isopen) {
+ mutex_unlock(&context->lock);
+ return -EINVAL;
+ }
+
+ if (context->ir_isopen) {
+ context->ir_isassociating = 1;
+ send_associate_24g(context);
+ }
+ mutex_unlock(&context->lock);
+
+ return count;
+}
+
+/**
+ * sysfs functions to control internal imon clock
+ */
+static ssize_t show_imon_clock(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct imon_context *context = dev_get_drvdata(d);
+ size_t len;
+
+ if (!context)
+ return -ENODEV;
+
+ mutex_lock(&context->lock);
+
+ if (!context->display_supported) {
+ len = snprintf(buf, PAGE_SIZE, "Not supported.");
+ } else {
+ len = snprintf(buf, PAGE_SIZE,
+ "To set the clock on your iMON display:\n"
+ "# date \"+%%y %%m %%d %%w %%H %%M %%S\" > imon_clock\n"
+ "%s", context->display_isopen ?
+ "\nNOTE: imon device must be closed\n" : "");
+ }
+
+ mutex_unlock(&context->lock);
+
+ return len;
+}
+
+static ssize_t store_imon_clock(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct imon_context *context = dev_get_drvdata(d);
+ ssize_t retval;
+ unsigned int year, month, day, dow, hour, minute, second;
+
+ if (!context)
+ return -ENODEV;
+
+ mutex_lock(&context->lock);
+
+ if (!context->display_supported) {
+ retval = -ENODEV;
+ goto exit;
+ } else if (context->display_isopen) {
+ retval = -EBUSY;
+ goto exit;
+ }
+
+ if (sscanf(buf, "%u %u %u %u %u %u %u", &year, &month, &day, &dow,
+ &hour, &minute, &second) != 7) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if ((month < 1 || month > 12) ||
+ (day < 1 || day > 31) || (dow > 6) ||
+ (hour > 23) || (minute > 59) || (second > 59)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ retval = send_set_imon_clock(context, year, month, day, dow,
+ hour, minute, second);
+ if (retval)
+ goto exit;
+
+ retval = count;
+exit:
+ mutex_unlock(&context->lock);
+
+ return retval;
+}
+
+
+static DEVICE_ATTR(imon_clock, S_IWUSR | S_IRUGO, show_imon_clock,
+ store_imon_clock);
+
+static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote,
+ store_associate_remote);
+
+static struct attribute *imon_display_sysfs_entries[] = {
+ &dev_attr_imon_clock.attr,
+ NULL
+};
+
+static struct attribute_group imon_display_attribute_group = {
+ .attrs = imon_display_sysfs_entries
+};
+
+static struct attribute *imon_rf_sysfs_entries[] = {
+ &dev_attr_associate_remote.attr,
+ NULL
+};
+
+static struct attribute_group imon_rf_attribute_group = {
+ .attrs = imon_rf_sysfs_entries
+};
+
+/**
+ * Writes data to the VFD. The iMON VFD is 2x16 characters
+ * and requires data in 5 consecutive USB interrupt packets,
+ * each packet but the last carrying 7 bytes.
+ *
+ * I don't know if the VFD board supports features such as
+ * scrolling, clearing rows, blanking, etc. so at
+ * the caller must provide a full screen of data. If fewer
+ * than 32 bytes are provided spaces will be appended to
+ * generate a full screen.
+ */
+static ssize_t vfd_write(struct file *file, const char *buf,
+ size_t n_bytes, loff_t *pos)
+{
+ int i;
+ int offset;
+ int seq;
+ int retval = 0;
+ struct imon_context *context;
+ const unsigned char vfd_packet6[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
+
+ context = (struct imon_context *)file->private_data;
+ if (!context) {
+ err("%s: no context for device", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&context->lock);
+
+ if (!context->dev_present_intf0) {
+ err("%s: no iMON device present", __func__);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (n_bytes <= 0 || n_bytes > 32) {
+ err("%s: invalid payload size", __func__);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (copy_from_user(context->tx.data_buf, buf, n_bytes)) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ /* Pad with spaces */
+ for (i = n_bytes; i < 32; ++i)
+ context->tx.data_buf[i] = ' ';
+
+ for (i = 32; i < 35; ++i)
+ context->tx.data_buf[i] = 0xFF;
+
+ offset = 0;
+ seq = 0;
+
+ do {
+ memcpy(context->usb_tx_buf, context->tx.data_buf + offset, 7);
+ context->usb_tx_buf[7] = (unsigned char) seq;
+
+ retval = send_packet(context);
+ if (retval) {
+ err("%s: send packet failed for packet #%d",
+ __func__, seq/2);
+ goto exit;
+ } else {
+ seq += 2;
+ offset += 7;
+ }
+
+ } while (offset < 35);
+
+ if (context->vfd_proto_6p) {
+ /* Send packet #6 */
+ memcpy(context->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6));
+ context->usb_tx_buf[7] = (unsigned char) seq;
+ retval = send_packet(context);
+ if (retval)
+ err("%s: send packet failed for packet #%d",
+ __func__, seq/2);
+ }
+
+exit:
+ mutex_unlock(&context->lock);
+
+ return (!retval) ? n_bytes : retval;
+}
+
+/**
+ * Writes data to the LCD. The iMON OEM LCD screen excepts 8-byte
+ * packets. We accept data as 16 hexadecimal digits, followed by a
+ * newline (to make it easy to drive the device from a command-line
+ * -- even though the actual binary data is a bit complicated).
+ *
+ * The device itself is not a "traditional" text-mode display. It's
+ * actually a 16x96 pixel bitmap display. That means if you want to
+ * display text, you've got to have your own "font" and translate the
+ * text into bitmaps for display. This is really flexible (you can
+ * display whatever diacritics you need, and so on), but it's also
+ * a lot more complicated than most LCDs...
+ */
+static ssize_t lcd_write(struct file *file, const char *buf,
+ size_t n_bytes, loff_t *pos)
+{
+ int retval = 0;
+ struct imon_context *context;
+
+ context = (struct imon_context *)file->private_data;
+ if (!context) {
+ err("%s: no context for device", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&context->lock);
+
+ if (!context->display_supported) {
+ err("%s: no iMON display present", __func__);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (n_bytes != 8) {
+ err("%s: invalid payload size: %d (expecting 8)",
+ __func__, (int) n_bytes);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (copy_from_user(context->usb_tx_buf, buf, 8)) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ retval = send_packet(context);
+ if (retval) {
+ err("%s: send packet failed!", __func__);
+ goto exit;
+ } else {
+ dev_dbg(context->driver->dev, "%s: write %d bytes to LCD\n",
+ __func__, (int) n_bytes);
+ }
+exit:
+ mutex_unlock(&context->lock);
+ return (!retval) ? n_bytes : retval;
+}
+
+/**
+ * Callback function for USB core API: transmit data
+ */
+static void usb_tx_callback(struct urb *urb)
+{
+ struct imon_context *context;
+
+ if (!urb)
+ return;
+ context = (struct imon_context *)urb->context;
+ if (!context)
+ return;
+
+ context->tx.status = urb->status;
+
+ /* notify waiters that write has finished */
+ atomic_set(&context->tx.busy, 0);
+ complete(&context->tx.finished);
+
+ return;
+}
+
+/**
+ * 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
+ * are decoded onboard the receiver.
+ */
+static void imon_set_ir_protocol(struct imon_context *context)
+{
+ int retval;
+ struct device *dev = context->driver->dev;
+ unsigned char ir_proto_packet[] =
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
+
+ switch (ir_protocol) {
+ case IMON_IR_PROTOCOL_MCE:
+ /* MCE proto not supported on devices without tx control */
+ if (!context->tx_control) {
+ dev_info(dev, "%s: MCE IR proto not supported on this "
+ "device, using iMON protocol\n", __func__);
+ context->ir_protocol = IMON_IR_PROTOCOL_IMON;
+ return;
+ }
+ dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
+ ir_proto_packet[0] = 0x01;
+ context->ir_protocol = IMON_IR_PROTOCOL_MCE;
+ break;
+ case IMON_IR_PROTOCOL_IMON:
+ dev_dbg(dev, "Configuring IR receiver for iMON protocol\n");
+ /* ir_proto_packet[0] = 0x00; // already the default */
+ context->ir_protocol = IMON_IR_PROTOCOL_IMON;
+ break;
+ case IMON_IR_PROTOCOL_IMON_NOPAD:
+ dev_dbg(dev, "Configuring IR receiver for iMON protocol "
+ "without PAD stabilize function enabled\n");
+ /* ir_proto_packet[0] = 0x00; // already the default */
+ context->ir_protocol = IMON_IR_PROTOCOL_IMON_NOPAD;
+ break;
+ default:
+ dev_info(dev, "%s: unknown IR protocol specified, will "
+ "just default to iMON protocol\n", __func__);
+ context->ir_protocol = IMON_IR_PROTOCOL_IMON;
+ break;
+ }
+
+ /* Don't send config packet on devices w/o tx ctrl ep */
+ if (!context->tx_control)
+ return;
+
+ memcpy(context->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
+ retval = send_packet(context);
+ if (retval)
+ dev_info(dev, "%s: failed to set remote type\n", __func__);
+}
+
+
+/**
+ * Called by lirc_dev when the application opens /dev/lirc
+ */
+static int ir_open(void *data)
+{
+ int retval = 0;
+ struct imon_context *context;
+
+ /* prevent races with disconnect */
+ mutex_lock(&driver_lock);
+
+ context = (struct imon_context *)data;
+
+ /* initial IR protocol decode variables */
+ context->rx.count = 0;
+ context->rx.initial_space = 1;
+ context->rx.prev_bit = 0;
+
+ /* set new IR protocol if it has changed since init or last open */
+ if (ir_protocol != context->ir_protocol) {
+ mutex_lock(&context->lock);
+ imon_set_ir_protocol(context);
+ mutex_unlock(&context->lock);
+ }
+
+ context->ir_isopen = 1;
+ dev_info(context->driver->dev, "IR port opened\n");
+
+ mutex_unlock(&driver_lock);
+ return retval;
+}
+
+/**
+ * Called by lirc_dev when the application closes /dev/lirc
+ */
+static void ir_close(void *data)
+{
+ struct imon_context *context;
+
+ context = (struct imon_context *)data;
+ if (!context) {
+ err("%s: no context for device", __func__);
+ return;
+ }
+
+ mutex_lock(&context->lock);
+
+ context->ir_isopen = 0;
+ context->ir_isassociating = 0;
+ dev_info(context->driver->dev, "IR port closed\n");
+
+ if (!context->dev_present_intf0) {
+ /*
+ * Device disconnected while IR port was still open. Driver
+ * was not deregistered at disconnect time, so do it now.
+ */
+ deregister_from_lirc(context);
+
+ if (!context->display_isopen) {
+ mutex_unlock(&context->lock);
+ free_imon_context(context);
+ return;
+ }
+ /*
+ * If display port is open, context will be deleted by
+ * display_close
+ */
+ }
+
+ mutex_unlock(&context->lock);
+ return;
+}
+
+/**
+ * Convert bit count to time duration (in us) and submit
+ * the value to lirc_dev.
+ */
+static void submit_data(struct imon_context *context)
+{
+ unsigned char buf[4];
+ int value = context->rx.count;
+ int i;
+
+ dev_dbg(context->driver->dev, "submitting data to LIRC\n");
+
+ value *= BIT_DURATION;
+ value &= PULSE_MASK;
+ if (context->rx.prev_bit)
+ value |= PULSE_BIT;
+
+ for (i = 0; i < 4; ++i)
+ buf[i] = value>>(i*8);
+
+ lirc_buffer_write(context->driver->rbuf, buf);
+ wake_up(&context->driver->rbuf->wait_poll);
+ return;
+}
+
+static inline int tv2int(const struct timeval *a, const struct timeval *b)
+{
+ int usecs = 0;
+ int sec = 0;
+
+ if (b->tv_usec > a->tv_usec) {
+ usecs = 1000000;
+ sec--;
+ }
+
+ usecs += a->tv_usec - b->tv_usec;
+
+ sec += a->tv_sec - b->tv_sec;
+ sec *= 1000;
+ usecs /= 1000;
+ sec += usecs;
+
+ if (sec < 0)
+ sec = 1000;
+
+ return sec;
+}
+
+/**
+ * The directional pad behaves a bit differently, depending on whether this is
+ * one of the older ffdc devices or a newer device. Newer devices appear to
+ * have a higher resolution matrix for more precise mouse movement, but it
+ * makes things overly sensitive in keyboard mode, so we do some interesting
+ * contortions to make it less touchy. Older devices run through the same
+ * routine with shorter timeout and a smaller threshold.
+ */
+static int stabilize(int a, int b, u16 timeout, u16 threshold)
+{
+ struct timeval ct;
+ static struct timeval prev_time = {0, 0};
+ static struct timeval hit_time = {0, 0};
+ static int x, y, prev_result, hits;
+ int result = 0;
+ int msec, msec_hit;
+
+ do_gettimeofday(&ct);
+ msec = tv2int(&ct, &prev_time);
+ msec_hit = tv2int(&ct, &hit_time);
+
+ if (msec > 100) {
+ x = 0;
+ y = 0;
+ hits = 0;
+ }
+
+ x += a;
+ y += b;
+
+ prev_time = ct;
+
+ if (abs(x) > threshold || abs(y) > threshold) {
+ if (abs(y) > abs(x))
+ result = (y > 0) ? 0x7F : 0x80;
+ else
+ result = (x > 0) ? 0x7F00 : 0x8000;
+
+ x = 0;
+ y = 0;
+
+ if (result == prev_result) {
+ hits++;
+
+ if (hits > 3) {
+ switch (result) {
+ case 0x7F:
+ y = 17 * threshold / 30;
+ break;
+ case 0x80:
+ y -= 17 * threshold / 30;
+ break;
+ case 0x7F00:
+ x = 17 * threshold / 30;
+ break;
+ case 0x8000:
+ x -= 17 * threshold / 30;
+ break;
+ }
+ }
+
+ if (hits == 2 && msec_hit < timeout) {
+ result = 0;
+ hits = 1;
+ }
+ } else {
+ prev_result = result;
+ hits = 1;
+ hit_time = ct;
+ }
+ }
+
+ return result;
+}
+
+static int imon_remote_key_lookup(u32 hw_code)
+{
+ int i;
+ u32 code = be32_to_cpu(hw_code);
+
+ /* Look for the initial press of a button */
+ for (i = 0; i < ARRAY_SIZE(imon_remote_key_table); i++)
+ if (imon_remote_key_table[i].hw_code == code)
+ return i;
+
+ /* Look for the release of a button */
+ for (i = 0; i < ARRAY_SIZE(imon_remote_key_table); i++)
+ if ((imon_remote_key_table[i].hw_code | 0x4000) == code)
+ return i;
+
+ return -1;
+}
+
+static int imon_mce_key_lookup(u32 hw_code)
+{
+ 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].hw_code == code)
+ return i;
+
+ for (i = 0; i < ARRAY_SIZE(imon_mce_key_table); i++)
+ if (imon_mce_key_table[i].hw_code == (code | 0x8000))
+ return i;
+
+ return -1;
+}
+
+static int imon_panel_key_lookup(u64 hw_code)
+{
+ int i;
+ 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))
+ return i;
+
+ return -1;
+}
+
+/**
+ * Process the incoming packet
+ */
+static void imon_incoming_packet(struct imon_context *context,
+ struct urb *urb, int intf)
+{
+ int len = urb->actual_length;
+ unsigned char *buf = urb->transfer_buffer;
+ struct device *dev = context->driver->dev;
+ char rel_x = 0x00, rel_y = 0x00;
+ int octet, bit;
+ unsigned char mask;
+ int i, chunk_num;
+ int ts_input = 0;
+ int dir = 0;
+ u16 timeout, threshold;
+ u16 keycode;
+ u16 norelease = 0;
+ int k;
+ u32 remote_key = 0;
+ u64 panel_key = 0;
+ int mouse_input;
+ int right_shift = 1;
+ struct input_dev *idev = NULL;
+ struct input_dev *touch = NULL;
+
+ idev = context->idev;
+ if (context->display_type == IMON_DISPLAY_TYPE_VGA)
+ touch = context->touch;
+
+ /* Figure out what key was pressed */
+ if (len == 8 && buf[7] == 0xee) {
+ memcpy(&panel_key, buf, len);
+ k = imon_panel_key_lookup(panel_key);
+ keycode = imon_panel_key_table[k].keycode;
+ } else {
+ memcpy(&remote_key, buf, sizeof(remote_key));
+ if (context->ir_protocol == IMON_IR_PROTOCOL_MCE) {
+ k = imon_mce_key_lookup(remote_key);
+ keycode = imon_mce_key_table[k].keycode;
+ } else {
+ k = imon_remote_key_lookup(remote_key);
+ keycode = imon_remote_key_table[k].keycode;
+ }
+ }
+
+ /* keyboard/mouse mode toggle button */
+ if (keycode == KEY_KEYBOARD && (buf[2] & 0x40) != 0x40) {
+ if (!nomouse) {
+ context->pad_mouse = ~(context->pad_mouse) & 0x1;
+ dev_dbg(dev, "toggling to %s mode\n",
+ context->pad_mouse ? "mouse" : "keyboard");
+ } else {
+ context->pad_mouse = 0;
+ dev_dbg(dev, "mouse mode was disabled by modparam\n");
+ }
+ context->last_keycode = keycode;
+ return;
+ }
+
+ /* send touchscreen events through input subsystem if touchpad data */
+ if (context->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
+ buf[7] == 0x86) {
+ if (touch == NULL) {
+ dev_warn(dev, "%s: touchscreen input device is "
+ "NULL!\n", __func__);
+ return;
+ }
+ 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);
+ ts_input = 1;
+
+ /* send mouse events through input subsystem in mouse mode */
+ } else if (context->pad_mouse || (!context->ir_isopen && lirc_mode)) {
+ /* newer iMON device PAD or mouse button */
+ if (!context->ffdc_dev && (buf[0] & 0x01) && len == 5) {
+ mouse_input = 1;
+ rel_x = buf[2];
+ rel_y = buf[3];
+ right_shift = 1;
+ /* 0xffdc iMON PAD or mouse button input */
+ } else if (context->ffdc_dev && (buf[0] & 0x40) &&
+ !((buf[1] & 0x01) || ((buf[1] >> 2) & 0x01))) {
+ mouse_input = 1;
+ rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
+ (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
+ if (buf[0] & 0x02)
+ rel_x |= ~0x0f;
+ rel_x = rel_x + rel_x / 2;
+ rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 |
+ (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
+ if (buf[0] & 0x01)
+ rel_y |= ~0x0f;
+ rel_y = rel_y + rel_y / 2;
+ right_shift = 2;
+ /* some ffdc devices decode mouse buttons differently... */
+ } else if (context->ffdc_dev && (buf[0] == 0x68)) {
+ mouse_input = 1;
+ right_shift = 2;
+ /* ch+/- buttons, which we use for an emulated scroll wheel */
+ } else if (keycode == KEY_CHANNELUP &&
+ (buf[2] & 0x40) != 0x40) {
+ mouse_input = 1;
+ dir = 1;
+ } else if (keycode == KEY_CHANNELDOWN &&
+ (buf[2] & 0x40) != 0x40) {
+ mouse_input = 1;
+ dir = -1;
+ } else
+ mouse_input = 0;
+
+ if (mouse_input) {
+ if (idev == NULL) {
+ dev_warn(dev, "%s: idev input device "
+ "is NULL!\n", __func__);
+ return;
+ }
+ dev_dbg(context->driver->dev,
+ "sending mouse data via input subsystem\n");
+
+ if (dir) {
+ input_report_rel(idev, REL_WHEEL, dir);
+ } else if (rel_x || rel_y) {
+ input_report_rel(idev, REL_X, rel_x);
+ input_report_rel(idev, REL_Y, rel_y);
+ } else {
+ input_report_key(idev, BTN_LEFT, buf[1] & 0x1);
+ input_report_key(idev, BTN_RIGHT,
+ buf[1] >> right_shift & 0x1);
+ }
+ input_sync(idev);
+ context->last_keycode = keycode;
+ return;
+ }
+ }
+
+ /*
+ * at this point, mouse and touchscreen input has been handled
+ * handled, so if we're in lirc mode, bail out if no listening
+ * IR client
+ */
+ if (!context->ir_isopen && lirc_mode)
+ return;
+
+ /* Now for some special handling to convert pad input to arrow keys */
+ if ((len == 5) && (buf[0] == 0x01) && (buf[4] == 0x00)) {
+ /* first, pad to 8 bytes so it conforms with everything else */
+ buf[5] = buf[6] = buf[7] = 0;
+ len = 8;
+ timeout = 500; /* in msecs */
+ /* (2*threshold) x (2*threshold) square */
+ threshold = pad_thresh ? pad_thresh : 28;
+ rel_x = buf[2];
+ rel_y = buf[3];
+
+ /*
+ * the imon directional pad functions more like a touchpad.
+ * Bytes 3 & 4 contain a position coordinate (x,y), with each
+ * component ranging from -14 to 14. Since this doesn't
+ * cooperate well with the way lirc works (it would appear to
+ * lirc as more than 100 different buttons) we need to map it
+ * to 4 discrete values. Also, when you get too close to
+ * diagonals, it has a tendancy to jump back and forth, so lets
+ * try to ignore when they get too close
+ */
+ if (context->ir_protocol == IMON_IR_PROTOCOL_IMON) {
+ if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
+ dir = stabilize((int)rel_x, (int)rel_y,
+ timeout, threshold);
+ if (!dir)
+ return;
+ buf[2] = dir & 0xFF;
+ buf[3] = (dir >> 8) & 0xFF;
+ memcpy(&remote_key, buf, sizeof(remote_key));
+ k = imon_remote_key_lookup(remote_key);
+ keycode = imon_remote_key_table[k].keycode;
+ }
+ } else {
+ if (abs(rel_y) > abs(rel_x)) {
+ buf[2] = (rel_y > 0) ? 0x7F : 0x80;
+ buf[3] = 0;
+ keycode = (rel_y > 0) ? KEY_DOWN : KEY_UP;
+ } else {
+ buf[2] = 0;
+ buf[3] = (rel_x > 0) ? 0x7F : 0x80;
+ keycode = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT;
+ }
+ }
+ norelease = 1;
+
+ } 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.
+ */
+ timeout = 10; /* in msecs */
+ /* (2*threshold) x (2*threshold) square */
+ threshold = pad_thresh ? pad_thresh : 15;
+
+ /* 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;
+
+ if (context->ir_protocol == IMON_IR_PROTOCOL_IMON) {
+ dir = stabilize((int)rel_x, (int)rel_y,
+ timeout, threshold);
+ if (!dir)
+ return;
+ buf[2] = dir & 0xFF;
+ buf[3] = (dir >> 8) & 0xFF;
+ } else {
+ if (abs(rel_y) > abs(rel_x)) {
+ buf[2] = (rel_y > 0) ? 0x7F : 0x80;
+ buf[3] = 0;
+ keycode = (rel_y > 0) ? KEY_DOWN : KEY_UP;
+ } else {
+ buf[2] = 0;
+ buf[3] = (rel_x > 0) ? 0x7F : 0x80;
+ keycode = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT;
+ }
+ }
+ norelease = 1;
+
+ } else if (ts_input) {
+ /*
+ * 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;
+ }
+
+ if (!lirc_mode && context->ir_onboard_decode) {
+ int press_type = 0;
+ static int seen_first;
+ int msec;
+ struct timeval t;
+ static struct timeval prev_time = { 0, 0 };
+ if (debug) {
+ printk(KERN_INFO "intf%d decoded packet: ", intf);
+ for (i = 0; i < len; ++i)
+ printk("%02x ", buf[i]);
+ printk("\n");
+ }
+
+ /* key release of 0x02XXXXXX key */
+ if (k == -1 && buf[0] == 0x02 && buf[3] == 0x00)
+ keycode = context->last_keycode;
+
+ /* initial mce button press */
+ else if (ir_protocol == IMON_IR_PROTOCOL_MCE && buf[0] == 0x80
+ && buf[2] != context->last_mce_byte)
+ goto input_out;
+
+ /* subsequent mce button press, on which we'll act */
+ else if (ir_protocol == IMON_IR_PROTOCOL_MCE && buf[0] == 0x80
+ && seen_first) {
+ press_type = 1;
+ norelease = 1;
+
+ /* incoherent or irrelevant data */
+ } else if (k == -1)
+ return;
+
+ /* key release of 0xXXXXXXb7 key */
+ else if (buf[3] == 0xb7 && (buf[2] & 0x40) == 0x40)
+ press_type = 0;
+
+ /* this is a button press */
+ else
+ press_type = 1;
+
+ /* KEY_MUTE repeats need to be suppressed */
+ if (keycode == KEY_MUTE && context->last_keycode == KEY_MUTE) {
+ do_gettimeofday(&t);
+ msec = tv2int(&t, &prev_time);
+ prev_time = t;
+ if (msec < 500)
+ return;
+ }
+
+ input_report_key(idev, keycode, press_type);
+ input_sync(idev);
+
+ /* panel keys and some remote keys don't generate a release */
+ if (panel_key || norelease) {
+ input_report_key(idev, keycode, 0);
+ input_sync(idev);
+ }
+
+input_out:
+ context->last_keycode = keycode;
+ if (ir_protocol == IMON_IR_PROTOCOL_MCE && buf[0] == 0x80) {
+ seen_first = ~seen_first & 0x1;
+ context->last_mce_byte = buf[2];
+ }
+ return;
+ }
+
+ if (len != 8) {
+ dev_warn(dev, "imon %s: invalid incoming packet "
+ "size (len = %d, intf%d)\n", __func__, len, intf);
+ return;
+ }
+
+ /* iMON 2.4G associate frame */
+ if (buf[0] == 0x00 &&
+ buf[2] == 0xFF && /* REFID */
+ buf[3] == 0xFF &&
+ buf[4] == 0xFF &&
+ buf[5] == 0xFF && /* iMON 2.4G */
+ ((buf[6] == 0x4E && buf[7] == 0xDF) || /* LT */
+ (buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */
+ dev_warn(dev, "%s: remote associated refid=%02X\n",
+ __func__, buf[1]);
+ context->ir_isassociating = 0;
+ }
+
+ chunk_num = buf[7];
+
+ if (chunk_num == 0xFF && !ts_input)
+ return; /* filler frame, no data here */
+
+ if (buf[0] == 0xFF &&
+ buf[1] == 0xFF &&
+ buf[2] == 0xFF &&
+ buf[3] == 0xFF &&
+ buf[4] == 0xFF &&
+ buf[5] == 0xFF && /* iMON 2.4G */
+ ((buf[6] == 0x4E && buf[7] == 0xAF) || /* LT */
+ (buf[6] == 0x5E && buf[7] == 0xAF))) /* DT */
+ return; /* filler frame, no data here */
+
+ if (debug) {
+ if (context->ir_onboard_decode)
+ printk(KERN_INFO "intf%d decoded packet: ", intf);
+ else
+ printk(KERN_INFO "raw packet: ");
+ for (i = 0; i < len; ++i)
+ printk("%02x ", buf[i]);
+ printk("\n");
+ }
+
+ if (context->ir_onboard_decode) {
+ /* The signals have been decoded onboard the iMON controller */
+ lirc_buffer_write(context->driver->rbuf, buf);
+ wake_up(&context->driver->rbuf->wait_poll);
+ return;
+ }
+
+ /*
+ * Translate received data to pulse and space lengths.
+ * Received data is active low, i.e. pulses are 0 and
+ * spaces are 1.
+ *
+ * My original algorithm was essentially similar to
+ * Changwoo Ryu's with the exception that he switched
+ * the incoming bits to active high and also fed an
+ * initial space to LIRC at the start of a new sequence
+ * if the previous bit was a pulse.
+ *
+ * I've decided to adopt his algorithm.
+ */
+
+ if (chunk_num == 1 && context->rx.initial_space) {
+ /* LIRC requires a leading space */
+ context->rx.prev_bit = 0;
+ context->rx.count = 4;
+ submit_data(context);
+ context->rx.count = 0;
+ }
+
+ for (octet = 0; octet < 5; ++octet) {
+ mask = 0x80;
+ for (bit = 0; bit < 8; ++bit) {
+ int curr_bit = !(buf[octet] & mask);
+ if (curr_bit != context->rx.prev_bit) {
+ if (context->rx.count) {
+ submit_data(context);
+ context->rx.count = 0;
+ }
+ context->rx.prev_bit = curr_bit;
+ }
+ ++context->rx.count;
+ mask >>= 1;
+ }
+ }
+
+ if (chunk_num == 10) {
+ if (context->rx.count) {
+ submit_data(context);
+ context->rx.count = 0;
+ }
+ context->rx.initial_space = context->rx.prev_bit;
+ }
+}
+
+/**
+ * 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->display_type == IMON_DISPLAY_TYPE_VGA)
+ 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_intf0(struct urb *urb)
+{
+ struct imon_context *context;
+ unsigned char *buf;
+ int len;
+ int intfnum = 0;
+
+ if (!urb)
+ return;
+
+ context = (struct imon_context *)urb->context;
+ if (!context)
+ return;
+
+ buf = urb->transfer_buffer;
+ len = urb->actual_length;
+
+ switch (urb->status) {
+ case -ENOENT: /* usbcore unlink successful! */
+ return;
+
+ case 0:
+ imon_incoming_packet(context, urb, intfnum);
+ break;
+
+ default:
+ dev_warn(context->driver->dev, "imon %s: status(%d): ignored\n",
+ __func__, urb->status);
+ break;
+ }
+
+ 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;
+ int intfnum = 1;
+
+ if (!urb)
+ return;
+
+ context = (struct imon_context *)urb->context;
+ if (!context)
+ return;
+
+ buf = urb->transfer_buffer;
+ len = urb->actual_length;
+
+ switch (urb->status) {
+ case -ENOENT: /* usbcore unlink successful! */
+ return;
+
+ case 0:
+ imon_incoming_packet(context, urb, intfnum);
+ break;
+
+ default:
+ dev_warn(context->driver->dev, "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
+ */
+static int imon_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_device *usbdev = NULL;
+ struct usb_host_interface *iface_desc = NULL;
+ struct usb_endpoint_descriptor *rx_endpoint = NULL;
+ struct usb_endpoint_descriptor *tx_endpoint = NULL;
+ struct urb *rx_urb = NULL;
+ 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;
+ int num_endpts;
+ int retval = 0;
+ int display_ep_found = 0;
+ int ir_ep_found = 0;
+ int alloc_status = 0;
+ int vfd_proto_6p = 0;
+ int ir_onboard_decode = 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, sysfs_err;
+ int configured_display_type = IMON_DISPLAY_TYPE_VFD;
+ u16 vendor, product;
+ const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x88 };
+
+ /*
+ * Try to auto-detect the type of display if the user hasn't set
+ * it by hand via the display_type modparam. Default is VFD.
+ */
+ if (display_type == IMON_DISPLAY_TYPE_AUTO) {
+ if (usb_match_id(interface, lcd_device_list))
+ configured_display_type = IMON_DISPLAY_TYPE_LCD;
+ else if (usb_match_id(interface, imon_touchscreen_list))
+ configured_display_type = IMON_DISPLAY_TYPE_VGA;
+ else if (usb_match_id(interface, ir_only_list))
+ configured_display_type = IMON_DISPLAY_TYPE_NONE;
+ else
+ configured_display_type = IMON_DISPLAY_TYPE_VFD;
+ } else {
+ configured_display_type = display_type;
+ dev_dbg(dev, "%s: overriding display type to %d via "
+ "modparam\n", __func__, display_type);
+ }
+
+ /*
+ * If it's the LCD, as opposed to the VFD, we just need to replace
+ * the "write" file op.
+ */
+ if (configured_display_type == IMON_DISPLAY_TYPE_LCD)
+ display_fops.write = &lcd_write;
+
+ /*
+ * To get front panel buttons working properly for newer LCD devices,
+ * we really do need a larger buffer.
+ */
+ if (usb_match_id(interface, large_buffer_list))
+ buf_chunk_size = 2 * BUF_CHUNK_SIZE;
+
+ code_length = buf_chunk_size * 8;
+
+ 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);
+
+ dev_dbg(dev, "%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:
+ * first input endpoint = IR endpoint
+ * first output endpoint = display endpoint
+ */
+ for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) {
+ struct usb_endpoint_descriptor *ep;
+ int ep_dir;
+ int ep_type;
+ ep = &iface_desc->endpoint[i].desc;
+ ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
+ ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+
+ if (!ir_ep_found &&
+ ep_dir == USB_DIR_IN &&
+ ep_type == USB_ENDPOINT_XFER_INT) {
+
+ rx_endpoint = ep;
+ ir_ep_found = 1;
+ dev_dbg(dev, "%s: found IR endpoint\n", __func__);
+
+ } else if (!display_ep_found &&
+ ep_dir == USB_DIR_OUT &&
+ ep_type == USB_ENDPOINT_XFER_INT) {
+ tx_endpoint = ep;
+ display_ep_found = 1;
+ dev_dbg(dev, "%s: found display endpoint\n", __func__);
+ }
+ }
+
+ /*
+ * If we didn't find a display endpoint, this is probably one of the
+ * newer iMON devices that use control urb instead of interrupt
+ */
+ if (!display_ep_found) {
+ if (usb_match_id(interface, ctl_ep_device_list)) {
+ tx_control = 1;
+ display_ep_found = 1;
+ dev_dbg(dev, "%s: device uses control endpoint, not "
+ "interface OUT endpoint\n", __func__);
+ }
+ }
+
+ /*
+ * Some iMON receivers have no display. Unfortunately, it seems
+ * that SoundGraph recycles device IDs between devices both with
+ * and without... :\
+ */
+ if (configured_display_type == IMON_DISPLAY_TYPE_NONE) {
+ display_ep_found = 0;
+ dev_dbg(dev, "%s: device has no display\n", __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 (configured_display_type == IMON_DISPLAY_TYPE_VGA) {
+ display_ep_found = 0;
+ dev_dbg(dev, "%s: iMON Touch device found\n", __func__);
+ }
+
+ /* Input endpoint is mandatory */
+ if (!ir_ep_found) {
+ err("%s: no valid input (IR) endpoint found.", __func__);
+ retval = -ENODEV;
+ goto exit;
+ } else {
+ /* Determine if the IR signals are decoded onboard */
+ if (usb_match_id(interface, ir_onboard_decode_list))
+ ir_onboard_decode = 1;
+
+ dev_dbg(dev, "%s: ir_onboard_decode: %d\n",
+ __func__, ir_onboard_decode);
+ }
+
+ /* Determine if display requires 6 packets */
+ if (display_ep_found) {
+ if (usb_match_id(interface, vfd_proto_6p_list))
+ vfd_proto_6p = 1;
+
+ dev_dbg(dev, "%s: vfd_proto_6p: %d\n",
+ __func__, vfd_proto_6p);
+ }
+
+ 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;
+ }
+ 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->vfd_proto_6p = vfd_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;
+
+ mutex_lock(&context->lock);
+
+ context->driver = driver;
+ /* start out in keyboard mode */
+ context->pad_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
+ dev_info(dev, "Registered iMON driver "
+ "(lirc minor: %d)\n", 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 = 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;
+
+ /*
+ * tx is used to send characters to lcd/vfd, associate RF
+ * remotes, set IR protocol, and maybe more...
+ */
+ context->tx_endpoint = tx_endpoint;
+ context->tx_urb = tx_urb;
+ context->tx_control = tx_control;
+
+ if (display_ep_found)
+ context->display_supported = 1;
+
+ if (product == 0xffdc)
+ context->ffdc_dev = 1;
+
+ context->display_type = configured_display_type;
+
+ context->idev = input_allocate_device();
+ input_set_drvdata(context->idev, context);
+
+ snprintf(context->name_idev, sizeof(context->name_idev),
+ "iMON IR Remote (%04x:%04x)", vendor, product);
+ context->idev->name = context->name_idev;
+
+ usb_make_path(usbdev, context->phys_idev,
+ sizeof(context->phys_idev));
+ strlcat(context->phys_idev, "/input0",
+ sizeof(context->phys_idev));
+ context->idev->phys = context->phys_idev;
+
+ context->idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+
+ context->idev->keybit[BIT_WORD(BTN_MOUSE)] =
+ BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
+ context->idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) |
+ BIT_MASK(REL_WHEEL);
+
+ /* register all the keys we support */
+ for (i = 0; i < ARRAY_SIZE(imon_remote_key_table); i++) {
+ u16 kc = imon_remote_key_table[i].keycode;
+ __set_bit(kc, context->idev->keybit);
+ }
+ for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) {
+ u16 kc = imon_panel_key_table[i].keycode;
+ __set_bit(kc, context->idev->keybit);
+ }
+ for (i = 0; i < ARRAY_SIZE(imon_mce_key_table); i++) {
+ u16 kc = imon_mce_key_table[i].keycode;
+ __set_bit(kc, context->idev->keybit);
+ }
+
+ usb_to_input_id(usbdev, &context->idev->id);
+ context->idev->dev.parent = &interface->dev;
+ retval = input_register_device(context->idev);
+ if (retval)
+ dev_info(dev, "%s: input device setup failed\n",
+ __func__);
+
+ 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_intf0, context,
+ context->rx_endpoint_intf0->bInterval);
+
+ retval = usb_submit_urb(context->rx_urb_intf0, GFP_KERNEL);
+
+ if (retval) {
+ err("%s: usb_submit_urb failed for intf0 (%d)",
+ __func__, retval);
+ mutex_unlock(&context->lock);
+ goto exit;
+ }
+
+ } else {
+ context->usbdev_intf1 = usbdev;
+ context->dev_present_intf1 = 1;
+ context->rx_endpoint_intf1 = rx_endpoint;
+ context->rx_urb_intf1 = rx_urb;
+
+ if (context->display_type == IMON_DISPLAY_TYPE_VGA) {
+ context->touch = input_allocate_device();
+
+ snprintf(context->name_touch,
+ sizeof(context->name_touch),
+ "iMON USB Touchscreen (%04x:%04x)",
+ vendor, product);
+ context->touch->name = context->name_touch;
+
+ usb_make_path(usbdev, context->phys_touch,
+ sizeof(context->phys_touch));
+ strlcat(context->phys_touch, "/input1",
+ sizeof(context->phys_touch));
+ context->touch->phys = context->phys_touch;
+
+ 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);
+ if (retval)
+ dev_info(dev, "%s: touchscreen input device "
+ "setup failed\n", __func__);
+ } else
+ context->touch = NULL;
+
+ 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);
+ mutex_unlock(&context->lock);
+ goto exit;
+ }
+ }
+
+ usb_set_intfdata(interface, context);
+
+ /* RF products *also* use 0xffdc... sigh... */
+ if (context->ffdc_dev) {
+ sysfs_err = sysfs_create_group(&interface->dev.kobj,
+ &imon_rf_attribute_group);
+ if (sysfs_err)
+ err("%s: Could not create RF sysfs entries(%d)",
+ __func__, sysfs_err);
+ }
+
+ if (context->display_supported && ifnum == 0) {
+ dev_dbg(dev, "%s: Registering iMON display with sysfs\n",
+ __func__);
+
+ /* set up sysfs entry for built-in clock */
+ sysfs_err = sysfs_create_group(&interface->dev.kobj,
+ &imon_display_attribute_group);
+ if (sysfs_err)
+ err("%s: Could not create display sysfs entries(%d)",
+ __func__, sysfs_err);
+
+ if (usb_register_dev(interface, &imon_class)) {
+ /* Not a fatal error, so ignore */
+ dev_info(dev, "%s: could not get a minor number for "
+ "display\n", __func__);
+ }
+
+ /* 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)
+ dev_info(dev, "%s: failed to enable front-panel "
+ "buttons and/or knobs\n", __func__);
+ }
+
+ /* set IR protocol/remote type */
+ imon_set_ir_protocol(context);
+
+ dev_info(dev, "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:
+ usb_free_urb(tx_urb);
+ case 6:
+ usb_free_urb(rx_urb);
+ case 5:
+ if (rbuf)
+ lirc_buffer_free(rbuf);
+ case 4:
+ kfree(rbuf);
+ case 3:
+ kfree(driver);
+ case 2:
+ kfree(context);
+ context = NULL;
+ case 1:
+ retval = -ENOMEM;
+ break;
+ case 0:
+ retval = 0;
+ }
+
+exit:
+ mutex_unlock(&driver_lock);
+
+ return retval;
+}
+
+/**
+ * Callback function for USB core API: disconnect
+ */
+static void imon_disconnect(struct usb_interface *interface)
+{
+ struct imon_context *context;
+ int ifnum;
+
+ /* prevent races with ir_open()/display_open() */
+ mutex_lock(&driver_lock);
+
+ context = usb_get_intfdata(interface);
+ ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
+
+ mutex_lock(&context->lock);
+
+ /*
+ * sysfs_remove_group is safe to call even if sysfs_create_group
+ * hasn't been called
+ */
+ sysfs_remove_group(&interface->dev.kobj,
+ &imon_display_attribute_group);
+ sysfs_remove_group(&interface->dev.kobj,
+ &imon_rf_attribute_group);
+
+ usb_set_intfdata(interface, NULL);
+
+ /* Abort ongoing write */
+ if (atomic_read(&context->tx.busy)) {
+ usb_kill_urb(context->tx_urb);
+ complete_all(&context->tx.finished);
+ }
+
+ if (ifnum == 0) {
+ context->dev_present_intf0 = 0;
+ usb_kill_urb(context->rx_urb_intf0);
+ input_unregister_device(context->idev);
+ 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->display_type == IMON_DISPLAY_TYPE_VGA)
+ input_unregister_device(context->touch);
+ }
+
+ 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(&driver_lock);
+
+ 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 (ifnum == 0)
+ usb_kill_urb(context->rx_urb_intf0);
+ else
+ usb_kill_urb(context->rx_urb_intf1);
+
+ return 0;
+}
+
+static int imon_resume(struct usb_interface *intf)
+{
+ int rc = 0;
+ struct imon_context *context = usb_get_intfdata(intf);
+ int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+ if (ifnum == 0) {
+ 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_intf0, context,
+ context->rx_endpoint_intf0->bInterval);
+
+ rc = usb_submit_urb(context->rx_urb_intf0, GFP_ATOMIC);
+
+ } else {
+ 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);
+
+ rc = usb_submit_urb(context->rx_urb_intf1, GFP_ATOMIC);
+ }
+
+ return rc;
+}
+
+static int __init imon_init(void)
+{
+ int rc;
+
+ printk(KERN_INFO MOD_NAME ": " MOD_DESC ", v" MOD_VERSION "\n");
+
+ rc = usb_register(&imon_driver);
+ if (rc) {
+ err("%s: usb register failed(%d)", __func__, rc);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void __exit imon_exit(void)
+{
+ usb_deregister(&imon_driver);
+ printk(KERN_INFO MOD_NAME ": module removed. Goodbye!\n");
+}
+
+module_init(imon_init);
+module_exit(imon_exit);
Index: b/drivers/input/lirc/lirc_imon.h
===================================================================
--- /dev/null
+++ b/drivers/input/lirc/lirc_imon.h
@@ -0,0 +1,209 @@
+/*
+ * lirc_imon.h: LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD
+ * including the iMON PAD model
+ *
+ * Copyright(C) 2004 Venky Raju([email protected])
+ * Copyright(C) 2009 Jarod Wilson <[email protected]>
+ *
+ * lirc_imon is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+static const struct {
+ u32 hw_code;
+ u16 keycode;
+} imon_remote_key_table[] = {
+ /* keys sorted mostly by frequency of use to optimize lookups */
+ { 0x2a8195b7, KEY_REWIND },
+ { 0x298315b7, KEY_REWIND },
+ { 0x2b8115b7, KEY_FASTFORWARD },
+ { 0x2b8315b7, KEY_FASTFORWARD },
+ { 0x2b9115b7, KEY_PREVIOUS },
+ { 0x298195b7, KEY_NEXT },
+
+ { 0x2a8115b7, KEY_PLAY },
+ { 0x2a8315b7, KEY_PLAY },
+ { 0x2a9115b7, KEY_PAUSE },
+ { 0x2b9715b7, KEY_STOP },
+ { 0x298115b7, KEY_RECORD },
+
+ { 0x01008000, KEY_UP },
+ { 0x01007f00, KEY_DOWN },
+ { 0x01000080, KEY_LEFT },
+ { 0x0100007f, KEY_RIGHT },
+
+ { 0x2aa515b7, KEY_UP },
+ { 0x289515b7, KEY_DOWN },
+ { 0x29a515b7, KEY_LEFT },
+ { 0x2ba515b7, KEY_RIGHT },
+
+ { 0x0200002c, KEY_SPACE }, /* Select/Space */
+ { 0x02000028, KEY_ENTER },
+ { 0x288195b7, KEY_EXIT },
+ { 0x02000029, KEY_ESC },
+ { 0x0200002a, KEY_BACKSPACE },
+
+ { 0x2b9595b7, KEY_MUTE },
+ { 0x28a395b7, KEY_VOLUMEUP },
+ { 0x28a595b7, KEY_VOLUMEDOWN },
+ { 0x289395b7, KEY_CHANNELUP },
+ { 0x288795b7, KEY_CHANNELDOWN },
+
+ { 0x0200001e, KEY_NUMERIC_1 },
+ { 0x0200001f, KEY_NUMERIC_2 },
+ { 0x02000020, KEY_NUMERIC_3 },
+ { 0x02000021, KEY_NUMERIC_4 },
+ { 0x02000022, KEY_NUMERIC_5 },
+ { 0x02000023, KEY_NUMERIC_6 },
+ { 0x02000024, KEY_NUMERIC_7 },
+ { 0x02000025, KEY_NUMERIC_8 },
+ { 0x02000026, KEY_NUMERIC_9 },
+ { 0x02000027, KEY_NUMERIC_0 },
+
+ { 0x02200025, KEY_NUMERIC_STAR },
+ { 0x02200020, KEY_NUMERIC_POUND },
+
+ { 0x2b8515b7, KEY_VIDEO },
+ { 0x299195b7, KEY_AUDIO },
+ { 0x2ba115b7, KEY_CAMERA },
+ { 0x28a515b7, KEY_TV },
+ { 0x29a395b7, KEY_DVD },
+ { 0x29a295b7, KEY_DVD },
+
+ /* the Menu key between DVD and Subtitle on the RM-200... */
+ { 0x2ba385b7, KEY_MENU },
+ { 0x2ba395b7, KEY_MENU },
+
+ { 0x288515b7, KEY_BOOKMARKS },
+ { 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */
+ { 0x298595b7, KEY_SUBTITLE },
+ { 0x2b8595b7, KEY_LANGUAGE },
+
+ { 0x29a595b7, KEY_ZOOM },
+ { 0x2aa395b7, KEY_SCREEN }, /* FullScreen */
+
+ { 0x299115b7, KEY_KEYBOARD },
+ { 0x299135b7, KEY_KEYBOARD },
+
+ { 0x01010000, BTN_LEFT },
+ { 0x01020000, BTN_RIGHT },
+ { 0x01010080, BTN_LEFT },
+ { 0x01020080, BTN_RIGHT },
+
+ { 0x2a9395b7, KEY_CYCLEWINDOWS }, /* TaskSwitcher */
+ { 0x2b8395b7, KEY_TIME }, /* Timer */
+
+ { 0x289115b7, KEY_POWER },
+ { 0x29b195b7, KEY_EJECTCD }, /* the one next to play */
+ { 0x299395b7, KEY_EJECTCLOSECD }, /* eject (above TaskSwitcher) */
+
+ { 0x02800000, KEY_MENU }, /* Left Menu */
+ { 0x02000065, KEY_COMPOSE }, /* RightMenu */
+ { 0x2ab195b7, KEY_PROG1 }, /* Go */
+ { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */
+};
+
+static const struct {
+ u32 hw_code;
+ u16 keycode;
+} imon_mce_key_table[] = {
+ /* keys sorted mostly by frequency of use to optimize lookups */
+ { 0x800f8415, KEY_REWIND },
+ { 0x800f8414, KEY_FASTFORWARD },
+ { 0x800f841b, KEY_PREVIOUS },
+ { 0x800f841a, KEY_NEXT },
+
+ { 0x800f8416, KEY_PLAY },
+ { 0x800f8418, KEY_PAUSE },
+ { 0x800f8418, KEY_PAUSE },
+ { 0x800f8419, KEY_STOP },
+ { 0x800f8417, KEY_RECORD },
+
+ { 0x02000052, KEY_UP },
+ { 0x02000051, KEY_DOWN },
+ { 0x02000050, KEY_LEFT },
+ { 0x0200004f, KEY_RIGHT },
+
+ { 0x02000028, KEY_ENTER },
+/* the OK and Enter buttons decode to the same value
+ { 0x02000028, KEY_OK }, */
+ { 0x0200002a, KEY_EXIT },
+ { 0x02000029, KEY_DELETE },
+
+ { 0x800f840e, KEY_MUTE },
+ { 0x800f8410, KEY_VOLUMEUP },
+ { 0x800f8411, KEY_VOLUMEDOWN },
+ { 0x800f8412, KEY_CHANNELUP },
+ { 0x800f8413, KEY_CHANNELDOWN },
+
+ { 0x0200001e, KEY_NUMERIC_1 },
+ { 0x0200001f, KEY_NUMERIC_2 },
+ { 0x02000020, KEY_NUMERIC_3 },
+ { 0x02000021, KEY_NUMERIC_4 },
+ { 0x02000022, KEY_NUMERIC_5 },
+ { 0x02000023, KEY_NUMERIC_6 },
+ { 0x02000024, KEY_NUMERIC_7 },
+ { 0x02000025, KEY_NUMERIC_8 },
+ { 0x02000026, KEY_NUMERIC_9 },
+ { 0x02000027, KEY_NUMERIC_0 },
+
+ { 0x02200025, KEY_NUMERIC_STAR },
+ { 0x02200020, KEY_NUMERIC_POUND },
+
+ { 0x800f8446, KEY_TV },
+ { 0x800f8447, KEY_AUDIO },
+ { 0x800f8448, KEY_PVR }, /* RecordedTV */
+ { 0x800f8449, KEY_CAMERA },
+ { 0x800f844a, KEY_VIDEO },
+ { 0x800f8424, KEY_DVD },
+ { 0x800f8425, KEY_TUNER }, /* LiveTV */
+
+ { 0x800f845b, KEY_RED },
+ { 0x800f845c, KEY_GREEN },
+ { 0x800f845d, KEY_YELLOW },
+ { 0x800f845e, KEY_BLUE },
+
+ { 0x800f840f, KEY_INFO },
+ { 0x800f8426, KEY_EPG }, /* Guide */
+ { 0x800f845a, KEY_SUBTITLE }, /* Caption */
+
+ { 0x800f840c, KEY_POWER },
+ { 0x800f840d, KEY_PROG1 }, /* Windows MCE button */
+
+};
+
+static const struct {
+ 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 },
+};
On Oct 20, 2009, at 9:56 AM, Jarod Wilson wrote:
> This here is a second go at submitting linux infrared remote control
> (lirc) drivers for kernel inclusion, with a much smaller patch set
> that
> includes only the core lirc driver and two device drivers, all three
> of
> which have been heavily updated since the last submission, based on
> feedback received.
Hm. Submitting this while the vast majority of people who might review
it were at the Japan Linux Symposium seems like it might have been a
bad idea. Or does no feedback mean its all good and ready to be
merged? ;)
--
Jarod Wilson
[email protected]
On Wed, 2009-11-04 at 17:56 -0500, Jarod Wilson wrote:
> On Oct 20, 2009, at 9:56 AM, Jarod Wilson wrote:
>
> > This here is a second go at submitting linux infrared remote control
> > (lirc) drivers for kernel inclusion, with a much smaller patch set
> > that
> > includes only the core lirc driver and two device drivers, all three
> > of
> > which have been heavily updated since the last submission, based on
> > feedback received.
>
> Hm. Submitting this while the vast majority of people who might review
> it were at the Japan Linux Symposium seems like it might have been a
> bad idea. Or does no feedback mean its all good and ready to be
> merged? ;)
Silence is concurrence. :)
Actually I will note, that lirc_dev.h uses kfifo:
http://git.wilsonet.com/linux-2.6-lirc.git/?a=blob_plain;f=drivers/input/lirc/lirc_dev.h;hb=f47f5e852d08f174c303d0ed53649733190014f7
but it least it appear to be nicely wrappered in that file. Moving to a
new kfifo implementation should be fairly easy, if the kfifo change
makes it in first.
Regards,
Andy
Em Wed, 4 Nov 2009 17:56:31 -0500
Jarod Wilson <[email protected]> escreveu:
> On Oct 20, 2009, at 9:56 AM, Jarod Wilson wrote:
>
> > This here is a second go at submitting linux infrared remote control
> > (lirc) drivers for kernel inclusion, with a much smaller patch set
> > that
> > includes only the core lirc driver and two device drivers, all three
> > of
> > which have been heavily updated since the last submission, based on
> > feedback received.
>
> Hm. Submitting this while the vast majority of people who might review
> it were at the Japan Linux Symposium seems like it might have been a
> bad idea.
True :) Such long trips generally affects the week before (to finish some
pending stuff before traveling) and the week after, where we have a big
backlog to handle.
> Or does no feedback mean its all good and ready to be
> merged? ;)
They are on my queue. I was handling a long pile of patches for the existing
drivers during last week. I intend to send the fixes upstream during this week,
and then going to analyze the lirc patches.
It would be wonderful to get also some feedback from the event/input people.
Cheers,
Mauro
On Nov 4, 2009, at 7:07 PM, Andy Walls wrote:
> On Wed, 2009-11-04 at 17:56 -0500, Jarod Wilson wrote:
>> On Oct 20, 2009, at 9:56 AM, Jarod Wilson wrote:
>>
>>> This here is a second go at submitting linux infrared remote control
>>> (lirc) drivers for kernel inclusion, with a much smaller patch set
>>> that
>>> includes only the core lirc driver and two device drivers, all three
>>> of
>>> which have been heavily updated since the last submission, based on
>>> feedback received.
>>
>> Hm. Submitting this while the vast majority of people who might
>> review
>> it were at the Japan Linux Symposium seems like it might have been a
>> bad idea. Or does no feedback mean its all good and ready to be
>> merged? ;)
>
> Silence is concurrence. :)
>
> Actually I will note, that lirc_dev.h uses kfifo:
>
> http://git.wilsonet.com/linux-2.6-lirc.git/?a=blob_plain;f=drivers/input/lirc/lirc_dev.h;hb=f47f5e852d08f174c303d0ed53649733190014f7
>
> but it least it appear to be nicely wrappered in that file. Moving
> to a
> new kfifo implementation should be fairly easy, if the kfifo change
> makes it in first.
Yeah, been keeping an eye on your own kfifo usage discussion w/lirc's
usage in mind... Thank you for blazing that trail. ;)
--
Jarod Wilson
[email protected]
On Nov 4, 2009, at 7:31 PM, Mauro Carvalho Chehab wrote:
> Em Wed, 4 Nov 2009 17:56:31 -0500
> Jarod Wilson <[email protected]> escreveu:
>
>> On Oct 20, 2009, at 9:56 AM, Jarod Wilson wrote:
>>
>>> This here is a second go at submitting linux infrared remote control
>>> (lirc) drivers for kernel inclusion, with a much smaller patch set
>>> that
>>> includes only the core lirc driver and two device drivers, all three
>>> of
>>> which have been heavily updated since the last submission, based on
>>> feedback received.
>>
>> Hm. Submitting this while the vast majority of people who might
>> review
>> it were at the Japan Linux Symposium seems like it might have been a
>> bad idea.
>
> True :) Such long trips generally affects the week before (to finish
> some
> pending stuff before traveling) and the week after, where we have a
> big
> backlog to handle.
>
>> Or does no feedback mean its all good and ready to be
>> merged? ;)
>
> They are on my queue. I was handling a long pile of patches for the
> existing
> drivers during last week. I intend to send the fixes upstream during
> this week,
> and then going to analyze the lirc patches.
I'd heard as much, but figured I should go ahead with the fishing
expedition just the same to see if we couldn't hook anyone else too...
> It would be wonderful to get also some feedback from the event/input
> people.
Yeah, I think that's probably the folks who really have the final say
on this, as we're ultimately (mostly) input devices.
--
Jarod Wilson
[email protected]
Hi
Thank you for trying to get lirc mainline. Hoping that no real complaints
against it arise, what about submitting the tree to linux-next, so it gets
more testing exposure before the merge window opens for 2.6.33?
On Friday 13 November 2009, Jarod Wilson wrote:
> lirc driver for Windows Media Center Ed. IR transceivers
[...]
> Index: b/drivers/input/lirc/Kconfig
> ===================================================================
> --- a/drivers/input/lirc/Kconfig
> +++ b/drivers/input/lirc/Kconfig
> @@ -11,6 +11,10 @@ menuconfig INPUT_LIRC
>
> if INPUT_LIRC
>
> -# Device-specific drivers go here
> +config LIRC_MCEUSB
> + tristate "Windows Media Center Ed. USB IR Transceiver"
> + depends on LIRC_DEV && USB
You have obviously renamed LIRC_DEV to INPUT_LIRC just before the
submission, but missed to do so for the individual drivers which still
depend on LIRC_DEV and are therefore not selectable; the same applies to
[PATCH 3/3 v2] lirc driver for SoundGraph iMON IR receivers and displays.
> + help
> + Driver for Windows Media Center Ed. USB IR Transceivers
>
> endif
Regards
Stefan Lippers-Hollmann
On Nov 13, 2009, at 3:43 PM, Stefan Lippers-Hollmann wrote:
> Hi
>
> Thank you for trying to get lirc mainline. Hoping that no real complaints
> against it arise, what about submitting the tree to linux-next, so it gets
> more testing exposure before the merge window opens for 2.6.33?
At the point, I'd be happy with getting into linux-next or even the staging tree.
> On Friday 13 November 2009, Jarod Wilson wrote:
>> lirc driver for Windows Media Center Ed. IR transceivers
> [...]
>> Index: b/drivers/input/lirc/Kconfig
>> ===================================================================
>> --- a/drivers/input/lirc/Kconfig
>> +++ b/drivers/input/lirc/Kconfig
>> @@ -11,6 +11,10 @@ menuconfig INPUT_LIRC
>>
>> if INPUT_LIRC
>>
>> -# Device-specific drivers go here
>> +config LIRC_MCEUSB
>> + tristate "Windows Media Center Ed. USB IR Transceiver"
>> + depends on LIRC_DEV && USB
>
> You have obviously renamed LIRC_DEV to INPUT_LIRC just before the
> submission, but missed to do so for the individual drivers which still
> depend on LIRC_DEV and are therefore not selectable; the same applies to
> [PATCH 3/3 v2] lirc driver for SoundGraph iMON IR receivers and displays.
D'oh. Yeah, I sure did. Didn't notice the fubar, because I was building and testing the stuff on an existing kernel that already had LIRC_DEV defined. Earlier versions actually had both INPUT_LIRC and LIRC_DEV, which are essentially one in the same. I'll fix that shortly.
--
Jarod Wilson
[email protected]
Hi Jarod,
Jarod Wilson wrote:
> Core Linux Infrared Remote Control driver and infrastructure
>
> -Add Kconfig and Makefile bits
> -Add device driver interface and headers
>
> The initial Kconfig and Makefile bits were done by Mario Limonciello for
> the Ubuntu kernel, but have been tweaked a bit since then. Any errors are
> probably my doing.
>
> Changes from prior submission:
> - Now uses dev_dbg instead of its own dprintk
> - Dynamic device numbers used
> - sleep_on() ripped out in favor of wake bits
> - Kconfig text improved and simplified
> - All inline keywords removed where possible
> - Obfuscating #defines and wrapper functions removed
> - We call 'em lirc drivers now instead of lirc plugins
Sorry to not analyze the code before. -ETOOBUSY here...
Some generic comments first:
1) As I said before, this code adds a new input API. So, you should
get input people's ack about it. It seems fine for me;
2) It would be really cool if you could submit a patch for DocBook as
well, in order to describe the API. IMO, the better is to put it together
with media infrastructure docbook, since, although it is possible to use
lirc code with other hardware (and were originally designed for it), the
current wider usage is together with V4L/DVB devices. The Docbooks are
at kernel Documentation/DocBook/ directory. Also, we have a copy of it
at our development tree (http://linuxtv.org/hg/v4l-dvb) at media-specs/
directory.
3) In general, the code looks sane for me. I have just a few small sugestions
for improvements:
> Index: b/drivers/input/lirc/lirc.h
> ===================================================================
> --- /dev/null
> +++ b/drivers/input/lirc/lirc.h
Hmm... as you're defining the kernel userspace interface, it would
be better to put the header under include/linux.
> +#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)
> +
Hmm... unsigned int/unsigned long are not portable between different architectures.
It would be better to use instead __u16/__u32/__u64. This way, you won't need
a 32 bits compat layer.
> +
> +int lirc_register_driver(struct lirc_driver *d)
> +{
> + struct irctl *ir;
> + int minor;
> + int bytes_in_key;
> + unsigned int chunk_size;
> + unsigned int buffer_size;
> + int err;
> +
> + if (!d) {
> + printk(KERN_ERR "lirc_dev: lirc_register_driver: "
> + "driver pointer must be not NULL!\n");
> + err = -EBADRQC;
> + goto out;
> + }
> +
> + if (MAX_IRCTL_DEVICES <= d->minor) {
> + dev_err(d->dev, "lirc_dev: lirc_register_driver: "
> + "\"minor\" must be between 0 and %d (%d)!\n",
> + MAX_IRCTL_DEVICES-1, d->minor);
> + err = -EBADRQC;
> + goto out;
> + }
> +
> + if (1 > d->code_length || (BUFLEN * 8) < d->code_length) {
> + dev_err(d->dev, "lirc_dev: lirc_register_driver: "
> + "code length in bits for minor (%d) "
> + "must be less than %d!\n",
> + d->minor, BUFLEN * 8);
> + err = -EBADRQC;
> + goto out;
> + }
> +
> + dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n",
> + d->sample_rate);
> + if (d->sample_rate) {
> + if (2 > d->sample_rate || HZ < d->sample_rate) {
> + dev_err(d->dev, "lirc_dev: lirc_register_driver: "
> + "sample_rate must be between 2 and %d!\n", HZ);
> + err = -EBADRQC;
> + goto out;
> + }
> + if (!d->add_to_buf) {
> + dev_err(d->dev, "lirc_dev: lirc_register_driver: "
> + "add_to_buf cannot be NULL when "
> + "sample_rate is set\n");
> + err = -EBADRQC;
> + goto out;
> + }
> + } else if (!(d->fops && d->fops->read) && !d->rbuf) {
> + dev_err(d->dev, "lirc_dev: lirc_register_driver: "
> + "fops->read and rbuf cannot all be NULL!\n");
> + err = -EBADRQC;
> + goto out;
> + } else if (!d->rbuf) {
> + if (!(d->fops && d->fops->read && d->fops->poll &&
> + d->fops->ioctl)) {
> + dev_err(d->dev, "lirc_dev: lirc_register_driver: "
> + "neither read, poll nor ioctl can be NULL!\n");
> + err = -EBADRQC;
> + goto out;
> + }
> + }
> +
> + mutex_lock(&lirc_dev_lock);
> +
> + minor = d->minor;
> +
> + if (minor < 0) {
> + /* find first free slot for driver */
> + for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++)
> + if (!irctls[minor])
> + break;
> + if (MAX_IRCTL_DEVICES == minor) {
> + dev_err(d->dev, "lirc_dev: lirc_register_driver: "
> + "no free slots for drivers!\n");
> + err = -ENOMEM;
> + goto out_lock;
> + }
> + } else if (irctls[minor]) {
> + dev_err(d->dev, "lirc_dev: lirc_register_driver: "
> + "minor (%d) just registered!\n", minor);
> + err = -EBUSY;
> + goto out_lock;
> + }
> +
> + ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
> + if (!ir) {
> + err = -ENOMEM;
> + goto out_lock;
> + }
> + init_irctl(ir);
> + irctls[minor] = ir;
> + d->minor = minor;
> +
> + if (d->sample_rate) {
> + ir->jiffies_to_wait = HZ / d->sample_rate;
> + } else {
> + /* it means - wait for external event in task queue */
> + ir->jiffies_to_wait = 0;
> + }
> +
> + /* some safety check 8-) */
> + d->name[sizeof(d->name)-1] = '\0';
> +
> + bytes_in_key = BITS_TO_LONGS(d->code_length) +
> + (d->code_length % 8 ? 1 : 0);
> + buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key;
> + chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key;
> +
> + if (d->rbuf) {
> + ir->buf = d->rbuf;
> + } else {
> + ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
For security reasons, wouldn't be better to use kzalloc here?
> +#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)
You wouldn't need those code, if you declare the ioctl's as __u32 at the
first place.
Also, the compat layer is needed not only for x86_64, but some other architectures
like sparc64 needs it, since userspace is 32 bits and kernelspace is 64 bits.
With V4L ioctls, we needed to do some adjustments for sparc, since the sizes there
are different for other types as well. Unfortunately, I can't remember what were
the difference (maybe int size?).
So, IMO, it would be a way better if you just declare everything using __u16/__u32/__u64
at the original ioctl definition and just remove all compat code.
> +EXPORT_SYMBOL(lirc_register_driver);
> +EXPORT_SYMBOL(lirc_unregister_driver);
> +EXPORT_SYMBOL(lirc_dev_fop_close);
> +EXPORT_SYMBOL(lirc_dev_fop_poll);
> +EXPORT_SYMBOL(lirc_dev_fop_ioctl);
> +EXPORT_SYMBOL(lirc_dev_fop_compat_ioctl);
> +EXPORT_SYMBOL(lirc_dev_fop_read);
> +EXPORT_SYMBOL(lirc_get_pdata);
> +EXPORT_SYMBOL(lirc_dev_fop_write);
I would declare everything as EXPORT_SYMBOL_GPL instead.
Mauro Carvalho Chehab wrote:
> Jarod Wilson wrote:
> 1) As I said before, this code adds a new input API. So, you should
> get input people's ack about it. It seems fine for me;
>> Index: b/drivers/input/lirc/lirc.h
>> ===================================================================
>> --- /dev/null
>> +++ b/drivers/input/lirc/lirc.h
>
> Hmm... as you're defining the kernel userspace interface, it would
> be better to put the header under include/linux.
It seems that I ran away from one important discussion here...
In fact, it seemed better to start a thread to discuss the API issues in
separate, an then adequate the code to do whatever decided.
-
The way the out-of-tree lirc driver works is by outputing (and inputing)
a raw sequence of pulses and spaces that have several different IR protocols,
like NEC, RC4, RC5, RC6 and pulse-distance protocols. On the other hand,
the current Input event interface (and the IR drivers at V4L/DVB code) does
is to have in-kernel code that converts those sequences or pulse/space into
a keystroke representation, outputing it to userspace.
To make things a little more complicated, it is also possible for some devices
to output IR codes. Let's first discuss the IR input case. IMO, whatever we define
for input, we should do also for output.
There's some advantages and disadvantages of both strategies, being the most
notable ones:
Raw pulse/space allows reception of IR's from all different variations of
the IR protocols. However:
it means a more complex setup at userspace, since the user must
use a daemon to decode IR code;
user must inform the IR type and the kernel driver that will receive
those keystrokes.
Event input has the advantage that the keystrokes will provide an unique
representation that is independent of the device. Considering the common case
where the lirc driver will be associated with a media input device, the
IR type can be detected automatically on kernel. However, advanced users may
opt to use other IR types than what's provided with the device they bought.
It should also be noticed that not all the already-existing IR drivers on kernel can
provide a lirc interface, since several devices have their own IR decoding chips
inside the hardware. On some cases, the hardware can be programmed to receive more
than one IR protocol type, where on others, the manufacturer provides IR decoding
capabilities only for the protocol they decided to provide together with their
hardware.
IMO, there are two different approaches that can be taken:
1) Just add lirc API as-is and let's have two different ways to get IR events
on kernel, and have two different API's for IR;
2) create a lirc kernel API, and have a layer there to decode IR protocols and
output them via the already existing input layer. In this case, all we need to do,
in terms of API, is to add a way to set the IR protocol that will be decoded,
and to enumberate the capabilities. The lirc API, will be an in-kernel API to
communicate with the devices that don't have IR protocols decoding capabilities
inside the hardware.
So, the basic question that should be decided is: should we create a new
userspace API for raw IR pulse/space or it would be better to standardize it
to always use the existing input layer?
Comments?
Cheers,
Mauro
Jarod Wilson wrote:
> lirc driver for Windows Media Center Ed. IR transceivers
>
> Successfully tested with the mce v2 transceiver and remote that shipped with a
> Hauppauge HVR-1500 expresscard tuner and an mce v1 transceiver from an old HP
> Media Center system.
>
> Changes from prior submission:
> - both v1 and v2 transceivers supported by one driver now
> - transmit works on the v1 devices
> - support for several new devices
> - now uses dev_dbg (and friends) instead of its own dprintk
>
> Signed-off-by: Jarod Wilson <[email protected]>
> Signed-off-by: Janne Grunau <[email protected]>
> CC: Christoph Bartelmus <[email protected]>
> Tested-by: Jarod Wilson <[email protected]>
>
> ---
> drivers/input/lirc/Kconfig | 6
> drivers/input/lirc/Makefile | 1
> drivers/input/lirc/lirc_mceusb.c | 1235 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 1241 insertions(+), 1 deletion(-)
>
> Index: b/drivers/input/lirc/Kconfig
> ===================================================================
> --- a/drivers/input/lirc/Kconfig
> +++ b/drivers/input/lirc/Kconfig
> @@ -11,6 +11,10 @@ menuconfig INPUT_LIRC
>
> if INPUT_LIRC
>
> -# Device-specific drivers go here
> +config LIRC_MCEUSB
> + tristate "Windows Media Center Ed. USB IR Transceiver"
> + depends on LIRC_DEV && USB
> + help
> + Driver for Windows Media Center Ed. USB IR Transceivers
>
> endif
> Index: b/drivers/input/lirc/Makefile
> ===================================================================
> --- a/drivers/input/lirc/Makefile
> +++ b/drivers/input/lirc/Makefile
> @@ -4,3 +4,4 @@
> # Each configuration option enables a list of files.
>
> obj-$(CONFIG_INPUT_LIRC) += lirc_dev.o
> +obj-$(CONFIG_LIRC_MCEUSB) += lirc_mceusb.o
> Index: b/drivers/input/lirc/lirc_mceusb.c
> ===================================================================
> --- /dev/null
> +++ b/drivers/input/lirc/lirc_mceusb.c
> @@ -0,0 +1,1235 @@
> +/*
> + * LIRC driver for Windows Media Center Edition USB Infrared Transceivers
> + *
> + * (C) by Martin A. Blatter <[email protected]>
> + *
> + * Transmitter support and reception code cleanup.
> + * (C) by Daniel Melander <[email protected]>
> + *
> + * Original lirc_mceusb driver for 1st-gen device:
> + * Copyright (c) 2003-2004 Dan Conti <[email protected]>
> + *
> + * Original lirc_mceusb driver deprecated in favor of this driver, which
> + * supports the 1st-gen device now too. Transmitting on the 1st-gen device
> + * only functions on port #2 at the moment.
> + *
> + * Support for 1st-gen device added June 2009,
> + * by Jarod Wilson <[email protected]>
> + *
> + * Initial transmission support for 1st-gen device added August 2009,
> + * by Patrick Calhoun <[email protected]>
> + *
> + * Derived from ATI USB driver by Paul Miller and the original
> + * MCE USB driver by Dan Conti (and now including chunks of the latter
> + * relevant to the 1st-gen device initialization)
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/kmod.h>
> +#include <linux/smp_lock.h>
> +#include <linux/completion.h>
> +#include <linux/uaccess.h>
> +#include <linux/usb.h>
> +#include <linux/wait.h>
> +#include <linux/time.h>
> +
> +#include "lirc.h"
> +#include "lirc_dev.h"
> +
> +#define DRIVER_VERSION "1.90"
> +#define DRIVER_AUTHOR "Daniel Melander <[email protected]>, " \
> + "Martin Blatter <[email protected]>, " \
> + "Dan Conti <[email protected]>"
> +#define DRIVER_DESC "Windows Media Center Edition USB IR Transceiver " \
> + "driver for LIRC"
> +#define DRIVER_NAME "lirc_mceusb"
> +
> +#define USB_BUFLEN 32 /* USB reception buffer length */
> +#define LIRCBUF_SIZE 256 /* LIRC work buffer length */
> +
> +/* MCE constants */
> +#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */
> +#define MCE_TIME_UNIT 50 /* Approx 50us resolution */
> +#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */
> +#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */
> +#define MCE_PACKET_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */
> +#define MCE_CONTROL_HEADER 0x9F /* MCE status header */
> +#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */
> +#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */
> +#define MCE_DEFAULT_TX_MASK 0x03 /* Val opts: TX1=0x01, TX2=0x02, ALL=0x03 */
> +#define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */
> +#define MCE_PULSE_MASK 0x7F /* Pulse mask */
> +#define MCE_MAX_PULSE_LENGTH 0x7F /* Longest transmittable pulse symbol */
> +#define MCE_PACKET_LENGTH_MASK 0x7F /* Pulse mask */
> +
> +
> +/* module parameters */
> +#ifdef CONFIG_USB_DEBUG
> +static int debug = 1;
> +#else
> +static int debug;
> +#endif
> +
> +/* general constants */
> +#define SEND_FLAG_IN_PROGRESS 1
> +#define SEND_FLAG_COMPLETE 2
> +#define RECV_FLAG_IN_PROGRESS 3
> +#define RECV_FLAG_COMPLETE 4
> +
> +#define MCEUSB_INBOUND 1
> +#define MCEUSB_OUTBOUND 2
> +
> +#define VENDOR_PHILIPS 0x0471
> +#define VENDOR_SMK 0x0609
> +#define VENDOR_TATUNG 0x1460
> +#define VENDOR_GATEWAY 0x107b
> +#define VENDOR_SHUTTLE 0x1308
> +#define VENDOR_SHUTTLE2 0x051c
> +#define VENDOR_MITSUMI 0x03ee
> +#define VENDOR_TOPSEED 0x1784
> +#define VENDOR_RICAVISION 0x179d
> +#define VENDOR_ITRON 0x195d
> +#define VENDOR_FIC 0x1509
> +#define VENDOR_LG 0x043e
> +#define VENDOR_MICROSOFT 0x045e
> +#define VENDOR_FORMOSA 0x147a
> +#define VENDOR_FINTEK 0x1934
> +#define VENDOR_PINNACLE 0x2304
> +#define VENDOR_ECS 0x1019
> +#define VENDOR_WISTRON 0x0fb8
> +#define VENDOR_COMPRO 0x185b
> +#define VENDOR_NORTHSTAR 0x04eb
Hmm... we should consider moving the USB ID's to a global kernel header, just like
what we have with PCI IDs...We have some of those ID's on some common headers:
drivers/hid/hid-ids.h
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
Unfortunately, it seems that each subsystem have their own place to store it, and
several drivers have the ID's at their own code.
> +#if 0
> + Uncomment this if the last 100ms "infinity"-space should be transmitted
> + to lirc directly instead of at the beginning of the next transmission.
> + Changes pulse/space order.
> +
> + if (++i < buf_len && ir->buf_in[i] == 0x01)
> + send_packet_to_lirc(ir);
> +
> +#endif
Hmm... Generating a different code if uncommenting it doesn't seem nice. It should
be checked what code will produce the right RC5 protocol and uncomment the #if or
remove it completely to avoid temptation of latter change the behavior by uncommenting
it.
> +
> +
> +static int mceusb_lirc_ioctl(struct inode *node, struct file *filep,
> + unsigned int cmd, unsigned long arg)
> +{
> + int result;
> + unsigned int ivalue;
> + unsigned long lvalue;
> + struct mceusb_dev *ir = NULL;
> +
> + /* Retrieve lirc_driver data for the device */
> + ir = lirc_get_pdata(filep);
> + if (!ir || !ir->usb_ep_out)
> + return -EFAULT;
> +
> +
> + switch (cmd) {
> + case LIRC_SET_TRANSMITTER_MASK:
> +
> + result = get_user(ivalue, (unsigned int *) arg);
> + if (result)
> + return result;
> + switch (ivalue) {
> + case 0x01: /* Transmitter 1 => 0x04 */
> + case 0x02: /* Transmitter 2 => 0x02 */
> + case 0x03: /* Transmitter 1 & 2 => 0x06 */
> + set_transmitter_mask(ir, ivalue);
> + break;
> +
> + default: /* Unsupported transmitter mask */
> + return MCE_MAX_CHANNELS;
> + }
> +
> + dev_dbg(ir->d->dev, ": SET_TRANSMITTERS mask=%d\n", ivalue);
> + break;
> +
> + case LIRC_GET_SEND_MODE:
> +
> + result = put_user(LIRC_SEND2MODE(LIRC_CAN_SEND_PULSE &
> + LIRC_CAN_SEND_MASK),
> + (unsigned long *) arg);
> +
> + if (result)
> + return result;
> + break;
> +
> + case LIRC_SET_SEND_MODE:
> +
> + result = get_user(lvalue, (unsigned long *) arg);
> +
> + if (result)
> + return result;
> + if (lvalue != (LIRC_MODE_PULSE&LIRC_CAN_SEND_MASK))
> + return -EINVAL;
> + break;
> +
> + case LIRC_SET_SEND_CARRIER:
> +
> + result = get_user(ivalue, (unsigned int *) arg);
> + if (result)
> + return result;
> +
> + set_send_carrier(ir, ivalue);
> + break;
> +
> + default:
> + return lirc_dev_fop_ioctl(node, filep, cmd, arg);
> + }
> +
> + return 0;
> +}
> +
> +static struct file_operations lirc_fops = {
> + .owner = THIS_MODULE,
> + .write = mceusb_transmit_ir,
> + .ioctl = mceusb_lirc_ioctl,
> + .read = lirc_dev_fop_read,
> + .poll = lirc_dev_fop_poll,
> + .open = lirc_dev_fop_open,
> + .release = lirc_dev_fop_close,
> +};
> +
> +static int mceusb_gen1_init(struct mceusb_dev *ir)
> +{
> + int i, ret;
> + char junk[64], data[8];
> + int partial = 0;
> +
> + /*
> + * Clear off the first few messages. These look like calibration
> + * or test data, I can't really tell. This also flushes in case
> + * we have random ir data queued up.
> + */
> + for (i = 0; i < 40; i++)
> + usb_bulk_msg(ir->usbdev,
> + usb_rcvbulkpipe(ir->usbdev,
> + ir->usb_ep_in->bEndpointAddress),
> + junk, 64, &partial, HZ * 10);
> +
> + ir->is_pulse = 1;
> +
> + memset(data, 0, 8);
Please use, instead:
memset(data, 0, sizeof(data));
> +
> + /* Get Status */
> + ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
> + USB_REQ_GET_STATUS, USB_DIR_IN,
> + 0, 0, data, 2, HZ * 3);
> +
> + /* ret = usb_get_status( ir->usbdev, 0, 0, data ); */
> + dev_dbg(ir->d->dev, "%s - ret = %d status = 0x%x 0x%x\n", __func__,
> + ret, data[0], data[1]);
> +
> + /*
> + * This is a strange one. They issue a set address to the device
> + * on the receive control pipe and expect a certain value pair back
> + */
> + memset(data, 0, 8);
Please use, instead:
memset(data, 0, sizeof(data));
> +
> + ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
> + USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
> + data, 2, HZ * 3);
> + dev_dbg(ir->d->dev, "%s - ret = %d, devnum = %d\n",
> + __func__, ret, ir->usbdev->devnum);
> + dev_dbg(ir->d->dev, "%s - data[0] = %d, data[1] = %d\n",
> + __func__, data[0], data[1]);
> +
> + /* set feature: bit rate 38400 bps */
> + ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
> + USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
> + 0xc04e, 0x0000, NULL, 0, HZ * 3);
> +
> + dev_dbg(ir->d->dev, "%s - ret = %d\n", __func__, ret);
> +
> + /* bRequest 4: set char length to 8 bits */
> + ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
> + 4, USB_TYPE_VENDOR,
> + 0x0808, 0x0000, NULL, 0, HZ * 3);
> + dev_dbg(ir->d->dev, "%s - retB = %d\n", __func__, ret);
> +
> + /* bRequest 2: set handshaking to use DTR/DSR */
> + ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
> + 2, USB_TYPE_VENDOR,
> + 0x0000, 0x0100, NULL, 0, HZ * 3);
> + dev_dbg(ir->d->dev, "%s - retC = %d\n", __func__, ret);
> +
> + return ret;
> +
> +};
> +
> +static int mceusb_dev_probe(struct usb_interface *intf,
> + const struct usb_device_id *id)
> +{
> + struct usb_device *dev = interface_to_usbdev(intf);
> + struct usb_host_interface *idesc;
> + struct usb_endpoint_descriptor *ep = NULL;
> + struct usb_endpoint_descriptor *ep_in = NULL;
> + struct usb_endpoint_descriptor *ep_out = NULL;
> + struct usb_host_config *config;
> + struct mceusb_dev *ir = NULL;
> + struct lirc_driver *driver = NULL;
> + struct lirc_buffer *rbuf = NULL;
> + int devnum, pipe, maxp;
> + int minor = 0;
> + int i;
> + char buf[63], name[128] = "";
> + int mem_failure = 0;
> + int is_pinnacle;
> + int is_microsoft_gen1;
> +
> + dev_dbg(&intf->dev, ": %s called\n", __func__);
> +
> + usb_reset_device(dev);
> +
> + config = dev->actconfig;
> +
> + idesc = intf->cur_altsetting;
> +
> + is_pinnacle = usb_match_id(intf, pinnacle_list) ? 1 : 0;
> +
> + is_microsoft_gen1 = usb_match_id(intf, microsoft_gen1_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;
> +
> + if ((ep_in == NULL)
> + && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
> + == USB_DIR_IN)
> + && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
> + == USB_ENDPOINT_XFER_BULK)
> + || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
> + == USB_ENDPOINT_XFER_INT))) {
> +
> + dev_dbg(&intf->dev, ": acceptable inbound endpoint "
> + "found\n");
> + ep_in = ep;
> + ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
> + if (is_pinnacle)
> + /*
> + * setting seems to 1 seem to cause issues with
> + * Pinnacle timing out on transfer.
> + */
> + ep_in->bInterval = ep->bInterval;
> + else
> + ep_in->bInterval = 1;
> + }
> +
> + if ((ep_out == NULL)
> + && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
> + == USB_DIR_OUT)
> + && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
> + == USB_ENDPOINT_XFER_BULK)
> + || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
> + == USB_ENDPOINT_XFER_INT))) {
> +
> + dev_dbg(&intf->dev, ": acceptable outbound endpoint "
> + "found\n");
> + ep_out = ep;
> + ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
> + if (is_pinnacle)
> + /*
> + * setting seems to 1 seem to cause issues with
> + * Pinnacle timing out on transfer.
> + */
> + ep_out->bInterval = ep->bInterval;
> + else
> + ep_out->bInterval = 1;
> + }
> + }
> + if (ep_in == NULL) {
> + dev_dbg(&intf->dev, ": inbound and/or endpoint not found\n");
> + return -ENODEV;
> + }
> +
> + devnum = dev->devnum;
> + pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress);
> + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
> +
> + mem_failure = 0;
> + ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL);
> + if (!ir) {
> + mem_failure = 1;
> + goto mem_failure_switch;
> + }
> +
> + driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
> + if (!driver) {
> + mem_failure = 2;
> + goto mem_failure_switch;
> + }
> +
> + rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
kzalloc?
> + if (!rbuf) {
> + mem_failure = 3;
> + goto mem_failure_switch;
> + }
> +
> + if (lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE)) {
> + mem_failure = 4;
> + goto mem_failure_switch;
> + }
> +
> + ir->buf_in = usb_buffer_alloc(dev, maxp, GFP_ATOMIC, &ir->dma_in);
> + if (!ir->buf_in) {
> + mem_failure = 5;
> + goto mem_failure_switch;
> + }
> +
> + ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
> + if (!ir->urb_in) {
> + mem_failure = 7;
> + goto mem_failure_switch;
> + }
> +
> + strcpy(driver->name, DRIVER_NAME);
> + driver->minor = -1;
> + driver->features = LIRC_CAN_SEND_PULSE |
> + LIRC_CAN_SET_TRANSMITTER_MASK |
> + LIRC_CAN_REC_MODE2 |
> + LIRC_CAN_SET_SEND_CARRIER;
> + driver->data = ir;
> + driver->rbuf = rbuf;
> + driver->set_use_inc = &mceusb_ir_open;
> + driver->set_use_dec = &mceusb_ir_close;
> + driver->code_length = sizeof(int) * 8;
> + driver->fops = &lirc_fops;
> + driver->dev = &intf->dev;
> + driver->owner = THIS_MODULE;
> +
> + mutex_init(&ir->lock);
> + init_waitqueue_head(&ir->wait_out);
> +
> + minor = lirc_register_driver(driver);
> + if (minor < 0)
> + mem_failure = 9;
> +
> +mem_failure_switch:
> +
> + switch (mem_failure) {
> + case 9:
> + usb_free_urb(ir->urb_in);
> + case 7:
> + usb_buffer_free(dev, maxp, ir->buf_in, ir->dma_in);
> + case 5:
> + lirc_buffer_free(rbuf);
> + case 4:
> + kfree(rbuf);
> + case 3:
> + kfree(driver);
> + case 2:
> + kfree(ir);
> + case 1:
> + dev_info(&intf->dev, "out of memory (code=%d)\n", mem_failure);
> + return -ENOMEM;
> + }
That seems ugly, IMHO ;) Better to use the standard way for it. Also, as kfree(NULL) is
valid, you could simply remove cases 3, 2 and 1.
The better is to use the standard way for errors, like:
error_free_urb:
usb_free_urb(ir->urb_in);
error_free_usb_buf:
usb_buffer_free(dev, maxp, ir->buf_in, ir->dma_in);
error_free_lirc_buf:
lirc_buffer_free(rbuf);
error:
kfree(rbuf);
kfree(driver);
kfree(ir);
dev_info(&intf->dev, "out of memory (code=%d)\n", mem_failure);
return -ENOMEM;
> +
> + driver->minor = minor;
> + ir->d = driver;
> + ir->devnum = devnum;
> + ir->usbdev = dev;
> + ir->len_in = maxp;
> + ir->overflow_len = 0;
> + ir->flags.connected = 0;
There's no need to initialize with 0, since kzalloc were used.
> + ir->flags.pinnacle = is_pinnacle;
> + ir->flags.microsoft_gen1 = is_microsoft_gen1;
> + ir->flags.transmitter_mask_inverted =
> + usb_match_id(intf, transmitter_mask_list) ? 0 : 1;
> +
> + ir->lircdata = PULSE_MASK;
> + ir->is_pulse = 0;
There's no need to initialize with 0, since kzalloc were used.
Cheers,
Mauro
Jarod Wilson wrote:
> lirc driver for SoundGraph iMON IR receivers and displays
>
> Successfully tested with multiple devices with and without displays.
>
> +static struct usb_device_id imon_usb_id_table[] = {
> + /* TriGem iMON (IR only) -- TG_iMON.inf */
> + { USB_DEVICE(0x0aa8, 0x8001) },
...
Another set of USB vendor ID's... this time, vendors weren't described. The
same comment I did on patch 2/3 applies here... IMO, we should really try
to create a global list of vendors/devices on kernel. Of course this is not
a non-go issue, as it is already present on several other USB drivers.
> +
> + /*
> + * Translate received data to pulse and space lengths.
> + * Received data is active low, i.e. pulses are 0 and
> + * spaces are 1.
> + *
> + * My original algorithm was essentially similar to
> + * Changwoo Ryu's with the exception that he switched
> + * the incoming bits to active high and also fed an
> + * initial space to LIRC at the start of a new sequence
> + * if the previous bit was a pulse.
> + *
> + * I've decided to adopt his algorithm.
> + */
> +
Before digging into all code details, am I wrong or this device has the
pulse/space decoding inside the chip?
In this case, we shouldn't really be converting their IR keystroke events into
a pseudo set of pulse/space marks, but use the standard events interface.
Cheers,
Mauro.
Mauro Carvalho Chehab <[email protected]> writes:
> Event input has the advantage that the keystrokes will provide an unique
> representation that is independent of the device.
This can hardly work as the only means, the remotes have different keys,
the user almost always has to provide customized key<>function mapping.
> Considering the common case
> where the lirc driver will be associated with a media input device, the
> IR type can be detected automatically on kernel. However, advanced users may
> opt to use other IR types than what's provided with the device they
> bought.
I think most users would want to do that, though I don't have hard
numbers of course. Why use a number of RCs simultaneously while one will
do?
> It should also be noticed that not all the already-existing IR drivers
> on kernel can provide a lirc interface, since several devices have
> their own IR decoding chips inside the hardware.
Right. I think they shouldn't use lirc interface, so it doesn't matter.
> 2) create a lirc kernel API, and have a layer there to decode IR
> protocols and output them via the already existing input layer. In
> this case, all we need to do, in terms of API, is to add a way to set
> the IR protocol that will be decoded, and to enumberate the
> capabilities. The lirc API, will be an in-kernel API to communicate
> with the devices that don't have IR protocols decoding capabilities
> inside the hardware.
I think this makes a lot of sense.
But: we don't need a database of RC codes in the kernel (that's a lot of
data, the user has to select the RC in use anyway so he/she can simply
provide mapping e.g. RC5<>keycode).
We do need RCx etc. protocols implementation in the kernel for the input
layer.
"lirc" interface: should we be sending time+on/off data to userspace, or
the RC5 etc. should be implemented in the kernel? There is (?) only
a handful of RC protocols, implementing them in the kernel and passing
only information such as proto+group+code+press/release etc. should be
more efficient.
Perhaps the raw RCx data could be sent over the input layer as well?
Something like the raw keyboard codes maybe?
We need to handle more than one RC at a time, of course.
> So, the basic question that should be decided is: should we create a new
> userspace API for raw IR pulse/space
I think so, doing the RCx proto handling in the kernel (but without
RCx raw code <> key mapping in this case due to multiple controllers
etc.). Though it could probably use the input layer as well(?).
> or it would be better to standardize it
> to always use the existing input layer?
I'd optionally provide a keyboard-alike input layer interface, with
mappings (proto + raw code <> key) provided by userspace program.
This should also work with multiple remotes.
Then the existing drivers (such as saa713x with GPIO+IRQ-driven IR
receiver (IR signal on/off generating IRQ)) should be converted.
I think we shouldn't at this time worry about IR transmitters.
--
Krzysztof Halasa
On Mon, Nov 23, 2009 at 9:14 AM, Krzysztof Halasa <[email protected]> wrote:
> I think this makes a lot of sense.
> But: we don't need a database of RC codes in the kernel (that's a lot of
> data, the user has to select the RC in use anyway so he/she can simply
> provide mapping e.g. RC5<>keycode).
Just bear in mind that with the current in-kernel code, users do *not
* have to manually select the RC code to use if they are using the
default remote that shipped with the product. This helps alot for
those unfamiliar with LIRC, since their product "works out of the box"
with the remote the product came with. I agree though, that the user
should be able to easily change the RC to be used if he/she decides to
use a remote other than the default.
Devin
--
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com
Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
>> Event input has the advantage that the keystrokes will provide an unique
>> representation that is independent of the device.
>
> This can hardly work as the only means, the remotes have different keys,
> the user almost always has to provide customized key<>function mapping.
Modern input drivers in the mainline kernel have a scancode-to-keycode
translation table (or equivalent) which can be overwritten by userspace.
The mechanism to do that is the EVIOCSKEYCODE ioctl.
(This is no recommendation for lirc. I have no idea whether a
pulse/space -> scancode -> keycode translation would be practical there.)
--
Stefan Richter
-=====-==--= =-== =-===
http://arcgraph.de/sr/
2009/11/23 Devin Heitmueller <[email protected]>:
> Just bear in mind that with the current in-kernel code, users do *not
> * have to manually select the RC code to use if they are using the
> default remote that shipped with the product.
This could still happen, if LIRC checks the identifiers of the
reciving device, and has a database that tells it mappings between
those devices and the remote controls that shipped with them.
However, it occours to me that the IR circumstances map pretty well to
what happens with ps/2 and serial devices now:
1: There are a variety of drivers for serio computer-side hardware,
each of which speaks the serio interface to the next-higher level.
These corrospond to the drivers for IR recievers.
2: There's a raw serio interface, for those wishing to do strange things.
3: There's also a variety of things that take data, using the kernel
serio API, and decode it into input events -- the ps2 keyboard driver,
the basic mouse driver, the advanced mice drivers. This is where the
interface falls down a little bit -- the ps2 keyboard driver is the
closest analogue to what I'm suggesting. The ps2 keyboard driver
creates scancode events, which map nicely to what the keyboard is
sending -- these are, for ex, rc5 codes. It will also produce
key-up/key-down events, if it has a keymap loaded. (This is the
difference with a ps2 keyboard -- a ps2 keyboard gets a map assigned
to it at boottime, so it works out-of-box. This isn't really possible
with an IR remote -- though perhaps rc5 is standarized enough, I don't
think other protocols neccessarly are.)
Userspace would have to load a keymap; those don't really belong in
kernel code. Of course, userspace could look at the device
identifiers to pick a reasonable default keymap if it's not configured
to load another, solving the out-of-box experince.
Why is this such a contentious point? I can understand wanting to
keep uncommon decoding algos out of the kernel, and keymaps, but at
the same time, they are currently there, in multiple drivers, and
while colesing them into a single place each makes sense, I'm not
convinced that moving them out completely makes all that much sense.
Having an explicit layer between the raw pulse/space layer and the
decoders means that usespace can hook in there, and create scancode
events, if it wishes to, but for the majority of remotes that use just
a couple of encoding schemes, the code can stay in the kernel. Of
course, devices that do the decoding in hardware would not implement
the raw interface, but simply create the scancode/keycode events.
-=- James Mastros
2009/11/23 Devin Heitmueller <[email protected]>:
> Just bear in mind that with the current in-kernel code, users do *not
> * have to manually select the RC code to use if they are using the
> default remote that shipped with the product.
This could still happen, if LIRC checks the identifiers of the
reciving device, and has a database that tells it mappings between
those devices and the remote controls that shipped with them.
However, it occours to me that the IR circumstances map pretty well to
what happens with ps/2 and serial devices now:
1: There are a variety of drivers for serio computer-side hardware,
each of which speaks the serio interface to the next-higher level.
These corrospond to the drivers for IR recievers.
2: There's a raw serio interface, for those wishing to do strange things.
3: There's also a variety of things that take data, using the kernel
serio API, and decode it into input events -- the ps2 keyboard driver,
the basic mouse driver, the advanced mice drivers. This is where the
interface falls down a little bit -- the ps2 keyboard driver is the
closest analogue to what I'm suggesting. The ps2 keyboard driver
creates scancode events, which map nicely to what the keyboard is
sending -- these are, for ex, rc5 codes. It will also produce
key-up/key-down events, if it has a keymap loaded. (This is the
difference with a ps2 keyboard -- a ps2 keyboard gets a map assigned
to it at boottime, so it works out-of-box. This isn't really possible
with an IR remote -- though perhaps rc5 is standarized enough, I don't
think other protocols neccessarly are.)
Userspace would have to load a keymap; those don't really belong in
kernel code. Of course, userspace could look at the device
identifiers to pick a reasonable default keymap if it's not configured
to load another, solving the out-of-box experince.
-=- James Mastros
On Mon, Nov 23, 2009 at 12:05 PM, James Mastros <[email protected]> wrote:
> 2009/11/23 Devin Heitmueller <[email protected]>:
>> Just bear in mind that with the current in-kernel code, users do *not
>> * have to manually select the RC code to use if they are using the
>> default remote that shipped with the product.
> This could still happen, if LIRC checks the identifiers of the
> reciving device, and has a database that tells it mappings between
> those devices and the remote controls that shipped with them.
> However, it occours to me that the IR circumstances map pretty well to
> what happens with ps/2 and serial devices now:
>
> 1: There are a variety of drivers for serio computer-side hardware,
> each of which speaks the serio interface to the next-higher level.
> These corrospond to the drivers for IR recievers.
> 2: There's a raw serio interface, for those wishing to do strange things.
> 3: There's also a variety of things that take data, using the kernel
> serio API, and decode it into input events -- the ps2 keyboard driver,
> the basic mouse driver, the advanced mice drivers. ?This is where the
> interface falls down a little bit -- the ps2 keyboard driver is the
> closest analogue to what I'm suggesting. ?The ps2 keyboard driver
> creates scancode events, which map nicely to what the keyboard is
> sending -- these are, for ex, rc5 codes. ?It will also produce
> key-up/key-down events, if it has a keymap loaded. ?(This is the
> difference with a ps2 keyboard -- a ps2 keyboard gets a map assigned
> to it at boottime, so it works out-of-box. ?This isn't really possible
> with an IR remote -- though perhaps rc5 is standarized enough, I don't
> think other protocols neccessarly are.)
>
> Userspace would have to load a keymap; those don't really belong in
> kernel code. ?Of course, userspace could look at the device
> identifiers to pick a reasonable default keymap if it's not configured
> to load another, solving the out-of-box experince.
I think perhaps before we go much further into this, we may wish to
come up with a set of use cases and expected behavior. I worry that
part of the problem here is people are thinking of how their
particular cards behave, and few people have a holistic picture of all
the possible scenarios. Whatever implementation we come up, we should
be confident that it meets the requirements of *all* the various
hardware implementations.
I will try to draft up some requirements/use cases if people think
this would be worthwhile.
Devin
--
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com
Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
>> Event input has the advantage that the keystrokes will provide an unique
>> representation that is independent of the device.
>
> This can hardly work as the only means, the remotes have different keys,
> the user almost always has to provide customized key<>function mapping.
Key mapping can be easily changed via input interface, as noticed by others.
>> Considering the common case
>> where the lirc driver will be associated with a media input device, the
>> IR type can be detected automatically on kernel. However, advanced users may
>> opt to use other IR types than what's provided with the device they
>> bought.
>
> I think most users would want to do that, though I don't have hard
> numbers of course. Why use a number of RCs simultaneously while one will
> do?
If you're building a dedicated hardware to act as a MCE, it makes sense to
use just one IR to control your TV and your hardware, but the common usage
is to add a TV board or stick to your desktop to see TV. For this,
the standard IR fits well.
>> It should also be noticed that not all the already-existing IR drivers
>> on kernel can provide a lirc interface, since several devices have
>> their own IR decoding chips inside the hardware.
>
> Right. I think they shouldn't use lirc interface, so it doesn't matter.
If you see patch 3/3, of the lirc submission series, you'll notice a driver
that has hardware decoding, but, due to lirc interface, the driver generates
pseudo pulse/space code for it to work via lirc interface.
It is very bad to have two interfaces for the same thing, because people
may do things like that.
Also, there are some cases where the same V4L driver can receive IR scancodes
directly for one board, while for others, it needs to get pulse/space decoding.
So, it makes sense to have an uniform way for doing it.
>> 2) create a lirc kernel API, and have a layer there to decode IR
>> protocols and output them via the already existing input layer. In
>> this case, all we need to do, in terms of API, is to add a way to set
>> the IR protocol that will be decoded, and to enumberate the
>> capabilities. The lirc API, will be an in-kernel API to communicate
>> with the devices that don't have IR protocols decoding capabilities
>> inside the hardware.
>
> I think this makes a lot of sense.
> But: we don't need a database of RC codes in the kernel (that's a lot of
> data, the user has to select the RC in use anyway so he/she can simply
> provide mapping e.g. RC5<>keycode).
This is an interesting discussion. We currently have lots of such tables in
kernel, but it can be a good idea to have it loaded by udev during boot time.
> We do need RCx etc. protocols implementation in the kernel for the input
> layer.
Yes. We already have this. See bttv, saa7134 and cx88 for several of such
protocol decoding.
> "lirc" interface: should we be sending time+on/off data to userspace, or
> the RC5 etc. should be implemented in the kernel? There is (?) only
> a handful of RC protocols, implementing them in the kernel and passing
> only information such as proto+group+code+press/release etc. should be
> more efficient.
>
> Perhaps the raw RCx data could be sent over the input layer as well?
> Something like the raw keyboard codes maybe?
>
> We need to handle more than one RC at a time, of course.
Are you meaning that we should do more than one RC per input event interface?
If so, why do you think we need to handle more than one IR protocol at the same time?
I think this will just make the driver more complex without need. Also, I'm
not sure if this would work well for all protocols.
>> So, the basic question that should be decided is: should we create a new
>> userspace API for raw IR pulse/space
>
> I think so, doing the RCx proto handling in the kernel (but without
> RCx raw code <> key mapping in this case due to multiple controllers
> etc.). Though it could probably use the input layer as well(?).
Since the key mapping table can be changed anytime, I don't see this as an issue.
If we are doing protocol handling in kernel, we just need to add some extensions
to the existing input event API to properly handle the IR protocol type.
> I think we shouldn't at this time worry about IR transmitters.
Agreed. We can postpone this discussion after solving the IR receivers
Cheers,
Mauro.
On Mon, Nov 23, 2009 at 03:14:56PM +0100, Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
> > Event input has the advantage that the keystrokes will provide an unique
> > representation that is independent of the device.
>
> This can hardly work as the only means, the remotes have different keys,
> the user almost always has to provide customized key<>function mapping.
>
Is it true? I would expect the remotes to have most of the keys to have
well-defined meanings (unless it is one of the programmable remotes)...
>
> Perhaps the raw RCx data could be sent over the input layer as well?
> Something like the raw keyboard codes maybe?
>
Curreently the "scan" codes in the input layer serve just to help users
to map whatever the device emits into a proper input event code so that
the rest of userspace would not have to care and would work with all
types of devices (USB, PS/2, etc).
I would not want to get to the point where the raw codes are used as a
primary data source.
> We need to handle more than one RC at a time, of course.
>
> > So, the basic question that should be decided is: should we create a new
> > userspace API for raw IR pulse/space
>
> I think so, doing the RCx proto handling in the kernel (but without
> RCx raw code <> key mapping in this case due to multiple controllers
> etc.). Though it could probably use the input layer as well(?).
>
I think if the data is used to do the primary protocol decoding then it
should be a separate interface that is processed by someone and then fed
into input subsystem (either in-kernel or through uinput).
Again, I would prefer to keep EV_KEY/KEY_* as the primary event type for
keys and buttons on all devices.
--
Dmitry
Stefan Richter wrote:
> Krzysztof Halasa wrote:
>> Mauro Carvalho Chehab <[email protected]> writes:
>>
>>> Event input has the advantage that the keystrokes will provide an unique
>>> representation that is independent of the device.
>> This can hardly work as the only means, the remotes have different keys,
>> the user almost always has to provide customized key<>function mapping.
>
> Modern input drivers in the mainline kernel have a scancode-to-keycode
> translation table (or equivalent) which can be overwritten by userspace.
> The mechanism to do that is the EVIOCSKEYCODE ioctl.
This mechanism is already used by all V4L drivers and several DVB drivers.
> (This is no recommendation for lirc. I have no idea whether a
> pulse/space -> scancode -> keycode translation would be practical there.)
pulse/space -> scancode translation is already done by several existing drivers.
For example, there are several bttv and saa7134 devices that polls (or receive
IRQ interrupts) to detect pulses (and the absense of them) in order to create
a pulse/space code. The conversion from pulse/space to scancode is done inside
the driver, with the help of some generic routines and based on the protocol
specifications.
The conversion from the scancode to a keycode is done based on in-kernel keycode
tables that can be changed from userspace with EVIOCSKEYCODE ioctl.
I can't see any technical reason why not doing the same for the lirc drivers,
except for one issue:
Those devices where the decoding is done by software can support any IR protocols.
So, it is possible to buy a device with a NEC IR, and use a RC5 IR to control it.
However, currently, there's no way to inform the kernel to use a different algorithm
to translate the kernel.
This can be solved by adding a few ioctls to enumerate the supported protocols and
to select the one(s) that will be handled by the kernel driver.
Cheers,
Mauro
James Mastros wrote:
> 2009/11/23 Devin Heitmueller <[email protected]>:
>> Just bear in mind that with the current in-kernel code, users do *not
>> * have to manually select the RC code to use if they are using the
>> default remote that shipped with the product.
> This could still happen, if LIRC checks the identifiers of the
> reciving device, and has a database that tells it mappings between
> those devices and the remote controls that shipped with them.
True, but this means that everyone with an IR will need to use lirc.
/me thinks that, whatever decided with those lirc drivers, this should be applied also to the existing V4L/DVB drivers.
IMO, it would be better to load the tables at the boot time (or at the
corresponding hotplug event, for USB devices).
> However, it occours to me that the IR circumstances map pretty well to
> what happens with ps/2 and serial devices now:
>
> 1: There are a variety of drivers for serio computer-side hardware,
> each of which speaks the serio interface to the next-higher level.
> These corrospond to the drivers for IR recievers.
> 2: There's a raw serio interface, for those wishing to do strange things.
> 3: There's also a variety of things that take data, using the kernel
> serio API, and decode it into input events -- the ps2 keyboard driver,
> the basic mouse driver, the advanced mice drivers.
Seems an interesting model.
> This is where the
> interface falls down a little bit -- the ps2 keyboard driver is the
> closest analogue to what I'm suggesting. The ps2 keyboard driver
> creates scancode events, which map nicely to what the keyboard is
> sending -- these are, for ex, rc5 codes. It will also produce
> key-up/key-down events, if it has a keymap loaded. (This is the
> difference with a ps2 keyboard -- a ps2 keyboard gets a map assigned
> to it at boottime, so it works out-of-box. This isn't really possible
> with an IR remote -- though perhaps rc5 is standarized enough, I don't
> think other protocols neccessarly are.)
Even with RC5, there are some vendors that implement it differently on his
IR (for example, using VCR and/or TV group for the keys).
> Userspace would have to load a keymap; those don't really belong in
> kernel code. Of course, userspace could look at the device
> identifiers to pick a reasonable default keymap if it's not configured
> to load another, solving the out-of-box experince.
I like this idea. We currently have hundreds of IR keymaps already in kernel.
It seems good to remove from kernel and let udev load those.
Cheers,
Mauro.
I'm a bit short on time to write up a more complete reply to anything in this thread at the moment, but a few quick notes interspersed below.
On Nov 23, 2009, at 12:29 PM, Mauro Carvalho Chehab wrote:
> Krzysztof Halasa wrote:
>> Mauro Carvalho Chehab <[email protected]> writes:
...
>>> Considering the common case
>>> where the lirc driver will be associated with a media input device, the
>>> IR type can be detected automatically on kernel. However, advanced users may
>>> opt to use other IR types than what's provided with the device they
>>> bought.
>>
>> I think most users would want to do that, though I don't have hard
>> numbers of course. Why use a number of RCs simultaneously while one will
>> do?
>
> If you're building a dedicated hardware to act as a MCE, it makes sense to
> use just one IR to control your TV and your hardware, but the common usage
> is to add a TV board or stick to your desktop to see TV. For this,
> the standard IR fits well.
The main use case that I have personal experience using IR and capture devices is with MythTV. Its not at all uncommon for a MythTV user to have a setup where the capture devices are attached to a completely different system from the system where the IR part needs to be. MythTV is client-server -- the backend server does the video capture via the capture devices, and the frontend client plays back the video, and its the frontend client that you navigate via an IR remote control. There are quite a few available IR options that are NOT tied to a video capture device at all -- the mceusb and imon drivers submitted in my patch series are actually two such beasts.
And particularly with the mceusb receivers, because they support damn near every IR protocol under the sun at any carrier frequency, using a remote other than the bundled one is quite common. Most people's set top boxes and/or televisions and/or AV receivers come with a remote capable of controlling multiple devices, and many bundled remotes are, quite frankly, utter garbage. I use a Logitech Harmony 880 universal remote myself.
>>> It should also be noticed that not all the already-existing IR drivers
>>> on kernel can provide a lirc interface, since several devices have
>>> their own IR decoding chips inside the hardware.
>>
>> Right. I think they shouldn't use lirc interface, so it doesn't matter.
>
> If you see patch 3/3, of the lirc submission series, you'll notice a driver
> that has hardware decoding, but, due to lirc interface, the driver generates
> pseudo pulse/space code for it to work via lirc interface.
Historically, this is true. But the version I submitted actually defaults to operating as a pure input layer device for all the imon devices that do onboard decoding. There are older imon devices that don't do onboard decoding, and I retained "legacy", if you will, lirc interface support in this pass of the driver for the onboard decode devices for those that want to keep things running as they always have (via a modparam).
More replyification later tonight...
--
Jarod Wilson
[email protected]
James Mastros <[email protected]> writes:
> (This is the
> difference with a ps2 keyboard -- a ps2 keyboard gets a map assigned
> to it at boottime, so it works out-of-box. This isn't really possible
> with an IR remote -- though perhaps rc5 is standarized enough, I don't
> think other protocols neccessarly are.)
Even with RC5 this isn't really possible. RC5 specifies several classes
of remotes, and with a typical HTPC scenario the sensor will pick up
more than one remote codeset - e.g. one for the display, one for TV
card, and maybe others (all those codes may be coming from a single
remote). We have no way to know in advance which one code set is for the
PC.
The only thing which we can "preconfigure" is the remote bundled with
the sensor (card etc). And even this can be incorrect. Several sensors
don't came with a remote controller.
I think the default sensor->remote assignment may only make sense in
userspace, while configuring the mapping.
Of course all the above changes when the sensors can't present the
"raw" data (IR on/off) but does all the decoding internally (and for
example can't decode all RC5 but only keys used on its remote). In such
unfortunate cases it has to go to the input layer directly.
> Userspace would have to load a keymap; those don't really belong in
> kernel code. Of course, userspace could look at the device
> identifiers to pick a reasonable default keymap if it's not configured
> to load another, solving the out-of-box experince.
Precisely.
--
Krzysztof Halasa
Mauro Carvalho Chehab <[email protected]> writes:
> True, but this means that everyone with an IR will need to use lirc.
I think that if the input layer (instead of raw code) is used, a utility
which only sets the mapping(s) would suffice. I.e. no daemon.
> /me thinks that, whatever decided with those lirc drivers, this should
> be applied also to the existing V4L/DVB drivers.
Certainly.
> IMO, it would be better to load the tables at the boot time (or at the
> corresponding hotplug event, for USB devices).
Sure (unless the "raw code" interface is in use).
Though maybe the raw code interface should be done in a simple library
instead of requiring the daemon.
--
Krzysztof Halasa
Mauro Carvalho Chehab <[email protected]> writes:
>> (This is no recommendation for lirc. I have no idea whether a
>> pulse/space -> scancode -> keycode translation would be practical
>> there.)
It would, but not exactly in the present shape.
> For example, there are several bttv and saa7134 devices that polls (or receive
> IRQ interrupts) to detect pulses (and the absense of them) in order to create
> a pulse/space code. The conversion from pulse/space to scancode is done inside
> the driver, with the help of some generic routines and based on the protocol
> specifications.
Right. There are currently several problems (I'm quite familiar with
saa713x RC5 code): the one that it barely works and is not implemented
for most such "GPIO/IRQ-driven" cards (as of 2.6.29 or so). This could
be fixed, I even have a working though quick&dirty patch. Another: the
RC5 allows for groups and codes within groups. The mapping can only use
one group, and there can only be one mapping. These design limitations
mean it's unusable in many cases.
> Those devices where the decoding is done by software can support any
> IR protocols.
Yes, and there can be multiple remote controllers, and multiple code
groups within a remote.
> This can be solved by adding a few ioctls to enumerate the supported
> protocols and to select the one(s) that will be handled by the kernel
> driver.
The driver may have to handle many protocols simultaneously. This is not
a problem from a technical POV.
--
Krzysztof Halasa
Mauro Carvalho Chehab <[email protected]> writes:
> If you see patch 3/3, of the lirc submission series, you'll notice a driver
> that has hardware decoding, but, due to lirc interface, the driver generates
> pseudo pulse/space code for it to work via lirc interface.
IOW the driver generates artificial pulse code for lircd?
I think - pure bloat. lircd can get events from input layer without
problems. Perhaps I misunderstood?
> It is very bad to have two interfaces for the same thing, because people
> may do things like that.
I think having a "raw" scan code interface + the key code "cooked" mode
is beneficial. For remotes lacking the raw interface only the latter
could be used.
> Also, there are some cases where the same V4L driver can receive IR scancodes
> directly for one board, while for others, it needs to get pulse/space
> decoding.
Sure.
> This is an interesting discussion. We currently have lots of such tables in
> kernel, but it can be a good idea to have it loaded by udev during
> boot time.
Sure.
> Are you meaning that we should do more than one RC per input event
> interface?
I think so. Why not?
For example, one of my remotes generates codes from at least two RC5
groups (in only one "mode"). Currently a remote is limited to only one
RC5 group.
I think the mapping should be: key = proto + group + raw code, while
key2 could be different_proto + different group (if any) + another code.
> If so, why do you think we need to handle more than one IR protocol at
> the same time?
Why not?
There are X-in-1 remotes on the market for years. They can "speak" many
protocols at once. One may want to have a protocol to handle DVD apps
while another for DVB etc.
And someone may want to use several different remotes, why not?
Personally I use two different remotes (both set to speak RC5 but what
if I couldn't set the protocol?). Sure, it requires a bit of hackery
(not with pulse code and lircd).
> I think this will just make the driver more complex without need.
Not much more, and there is a need.
--
Krzysztof Halasa
Jarod Wilson <[email protected]> writes:
> There are quite a few available IR options that are NOT tied to a
> video capture device at all -- the mceusb and imon drivers submitted
> in my patch series are actually two such beasts.
Precisely. This also includes the parallel and serial port receivers,
I'm under impression that they are, or at least were, the most common,
due to their extreme simplicity.
> And particularly with the mceusb receivers, because they support damn
> near every IR protocol under the sun at any carrier frequency, using a
> remote other than the bundled one is quite common. Most people's set
> top boxes and/or televisions and/or AV receivers come with a remote
> capable of controlling multiple devices, and many bundled remotes are,
> quite frankly, utter garbage.
This is precisely also my experience.
--
Krzysztof Halasa
Dmitry Torokhov <[email protected]> writes:
> Curreently the "scan" codes in the input layer serve just to help users
> to map whatever the device emits into a proper input event code so that
> the rest of userspace would not have to care and would work with all
> types of devices (USB, PS/2, etc).
>
> I would not want to get to the point where the raw codes are used as a
> primary data source.
The "key" interface is not flexible enough at present.
> Again, I would prefer to keep EV_KEY/KEY_* as the primary event type for
> keys and buttons on all devices.
Primary, I think so.
--
Krzysztof Halasa
Hi Jarod,
on 23 Nov 09 at 14:17, Jarod Wilson wrote:
>> Krzysztof Halasa wrote:
[...]
>> If you see patch 3/3, of the lirc submission series, you'll notice a driver
>> that has hardware decoding, but, due to lirc interface, the driver
>> generates pseudo pulse/space code for it to work via lirc interface.
> Historically, this is true.
No, it's not.
I think you misunderstood the code. The comment may be a bit misleading,
too.
Early iMON devices did not decode in hardware and the part of the driver
that Krzystof is referring to is translating a bit-stream of the sampled
input data into pulse/space durations.
Christoph
Czesc Krzysztof,
on 23 Nov 09 at 15:14, Krzysztof Halasa wrote:
[...]
> I think we shouldn't at this time worry about IR transmitters.
Sorry, but I have to disagree strongly.
Any interface without transmitter support would be absolutely unacceptable
for many LIRC users, including myself.
Christoph
[email protected] (Christoph Bartelmus) writes:
>> I think we shouldn't at this time worry about IR transmitters.
>
> Sorry, but I have to disagree strongly.
> Any interface without transmitter support would be absolutely unacceptable
> for many LIRC users, including myself.
I don't say don't use a transmitter.
I say the transmitter is not an input device, they are completely
independent functions. I can't see any reason to try and fit both in the
same interface - can you?
--
Krzysztof Halasa
On Mon, Nov 23, 2009 at 4:46 PM, Krzysztof Halasa <[email protected]> wrote:
> [email protected] (Christoph Bartelmus) writes:
>
>>> I think we shouldn't at this time worry about IR transmitters.
>>
>> Sorry, but I have to disagree strongly.
>> Any interface without transmitter support would be absolutely unacceptable
>> for many LIRC users, including myself.
>
> I don't say don't use a transmitter.
> I say the transmitter is not an input device, they are completely
> independent functions. I can't see any reason to try and fit both in the
> same interface - can you?
There is an argument to be made that since it may be desirable for
both IR receivers and transmitters to share the same table of remote
control definitions, it might make sense to at least *consider* how
the IR transmitter interface is going to work, even if it is decided
to not implement such a design in the first revision.
Personally, I would hate to see a situation where we find out that we
took a bad approach because nobody considered what would be required
for IR transmitters to reuse the same remote control definition data.
Devin
--
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com
I though about it a bit - my idea:
1. Receivers that can only decode their own remote controllers.
The present code (saa713x etc) can stay mostly unchanged. I'd only
verify that 7 bits (or whatever the number is) is enough for all
cases. The ioctl() should stay unchanged. That means keyboard-like
input layer interface.
2. Receivers that can be programmed to receive different codes, and/or
which simply generate IRQ on space/mark changes. They would use a new
ioctl() instead:
int set_rc_mapping_ioctl(void *data ...)
data should be:
u32 protocol1;
u32 length1;
u32 protocol2;
u32 length2;
...
u32 protocol_last;
u32 length_last;
(u32) 0.
The protocol data would follow (after all proto/length fields to avoid
alignment issues, but that's a detail of course).
For example, RC5. It uses 1 start bit (formerly 2 bits), 1 "toggle" bit,
5 address bits (group code) and 7 command bits (formerly 6 bits).
Each key would be represented by u16, or maybe by a couple of u8.
A "discard repeated" (perhaps inverted) bit should be included. Of
course, the "symbolic" key code should be included for each "scan" code.
Maybe: u8 address_and_discard_repeated_bit;
u8 command_value;
u8 symbolic_key_code;
repeated as required.
Protocol2 would follow protocol1 etc. (alignment issues). The driver
could see this info (for example, to program hardware to receive a
specific protocol) and then it should pass it to the generic
lirc_set_mapping() routine.
I'd also add separate trivial space/mark protocol, for debugging etc.
Maybe: u8 key_code_for_space;
u8 key_code_for_mark;
Maybe specifying length = 0 (meaning constant "key" codes) would be
enough? I think the "key" code should also specify some time stamp (or
pulse length).
Interface to the sensor driver:
The driver should register an IRQ called on both (preferably) edges of
the input signal. Basically it should only register IRQ and do:
irqreturn_t xxx_irq()
{
ack_irq_as_usual_etc();
if (input_signal->changed_state) /* really for us */
lirc_signal_state_change(input_signal->current_state);
}
The sensor driver would not know about the protocols etc. unless it
needs to e.g. program the hardware.
The middle layer (some sort of a library, and module) would interface to
the userspace (ioctl passed by the driver, input interface) and to the
hw driver. It would have to enable and call the required protocol
decoders (based on the keymap loaded).
--
Krzysztof Halasa
Devin Heitmueller <[email protected]> writes:
> There is an argument to be made that since it may be desirable for
> both IR receivers and transmitters to share the same table of remote
> control definitions, it might make sense to at least *consider* how
> the IR transmitter interface is going to work, even if it is decided
> to not implement such a design in the first revision.
>
> Personally, I would hate to see a situation where we find out that we
> took a bad approach because nobody considered what would be required
> for IR transmitters to reuse the same remote control definition data.
I briefly though about such possibility, but dismissed it with
assumption that we won't transmit the same codes (including "key" codes)
that we receive.
Perhaps I'm wrong.
--
Krzysztof Halasa
On Mon, Nov 23, 2009 at 5:31 PM, Krzysztof Halasa <[email protected]> wrote:
> Devin Heitmueller <[email protected]> writes:
>
>> There is an argument to be made that since it may be desirable for
>> both IR receivers and transmitters to share the same table of remote
>> control definitions, it might make sense to at least *consider* how
>> the IR transmitter interface is going to work, even if it is decided
>> to not implement such a design in the first revision.
>>
>> Personally, I would hate to see a situation where we find out that we
>> took a bad approach because nobody considered what would be required
>> for IR transmitters to reuse the same remote control definition data.
>
> I briefly though about such possibility, but dismissed it with
> assumption that we won't transmit the same codes (including "key" codes)
> that we receive.
I'm not specifically suggesting that you would want to transmit the
same codes that you receive, but you probably want the database of
remote control definitions to be shared.
For example, you might want the IR receiver to be listening for codes
using the "Universal Remote Control XYZ" profile and the IR
transmitter pretending to be "Cable Company Remote Control ABC" when
blasting IR codes to the cable box. Ideally, there would be a single
shared database of the definitions of the remote controls, regardless
of whether you are IR receiving or transmitting.
Devin
--
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com
Devin Heitmueller <[email protected]> writes:
> For example, you might want the IR receiver to be listening for codes
> using the "Universal Remote Control XYZ" profile and the IR
> transmitter pretending to be "Cable Company Remote Control ABC" when
> blasting IR codes to the cable box. Ideally, there would be a single
> shared database of the definitions of the remote controls, regardless
> of whether you are IR receiving or transmitting.
Well, with different receivers, the maps must certainly be different.
There can be single database in the userspace but the kernel must be
uploaded the relevant info only.
--
Krzysztof Halasa
On Mon, 2009-11-23 at 22:11 +0100, Christoph Bartelmus wrote:
> Czesc Krzysztof,
>
> on 23 Nov 09 at 15:14, Krzysztof Halasa wrote:
> [...]
> > I think we shouldn't at this time worry about IR transmitters.
>
> Sorry, but I have to disagree strongly.
> Any interface without transmitter support would be absolutely unacceptable
> for many LIRC users, including myself.
I agree with Christoph.
Is it that the input subsystem is better developed and seen as a
leverage point for development and thus an "easier" place to get results
earlier? If so, then one should definitely deal with transmitters early
in the design, as that is where the most unknowns lie.
With the end of analog TV, people will have STBs feeding analog only
video cards. Being able to change the channel on the STB with an IR
transmitter controlled by applications like MythTV is essential.
And on some different notes:
I generally don't understand the LIRC aversion I perceive in this thread
(maybe I just have a skewed perception). Aside for a video card's
default remote setup, the suggestions so far don't strike me as any
simpler for the end user than LIRC -- maybe I'm just used to LIRC. LIRC
already works for both transmit and receive and has existing support in
applications such as MythTV and mplayer.
I believe Jarod's intent is to have the LIRC components, that need to be
in kernel modules, moved into kernel mainline to avoid the headaches of
out of kernel driver maintenance. I'm not sure it is time well spent
for developers, or end users, to develop yet another IR receive
implementation in addition to the ones we suffer with now.
I would also note that RC-6 Mode 6A, used by most MCE remotes, was
developed by Philips, but Microsoft has some sort of licensing interest
in it and it is almost surely encumbered somwhow:
http://download.microsoft.com/download/9/8/f/98f3fe47-dfc3-4e74-92a3-088782200fe7/TWEN05007_WinHEC05.ppt
"Microsoft recommends the Microsoft-Philips IR protocol (based on RC6)
* You can become a licensee at no charge to you
[...]
* How to license RC6
* Contact RemoteMC @ microsoft.com for license agreement"
I would much rather that RC-6 be handled as much as possible in user
space than in the kernel. LIRC userspace components already handle it,
IIRC.
Regards,
Andy "LIRC Fan-Boy" Walls
On Mon, 2009-11-23 at 22:46 +0100, Krzysztof Halasa wrote:
> [email protected] (Christoph Bartelmus) writes:
>
> >> I think we shouldn't at this time worry about IR transmitters.
> >
> > Sorry, but I have to disagree strongly.
> > Any interface without transmitter support would be absolutely unacceptable
> > for many LIRC users, including myself.
>
> I don't say don't use a transmitter.
> I say the transmitter is not an input device, they are completely
> independent functions. I can't see any reason to try and fit both in the
> same interface - can you?
The underlying hardware need not be completely independent.
For example, the CX2584[0123], CX2388[578], CX23418, and CX2310[012]
chips have IR hardware that shares a common timing source, interrupt
line, interrupt status register, etc, between IR Rx and Tx. They can
also do things like loopback of Tx to Rx.
That said, an underlying hardware implementation can be split up to user
space with separate interfaces Tx and Rx. The underlying driver module
would have to manage the dependencies. I would guess that would be
easier for driver modules, if the userspace interfaces were designed
with such combined IR Tx/Rx hardware in mind.
Regards,
Andy
On 11/23/2009 04:10 PM, Christoph Bartelmus wrote:
> Hi Jarod,
>
> on 23 Nov 09 at 14:17, Jarod Wilson wrote:
>>> Krzysztof Halasa wrote:
> [...]
>>> If you see patch 3/3, of the lirc submission series, you'll notice a driver
>>> that has hardware decoding, but, due to lirc interface, the driver
>>> generates pseudo pulse/space code for it to work via lirc interface.
>
>> Historically, this is true.
>
> No, it's not.
> I think you misunderstood the code. The comment may be a bit misleading,
> too.
> Early iMON devices did not decode in hardware and the part of the driver
> that Krzystof is referring to is translating a bit-stream of the sampled
> input data into pulse/space durations.
Sorry, no, I know the newer devices don't actually send pulse/data info
out to userspace, just hex codes that correspond to key presses. What I
meant was "onboard decoding devices can operate as pure input devices or
in classic lirc mode", leaving out the details on exactly what they were
sending out to userspace. :)
--
Jarod Wilson
[email protected]
On 11/23/2009 07:58 AM, Mauro Carvalho Chehab wrote:
> Jarod Wilson wrote:
>> lirc driver for SoundGraph iMON IR receivers and displays
>>
>> Successfully tested with multiple devices with and without displays.
>>
>
>
>> +static struct usb_device_id imon_usb_id_table[] = {
>> + /* TriGem iMON (IR only) -- TG_iMON.inf */
>> + { USB_DEVICE(0x0aa8, 0x8001) },
> ...
>
> Another set of USB vendor ID's... this time, vendors weren't described. The
> same comment I did on patch 2/3 applies here... IMO, we should really try
> to create a global list of vendors/devices on kernel. Of course this is not
> a non-go issue, as it is already present on several other USB drivers.
My first thought is that a global list shared by everyone would be a
pain to manage -- which upstream tree would be the entry point for
additions? I think a global-within-lirc header would be just fine
though. Most usb lirc drivers don't have very long lists, these two
(mceusb and imon) are by far the longest ones.
>> +
>> + /*
>> + * Translate received data to pulse and space lengths.
>> + * Received data is active low, i.e. pulses are 0 and
>> + * spaces are 1.
>> + *
>> + * My original algorithm was essentially similar to
>> + * Changwoo Ryu's with the exception that he switched
>> + * the incoming bits to active high and also fed an
>> + * initial space to LIRC at the start of a new sequence
>> + * if the previous bit was a pulse.
>> + *
>> + * I've decided to adopt his algorithm.
>> + */
>> +
>
> Before digging into all code details, am I wrong or this device has the
> pulse/space decoding inside the chip?
The current generation of imon devices do onboard decoding, but the
driver supports older imon devices as well, which do NOT do onboard
decoding, and follow the code referenced by the above comment block.
> In this case, we shouldn't really be converting their IR keystroke events into
> a pseudo set of pulse/space marks, but use the standard events interface.
And that's actually the default mode for the devices that do onboard
decoding -- the key mappings are all in lirc_imon.h. A modparam can be
used to override pure input mode and instead pass the decoded hex values
out to userspace for lircd to handle.
Its entirely possible we could split this driver into two, one that is
for the older devices, and another for the newer devices that do onboard
decoding, which is a pure input mode driver (and still usable with lirc
via its devinput userspace driver). It'd be a lot of extra work at the
moment though, and I have no older devices to test with, only the newer
ones.
--
Jarod Wilson
[email protected]
On 11/23/2009 12:37 PM, Dmitry Torokhov wrote:
> On Mon, Nov 23, 2009 at 03:14:56PM +0100, Krzysztof Halasa wrote:
>> Mauro Carvalho Chehab<[email protected]> writes:
>>
>>> Event input has the advantage that the keystrokes will provide an unique
>>> representation that is independent of the device.
>>
>> This can hardly work as the only means, the remotes have different keys,
>> the user almost always has to provide customized key<>function mapping.
>>
>
> Is it true? I would expect the remotes to have most of the keys to have
> well-defined meanings (unless it is one of the programmable remotes)...
Its the cases like programmable universal remotes that really throw
things for a loop. That, and people wanting to use random remote X that
came with the amp or tv or set top box, with IR receiver Y.
...
>> We need to handle more than one RC at a time, of course.
>>
>>> So, the basic question that should be decided is: should we create a new
>>> userspace API for raw IR pulse/space
>>
>> I think so, doing the RCx proto handling in the kernel (but without
>> RCx raw code<> key mapping in this case due to multiple controllers
>> etc.). Though it could probably use the input layer as well(?).
>>
>
> I think if the data is used to do the primary protocol decoding then it
> should be a separate interface that is processed by someone and then fed
> into input subsystem (either in-kernel or through uinput).
>
> Again, I would prefer to keep EV_KEY/KEY_* as the primary event type for
> keys and buttons on all devices.
Current lircd actually inter-operates with the input subsystem quite
well for any and all supported remotes if their keys are mapped in their
respective lircd.conf file using standard input subsystem key names, and
the lirc daemon started with the --uinput param. lircd decodes the raw
IR, finds the mapping in its config, and happily passes it along to uinput.
--
Jarod Wilson
[email protected]
On Nov 23, 2009, at 7:53 PM, Andy Walls wrote:
> On Mon, 2009-11-23 at 22:11 +0100, Christoph Bartelmus wrote:
...
> I generally don't understand the LIRC aversion I perceive in this thread
> (maybe I just have a skewed perception). Aside for a video card's
> default remote setup, the suggestions so far don't strike me as any
> simpler for the end user than LIRC -- maybe I'm just used to LIRC. LIRC
> already works for both transmit and receive and has existing support in
> applications such as MythTV and mplayer.
There's one gripe I agree with, and that is that its still not plug-n-play. Something where udev auto-loads a sane default remote config for say, mceusb transceivers, and the stock mce remote Just Works would be nice, but auto-config is mostly out the window the second you involve transmitters and universal remotes anyway. But outside of that, I think objections are largely philosophical -- in a nutshell, the kernel has an input layer, remotes are input devices, and lirc doesn't conform to input layer standards. I do understand that argument, I just don't currently agree that all IR must go through the input layer before the drivers are acceptable for upstream -- especially since lircd can reinject decoded key presses into the input layer via uinput.
> I believe Jarod's intent is to have the LIRC components, that need to be
> in kernel modules, moved into kernel mainline to avoid the headaches of
> out of kernel driver maintenance. I'm not sure it is time well spent
> for developers, or end users, to develop yet another IR receive
> implementation in addition to the ones we suffer with now.
Yeah, a fairly relevant factor in all this is that, despite not being in the linux kernel source tree proper-like, the lirc drivers and lirc have been in use for many years by lots of users. The likes of Fedora, Debian, Ubuntu, SUSE, Mandriva, etc. have all been shipping lirc drivers for years now. While lirc certainly isn't perfect (its not always the easiest thing for users to set up), it has actually proven itself pretty robust and useful in the field, once set up. The bulk of breakage in lirc I've personally had to deal with has mostly come in the form of kernel interface changes, which would definitely be mitigated by not having to maintain the drivers out-of-tree any longer.
Now, I'm all for "improving" things and integrating better with the input subsystem, but what I don't really want to do is break compatibility with the existing setups on thousands (and thousands?) of MythTV boxes around the globe. The lirc userspace can be pretty nimble. If we can come up with a shiny new way that raw IR can be passed out through an input device, I'm pretty sure lirc userspace can be adapted to handle that. If a new input-layer-based transmit interface is developed, we can take advantage of that too. But there's already a very mature lirc interface for doing all of this. So why not start with adding things more or less as they exist right now and evolve the drivers into an idealized form? Getting *something* into the kernel in the first place is a huge step in that direction.
--
Jarod Wilson
[email protected]
Folks, I really want to tell everyone that doing all the mapping from
raw codes to keypresses in kernel is wrong.
This idea keeps showing up, because many users think that remotes send
some universal codes that you can just 'parse' and feed back to input
system.
Its not the case.
There are many protocols, I know that by experimenting with my universal
remote. There are many receivers, and all have different accuracy.
Most remotes aren't designed to be used with PC, thus user has to invent
mapping between buttons and actions.
Its is not possible to identify remotes accurately, many remotes send
just a 8 bit integer that specifies the 'model' thus many remotes can
share it.
Some don't send anything.
There are some weird remotes that send whole packet of data will all
kind of states.
Think about it, video capture device is also an input device, a scanner
is an input device too, sound card can work as input device too.
But we aren't doing any parsing, even we don't support deflating of many
proprietary and standard video/image encoding formats.
We let userspace do it.
Kernel job is to take the information from device and present it to
userspace using uniform format, that is kernel does 1:1 translating, but
doesn't parse the data.
Uniform format doesn't mean kernel always converts to one format, its
not like sound card always recording in 32 bit 96000 Khz format, even if
underlying device doesn't support that.
So, device that decode IR code are presented to userspace as pure input
devices. I agree that creating fake raw codes from that is bad.
But devices that send raw data pass it to lirc.
lirc is well capable to decode it, and its not hard to add
auto-detection based on existing configuration drivers, so IR devices
will work with absolutely no configuration.
All you will have to do is ensure that lirc is installed.
Then udev can even start it automatically.
Then as soon as you press a key, lirc can scan its config database, and
find a config file to use. combine that with a GUI for unknown remotes
and you get an awesome usability.
Also don't forget that there are pure userspace drivers. They won't have
access to in-kernel decoder so they will still have to parse protocols,
so will have code duplication, and will still need lirc thus.
So why to burden the kernel with protocols, etc..
Best regards,
Maxim Levitsky
On Wed, 25 Nov 2009, Maxim Levitsky wrote:
>
> Its not the case.
> There are many protocols, I know that by experimenting with my universal
> remote. There are many receivers, and all have different accuracy.
> Most remotes aren't designed to be used with PC, thus user has to invent
> mapping between buttons and actions.
> Its is not possible to identify remotes accurately, many remotes send
> just a 8 bit integer that specifies the 'model' thus many remotes can
> share it.
The signal recevied by the ir receiver contains glitches. Depending on the
receiver there can be quite a few. It is also not trivial to turn the raw
signal sent by the remote into a digital value, even if you know what to
expect. It takes digital signal processing techniques to turn the messy
sequence of inaccurate mark and space lengths into a best guess at what
digital code the remote sent.
It's like turning raw VBI data into decoded ASCII teletext from a simulated
keyboard device, all in the kernel.
> Kernel job is to take the information from device and present it to
> userspace using uniform format, that is kernel does 1:1 translating, but
> doesn't parse the data.
One thing that could be done, unless it has changed much since I wrote it
10+ years ago, is to take the mark/space protocol the ir device uses and sent
that data to lircd via the input layer. It would be less efficient, but
would avoid another kernel interface. Of course the input layer to lircd
interface would be somewhat different than other input devices, so
it's not entirely correct to say another interface is avoided.
On Tue, 2009-11-24 at 19:32 -0800, Trent Piepho wrote:
> On Wed, 25 Nov 2009, Maxim Levitsky wrote:
> >
> > Its not the case.
> > There are many protocols, I know that by experimenting with my universal
> > remote. There are many receivers, and all have different accuracy.
> > Most remotes aren't designed to be used with PC, thus user has to invent
> > mapping between buttons and actions.
> > Its is not possible to identify remotes accurately, many remotes send
> > just a 8 bit integer that specifies the 'model' thus many remotes can
> > share it.
>
> The signal recevied by the ir receiver contains glitches. Depending on the
> receiver there can be quite a few. It is also not trivial to turn the raw
> signal sent by the remote into a digital value, even if you know what to
> expect. It takes digital signal processing techniques to turn the messy
> sequence of inaccurate mark and space lengths into a best guess at what
> digital code the remote sent.
Exactly
>
> It's like turning raw VBI data into decoded ASCII teletext from a simulated
> keyboard device, all in the kernel.
You hit a nail on the head with this one.
>
> > Kernel job is to take the information from device and present it to
> > userspace using uniform format, that is kernel does 1:1 translating, but
> > doesn't parse the data.
>
> One thing that could be done, unless it has changed much since I wrote it
> 10+ years ago, is to take the mark/space protocol the ir device uses and sent
> that data to lircd via the input layer. It would be less efficient, but
> would avoid another kernel interface. Of course the input layer to lircd
> interface would be somewhat different than other input devices, so
> it's not entirely correct to say another interface is avoided.
I agree with this one, but it is very optional.
I also want to add that lirc can and does behave just like an input
device.
It sends the parsed events using uinput, so your remote appears just
like a keyboard.
It can even act like a mouse, and btw I use that feature, and it works
just fine.
So lets put lirc into the kernel finally?
Best regards,
Maxim Levitsky
Andy Walls <[email protected]> writes:
> I would also note that RC-6 Mode 6A, used by most MCE remotes, was
> developed by Philips, but Microsoft has some sort of licensing interest
> in it and it is almost surely encumbered somwhow:
I don't know about legal problems in some countries but from the
technical POV handling the protocol in the kernel is more efficient
or (/and) simpler.
--
Krzysztof Halasa
Jarod Wilson <[email protected]> writes:
> The bulk of breakage in lirc I've personally had to deal with has
> mostly come in the form of kernel interface changes, which would
> definitely be mitigated by not having to maintain the drivers
> out-of-tree any longer.
Certainly.
> Now, I'm all for "improving" things and integrating better with the
> input subsystem, but what I don't really want to do is break
> compatibility with the existing setups on thousands (and thousands?)
> of MythTV boxes around the globe. The lirc userspace can be pretty
> nimble. If we can come up with a shiny new way that raw IR can be
> passed out through an input device, I'm pretty sure lirc userspace can
> be adapted to handle that.
Lirc can already handle input layer. Since both ways require userspace
changes, why not do it the right way the first time? Most of the code
is already written.
> If a new input-layer-based transmit interface is developed, we can
> take advantage of that too. But there's already a very mature lirc
> interface for doing all of this. So why not start with adding things
> more or less as they exist right now and evolve the drivers into an
> idealized form? Getting *something* into the kernel in the first place
> is a huge step in that direction.
What I see as potentially problematic is breaking compatibility multiple
times.
--
Krzysztof Halasa
Maxim Levitsky <[email protected]> writes:
> There are many protocols,
Few of them really popular.
> There are many receivers, and all have different accuracy.
Receivers? Accuracy? What do you mean exactly?
> Most remotes aren't designed to be used with PC, thus user has to invent
> mapping between buttons and actions.
Of course. You can't change that. Being designed to be used with PC is
not relevant.
> Its is not possible to identify remotes accurately, many remotes send
> just a 8 bit integer that specifies the 'model' thus many remotes can
> share it.
I have never seen a remote that sends "model" number.
But I admit I only used few universal (including programmable) and few
simple bundled remotes.
> Some don't send anything.
How do they communicate with the receiver?
> There are some weird remotes that send whole packet of data will all
> kind of states.
Of course. This is called "encoding".
> Think about it, video capture device is also an input device, a scanner
> is an input device too, sound card can work as input device too.
But their primary function isn't passing keystrokes, is it?
> Kernel job is to take the information from device and present it to
> userspace using uniform format, that is kernel does 1:1 translating, but
> doesn't parse the data.
Why do you think so?
This is less efficient, and more complicated. And would require
incompatible changes to drivers already in the kernel. Keyword:
"regression".
> lirc is well capable to decode it, and its not hard to add
> auto-detection based on existing configuration drivers, so IR devices
> will work with absolutely no configuration.
Really? You don't know what you're talking about. Forget this idea,
there is absolutely no way to use this without prior configuration. You
can get as far as suggesting default "bundled" model, if there was
something bundled with the receiver of course.
> Then as soon as you press a key, lirc can scan its config database, and
> find a config file to use.
Forget it.
> Also don't forget that there are pure userspace drivers. They won't have
> access to in-kernel decoder so they will still have to parse protocols,
> so will have code duplication, and will still need lirc thus.
This is not a problem. BTW I have nothing against lirc. It can get
keystrokes from input layer. That's the way I use it in fact.
--
Krzysztof Halasa
Trent Piepho <[email protected]> writes:
> The signal recevied by the ir receiver contains glitches. Depending on the
> receiver there can be quite a few. It is also not trivial to turn the raw
> signal sent by the remote into a digital value, even if you know what to
> expect. It takes digital signal processing techniques to turn the messy
> sequence of inaccurate mark and space lengths into a best guess at what
> digital code the remote sent.
This is of course true. Except that most receivers do that in hardware,
the receiver/demodular chip such as TSOP1838 does it.
If you receive with a phototransistor or a photodiode feeding some sort
of ADC device (not a very smart design), sure - you have to do this
yourself.
I have never heard of such receiver, though.
> One thing that could be done, unless it has changed much since I wrote it
> 10+ years ago, is to take the mark/space protocol the ir device uses and sent
> that data to lircd via the input layer. It would be less efficient, but
> would avoid another kernel interface. Of course the input layer to lircd
> interface would be somewhat different than other input devices, so
> it's not entirely correct to say another interface is avoided.
IOW, it would be worse, wouldn't it?
--
Krzysztof Halasa
Hi,
on 25 Nov 09 at 17:53, Krzysztof Halasa wrote:
> Jarod Wilson <[email protected]> writes:
[...]
>> nimble. If we can come up with a shiny new way that raw IR can be
>> passed out through an input device, I'm pretty sure lirc userspace can
>> be adapted to handle that.
As Trent already pointed out, adding support for raw IR through an input
device would require a new interface too. You just put the label "input
device" on it. This does not make much sense for me.
> Lirc can already handle input layer. Since both ways require userspace
> changes,
I'm not sure what two ways you are talking about. With the patches posted
by Jarod, nothing has to be changed in userspace.
Everything works, no code needs to be written and tested, everybody is
happy.
We had exactly the same discussion around one year ago. I've seen no new
arguements in the current discussion and nobody came up with this shiny
new way of integrating LIRC into the input layer since last year. Maybe
it's about time to just accept that the LIRC interface is the way to go.
Can we finally get the patch integrated, please?
Christoph
[email protected] (Christoph Bartelmus) writes:
> I'm not sure what two ways you are talking about. With the patches posted
> by Jarod, nothing has to be changed in userspace.
> Everything works, no code needs to be written and tested, everybody is
> happy.
The existing drivers use input layer. Do you want part of the tree to
use existing lirc interface while the other part uses their own
in-kernel (badly broken for example) code to do precisely the same
thing?
We can have a good code for both, or we can end up with "badly broken"
media drivers and incompatible, suboptimal existing lirc interface
(though most probably much better in terms of quality, especially after
Jarod's work).
--
Krzysztof Halasa
On Nov 25, 2009, at 11:53 AM, Krzysztof Halasa wrote:
> Jarod Wilson <[email protected]> writes:
...
>> Now, I'm all for "improving" things and integrating better with the
>> input subsystem, but what I don't really want to do is break
>> compatibility with the existing setups on thousands (and thousands?)
>> of MythTV boxes around the globe. The lirc userspace can be pretty
>> nimble. If we can come up with a shiny new way that raw IR can be
>> passed out through an input device, I'm pretty sure lirc userspace can
>> be adapted to handle that.
>
> Lirc can already handle input layer. Since both ways require userspace
> changes, why not do it the right way the first time? Most of the code
> is already written.
There's obviously still some debate as to what "the right way" is. :)
And the matter of someone having the time to write the rest of the code that would be needed.
>> If a new input-layer-based transmit interface is developed, we can
>> take advantage of that too. But there's already a very mature lirc
>> interface for doing all of this. So why not start with adding things
>> more or less as they exist right now and evolve the drivers into an
>> idealized form? Getting *something* into the kernel in the first place
>> is a huge step in that direction.
>
> What I see as potentially problematic is breaking compatibility multiple
> times.
Ah, but the approach I'd take to converting to in-kernel decoding[*] would be this:
1) bring drivers in in their current state
- users keep using lirc as they always have
2) add in-kernel decoding infra that feeds input layer
3) add option to use in-kernel decoding to existing lirc drivers
- users can keep using lirc as they always have
- users can optionally try out in-kernel decoding via a modparam
4) switch the default mode from lirc decode to kernel decode for each lirc driver
- modparam can be used to continue using lirc interface instead
5) assuming users aren't coming at us with pitchforks, because things don't actually work reliably with in-kernel decoding, deprecate the lirc interface in driver
6) remove lirc interface from driver, its now a pure input device
This would all be on a per-lirc-driver basis, and if/when all decoding could be reliably done in-kernel, and/or there was a way other than the lirc interface to pass raw IR signals out to userspace, the lirc interface could be removed entirely.
And we still need to consider IR transmitters as well. Those are handled quite well through the lirc interface, and I've not seen any concrete code (or even fully fleshed out ideas) on how IR transmit could be handled in this in-kernel decoding world.
[*] assuming, of course, that it was actually agreed upon that in-kernel decoding was the right way, the only way, all others will be shot on sight. ;)
--
Jarod Wilson
[email protected]
On Nov 25, 2009, at 12:40 PM, Krzysztof Halasa wrote:
> [email protected] (Christoph Bartelmus) writes:
>
>> I'm not sure what two ways you are talking about. With the patches posted
>> by Jarod, nothing has to be changed in userspace.
>> Everything works, no code needs to be written and tested, everybody is
>> happy.
>
> The existing drivers use input layer. Do you want part of the tree to
> use existing lirc interface while the other part uses their own
> in-kernel (badly broken for example) code to do precisely the same
> thing?
Took me a minute to figure out exactly what you were talking about. You're referring to the current in-kernel decoding done on an ad-hoc basis for assorted remotes bundled with capture devices, correct?
Admittedly, unifying those and the lirc driven devices hasn't really been on my radar.
> We can have a good code for both, or we can end up with "badly broken"
> media drivers and incompatible, suboptimal existing lirc interface
> (though most probably much better in terms of quality, especially after
> Jarod's work).
Well, is there any reason most of those drivers with currently-in-kernel-but-badly-broken decoding can't be converted to use the lirc interface if its merged into the kernel? And/or, everything could converge on a new in-kernel decoding infra that wasn't badly broken. Sure, there may be two separate ways of doing essentially the same thing for a while, but meh. The lirc way works NOW for an incredibly wide variety of receivers, transmitters, IR protocols, etc.
I do concur that Just Works decoding for bundled remotes w/o having to configure anything would be nice, and one way to go about doing that certainly is via in-kernel IR decoding. But at the same time, the second you want to use something other than a bundled remote, things fall down, and having to do a bunch of setkeycode ops seems less optimal than simply dropping an appropriate lircd.conf in place.
--
Jarod Wilson
[email protected]
On Wed, Nov 25, 2009 at 1:07 PM, Jarod Wilson <[email protected]> wrote:
> Took me a minute to figure out exactly what you were talking about. You're referring to the current in-kernel decoding done on an ad-hoc basis for assorted remotes bundled with capture devices, correct?
>
> Admittedly, unifying those and the lirc driven devices hasn't really been on my radar.
This is one of the key use cases I would be very concerned with. For
many users who have bought tuner products, the bundled remotes work
"out-of-the-box", regardless of whether lircd is installed. I have no
objection so much as to saying "well, you have to install the lircd
service now", but there needs to be a way for the driver to
automatically tell lirc what the default remote control should be, to
avoid a regression in functionality. We cannot go from a mode where
it worked automatically to a mode where now inexperienced users now
have to deal with the guts of getting lircd properly configured.
If such an interface were available, I would see to it that at least
all the devices I have added RC support for will continue to work
(converting the in-kernel RC profiles to lirc RC profiles as needed
and doing the associations with the driver).
The other key thing I don't think we have given much thought to is the
fact that in many tuners, the hardware does RC decoding and just
returns NEC/RC5/RC6 codes. And in many of those cases, the hardware
has to be configured to know what format to receive. We probably need
some kernel API such that the hardware can tell lirc what formats are
supported, and another API call to tell the hardware which mode to
operate in.
This is why I think we really should put together a list of use cases,
so that we can see how any given proposal addresses those use cases.
I offered to do such, but nobody seemed really interested in this.
Devin
--
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com
On Nov 25, 2009, at 1:20 PM, Devin Heitmueller wrote:
> On Wed, Nov 25, 2009 at 1:07 PM, Jarod Wilson <[email protected]> wrote:
>> Took me a minute to figure out exactly what you were talking about. You're referring to the current in-kernel decoding done on an ad-hoc basis for assorted remotes bundled with capture devices, correct?
>>
>> Admittedly, unifying those and the lirc driven devices hasn't really been on my radar.
>
> This is one of the key use cases I would be very concerned with. For
> many users who have bought tuner products, the bundled remotes work
> "out-of-the-box", regardless of whether lircd is installed. I have no
> objection so much as to saying "well, you have to install the lircd
> service now", but there needs to be a way for the driver to
> automatically tell lirc what the default remote control should be, to
> avoid a regression in functionality. We cannot go from a mode where
> it worked automatically to a mode where now inexperienced users now
> have to deal with the guts of getting lircd properly configured.
Agreed. Auto-config of lircd for remotes bundled with receivers is definitely on the TODO list. It sorta kinda works using gnome-lirc-properties, but well, that's not an actual lirc project component, and from what I've seen, its fairly incomplete (and reproduces a device ID list within its own code, that has never been fully updated to match the list of stuff the lirc drivers actually support).
> If such an interface were available, I would see to it that at least
> all the devices I have added RC support for will continue to work
> (converting the in-kernel RC profiles to lirc RC profiles as needed
> and doing the associations with the driver).
>
> The other key thing I don't think we have given much thought to is the
> fact that in many tuners, the hardware does RC decoding and just
> returns NEC/RC5/RC6 codes. And in many of those cases, the hardware
> has to be configured to know what format to receive. We probably need
> some kernel API such that the hardware can tell lirc what formats are
> supported, and another API call to tell the hardware which mode to
> operate in.
Well, we've got a number of IOCTLs already, could extend those. (Although its been suggested elsewhere that we replace the IOCTLs with sysfs knobs). A simple sysfs attr that contains the name of the default config file for the bundled remote of a given receiver would seem simple enough to implement.
> This is why I think we really should put together a list of use cases,
> so that we can see how any given proposal addresses those use cases.
> I offered to do such, but nobody seemed really interested in this.
D'oh, sorry, I recall reading that email, but neglected to respond. Yes, I think that's useful, and would gladly contribute to the list.
--
Jarod Wilson
[email protected]
Jarod Wilson <[email protected]> writes:
> Ah, but the approach I'd take to converting to in-kernel decoding[*]
> would be this:
>
> 1) bring drivers in in their current state
> - users keep using lirc as they always have
>
> 2) add in-kernel decoding infra that feeds input layer
Well. I think the above is fine enough.
> 3) add option to use in-kernel decoding to existing lirc drivers
> - users can keep using lirc as they always have
> - users can optionally try out in-kernel decoding via a modparam
>
> 4) switch the default mode from lirc decode to kernel decode for each lirc driver
> - modparam can be used to continue using lirc interface instead
>
> 5) assuming users aren't coming at us with pitchforks, because things don't actually work reliably with in-kernel decoding, deprecate the lirc interface in driver
>
> 6) remove lirc interface from driver, its now a pure input device
But 3-6 are IMHO not useful. We don't need lirc _or_ input. We need
both at the same time: input for the general, simple case and for
consistency with receivers decoding in firmware/hardware; input for
special cases such as mapping the keys, protocols not supported by the
kernel and so on (also for in-tree media drivers where applicable).
> [*] assuming, of course, that it was actually agreed upon that
> in-kernel decoding was the right way, the only way, all others will be
> shot on sight. ;)
I think: in-kernel decoding only as the general, primary means. Not the
only one.
--
Krzysztof Halasa
Jarod Wilson <[email protected]> writes:
> Took me a minute to figure out exactly what you were talking about.
> You're referring to the current in-kernel decoding done on an ad-hoc
> basis for assorted remotes bundled with capture devices, correct?
Yes.
> Well, is there any reason most of those drivers with
> currently-in-kernel-but-badly-broken decoding can't be converted to
> use the lirc interface if its merged into the kernel?
For many of them "lirc mode" can be easily _added_.
--
Krzysztof Halasa
Devin Heitmueller <[email protected]> writes:
> The other key thing I don't think we have given much thought to is the
> fact that in many tuners, the hardware does RC decoding and just
> returns NEC/RC5/RC6 codes. And in many of those cases, the hardware
> has to be configured to know what format to receive. We probably need
> some kernel API such that the hardware can tell lirc what formats are
> supported, and another API call to tell the hardware which mode to
> operate in.
For such cases, I wouldn't bother with lirc mode. Input layer + key
mapping with ioctl (probably improved), and lircd can grab events from
input layer if needed.
--
Krzysztof Halasa
Jarod Wilson <[email protected]> writes:
> Well, we've got a number of IOCTLs already, could extend those.
> (Although its been suggested elsewhere that we replace the IOCTLs with
> sysfs knobs).
Not sure if sysfs would be fast enough.
> A simple sysfs attr that contains the name of the default config file
> for the bundled remote of a given receiver would seem simple enough to
> implement.
A model name maybe. Though there is this mapping thing which I think
need ioctl().
--
Krzysztof Halasa
On Wed, Nov 25, 2009 at 03:28:54PM +0200, Maxim Levitsky wrote:
> On Tue, 2009-11-24 at 19:32 -0800, Trent Piepho wrote:
> > On Wed, 25 Nov 2009, Maxim Levitsky wrote:
> > > Its not the case.
> > > There are many protocols, I know that by experimenting with my universal
> > > remote. There are many receivers, and all have different accuracy.
> > > Most remotes aren't designed to be used with PC, thus user has to invent
> > > mapping between buttons and actions.
> > > Its is not possible to identify remotes accurately, many remotes send
> > > just a 8 bit integer that specifies the 'model' thus many remotes can
> > > share it.
> >
> > The signal recevied by the ir receiver contains glitches. Depending on the
> > receiver there can be quite a few. It is also not trivial to turn the raw
> > signal sent by the remote into a digital value, even if you know what to
> > expect. It takes digital signal processing techniques to turn the messy
> > sequence of inaccurate mark and space lengths into a best guess at what
> > digital code the remote sent.
> Exactly
>
> >
> > It's like turning raw VBI data into decoded ASCII teletext from a simulated
> > keyboard device, all in the kernel.
> You hit a nail on the head with this one.
Absolutely. There are a number of use cases when you want access to the
space-pulse (i.e. IR) information. For debugging purposes; support for
non-standard remotes. Being able to do a precise recording of IR activity
so you can replay without parsing. One could even imagine IR being used
for completely different purposes than "key strokes", so the kernel
should not enforce this "policy".
In the past I've spent time dissecting the IR output of a strange remote,
I would hate to think this would not be possible due to mad kernel
interfaces which cater just for drooling in front of the telly with
your *new* remote.
Sean
On 11/25/09 19:20, Devin Heitmueller wrote:
> On Wed, Nov 25, 2009 at 1:07 PM, Jarod Wilson<[email protected]>
> wrote:
>> Took me a minute to figure out exactly what you were talking
>> about. You're referring to the current in-kernel decoding done on
>> an ad-hoc basis for assorted remotes bundled with capture devices,
>> correct?
>>
>> Admittedly, unifying those and the lirc driven devices hasn't
>> really been on my radar.
I think at the end of the day we'll want to have all IR drivers use the
same interface. The way the current in-kernel input layer drivers work
obviously isn't perfect too, so we *must* consider both worlds to get a
good solution for long-term ...
> This is one of the key use cases I would be very concerned with. For
> many users who have bought tuner products, the bundled remotes work
> "out-of-the-box", regardless of whether lircd is installed.
I bet this simply isn't going to change.
> I have no objection so much as to saying "well, you have to install
> the lircd service now", but there needs to be a way for the driver to
> automatically tell lirc what the default remote control should be,
> to avoid a regression in functionality.
*Requiring* lircd for the current in-kernel drivers doesn't make sense
at all. Allowing lircd being used so it can do some more advanced stuff
makes sense though.
> This is why I think we really should put together a list of use
> cases, so that we can see how any given proposal addresses those use
> cases. I offered to do such, but nobody seemed really interested in
> this.
Lets have a look at the problems the current input layer bits have
compared to lirc:
(1) ir code (say rc5) -> keycode conversion looses information.
I think this can easily be addressed by adding a IR event type to the
input layer, which could look like this:
input_event->type = EV_IR
input_event->code = IR_RC5
input_event->value = <rc5 value>
In case the 32bit value is too small we might want send two events
instead, with ->code being set to IR_<code>_1 and IR_<code>_2
Advantages:
* Applications (including lircd) can get access to the unmodified
rc5/rc6/... codes.
* All the ir-code -> keycode mapping magic can be handled by the
core input layer then. All the driver needs to do is to pass on
the information which keymap should be loaded by default (for the
bundled remote if any). The configuration can happen in userspace
(sysfs attribute + udev + small utility in tools/ir/).
* lirc drivers which get ir codes from the hardware can be converted
to pure input layer drivers without regressions. lircd is not
required any more.
(2) input layer doesn't give access to the raw samples.
Not sure how to deal with that best. Passing them through the input
layer would certainly be possible to hack up. But what would be the
point? The input layer wouldn't do any processing on them. It wouldn't
buy us much. So we might want to simply stick with todays lirc
interface for the raw samples.
Drivers which support both ir codes (be it by hardware or by in-kernel
decoding) and raw samples would register two devices then, one input
device and one lirc device. It would probably a good idea to stop
sending events to the input layer as soon as someone (most likely lircd)
opens the lirc device to avoid keystrokes showing up twice.
By default the in-kernel bits will be at work, but optionally you can
have lircd grab the raw samples and do fancy advanced decoding.
(3) input layer doesn't allow transmitting IR codes.
If we keep the lirc interface for raw samples anyway, then we can keep
it for sending too, problem solved ;) How does sending hardware work
btw? Do they all accept just raw samples? Or does some hardware also
accept ir-codes?
cheers,
Gerd
Sean Young <[email protected]> writes:
> Absolutely. There are a number of use cases when you want access to the
> space-pulse (i.e. IR) information.
I think nobody proposes otherwise (except for devices which can't pass
this info).
--
Krzysztof Halasa
Hi Gerd,
on 25 Nov 09 at 22:58, Gerd Hoffmann wrote:
[...]
> (1) ir code (say rc5) -> keycode conversion looses information.
>
> I think this can easily be addressed by adding a IR event type to the
> input layer, which could look like this:
>
> input_event->type = EV_IR
> input_event->code = IR_RC5
> input_event->value = <rc5 value>
>
> In case the 32bit value is too small we might want send two events
> instead, with ->code being set to IR_<code>_1 and IR_<code>_2
>
> Advantages:
> * Applications (including lircd) can get access to the unmodified
> rc5/rc6/... codes.
Unfortunately with most hardware decoders the code that you get is only
remotely related to the actual code sent. Most RC-5 decoders strip off
start bits. Toggle-bits are thrown away. NEC decoders usually don't pass
through the address part. Some even generate some pseudo-random code
(Irman). There is no common standard which bit is sent first, LSB or MSB.
Checksums are thrown away.
To sum it up: I don't think this information will be useful at all for
lircd or anyone else. Actually lircd does not even know anything about
actual protocols. We only distinguish between certain protocol types, like
Manchester encoded, space encoded, pulse encoded etc. Everything else like
the actual timing is fully configurable.
[...]
> If we keep the lirc interface for raw samples anyway, then we can keep
> it for sending too, problem solved ;) How does sending hardware work
> btw? Do they all accept just raw samples? Or does some hardware also
> accept ir-codes?
Usually raw samples in some form. I've never seen any device that would
accept just ir-codes. UIRT2 devices have some more advanced modes but also
accept raw samples.
Christoph
On Wed, 2009-11-25 at 23:30 +0100, Krzysztof Halasa wrote:
> Sean Young <[email protected]> writes:
>
> > Absolutely. There are a number of use cases when you want access to the
> > space-pulse (i.e. IR) information.
>
> I think nobody proposes otherwise (except for devices which can't pass
> this info).
I think we were taking about such devices.
I have no objection that devices that *do* decode the protocol, they
should be handled inside kernel.
But devices that send raw pulse/space data should be handled in lirc
that will feed the data back to the kernel via uinput.
Best regards,
Maxim Levitsky
>> (1) ir code (say rc5) -> keycode conversion looses information.
>>
>> I think this can easily be addressed by adding a IR event type to the
>> input layer, which could look like this:
>>
>> input_event->type = EV_IR
>> input_event->code = IR_RC5
>> input_event->value =<rc5 value>
>>
>> In case the 32bit value is too small we might want send two events
>> instead, with ->code being set to IR_<code>_1 and IR_<code>_2
>>
>> Advantages:
>> * Applications (including lircd) can get access to the unmodified
>> rc5/rc6/... codes.
>
> Unfortunately with most hardware decoders the code that you get is only
> remotely related to the actual code sent. Most RC-5 decoders strip off
> start bits.
I would include only the actual data bits in the payload anyway.
> Toggle-bits are thrown away. NEC decoders usually don't pass
> through the address part.
Too bad. But information which isn't provided by the hardware can't be
passed up anyway, no matter what kernel/userspace interface is used.
Gone is gone.
> There is no common standard which bit is sent first, LSB or MSB.
Input layer would have to define a bit order. And drivers which get it
the other way from the hardware have to convert. Or maybe signal the
order and the input core then will convert if needed.
> Checksums are thrown away.
Don't include them.
> To sum it up: I don't think this information will be useful at all for
> lircd or anyone else.
Why not? With RC5 remotes applications can get the device address bits
for example, which right now are simply get lost in the ir code ->
keycode conversion step.
> Actually lircd does not even know anything about
> actual protocols. We only distinguish between certain protocol types, like
> Manchester encoded, space encoded, pulse encoded etc. Everything else like
> the actual timing is fully configurable.
I know that lircd does matching instead of decoding, which allows to
handle unknown encodings. Thats why I think there will always be cases
which only lircd will be able to handle (using raw samples).
That doesn't make attempts to actually decode the IR samples a useless
exercise though ;)
cheers,
Gerd
On Wed, 2009-11-25 at 13:07 -0500, Jarod Wilson wrote:
> On Nov 25, 2009, at 12:40 PM, Krzysztof Halasa wrote:
>
> > [email protected] (Christoph Bartelmus) writes:
> >
> >> I'm not sure what two ways you are talking about. With the patches posted
> >> by Jarod, nothing has to be changed in userspace.
> >> Everything works, no code needs to be written and tested, everybody is
> >> happy.
> >
> > The existing drivers use input layer. Do you want part of the tree to
> > use existing lirc interface while the other part uses their own
> > in-kernel (badly broken for example) code to do precisely the same
> > thing?
>
> Took me a minute to figure out exactly what you were talking about. You're referring to the current in-kernel decoding done on an ad-hoc basis for assorted remotes bundled with capture devices, correct?
>
> Admittedly, unifying those and the lirc driven devices hasn't really been on my radar.
It has been on mine. I have been somewhat against the input subsystem
route for unification because it neglects transmitters and appears to
trade the userspace complexity we already have (i.e. LIRC configuration)
for another new (and hence less documented) configuration complexity for
end users.
My strategy for unification goes something like this:
1. Get lirc_dev and the needed supporting headers in the kernel. I will
concede LIRC is not perfect or beautiful, but I'll assert it is feature
complete for all the end user use cases that matter.
2. Encapsulate all the various IR controller hardware handling in
V4L-DVB into v4l_subdevice objects and provide a uniform interface to IR
hardware internally via v4l2_subdev_ir_ops. The exact nature of the IR
hardware is then mostly abstracted away: I2C bus microcontroller,
register block, GPIO line control of discretes devices, etc. can all be
accessed in a somewhat unifrom manner.
3. In conjunction with 2, common IR handling routines that exist in
various drivers already can be broken out: RC-5 protocol handling, etc.
4. Develop an internal interface so the v4l2_subdev object instance for
the IR hardware is exposed through a bridge driver's v4l2_device object.
5. Develop the needed layer between lirc_dev and the v4l2_device object
to connect things up.
That unifies all the IR cats and dogs in V4L-DVB at the low levels and
glues them in a consistent manner to something up top (i.e. lirc_dev)
that already handles Rx, Tx, protocols, keymapping, etc.
My primary desire is to encapsulate or remove the complexity we
currently have in kernel with all the ad-hoc IR hardware handling and
get it unifrom and layered.
The upper level glue to userspace doesn't have to be lirc_dev, but why
not? It's there and the end users are familiair with it. I have
set-top boxes, I need IR Tx.
> > We can have a good code for both, or we can end up with "badly broken"
> > media drivers and incompatible, suboptimal existing lirc interface
> > (though most probably much better in terms of quality, especially after
> > Jarod's work).
>
> Well, is there any reason most of those drivers with
> currently-in-kernel-but-badly-broken decoding can't be converted to
> use the lirc interface if its merged into the kernel?
I think all the V4L-DVB IR hardware can be. I have not done sufficient
research on the Serial, USB and other devices to say personally.
> And/or, everything could converge on a new in-kernel decoding infra
> that wasn't badly broken. Sure, there may be two separate ways of
> doing essentially the same thing for a while, but meh. The lirc way
> works NOW for an incredibly wide variety of receivers, transmitters,
> IR protocols, etc.
Also LIRC has had years of requirements collection and refinement of use
cases. Anything new implementation will likely end up converging to the
feature set LIRC already has implemented.
> I do concur that Just Works decoding for bundled remotes w/o having to
> configure anything would be nice, and one way to go about doing that
> certainly is via in-kernel IR decoding. But at the same time, the
> second you want to use something other than a bundled remote, things
> fall down, and having to do a bunch of setkeycode ops seems less
> optimal than simply dropping an appropriate lircd.conf in place.
>From a big picture perspective I would never see the OS kenrel as a good
place to address usability issues. It seems more logical to fix
usability issues with a decent GUI application and good documentation.
(LIRC needs a configuration GUI!). Expecting IR usability problems to
be eased by the kernel and command line utilties is - well -
optimistic.
I'll add that there are too many factors that can be permuted by the end
user and OEM -- protocols, remote layouts, button codes, PC IR Rx/Tx
hardware, and Set top boxes feeding PC video capture devices -- that
generating defaults that "Just Work" is a generally unsolvable problem.
Regards,
Andy
On Wed, 2009-11-25 at 13:20 -0500, Devin Heitmueller wrote:
> On Wed, Nov 25, 2009 at 1:07 PM, Jarod Wilson <[email protected]> wrote:
> > Took me a minute to figure out exactly what you were talking about. You're referring to the current in-kernel decoding done on an ad-hoc basis for assorted remotes bundled with capture devices, correct?
> >
> > Admittedly, unifying those and the lirc driven devices hasn't really been on my radar.
>
> This is one of the key use cases I would be very concerned with. For
> many users who have bought tuner products, the bundled remotes work
> "out-of-the-box", regardless of whether lircd is installed. I have no
> objection so much as to saying "well, you have to install the lircd
> service now", but there needs to be a way for the driver to
> automatically tell lirc what the default remote control should be, to
> avoid a regression in functionality. We cannot go from a mode where
> it worked automatically to a mode where now inexperienced users now
> have to deal with the guts of getting lircd properly configured.
>
> If such an interface were available, I would see to it that at least
> all the devices I have added RC support for will continue to work
> (converting the in-kernel RC profiles to lirc RC profiles as needed
> and doing the associations with the driver).
>
> The other key thing I don't think we have given much thought to is the
> fact that in many tuners, the hardware does RC decoding and just
> returns NEC/RC5/RC6 codes. And in many of those cases, the hardware
> has to be configured to know what format to receive. We probably need
> some kernel API such that the hardware can tell lirc what formats are
> supported, and another API call to tell the hardware which mode to
> operate in.
Please think about how we would need to augment the v4l_subdev_ir_ops:
http://linuxtv.org/hg/v4l-dvb/file/74ad936bcca2/linux/include/media/v4l2-subdev.h#l246
http://linuxtv.org/hg/v4l-dvb/file/74ad936bcca2/linux/include/media/v4l2-subdev.h#l305
http://linuxtv.org/hg/v4l-dvb/file/74ad936bcca2/linux/include/media/v4l2-subdev.h#l27
I think encapsulation of the various IR devices under V4L-DVB into
v4l_subdevices can facilitate your suggestions.
The CX23888 IR subdevice code configures itself to a single default
setup for Tx and Rx:
http://linuxtv.org/hg/v4l-dvb/file/74ad936bcca2/linux/drivers/media/video/cx23885/cx23888-ir.c#l1192
http://linuxtv.org/hg/v4l-dvb/file/74ad936bcca2/linux/drivers/media/video/cx23885/cx23888-ir.c#l1211
but there isn't a reason V4L2 IR subdevices couldn't configure to a per
"product" defaults based on information about the detected card from the
main bridge driver code.
Regards,
Andy
> This is why I think we really should put together a list of use cases,
> so that we can see how any given proposal addresses those use cases.
> I offered to do such, but nobody seemed really interested in this.
>
> Devin
Am Mittwoch, den 25.11.2009, 22:31 -0500 schrieb Andy Walls:
> On Wed, 2009-11-25 at 13:07 -0500, Jarod Wilson wrote:
> > On Nov 25, 2009, at 12:40 PM, Krzysztof Halasa wrote:
> >
> > > [email protected] (Christoph Bartelmus) writes:
> > >
> > >> I'm not sure what two ways you are talking about. With the patches posted
> > >> by Jarod, nothing has to be changed in userspace.
> > >> Everything works, no code needs to be written and tested, everybody is
> > >> happy.
> > >
> > > The existing drivers use input layer. Do you want part of the tree to
> > > use existing lirc interface while the other part uses their own
> > > in-kernel (badly broken for example) code to do precisely the same
> > > thing?
> >
> > Took me a minute to figure out exactly what you were talking about. You're referring to the current in-kernel decoding done on an ad-hoc basis for assorted remotes bundled with capture devices, correct?
> >
> > Admittedly, unifying those and the lirc driven devices hasn't really been on my radar.
>
> It has been on mine. I have been somewhat against the input subsystem
> route for unification because it neglects transmitters and appears to
> trade the userspace complexity we already have (i.e. LIRC configuration)
> for another new (and hence less documented) configuration complexity for
> end users.
>
> My strategy for unification goes something like this:
>
> 1. Get lirc_dev and the needed supporting headers in the kernel. I will
> concede LIRC is not perfect or beautiful, but I'll assert it is feature
> complete for all the end user use cases that matter.
>
> 2. Encapsulate all the various IR controller hardware handling in
> V4L-DVB into v4l_subdevice objects and provide a uniform interface to IR
> hardware internally via v4l2_subdev_ir_ops. The exact nature of the IR
> hardware is then mostly abstracted away: I2C bus microcontroller,
> register block, GPIO line control of discretes devices, etc. can all be
> accessed in a somewhat unifrom manner.
>
> 3. In conjunction with 2, common IR handling routines that exist in
> various drivers already can be broken out: RC-5 protocol handling, etc.
>
> 4. Develop an internal interface so the v4l2_subdev object instance for
> the IR hardware is exposed through a bridge driver's v4l2_device object.
>
> 5. Develop the needed layer between lirc_dev and the v4l2_device object
> to connect things up.
>
>
> That unifies all the IR cats and dogs in V4L-DVB at the low levels and
> glues them in a consistent manner to something up top (i.e. lirc_dev)
> that already handles Rx, Tx, protocols, keymapping, etc.
>
> My primary desire is to encapsulate or remove the complexity we
> currently have in kernel with all the ad-hoc IR hardware handling and
> get it unifrom and layered.
>
> The upper level glue to userspace doesn't have to be lirc_dev, but why
> not? It's there and the end users are familiair with it. I have
> set-top boxes, I need IR Tx.
>
>
>
> > > We can have a good code for both, or we can end up with "badly broken"
> > > media drivers and incompatible, suboptimal existing lirc interface
> > > (though most probably much better in terms of quality, especially after
> > > Jarod's work).
> >
> > Well, is there any reason most of those drivers with
> > currently-in-kernel-but-badly-broken decoding can't be converted to
> > use the lirc interface if its merged into the kernel?
>
> I think all the V4L-DVB IR hardware can be. I have not done sufficient
> research on the Serial, USB and other devices to say personally.
>
>
> > And/or, everything could converge on a new in-kernel decoding infra
> > that wasn't badly broken. Sure, there may be two separate ways of
> > doing essentially the same thing for a while, but meh. The lirc way
> > works NOW for an incredibly wide variety of receivers, transmitters,
> > IR protocols, etc.
>
> Also LIRC has had years of requirements collection and refinement of use
> cases. Anything new implementation will likely end up converging to the
> feature set LIRC already has implemented.
>
>
>
> > I do concur that Just Works decoding for bundled remotes w/o having to
> > configure anything would be nice, and one way to go about doing that
> > certainly is via in-kernel IR decoding. But at the same time, the
> > second you want to use something other than a bundled remote, things
> > fall down, and having to do a bunch of setkeycode ops seems less
> > optimal than simply dropping an appropriate lircd.conf in place.
>
>
> >From a big picture perspective I would never see the OS kenrel as a good
> place to address usability issues. It seems more logical to fix
> usability issues with a decent GUI application and good documentation.
> (LIRC needs a configuration GUI!). Expecting IR usability problems to
> be eased by the kernel and command line utilties is - well -
> optimistic.
>
> I'll add that there are too many factors that can be permuted by the end
> user and OEM -- protocols, remote layouts, button codes, PC IR Rx/Tx
> hardware, and Set top boxes feeding PC video capture devices -- that
> generating defaults that "Just Work" is a generally unsolvable problem.
>
>
> Regards,
> Andy
>
It has something that seemingly can be discussed endlessly.
By all good pros and cons, it takes much too long to see anything
forthcoming soon.
To remind, we had eleven 2.6.x test kernels, nothing on lirc came even
close to it, and on 2.6.6 some first sign of life again ... IIRC.
Including 2.5.x, how long is that?
By all sympathy, it was a big peace of crap for much too long, simply
ignoring the kernel development, and I don't have any tears for it
getting dropped that time.
We _need_ to live without it, that is the only reason for the IR input
layer in kernel, and not any other way round.
Gerd can of course tell better, but that is how I have it and there was
a lot of work because of such lamers not coming by in time then.
Cheers,
Hermann
On Wed, 2009-11-25 at 22:58 +0100, Gerd Hoffmann wrote:
> On 11/25/09 19:20, Devin Heitmueller wrote:
> > On Wed, Nov 25, 2009 at 1:07 PM, Jarod Wilson<[email protected]>
> > wrote:
> >> Took me a minute to figure out exactly what you were talking
> >> about. You're referring to the current in-kernel decoding done on
> >> an ad-hoc basis for assorted remotes bundled with capture devices,
> >> correct?
> >>
> >> Admittedly, unifying those and the lirc driven devices hasn't
> >> really been on my radar.
>
> I think at the end of the day we'll want to have all IR drivers use the
> same interface. The way the current in-kernel input layer drivers work
> obviously isn't perfect too, so we *must* consider both worlds to get a
> good solution for long-term ...
>
> > This is one of the key use cases I would be very concerned with. For
> > many users who have bought tuner products, the bundled remotes work
> > "out-of-the-box", regardless of whether lircd is installed.
>
> I bet this simply isn't going to change.
>
> > I have no objection so much as to saying "well, you have to install
> > the lircd service now", but there needs to be a way for the driver to
> > automatically tell lirc what the default remote control should be,
> > to avoid a regression in functionality.
>
> *Requiring* lircd for the current in-kernel drivers doesn't make sense
> at all. Allowing lircd being used so it can do some more advanced stuff
> makes sense though.
>
> > This is why I think we really should put together a list of use
> > cases, so that we can see how any given proposal addresses those use
> > cases. I offered to do such, but nobody seemed really interested in
> > this.
>
> Lets have a look at the problems the current input layer bits have
> compared to lirc:
>
>
> (1) ir code (say rc5) -> keycode conversion looses information.
>
> I think this can easily be addressed by adding a IR event type to the
> input layer, which could look like this:
>
> input_event->type = EV_IR
> input_event->code = IR_RC5
> input_event->value = <rc5 value>
>
> In case the 32bit value is too small we might want send two events
> instead, with ->code being set to IR_<code>_1 and IR_<code>_2
RC-6 Mode 6A can be up to 67 bits:
http://www.picbasic.nl/frameload_uk.htm?http://www.picbasic.nl/rc5-rc6_transceiver_uk.htm
(This page is slightly wrong, there is some data coded in the header
such as the RC-6 Mode, but I can't remeber if it's biphase or not.)
> Advantages:
> * Applications (including lircd) can get access to the unmodified
> rc5/rc6/... codes.
> * All the ir-code -> keycode mapping magic can be handled by the
> core input layer then. All the driver needs to do is to pass on
> the information which keymap should be loaded by default (for the
> bundled remote if any). The configuration can happen in userspace
> (sysfs attribute + udev + small utility in tools/ir/).
> * lirc drivers which get ir codes from the hardware can be converted
> to pure input layer drivers without regressions. lircd is not
> required any more.
>
> (2) input layer doesn't give access to the raw samples.
>
> Not sure how to deal with that best. Passing them through the input
> layer would certainly be possible to hack up. But what would be the
> point? The input layer wouldn't do any processing on them. It wouldn't
> buy us much. So we might want to simply stick with todays lirc
> interface for the raw samples.
>
> Drivers which support both ir codes (be it by hardware or by in-kernel
> decoding) and raw samples would register two devices then, one input
> device and one lirc device. It would probably a good idea to stop
> sending events to the input layer as soon as someone (most likely lircd)
> opens the lirc device to avoid keystrokes showing up twice.
>
> By default the in-kernel bits will be at work, but optionally you can
> have lircd grab the raw samples and do fancy advanced decoding.
(2a) Input layer doesn't help with raw samples:
So now what about devices that don't produce codes at all, but simply
pulse width measurements? Where's the infrastrucutre to perform low
pass filtering to get rid of glitches and to perform oversampling to
deal with pulse jitter, so that adding a new IR device isn't a pain
incurred per driver?
I was quite dismayed at how much I had to reimplement here, just for
RC-5 for the sake of the input layer and having a remote "Just Work":
http://linuxtv.org/hg/v4l-dvb/file/74ad936bcca2/linux/drivers/media/video/cx23885/cx23885-input.c
lirc does all that stuff in spades.
> (3) input layer doesn't allow transmitting IR codes.
>
> If we keep the lirc interface for raw samples anyway, then we can keep
> it for sending too, problem solved ;) How does sending hardware work
> btw? Do they all accept just raw samples? Or does some hardware also
> accept ir-codes?
The Conexant chips' integrated IR Tx hardware expects a series of pulse
widths and a flag for mark or space with each width.
I'd have to research other implementations.
Regards,
Andy
> cheers,
> Gerd
On Nov 25, 2009, at 2:27 PM, Krzysztof Halasa wrote:
> Jarod Wilson <[email protected]> writes:
>
>> Ah, but the approach I'd take to converting to in-kernel decoding[*]
>> would be this:
>>
>> 1) bring drivers in in their current state
>> - users keep using lirc as they always have
>>
>> 2) add in-kernel decoding infra that feeds input layer
>
> Well. I think the above is fine enough.
>
>> 3) add option to use in-kernel decoding to existing lirc drivers
>> - users can keep using lirc as they always have
>> - users can optionally try out in-kernel decoding via a modparam
>>
>> 4) switch the default mode from lirc decode to kernel decode for each lirc driver
>> - modparam can be used to continue using lirc interface instead
>>
>> 5) assuming users aren't coming at us with pitchforks, because things don't actually work reliably with in-kernel decoding, deprecate the lirc interface in driver
>>
>> 6) remove lirc interface from driver, its now a pure input device
>
> But 3-6 are IMHO not useful. We don't need lirc _or_ input. We need
> both at the same time: input for the general, simple case and for
> consistency with receivers decoding in firmware/hardware; input for
> special cases such as mapping the keys, protocols not supported by the
> kernel and so on (also for in-tree media drivers where applicable).
>
>> [*] assuming, of course, that it was actually agreed upon that
>> in-kernel decoding was the right way, the only way, all others will be
>> shot on sight. ;)
>
> I think: in-kernel decoding only as the general, primary means. Not the
> only one.
Okay, I read ya now. I got my wires crossed, thought you were advocating for dropping the lirc interface entirely. I think we're on the same page then. :)
--
Jarod Wilson
[email protected]
On Mon, Nov 23, 2009 at 09:51:31PM +0100, Krzysztof Halasa wrote:
> Dmitry Torokhov <[email protected]> writes:
>
> > Curreently the "scan" codes in the input layer serve just to help users
> > to map whatever the device emits into a proper input event code so that
> > the rest of userspace would not have to care and would work with all
> > types of devices (USB, PS/2, etc).
> >
> > I would not want to get to the point where the raw codes are used as a
> > primary data source.
>
> The "key" interface is not flexible enough at present.
>
In what way the key interface is unsufficient for delivering button
events?
--
Dmitry
On Mon, Nov 23, 2009 at 11:37:53PM -0500, Jarod Wilson wrote:
> On 11/23/2009 12:37 PM, Dmitry Torokhov wrote:
>> On Mon, Nov 23, 2009 at 03:14:56PM +0100, Krzysztof Halasa wrote:
>>> Mauro Carvalho Chehab<[email protected]> writes:
>>>
>>>> Event input has the advantage that the keystrokes will provide an unique
>>>> representation that is independent of the device.
>>>
>>> This can hardly work as the only means, the remotes have different keys,
>>> the user almost always has to provide customized key<>function mapping.
>>>
>>
>> Is it true? I would expect the remotes to have most of the keys to have
>> well-defined meanings (unless it is one of the programmable remotes)...
>
> Its the cases like programmable universal remotes that really throw
> things for a loop. That, and people wanting to use random remote X that
> came with the amp or tv or set top box, with IR receiver Y.
Right, but still the keys usually do have the well-defined meaning, teh
issue is in mapping raw code to the appropriate keycode. This can be
done either by lirc config file (when lirc is used) or by some other
means.
> ...
>>> We need to handle more than one RC at a time, of course.
>>>
>>>> So, the basic question that should be decided is: should we create a new
>>>> userspace API for raw IR pulse/space
>>>
>>> I think so, doing the RCx proto handling in the kernel (but without
>>> RCx raw code<> key mapping in this case due to multiple controllers
>>> etc.). Though it could probably use the input layer as well(?).
>>>
>>
>> I think if the data is used to do the primary protocol decoding then it
>> should be a separate interface that is processed by someone and then fed
>> into input subsystem (either in-kernel or through uinput).
>>
>> Again, I would prefer to keep EV_KEY/KEY_* as the primary event type for
>> keys and buttons on all devices.
>
> Current lircd actually inter-operates with the input subsystem quite
> well for any and all supported remotes if their keys are mapped in their
> respective lircd.conf file using standard input subsystem key names, and
> the lirc daemon started with the --uinput param. lircd decodes the raw
> IR, finds the mapping in its config, and happily passes it along to
> uinput.
Right.
I guess the question is what is the interface we want the regular
userspace (i.e. not lircd) to use. Right now programs has to use 2
intercfaces - one lirc for dealing with remotes that are not using
the standard event interface and evdev for remotes using it as well
as the rest of the input devices.
--
Dmitry
On Wed, Nov 25, 2009 at 01:32:51AM +0200, Maxim Levitsky wrote:
> Folks, I really want to tell everyone that doing all the mapping from
> raw codes to keypresses in kernel is wrong.
Why is this wrong? Doing simple translation is easy and it does not
require having all the tables for all possible remotes in the kernel. We
have appropriate interfaces to load keymaps at runtime (for the devices
whose drivers support this feature).
> This idea keeps showing up, because many users think that remotes send
> some universal codes that you can just 'parse' and feed back to input
> system.
>
Well, they send some data that can be parsed and thus fed to whatever we
want to feed it.
> Its not the case.
> There are many protocols, I know that by experimenting with my universal
> remote. There are many receivers, and all have different accuracy.
> Most remotes aren't designed to be used with PC, thus user has to invent
> mapping between buttons and actions.
> Its is not possible to identify remotes accurately, many remotes send
> just a 8 bit integer that specifies the 'model' thus many remotes can
> share it.
> Some don't send anything.
>
> There are some weird remotes that send whole packet of data will all
> kind of states.
>
> Think about it, video capture device is also an input device, a scanner
> is an input device too, sound card can work as input device too.
You are stretching. There are no button presses involved with sound (not
unless you go all the way down to keys on a piano ;) )
> But we aren't doing any parsing, even we don't support deflating of many
> proprietary and standard video/image encoding formats.
> We let userspace do it.
>
> Kernel job is to take the information from device and present it to
> userspace using uniform format, that is kernel does 1:1 translating, but
> doesn't parse the data.
Should we return to the times where we had raw PS/2 data streams sent to
userspace, separately from HID and other formats? I don't think it is a
good idea.
> Uniform format doesn't mean kernel always converts to one format, its
> not like sound card always recording in 32 bit 96000 Khz format, even if
> underlying device doesn't support that.
>
>
> So, device that decode IR code are presented to userspace as pure input
> devices. I agree that creating fake raw codes from that is bad.
>
> But devices that send raw data pass it to lirc.
> lirc is well capable to decode it, and its not hard to add
> auto-detection based on existing configuration drivers, so IR devices
> will work with absolutely no configuration.
> All you will have to do is ensure that lirc is installed.
> Then udev can even start it automatically.
> Then as soon as you press a key, lirc can scan its config database, and
> find a config file to use. combine that with a GUI for unknown remotes
> and you get an awesome usability.
>
Why can't the same be done in kernalspace though?
> Also don't forget that there are pure userspace drivers. They won't have
> access to in-kernel decoder so they will still have to parse protocols,
> so will have code duplication, and will still need lirc thus.
>
>
> So why to burden the kernel with protocols, etc..
We do burden it with TCP, shall we take it out?
--
Dmitry
On Nov 25, 2009, at 10:31 PM, Andy Walls wrote:
> On Wed, 2009-11-25 at 13:07 -0500, Jarod Wilson wrote:
>> On Nov 25, 2009, at 12:40 PM, Krzysztof Halasa wrote:
>>
>>> [email protected] (Christoph Bartelmus) writes:
>>>
>>>> I'm not sure what two ways you are talking about. With the patches posted
>>>> by Jarod, nothing has to be changed in userspace.
>>>> Everything works, no code needs to be written and tested, everybody is
>>>> happy.
>>>
>>> The existing drivers use input layer. Do you want part of the tree to
>>> use existing lirc interface while the other part uses their own
>>> in-kernel (badly broken for example) code to do precisely the same
>>> thing?
>>
>> Took me a minute to figure out exactly what you were talking about. You're referring to the current in-kernel decoding done on an ad-hoc basis for assorted remotes bundled with capture devices, correct?
>>
>> Admittedly, unifying those and the lirc driven devices hasn't really been on my radar.
>
> It has been on mine. I have been somewhat against the input subsystem
> route for unification because it neglects transmitters and appears to
> trade the userspace complexity we already have (i.e. LIRC configuration)
> for another new (and hence less documented) configuration complexity for
> end users.
>
> My strategy for unification goes something like this:
>
> 1. Get lirc_dev and the needed supporting headers in the kernel. I will
> concede LIRC is not perfect or beautiful, but I'll assert it is feature
> complete for all the end user use cases that matter.
So... What I'd like to propose is that I address Mauro's review comments for my v2 patchset, and resubmit a v3 patchset. If there are no show-stoppers, lets get the thing merged. If people don't want to use it, they don't have to, I won't be offended. But it seems there are quite a few people that would be incredibly happy to see this finally get in. There are definitely worse things that could be merged. :)
And from what I've been able to surmise, the input layer would need so much new functionality to handle both raw IR output and IR transmit, that we'd simply be reinventing a hefty chunk of the lirc device interface under the guise of being an input device, to be used *only* by things that can already simply use the existing feature-complete lirc device interface, which seems... wasteful.
> 2. Encapsulate all the various IR controller hardware handling in
> V4L-DVB into v4l_subdevice objects and provide a uniform interface to IR
> hardware internally via v4l2_subdev_ir_ops. The exact nature of the IR
> hardware is then mostly abstracted away: I2C bus microcontroller,
> register block, GPIO line control of discretes devices, etc. can all be
> accessed in a somewhat unifrom manner.
>
> 3. In conjunction with 2, common IR handling routines that exist in
> various drivers already can be broken out: RC-5 protocol handling, etc.
Once 1 happens, I'd be happy to work on adding code to currently pure lirc device drivers (like lirc_mceusb) to do in-kernel decoding for their bundled remotes. The vague plan in my head (shamelessly heisted from someone else in this thread, can't remember who atm) involves each lirc device registering two devices, one input device and one lirc device. Out of the box, without lircd, they would operate as a pure input device with their bundled remote -- out-of-the-box bliss. Once lircd opened the device's lirc device, we'd stop sending input data, and feed data out via the lirc interface.
This hybrid approach gives those who want nothing to do with lircd and the lirc device interface what they want (hell, drivers might even be buildable w/o the lirc portion even enabled), and those that want more flexibility can use either/or.
> 4. Develop an internal interface so the v4l2_subdev object instance for
> the IR hardware is exposed through a bridge driver's v4l2_device object.
>
> 5. Develop the needed layer between lirc_dev and the v4l2_device object
> to connect things up.
>
>
> That unifies all the IR cats and dogs in V4L-DVB at the low levels and
> glues them in a consistent manner to something up top (i.e. lirc_dev)
> that already handles Rx, Tx, protocols, keymapping, etc.
>
> My primary desire is to encapsulate or remove the complexity we
> currently have in kernel with all the ad-hoc IR hardware handling and
> get it unifrom and layered.
>
> The upper level glue to userspace doesn't have to be lirc_dev, but why
> not? It's there and the end users are familiair with it. I have
> set-top boxes, I need IR Tx.
Yup, me too. :)
>>> We can have a good code for both, or we can end up with "badly broken"
>>> media drivers and incompatible, suboptimal existing lirc interface
>>> (though most probably much better in terms of quality, especially after
>>> Jarod's work).
>>
>> Well, is there any reason most of those drivers with
>> currently-in-kernel-but-badly-broken decoding can't be converted to
>> use the lirc interface if its merged into the kernel?
>
> I think all the V4L-DVB IR hardware can be. I have not done sufficient
> research on the Serial, USB and other devices to say personally.
Which serial and/or usb devices other than those already supported by lirc drivers did you have in mind? Damn near all the serial and usb IR devices I know of are already supported by either another lirc kernel driver I have laying in wait, or by a userspace driver (typically interfacing w/a usb receiver using libusb).
>> And/or, everything could converge on a new in-kernel decoding infra
>> that wasn't badly broken. Sure, there may be two separate ways of
>> doing essentially the same thing for a while, but meh. The lirc way
>> works NOW for an incredibly wide variety of receivers, transmitters,
>> IR protocols, etc.
>
> Also LIRC has had years of requirements collection and refinement of use
> cases. Anything new implementation will likely end up converging to the
> feature set LIRC already has implemented.
Yep, I suspect as much myself. The only major feature I'm aware of that lirc hasn't already implemented is zero-config, works-out-of-the-box, really.
>> I do concur that Just Works decoding for bundled remotes w/o having to
>> configure anything would be nice, and one way to go about doing that
>> certainly is via in-kernel IR decoding. But at the same time, the
>> second you want to use something other than a bundled remote, things
>> fall down, and having to do a bunch of setkeycode ops seems less
>> optimal than simply dropping an appropriate lircd.conf in place.
>
>
>> From a big picture perspective I would never see the OS kenrel as a good
> place to address usability issues. It seems more logical to fix
> usability issues with a decent GUI application and good documentation.
> (LIRC needs a configuration GUI!).
gnome-lirc-properties attempts to be that, but needs a lot more love, and isn't actually part of the lirc userspace source, its maintained by some gnome folks on freedesktop.org, iirc...
> Expecting IR usability problems to
> be eased by the kernel and command line utilties is - well -
> optimistic.
>
> I'll add that there are too many factors that can be permuted by the end
> user and OEM -- protocols, remote layouts, button codes, PC IR Rx/Tx
> hardware, and Set top boxes feeding PC video capture devices -- that
> generating defaults that "Just Work" is a generally unsolvable problem.
Agreed. *Especially* with IR TX in the mix, which a LOT of DVR users rely heavily upon -- we have no way of divining what the hell IR codes a random set top box needs. And the bulk of bundled remotes we can make Just Work are flimsy, crappy, cheap plastic pieces of junk. No self-respecting HTPC user actually uses any of those things. ;)
--
Jarod Wilson
[email protected]
On Tue, Nov 24, 2009 at 07:32:42PM -0800, Trent Piepho wrote:
>
> One thing that could be done, unless it has changed much since I wrote it
> 10+ years ago, is to take the mark/space protocol the ir device uses and sent
> that data to lircd via the input layer. It would be less efficient, but
> would avoid another kernel interface. Of course the input layer to lircd
> interface would be somewhat different than other input devices, so
> it's not entirely correct to say another interface is avoided.
No, it would still be completely new interface that just happened to use
input layer as transport. An ordinary program that would just want to
react to play. pause, forward, etc buttons would have no idea what to do
with the data so you'd still need a very specialized library to deal
with the data.
--
Dmitry
On Mon, Nov 23, 2009 at 07:53:57PM -0500, Andy Walls wrote:
> On Mon, 2009-11-23 at 22:11 +0100, Christoph Bartelmus wrote:
> > Czesc Krzysztof,
> >
> > on 23 Nov 09 at 15:14, Krzysztof Halasa wrote:
> > [...]
> > > I think we shouldn't at this time worry about IR transmitters.
> >
> > Sorry, but I have to disagree strongly.
> > Any interface without transmitter support would be absolutely unacceptable
> > for many LIRC users, including myself.
>
> I agree with Christoph.
>
> Is it that the input subsystem is better developed and seen as a
> leverage point for development and thus an "easier" place to get results
> earlier? If so, then one should definitely deal with transmitters early
> in the design, as that is where the most unknowns lie.
>
> With the end of analog TV, people will have STBs feeding analog only
> video cards. Being able to change the channel on the STB with an IR
> transmitter controlled by applications like MythTV is essential.
>
>
> And on some different notes:
>
> I generally don't understand the LIRC aversion I perceive in this thread
> (maybe I just have a skewed perception). Aside for a video card's
> default remote setup, the suggestions so far don't strike me as any
> simpler for the end user than LIRC -- maybe I'm just used to LIRC. LIRC
> already works for both transmit and receive and has existing support in
> applications such as MythTV and mplayer.
Is it that LIRC supports MythTV and mplayer or MythTV and mplayer are
forced to support lirc because the remores are not available through
other means? I believe it is the latter and applications writers would
be happy to reduce number of ways they get button data.
I don't think there is LIRC aversion per se. We are just trying to
decide whether multiple interfaces for the same data is needed. And
I don't think that we will completely reject userspace components. Just
as input subsystem allows for userspace drivers I do not think why we
can't have the same for the LIRC. But I do think that the primary
interface for regular userspace consumers (read mplayer and MythTV and
the likes) should be input event interface (EV_KEY/KEY_*).
--
Dmitry
On Wed, Nov 25, 2009 at 09:49:28PM +0100, Krzysztof Halasa wrote:
> Jarod Wilson <[email protected]> writes:
>
> > Well, we've got a number of IOCTLs already, could extend those.
> > (Although its been suggested elsewhere that we replace the IOCTLs with
> > sysfs knobs).
>
> Not sure if sysfs would be fast enough.
>
Why would sysfs write be slower than ioctl?
--
Dmitry
On Nov 26, 2009, at 12:31 AM, Dmitry Torokhov wrote:
> On Mon, Nov 23, 2009 at 11:37:53PM -0500, Jarod Wilson wrote:
>> On 11/23/2009 12:37 PM, Dmitry Torokhov wrote:
>>> On Mon, Nov 23, 2009 at 03:14:56PM +0100, Krzysztof Halasa wrote:
>>>> Mauro Carvalho Chehab<[email protected]> writes:
>>>>
>>>>> Event input has the advantage that the keystrokes will provide an unique
>>>>> representation that is independent of the device.
>>>>
>>>> This can hardly work as the only means, the remotes have different keys,
>>>> the user almost always has to provide customized key<>function mapping.
>>>>
>>>
>>> Is it true? I would expect the remotes to have most of the keys to have
>>> well-defined meanings (unless it is one of the programmable remotes)...
>>
>> Its the cases like programmable universal remotes that really throw
>> things for a loop. That, and people wanting to use random remote X that
>> came with the amp or tv or set top box, with IR receiver Y.
>
> Right, but still the keys usually do have the well-defined meaning,
Except when they don't. I have two very similar remotes, one that was bundled with a system from CaptiveWorks, and one that was bundled with an Antec Veris IR/LCD (SoundGraph iMON rebrand). Outside of the Antec remote having a mouse pad instead of up/down/left/right/enter, they have an identical layout, and the keys in the same locations on the remotes send the same IR signal. But the button names vary a LOT between the two. So on the DVD key on the Antec and the MUTE key on the CW send the same signal. Same with Audio vs. Eject, TV vs. History, etc. Moral of the story is that not all IR protocols spell things out particularly well for what a given code should actually mean.
> teh
> issue is in mapping raw code to the appropriate keycode. This can be
> done either by lirc config file (when lirc is used) or by some other
> means.
The desire to map a button press to multiple keystrokes isn't uncommon either, though I presume that's doable within the input layer context too.
>> ...
>>>> We need to handle more than one RC at a time, of course.
>>>>
>>>>> So, the basic question that should be decided is: should we create a new
>>>>> userspace API for raw IR pulse/space
>>>>
>>>> I think so, doing the RCx proto handling in the kernel (but without
>>>> RCx raw code<> key mapping in this case due to multiple controllers
>>>> etc.). Though it could probably use the input layer as well(?).
>>>>
>>>
>>> I think if the data is used to do the primary protocol decoding then it
>>> should be a separate interface that is processed by someone and then fed
>>> into input subsystem (either in-kernel or through uinput).
>>>
>>> Again, I would prefer to keep EV_KEY/KEY_* as the primary event type for
>>> keys and buttons on all devices.
>>
>> Current lircd actually inter-operates with the input subsystem quite
>> well for any and all supported remotes if their keys are mapped in their
>> respective lircd.conf file using standard input subsystem key names, and
>> the lirc daemon started with the --uinput param. lircd decodes the raw
>> IR, finds the mapping in its config, and happily passes it along to
>> uinput.
>
> Right.
>
> I guess the question is what is the interface we want the regular
> userspace (i.e. not lircd) to use. Right now programs has to use 2
> intercfaces - one lirc for dealing with remotes that are not using
> the standard event interface and evdev for remotes using it as well
> as the rest of the input devices.
>From the mythtv perspective, using the input layer could yield a better out-of-the-box experience -- users don't have to set up an lircrc mapping that converts key names as specified in lircd.conf into commands (key strokes, actually) that mythtv understands. For example, a button labeled "Play" in lircd.conf has to be mapped to 'p' in ~/.lircrc for mythtv to do the right thing with it. If everything came through the input layer, be that natively or via lircd's uinput reinjection, there would be no need to do that extra mapping step, mythtv would simply handle a KEY_PLAY event. So at worst, one manual mapping to do -- IR signal to standard button name in lircd.conf -- instead of two. But the lircrc approach does also allow more flexibility, in that you can only have a certain app respond to a certain key, if so desired, and remap a key to a different function (KEY_RED, KEY_GREEN, KEY_BLUE, KEY_YELLOW -- what should their default functionality be? I know some users map a pair of those to mythtv's "skip to next commflag point" and "skip to prior commflag point").
Unfortunately, mythtv currently doesn't handle KEY_PLAY, KEY_VOLUMEUP, etc., etc. at all right now, it operates purely on keys commonly found on a standard keyboard. Remedying that is on my TODO list for the next release, if I can carve out the time.
--
Jarod Wilson
[email protected]
On Nov 26, 2009, at 12:49 AM, Dmitry Torokhov wrote:
> On Mon, Nov 23, 2009 at 07:53:57PM -0500, Andy Walls wrote:
>> On Mon, 2009-11-23 at 22:11 +0100, Christoph Bartelmus wrote:
>>> Czesc Krzysztof,
>>>
>>> on 23 Nov 09 at 15:14, Krzysztof Halasa wrote:
>>> [...]
>>>> I think we shouldn't at this time worry about IR transmitters.
>>>
>>> Sorry, but I have to disagree strongly.
>>> Any interface without transmitter support would be absolutely unacceptable
>>> for many LIRC users, including myself.
>>
>> I agree with Christoph.
>>
>> Is it that the input subsystem is better developed and seen as a
>> leverage point for development and thus an "easier" place to get results
>> earlier? If so, then one should definitely deal with transmitters early
>> in the design, as that is where the most unknowns lie.
>>
>> With the end of analog TV, people will have STBs feeding analog only
>> video cards. Being able to change the channel on the STB with an IR
>> transmitter controlled by applications like MythTV is essential.
>>
>>
>> And on some different notes:
>>
>> I generally don't understand the LIRC aversion I perceive in this thread
>> (maybe I just have a skewed perception). Aside for a video card's
>> default remote setup, the suggestions so far don't strike me as any
>> simpler for the end user than LIRC -- maybe I'm just used to LIRC. LIRC
>> already works for both transmit and receive and has existing support in
>> applications such as MythTV and mplayer.
>
> Is it that LIRC supports MythTV and mplayer or MythTV and mplayer are
> forced to support lirc because the remores are not available through
> other means? I believe it is the latter and applications writers would
> be happy to reduce number of ways they get button data.
Well, when mythtv was started, I don't know that there were many input layer remotes around... lirc was definitely around though. serial receivers and transmitters, both supported by lirc_serial, were the most frequently used devices outside of plain old keyboards. The lirc support in mythtv actually relies on mapping remote button names as defined in lircd.conf to keyboard key strokes. As mentioned elsewhere in this beast of a thread, mythtv doesn't currently support things like KEY_PLAY, KEY_VOLUMEUP, KEY_CHANNELUP, etc. just yet, but I intend on fixing that...
> I don't think there is LIRC aversion per se. We are just trying to
> decide whether multiple interfaces for the same data is needed. And
> I don't think that we will completely reject userspace components. Just
> as input subsystem allows for userspace drivers I do not think why we
> can't have the same for the LIRC. But I do think that the primary
> interface for regular userspace consumers (read mplayer and MythTV and
> the likes) should be input event interface (EV_KEY/KEY_*).
Works for me.
--
Jarod Wilson
[email protected]
Hi Gerd,
on 26 Nov 09 at 00:22, Gerd Hoffmann wrote:
[...]
>> To sum it up: I don't think this information will be useful at all for
>> lircd or anyone else.
[...]
> I know that lircd does matching instead of decoding, which allows to
> handle unknown encodings. Thats why I think there will always be cases
> which only lircd will be able to handle (using raw samples).
>
> That doesn't make attempts to actually decode the IR samples a useless
> exercise though ;)
Well, in my opinion it is kind of useless. I don't see any use case or any
demand for passing this kind of information to userspace, at least in the
LIRC context.
If there's no demand, why bother?
Christoph
Hi,
on 25 Nov 09 at 12:44, Jarod Wilson wrote:
[...]
> Ah, but the approach I'd take to converting to in-kernel decoding[*] would
> be this:
[...]
> [*] assuming, of course, that it was actually agreed upon that in-kernel
> decoding was the right way, the only way, all others will be shot on sight.
I'm happy to see that the discussion is getting along.
But I'm still a bit hesitant about the in-kernel decoding. Maybe it's just
because I'm not familiar at all with input layer toolset.
1. For sure in-kernel decoding will require some assistance from userspace
to load the mapping from IR codes to keys. So, if there needs to be a tool
in userspace that does some kind of autodetection, why not have a tool
that does some autodetection and autoconfigures lircd for the current
device. Lots of code duplication in kernel saved. What's the actual
benefit of in-kernel decoding?
2. What would be the format of the key map? lircd.conf files already exist
for a lot of remote controls. Will we have a second incompatible format to
map the keys in-kernel? Where are the tools that create the key maps for
new remotes?
Maybe someone can shed some light on this.
Christoph
On Thu, Nov 26, 2009 at 09:01:00AM +0100, Christoph Bartelmus wrote:
> Hi,
>
> on 25 Nov 09 at 12:44, Jarod Wilson wrote:
> [...]
> > Ah, but the approach I'd take to converting to in-kernel decoding[*] would
> > be this:
> [...]
> > [*] assuming, of course, that it was actually agreed upon that in-kernel
> > decoding was the right way, the only way, all others will be shot on sight.
>
> I'm happy to see that the discussion is getting along.
> But I'm still a bit hesitant about the in-kernel decoding. Maybe it's just
> because I'm not familiar at all with input layer toolset.
>
> 1. For sure in-kernel decoding will require some assistance from userspace
> to load the mapping from IR codes to keys. So, if there needs to be a tool
> in userspace that does some kind of autodetection, why not have a tool
> that does some autodetection and autoconfigures lircd for the current
> device. Lots of code duplication in kernel saved. What's the actual
> benefit of in-kernel decoding?
Why are you mixing configuration and decoding? Configuration I expect
will be done with the help of userspace. Udev is probably the best
place.
>
> 2. What would be the format of the key map? lircd.conf files already exist
> for a lot of remote controls. Will we have a second incompatible format to
> map the keys in-kernel? Where are the tools that create the key maps for
> new remotes?
>
Same as the keymaps for the other input devices I'd expect.
> Maybe someone can shed some light on this.
>
> Christoph
--
Dmitry
On 11/26/09 08:28, Christoph Bartelmus wrote:
> Hi Gerd,
>
> on 26 Nov 09 at 00:22, Gerd Hoffmann wrote:
> [...]
>>> To sum it up: I don't think this information will be useful at all for
>>> lircd or anyone else.
> [...]
>> I know that lircd does matching instead of decoding, which allows to
>> handle unknown encodings. Thats why I think there will always be cases
>> which only lircd will be able to handle (using raw samples).
>>
>> That doesn't make attempts to actually decode the IR samples a useless
>> exercise though ;)
>
> Well, in my opinion it is kind of useless. I don't see any use case or any
> demand for passing this kind of information to userspace, at least in the
> LIRC context.
> If there's no demand, why bother?
There have been complains about this getting lost somewhere in this
thread, so it looks like there are people which do care.
cheers,
Gerd
On 11/26/09 07:23, Jarod Wilson wrote:
> Well, when mythtv was started, I don't know that there were many
> input layer remotes around... lirc was definitely around though.
lirc predates the input layer IR drivers by years, maybe even the input
layer itself.
The main reason for the input layer IR drivers appearing was lirc not
being mainline. A in-kernel driver (bttv in that case) which depends on
a out-of-tree subsystem for IR support was simply a pain in the ass for
both maintainer (/me back then) and users.
At least for IR hardware which allows access to the raw samples it
certainly makes sense to support lirc, additional to the current (or
improved) input layer support.
> The lirc support in mythtv actually relies on mapping remote button
> names as defined in lircd.conf to keyboard key strokes. As mentioned
> elsewhere in this beast of a thread, mythtv doesn't currently support
> things like KEY_PLAY, KEY_VOLUMEUP, KEY_CHANNELUP, etc. just yet, but
> I intend on fixing that...
lircd can handle the input layer as input as well, so you actually can
remap things via lircd even for pure input layer drivers. mythtv
handling KEY_VOLUMEUP directly would be more elegant though.
cheers,
Gerd
Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
>>> (This is no recommendation for lirc. I have no idea whether a
>>> pulse/space -> scancode -> keycode translation would be practical
>>> there.)
>
> It would, but not exactly in the present shape.
>
>> For example, there are several bttv and saa7134 devices that polls (or receive
>> IRQ interrupts) to detect pulses (and the absense of them) in order to create
>> a pulse/space code. The conversion from pulse/space to scancode is done inside
>> the driver, with the help of some generic routines and based on the protocol
>> specifications.
>
> Right. There are currently several problems (I'm quite familiar with
> saa713x RC5 code): the one that it barely works and is not implemented
> for most such "GPIO/IRQ-driven" cards (as of 2.6.29 or so). This could
> be fixed, I even have a working though quick&dirty patch. Another: the
> RC5 allows for groups and codes within groups. The mapping can only use
> one group, and there can only be one mapping. These design limitations
> mean it's unusable in many cases.
This is a current limitation, since the saa713x code converts the RC5 code into a 7bits
scancode, by applying a mask. One of the reasons for that conversion is that the two
ioctls that allows reading/changing the keycode table (EVIOCSKEYCODE and EVIOCGKEYCODE)
were implemented via a table with a fixed size of 128 entries.
We already have an implementation at the dvb-usb driver that uses a table without
such limits, where the IR scancode is completely stored there. So, you can create
any arbitrary scancode <--> keycode table there.
Technically, it is not hard to port this solution to the other drivers, but the issue
is that we don't have all those IR's to know what is the complete scancode that
each key produces. So, the hardest part is to find a way for doing it without
causing regressions, and to find a group of people that will help testing the new way.
Maybe one alternative would be to add a modprobe parameter at the converted drivers
to allow them to work with the old behavior, after their migration.
>> Those devices where the decoding is done by software can support any
>> IR protocols.
>
> Yes, and there can be multiple remote controllers, and multiple code
> groups within a remote.
>
>> This can be solved by adding a few ioctls to enumerate the supported
>> protocols and to select the one(s) that will be handled by the kernel
>> driver.
>
> The driver may have to handle many protocols simultaneously. This is not
> a problem from a technical POV.
There are 3 different situations:
1) hardware where you can support multiple protocols at the same time;
2) hardware that supports one programmable protocol;
3) hardware that support just one (or a limited set) of protocols.
In general, (1) applies only to those devices that outputs a raw pulse/space code,
where they just connect the IR sensor to a generic I/O pin and let the software
to decode the code. This is the case of most of cheapest devices. Yet, you can
find some cheap devices with low-cost micro-controllers with a dedicated firmware
on its ROM, doing (2).
The most commonly found hardware, in general have a chip to decode IR pulse/space
sequences, converting it on a scancode and implementing (3).
That's said, a raw input interface, only fits on case (1). On the other hand, the
existing input API works for all types of IR. However, we need to add the ioctls
to allow protocol selection, to better handle (1) and (3).
Cheers,
Mauro.
On Thu, 2009-11-26 at 01:23 -0500, Jarod Wilson wrote:
> On Nov 26, 2009, at 12:49 AM, Dmitry Torokhov wrote:
>
> > On Mon, Nov 23, 2009 at 07:53:57PM -0500, Andy Walls wrote:
> >> On Mon, 2009-11-23 at 22:11 +0100, Christoph Bartelmus wrote:
> >>> Czesc Krzysztof,
> >>>
> >>> on 23 Nov 09 at 15:14, Krzysztof Halasa wrote:
> >>> [...]
> >>>> I think we shouldn't at this time worry about IR transmitters.
> >>>
> >>> Sorry, but I have to disagree strongly.
> >>> Any interface without transmitter support would be absolutely unacceptable
> >>> for many LIRC users, including myself.
> >>
> >> I agree with Christoph.
> >>
> >> Is it that the input subsystem is better developed and seen as a
> >> leverage point for development and thus an "easier" place to get results
> >> earlier? If so, then one should definitely deal with transmitters early
> >> in the design, as that is where the most unknowns lie.
> >>
> >> With the end of analog TV, people will have STBs feeding analog only
> >> video cards. Being able to change the channel on the STB with an IR
> >> transmitter controlled by applications like MythTV is essential.
> >>
> >>
> >> And on some different notes:
> >>
> >> I generally don't understand the LIRC aversion I perceive in this thread
> >> (maybe I just have a skewed perception). Aside for a video card's
> >> default remote setup, the suggestions so far don't strike me as any
> >> simpler for the end user than LIRC -- maybe I'm just used to LIRC. LIRC
> >> already works for both transmit and receive and has existing support in
> >> applications such as MythTV and mplayer.
> >
> > Is it that LIRC supports MythTV and mplayer or MythTV and mplayer are
> > forced to support lirc because the remores are not available through
> > other means? I believe it is the latter and applications writers would
> > be happy to reduce number of ways they get button data.
>
> Well, when mythtv was started, I don't know that there were many input layer remotes around... lirc was definitely around though. serial receivers and transmitters, both supported by lirc_serial, were the most frequently used devices outside of plain old keyboards. The lirc support in mythtv actually relies on mapping remote button names as defined in lircd.conf to keyboard key strokes. As mentioned elsewhere in this beast of a thread, mythtv doesn't currently support things like KEY_PLAY, KEY_VOLUMEUP, KEY_CHANNELUP, etc. just yet, but I intend on fixing that...
>
> > I don't think there is LIRC aversion per se. We are just trying to
> > decide whether multiple interfaces for the same data is needed. And
> > I don't think that we will completely reject userspace components. Just
> > as input subsystem allows for userspace drivers I do not think why we
> > can't have the same for the LIRC. But I do think that the primary
> > interface for regular userspace consumers (read mplayer and MythTV and
> > the likes) should be input event interface (EV_KEY/KEY_*).
>
> Works for me.
Even though two interfaces is a bit of "extra" work, I'm not averse to
Gerd's suggestions of a dual implementation: input layer for the simple,
common use case, and lirc type interface for more sophisticated usage.
One thing I would like to be provided by the input layer is automatic
key-up after a specified time. Remote protocols send an initial button
press and then after a certain amount of time (~115 ms for RC-5) send a
repeated code or repeat sequence, if the button is still pressed.
Currently, most of the V4L-DVB drivers have some code to perform a
timeout just to send the key-up event. That's a good bit of redundant
code for key-up timeouts that I suspect makes sense for the input layer
to handle.
Regards,
Andy
Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
>> If you see patch 3/3, of the lirc submission series, you'll notice a driver
>> that has hardware decoding, but, due to lirc interface, the driver generates
>> pseudo pulse/space code for it to work via lirc interface.
>
> IOW the driver generates artificial pulse code for lircd?
> I think - pure bloat. lircd can get events from input layer without
> problems. Perhaps I misunderstood?
lircd supports input layer interface. Yet, patch 3/3 exports both devices
that support only pulse/space raw mode and devices that generate scan
codes via the raw mode interface. It does it by generating artificial
pulse codes.
>
>> It is very bad to have two interfaces for the same thing, because people
>> may do things like that.
>
> I think having a "raw" scan code interface + the key code "cooked" mode
> is beneficial. For remotes lacking the raw interface only the latter
> could be used.
It sounds an interesting idea.
>> Are you meaning that we should do more than one RC per input event
>> interface?
>
> I think so. Why not?
>
> For example, one of my remotes generates codes from at least two RC5
> groups (in only one "mode"). Currently a remote is limited to only one
> RC5 group.
Yet, both are RC5. This can already be handled by the input layer.
See dvb-usb implementation.
The issue I see is to support at the same time NEC and RC5 protocols. While
this may work with some devices, for others, the hardware won't allow.
>
> I think the mapping should be: key = proto + group + raw code, while
> key2 could be different_proto + different group (if any) + another code.
This may work for protocols up to RC5, that uses either 8 or 16 bits.
However, RC6 mode 6 codes can be 32 bits, and we have "only" 32 bits
for a scancode. So, we don't have spare bits to represent a protocol,
if we consider RC6 mode 6 codes as well.
>> If so, why do you think we need to handle more than one IR protocol at
>> the same time?
>
> Why not?
> There are X-in-1 remotes on the market for years. They can "speak" many
> protocols at once. One may want to have a protocol to handle DVD apps
> while another for DVB etc.
> And someone may want to use several different remotes, why not?
> Personally I use two different remotes (both set to speak RC5 but what
> if I couldn't set the protocol?). Sure, it requires a bit of hackery
> (not with pulse code and lircd).
>
>> I think this will just make the driver more complex without need.
>
> Not much more, and there is a need.
See above. Also, several protocols have a way to check if a keystroke were
properly received. When handling just one protocol, we can use this to double
check the key. However, on a multiprotocol mode, we'll need to disable this
feature.
PS.: For those following those discussions that want to know more about
IR protocols, a good reference is at:
http://www.sbprojects.com/knowledge/ir/ir.htm
Unfortunately, it doesn't describe RC6 mode 6.
Cheers,
Mauro.
Andy Walls wrote:
> I generally don't understand the LIRC aversion I perceive in this thread
> (maybe I just have a skewed perception).
> Regards,
> Andy "LIRC Fan-Boy" Walls
This is not a lirc love or hate thread. We're simply discussing the better
API's for IR, from the technical standpoint, considering that some users
may want to use lirc and some users may want to have their IR working
out-of-the-box.
By not using lirc, users will loose the advantages of having lircd, like clicking
on a button and calling automatically the DVD player application, but this means
that their device with the shipped IR will work without needing to do any setup.
Whatever we do, both kind of usages should be possible, since there are demand
for both.
Also, the decision should consider that the existing drivers will need to
support the new way without causing regressions.
Cheers,
Mauro.
On Thu, 2009-11-26 at 10:36 -0200, Mauro Carvalho Chehab wrote:
> Krzysztof Halasa wrote:
> > Mauro Carvalho Chehab <[email protected]> writes:
> PS.: For those following those discussions that want to know more about
> IR protocols, a good reference is at:
> http://www.sbprojects.com/knowledge/ir/ir.htm
>
> Unfortunately, it doesn't describe RC6 mode 6.
RC-6 Mode 0 and Mode 6A is briefly describe here:
http://www.picbasic.nl/frameload_uk.htm?http://www.picbasic.nl/rc5-rc6_transceiver_uk.htm
That page is slightly wrong, as there is some data coded in the header
such as the RC-6 Mode.
This page is an older version of the sbprojects.com RC-6 page, before
the information on RC-6 Mode 6A was removed:
http://slycontrol.ru/scr/kb/rc6.htm
My personal opinion is that, for non-technical reasons, RC-6 Mode 6A
decoding should not be included in the kernel. That's why I didn't do
it for the HVR-1850/CX23888.
Regards,
Andy
Andy Walls wrote:
> On Mon, 2009-11-23 at 22:46 +0100, Krzysztof Halasa wrote:
>> [email protected] (Christoph Bartelmus) writes:
>>
>>>> I think we shouldn't at this time worry about IR transmitters.
>>> Sorry, but I have to disagree strongly.
>>> Any interface without transmitter support would be absolutely unacceptable
>>> for many LIRC users, including myself.
>> I don't say don't use a transmitter.
>> I say the transmitter is not an input device, they are completely
>> independent functions. I can't see any reason to try and fit both in the
>> same interface - can you?
>
> The underlying hardware need not be completely independent.
>
> For example, the CX2584[0123], CX2388[578], CX23418, and CX2310[012]
> chips have IR hardware that shares a common timing source, interrupt
> line, interrupt status register, etc, between IR Rx and Tx. They can
> also do things like loopback of Tx to Rx.
>
> That said, an underlying hardware implementation can be split up to user
> space with separate interfaces Tx and Rx. The underlying driver module
> would have to manage the dependencies. I would guess that would be
> easier for driver modules, if the userspace interfaces were designed
> with such combined IR Tx/Rx hardware in mind.
True, but, in the case of Rx, there are already API's for it. Tx case is
simpler, as we don't have any API for it yet.
I'm not sure if all the existing hardware for TX currently supports only
raw pulse/code sequencies, but I still think that, even on the Tx case,
it is better to send scancodes to the driver, and let it do the conversion
to raw pulse/code, if the hardware requires pulse/code instead of scancodes.
However, as we have green field,
I would add the protocol explicitly for each scancode to be transmitted, like:
struct ir_tx {
enum ir_protocol proto;
u32 scancode;
};
Eventually, we might have a protocol "raw" and some extra field to allow passing
a raw pulse/code sequence instead of a scancode.
Cheers,
Mauro.
On Thu, 2009-11-26 at 11:25 -0200, Mauro Carvalho Chehab wrote:
> Andy Walls wrote:
> > On Mon, 2009-11-23 at 22:46 +0100, Krzysztof Halasa wrote:
> >> [email protected] (Christoph Bartelmus) writes:
> >>
> >>>> I think we shouldn't at this time worry about IR transmitters.
> >>> Sorry, but I have to disagree strongly.
> >>> Any interface without transmitter support would be absolutely unacceptable
> >>> for many LIRC users, including myself.
> >> I don't say don't use a transmitter.
> >> I say the transmitter is not an input device, they are completely
> >> independent functions. I can't see any reason to try and fit both in the
> >> same interface - can you?
> >
> > The underlying hardware need not be completely independent.
> >
> > For example, the CX2584[0123], CX2388[578], CX23418, and CX2310[012]
> > chips have IR hardware that shares a common timing source, interrupt
> > line, interrupt status register, etc, between IR Rx and Tx. They can
> > also do things like loopback of Tx to Rx.
> >
> > That said, an underlying hardware implementation can be split up to user
> > space with separate interfaces Tx and Rx. The underlying driver module
> > would have to manage the dependencies. I would guess that would be
> > easier for driver modules, if the userspace interfaces were designed
> > with such combined IR Tx/Rx hardware in mind.
>
> True, but, in the case of Rx, there are already API's for it. Tx case is
> simpler, as we don't have any API for it yet.
>
> I'm not sure if all the existing hardware for TX currently supports only
> raw pulse/code sequencies, but I still think that, even on the Tx case,
> it is better to send scancodes to the driver, and let it do the conversion
> to raw pulse/code, if the hardware requires pulse/code instead of scancodes.
That seems like a decision which will create a lots of duplicative code
in the kernel. Add it's just busy-work to write such code when a
userspace application in common use already handles the protocols and
sends raw pulses to hardware that expects raw pulses.
> However, as we have green field,
> I would add the protocol explicitly for each scancode to be transmitted, like:
>
> struct ir_tx {
> enum ir_protocol proto;
> u32 scancode;
> };
>
> Eventually, we might have a protocol "raw" and some extra field to allow passing
> a raw pulse/code sequence instead of a scancode.
I think you would have to. 32 bits is really not enough for all
protocols, and it is already partial encoding of information anyway.
If the Tx driver has to break them down into pulses anyway, why not have
fields with more meaningful names
mode
toggle
customer code (or system code or address),
information (or command)
According to
http://slycontrol.ru/scr/kb/rc6.htm
the "information" field could be up to 128 bits.
(Not that I'm going to put any RC-6 Mode 6A decoding/encoding in the
kernel.)
Regards,
Andy
> Cheers,
> Mauro.
Jarod Wilson wrote:
> On Nov 23, 2009, at 7:53 PM, Andy Walls wrote:
>
>> On Mon, 2009-11-23 at 22:11 +0100, Christoph Bartelmus wrote:
> ...
>> I generally don't understand the LIRC aversion I perceive in this thread
>> (maybe I just have a skewed perception). Aside for a video card's
>> default remote setup, the suggestions so far don't strike me as any
>> simpler for the end user than LIRC -- maybe I'm just used to LIRC. LIRC
>> already works for both transmit and receive and has existing support in
>> applications such as MythTV and mplayer.
>
> There's one gripe I agree with, and that is that its still not plug-n-play.
> Something where udev auto-loads a sane default remote config for say,
> mceusb transceivers, and the stock mce remote Just Works would be nice,
> but auto-config is mostly out the window the second you involve transmitters
> and universal remotes anyway.
For several devices, an udev rule that auto-loads a sane default keymap does work.
Of course, this won't cover 100% of the usages, and I lirc is a very good way
of covering the holes.
> But outside of that, I think objections are largely philosophical --
> in a nutshell, the kernel has an input layer, remotes are input devices,
> and lirc doesn't conform to input layer standards.
Yes. I think this is mainly the issue.
The other issue is how to migrate the existing drivers to a new API without
causing regressions. If we decide that IR's that receive raw pulse/code
should use the raw input interface, this means that a large task force will be
needed to convert the existing drivers to use it.
> I do understand that argument, I just don't currently agree that all IR must
> go through the input layer before the drivers are acceptable for upstream --
> especially since lircd can reinject decoded key presses into the input layer via uinput.
IMHO, there are some scenarios for an upcoming kernel IR raw input interface:
1) as a temporary solution for merging lirc drivers, knowing in advance that it will
be later converted to the standard input API;
2) as a raw interface for some weird usages, with its usage limited to just a
few device drivers;
3) as the solution for all IR's that produces pulse/code raw sequences;
For (1), while it may make sense, we'll be creating an userspace API that is
meant to be stable, knowing in advance that it will be removed in a close
future.
IMHO, we should avoid (2), since it will be hard to define what is the "limited
usage", and I bet that it will evolute to (3) in a long term.
For (3), we need to consider the migration of the existing drivers.
By discarding scenario (2), this means that, in the long term, we'll need to either
migrate all existing out-of-tree lirc drivers to the standard input API interface
(scenario 1) or to migrate the existing drivers to the raw input interface (scenario 3).
For me, scenario (1) is fine if we add the lirc drivers at drivers/staging.
>> I believe Jarod's intent is to have the LIRC components, that need to be
>> in kernel modules, moved into kernel mainline to avoid the headaches of
>> out of kernel driver maintenance. I'm not sure it is time well spent
>> for developers, or end users, to develop yet another IR receive
>> implementation in addition to the ones we suffer with now.
>
> Yeah, a fairly relevant factor in all this is that, despite not being in the linux
> kernel source tree proper-like, the lirc drivers and lirc have been in use for many
> years by lots of users. The likes of Fedora, Debian, Ubuntu, SUSE, Mandriva, etc.
> have all been shipping lirc drivers for years now. While lirc certainly isn't
> perfect (its not always the easiest thing for users to set up), it has actually
> proven itself pretty robust and useful in the field, once set up. The bulk of
> breakage in lirc I've personally had to deal with has mostly come in the
> form of kernel interface changes, which would definitely be mitigated by
> not having to maintain the drivers out-of-tree any longer.
>
> Now, I'm all for "improving" things and integrating better with the input
> subsystem, but what I don't really want to do is break compatibility with the
> existing setups on thousands (and thousands?) of MythTV boxes around the globe.
> The lirc userspace can be pretty nimble. If we can come up with a shiny new way
> that raw IR can be passed out through an input device, I'm pretty sure lirc
> userspace can be adapted to handle that. If a new input-layer-based transmit
> interface is developed, we can take advantage of that too. But there's already
> a very mature lirc interface for doing all of this. So why not start with adding
> things more or less as they exist right now and evolve the drivers into an
> idealized form? Getting *something* into the kernel in the first place is a
> huge step in that direction.
I agree. We should really move forward and add it to kernel as soon as possible,
and start to work on improving the IR support at the upstream kernel.
Jarold,
What do you think of adding lirc at staging while we discuss/improve the API's and lircd
support for the input event interface? Do you think this would work?
Cheers,
Mauro.
Krzysztof Halasa wrote:
> Andy Walls <[email protected]> writes:
>
>> I would also note that RC-6 Mode 6A, used by most MCE remotes, was
>> developed by Philips, but Microsoft has some sort of licensing interest
>> in it and it is almost surely encumbered somwhow:
>
> I don't know about legal problems in some countries but from the
> technical POV handling the protocol in the kernel is more efficient
> or (/and) simpler.
A software licensing from Microsoft won't apply to Linux kernel, so I'm
assuming that you're referring to some patent that they could be filled
about RC6 mode 6A.
I don't know if is there any US patent pending about it (AFAIK, only US
accepts software patents), but there are some prior-art for IR key
decoding. So, I don't see what "innovation" RC6 would be adding.
If it is some new way to transmit waves, the patent issues
aren't related to software, and the device manufacturer had already handled
it when they made their devices. If it is just a new keytable, this issue
could be easily solved by loading the keytable via userspace.
Also, assuming that you can use the driver only with a hardware that comes
with a licensed software, the user has already the license for using it.
Do you have any details on what patents they are claiming?
Cheers,
Mauro.
Jarod Wilson wrote:
> On Nov 25, 2009, at 12:40 PM, Krzysztof Halasa wrote:
>
>> [email protected] (Christoph Bartelmus) writes:
>>
>>> I'm not sure what two ways you are talking about. With the patches posted
>>> by Jarod, nothing has to be changed in userspace.
>>> Everything works, no code needs to be written and tested, everybody is
>>> happy.
>> The existing drivers use input layer. Do you want part of the tree to
>> use existing lirc interface while the other part uses their own
>> in-kernel (badly broken for example) code to do precisely the same
>> thing?
>
> Took me a minute to figure out exactly what you were talking about. You're referring to the
> current in-kernel decoding done on an ad-hoc basis for assorted remotes
> bundled with capture devices, correct?
They are not limited to the currently bundled IR's, since almost all drivers allow
replacing the existing scancode/keycode table to a new onw.
> Admittedly, unifying those and the lirc driven devices hasn't really been on my radar.
It should be done. Having two ways for doing the same thing is not an option. We'll
need to unify them sooner or later. The sooner, the better.
>> We can have a good code for both, or we can end up with "badly broken"
>> media drivers and incompatible, suboptimal existing lirc interface
>> (though most probably much better in terms of quality, especially after
>> Jarod's work).
>
> Well, is there any reason most of those drivers with
> currently-in-kernel-but-badly-broken decoding can't be converted to
> use the lirc interface if its merged into the kernel?
> And/or, everything
> could converge on a new in-kernel decoding infra that wasn't badly broken.
> Sure, there may be two separate ways of doing essentially the same thing
> for a while, but meh. The lirc way works NOW for an incredibly wide
> variety of receivers, transmitters, IR protocols, etc.
Yes: the same drivers support both pulse/space and in-hardware scancode conversion.
In order to use the raw pulse/space API, they'll need to generate pseudo pulse/space's.
This would be a dirty solution, IMHO.
Also, changing the drivers would not be that easy, since it will require lots of
tests with IR's and devices that the developers won't have. This is a weaker argument,
since no matter what decided, we'll need to change the drivers code (on lirc drivers
or on the in-kernel drivers) even without having all hardware available.
> I do concur that Just Works decoding for bundled remotes w/o having to
> configure anything would be nice, and one way to go about doing that
> certainly is via in-kernel IR decoding. But at the same time, the second
> you want to use something other than a bundled remote, things fall down,
> and having to do a bunch of setkeycode ops seems less optimal than simply
> dropping an appropriate lircd.conf in place.
I don't see this as an issue. We have by far too much work to be done in kernelspace
than the changes that are needed on userspace.
Replace the entire scancode table with setkeycode ops is very fast, and needs to be
done only once, at lirc startup. Once you load the new IR code at the driver,
the kernel will send the new keycodes to lirc.
It doesn't seem hard to modify lirc to do read the lircd.conf table and replace the
IR scancodes at the in-kernel driver. It took me half an hour to write my own keycode
loader code, and you can use it as the basis for such feature:
http://linuxtv.org/hg/v4l-dvb/file/tip/v4l2-apps/util/keytable.c
Cheers,
Mauro.
Gerd Hoffmann wrote:
> On 11/25/09 19:20, Devin Heitmueller wrote:
>> On Wed, Nov 25, 2009 at 1:07 PM, Jarod Wilson<[email protected]>
>> wrote:
>>> Took me a minute to figure out exactly what you were talking
>>> about. You're referring to the current in-kernel decoding done on
>>> an ad-hoc basis for assorted remotes bundled with capture devices,
>>> correct?
>>>
>>> Admittedly, unifying those and the lirc driven devices hasn't
>>> really been on my radar.
>
> I think at the end of the day we'll want to have all IR drivers use the
> same interface. The way the current in-kernel input layer drivers work
> obviously isn't perfect too, so we *must* consider both worlds to get a
> good solution for long-term ...
>
>> This is one of the key use cases I would be very concerned with. For
>> many users who have bought tuner products, the bundled remotes work
>> "out-of-the-box", regardless of whether lircd is installed.
>
> I bet this simply isn't going to change.
>
>> I have no objection so much as to saying "well, you have to install
>> the lircd service now", but there needs to be a way for the driver to
>> automatically tell lirc what the default remote control should be,
>> to avoid a regression in functionality.
>
> *Requiring* lircd for the current in-kernel drivers doesn't make sense
> at all. Allowing lircd being used so it can do some more advanced stuff
> makes sense though.
>
>> This is why I think we really should put together a list of use
>> cases, so that we can see how any given proposal addresses those use
>> cases. I offered to do such, but nobody seemed really interested in
>> this.
>
> Lets have a look at the problems the current input layer bits have
> compared to lirc:
>
>
> (1) ir code (say rc5) -> keycode conversion looses information.
>
> I think this can easily be addressed by adding a IR event type to the
> input layer, which could look like this:
>
> input_event->type = EV_IR
> input_event->code = IR_RC5
> input_event->value = <rc5 value>
Agreed. We're doing this already with some drivers (dvb-usb ones). I've
started working on a patchset to extend this to the remaining drivers.
I'm not sure whare were already merged from this tree, but my intention
is to extend this to all drivers.
> In case the 32bit value is too small we might want send two events
> instead, with ->code being set to IR_<code>_1 and IR_<code>_2
Well, RC6 mode 6 uses 32 bits. I don't know if is there any case for
more than 32 bits. However, on some I2C IR chips, we see some cases
where the IR scancode key is encapsulated into some protocol with more
bytes. It seems that those extra bytes are used to handle key repetition
sort of events. I'm not sure if it would make sense to pass the raw
data to userspace. Probably not.
> Advantages:
> * Applications (including lircd) can get access to the unmodified
> rc5/rc6/... codes.
> * All the ir-code -> keycode mapping magic can be handled by the
> core input layer then. All the driver needs to do is to pass on
> the information which keymap should be loaded by default (for the
> bundled remote if any). The configuration can happen in userspace
> (sysfs attribute + udev + small utility in tools/ir/).
I like the idea of such small utility to load the keymap table.
> * lirc drivers which get ir codes from the hardware can be converted
> to pure input layer drivers without regressions. lircd is not
> required any more.
>
>
> (2) input layer doesn't give access to the raw samples.
>
> Not sure how to deal with that best. Passing them through the input
> layer would certainly be possible to hack up. But what would be the
> point? The input layer wouldn't do any processing on them. It wouldn't
> buy us much. So we might want to simply stick with todays lirc
> interface for the raw samples.
If we need such interface, the better is to keep using the lirc interface.
Yet, I'm not sure if we should really keep outputing raw samples, since
several devices won't support it.
> Drivers which support both ir codes (be it by hardware or by in-kernel
> decoding) and raw samples would register two devices then, one input
> device and one lirc device. It would probably a good idea to stop
> sending events to the input layer as soon as someone (most likely lircd)
> opens the lirc device to avoid keystrokes showing up twice.
>
> By default the in-kernel bits will be at work, but optionally you can
> have lircd grab the raw samples and do fancy advanced decoding.
>
>
> (3) input layer doesn't allow transmitting IR codes.
>
> If we keep the lirc interface for raw samples anyway, then we can keep
> it for sending too, problem solved ;) How does sending hardware work
> btw? Do they all accept just raw samples? Or does some hardware also
> accept ir-codes?
I would do it in a way that it will accept scancodes and raw samples,
since, even if we currently have only devices that accept raw samples,
it would be more future-proof to allow sending scancodes also.
Cheers,
Mauro
On Thu, Nov 26, 2009 at 9:45 AM, Mauro Carvalho Chehab
<[email protected]> wrote:
> Gerd Hoffmann wrote:
>> On 11/25/09 19:20, Devin Heitmueller wrote:
>>> On Wed, Nov 25, 2009 at 1:07 PM, Jarod Wilson<[email protected]>
>>> wrote:
>>>> Took me a minute to figure out exactly what you were talking
>>>> about. You're referring to the current in-kernel decoding done on
>>>> an ad-hoc basis for assorted remotes bundled with capture devices,
>>>> correct?
>>>>
>>>> Admittedly, unifying those and the lirc driven devices hasn't
>>>> really been on my radar.
>>
>> I think at the end of the day we'll want to have all IR drivers use the
>> same interface. ?The way the current in-kernel input layer drivers work
>> obviously isn't perfect too, so we *must* consider both worlds to get a
>> good solution for long-term ...
I made an attempt at implementing all of this a year ago.
http://lkml.org/lkml/2008/11/5/233
All of this kernel code is tiny, about 20K including a driver.
Basic flow works like this:
Add a new IR data type to the input framework
http://lkml.org/lkml/2008/11/5/234
Example mceusb IR input driver
http://lkml.org/lkml/2008/11/5/238
In-kernel decoding of core IR protocols - RC5, RC6, etc
http://lkml.org/lkml/2008/11/5/234
Decoded core protocols pass through a translation map based on configfs
When core protocol matches an entry in configfs it is turned into a
keycode event.
http://lkml.org/lkml/2008/11/5/235
You make a directory in /configfs/remotes for each remote you have.
Making the directory creates a new evdev device. Under the directory
make an entry for each command generated by the device. These entries
cause the decoded IR data to be mapped into keycodes on the new evdev
device. udev would load these configfs mappings at boot time...
mkdir /config/remotes/sony
-- this creates a new evdev device
mkdir remotes/sony/one
echo 7 >remotes/sony/one/protocol
echo 264 >remotes/sony/one/command
echo 2 >remotes/sony/one/keycode
This transforms a button push of 1 on my remote into a key stroke for KEY_1
* configfs root
* --remotes
* ----specific remote
* ------keymap
* --------protocol
* --------device
* --------command
* --------keycode
* ------repeat keymaps
* --------....
* ----another remote
* ------more keymaps
You can map the 1 button from multiple remotes to KEY_1 if you want. Or
you can use a single remote to create multiple virtual keyboards.
-------------------------
Raw IR pulse data is available in a FIFO via sysfs. You can use this
to figure out new remote protocols.
Two input events are generated
1) an event for the decoded raw IR protocol
2) a keycode event if thedecoded raw IR protocol matches an entry in
the configfs
You can also send pulses.
------
If you want to script this, you would have a user space task that
watches for either the decoded IR codes or the mapped keycodes.
This system also works with user space device drivers. They can inject
input events into the early event flow and they will get processed as
if the event originated in the kernel.
---------------------
Sure you could push the protocol decoding code (RC5, etc) into user
space. Seems like a lot of hassle to move about 3KB of code out of the
kernel.
--
Jon Smirl
[email protected]
BTW, we used to have device specific user space interfaces for mouse
and keyboard. These caused all sort of problems. A lot of work went
into unifying them under evdev. It will be years until the old,
messed up interfaces can be totally removed.
I'm not in favor of repeating the problems with a device specific user
space interface for IR. I believe all new input devices should
implement the evdev framework.
--
Jon Smirl
[email protected]
Jarod Wilson wrote:
>> I guess the question is what is the interface we want the regular
>> userspace (i.e. not lircd) to use. Right now programs has to use 2
>> intercfaces - one lirc for dealing with remotes that are not using
>> the standard event interface and evdev for remotes using it as well
>> as the rest of the input devices.
>
> From the mythtv perspective, using the input layer could yield a better
> out-of-the-box experience -- users don't have to set up an lircrc mapping
> that converts key names as specified in lircd.conf into commands
> (key strokes, actually) that mythtv understands. For example, a button labeled "Play"
> in lircd.conf has to be mapped to 'p' in ~/.lircrc for mythtv to do the right
> thing with it. If everything came through the input layer, be that natively
> or via lircd's uinput reinjection, there would be no need to do that extra
> mapping step, mythtv would simply handle a KEY_PLAY event. So at worst,
> one manual mapping to do -- IR signal to standard button name in lircd.conf --
> instead of two. But the lircrc approach does also allow more flexibility,
> in that you can only have a certain app respond to a certain key, if so desired,
> and remap a key to a different function (KEY_RED, KEY_GREEN, KEY_BLUE, KEY_YELLOW
> -- what should their default functionality be? I know some users map a pair
> of those to mythtv's "skip to next commflag point" and "skip to prior commflag point").
>
> Unfortunately, mythtv currently doesn't handle KEY_PLAY, KEY_VOLUMEUP, etc., etc. at
> all right now, it operates purely on keys commonly found on a standard keyboard.
> Remedying that is on my TODO list for the next release, if I can carve out the time.
This discussion is a little OT from the API discussions, since it affects both out-of-the
box IR reception via input layer and lirc.
All media applications should be capable of handling the corresponding KEY_PLAY, KEY_VOLUMEUP ...
keys without needing to do anything else than just handling the corresponding keycode.
You shouldn't need to start a daemon or doing anything else for this to work out-of-the-box.
They currently don't do it due to historic reasons (it is easier to let something else
remap KEY_PLAY into 'p' than to add the proper code there).
When using non-hot-pluggable devices where you're building a dedicated MCE hardware (this
is the common case of MythTV setups), things are not that bad, since, once you set your
hardware, it is done.
However, by looking on the number of different new devices, it seems that the most common
type of devices are the TV USB sticks. As they are hot pluggable, eventually users may
have more than one hardware and they expect that the IR layer will work equally on
all your devices.
The proper way for supporting it is to have a common application-agnostic keycode to indicate
the received events. For example, all IR's should produce KEY_CHANNELUP/KEY_CHANNELDOWN events
for changing the channels. Also, on a perfect world, lirc should send this event to the
multimedia application that handles TV when such key is pressed, instead of converting into
some other keycode. This prevents future problems if, for some reason, the application needs to
do something else with that key, or if the key has a different meaning on some different contexts.
For example, on some applications, KEY_UP/KEY_DOWN can mean to change a channel, but those keys
are also used for menu navigation. However, KEY_CHANNELUP has a clear unique meaning: to change a channel.
The expected behavior, from users perspective, is to mimic a TV box, where if you press channel UP
any open menu will be closed and the channel will be changed, but pressing UP key will
navigate at the menu. Well, if you map KEY_CHANNELUP as KEY_UP, you'll produce a different behavior.
Cheers,
Mauro.
0x0700 KEY_MUTE
0x0701 KEY_MENU
0x0739 KEY_POWER
0x0703 KEY_VOLUMEUP
0x0709 KEY_VOLUMEDOWN
0x0706 KEY_CHANNELUP
0x070c KEY_CHANNELDOWN
0x070f KEY_1
0x0715 KEY_2
0x0710 KEY_3
0x0718 KEY_4
0x071b KEY_5
0x071e KEY_6
0x0711 KEY_7
0x0721 KEY_8
0x0712 KEY_9
0x0727 KEY_0
0x0724 KEY_SCREEN
0x072a KEY_TEXT
0x072d KEY_REWIND
0x0730 KEY_PLAY
0x0733 KEY_FASTFORWARD
0x0736 KEY_RECORD
0x073c KEY_STOP
0x073f KEY_CANCEL
0xeb01 KEY_POWER
0xeb02 KEY_1
0xeb03 KEY_2
0xeb04 KEY_3
0xeb05 KEY_4
0xeb06 KEY_5
0xeb07 KEY_6
0xeb08 KEY_7
0xeb09 KEY_8
0xeb0a KEY_9
0xeb0b KEY_VIDEO
0xeb0c KEY_0
0xeb0d KEY_REFRESH
0xeb0f KEY_EPG
0xeb10 KEY_UP
0xeb11 KEY_LEFT
0xeb12 KEY_OK
0xeb13 KEY_RIGHT
0xeb14 KEY_DOWN
0xeb16 KEY_INFO
0xeb17 KEY_RED
0xeb18 KEY_GREEN
0xeb19 KEY_YELLOW
0xeb1a KEY_BLUE
0xeb1b KEY_CHANNELUP
0xeb1c KEY_VOLUMEUP
0xeb1d KEY_MUTE
0xeb1e KEY_VOLUMEDOWN
0xeb1f KEY_CHANNELDOWN
0xeb40 KEY_PAUSE
0xeb41 KEY_HOME
0xeb42 KEY_MENU
0xeb43 KEY_SUBTITLE
0xeb44 KEY_TEXT
0xeb45 KEY_DELETE
0xeb46 KEY_TV
0xeb47 KEY_DVD
0xeb48 KEY_STOP
0xeb49 KEY_VIDEO
0xeb4a KEY_AUDIO
0xeb4b KEY_SCREEN
0xeb4c KEY_PLAY
0xeb4d KEY_BACK
0xeb4e KEY_REWIND
0xeb4f KEY_FASTFORWARD
0xeb54 KEY_PREVIOUS
0xeb58 KEY_RECORD
0xeb5c KEY_NEXT
0x1e00 KEY_0
0x1e01 KEY_1
0x1e02 KEY_2
0x1e03 KEY_3
0x1e04 KEY_4
0x1e05 KEY_5
0x1e06 KEY_6
0x1e07 KEY_7
0x1e08 KEY_8
0x1e09 KEY_9
0x1e0a KEY_KPASTERISK
0x1e0b KEY_RED
0x1e0c KEY_RADIO
0x1e0d KEY_MENU
0x1e0e KEY_GRAVE
0x1e0f KEY_MUTE
0x1e10 KEY_VOLUMEUP
0x1e11 KEY_VOLUMEDOWN
0x1e12 KEY_CHANNEL
0x1e14 KEY_UP
0x1e15 KEY_DOWN
0x1e16 KEY_LEFT
0x1e17 KEY_RIGHT
0x1e18 KEY_VIDEO
0x1e19 KEY_AUDIO
0x1e1a KEY_MEDIA
0x1e1b KEY_EPG
0x1e1c KEY_TV
0x1e1e KEY_NEXT
0x1e1f KEY_BACK
0x1e20 KEY_CHANNELUP
0x1e21 KEY_CHANNELDOWN
0x1e24 KEY_LAST
0x1e25 KEY_OK
0x1e29 KEY_BLUE
0x1e2e KEY_GREEN
0x1e30 KEY_PAUSE
0x1e32 KEY_REWIND
0x1e34 KEY_FASTFORWARD
0x1e35 KEY_PLAY
0x1e36 KEY_STOP
0x1e37 KEY_RECORD
0x1e38 KEY_YELLOW
0x1e3b KEY_GOTO
0x1e3d KEY_POWER
0x0042 KEY_POWER
0x077c KEY_TUNER
0x0f4e KEY_PRINT
0x0840 KEY_SCREEN
0x0f71 KEY_DOT
0x0743 KEY_0
0x0c41 KEY_1
0x0443 KEY_2
0x0b7f KEY_3
0x0e41 KEY_4
0x0643 KEY_5
0x097f KEY_6
0x0d7e KEY_7
0x057c KEY_8
0x0a40 KEY_9
0x0e4e KEY_CLEAR
0x047c KEY_CHANNEL
0x0f41 KEY_LAST
0x0342 KEY_MUTE
0x064c KEY_RESERVED
0x0172 KEY_SHUFFLE
0x0c4e KEY_PLAYPAUSE
0x0b70 KEY_RECORD
0x037d KEY_VOLUMEUP
0x017d KEY_VOLUMEDOWN
0x0242 KEY_CHANNELUP
0x007d KEY_CHANNELDOWN
0x1d00 KEY_0
0x1d01 KEY_1
0x1d02 KEY_2
0x1d03 KEY_3
0x1d04 KEY_4
0x1d05 KEY_5
0x1d06 KEY_6
0x1d07 KEY_7
0x1d08 KEY_8
0x1d09 KEY_9
0x1d0a KEY_TEXT
0x1d0d KEY_MENU
0x1d0f KEY_MUTE
0x1d10 KEY_VOLUMEUP
0x1d11 KEY_VOLUMEDOWN
0x1d12 KEY_CHANNEL
0x1d14 KEY_UP
0x1d15 KEY_DOWN
0x1d16 KEY_LEFT
0x1d17 KEY_RIGHT
0x1d1c KEY_TV
0x1d1e KEY_NEXT
0x1d1f KEY_BACK
0x1d20 KEY_CHANNELUP
0x1d21 KEY_CHANNELDOWN
0x1d24 KEY_LAST
0x1d25 KEY_OK
0x1d30 KEY_PAUSE
0x1d32 KEY_REWIND
0x1d34 KEY_FASTFORWARD
0x1d35 KEY_PLAY
0x1d36 KEY_STOP
0x1d37 KEY_RECORD
0x1d3b KEY_GOTO
0x1d3d KEY_POWER
0x8613 KEY_MUTE
0x8612 KEY_POWER
0x8601 KEY_1
0x8602 KEY_2
0x8603 KEY_3
0x8604 KEY_4
0x8605 KEY_5
0x8606 KEY_6
0x8607 KEY_7
0x8608 KEY_8
0x8609 KEY_9
0x8600 KEY_0
0x860d KEY_CHANNELUP
0x8619 KEY_CHANNELDOWN
0x8610 KEY_VOLUMEUP
0x860c KEY_VOLUMEDOWN
0x860a KEY_CAMERA
0x860b KEY_ZOOM
0x861b KEY_BACKSPACE
0x8615 KEY_ENTER
0x861d KEY_UP
0x861e KEY_DOWN
0x860e KEY_LEFT
0x860f KEY_RIGHT
0x8618 KEY_RECORD
0x861a KEY_STOP
0x7a00 KEY_MENU
0x7a01 KEY_RECORD
0x7a02 KEY_PLAY
0x7a03 KEY_STOP
0x7a10 KEY_CHANNELUP
0x7a11 KEY_CHANNELDOWN
0x7a12 KEY_VOLUMEUP
0x7a13 KEY_VOLUMEDOWN
0x7a40 KEY_POWER
0x7a41 KEY_MUTE
Andy Walls wrote:
> On Thu, 2009-11-26 at 11:25 -0200, Mauro Carvalho Chehab wrote:
>> I'm not sure if all the existing hardware for TX currently supports only
>> raw pulse/code sequencies, but I still think that, even on the Tx case,
>> it is better to send scancodes to the driver, and let it do the conversion
>> to raw pulse/code, if the hardware requires pulse/code instead of scancodes.
>
> That seems like a decision which will create a lots of duplicative code
> in the kernel. Add it's just busy-work to write such code when a
> userspace application in common use already handles the protocols and
> sends raw pulses to hardware that expects raw pulses.
I don't see how this would create lots of duplicative code.
>> However, as we have green field,
>> I would add the protocol explicitly for each scancode to be transmitted, like:
>>
>> struct ir_tx {
>> enum ir_protocol proto;
>> u32 scancode;
>> };
>>
>> Eventually, we might have a protocol "raw" and some extra field to allow passing
>> a raw pulse/code sequence instead of a scancode.
>
> I think you would have to. 32 bits is really not enough for all
> protocols, and it is already partial encoding of information anyway.
>
> If the Tx driver has to break them down into pulses anyway,
Do all Tx drivers need handle pulse by pulse, or there are some that works
only with scancodes?
> why not have fields with more meaningful names
>
> mode
> toggle
> customer code (or system code or address),
> information (or command)
>
> According to
>
> http://slycontrol.ru/scr/kb/rc6.htm
>
> the "information" field could be up to 128 bits.
Seems fine to me.
> (Not that I'm going to put any RC-6 Mode 6A decoding/encoding in the
> kernel.)
>
> Regards,
> Andy
>
>> Cheers,
>> Mauro.
>
>
Gerd Hoffmann <[email protected]> writes:
> Why not? With RC5 remotes applications can get the device address
> bits for example, which right now are simply get lost in the ir code
> ->
> keycode conversion step.
Right, this in fact makes the input layer interface unusable for many
remotes at this time.
I think the address (aka group) should be just a part of the key
("command") code, IIRC this is what lirc RC5 does (I'm presently using
a custom "media" version of RC5).
> I know that lircd does matching instead of decoding, which allows to
> handle unknown encodings. Thats why I think there will always be
> cases which only lircd will be able to handle (using raw samples).
>
> That doesn't make attempts to actually decode the IR samples a useless
> exercise though ;)
Sure. Especially RC5-like protos are simple to decode, and it's very
reliable, even with a very unstable remote clock source (such as
RC-based = resistor + capacitor).
--
Krzysztof Halasa
On 11/26/2009 04:14 AM, Gerd Hoffmann wrote:
> On 11/26/09 07:23, Jarod Wilson wrote:
>> Well, when mythtv was started, I don't know that there were many
>> input layer remotes around... lirc was definitely around though.
>
> lirc predates the input layer IR drivers by years, maybe even the input
> layer itself.
That was my guess, but I didn't have a timeline in front of me. :)
> The main reason for the input layer IR drivers appearing was lirc not
> being mainline. A in-kernel driver (bttv in that case) which depends on
> a out-of-tree subsystem for IR support was simply a pain in the ass for
> both maintainer (/me back then) and users.
>
> At least for IR hardware which allows access to the raw samples it
> certainly makes sense to support lirc, additional to the current (or
> improved) input layer support.
I'm liking the idea of a hybrid approach, where IR devices can support
both lirc and input device interfaces. I think its the most
regression-proof for end-users, if done correctly, which is one of my
biggest concerns.
>> The lirc support in mythtv actually relies on mapping remote button
>> names as defined in lircd.conf to keyboard key strokes. As mentioned
>> elsewhere in this beast of a thread, mythtv doesn't currently support
>> things like KEY_PLAY, KEY_VOLUMEUP, KEY_CHANNELUP, etc. just yet, but
>> I intend on fixing that...
>
> lircd can handle the input layer as input as well, so you actually can
> remap things via lircd even for pure input layer drivers. mythtv
> handling KEY_VOLUMEUP directly would be more elegant though.
Yeah, no, I know lircd can attach to an input device. But even if you do
that, you have to have a mapping that converts KEY_VOLUMEUP as captured
by lircd into (iirc) right-bracket (]) for mythtv to actually consume
it. Directly handling definitely needs to be added to mythtv.
--
Jarod Wilson
[email protected]
On 11/26/2009 08:54 AM, Mauro Carvalho Chehab wrote:
> Jarod Wilson wrote:
>> On Nov 23, 2009, at 7:53 PM, Andy Walls wrote:
>>
>>> On Mon, 2009-11-23 at 22:11 +0100, Christoph Bartelmus wrote:
>> ...
>>> I generally don't understand the LIRC aversion I perceive in this thread
>>> (maybe I just have a skewed perception). Aside for a video card's
>>> default remote setup, the suggestions so far don't strike me as any
>>> simpler for the end user than LIRC -- maybe I'm just used to LIRC. LIRC
>>> already works for both transmit and receive and has existing support in
>>> applications such as MythTV and mplayer.
>>
>> There's one gripe I agree with, and that is that its still not plug-n-play.
>> Something where udev auto-loads a sane default remote config for say,
>> mceusb transceivers, and the stock mce remote Just Works would be nice,
>> but auto-config is mostly out the window the second you involve transmitters
>> and universal remotes anyway.
>
> For several devices, an udev rule that auto-loads a sane default keymap does work.
> Of course, this won't cover 100% of the usages, and I lirc is a very good way
> of covering the holes.
>
>> But outside of that, I think objections are largely philosophical --
>> in a nutshell, the kernel has an input layer, remotes are input devices,
>> and lirc doesn't conform to input layer standards.
>
> Yes. I think this is mainly the issue.
>
> The other issue is how to migrate the existing drivers to a new API without
> causing regressions. If we decide that IR's that receive raw pulse/code
> should use the raw input interface, this means that a large task force will be
> needed to convert the existing drivers to use it.
Aversion to regression is definitely a major concern. And why I'm liking
the idea of a hybrid approach, at least initially.
> What do you think of adding lirc at staging while we discuss/improve the API's and lircd
> support for the input event interface? Do you think this would work?
Sure, I don't see why not. And I've got another dozen or so drivers to
follow those first three... :)
--
Jarod Wilson
[email protected]
Dmitry Torokhov <[email protected]> writes:
> In what way the key interface is unsufficient for delivering button
> events?
At present: 128 different keys only (RC5: one group). One remote per
device only.
The protocol itself doesn't have the above limitations, but has others,
with are acceptable for key input.
--
Krzysztof Halasa
Jarod Wilson wrote:
> On 11/26/2009 08:54 AM, Mauro Carvalho Chehab wrote:
>> Jarod Wilson wrote:
>>> On Nov 23, 2009, at 7:53 PM, Andy Walls wrote:
>>>
>>>> On Mon, 2009-11-23 at 22:11 +0100, Christoph Bartelmus wrote:
>>> ...
>>>> I generally don't understand the LIRC aversion I perceive in this
>>>> thread
>>>> (maybe I just have a skewed perception). Aside for a video card's
>>>> default remote setup, the suggestions so far don't strike me as any
>>>> simpler for the end user than LIRC -- maybe I'm just used to LIRC.
>>>> LIRC
>>>> already works for both transmit and receive and has existing support in
>>>> applications such as MythTV and mplayer.
>>>
>>> There's one gripe I agree with, and that is that its still not
>>> plug-n-play.
>>> Something where udev auto-loads a sane default remote config for say,
>>> mceusb transceivers, and the stock mce remote Just Works would be nice,
>>> but auto-config is mostly out the window the second you involve
>>> transmitters
>>> and universal remotes anyway.
>>
>> For several devices, an udev rule that auto-loads a sane default
>> keymap does work.
>> Of course, this won't cover 100% of the usages, and I lirc is a very
>> good way
>> of covering the holes.
>>
>>> But outside of that, I think objections are largely philosophical --
>>> in a nutshell, the kernel has an input layer, remotes are input devices,
>>> and lirc doesn't conform to input layer standards.
>>
>> Yes. I think this is mainly the issue.
>>
>> The other issue is how to migrate the existing drivers to a new API
>> without
>> causing regressions. If we decide that IR's that receive raw pulse/code
>> should use the raw input interface, this means that a large task force
>> will be
>> needed to convert the existing drivers to use it.
>
> Aversion to regression is definitely a major concern. And why I'm liking
> the idea of a hybrid approach, at least initially.
Yes. This indeed seems to be a very good idea.
>
>> What do you think of adding lirc at staging while we discuss/improve
>> the API's and lircd
>> support for the input event interface? Do you think this would work?
>
> Sure, I don't see why not. And I've got another dozen or so drivers to
> follow those first three... :)
Ok. As you said you'll do some work at the patches, could you please send us v3
in order to add it into drivers/staging?
In the case of the API header file, I would tag at the header file that the API
is experimental, so can be changed without prior announcements, etc (in order to
avoid people to use and rely on it it outside lirc). IMO, the better is to keep
such announcement there while we're still working at the hybrid approach, as we
may need to change something during the development phase.
Dmitry,
While lirc is basically a series of input drivers, considering that they have lots
in common with the input drivers at V4L/DVB and that we'll need to work on
some glue to merge both, do you mind if I add the lirc drivers at drivers/staging from
my trees?
Cheers,
Mauro.
Krzysztof Halasa wrote:
> Dmitry Torokhov <[email protected]> writes:
>
>> In what way the key interface is unsufficient for delivering button
>> events?
>
> At present: 128 different keys only (RC5: one group). One remote per
> device only.
>
> The protocol itself doesn't have the above limitations, but has others,
> with are acceptable for key input.
This is not a limit at the input subsystem. It were a design decision for
some drivers at the V4L subsystem that we need to change.
Cheers,
Mauro.
Mauro Carvalho Chehab <[email protected]> writes:
> 1) the developer that adds the hardware also adds the IR code. He has
> the hardware and the IR for testing, so it means a faster development
> cycle than waiting for someone else with the same hardware and IR to
> recode it on some other place. You should remember that not all
> developers use lirc;
It's fine, but please - no keymaps in the kernel (except for fixed
receivers, i.e. the ones which can only work with their own dedicated
remote, and which don't pass RC5/etc. code).
The existing keymaps (those which can be used with lirc) have to be
moved to userspace as well.
--
Krzysztof Halasa
Mauro Carvalho Chehab <[email protected]> writes:
> Technically, it is not hard to port this solution to the other
> drivers, but the issue is that we don't have all those IR's to know
> what is the complete scancode that each key produces. So, the hardest
> part is to find a way for doing it without causing regressions, and to
> find a group of people that will help testing the new way.
We don't want to "port it" to other drivers. We need to have a common
module which does all RCx decoding. The individual drivers should be as
simple as possible, something that I outlined in a previous mail.
--
Krzysztof Halasa
Mauro Carvalho Chehab <[email protected]> writes:
> The issue I see is to support at the same time NEC and RC5 protocols. While
> this may work with some devices, for others, the hardware won't allow.
Sure. We can handle it for the "simple" devices at least.
>> I think the mapping should be: key = proto + group + raw code, while
>> key2 could be different_proto + different group (if any) + another code.
>
> This may work for protocols up to RC5, that uses either 8 or 16 bits.
> However, RC6 mode 6 codes can be 32 bits, and we have "only" 32 bits
> for a scancode. So, we don't have spare bits to represent a protocol,
> if we consider RC6 mode 6 codes as well.
I don't see this limitation. The number of bits should depend on the
protocol.
> See above. Also, several protocols have a way to check if a keystroke were
> properly received. When handling just one protocol, we can use this to double
> check the key. However, on a multiprotocol mode, we'll need to disable this
> feature.
I don't think so. We can pass the space/mark data to all (configured,
i.e. with active mapping) protocol handlers at once. Should a check
fail, we ignore the data. Perhaps another protocol will make some sense
out of it.
--
Krzysztof Halasa
Maxim Levitsky <[email protected]> writes:
> But devices that send raw pulse/space data should be handled in lirc
> that will feed the data back to the kernel via uinput.
I still do want the in-kernel RCx decoding. And lirc pulse/space.
--
Krzysztof Halasa
Dmitry Torokhov <[email protected]> writes:
> Why would sysfs write be slower than ioctl?
Sysfs is generally one-value, one-file. open, read/write, close.
ioctl() OTOH does everything (e.g. a whole key table) in one syscall.
--
Krzysztof Halasa
Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
>> 1) the developer that adds the hardware also adds the IR code. He has
>> the hardware and the IR for testing, so it means a faster development
>> cycle than waiting for someone else with the same hardware and IR to
>> recode it on some other place. You should remember that not all
>> developers use lirc;
>
> It's fine, but please - no keymaps in the kernel (except for fixed
> receivers, i.e. the ones which can only work with their own dedicated
> remote, and which don't pass RC5/etc. code).
>
> The existing keymaps (those which can be used with lirc) have to be
> moved to userspace as well.
The removal of the existing keymaps from kernel depends on having an application
to be called from udev to load the proper keymaps when a device is probed.
After having it for a while, we should deprecate the in-kernel keymaps
and move them to userspace.
I also think that it is important to remove the 7 bits limitation from all drivers
and re-generate the keymaps, since they'll change after it.
cheers,
Mauro.
Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
>> Technically, it is not hard to port this solution to the other
>> drivers, but the issue is that we don't have all those IR's to know
>> what is the complete scancode that each key produces. So, the hardest
>> part is to find a way for doing it without causing regressions, and to
>> find a group of people that will help testing the new way.
>
> We don't want to "port it" to other drivers. We need to have a common
> module which does all RCx decoding. The individual drivers should be as
> simple as possible, something that I outlined in a previous mail.
With the current 7bits mask applied to almost all devices, it is probably not very
useful for those who want to use generic IRs. We really need to port the solution
we've done on dvb-usb to the other drivers, allowing them to have the entire
scancode at the tables while keep supporting table replacement.
The issue is that we currently have only 7bits of the scan codes produced by the IR's.
So, we need to re-generate the keycode tables for each IR after the changes got applied.
With respect to a common module, unfortunately most of the work should be done on
each driver, since the code that communicates with the hardware is specific to each
device. There is a common code (at ir-common.ko) with helper decoding routines.
Please feel free to send us contributions to improve the current code.
Cheers,
Mauro.
Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
>> The issue I see is to support at the same time NEC and RC5 protocols. While
>> this may work with some devices, for others, the hardware won't allow.
>
> Sure. We can handle it for the "simple" devices at least.
>
>>> I think the mapping should be: key = proto + group + raw code, while
>>> key2 could be different_proto + different group (if any) + another code.
>> This may work for protocols up to RC5, that uses either 8 or 16 bits.
>> However, RC6 mode 6 codes can be 32 bits, and we have "only" 32 bits
>> for a scancode. So, we don't have spare bits to represent a protocol,
>> if we consider RC6 mode 6 codes as well.
>
> I don't see this limitation. The number of bits should depend on the
> protocol.
see include/linux/input.h:
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
extending the value to more than 32 bits require some changes at the input layer,
probably breaking kernel API.
>
>> See above. Also, several protocols have a way to check if a keystroke were
>> properly received. When handling just one protocol, we can use this to double
>> check the key. However, on a multiprotocol mode, we'll need to disable this
>> feature.
>
> I don't think so. We can pass the space/mark data to all (configured,
> i.e. with active mapping) protocol handlers at once. Should a check
> fail, we ignore the data. Perhaps another protocol will make some sense
> out of it.
What happens if it succeeds on two protocol handlers?
Cheers,
Mauro.
On Thu, 2009-11-26 at 12:05 -0200, Mauro Carvalho Chehab wrote:
> Krzysztof Halasa wrote:
> > Andy Walls <[email protected]> writes:
> >
> >> I would also note that RC-6 Mode 6A, used by most MCE remotes, was
> >> developed by Philips, but Microsoft has some sort of licensing interest
> >> in it and it is almost surely encumbered somwhow:
> >
> > I don't know about legal problems in some countries but from the
> > technical POV handling the protocol in the kernel is more efficient
> > or (/and) simpler.
>
> A software licensing from Microsoft won't apply to Linux kernel, so I'm
> assuming that you're referring to some patent that they could be filled
> about RC6 mode 6A.
>
> I don't know if is there any US patent pending about it (AFAIK, only US
> accepts software patents), but there are some prior-art for IR key
> decoding. So, I don't see what "innovation" RC6 would be adding.
> If it is some new way to transmit waves, the patent issues
> aren't related to software, and the device manufacturer had already handled
> it when they made their devices.
>
> If it is just a new keytable, this issue
> could be easily solved by loading the keytable via userspace.
>
> Also, assuming that you can use the driver only with a hardware that comes
> with a licensed software, the user has already the license for using it.
>
> Do you have any details on what patents they are claiming?
The US Philips RC-6 patent is US Patent 5,877,702
http://www.google.com/patents?vid=USPAT5877702
Click on download PDF to get a copy of the whole patent.
I am not a lawyer. Philips claims' all appear to tie to a transmitter
or receiver as part of a system, but most of the claims are about
information and bit positions and lengths.
I don't know for sure what Microsoft claims to be licensing. I think it
is the protocol itself:
http://www.microsoft.com/presspass/Press/2002/Apr02/04-16FreestylePhilipsPR.mspx
"Under the terms of the agreement, Microsoft and Philips will license to
OEMs an IR protocol based on Philips proprietary RC6 IR technology. The
patented and globally adopted solution minimizes interference from other
remote-control devices in the household. Use of this established
protocol will help ensure uniform development of Windows infrared
remote-control products, which include infrared remote-control units and
remote-control receivers..."
http://download.microsoft.com/download/9/8/f/98f3fe47-dfc3-4e74-92a3-088782200fe7/TWEN05007_WinHEC05.ppt
See Slide 5, which has the bullet: "How to License RC6"
Since the content of the information field in RC-6 Mode 6A is left up to
OEMs, I would not be surprised by bogus "innovations" in OEM patents
about RC-6 Mode 6A contents. I would not be at all surprised by
something like "a bit to indicate a toggled remote key press in the
information field" since RC-6's T bits for mode 6 indicate Mode 6A or
Mode 6B and not toggles.
IMO, given
a. the dearth of public information about RC-6, indicating someone
thinks it's their trade secret or intellectual property
b. Microsoft claiming to license something related to the MCE remote
protocols (which are obviously RC-6 Mode 6A),
c. my inability to draw a "clear, bright line" that RC-6 Mode 6A
encoding and decoding, as needed by MCE remotes, implemented in software
doesn't violate anyone's government granted rights to exclusivity.
I think it's much better to implement software RC-6 Mode 6A encoding and
decoding in user space, doing only the minimum needed to get the
hardware setup and going in the kernel.
Encoding/decoding of RC-6 by microcontrollers with firmware doesn't
worry me.
Maybe I'm being too conservative here, but I have a personal interest in
keeping Linux free and unencumbered even in the US which, I cannot deny,
has a patent system that is screwed up.
Regards,
Andy
> Cheers,
> Mauro.
Mauro Carvalho Chehab <[email protected]> writes:
> The removal of the existing keymaps from kernel depends on having an
> application
> to be called from udev to load the proper keymaps when a device is probed.
>
> After having it for a while, we should deprecate the in-kernel keymaps
> and move them to userspace.
Sounds like a plan.
> I also think that it is important to remove the 7 bits limitation from
> all drivers
> and re-generate the keymaps, since they'll change after it.
I think the existing space/mark media drivers need to be reworked
completely.
--
Krzysztof Halasa
Mauro Carvalho Chehab <[email protected]> writes:
> see include/linux/input.h:
>
> struct input_event {
> struct timeval time;
> __u16 type;
> __u16 code;
> __s32 value;
> };
>
> extending the value to more than 32 bits require some changes at the
> input layer, probably breaking kernel API.
Yeah, but that's a "key" space, not "raw code" space.
Keys via input and raw codes via lirc and there is no problem.
The mapping tables for input layer need to have variable code widths,
depending on the protocol, sure.
>> I don't think so. We can pass the space/mark data to all (configured,
>> i.e. with active mapping) protocol handlers at once. Should a check
>> fail, we ignore the data. Perhaps another protocol will make some sense
>> out of it.
>
> What happens if it succeeds on two protocol handlers?
We signal both and hope it isn't self-destruct button.
We can't fix it no matter how hard we try.
--
Krzysztof Halasa
Hi Mauro,
on 26 Nov 09 at 10:36, Mauro Carvalho Chehab wrote:
[...]
> lircd supports input layer interface. Yet, patch 3/3 exports both devices
> that support only pulse/space raw mode and devices that generate scan
> codes via the raw mode interface. It does it by generating artificial
> pulse codes.
Nonsense! There's no generation of artificial pulse codes in the drivers.
The LIRC interface includes ways to pass decoded IR codes of arbitrary
length to userspace.
Christoph
Christoph Bartelmus wrote:
> Hi Mauro,
>
> on 26 Nov 09 at 10:36, Mauro Carvalho Chehab wrote:
> [...]
>> lircd supports input layer interface. Yet, patch 3/3 exports both devices
>> that support only pulse/space raw mode and devices that generate scan
>> codes via the raw mode interface. It does it by generating artificial
>> pulse codes.
>
> Nonsense! There's no generation of artificial pulse codes in the drivers.
> The LIRC interface includes ways to pass decoded IR codes of arbitrary
> length to userspace.
I might have got wrong then a comment in the middle of the
imon_incoming_packet() of the SoundGraph iMON IR patch:
+ /*
+ * Translate received data to pulse and space lengths.
+ * Received data is active low, i.e. pulses are 0 and
+ * spaces are 1.
+ *
+ * My original algorithm was essentially similar to
+ * Changwoo Ryu's with the exception that he switched
+ * the incoming bits to active high and also fed an
+ * initial space to LIRC at the start of a new sequence
+ * if the previous bit was a pulse.
+ *
+ * I've decided to adopt his algorithm.
+ */
Cheers,
Mauro.
Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
>> see include/linux/input.h:
>>
>> struct input_event {
>> struct timeval time;
>> __u16 type;
>> __u16 code;
>> __s32 value;
>> };
>>
>> extending the value to more than 32 bits require some changes at the
>> input layer, probably breaking kernel API.
>
> Yeah, but that's a "key" space, not "raw code" space.
> Keys via input and raw codes via lirc and there is no problem.
No. All the other API functions there work with 32 bits for scancodes.
For example, the two ioctls to replace a scancode x key code are defined as:
#define EVIOCGKEYCODE _IOR('E', 0x04, int[2]) /* get keycode */
#define EVIOCSKEYCODE _IOW('E', 0x04, int[2]) /* set keycode */
We need to better analyze the API to see how this can be extended to
allow bigger widths.
(what's worse is that it is defined as "int" instead of "u32" - so the number
of bits is different on 32 and on 64 systems)
> The mapping tables for input layer need to have variable code widths,
> depending on the protocol, sure.
>
>>> I don't think so. We can pass the space/mark data to all (configured,
>>> i.e. with active mapping) protocol handlers at once. Should a check
>>> fail, we ignore the data. Perhaps another protocol will make some sense
>>> out of it.
>> What happens if it succeeds on two protocol handlers?
>
> We signal both and hope it isn't self-destruct button.
> We can't fix it no matter how hard we try.
We can fix. Just let the userspace select what protocol(s) is(are) enabled.
Cheers,
Mauro.
Mauro Carvalho Chehab <[email protected]> writes:
> No. All the other API functions there work with 32 bits for scancodes.
We don't need them, do we? We need a new ioctl for changing key mappings
anyway (a single ioctl for setting the whole table I think), and we can
have arbitrary length of scan codes there.
> (what's worse is that it is defined as "int" instead of "u32" - so the number
> of bits is different on 32 and on 64 systems)
Most (all?) 64-bit systems use 32-bit ints (and 64-bit longs).
u32 and similar are for sure better.
>> We signal both and hope it isn't self-destruct button.
>> We can't fix it no matter how hard we try.
>
> We can fix. Just let the userspace select what protocol(s) is(are) enabled.
Sure, I meant the situation when both protocols (and scan codes) where
enabled and configured. If we don't use RCx in the mapping table, we
don't pass anything to RCx routine. If we have RCx but don't have the
scan code in question, we don't find the key in the table and thus we
ignore it again.
--
Krzysztof Halasa
Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
>> The removal of the existing keymaps from kernel depends on having an
>> application
>> to be called from udev to load the proper keymaps when a device is probed.
>>
>> After having it for a while, we should deprecate the in-kernel keymaps
>> and move them to userspace.
>
> Sounds like a plan.
>
>> I also think that it is important to remove the 7 bits limitation from
>> all drivers
>> and re-generate the keymaps, since they'll change after it.
>
> I think the existing space/mark media drivers need to be reworked
> completely.
Nah. the changes aren't big. The first part of the change were already done
for 2.6.32: instead of having a vector of 128 elements, where the element order
used to be the masked scancode, we now have a table of scancode x keycode, defined
as:
struct ir_scancode {
u16 scancode;
u32 keycode;
};
Changing scancode to u32 is as easy as edit a file - it is currently 16 just because
all currently supported IR's and protocols have 16 bits only - there's no in-kernel
implementation for RC6 mode 6 yet. However, increasing it above to 64 bits will break on
32 bits kernels (and above 64 bits, on all architectures), due to the current API limits.
this change is currently limited to the ir keytables, but I have a patch already done
extending this change for the drivers to work directly with the new table.
The next step is to replace the ir->mask_keycode at the drivers to a value that
gets the entire scancode. We may still need a mask there, since not all drivers output
a 32 bits scancode.
Also, there's no single "space/mark" media driver. All drivers that support
pulse/space also support in-hardware IR decoding, in order to support the
different types of devices. They generally support several ways to get keys:
- serial pulse/space decoding on one GPIO pin (most pci hardware have);
- serial pulse/space decoding via a IRQ enabled GPIO pin (several saa7134 IR's use this way);
- i2c IR's (common on several popular devices);
- parallel scancode output via gpio pins several cx88 IR's use this way);
- direct IR hardware decoding done by the video chipset
(DibCom and newer em28xx hardware, for example).
So, the driver input complexity is needed to support all those different ways.
So, rewriting it would likely cause regressions.
I agree that there are some cleanups that should be done for the serial pulse/space raw
decoding. By adding a lirc interface, we'll need to have a common code for handling
those events anyway.
Cheers,
Mauro.
On Nov 26, 2009, at 9:46 AM, Krzysztof Halasa <[email protected]> wrote:
> Dmitry Torokhov <[email protected]> writes:
>
>> In what way the key interface is unsufficient for delivering button
>> events?
>
> At present: 128 different keys only (RC5: one group).
Where did this limitation come from? We have more than 256 keycodes
already _defined_ in the input core and we can add more if needed.
> One remote per
> device only.
Why would you want more? One physical device usually corresponds to a
logical device. If you have 2 remotes create 2 devices.
> The protocol itself doesn't have the above limitations, but has
> others,
> with are acceptable for key input.
> --
> Krzysztof Halasa
--
Dmitry
Hi Mauro,
on 26 Nov 09 at 18:59, Mauro Carvalho Chehab wrote:
> Christoph Bartelmus wrote:
[...]
>>> lircd supports input layer interface. Yet, patch 3/3 exports both devices
>>> that support only pulse/space raw mode and devices that generate scan
>>> codes via the raw mode interface. It does it by generating artificial
>>> pulse codes.
>>
>> Nonsense! There's no generation of artificial pulse codes in the drivers.
>> The LIRC interface includes ways to pass decoded IR codes of arbitrary
>> length to userspace.
> I might have got wrong then a comment in the middle of the
> imon_incoming_packet() of the SoundGraph iMON IR patch:
Indeed, you got it wrong.
As I already explained before, this device samples the signal at a
constant rate and delivers the current level in a bit-array. This data is
then condensed to pulse/space data.
Christoph
Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
>> No. All the other API functions there work with 32 bits for scancodes.
>
> We don't need them, do we? We need a new ioctl for changing key mappings
> anyway (a single ioctl for setting the whole table I think), and we can
> have arbitrary length of scan codes there.
Why do you want to replace everything into a single shot? Had you ever tried
to replace a scancode table with the current API?
$ wc ./keycodes/dib0700_rc_keys
216 432 3541 ./keycodes/dib0700_rc_keys
This is the biggest table we have: 216 scancodes. It has codes for several
different IR's bound together into the same table.
Let's replace the entire table (tested on a dib8076 reference design device):
$ time ./keytable ./keycodes/dib0700_rc_keys
real 0m0.029s
user 0m0.000s
sys 0m0.027s
Don't you think that 29ms to replace 216 codes to be fast enough, especially since
you only need to do it once after plugging a device?
Also, if you want to control your device with two different IR controllers, the better
is to allow adding new keycodes there, instead of just allowing the replacement
of the entire table.
Maybe we'll need some extensions there, for example to extend the size of the dynamic
table, but I don't see any timing issue here.
Cheers,
Mauro
Christoph Bartelmus wrote:
> Hi Mauro,
>
> on 26 Nov 09 at 18:59, Mauro Carvalho Chehab wrote:
>> Christoph Bartelmus wrote:
> [...]
>>>> lircd supports input layer interface. Yet, patch 3/3 exports both devices
>>>> that support only pulse/space raw mode and devices that generate scan
>>>> codes via the raw mode interface. It does it by generating artificial
>>>> pulse codes.
>>> Nonsense! There's no generation of artificial pulse codes in the drivers.
>>> The LIRC interface includes ways to pass decoded IR codes of arbitrary
>>> length to userspace.
>
>> I might have got wrong then a comment in the middle of the
>> imon_incoming_packet() of the SoundGraph iMON IR patch:
>
> Indeed, you got it wrong.
> As I already explained before, this device samples the signal at a
> constant rate and delivers the current level in a bit-array. This data is
> then condensed to pulse/space data.
Ah, ok. It is now clear to me.
IMHO, it would be better to explain this at the source code, since the
imon_incoming_packet() is a little complex.
It would help the review process if those big routines could be broken into
a few functions. While this improves code readability, it shouldn't
affect performance, as gcc will handle the static functions used only once
as inline.
> Christoph
Cheers,
Mauro.
On Thu, 26 Nov 2009, Mauro Carvalho Chehab wrote:
> >> See above. Also, several protocols have a way to check if a keystroke were
> >> properly received. When handling just one protocol, we can use this to double
> >> check the key. However, on a multiprotocol mode, we'll need to disable this
> >> feature.
> >
> > I don't think so. We can pass the space/mark data to all (configured,
> > i.e. with active mapping) protocol handlers at once. Should a check
> > fail, we ignore the data. Perhaps another protocol will make some sense
> > out of it.
>
> What happens if it succeeds on two protocol handlers?
Then you use the protocol that fits best. For instance decoding with one
protocol might produce a scancode that isn't assigned to any key, while
another protocol produces an assigned scancode. Clearly then the latter is
most likely to be correct. It also possible to have a space/mark length
that is within the allowable tolerances for one remote, but is even closer
another remote. You don't want to just find *a* match, you want to find
the *best* match.
The in kernel code in v4l is very simple in that it is only designed to
work with one procotol and one remote. Once you have multiple remotes of
any type things become much more complicted. Keep in mind that remotes
that aren't even intended to be used with the computer but are used in the
same room will still be received by the receiver. It's not enough to
decode the signals you expect to receive, you must also not get confused by
random signals destined for somewhere else.
On Thu, 26 Nov 2009, Mauro Carvalho Chehab wrote:
> >> lircd supports input layer interface. Yet, patch 3/3 exports both devices
> >> that support only pulse/space raw mode and devices that generate scan
> >> codes via the raw mode interface. It does it by generating artificial
> >> pulse codes.
> >
> > Nonsense! There's no generation of artificial pulse codes in the drivers.
> > The LIRC interface includes ways to pass decoded IR codes of arbitrary
> > length to userspace.
>
> I might have got wrong then a comment in the middle of the
> imon_incoming_packet() of the SoundGraph iMON IR patch:
>
> + /*
> + * Translate received data to pulse and space lengths.
> + * Received data is active low, i.e. pulses are 0 and
> + * spaces are 1.
I'm not sure about this specific code, but what is likely
going on here is the waveform is being RLE encoding.
For example, a cx88 receiver has two ways of being connected (without
using an external decoder chip). One generates an IRQ on each
edge of the signal. The time between IRQs gives mark/space lengths
which is what lirc expects. This is how a simple serial port receiver
works too.
Another connections effectivly samples the waveform one bit deep at IIRC
4kHz. I think that's what the code you are looking at gets. The code
extracts the edges from the waveform and returns the time between them. In
effect one is run length encoding a sequence of bits.
On Thu, Nov 26, 2009 at 07:05:01PM -0200, Mauro Carvalho Chehab wrote:
>
> For example, the two ioctls to replace a scancode x key code are defined as:
>
> #define EVIOCGKEYCODE _IOR('E', 0x04, int[2]) /* get keycode */
> #define EVIOCSKEYCODE _IOW('E', 0x04, int[2]) /* set keycode */
>
> We need to better analyze the API to see how this can be extended to
> allow bigger widths.
>
> (what's worse is that it is defined as "int" instead of "u32" - so the number
> of bits is different on 32 and on 64 systems)
>
Not really, int is 32 bits on both, longs the ones that differ.
--
Dmitry
On Thu, Nov 26, 2009 at 10:27:08PM +0100, Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
> > No. All the other API functions there work with 32 bits for scancodes.
>
> We don't need them, do we? We need a new ioctl for changing key mappings
> anyway (a single ioctl for setting the whole table I think), and we can
> have arbitrary length of scan codes there.
Unless we determine that we 100% need bigger size of scancode then the
current ioctls are just fine. Why do we _need_ an ioctl to load the whole
tabe? Are you concerned about speed with which the keymap is populated?
I don't think it would be an issue.
--
Dmitry
On Thu, Nov 26, 2009 at 01:16:01AM -0500, Jarod Wilson wrote:
> On Nov 26, 2009, at 12:31 AM, Dmitry Torokhov wrote:
>
> > On Mon, Nov 23, 2009 at 11:37:53PM -0500, Jarod Wilson wrote:
> >> On 11/23/2009 12:37 PM, Dmitry Torokhov wrote:
> >>> On Mon, Nov 23, 2009 at 03:14:56PM +0100, Krzysztof Halasa wrote:
> >>>> Mauro Carvalho Chehab<[email protected]> writes:
> >>>>
> >>>>> Event input has the advantage that the keystrokes will provide an unique
> >>>>> representation that is independent of the device.
> >>>>
> >>>> This can hardly work as the only means, the remotes have different keys,
> >>>> the user almost always has to provide customized key<>function mapping.
> >>>>
> >>>
> >>> Is it true? I would expect the remotes to have most of the keys to have
> >>> well-defined meanings (unless it is one of the programmable remotes)...
> >>
> >> Its the cases like programmable universal remotes that really throw
> >> things for a loop. That, and people wanting to use random remote X that
> >> came with the amp or tv or set top box, with IR receiver Y.
> >
> > Right, but still the keys usually do have the well-defined meaning,
>
> Except when they don't. I have two very similar remotes, one that was bundled with a system from CaptiveWorks, and one that was bundled with an Antec Veris IR/LCD (SoundGraph iMON rebrand). Outside of the Antec remote having a mouse pad instead of up/down/left/right/enter, they have an identical layout, and the keys in the same locations on the remotes send the same IR signal. But the button names vary a LOT between the two. So on the DVD key on the Antec and the MUTE key on the CW send the same signal. Same with Audio vs. Eject, TV vs. History, etc. Moral of the story is that not all IR protocols spell things out particularly well for what a given code should actually mean.
I guess we are talking about different things. While the 2 remotes may
use different protocols to communicate and may use the same codes to
mean different things they buttons have well-defined meaning and we
could map that to input keycodes. Then what is left is to load the
proper mapping for particular device into the kernel. This can be done
either automatically (when we know the mapping) or with the help of the
user (owner of the system).
>
> > teh
> > issue is in mapping raw code to the appropriate keycode. This can be
> > done either by lirc config file (when lirc is used) or by some other
> > means.
>
> The desire to map a button press to multiple keystrokes isn't uncommon either, though I presume that's doable within the input layer context too.
No, at present we expect 1:1 button->event mapping leaving macro
expansion (i.e. KEY_PROG1 -> "do some multi-step sequence" to
userspace).
--
Dmitry
On Thu, Nov 26, 2009 at 07:40:01PM +0100, Krzysztof Halasa wrote:
> Dmitry Torokhov <[email protected]> writes:
>
> > Why would sysfs write be slower than ioctl?
>
> Sysfs is generally one-value, one-file. open, read/write, close.
> ioctl() OTOH does everything (e.g. a whole key table) in one syscall.
There are binary sysfs attributes. For ioctl you also need to open and
close the device. Plus, how often do you expect to perform this
operation? Don't you think you are trying to optimize something that
does not have any real performavnce impact here?
--
Dmitry
On Wed, Nov 25, 2009 at 10:58:29PM +0100, Gerd Hoffmann wrote:
>
> (1) ir code (say rc5) -> keycode conversion looses information.
>
> I think this can easily be addressed by adding a IR event type to the
> input layer, which could look like this:
>
> input_event->type = EV_IR
> input_event->code = IR_RC5
> input_event->value = <rc5 value>
>
> In case the 32bit value is too small we might want send two events
> instead, with ->code being set to IR_<code>_1 and IR_<code>_2
>
> Advantages:
> * Applications (including lircd) can get access to the unmodified
> rc5/rc6/... codes.
> * All the ir-code -> keycode mapping magic can be handled by the
> core input layer then. All the driver needs to do is to pass on
> the information which keymap should be loaded by default (for the
> bundled remote if any). The configuration can happen in userspace
> (sysfs attribute + udev + small utility in tools/ir/).
> * lirc drivers which get ir codes from the hardware can be converted
> to pure input layer drivers without regressions. lircd is not
> required any more.
>
I think we need to separate 2 kinds of applications since they have
different requirements as far as interface goes:
1. "Reguilar" user-space applications interested in receiving keystrokes
from user and reacting to them. Movie players, CD players, MythTV-like
applications and so on. Those, to my understanding, are not concerned
with the fine details of RC5, RC6, NEC and so forth protocol decoding
and just want to know when to start playing, when to stop and when to
revind. That class of applications is best served by current input layer
since it unifies data coming from IR, keyboards, button devices and so
forth.
2. "System" applications that are interested in protocol decoding. Those
need interface best suited for IR and nothing else. This protocol is
appears is better kept separate from the evdev input protocol. In case
where we rely solely on such userspace application(s) to perform protocol
decoding we should route input events back to kernel through uinput for
consumption by "class 1" applications.
We use this approach for PS/2 (serio allows binding either psmouse/atkbd
or serio_raw to provide alternate interfaces depending on the users
need), USB hid allows raw access as well, maybe we should follow the
suit here.
--
Dmitry
On Thu, Nov 26, 2009 at 03:49:13PM -0200, Mauro Carvalho Chehab wrote:
>
> Dmitry,
>
> While lirc is basically a series of input drivers, considering that they have lots
> in common with the input drivers at V4L/DVB and that we'll need to work on
> some glue to merge both, do you mind if I add the lirc drivers at drivers/staging from
> my trees?
>
Mauro,
I would not mind if you will be pushing it to staging, however I am not
sure we have an agreement on what exactly the interface that we will be
using. I would hate to get something in that will need to be reworked
again.
Thanks.
--
Dmitry
Dmitry Torokhov <[email protected]> writes:
>> One remote per
>> device only.
>
> Why would you want more? One physical device usually corresponds to a
> logical device. If you have 2 remotes create 2 devices.
I meant "per receiver device".
--
Krzysztof Halasa
Mauro Carvalho Chehab <[email protected]> writes:
> Why do you want to replace everything into a single shot?
Why not? It seems simpler to me. We need to change this anyway.
If we change the whole table in a single ioctl, we can easily enumerate
protocols requested and enable then selectively.
But I think it's a minor implementation decision and we don't need to
look at it at this time.
--
Krzysztof Halasa
On Fri, Nov 27, 2009 at 01:13:51AM +0100, Krzysztof Halasa wrote:
> Dmitry Torokhov <[email protected]> writes:
>
> >> One remote per
> >> device only.
> >
> > Why would you want more? One physical device usually corresponds to a
> > logical device. If you have 2 remotes create 2 devices.
>
> I meant "per receiver device".
There is nothing in input layer that precludes you from creating
multiple input devices per *whatever*. Please, when you are talking
about limitations, specify whether those limitations are applicable to
the input layer, the current implementation of IR in DVB or something
else.
Thanks.
--
Dmitry
Dmitry Torokhov <[email protected]> writes:
> There are binary sysfs attributes.
Aren't they to be used for things like ROMs and EEPROMs exclusively?
> For ioctl you also need to open and
> close the device.
Sure, but I do it once.
> Plus, how often do you expect to perform this
> operation? Don't you think you are trying to optimize something that
> does not have any real performavnce impact here?
Maybe, anyway it will have to work before it's included in the kernel,
so I don't worry too much about it. Perhaps we should then merge the
lirc patches so both driver sets can be improved?
--
Krzysztof Halasa
On Friday 27 November 2009 00:19:44 Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>
> > Why do you want to replace everything into a single shot?
>
> Why not? It seems simpler to me. We need to change this anyway.
ioctls with a variable argument length are a pain for 32 bit
emulation and stuff like strace. You either need to encode
the variable length into the ioctl cmd, making it variable
as well, or use a pointer in the data structure, which requires
conversion.
Ideally, ioctl arguments have a constant layout, no pointers
and are at most 64 bits long.
Arnd <><
Dmitry Torokhov <[email protected]> writes:
> There is nothing in input layer that precludes you from creating
> multiple input devices per *whatever*.
Of course. I though it was obvious I mean present situation with the
media drivers but I can see now it was far from being obvious.
--
Krzysztof Halasa
Trent Piepho <[email protected]> writes:
> Then you use the protocol that fits best. For instance decoding with one
> protocol might produce a scancode that isn't assigned to any key, while
> another protocol produces an assigned scancode. Clearly then the latter is
> most likely to be correct.
Right.
> It also possible to have a space/mark length
> that is within the allowable tolerances for one remote, but is even closer
> another remote. You don't want to just find *a* match, you want to find
> the *best* match.
That won't work, the decoders don't calculate quality. And even if they
did, if you have two remotes generating the same e.g. RC5 code, you
won't be able to differentiate between them. Your TV etc. won't do that
either.
> The in kernel code in v4l is very simple in that it is only designed to
> work with one procotol and one remote. Once you have multiple remotes of
> any type things become much more complicted.
If you're using them at once, sure :-)
> Keep in mind that remotes
> that aren't even intended to be used with the computer but are used in the
> same room will still be received by the receiver. It's not enough to
> decode the signals you expect to receive, you must also not get confused by
> random signals destined for somewhere else.
This is usually not a problem. My experience is the decoding is very
reliable.
--
Krzysztof Halasa
Dmitry Torokhov wrote:
> On Thu, Nov 26, 2009 at 03:49:13PM -0200, Mauro Carvalho Chehab wrote:
>> Dmitry,
>>
>> While lirc is basically a series of input drivers, considering that they have lots
>> in common with the input drivers at V4L/DVB and that we'll need to work on
>> some glue to merge both, do you mind if I add the lirc drivers at drivers/staging from
>> my trees?
>>
>
> Mauro,
>
> I would not mind if you will be pushing it to staging, however I am not
> sure we have an agreement on what exactly the interface that we will be
> using. I would hate to get something in that will need to be reworked
> again.
I understand your concerns.
IMHO, we should be really careful with API's when migrating from staging to the
right place, but I'm not that much concerned with staging. We already have several
drivers there with bad behaviors and even with some API's there that will go to /dev/null.
For example there's a V4L2 driver there (staging/go7007) that has their own private
API to handle compressed streams. I won't ack moving it from staging while
it has their own private extensions for something that are part of V4L2 API.
Also, staging drivers without progress for a few kernel cycles will be moved to /dev/null,
so I don't see much sense of denying a driver to go there.
Anyway, I'll add it there only when you feel comfortable about that and send us your ack.
-
>From what I heard on the comments, I think we have already a consensus of some points:
1) all IR's should implement the standard evdev interface;
2) IR's with raw interfaces will implement a raw pulse/space IR interface.
The proposal is to use lirc API interface for raw pulse/code TX and RX.
Do you think we'll need to better detail the IR raw interface API before accepting
the patches for staging? If so, what level of details do you want?
Cheers,
Mauro.
On 11/26/2009 06:23 PM, Dmitry Torokhov wrote:
> On Thu, Nov 26, 2009 at 01:16:01AM -0500, Jarod Wilson wrote:
>> On Nov 26, 2009, at 12:31 AM, Dmitry Torokhov wrote:
>>
>>> On Mon, Nov 23, 2009 at 11:37:53PM -0500, Jarod Wilson wrote:
>>>> On 11/23/2009 12:37 PM, Dmitry Torokhov wrote:
>>>>> On Mon, Nov 23, 2009 at 03:14:56PM +0100, Krzysztof Halasa wrote:
>>>>>> Mauro Carvalho Chehab<[email protected]> writes:
>>>>>>
>>>>>>> Event input has the advantage that the keystrokes will provide an unique
>>>>>>> representation that is independent of the device.
>>>>>>
>>>>>> This can hardly work as the only means, the remotes have different keys,
>>>>>> the user almost always has to provide customized key<>function mapping.
>>>>>>
>>>>>
>>>>> Is it true? I would expect the remotes to have most of the keys to have
>>>>> well-defined meanings (unless it is one of the programmable remotes)...
>>>>
>>>> Its the cases like programmable universal remotes that really throw
>>>> things for a loop. That, and people wanting to use random remote X that
>>>> came with the amp or tv or set top box, with IR receiver Y.
>>>
>>> Right, but still the keys usually do have the well-defined meaning,
>>
>> Except when they don't. I have two very similar remotes, one that was bundled with a system from CaptiveWorks, and one that was bundled with an Antec Veris IR/LCD (SoundGraph iMON rebrand). Outside of the Antec remote having a mouse pad instead of up/down/left/right/enter, they have an identical layout, and the keys in the same locations on the remotes send the same IR signal. But the button names vary a LOT between the two. So on the DVD key on the Antec and the MUTE key on the CW send the same signal. Same with Audio vs. Eject, TV vs. History, etc. Moral of the story is that not all IR protocols spell things out particularly well for what a given code should actually mean.
>
> I guess we are talking about different things. While the 2 remotes may
> use different protocols to communicate
The remotes use the exact same protocol. Their respective bundled
receivers however, do translate key presses differently. Perhaps this is
a bad example though, because both of these remotes came with receivers
that do onboard decoding. But there's nothing stopping me from wanting
to use either of these remotes with an mceusb IR transceiver.
> and may use the same codes to
> mean different things they buttons have well-defined meaning and we
> could map that to input keycodes. Then what is left is to load the
> proper mapping for particular device into the kernel.
In this case, its not the device, but the remote, that we need a
different mapping for.
> This can be done
> either automatically (when we know the mapping) or with the help of the
> user (owner of the system).
Yep, that'd work. Just trying to illustrate that the same code doesn't
always mean anywhere near the same thing from one remote to another.
>>> teh
>>> issue is in mapping raw code to the appropriate keycode. This can be
>>> done either by lirc config file (when lirc is used) or by some other
>>> means.
>>
>> The desire to map a button press to multiple keystrokes isn't uncommon either, though I presume that's doable within the input layer context too.
>
> No, at present we expect 1:1 button->event mapping leaving macro
> expansion (i.e. KEY_PROG1 -> "do some multi-step sequence" to
> userspace).
Hm. So ctrl-x, alt-tab, etc. would have to be faked in userspace
somehow. Bummer.
--
Jarod Wilson
[email protected]
Am Donnerstag, den 26.11.2009, 14:59 -0800 schrieb Trent Piepho:
> On Thu, 26 Nov 2009, Mauro Carvalho Chehab wrote:
> > >> See above. Also, several protocols have a way to check if a keystroke were
> > >> properly received. When handling just one protocol, we can use this to double
> > >> check the key. However, on a multiprotocol mode, we'll need to disable this
> > >> feature.
> > >
> > > I don't think so. We can pass the space/mark data to all (configured,
> > > i.e. with active mapping) protocol handlers at once. Should a check
> > > fail, we ignore the data. Perhaps another protocol will make some sense
> > > out of it.
> >
> > What happens if it succeeds on two protocol handlers?
>
> Then you use the protocol that fits best. For instance decoding with one
> protocol might produce a scancode that isn't assigned to any key, while
> another protocol produces an assigned scancode. Clearly then the latter is
> most likely to be correct. It also possible to have a space/mark length
> that is within the allowable tolerances for one remote, but is even closer
> another remote. You don't want to just find *a* match, you want to find
> the *best* match.
>
> The in kernel code in v4l is very simple in that it is only designed to
> work with one procotol and one remote. Once you have multiple remotes of
> any type things become much more complicted. Keep in mind that remotes
> that aren't even intended to be used with the computer but are used in the
> same room will still be received by the receiver. It's not enough to
> decode the signals you expect to receive, you must also not get confused by
> random signals destined for somewhere else.
Giving some random living room these days, likely open to the kids
rooms, you have to take that into account.
Another point, if decoding from IRQs generated by the remote, there is
flawed hardware around, needing to poll IRQs in some timely manner to
get it to something at all.
This will break such remotes. Never seen?
For me the first priority is, that existing remotes are not broken.
Don't tell you have done a nice job just now, but are unfortunately in
need of testers ...
Cheers,
Hermann
On Thu, Nov 26, 2009 at 9:28 PM, Jarod Wilson <[email protected]> wrote:
>> No, at present we expect 1:1 button->event mapping leaving macro
>> expansion (i.e. KEY_PROG1 -> ?"do some multi-step sequence" to
>> userspace).
>
> Hm. So ctrl-x, alt-tab, etc. would have to be faked in userspace somehow.
> Bummer.
That is scripting. Scripting always needs to be done in user space.
In the code I posted there is one evdev device for each configured
remote. Mapped single keycodes are presented on these devices for each
IR burst. There is no device for the IR receiver. A LIRC type process
could watch these devices and then execute scripts based on the
keycodes reported.
The configfs model is very flexible. You could make a "remote" that
translates the UP/DOWN buttons of several different remotes into
KEY_UP/DOWN. That lets several different remotes control the same
app.
Sure it is clunky to play with IR hex codes and keycodes in the
configfs mapping dir. If you don't like it write a GUI app for
manipulating the codes. GUI would then generate a script for udev to
run which builds the configfs entries.
Maybe I should rename those directory entries to "app" instead of
"remote". They contain the mappings from IR hex codes to keycodes that
an app is interested in. Usually there is a 1:1 correspondence between
remote and app but there doesn't have to be.
--
Jon Smirl
[email protected]
On Thu, Nov 26, 2009 at 09:28:51PM -0500, Jarod Wilson wrote:
> On 11/26/2009 06:23 PM, Dmitry Torokhov wrote:
>> On Thu, Nov 26, 2009 at 01:16:01AM -0500, Jarod Wilson wrote:
>>> On Nov 26, 2009, at 12:31 AM, Dmitry Torokhov wrote:
>>>
>>>> On Mon, Nov 23, 2009 at 11:37:53PM -0500, Jarod Wilson wrote:
>>>>> On 11/23/2009 12:37 PM, Dmitry Torokhov wrote:
>>>>>> On Mon, Nov 23, 2009 at 03:14:56PM +0100, Krzysztof Halasa wrote:
>>>>>>> Mauro Carvalho Chehab<[email protected]> writes:
>>>>>>>
>>>>>>>> Event input has the advantage that the keystrokes will provide an unique
>>>>>>>> representation that is independent of the device.
>>>>>>>
>>>>>>> This can hardly work as the only means, the remotes have different keys,
>>>>>>> the user almost always has to provide customized key<>function mapping.
>>>>>>>
>>>>>>
>>>>>> Is it true? I would expect the remotes to have most of the keys to have
>>>>>> well-defined meanings (unless it is one of the programmable remotes)...
>>>>>
>>>>> Its the cases like programmable universal remotes that really throw
>>>>> things for a loop. That, and people wanting to use random remote X that
>>>>> came with the amp or tv or set top box, with IR receiver Y.
>>>>
>>>> Right, but still the keys usually do have the well-defined meaning,
>>>
>>> Except when they don't. I have two very similar remotes, one that was bundled with a system from CaptiveWorks, and one that was bundled with an Antec Veris IR/LCD (SoundGraph iMON rebrand). Outside of the Antec remote having a mouse pad instead of up/down/left/right/enter, they have an identical layout, and the keys in the same locations on the remotes send the same IR signal. But the button names vary a LOT between the two. So on the DVD key on the Antec and the MUTE key on the CW send the same signal. Same with Audio vs. Eject, TV vs. History, etc. Moral of the story is that not all IR protocols spell things out particularly well for what a given code should actually mean.
>>
>> I guess we are talking about different things. While the 2 remotes may
>> use different protocols to communicate
>
> The remotes use the exact same protocol. Their respective bundled
> receivers however, do translate key presses differently. Perhaps this is
> a bad example though, because both of these remotes came with receivers
> that do onboard decoding. But there's nothing stopping me from wanting
> to use either of these remotes with an mceusb IR transceiver.
>
>> and may use the same codes to
>> mean different things they buttons have well-defined meaning and we
>> could map that to input keycodes. Then what is left is to load the
>> proper mapping for particular device into the kernel.
>
> In this case, its not the device, but the remote, that we need a
> different mapping for.
I would say that the remote is the device, not the receiver...
>
>> This can be done
>> either automatically (when we know the mapping) or with the help of the
>> user (owner of the system).
>
> Yep, that'd work. Just trying to illustrate that the same code doesn't
> always mean anywhere near the same thing from one remote to another.
We have the same scenatio with atkbd and various laptops - the
"extended" keys may use the same scancodes for different keys and we use
DMI data to load the proper keymap. Obviously in case if IRC we won't be
using DMI but something else.
>
>>>> teh
>>>> issue is in mapping raw code to the appropriate keycode. This can be
>>>> done either by lirc config file (when lirc is used) or by some other
>>>> means.
>>>
>>> The desire to map a button press to multiple keystrokes isn't uncommon either, though I presume that's doable within the input layer context too.
>>
>> No, at present we expect 1:1 button->event mapping leaving macro
>> expansion (i.e. KEY_PROG1 -> "do some multi-step sequence" to
>> userspace).
>
> Hm. So ctrl-x, alt-tab, etc. would have to be faked in userspace
> somehow. Bummer.
>
What is Ctrl-x? Alt-tab? This are application-specific binding and of
course kernel does not emit these. If there is a distinct action that
needs to be signalled then there [normally] is a keycode for it.
--
Dmitry
On Thu, Nov 26, 2009 at 10:08:29PM -0500, Jon Smirl wrote:
> On Thu, Nov 26, 2009 at 9:28 PM, Jarod Wilson <[email protected]> wrote:
> >> No, at present we expect 1:1 button->event mapping leaving macro
> >> expansion (i.e. KEY_PROG1 -> ?"do some multi-step sequence" to
> >> userspace).
> >
> > Hm. So ctrl-x, alt-tab, etc. would have to be faked in userspace somehow.
> > Bummer.
>
> That is scripting. Scripting always needs to be done in user space.
>
> In the code I posted there is one evdev device for each configured
> remote. Mapped single keycodes are presented on these devices for each
> IR burst. There is no device for the IR receiver. A LIRC type process
> could watch these devices and then execute scripts based on the
> keycodes reported.
>
> The configfs model is very flexible. You could make a "remote" that
> translates the UP/DOWN buttons of several different remotes into
> KEY_UP/DOWN. That lets several different remotes control the same
> app.
>
> Sure it is clunky to play with IR hex codes and keycodes in the
> configfs mapping dir. If you don't like it write a GUI app for
> manipulating the codes. GUI would then generate a script for udev to
> run which builds the configfs entries.
>
> Maybe I should rename those directory entries to "app" instead of
> "remote". They contain the mappings from IR hex codes to keycodes that
> an app is interested in. Usually there is a 1:1 correspondence between
> remote and app but there doesn't have to be.
>
Maybe we should revisit Jon's patchset as well. Regretfully I did not
have time to do that when it was submitted the last time.
--
Dmitry
On Thu, Nov 26, 2009 at 11:33 PM, Dmitry Torokhov
<[email protected]> wrote:
>> In the code I posted there is one evdev device for each configured
>> remote. Mapped single keycodes are presented on these devices for each
>> IR burst. There is no device for the IR receiver. ?A LIRC type process
>> could watch these devices and then execute scripts based on the
>> keycodes reported.
>>
...
>
> Maybe we should revisit Jon's patchset as well. Regretfully I did not
> have time to do that when it was submitted the last time.
Consider my patch set a technology demo starting point. It shows a
modern architecture for integrating IR into evdev. Use the input from
everyone else to turn these concepts into a real design. I wrote the
code for the fun of it, I have no commercial interest in IR. I was
annoyed with how LIRC handled Sony remotes on my home system.
The design is a clean slate implementation of IR for the kernel. No
attempt was made at legacy compatibility. I was familiar with evdev vs
/dev/mouse problems from my work on the X server. Because of working
on X I've also always hated keymaps (that's what drove the configfs
design).
I wish one of the set top box or TV manufacturers would step up and
own this. They are the ones that would benefit the most. Jarod would
probably be open to some consulting, right?
--
Jon Smirl
[email protected]
Hi Jon,
on 27 Nov 09 at 00:06, Jon Smirl wrote:
[...]
> code for the fun of it, I have no commercial interest in IR. I was
> annoyed with how LIRC handled Sony remotes on my home system.
Can you elaborate on this?
I'm not aware of any issue with Sony remotes.
Christoph
Hi Mauro,
on 26 Nov 09 at 14:25, Mauro Carvalho Chehab wrote:
> Christoph Bartelmus wrote:
[...]
>> But I'm still a bit hesitant about the in-kernel decoding. Maybe it's just
>> because I'm not familiar at all with input layer toolset.
[...]
> I hope it helps for you to better understand how this works.
So the plan is to have two ways of using IR in the future which are
incompatible to each other, the feature-set of one being a subset of the
other?
When designing the key mapping in the kernel you should be aware that
there are remotes out there that send a sequence of scan codes for some
buttons, e.g.
http://lirc.sourceforge.net/remotes/pioneer/CU-VSX159
Christoph
On Fri, Nov 27, 2009 at 2:33 AM, Christoph Bartelmus <[email protected]> wrote:
> Hi Jon,
>
> on 27 Nov 09 at 00:06, Jon Smirl wrote:
> [...]
>> code for the fun of it, I have no commercial interest in IR. I was
>> annoyed with how LIRC handled Sony remotes on my home system.
>
> Can you elaborate on this?
> I'm not aware of any issue with Sony remotes.
irrecord can't figure out that Sony remotes transmit multiple
protocols so it reverts to raw mode. When trying to figure that out I
started working on the concept of running simultaneous state machines
to decode the pulse timings. I also had an embedded system with an IR
receiver hooked to a timer input pin. I started off with a
implementation that ran multiple Sony protocol decoders and used the
input from the timer pin. I know now that I could use irrecord
individually for each group of keys on the Sony remote and then glue
the flies together. But that's the path that caused me to write the
code.
Also throw into pot that I had previously had some very bad
experiences trying to deal with the old mouse and kbd device inside of
the X server. I was aware that evdev was designed to fix all of those
problems. That made me want a fully evdev based design.
>
> Christoph
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
--
Jon Smirl
[email protected]
Em Thu, 26 Nov 2009 17:06:03 -0200
Mauro Carvalho Chehab <[email protected]> escreveu:
> Krzysztof Halasa wrote:
> > Mauro Carvalho Chehab <[email protected]> writes:
> >
> >> Technically, it is not hard to port this solution to the other
> >> drivers, but the issue is that we don't have all those IR's to know
> >> what is the complete scancode that each key produces. So, the hardest
> >> part is to find a way for doing it without causing regressions, and to
> >> find a group of people that will help testing the new way.
> >
> > We don't want to "port it" to other drivers. We need to have a common
> > module which does all RCx decoding. The individual drivers should be as
> > simple as possible, something that I outlined in a previous mail.
>
> With the current 7bits mask applied to almost all devices, it is probably not very
> useful for those who want to use generic IRs. We really need to port the solution
> we've done on dvb-usb to the other drivers, allowing them to have the entire
> scancode at the tables while keep supporting table replacement.
>
> The issue is that we currently have only 7bits of the scan codes produced by the IR's.
> So, we need to re-generate the keycode tables for each IR after the changes got applied.
Ok, I got some time to add support for tables with the full scan codes at the V4L drivers.
In order to not break all tables, I've confined the changes to just one device (HVR-950,
at the em28xx driver). The patches were already committed at the -hg development tree.
In order to support tables with the full scan codes, all that is needed is to add the
RC5 address + RC5 data when calling ir_input_keydown. So, the change is as simple as:
- ir_input_keydown(ir->input, &ir->ir,
- poll_result.rc_data[0]);
+ ir_input_keydown(ir->input, &ir->ir,
+ poll_result.rc_address << 8 |
+ poll_result.rc_data[0]);
+ else
An example of such patch can be seen at:
http://linuxtv.org/hg/v4l-dvb/rev/9c38704cfd56
There are still some work to do, since, currently, the drivers will use a table with a fixed
size. So, you can replace the current values, but it is not possible to add new keys.
The fix for it is simple, but we need to think what would be the better way for it. There are
two alternatives:
- A table with a fixed size (like 128 or 256 entries - maybe a modprobe parameter
could be used to change its size);
- some way to increase/reduce the table size. In this case, we'll likely need some
ioctl for it.
--
Cheers,
Mauro
On Sat, Nov 28, 2009 at 12:39:18AM -0200, Mauro Carvalho Chehab wrote:
> Em Thu, 26 Nov 2009 17:06:03 -0200
> Mauro Carvalho Chehab <[email protected]> escreveu:
>
> > Krzysztof Halasa wrote:
> > > Mauro Carvalho Chehab <[email protected]> writes:
> > >
> > >> Technically, it is not hard to port this solution to the other
> > >> drivers, but the issue is that we don't have all those IR's to know
> > >> what is the complete scancode that each key produces. So, the hardest
> > >> part is to find a way for doing it without causing regressions, and to
> > >> find a group of people that will help testing the new way.
> > >
> > > We don't want to "port it" to other drivers. We need to have a common
> > > module which does all RCx decoding. The individual drivers should be as
> > > simple as possible, something that I outlined in a previous mail.
> >
> > With the current 7bits mask applied to almost all devices, it is probably not very
> > useful for those who want to use generic IRs. We really need to port the solution
> > we've done on dvb-usb to the other drivers, allowing them to have the entire
> > scancode at the tables while keep supporting table replacement.
> >
> > The issue is that we currently have only 7bits of the scan codes produced by the IR's.
> > So, we need to re-generate the keycode tables for each IR after the changes got applied.
>
> Ok, I got some time to add support for tables with the full scan codes at the V4L drivers.
> In order to not break all tables, I've confined the changes to just one device (HVR-950,
> at the em28xx driver). The patches were already committed at the -hg development tree.
>
> In order to support tables with the full scan codes, all that is needed is to add the
> RC5 address + RC5 data when calling ir_input_keydown. So, the change is as simple as:
>
> - ir_input_keydown(ir->input, &ir->ir,
> - poll_result.rc_data[0]);
> + ir_input_keydown(ir->input, &ir->ir,
> + poll_result.rc_address << 8 |
> + poll_result.rc_data[0]);
> + else
>
> An example of such patch can be seen at:
> http://linuxtv.org/hg/v4l-dvb/rev/9c38704cfd56
>
> There are still some work to do, since, currently, the drivers will use a table with a fixed
> size. So, you can replace the current values, but it is not possible to add new keys.
>
> The fix for it is simple, but we need to think what would be the better way for it. There are
> two alternatives:
> - A table with a fixed size (like 128 or 256 entries - maybe a modprobe parameter
> could be used to change its size);
> - some way to increase/reduce the table size. In this case, we'll likely need some
> ioctl for it.
>
Hmm, why can't you just resize it when you get EVIOCSKEYCODE for
scancode that would be out of bounds for the current table (if using
table approach)?
--
Dmitry
Dmitry Torokhov wrote:
> On Sat, Nov 28, 2009 at 12:39:18AM -0200, Mauro Carvalho Chehab wrote:
>> Em Thu, 26 Nov 2009 17:06:03 -0200
>> Mauro Carvalho Chehab <[email protected]> escreveu:
>>
>>> Krzysztof Halasa wrote:
>>>> Mauro Carvalho Chehab <[email protected]> writes:
>>>>
>>>>> Technically, it is not hard to port this solution to the other
>>>>> drivers, but the issue is that we don't have all those IR's to know
>>>>> what is the complete scancode that each key produces. So, the hardest
>>>>> part is to find a way for doing it without causing regressions, and to
>>>>> find a group of people that will help testing the new way.
>>>> We don't want to "port it" to other drivers. We need to have a common
>>>> module which does all RCx decoding. The individual drivers should be as
>>>> simple as possible, something that I outlined in a previous mail.
>>> With the current 7bits mask applied to almost all devices, it is probably not very
>>> useful for those who want to use generic IRs. We really need to port the solution
>>> we've done on dvb-usb to the other drivers, allowing them to have the entire
>>> scancode at the tables while keep supporting table replacement.
>>>
>>> The issue is that we currently have only 7bits of the scan codes produced by the IR's.
>>> So, we need to re-generate the keycode tables for each IR after the changes got applied.
>> Ok, I got some time to add support for tables with the full scan codes at the V4L drivers.
>> In order to not break all tables, I've confined the changes to just one device (HVR-950,
>> at the em28xx driver). The patches were already committed at the -hg development tree.
>>
>> In order to support tables with the full scan codes, all that is needed is to add the
>> RC5 address + RC5 data when calling ir_input_keydown. So, the change is as simple as:
>>
>> - ir_input_keydown(ir->input, &ir->ir,
>> - poll_result.rc_data[0]);
>> + ir_input_keydown(ir->input, &ir->ir,
>> + poll_result.rc_address << 8 |
>> + poll_result.rc_data[0]);
>> + else
>>
>> An example of such patch can be seen at:
>> http://linuxtv.org/hg/v4l-dvb/rev/9c38704cfd56
>>
>> There are still some work to do, since, currently, the drivers will use a table with a fixed
>> size. So, you can replace the current values, but it is not possible to add new keys.
>>
>> The fix for it is simple, but we need to think what would be the better way for it. There are
>> two alternatives:
>> - A table with a fixed size (like 128 or 256 entries - maybe a modprobe parameter
>> could be used to change its size);
>> - some way to increase/reduce the table size. In this case, we'll likely need some
>> ioctl for it.
>>
>
> Hmm, why can't you just resize it when you get EVIOCSKEYCODE for
> scancode that would be out of bounds for the current table (if using
> table approach)?
For your reference, the code where EVIOGKEYCODE/EVIOSKEYCODE handling is done is at
this changeset:
http://linuxtv.org/hg/v4l-dvb/rev/21e71d58cd2a
Dynamic resizing can be done, but there are a few different use cases for
someone to touch on the keymaps:
1. People want to change the key assignment for a key at the shipped IR. In this case,
the table won't need to change its size;
2. People want to use the shipped IR, plus a different one. In this case, table size needs
to be extended to store the newer codes;
3. People want to discard the shipped IR and use something else.
Case 3 is the worse scenario. Let's suppose, for example that instead of using a 49 keys
IR, they want to use some programable IR with 55 keys, with different
scancodes. This means that they'll need to delete all 49 scancodes from the old IR
and add 55 new scancodes. As there's no explicit call to delete a scan code, the solution
I found with the current API is to read the current scancode table and replace them with
KEY_UNKNOWN, allowing its re-use (this is what the driver currently does) or deleting
that scancode from the table. After deleting 49 keys, you'll need to add the 55 new keys.
If we do dynamic table resize for each operation, we'll do 104 sequences of kmalloc/kfree
for replacing one table.
IMO, it would be better to have an ioctl to do the keycode table resize. An optional flag
at the ioctl (or a separate one) can be used to ask the driver to clean the current
keymap table and allocate a new one with the specified size.
This will avoid playing with memory allocation for every new key and will provide a simple
way to say to the driver to discard the current keybable, since a new one will be used.
Cheers,
Mauro.
Mauro Carvalho Chehab wrote:
> Dmitry Torokhov wrote:
[scancode-to-keycode map size]
>> Hmm, why can't you just resize it when you get EVIOCSKEYCODE for
>> scancode that would be out of bounds for the current table (if using
>> table approach)?
[...]
> Let's suppose, for example that instead of using a 49 keys
> IR, they want to use some programable IR with 55 keys, with different
> scancodes. This means that they'll need to delete all 49 scancodes from the old IR
> and add 55 new scancodes. As there's no explicit call to delete a scan code, the solution
> I found with the current API is to read the current scancode table and replace them with
> KEY_UNKNOWN, allowing its re-use (this is what the driver currently does) or deleting
> that scancode from the table. After deleting 49 keys, you'll need to add the 55 new keys.
> If we do dynamic table resize for each operation, we'll do 104 sequences of kmalloc/kfree
> for replacing one table.
It is not a performance sensitive task, is it? If you can trade ABI
simplicity for performance (which shouldn't actually matter), that'd be
a better deal.
Besides, some of the necessary kernel-internal house-keeping can also be
deferred until close().
> IMO, it would be better to have an ioctl to do the keycode table resize. An optional flag
> at the ioctl (or a separate one) can be used to ask the driver to clean the current
> keymap table and allocate a new one with the specified size.
> This will avoid playing with memory allocation for every new key and will provide a simple
> way to say to the driver to discard the current keybable, since a new one will be used.
OTOH, an additional "forget all current mappings" ioctl sounds like an
ABI simplification.
--
Stefan Richter
-=====-==--= =-== ===--
http://arcgraph.de/sr/
On Saturday 28 November 2009, Mauro Carvalho Chehab wrote:
> After deleting 49 keys, you'll need to add the 55 new keys.
> If we do dynamic table resize for each operation, we'll do 104
> sequences of kmalloc/kfree for replacing one table.
Given that kmalloc only does power-of-two allocations, you can limit
the resize operations to when you go beyond the current allocation
limit. You can also choose a reasonable minimum table size (e.g. 32
or 64 entries) and avoid resizes for many of the common cases entirely.
Arnd <><
On Nov 27, 2009, at 12:06 AM, Jon Smirl wrote:
> On Thu, Nov 26, 2009 at 11:33 PM, Dmitry Torokhov
> <[email protected]> wrote:
>>> In the code I posted there is one evdev device for each configured
>>> remote. Mapped single keycodes are presented on these devices for each
>>> IR burst. There is no device for the IR receiver. A LIRC type process
>>> could watch these devices and then execute scripts based on the
>>> keycodes reported.
>>>
> ...
>>
>> Maybe we should revisit Jon's patchset as well. Regretfully I did not
>> have time to do that when it was submitted the last time.
>
> Consider my patch set a technology demo starting point. It shows a
> modern architecture for integrating IR into evdev. Use the input from
> everyone else to turn these concepts into a real design. I wrote the
> code for the fun of it, I have no commercial interest in IR. I was
> annoyed with how LIRC handled Sony remotes on my home system.
>
> The design is a clean slate implementation of IR for the kernel. No
> attempt was made at legacy compatibility. I was familiar with evdev vs
> /dev/mouse problems from my work on the X server. Because of working
> on X I've also always hated keymaps (that's what drove the configfs
> design).
>
> I wish one of the set top box or TV manufacturers would step up and
> own this. They are the ones that would benefit the most. Jarod would
> probably be open to some consulting, right?
Mauro may actually have better connections on that front than I do... Thus far, I've only talked to a few vendors of IR devices, with mixed results getting any sort of support out of them. But its on my todo list to put out some feelers on the work front to see if we have any connections that we might be able to utilize.
--
Jarod Wilson
[email protected]
On Nov 26, 2009, at 2:43 PM, Andy Walls wrote:
> On Thu, 2009-11-26 at 12:05 -0200, Mauro Carvalho Chehab wrote:
>> Krzysztof Halasa wrote:
>>> Andy Walls <[email protected]> writes:
>>>
>>>> I would also note that RC-6 Mode 6A, used by most MCE remotes, was
>>>> developed by Philips, but Microsoft has some sort of licensing interest
>>>> in it and it is almost surely encumbered somwhow:
>>>
>>> I don't know about legal problems in some countries but from the
>>> technical POV handling the protocol in the kernel is more efficient
>>> or (/and) simpler.
>>
>> A software licensing from Microsoft won't apply to Linux kernel, so I'm
>> assuming that you're referring to some patent that they could be filled
>> about RC6 mode 6A.
>>
>> I don't know if is there any US patent pending about it (AFAIK, only US
>> accepts software patents), but there are some prior-art for IR key
>> decoding. So, I don't see what "innovation" RC6 would be adding.
>> If it is some new way to transmit waves, the patent issues
>> aren't related to software, and the device manufacturer had already handled
>> it when they made their devices.
>>
>> If it is just a new keytable, this issue
>> could be easily solved by loading the keytable via userspace.
>>
>> Also, assuming that you can use the driver only with a hardware that comes
>> with a licensed software, the user has already the license for using it.
>>
>> Do you have any details on what patents they are claiming?
>
> The US Philips RC-6 patent is US Patent 5,877,702
>
> http://www.google.com/patents?vid=USPAT5877702
>
> Click on download PDF to get a copy of the whole patent.
>
> I am not a lawyer. Philips claims' all appear to tie to a transmitter
> or receiver as part of a system, but most of the claims are about
> information and bit positions and lengths.
...
> IMO, given
>
> a. the dearth of public information about RC-6, indicating someone
> thinks it's their trade secret or intellectual property
>
> b. Microsoft claiming to license something related to the MCE remote
> protocols (which are obviously RC-6 Mode 6A),
>
> c. my inability to draw a "clear, bright line" that RC-6 Mode 6A
> encoding and decoding, as needed by MCE remotes, implemented in software
> doesn't violate anyone's government granted rights to exclusivity.
>
> I think it's much better to implement software RC-6 Mode 6A encoding and
> decoding in user space, doing only the minimum needed to get the
> hardware setup and going in the kernel.
>
> Encoding/decoding of RC-6 by microcontrollers with firmware doesn't
> worry me.
>
>
> Maybe I'm being too conservative here, but I have a personal interest in
> keeping Linux free and unencumbered even in the US which, I cannot deny,
> has a patent system that is screwed up.
So I had one of the people who does all the license and patent audits for Fedora packages look at the Philips patent on RC-6. He's 100% positive that the patent *only* covers hardware, there should be no problem whatsoever writing a software decoder for RC-6.
--
Jarod Wilson
[email protected]
Jarod Wilson wrote:
> On Nov 26, 2009, at 2:43 PM, Andy Walls wrote:
>
>> On Thu, 2009-11-26 at 12:05 -0200, Mauro Carvalho Chehab wrote:
>> Maybe I'm being too conservative here, but I have a personal interest in
>> keeping Linux free and unencumbered even in the US which, I cannot deny,
>> has a patent system that is screwed up.
>
> So I had one of the people who does all the license and patent audits for
> Fedora packages look at the Philips patent on RC-6. He's 100% positive
> that the patent *only* covers hardware, there should be no problem whatsoever
> writing a software decoder for RC-6.
That's good!
Cheers,
Mauro.
On Mon, 2009-12-07 at 13:19 -0500, Jarod Wilson wrote:
> On Nov 26, 2009, at 2:43 PM, Andy Walls wrote:
>
> > On Thu, 2009-11-26 at 12:05 -0200, Mauro Carvalho Chehab wrote:
> >> Krzysztof Halasa wrote:
> >>> Andy Walls <[email protected]> writes:
> >>>
> >>>> I would also note that RC-6 Mode 6A, used by most MCE remotes, was
> >>>> developed by Philips, but Microsoft has some sort of licensing interest
> >>>> in it and it is almost surely encumbered somwhow:
> >>>
> >>> I don't know about legal problems in some countries but from the
> >>> technical POV handling the protocol in the kernel is more efficient
> >>> or (/and) simpler.
> >>
> >> A software licensing from Microsoft won't apply to Linux kernel, so I'm
> >> assuming that you're referring to some patent that they could be filled
> >> about RC6 mode 6A.
> >>
> >> I don't know if is there any US patent pending about it (AFAIK, only US
> >> accepts software patents), but there are some prior-art for IR key
> >> decoding. So, I don't see what "innovation" RC6 would be adding.
> >> If it is some new way to transmit waves, the patent issues
> >> aren't related to software, and the device manufacturer had already handled
> >> it when they made their devices.
> >>
> >> If it is just a new keytable, this issue
> >> could be easily solved by loading the keytable via userspace.
> >>
> >> Also, assuming that you can use the driver only with a hardware that comes
> >> with a licensed software, the user has already the license for using it.
> >>
> >> Do you have any details on what patents they are claiming?
> >
> > The US Philips RC-6 patent is US Patent 5,877,702
> >
> > http://www.google.com/patents?vid=USPAT5877702
> >
> > Click on download PDF to get a copy of the whole patent.
> >
> > I am not a lawyer. Philips claims' all appear to tie to a transmitter
> > or receiver as part of a system, but most of the claims are about
> > information and bit positions and lengths.
> ...
> > IMO, given
> >
> > a. the dearth of public information about RC-6, indicating someone
> > thinks it's their trade secret or intellectual property
> >
> > b. Microsoft claiming to license something related to the MCE remote
> > protocols (which are obviously RC-6 Mode 6A),
> >
> > c. my inability to draw a "clear, bright line" that RC-6 Mode 6A
> > encoding and decoding, as needed by MCE remotes, implemented in software
> > doesn't violate anyone's government granted rights to exclusivity.
> >
> > I think it's much better to implement software RC-6 Mode 6A encoding and
> > decoding in user space, doing only the minimum needed to get the
> > hardware setup and going in the kernel.
> >
> > Encoding/decoding of RC-6 by microcontrollers with firmware doesn't
> > worry me.
> >
> >
> > Maybe I'm being too conservative here, but I have a personal interest in
> > keeping Linux free and unencumbered even in the US which, I cannot deny,
> > has a patent system that is screwed up.
>
> So I had one of the people who does all the license and patent audits
> for Fedora packages look at the Philips patent on RC-6. He's 100%
> positive that the patent *only* covers hardware, there should be no
> problem whatsoever writing a software decoder for RC-6.
OK. Thanks for having some professionals take a look. (I'm assuming
that's the only patent.)
So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
end of the month.
I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
a common set of parameters, so I may be able to set up the decoders to
handle decoding from two different remote types at once. The HVR boards
can ship with either type of remote AFAIK.
I wonder if I can flip the keytables on the fly or if I have to create
two different input devices?
Regards,
Andy
On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
> On Mon, 2009-12-07 at 13:19 -0500, Jarod Wilson wrote:
> > On Nov 26, 2009, at 2:43 PM, Andy Walls wrote:
> >
> > > On Thu, 2009-11-26 at 12:05 -0200, Mauro Carvalho Chehab wrote:
> > >> Krzysztof Halasa wrote:
> > >>> Andy Walls <[email protected]> writes:
> > >>>
> > >>>> I would also note that RC-6 Mode 6A, used by most MCE remotes, was
> > >>>> developed by Philips, but Microsoft has some sort of licensing interest
> > >>>> in it and it is almost surely encumbered somwhow:
> > >>>
> > >>> I don't know about legal problems in some countries but from the
> > >>> technical POV handling the protocol in the kernel is more efficient
> > >>> or (/and) simpler.
> > >>
> > >> A software licensing from Microsoft won't apply to Linux kernel, so I'm
> > >> assuming that you're referring to some patent that they could be filled
> > >> about RC6 mode 6A.
> > >>
> > >> I don't know if is there any US patent pending about it (AFAIK, only US
> > >> accepts software patents), but there are some prior-art for IR key
> > >> decoding. So, I don't see what "innovation" RC6 would be adding.
> > >> If it is some new way to transmit waves, the patent issues
> > >> aren't related to software, and the device manufacturer had already handled
> > >> it when they made their devices.
> > >>
> > >> If it is just a new keytable, this issue
> > >> could be easily solved by loading the keytable via userspace.
> > >>
> > >> Also, assuming that you can use the driver only with a hardware that comes
> > >> with a licensed software, the user has already the license for using it.
> > >>
> > >> Do you have any details on what patents they are claiming?
> > >
> > > The US Philips RC-6 patent is US Patent 5,877,702
> > >
> > > http://www.google.com/patents?vid=USPAT5877702
> > >
> > > Click on download PDF to get a copy of the whole patent.
> > >
> > > I am not a lawyer. Philips claims' all appear to tie to a transmitter
> > > or receiver as part of a system, but most of the claims are about
> > > information and bit positions and lengths.
> > ...
> > > IMO, given
> > >
> > > a. the dearth of public information about RC-6, indicating someone
> > > thinks it's their trade secret or intellectual property
> > >
> > > b. Microsoft claiming to license something related to the MCE remote
> > > protocols (which are obviously RC-6 Mode 6A),
> > >
> > > c. my inability to draw a "clear, bright line" that RC-6 Mode 6A
> > > encoding and decoding, as needed by MCE remotes, implemented in software
> > > doesn't violate anyone's government granted rights to exclusivity.
> > >
> > > I think it's much better to implement software RC-6 Mode 6A encoding and
> > > decoding in user space, doing only the minimum needed to get the
> > > hardware setup and going in the kernel.
> > >
> > > Encoding/decoding of RC-6 by microcontrollers with firmware doesn't
> > > worry me.
> > >
> > >
> > > Maybe I'm being too conservative here, but I have a personal interest in
> > > keeping Linux free and unencumbered even in the US which, I cannot deny,
> > > has a patent system that is screwed up.
> >
> > So I had one of the people who does all the license and patent audits
> > for Fedora packages look at the Philips patent on RC-6. He's 100%
> > positive that the patent *only* covers hardware, there should be no
> > problem whatsoever writing a software decoder for RC-6.
>
> OK. Thanks for having some professionals take a look. (I'm assuming
> that's the only patent.)
>
> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
> end of the month.
>
> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
> a common set of parameters, so I may be able to set up the decoders to
> handle decoding from two different remote types at once. The HVR boards
> can ship with either type of remote AFAIK.
>
> I wonder if I can flip the keytables on the fly or if I have to create
> two different input devices?
>
Can you distinguish between the 2 remotes (not receivers)? Like I said,
I think the preferred way is to represent every remote that can be
distinguished from each other as a separate input device. Applications
expect to query device capabilities and expect them to stay somewhat
stable (we do support keymap change but I don't think anyone expectes
flip-flopping).
--
Dmitry
Andy Walls wrote:
> On Mon, 2009-12-07 at 13:19 -0500, Jarod Wilson wrote:
>> On Nov 26, 2009, at 2:43 PM, Andy Walls wrote:
>>
>>> On Thu, 2009-11-26 at 12:05 -0200, Mauro Carvalho Chehab wrote:
>>>> Krzysztof Halasa wrote:
>>>>> Andy Walls <[email protected]> writes:
>>>>>
>>>>>> I would also note that RC-6 Mode 6A, used by most MCE remotes, was
>>>>>> developed by Philips, but Microsoft has some sort of licensing interest
>>>>>> in it and it is almost surely encumbered somwhow:
>>>>> I don't know about legal problems in some countries but from the
>>>>> technical POV handling the protocol in the kernel is more efficient
>>>>> or (/and) simpler.
>>>> A software licensing from Microsoft won't apply to Linux kernel, so I'm
>>>> assuming that you're referring to some patent that they could be filled
>>>> about RC6 mode 6A.
>>>>
>>>> I don't know if is there any US patent pending about it (AFAIK, only US
>>>> accepts software patents), but there are some prior-art for IR key
>>>> decoding. So, I don't see what "innovation" RC6 would be adding.
>>>> If it is some new way to transmit waves, the patent issues
>>>> aren't related to software, and the device manufacturer had already handled
>>>> it when they made their devices.
>>>>
>>>> If it is just a new keytable, this issue
>>>> could be easily solved by loading the keytable via userspace.
>>>>
>>>> Also, assuming that you can use the driver only with a hardware that comes
>>>> with a licensed software, the user has already the license for using it.
>>>>
>>>> Do you have any details on what patents they are claiming?
>>> The US Philips RC-6 patent is US Patent 5,877,702
>>>
>>> http://www.google.com/patents?vid=USPAT5877702
>>>
>>> Click on download PDF to get a copy of the whole patent.
>>>
>>> I am not a lawyer. Philips claims' all appear to tie to a transmitter
>>> or receiver as part of a system, but most of the claims are about
>>> information and bit positions and lengths.
>> ...
>>> IMO, given
>>>
>>> a. the dearth of public information about RC-6, indicating someone
>>> thinks it's their trade secret or intellectual property
>>>
>>> b. Microsoft claiming to license something related to the MCE remote
>>> protocols (which are obviously RC-6 Mode 6A),
>>>
>>> c. my inability to draw a "clear, bright line" that RC-6 Mode 6A
>>> encoding and decoding, as needed by MCE remotes, implemented in software
>>> doesn't violate anyone's government granted rights to exclusivity.
>>>
>>> I think it's much better to implement software RC-6 Mode 6A encoding and
>>> decoding in user space, doing only the minimum needed to get the
>>> hardware setup and going in the kernel.
>>>
>>> Encoding/decoding of RC-6 by microcontrollers with firmware doesn't
>>> worry me.
>>>
>>>
>>> Maybe I'm being too conservative here, but I have a personal interest in
>>> keeping Linux free and unencumbered even in the US which, I cannot deny,
>>> has a patent system that is screwed up.
>> So I had one of the people who does all the license and patent audits
>> for Fedora packages look at the Philips patent on RC-6. He's 100%
>> positive that the patent *only* covers hardware, there should be no
>> problem whatsoever writing a software decoder for RC-6.
>
> OK. Thanks for having some professionals take a look. (I'm assuming
> that's the only patent.)
>
> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
> end of the month.
Good! Please, try to design the decoder as an independent module that gets
data from a kfifo and generate scancodes for the input API.
> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
> a common set of parameters, so I may be able to set up the decoders to
> handle decoding from two different remote types at once. The HVR boards
> can ship with either type of remote AFAIK.
>
> I wonder if I can flip the keytables on the fly or if I have to create
> two different input devices?
IMO, the better is, by default, to open just one input device per IR receiver.
>From what I understand from our discussions, if the user wants to filter IR
commands into several input interfaces, some userspace interface will be
provided to allow the creation of other input interfaces for that purpose.
Cheers,
Mauro.
Dmitry Torokhov wrote:
> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>> On Mon, 2009-12-07 at 13:19 -0500, Jarod Wilson wrote:
>>> On Nov 26, 2009, at 2:43 PM, Andy Walls wrote:
>>>
>>>> On Thu, 2009-11-26 at 12:05 -0200, Mauro Carvalho Chehab wrote:
>>>>> Krzysztof Halasa wrote:
>>>>>> Andy Walls <[email protected]> writes:
>>>>>>
>>>>>>> I would also note that RC-6 Mode 6A, used by most MCE remotes, was
>>>>>>> developed by Philips, but Microsoft has some sort of licensing interest
>>>>>>> in it and it is almost surely encumbered somwhow:
>>>>>> I don't know about legal problems in some countries but from the
>>>>>> technical POV handling the protocol in the kernel is more efficient
>>>>>> or (/and) simpler.
>>>>> A software licensing from Microsoft won't apply to Linux kernel, so I'm
>>>>> assuming that you're referring to some patent that they could be filled
>>>>> about RC6 mode 6A.
>>>>>
>>>>> I don't know if is there any US patent pending about it (AFAIK, only US
>>>>> accepts software patents), but there are some prior-art for IR key
>>>>> decoding. So, I don't see what "innovation" RC6 would be adding.
>>>>> If it is some new way to transmit waves, the patent issues
>>>>> aren't related to software, and the device manufacturer had already handled
>>>>> it when they made their devices.
>>>>>
>>>>> If it is just a new keytable, this issue
>>>>> could be easily solved by loading the keytable via userspace.
>>>>>
>>>>> Also, assuming that you can use the driver only with a hardware that comes
>>>>> with a licensed software, the user has already the license for using it.
>>>>>
>>>>> Do you have any details on what patents they are claiming?
>>>> The US Philips RC-6 patent is US Patent 5,877,702
>>>>
>>>> http://www.google.com/patents?vid=USPAT5877702
>>>>
>>>> Click on download PDF to get a copy of the whole patent.
>>>>
>>>> I am not a lawyer. Philips claims' all appear to tie to a transmitter
>>>> or receiver as part of a system, but most of the claims are about
>>>> information and bit positions and lengths.
>>> ...
>>>> IMO, given
>>>>
>>>> a. the dearth of public information about RC-6, indicating someone
>>>> thinks it's their trade secret or intellectual property
>>>>
>>>> b. Microsoft claiming to license something related to the MCE remote
>>>> protocols (which are obviously RC-6 Mode 6A),
>>>>
>>>> c. my inability to draw a "clear, bright line" that RC-6 Mode 6A
>>>> encoding and decoding, as needed by MCE remotes, implemented in software
>>>> doesn't violate anyone's government granted rights to exclusivity.
>>>>
>>>> I think it's much better to implement software RC-6 Mode 6A encoding and
>>>> decoding in user space, doing only the minimum needed to get the
>>>> hardware setup and going in the kernel.
>>>>
>>>> Encoding/decoding of RC-6 by microcontrollers with firmware doesn't
>>>> worry me.
>>>>
>>>>
>>>> Maybe I'm being too conservative here, but I have a personal interest in
>>>> keeping Linux free and unencumbered even in the US which, I cannot deny,
>>>> has a patent system that is screwed up.
>>> So I had one of the people who does all the license and patent audits
>>> for Fedora packages look at the Philips patent on RC-6. He's 100%
>>> positive that the patent *only* covers hardware, there should be no
>>> problem whatsoever writing a software decoder for RC-6.
>> OK. Thanks for having some professionals take a look. (I'm assuming
>> that's the only patent.)
>>
>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>> end of the month.
>>
>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>> a common set of parameters, so I may be able to set up the decoders to
>> handle decoding from two different remote types at once. The HVR boards
>> can ship with either type of remote AFAIK.
>>
>> I wonder if I can flip the keytables on the fly or if I have to create
>> two different input devices?
>>
>
> Can you distinguish between the 2 remotes (not receivers)? Like I said,
> I think the preferred way is to represent every remote that can be
> distinguished from each other as a separate input device. Applications
> expect to query device capabilities and expect them to stay somewhat
> stable (we do support keymap change but I don't think anyone expectes
> flip-flopping).
>
With RC-5, you have no fields describing the remote. So, all the driver could
do is an educated guess.
>From a quick look I did at the RC-6 Mode 6A docs I found, I suspect that
you can distinguish two different remotes when someone press a key there.
However, I don't think it is a good idea to automatically create a new interface
every time a different vendor is detected. Maybe the user simply have a
RC-6 IR to control his TV and doesn't have any intention on using that
device on his computer.
IMO, the better is to have an API to allow creation of multiple interfaces
per IR receiver, based on some scancode matching table and/or on some
matching mask.
It should be possible to use the filter API to match different IR's by
vendor/product on protocols that supports it, or to match address/command
tuples on protocols where you just have those fields.
Cheers,
Mauro.
On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
> > So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
> > end of the month.
> >
> > I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
> > a common set of parameters, so I may be able to set up the decoders to
> > handle decoding from two different remote types at once. The HVR boards
> > can ship with either type of remote AFAIK.
> >
> > I wonder if I can flip the keytables on the fly or if I have to create
> > two different input devices?
> >
>
> Can you distinguish between the 2 remotes (not receivers)?
Yes. RC-6 and RC-5 are different enough to distinguish between the two.
(Honestly I could pile on more protocols that have similar pulse time
periods, but that's complexity for no good reason and I don't know of a
vendor that bundles 3 types of remotes per TV card.)
> Like I said,
> I think the preferred way is to represent every remote that can be
> distinguished from each other as a separate input device.
OK. With RC-5, NEC, and RC-6 at least there is also an address or
system byte or word to distingish different remotes. However creating
multiple input devices on the fly for detected remotes would be madness
- especially with a decoding error in the address bits.
Any one vendor usually picks one address for their bundled remote.
Hauppaugue uses address 0x1e for it's RC-5 remotes AFAICT.
> Applications
> expect to query device capabilities and expect them to stay somewhat
> stable (we do support keymap change but I don't think anyone expectes
> flip-flopping).
OK.
On Tue, 2009-12-08 at 09:32 -0200, Mauro Carvalho Chehab wrote:
> Andy Walls wrote:
> > On Mon, 2009-12-07 at 13:19 -0500, Jarod Wilson wrote:
> > So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
> > end of the month.
>
> Good! Please, try to design the decoder as an independent module that gets
> data from a kfifo and generate scancodes for the input API.
Hmmm. Let me see how the protoype turns out keeping that design
objective in mind. I've already got the current RC-5 and NEC decoding
state machines in cx23885-input a bit layered, but they are taking
advantage of specific events signaled by my v4l2_subdev implementation.
Strictly speaking the state machines don't have to. All of the remote
protocols I have played with make framing pretty easy.
> > I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
> > a common set of parameters, so I may be able to set up the decoders to
> > handle decoding from two different remote types at once. The HVR boards
> > can ship with either type of remote AFAIK.
> >
> > I wonder if I can flip the keytables on the fly or if I have to create
> > two different input devices?
>
> IMO, the better is, by default, to open just one input device per IR receiver.
> >From what I understand from our discussions, if the user wants to filter IR
> commands into several input interfaces, some userspace interface will be
> provided to allow the creation of other input interfaces for that purpose.
Hmm. That's not what I just thought I read from Dmitry....
Oh well. If I don'y get it done by 24 Dec, it'll be in the new year.
Regards,
Andy
On Tue, Dec 8, 2009 at 7:35 AM, Andy Walls <[email protected]> wrote:
> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>
>> > So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>> > end of the month.
>> >
>> > I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>> > a common set of parameters, so I may be able to set up the decoders to
>> > handle decoding from two different remote types at once. ?The HVR boards
>> > can ship with either type of remote AFAIK.
>> >
>> > I wonder if I can flip the keytables on the fly or if I have to create
>> > two different input devices?
>> >
>>
>> Can you distinguish between the 2 remotes (not receivers)?
>
> Yes. ?RC-6 and RC-5 are different enough to distinguish between the two.
> (Honestly I could pile on more protocols that have similar pulse time
> periods, but that's complexity for no good reason and I don't know of a
> vendor that bundles 3 types of remotes per TV card.)
>
>
>> ?Like I said,
>> I think the preferred way is to represent every remote that can be
>> distinguished from each other as a separate input device.
>
> OK. ?With RC-5, NEC, and RC-6 at least there is also an address or
> system byte or word to distingish different remotes. ?However creating
> multiple input devices on the fly for detected remotes would be madness
> - especially with a decoding error in the address bits.
I agree that creating devices on the fly has problems. Another
solution is to create one device for each map that is loaded. There
would be a couple built-in maps for bundled remotes - each would
create a device. Then the user could load more maps with each map
creating a device.
Incoming scancodes are matched against all of the loaded maps and a
keycode event is generated if a match occurs.
This illustrates why there should an EV_IR event which communicates
scancodes, without this event you can't see the scancodes that don't
match a map entry. A scancode would be first matched against the map,
then if there as no match an EV_IR event would be reported.
>
> Any one vendor usually picks one address for their bundled remote.
> Hauppaugue uses address 0x1e for it's RC-5 remotes AFAICT.
>
>
>
>> ?Applications
>> expect to query device capabilities and expect them to stay somewhat
>> stable (we do support keymap change but I don't think anyone expectes
>> flip-flopping).
>
> OK.
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
--
Jon Smirl
[email protected]
Andy Walls wrote:
> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>
>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>> end of the month.
>>>
>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>> a common set of parameters, so I may be able to set up the decoders to
>>> handle decoding from two different remote types at once. The HVR boards
>>> can ship with either type of remote AFAIK.
>>>
>>> I wonder if I can flip the keytables on the fly or if I have to create
>>> two different input devices?
>>>
>> Can you distinguish between the 2 remotes (not receivers)?
>
> Yes. RC-6 and RC-5 are different enough to distinguish between the two.
> (Honestly I could pile on more protocols that have similar pulse time
> periods, but that's complexity for no good reason and I don't know of a
> vendor that bundles 3 types of remotes per TV card.)
You'll be distinguishing the protocol, not the remote. If I understood
Dmitry's question, he is asking if you can distinguish between two different
remotes that may, for example, be using both RC-5 or both RC-6 or one RC-5
and another RC-6.
>> Like I said,
>> I think the preferred way is to represent every remote that can be
>> distinguished from each other as a separate input device.
>
> OK. With RC-5, NEC, and RC-6 at least there is also an address or
> system byte or word to distingish different remotes. However creating
> multiple input devices on the fly for detected remotes would be madness
> - especially with a decoding error in the address bits.
>
> Any one vendor usually picks one address for their bundled remote.
> Hauppaugue uses address 0x1e for it's RC-5 remotes AFAICT.
The address field on RC-5 protocol is not meant to distinguish different
vendors, but different "applications". It identifies that a code should
be sent to a TV or a VCR, or a DVD or a SAT.
In the case of bundled IR's, some vendors like Hauppauge opted to use a
reserved address to avoid conflicts with other equipments. It happens that
vendor's "reserved address" can be different between two different vendors,
but is just an educated guess to say that an address equal to 0x1e is Hauppauge.
Cheers,
Mauro.
Jon Smirl wrote:
> On Tue, Dec 8, 2009 at 7:35 AM, Andy Walls <[email protected]> wrote:
>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>> end of the month.
>>>>
>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>> a common set of parameters, so I may be able to set up the decoders to
>>>> handle decoding from two different remote types at once. The HVR boards
>>>> can ship with either type of remote AFAIK.
>>>>
>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>> two different input devices?
>>>>
>>> Can you distinguish between the 2 remotes (not receivers)?
>> Yes. RC-6 and RC-5 are different enough to distinguish between the two.
>> (Honestly I could pile on more protocols that have similar pulse time
>> periods, but that's complexity for no good reason and I don't know of a
>> vendor that bundles 3 types of remotes per TV card.)
>>
>>
>>> Like I said,
>>> I think the preferred way is to represent every remote that can be
>>> distinguished from each other as a separate input device.
>> OK. With RC-5, NEC, and RC-6 at least there is also an address or
>> system byte or word to distingish different remotes. However creating
>> multiple input devices on the fly for detected remotes would be madness
>> - especially with a decoding error in the address bits.
>
> I agree that creating devices on the fly has problems. Another
> solution is to create one device for each map that is loaded. There
> would be a couple built-in maps for bundled remotes - each would
> create a device. Then the user could load more maps with each map
> creating a device.
No, please. We currently have already 89 different keymaps in-kernel. Creating
89 different interfaces per IR receiver is not useful at all.
IMO, the interfaces should be created as the keymaps are associated
to an specific IR receiver.
> Incoming scancodes are matched against all of the loaded maps and a
> keycode event is generated if a match occurs.
s/all of the loaded maps/all of the loaded maps per device/
You may have more than one IR receiver on a given machine.
IMO, we may have a mask filter matching also, associated with each keycode
table, to minimize the keycode seek time. Something like:
if (scancode & scancode_mask)
check_scancode()
> This illustrates why there should an EV_IR event which communicates
> scancodes, without this event you can't see the scancodes that don't
> match a map entry. A scancode would be first matched against the map,
> then if there as no match an EV_IR event would be reported.
There's nothing wrong on receiving a scancode that won't map. This can
simply be an event that you don't want to handle (for example, an IR
code sent to user's TV set).
IMO, the better is to provide this scancode at KERN_DEBUG (if debug is
enabled), and via an "observer" program.
Cheers,
Mauro.
On Tue, Dec 8, 2009 at 8:30 AM, Mauro Carvalho Chehab
<[email protected]> wrote:
> Andy Walls wrote:
>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>
>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>> end of the month.
>>>>
>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>> a common set of parameters, so I may be able to set up the decoders to
>>>> handle decoding from two different remote types at once. ?The HVR boards
>>>> can ship with either type of remote AFAIK.
>>>>
>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>> two different input devices?
>>>>
>>> Can you distinguish between the 2 remotes (not receivers)?
>>
>> Yes. ?RC-6 and RC-5 are different enough to distinguish between the two.
>> (Honestly I could pile on more protocols that have similar pulse time
>> periods, but that's complexity for no good reason and I don't know of a
>> vendor that bundles 3 types of remotes per TV card.)
>
> You'll be distinguishing the protocol, not the remote. If I understood
> Dmitry's question, he is asking if you can distinguish between two different
> remotes that may, for example, be using both RC-5 or both RC-6 or one RC-5
> and another RC-6.
RC-5 and RC-6 both contain an address field. My opinion is that
different addresses represent different devices and in general they
should appear on an input devices per address.
However, I prefer a different scheme for splitting the signals apart.
Load separate maps containing scancodes for each address. When the IR
signals come in they are matched against the maps and a keycode is
generated when a match is found. Now there is no need to distinguish
between the remotes. It doesn't matter which remote generated the
signal.
scancode RC5/12/1 - protocol, address, command tuplet. Map this to
KP_1 on interface 1.
scancode RC5/7/1 - protocol, address, command tuplet. Map this to KP_1
on interface 2.
Using the maps to split the commands out also fixes the problem with
Sony remotes which use multiple protocols to control a single device.
scancode Sony12/12/1 - protocol, address, command tuplet. Map this to
power_on on interface 1.
scancode Sony15/12/1 - protocol, address, command tuplet. Map this to
KP_1 on interface 1.
>
>>> ?Like I said,
>>> I think the preferred way is to represent every remote that can be
>>> distinguished from each other as a separate input device.
>>
>> OK. ?With RC-5, NEC, and RC-6 at least there is also an address or
>> system byte or word to distingish different remotes. ?However creating
>> multiple input devices on the fly for detected remotes would be madness
>> - especially with a decoding error in the address bits.
>>
>> Any one vendor usually picks one address for their bundled remote.
>> Hauppaugue uses address 0x1e for it's RC-5 remotes AFAICT.
>
> The address field on RC-5 protocol is not meant to distinguish different
> vendors, but different "applications". It identifies that a code should
> be sent to a TV or a VCR, or a DVD or a SAT.
>
> In the case of bundled IR's, some vendors like Hauppauge opted to use a
> reserved address to avoid conflicts with other equipments. It happens that
> vendor's "reserved address" can be different between two different vendors,
> but is just an educated guess to say that an address equal to 0x1e is Hauppauge.
>
> Cheers,
> Mauro.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
--
Jon Smirl
[email protected]
Jon Smirl wrote:
> On Tue, Dec 8, 2009 at 8:30 AM, Mauro Carvalho Chehab
> <[email protected]> wrote:
>> Andy Walls wrote:
>>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>>> end of the month.
>>>>>
>>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>>> a common set of parameters, so I may be able to set up the decoders to
>>>>> handle decoding from two different remote types at once. The HVR boards
>>>>> can ship with either type of remote AFAIK.
>>>>>
>>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>>> two different input devices?
>>>>>
>>>> Can you distinguish between the 2 remotes (not receivers)?
>>> Yes. RC-6 and RC-5 are different enough to distinguish between the two.
>>> (Honestly I could pile on more protocols that have similar pulse time
>>> periods, but that's complexity for no good reason and I don't know of a
>>> vendor that bundles 3 types of remotes per TV card.)
>> You'll be distinguishing the protocol, not the remote. If I understood
>> Dmitry's question, he is asking if you can distinguish between two different
>> remotes that may, for example, be using both RC-5 or both RC-6 or one RC-5
>> and another RC-6.
>
> RC-5 and RC-6 both contain an address field. My opinion is that
> different addresses represent different devices and in general they
> should appear on an input devices per address.
The same IR can produce two different addresses. The IR bundled with my satellite
STB produces two different codes, depending if you previously pressed <TV> or <SAT>
key (in fact, I think it can even produce different protocols for TV, as it can
be configured to work with different TV sets).
> However, I prefer a different scheme for splitting the signals apart.
> Load separate maps containing scancodes for each address. When the IR
> signals come in they are matched against the maps and a keycode is
> generated when a match is found. Now there is no need to distinguish
> between the remotes. It doesn't matter which remote generated the
> signal.
>
> scancode RC5/12/1 - protocol, address, command tuplet. Map this to
> KP_1 on interface 1.
> scancode RC5/7/1 - protocol, address, command tuplet. Map this to KP_1
> on interface 2.
>
> Using the maps to split the commands out also fixes the problem with
> Sony remotes which use multiple protocols to control a single device.
> scancode Sony12/12/1 - protocol, address, command tuplet. Map this to
> power_on on interface 1.
> scancode Sony15/12/1 - protocol, address, command tuplet. Map this to
> KP_1 on interface 1.
>
I agree.
Cheers,
Mauro.
On Tue, Dec 8, 2009 at 8:40 AM, Mauro Carvalho Chehab
<[email protected]> wrote:
> Jon Smirl wrote:
>> On Tue, Dec 8, 2009 at 7:35 AM, Andy Walls <[email protected]> wrote:
>>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>>> end of the month.
>>>>>
>>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>>> a common set of parameters, so I may be able to set up the decoders to
>>>>> handle decoding from two different remote types at once. ?The HVR boards
>>>>> can ship with either type of remote AFAIK.
>>>>>
>>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>>> two different input devices?
>>>>>
>>>> Can you distinguish between the 2 remotes (not receivers)?
>>> Yes. ?RC-6 and RC-5 are different enough to distinguish between the two.
>>> (Honestly I could pile on more protocols that have similar pulse time
>>> periods, but that's complexity for no good reason and I don't know of a
>>> vendor that bundles 3 types of remotes per TV card.)
>>>
>>>
>>>> ?Like I said,
>>>> I think the preferred way is to represent every remote that can be
>>>> distinguished from each other as a separate input device.
>>> OK. ?With RC-5, NEC, and RC-6 at least there is also an address or
>>> system byte or word to distingish different remotes. ?However creating
>>> multiple input devices on the fly for detected remotes would be madness
>>> - especially with a decoding error in the address bits.
>>
>> I agree that creating devices on the fly has problems. Another
>> solution is to create one device for each map that is loaded. There
>> would be a couple built-in maps for bundled remotes - each would
>> create a device. Then the user could load more maps with each map
>> creating a device.
>
> No, please. We currently have already 89 different keymaps in-kernel. Creating
> 89 different interfaces per IR receiver is not useful at all.
>
> IMO, the interfaces should be created as the keymaps are associated
> to an specific IR receiver.
Each IR receiver device driver would have a built-in keymap for the
remote bundled with it. When you load the driver it will poke the
input system and install the map. Any additional keymaps would get
loaded from user space. You would load one keymap per input device.
You might have 89 maps in the kernel with each map being built into
the device driver for those 89 IR receivers. But you'll only own one
or two of those devices so only one or two of the 89 maps will load.
Building the map for the bundled receiver into the device driver is an
important part of achieving "just works".
I suspect we'll have a 1,000 maps defined after ten years, most of
these maps will be loaded from user space. But you'll only have two or
three loaded at any one time into your kernel. You need one map per
input device created. These maps are tiny, less than 1KB.
Having all of these maps is the price of allowing everyone to use any
more that they please. If you force the use of universal remotes most
of the maps can be eliminated.
>
>> Incoming scancodes are matched against all of the loaded maps and a
>> keycode event is generated if a match occurs.
>
> s/all of the loaded maps/all of the loaded maps per device/
>
> You may have more than one IR receiver on a given machine.
>
> IMO, we may have a mask filter matching also, associated with each keycode
> table, to minimize the keycode seek time. Something like:
>
> ? ? ? ?if (scancode & scancode_mask)
> ? ? ? ? ? ? ? ?check_scancode()
>
>> This illustrates why there should an EV_IR event which communicates
>> scancodes, without this event you can't see the scancodes that don't
>> match a map entry. A scancode would be first matched against the map,
>> then if there as no match an EV_IR event would be reported.
>
> There's nothing wrong on receiving a scancode that won't map. This can
> simply be an event that you don't want to handle (for example, an IR
> code sent to user's TV set).
>
> IMO, the better is to provide this scancode at KERN_DEBUG (if debug is
> enabled), and via an "observer" program.
>
> Cheers,
> Mauro.
>
--
Jon Smirl
[email protected]
Mauro Carvalho Chehab <[email protected]> writes:
> With RC-5, you have no fields describing the remote. So, all the driver could
> do is an educated guess.
It can't even do that, e.g. single remotes (even the dumb ones) can send
different code groups (addresses) for different keys.
> IMO, the better is to have an API to allow creation of multiple interfaces
> per IR receiver, based on some scancode matching table and/or on some
> matching mask.
I think setting the keytables for each logical device would do.
I.e. just have a way to create additional logical devices. Each can have
its own keytable. The decoders would send their output to all logical
remotes, trying to match the tables etc.
> It should be possible to use the filter API to match different IR's by
> vendor/product on protocols that supports it,
That would mean unnecessary limiting.
> or to match address/command
> tuples on protocols where you just have those fields.
Precisely.
--
Krzysztof Halasa
Jon Smirl wrote:
> On Tue, Dec 8, 2009 at 8:40 AM, Mauro Carvalho Chehab
> <[email protected]> wrote:
>> Jon Smirl wrote:
>>> On Tue, Dec 8, 2009 at 7:35 AM, Andy Walls <[email protected]> wrote:
>>>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>>>> end of the month.
>>>>>>
>>>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>>>> a common set of parameters, so I may be able to set up the decoders to
>>>>>> handle decoding from two different remote types at once. The HVR boards
>>>>>> can ship with either type of remote AFAIK.
>>>>>>
>>>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>>>> two different input devices?
>>>>>>
>>>>> Can you distinguish between the 2 remotes (not receivers)?
>>>> Yes. RC-6 and RC-5 are different enough to distinguish between the two.
>>>> (Honestly I could pile on more protocols that have similar pulse time
>>>> periods, but that's complexity for no good reason and I don't know of a
>>>> vendor that bundles 3 types of remotes per TV card.)
>>>>
>>>>
>>>>> Like I said,
>>>>> I think the preferred way is to represent every remote that can be
>>>>> distinguished from each other as a separate input device.
>>>> OK. With RC-5, NEC, and RC-6 at least there is also an address or
>>>> system byte or word to distingish different remotes. However creating
>>>> multiple input devices on the fly for detected remotes would be madness
>>>> - especially with a decoding error in the address bits.
>>> I agree that creating devices on the fly has problems. Another
>>> solution is to create one device for each map that is loaded. There
>>> would be a couple built-in maps for bundled remotes - each would
>>> create a device. Then the user could load more maps with each map
>>> creating a device.
>> No, please. We currently have already 89 different keymaps in-kernel. Creating
>> 89 different interfaces per IR receiver is not useful at all.
>>
>> IMO, the interfaces should be created as the keymaps are associated
>> to an specific IR receiver.
>
> Each IR receiver device driver would have a built-in keymap for the
> remote bundled with it. When you load the driver it will poke the
> input system and install the map. Any additional keymaps would get
> loaded from user space. You would load one keymap per input device.
>
> You might have 89 maps in the kernel with each map being built into
> the device driver for those 89 IR receivers. But you'll only own one
> or two of those devices so only one or two of the 89 maps will load.
> Building the map for the bundled receiver into the device driver is an
> important part of achieving "just works".
>
> I suspect we'll have a 1,000 maps defined after ten years, most of
> these maps will be loaded from user space. But you'll only have two or
> three loaded at any one time into your kernel. You need one map per
> input device created. These maps are tiny, less than 1KB.
>
> Having all of these maps is the price of allowing everyone to use any
> more that they please. If you force the use of universal remotes most
> of the maps can be eliminated.
Makes sense. Yet, I would add an option at Kbuild to create a module or not
with the bundled IR keymaps.
So, it should be possible to have all of them completely on userspace or
having them at kernelspace.
Cheers,
Mauro.
On Tue, Dec 8, 2009 at 8:59 AM, Mauro Carvalho Chehab
<[email protected]> wrote:
> Jon Smirl wrote:
>> On Tue, Dec 8, 2009 at 8:30 AM, Mauro Carvalho Chehab
>> <[email protected]> wrote:
>>> Andy Walls wrote:
>>>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>>>> end of the month.
>>>>>>
>>>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>>>> a common set of parameters, so I may be able to set up the decoders to
>>>>>> handle decoding from two different remote types at once. ?The HVR boards
>>>>>> can ship with either type of remote AFAIK.
>>>>>>
>>>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>>>> two different input devices?
>>>>>>
>>>>> Can you distinguish between the 2 remotes (not receivers)?
>>>> Yes. ?RC-6 and RC-5 are different enough to distinguish between the two.
>>>> (Honestly I could pile on more protocols that have similar pulse time
>>>> periods, but that's complexity for no good reason and I don't know of a
>>>> vendor that bundles 3 types of remotes per TV card.)
>>> You'll be distinguishing the protocol, not the remote. If I understood
>>> Dmitry's question, he is asking if you can distinguish between two different
>>> remotes that may, for example, be using both RC-5 or both RC-6 or one RC-5
>>> and another RC-6.
>>
>> RC-5 and RC-6 both contain an address field. ?My opinion is that
>> different addresses represent different devices and in general they
>> should appear on an input devices per address.
>
> The same IR can produce two different addresses. The IR bundled with my satellite
> STB produces two different codes, depending if you previously pressed <TV> or <SAT>
> key (in fact, I think it can even produce different protocols for TV, as it can
> be configured to work with different TV sets).
You have a multi-function remote. Multi-function remotes combine
multiple single function remotes into a single device. All universal
remotes I have seen are multi-function. They usually combine three to
five single function remotes.
Yours is a two function remote <TV> and <SAT>. When you push <TV> and
<SAT> you are changing which single function remote is being emulated.
That's why those keys don't send codes. When writing code you should
think of this remote as being two indpendent virtual remotes, not a
single one.
Note that it is common for multfunction remotes to completely change
IR protocol families when you switch which single function remote you
are emulating. I have my universal set for a Sony TV , JVC DVD player
and a Comcast STB. All three of those use different IR protocols.
By using maps containing the two different addresses for <TV> and
<SAT> you can split these commands onto two different evdev devices.
This model is complicated by the fact that some remotes that look like
multi-function remotes aren't really multifunction. The remote bundled
with the MS MCE receiver is one. That remote is a single function
device even though it has function buttons for TV, Music, Pictures,
etc.
>
>> However, I prefer a different scheme for splitting the signals apart.
>> Load separate maps containing scancodes for each address. When the IR
>> signals come in they are matched against the maps and a keycode is
>> generated when a match is found. Now there is no need to distinguish
>> between the remotes. It doesn't matter which remote generated the
>> signal.
>>
>> scancode RC5/12/1 - protocol, address, command tuplet. Map this to
>> KP_1 on interface 1.
>> scancode RC5/7/1 - protocol, address, command tuplet. Map this to KP_1
>> on interface 2.
>>
>> Using the maps to split the commands out also fixes the problem with
>> Sony remotes which use multiple protocols to control a single device.
>> scancode Sony12/12/1 - protocol, address, command tuplet. Map this to
>> power_on on interface 1.
>> scancode Sony15/12/1 - protocol, address, command tuplet. Map this to
>> KP_1 on interface 1.
>>
>
> I agree.
>
> Cheers,
> Mauro.
>
--
Jon Smirl
[email protected]
Krzysztof Halasa wrote:
> Mauro Carvalho Chehab <[email protected]> writes:
>> IMO, the better is to have an API to allow creation of multiple interfaces
>> per IR receiver, based on some scancode matching table and/or on some
>> matching mask.
>
> I think setting the keytables for each logical device would do.
Yes.
>
> I.e. just have a way to create additional logical devices. Each can have
> its own keytable. The decoders would send their output to all logical
> remotes, trying to match the tables etc.
>
>> It should be possible to use the filter API to match different IR's by
>> vendor/product on protocols that supports it,
>
> That would mean unnecessary limiting.
If the mask is (unsigned)-1, it will not add any limit. This should be the default.
The advantage of the mask is that you can speedup the keycode decoding by not calling
a seek routine in the cases where it doesn't make sense.
Also, the cost of scancode & scancode_mask is cheap enough, comparing with the
potential optimization gain of not seeking a data in a table that wouldn't match anyway.
Also, the IR core may automatically generate such mask, by doing an "and" operation of all
the scancodes at the table during table initialization/changes. If the mask is zero, it
defaults to use a (unsigned) -1 mask.
Cheers,
Mauro.
On Tue, Dec 8, 2009 at 9:16 AM, Mauro Carvalho Chehab
<[email protected]> wrote:
> Jon Smirl wrote:
>> On Tue, Dec 8, 2009 at 8:40 AM, Mauro Carvalho Chehab
>> <[email protected]> wrote:
>>> Jon Smirl wrote:
>>>> On Tue, Dec 8, 2009 at 7:35 AM, Andy Walls <[email protected]> wrote:
>>>>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>>>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>>>>> end of the month.
>>>>>>>
>>>>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>>>>> a common set of parameters, so I may be able to set up the decoders to
>>>>>>> handle decoding from two different remote types at once. ?The HVR boards
>>>>>>> can ship with either type of remote AFAIK.
>>>>>>>
>>>>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>>>>> two different input devices?
>>>>>>>
>>>>>> Can you distinguish between the 2 remotes (not receivers)?
>>>>> Yes. ?RC-6 and RC-5 are different enough to distinguish between the two.
>>>>> (Honestly I could pile on more protocols that have similar pulse time
>>>>> periods, but that's complexity for no good reason and I don't know of a
>>>>> vendor that bundles 3 types of remotes per TV card.)
>>>>>
>>>>>
>>>>>> ?Like I said,
>>>>>> I think the preferred way is to represent every remote that can be
>>>>>> distinguished from each other as a separate input device.
>>>>> OK. ?With RC-5, NEC, and RC-6 at least there is also an address or
>>>>> system byte or word to distingish different remotes. ?However creating
>>>>> multiple input devices on the fly for detected remotes would be madness
>>>>> - especially with a decoding error in the address bits.
>>>> I agree that creating devices on the fly has problems. Another
>>>> solution is to create one device for each map that is loaded. There
>>>> would be a couple built-in maps for bundled remotes - each would
>>>> create a device. Then the user could load more maps with each map
>>>> creating a device.
>>> No, please. We currently have already 89 different keymaps in-kernel. Creating
>>> 89 different interfaces per IR receiver is not useful at all.
>>>
>>> IMO, the interfaces should be created as the keymaps are associated
>>> to an specific IR receiver.
>>
>> Each IR receiver device driver would have a built-in keymap for the
>> remote bundled with it. When you load the driver it will poke the
>> input system and install the map. Any additional keymaps would get
>> loaded from user space. You would load one keymap per input device.
>>
>> You might have 89 maps in the kernel with each map being built into
>> the device driver for those 89 IR receivers. But you'll only own one
>> or two of those devices so only one or two of the 89 maps will load.
>> Building the map for the bundled receiver into the device driver is an
>> important part of achieving "just works".
>>
>> I suspect we'll have a 1,000 maps defined after ten years, most of
>> these maps will be loaded from user space. But you'll only have two or
>> three loaded at any one time into your kernel. You need one map per
>> input device created. These maps are tiny, less than 1KB.
>>
>> Having all of these maps is the price of allowing everyone to use any
>> more that they please. If you force the use of universal remotes most
>> of the maps can be eliminated.
>
> Makes sense. Yet, I would add an option at Kbuild to create a module or not
> with the bundled IR keymaps.
>
> So, it should be possible to have all of them completely on userspace or
> having them at kernelspace.
Removing the maps for the bundled remotes from the receiver device
drivers will break "just works". The map will be in an __init section
of the IR device driver. When it is fed into the input system a RAM
based structure will be created. If you really want the 1KB memory
back, use sysfs to remove the default map. An embedded system will
have a bundled remote so it is going to want the map. If you want to
change the default map loading a new map will release the memory from
the previous map.
>
> Cheers,
> Mauro.
>
--
Jon Smirl
[email protected]
Jon Smirl wrote:
> On Tue, Dec 8, 2009 at 8:59 AM, Mauro Carvalho Chehab
> <[email protected]> wrote:
>> Jon Smirl wrote:
>>> On Tue, Dec 8, 2009 at 8:30 AM, Mauro Carvalho Chehab
>>> <[email protected]> wrote:
>>>> Andy Walls wrote:
>>>>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>>>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>>>>> end of the month.
>>>>>>>
>>>>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>>>>> a common set of parameters, so I may be able to set up the decoders to
>>>>>>> handle decoding from two different remote types at once. The HVR boards
>>>>>>> can ship with either type of remote AFAIK.
>>>>>>>
>>>>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>>>>> two different input devices?
>>>>>>>
>>>>>> Can you distinguish between the 2 remotes (not receivers)?
>>>>> Yes. RC-6 and RC-5 are different enough to distinguish between the two.
>>>>> (Honestly I could pile on more protocols that have similar pulse time
>>>>> periods, but that's complexity for no good reason and I don't know of a
>>>>> vendor that bundles 3 types of remotes per TV card.)
>>>> You'll be distinguishing the protocol, not the remote. If I understood
>>>> Dmitry's question, he is asking if you can distinguish between two different
>>>> remotes that may, for example, be using both RC-5 or both RC-6 or one RC-5
>>>> and another RC-6.
>>> RC-5 and RC-6 both contain an address field. My opinion is that
>>> different addresses represent different devices and in general they
>>> should appear on an input devices per address.
>> The same IR can produce two different addresses. The IR bundled with my satellite
>> STB produces two different codes, depending if you previously pressed <TV> or <SAT>
>> key (in fact, I think it can even produce different protocols for TV, as it can
>> be configured to work with different TV sets).
>
> You have a multi-function remote.
Yes.
> That's why those keys don't send codes. When writing code you should
> think of this remote as being two indpendent virtual remotes, not a
> single one.
Not really. I may think on it as a single device and use the two groups
of functions to control two aspects at the same application.
For example, I may map the <TV> group on kaffeine for DVB reception and the
<SAT> group for DVD (well, probably, in this case, I'll use an IR with
<TV> and <DVD> keys, instead ;) ).
> By using maps containing the two different addresses for <TV> and
> <SAT> you can split these commands onto two different evdev devices.
True. I can do it, but I can opt to have both mapped as one evdev device as well.
This will basically depend on how I want to mount my environment.
> This model is complicated by the fact that some remotes that look like
> multi-function remotes aren't really multifunction. The remote bundled
> with the MS MCE receiver is one. That remote is a single function
> device even though it has function buttons for TV, Music, Pictures,
> etc.
It is very common to have such remotes bundled with multimedia devices.
An unsolved question on my mind is how should we map such IR's? Should we
provide a way for them to emulate a multifunction IR (for example, after pressing
TV key, subsequent keystrokes would be directed to the TV evdev device?), or
should we let this up to some userspace app to handle this case?
Cheers,
Mauro.
Jon Smirl wrote:
> On Tue, Dec 8, 2009 at 9:16 AM, Mauro Carvalho Chehab
> <[email protected]> wrote:
>> Jon Smirl wrote:
>>> On Tue, Dec 8, 2009 at 8:40 AM, Mauro Carvalho Chehab
>>> <[email protected]> wrote:
>>>> Jon Smirl wrote:
>>>>> On Tue, Dec 8, 2009 at 7:35 AM, Andy Walls <[email protected]> wrote:
>>>>>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>>>>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>>>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>>>>>> end of the month.
>>>>>>>>
>>>>>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>>>>>> a common set of parameters, so I may be able to set up the decoders to
>>>>>>>> handle decoding from two different remote types at once. The HVR boards
>>>>>>>> can ship with either type of remote AFAIK.
>>>>>>>>
>>>>>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>>>>>> two different input devices?
>>>>>>>>
>>>>>>> Can you distinguish between the 2 remotes (not receivers)?
>>>>>> Yes. RC-6 and RC-5 are different enough to distinguish between the two.
>>>>>> (Honestly I could pile on more protocols that have similar pulse time
>>>>>> periods, but that's complexity for no good reason and I don't know of a
>>>>>> vendor that bundles 3 types of remotes per TV card.)
>>>>>>
>>>>>>
>>>>>>> Like I said,
>>>>>>> I think the preferred way is to represent every remote that can be
>>>>>>> distinguished from each other as a separate input device.
>>>>>> OK. With RC-5, NEC, and RC-6 at least there is also an address or
>>>>>> system byte or word to distingish different remotes. However creating
>>>>>> multiple input devices on the fly for detected remotes would be madness
>>>>>> - especially with a decoding error in the address bits.
>>>>> I agree that creating devices on the fly has problems. Another
>>>>> solution is to create one device for each map that is loaded. There
>>>>> would be a couple built-in maps for bundled remotes - each would
>>>>> create a device. Then the user could load more maps with each map
>>>>> creating a device.
>>>> No, please. We currently have already 89 different keymaps in-kernel. Creating
>>>> 89 different interfaces per IR receiver is not useful at all.
>>>>
>>>> IMO, the interfaces should be created as the keymaps are associated
>>>> to an specific IR receiver.
>>> Each IR receiver device driver would have a built-in keymap for the
>>> remote bundled with it. When you load the driver it will poke the
>>> input system and install the map. Any additional keymaps would get
>>> loaded from user space. You would load one keymap per input device.
>>>
>>> You might have 89 maps in the kernel with each map being built into
>>> the device driver for those 89 IR receivers. But you'll only own one
>>> or two of those devices so only one or two of the 89 maps will load.
>>> Building the map for the bundled receiver into the device driver is an
>>> important part of achieving "just works".
>>>
>>> I suspect we'll have a 1,000 maps defined after ten years, most of
>>> these maps will be loaded from user space. But you'll only have two or
>>> three loaded at any one time into your kernel. You need one map per
>>> input device created. These maps are tiny, less than 1KB.
>>>
>>> Having all of these maps is the price of allowing everyone to use any
>>> more that they please. If you force the use of universal remotes most
>>> of the maps can be eliminated.
>> Makes sense. Yet, I would add an option at Kbuild to create a module or not
>> with the bundled IR keymaps.
>>
>> So, it should be possible to have all of them completely on userspace or
>> having them at kernelspace.
>
> Removing the maps for the bundled remotes from the receiver device
> drivers will break "just works".
No. This can be provided by an udev application that will load the keytable
when the device is connected.
Of course before adding it into a module, we'll need to write such app.
This will only affects the need of IR during boot time.
> The map will be in an __init section
> of the IR device driver. When it is fed into the input system a RAM
> based structure will be created.
We can't use __init, since another device needing the keymap may be hot-plugged.
> If you really want the 1KB memory
> back, use sysfs to remove the default map. An embedded system will
> have a bundled remote so it is going to want the map.
Yes, but it needs just one map, not all of them. The maps shouldn't be linked
into the drivers, as the same map is used by several different devices on
different drivers. So, the option is to allow customizing the available keymaps,
if CONFIG_EMBEDDED.
Cheers,
Mauro.
On Tue, Dec 8, 2009 at 9:34 AM, Mauro Carvalho Chehab
<[email protected]> wrote:
> Jon Smirl wrote:
>> On Tue, Dec 8, 2009 at 8:59 AM, Mauro Carvalho Chehab
>> <[email protected]> wrote:
>>> Jon Smirl wrote:
>>>> On Tue, Dec 8, 2009 at 8:30 AM, Mauro Carvalho Chehab
>>>> <[email protected]> wrote:
>>>>> Andy Walls wrote:
>>>>>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>>>>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>>>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>>>>>> end of the month.
>>>>>>>>
>>>>>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>>>>>> a common set of parameters, so I may be able to set up the decoders to
>>>>>>>> handle decoding from two different remote types at once. ?The HVR boards
>>>>>>>> can ship with either type of remote AFAIK.
>>>>>>>>
>>>>>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>>>>>> two different input devices?
>>>>>>>>
>>>>>>> Can you distinguish between the 2 remotes (not receivers)?
>>>>>> Yes. ?RC-6 and RC-5 are different enough to distinguish between the two.
>>>>>> (Honestly I could pile on more protocols that have similar pulse time
>>>>>> periods, but that's complexity for no good reason and I don't know of a
>>>>>> vendor that bundles 3 types of remotes per TV card.)
>>>>> You'll be distinguishing the protocol, not the remote. If I understood
>>>>> Dmitry's question, he is asking if you can distinguish between two different
>>>>> remotes that may, for example, be using both RC-5 or both RC-6 or one RC-5
>>>>> and another RC-6.
>>>> RC-5 and RC-6 both contain an address field. ?My opinion is that
>>>> different addresses represent different devices and in general they
>>>> should appear on an input devices per address.
>>> The same IR can produce two different addresses. The IR bundled with my satellite
>>> STB produces two different codes, depending if you previously pressed <TV> or <SAT>
>>> key (in fact, I think it can even produce different protocols for TV, as it can
>>> be configured to work with different TV sets).
>>
>> You have a multi-function remote.
>
> Yes.
>
>> That's why those keys don't send codes. When writing code you should
>> think of this remote as being two indpendent virtual remotes, not a
>> single one.
>
> Not really. I may think on it as a single device and use the two groups
> of functions to control two aspects at the same application.
>
> For example, I may map the <TV> group on kaffeine for DVB reception and the
> <SAT> group for DVD (well, probably, in this case, I'll use an IR with
> <TV> and <DVD> keys, instead ;) ).
>
>> By using maps containing the two different addresses for <TV> and
>> <SAT> you can split these commands onto two different evdev devices.
>
> True. I can do it, but I can opt to have both mapped as one evdev device as well.
> This will basically depend on how I want to mount my environment.
>
>> This model is complicated by the fact that some remotes that look like
>> multi-function remotes aren't really multifunction. The remote bundled
>> with the MS MCE receiver is one. That remote is a single function
>> device even though it has function buttons for TV, Music, Pictures,
>> etc.
>
> It is very common to have such remotes bundled with multimedia devices.
>
> An unsolved question on my mind is how should we map such IR's? Should we
> provide a way for them to emulate a multifunction IR (for example, after pressing
> TV key, subsequent keystrokes would be directed to the TV evdev device?), or
> should we let this up to some userspace app to handle this case?
Splitting them into multiple devices requires remembering state and
scripting so it needs to be done in user space. If the user wants to
control a radio app and a home automation app they need to choose.
Keep the bundled remote and do some non-trivial scripting or buy a
universal remote.
Universal remotes make it much easier to achieve "just works".
The IR core can contain default universal profiles for various classes
of devices. Say Morotola_DVR and SciAtlanta_DVR. The core would check
if the receiver is cable of receiving these profiles before loading
them. There would be ten of these default universal profiles at most
and you can unload them from RAM if they aren't needed.
Now Myth can have a menu with three remote choices:
Universal Morotola_DVR
Universal SciAtlanta_DVR
Bundled
The Bundled choice came from the map built into the IR receiver's device driver.
The other two choices were loaded by the IR core after ensuring that
the hardware could receive from a universal remote.
The core would also load a couple of default radio profiles
Univeral SonyDR112_RADIO
Univeral OnkyoTX8255_RADIO
Same for automation and mouse/keyboard emulation.
Myth looks in sysfs and builds a menu containing DVR devices and all
bundled entries. First app to open the "Bundled" device gets to keep
it.
These apps could take "just works" even farther. When they start up
they could listen on all three evdev devices: Morotola_DVR,
SciAtlanta_DVR, Bundled. And then if you find Myth responding to
unwanted commands you could disable the unwanted profiles by
deselecting them in the Myth UI.
All of this may seem complicated to build, but the purpose is to
create an environment where a non-technical user can get an IR remote
working without needing detailed knowledge about how IR protocols
work.
--
Jon Smirl
[email protected]
On Tue, Dec 8, 2009 at 9:40 AM, Mauro Carvalho Chehab
<[email protected]> wrote:
> Jon Smirl wrote:
>> On Tue, Dec 8, 2009 at 9:16 AM, Mauro Carvalho Chehab
>> <[email protected]> wrote:
>>> Jon Smirl wrote:
>>>> On Tue, Dec 8, 2009 at 8:40 AM, Mauro Carvalho Chehab
>>>> <[email protected]> wrote:
>>>>> Jon Smirl wrote:
>>>>>> On Tue, Dec 8, 2009 at 7:35 AM, Andy Walls <[email protected]> wrote:
>>>>>>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>>>>>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>>>>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>>>>>>> end of the month.
>>>>>>>>>
>>>>>>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>>>>>>> a common set of parameters, so I may be able to set up the decoders to
>>>>>>>>> handle decoding from two different remote types at once. ?The HVR boards
>>>>>>>>> can ship with either type of remote AFAIK.
>>>>>>>>>
>>>>>>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>>>>>>> two different input devices?
>>>>>>>>>
>>>>>>>> Can you distinguish between the 2 remotes (not receivers)?
>>>>>>> Yes. ?RC-6 and RC-5 are different enough to distinguish between the two.
>>>>>>> (Honestly I could pile on more protocols that have similar pulse time
>>>>>>> periods, but that's complexity for no good reason and I don't know of a
>>>>>>> vendor that bundles 3 types of remotes per TV card.)
>>>>>>>
>>>>>>>
>>>>>>>> ?Like I said,
>>>>>>>> I think the preferred way is to represent every remote that can be
>>>>>>>> distinguished from each other as a separate input device.
>>>>>>> OK. ?With RC-5, NEC, and RC-6 at least there is also an address or
>>>>>>> system byte or word to distingish different remotes. ?However creating
>>>>>>> multiple input devices on the fly for detected remotes would be madness
>>>>>>> - especially with a decoding error in the address bits.
>>>>>> I agree that creating devices on the fly has problems. Another
>>>>>> solution is to create one device for each map that is loaded. There
>>>>>> would be a couple built-in maps for bundled remotes - each would
>>>>>> create a device. Then the user could load more maps with each map
>>>>>> creating a device.
>>>>> No, please. We currently have already 89 different keymaps in-kernel. Creating
>>>>> 89 different interfaces per IR receiver is not useful at all.
>>>>>
>>>>> IMO, the interfaces should be created as the keymaps are associated
>>>>> to an specific IR receiver.
>>>> Each IR receiver device driver would have a built-in keymap for the
>>>> remote bundled with it. When you load the driver it will poke the
>>>> input system and install the map. Any additional keymaps would get
>>>> loaded from user space. You would load one keymap per input device.
>>>>
>>>> You might have 89 maps in the kernel with each map being built into
>>>> the device driver for those 89 IR receivers. But you'll only own one
>>>> or two of those devices so only one or two of the 89 maps will load.
>>>> Building the map for the bundled receiver into the device driver is an
>>>> important part of achieving "just works".
>>>>
>>>> I suspect we'll have a 1,000 maps defined after ten years, most of
>>>> these maps will be loaded from user space. But you'll only have two or
>>>> three loaded at any one time into your kernel. You need one map per
>>>> input device created. These maps are tiny, less than 1KB.
>>>>
>>>> Having all of these maps is the price of allowing everyone to use any
>>>> more that they please. If you force the use of universal remotes most
>>>> of the maps can be eliminated.
>>> Makes sense. Yet, I would add an option at Kbuild to create a module or not
>>> with the bundled IR keymaps.
>>>
>>> So, it should be possible to have all of them completely on userspace or
>>> having them at kernelspace.
>>
>> Removing the maps for the bundled remotes from the receiver device
>> drivers will break "just works".
>
> No. This can be provided by an udev application that will load the keytable
> when the device is connected.
Why do you want to pull the 1KB default mapping table out of the
device driver __init section and more it to a udev script? Now we will
have to maintain a parallel udev script for ever receiver's device
driver.
The purpose of putting this table into __init is to get rid of all
these udev scripts in the default case.
>
> Of course before adding it into a module, we'll need to write such app.
>
> This will only affects the need of IR during boot time.
>
>> The map will be in an __init section
>> of the IR device driver. When it is fed into the input system a RAM
>> based structure will be created.
>
> We can't use __init, since another device needing the keymap may be hot-plugged.
You can handle that with __devinit
>> If you really want the 1KB memory
>> back, use sysfs to remove the default map. ?An embedded system will
>> have a bundled remote so it is going to want the map.
>
> Yes, but it needs just one map, not all of them. The maps shouldn't be linked
> into the drivers, as the same map is used by several different devices on
Link them or #include them, it doesn't make any difference.
> different drivers. So, the option is to allow customizing the available keymaps,
> if CONFIG_EMBEDDED.
>
> Cheers,
> Mauro.
>
--
Jon Smirl
[email protected]
Mauro Carvalho Chehab <[email protected]> writes:
> Jon Smirl wrote:
>
>> This model is complicated by the fact that some remotes that look
>> like multi-function remotes aren't really multifunction. The remote
>> bundled with the MS MCE receiver is one. That remote is a single
>> function device even though it has function buttons for TV, Music,
>> Pictures, etc.
>
> An unsolved question on my mind is how should we map such IR's? Should
> we provide a way for them to emulate a multifunction IR (for example,
> after pressing TV key, subsequent keystrokes would be directed to the
> TV evdev device?), or should we let this up to some userspace app to
> handle this case?
This case feels similar to that of Caps Lock, Num Lock and Scrool Lock,
but I don't know if that scheme could be applied here.
--
Regards,
Feri.
Jon Smirl wrote:
> On Tue, Dec 8, 2009 at 9:34 AM, Mauro Carvalho Chehab
> <[email protected]> wrote:
>> Jon Smirl wrote:
>>> On Tue, Dec 8, 2009 at 8:59 AM, Mauro Carvalho Chehab
>>> <[email protected]> wrote:
>>>> Jon Smirl wrote:
>>>>> On Tue, Dec 8, 2009 at 8:30 AM, Mauro Carvalho Chehab
>>>>> <[email protected]> wrote:
>>>>>> Andy Walls wrote:
>>>>>>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>>>>>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>>>>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>>>>>>> end of the month.
>>>>>>>>>
>>>>>>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>>>>>>> a common set of parameters, so I may be able to set up the decoders to
>>>>>>>>> handle decoding from two different remote types at once. The HVR boards
>>>>>>>>> can ship with either type of remote AFAIK.
>>>>>>>>>
>>>>>>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>>>>>>> two different input devices?
>>>>>>>>>
>>>>>>>> Can you distinguish between the 2 remotes (not receivers)?
>>>>>>> Yes. RC-6 and RC-5 are different enough to distinguish between the two.
>>>>>>> (Honestly I could pile on more protocols that have similar pulse time
>>>>>>> periods, but that's complexity for no good reason and I don't know of a
>>>>>>> vendor that bundles 3 types of remotes per TV card.)
>>>>>> You'll be distinguishing the protocol, not the remote. If I understood
>>>>>> Dmitry's question, he is asking if you can distinguish between two different
>>>>>> remotes that may, for example, be using both RC-5 or both RC-6 or one RC-5
>>>>>> and another RC-6.
>>>>> RC-5 and RC-6 both contain an address field. My opinion is that
>>>>> different addresses represent different devices and in general they
>>>>> should appear on an input devices per address.
>>>> The same IR can produce two different addresses. The IR bundled with my satellite
>>>> STB produces two different codes, depending if you previously pressed <TV> or <SAT>
>>>> key (in fact, I think it can even produce different protocols for TV, as it can
>>>> be configured to work with different TV sets).
>>> You have a multi-function remote.
>> Yes.
>>
>>> That's why those keys don't send codes. When writing code you should
>>> think of this remote as being two indpendent virtual remotes, not a
>>> single one.
>> Not really. I may think on it as a single device and use the two groups
>> of functions to control two aspects at the same application.
>>
>> For example, I may map the <TV> group on kaffeine for DVB reception and the
>> <SAT> group for DVD (well, probably, in this case, I'll use an IR with
>> <TV> and <DVD> keys, instead ;) ).
>>
>>> By using maps containing the two different addresses for <TV> and
>>> <SAT> you can split these commands onto two different evdev devices.
>> True. I can do it, but I can opt to have both mapped as one evdev device as well.
>> This will basically depend on how I want to mount my environment.
>>
>>> This model is complicated by the fact that some remotes that look like
>>> multi-function remotes aren't really multifunction. The remote bundled
>>> with the MS MCE receiver is one. That remote is a single function
>>> device even though it has function buttons for TV, Music, Pictures,
>>> etc.
>> It is very common to have such remotes bundled with multimedia devices.
>>
>> An unsolved question on my mind is how should we map such IR's? Should we
>> provide a way for them to emulate a multifunction IR (for example, after pressing
>> TV key, subsequent keystrokes would be directed to the TV evdev device?), or
>> should we let this up to some userspace app to handle this case?
>
> Splitting them into multiple devices requires remembering state and
> scripting so it needs to be done in user space.
It shouldn't be hard to do it in kernelspace, since you'll need to have
one evdev interface associated with the IR anyway, but this will add
some extra complexity at the scancode->keycode conversion, but I'm wandering
if we should do it or not.
Maybe the better is to not do it in kernelspace, to avoid adding there an
extra complexity that can easily be done in userspace.
> If the user wants to
> control a radio app and a home automation app they need to choose.
> Keep the bundled remote and do some non-trivial scripting or buy a
> universal remote.
Ok, but using the shipped IR even without a separate address group for
different applications, and having it controlling radio app and tv app
(not simultaneously) should not be hard, but I LIRC already covers such
usecase, so maybe we don't need to worry about it.
> Universal remotes make it much easier to achieve "just works".
True.
> The IR core can contain default universal profiles for various classes
> of devices. Say Morotola_DVR and SciAtlanta_DVR. The core would check
> if the receiver is cable of receiving these profiles before loading
> them. There would be ten of these default universal profiles at most
> and you can unload them from RAM if they aren't needed.
>
> Now Myth can have a menu with three remote choices:
> Universal Morotola_DVR
> Universal SciAtlanta_DVR
> Bundled
>
> The Bundled choice came from the map built into the IR receiver's device driver.
> The other two choices were loaded by the IR core after ensuring that
> the hardware could receive from a universal remote.
>
> The core would also load a couple of default radio profiles
> Univeral SonyDR112_RADIO
> Univeral OnkyoTX8255_RADIO
> Same for automation and mouse/keyboard emulation.
Agreed.
> Myth looks in sysfs and builds a menu containing DVR devices and all
> bundled entries. First app to open the "Bundled" device gets to keep
> it.
Myth (or other userspace apps) don't need to to that, since we've standardized
the keycode actions (see the IR chapter of the media DocBook). It just
needs to support the keycodes already defined, for the common case.
> These apps could take "just works" even farther. When they start up
> they could listen on all three evdev devices: Morotola_DVR,
> SciAtlanta_DVR, Bundled. And then if you find Myth responding to
> unwanted commands you could disable the unwanted profiles by
> deselecting them in the Myth UI.
I don't like the idea of automatically loading 3 different keycodes at the
same time. You may have overlaps between different keycode tables. The
better is to have some userspace GUI that will allow the user to select
what keycode table(s) he want to be available, if he decides to not use the
bundled IR.
The same applies to applications: if you have 3 keymaps loaded, is because you
want do do different things with the 3 keymaps (like using keymap 1 for kaffeine,
keymap 2 for mplayer, keymap 3 for mythtv).
So, IR-aware applications should have a setup interface to specify what IR keycodes
are relevant to that particular application, and how to associate an evdev interface
to an specific group of functions (for applications that supports several different
types of media, like MythTV and Kaffeine, where you'll end by having a "TV" keymap/evdev,
a "Radio" keymap/evdev, a "CD/DVD" Keymap/evdev, etc).
Btw, if we're doing that, IMO, we should have an string sysfs alias attribute,
to allow associating the userspace application to an specific keymap alias
(like "radio", "tv", etc.).
> All of this may seem complicated to build, but the purpose is to
> create an environment where a non-technical user can get an IR remote
> working without needing detailed knowledge about how IR protocols
> work.
IMO, this is an important requisite to fulfill.
Cheers,
Mauro.
On Tue, Dec 08, 2009 at 09:44:29AM -0200, Mauro Carvalho Chehab wrote:
> Dmitry Torokhov wrote:
> > On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
> >> On Mon, 2009-12-07 at 13:19 -0500, Jarod Wilson wrote:
> >>> On Nov 26, 2009, at 2:43 PM, Andy Walls wrote:
> >>>
> >>>> On Thu, 2009-11-26 at 12:05 -0200, Mauro Carvalho Chehab wrote:
> >>>>> Krzysztof Halasa wrote:
> >>>>>> Andy Walls <[email protected]> writes:
> >>>>>>
> >>>>>>> I would also note that RC-6 Mode 6A, used by most MCE remotes, was
> >>>>>>> developed by Philips, but Microsoft has some sort of licensing interest
> >>>>>>> in it and it is almost surely encumbered somwhow:
> >>>>>> I don't know about legal problems in some countries but from the
> >>>>>> technical POV handling the protocol in the kernel is more efficient
> >>>>>> or (/and) simpler.
> >>>>> A software licensing from Microsoft won't apply to Linux kernel, so I'm
> >>>>> assuming that you're referring to some patent that they could be filled
> >>>>> about RC6 mode 6A.
> >>>>>
> >>>>> I don't know if is there any US patent pending about it (AFAIK, only US
> >>>>> accepts software patents), but there are some prior-art for IR key
> >>>>> decoding. So, I don't see what "innovation" RC6 would be adding.
> >>>>> If it is some new way to transmit waves, the patent issues
> >>>>> aren't related to software, and the device manufacturer had already handled
> >>>>> it when they made their devices.
> >>>>>
> >>>>> If it is just a new keytable, this issue
> >>>>> could be easily solved by loading the keytable via userspace.
> >>>>>
> >>>>> Also, assuming that you can use the driver only with a hardware that comes
> >>>>> with a licensed software, the user has already the license for using it.
> >>>>>
> >>>>> Do you have any details on what patents they are claiming?
> >>>> The US Philips RC-6 patent is US Patent 5,877,702
> >>>>
> >>>> http://www.google.com/patents?vid=USPAT5877702
> >>>>
> >>>> Click on download PDF to get a copy of the whole patent.
> >>>>
> >>>> I am not a lawyer. Philips claims' all appear to tie to a transmitter
> >>>> or receiver as part of a system, but most of the claims are about
> >>>> information and bit positions and lengths.
> >>> ...
> >>>> IMO, given
> >>>>
> >>>> a. the dearth of public information about RC-6, indicating someone
> >>>> thinks it's their trade secret or intellectual property
> >>>>
> >>>> b. Microsoft claiming to license something related to the MCE remote
> >>>> protocols (which are obviously RC-6 Mode 6A),
> >>>>
> >>>> c. my inability to draw a "clear, bright line" that RC-6 Mode 6A
> >>>> encoding and decoding, as needed by MCE remotes, implemented in software
> >>>> doesn't violate anyone's government granted rights to exclusivity.
> >>>>
> >>>> I think it's much better to implement software RC-6 Mode 6A encoding and
> >>>> decoding in user space, doing only the minimum needed to get the
> >>>> hardware setup and going in the kernel.
> >>>>
> >>>> Encoding/decoding of RC-6 by microcontrollers with firmware doesn't
> >>>> worry me.
> >>>>
> >>>>
> >>>> Maybe I'm being too conservative here, but I have a personal interest in
> >>>> keeping Linux free and unencumbered even in the US which, I cannot deny,
> >>>> has a patent system that is screwed up.
> >>> So I had one of the people who does all the license and patent audits
> >>> for Fedora packages look at the Philips patent on RC-6. He's 100%
> >>> positive that the patent *only* covers hardware, there should be no
> >>> problem whatsoever writing a software decoder for RC-6.
> >> OK. Thanks for having some professionals take a look. (I'm assuming
> >> that's the only patent.)
> >>
> >> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
> >> end of the month.
> >>
> >> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
> >> a common set of parameters, so I may be able to set up the decoders to
> >> handle decoding from two different remote types at once. The HVR boards
> >> can ship with either type of remote AFAIK.
> >>
> >> I wonder if I can flip the keytables on the fly or if I have to create
> >> two different input devices?
> >>
> >
> > Can you distinguish between the 2 remotes (not receivers)? Like I said,
> > I think the preferred way is to represent every remote that can be
> > distinguished from each other as a separate input device. Applications
> > expect to query device capabilities and expect them to stay somewhat
> > stable (we do support keymap change but I don't think anyone expectes
> > flip-flopping).
> >
> With RC-5, you have no fields describing the remote. So, all the driver could
> do is an educated guess.
>
> From a quick look I did at the RC-6 Mode 6A docs I found, I suspect that
> you can distinguish two different remotes when someone press a key there.
>
> However, I don't think it is a good idea to automatically create a new interface
> every time a different vendor is detected. Maybe the user simply have a
> RC-6 IR to control his TV and doesn't have any intention on using that
> device on his computer.
>
> IMO, the better is to have an API to allow creation of multiple interfaces
> per IR receiver, based on some scancode matching table and/or on some
> matching mask.
>
> It should be possible to use the filter API to match different IR's by
> vendor/product on protocols that supports it, or to match address/command
> tuples on protocols where you just have those fields.
>
OK, fair enough.
--
Dmitry
On Tue, Dec 08, 2009 at 07:52:02AM -0500, Jon Smirl wrote:
> On Tue, Dec 8, 2009 at 7:35 AM, Andy Walls <[email protected]> wrote:
> > On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
> >> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
> >
> >> > So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
> >> > end of the month.
> >> >
> >> > I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
> >> > a common set of parameters, so I may be able to set up the decoders to
> >> > handle decoding from two different remote types at once. ?The HVR boards
> >> > can ship with either type of remote AFAIK.
> >> >
> >> > I wonder if I can flip the keytables on the fly or if I have to create
> >> > two different input devices?
> >> >
> >>
> >> Can you distinguish between the 2 remotes (not receivers)?
> >
> > Yes. ?RC-6 and RC-5 are different enough to distinguish between the two.
> > (Honestly I could pile on more protocols that have similar pulse time
> > periods, but that's complexity for no good reason and I don't know of a
> > vendor that bundles 3 types of remotes per TV card.)
> >
> >
> >> ?Like I said,
> >> I think the preferred way is to represent every remote that can be
> >> distinguished from each other as a separate input device.
> >
> > OK. ?With RC-5, NEC, and RC-6 at least there is also an address or
> > system byte or word to distingish different remotes. ?However creating
> > multiple input devices on the fly for detected remotes would be madness
> > - especially with a decoding error in the address bits.
>
> I agree that creating devices on the fly has problems. Another
> solution is to create one device for each map that is loaded. There
> would be a couple built-in maps for bundled remotes - each would
> create a device. Then the user could load more maps with each map
> creating a device.
>
> Incoming scancodes are matched against all of the loaded maps and a
> keycode event is generated if a match occurs.
>
How many sancodes do we need to reliably recognize the device though? I
am not sure users would want to press 5 random buttons in order to start
using the remote, unless it happens exactly once and then we manage to
store the data somewhere.
> This illustrates why there should an EV_IR event which communicates
> scancodes, without this event you can't see the scancodes that don't
> match a map entry. A scancode would be first matched against the map,
> then if there as no match an EV_IR event would be reported.
Just report MSC_SCAN always. As I said elsewhere we can extend it to be
multi-dword if needed (just need to agree on endianness).
--
Dmitry
On Tue, Dec 08, 2009 at 07:46:52AM -0500, Andy Walls wrote:
> On Tue, 2009-12-08 at 09:32 -0200, Mauro Carvalho Chehab wrote:
> > Andy Walls wrote:
> > > On Mon, 2009-12-07 at 13:19 -0500, Jarod Wilson wrote:
>
> > > So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
> > > end of the month.
> >
> > Good! Please, try to design the decoder as an independent module that gets
> > data from a kfifo and generate scancodes for the input API.
>
> Hmmm. Let me see how the protoype turns out keeping that design
> objective in mind. I've already got the current RC-5 and NEC decoding
> state machines in cx23885-input a bit layered, but they are taking
> advantage of specific events signaled by my v4l2_subdev implementation.
>
> Strictly speaking the state machines don't have to. All of the remote
> protocols I have played with make framing pretty easy.
>
>
>
> > > I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
> > > a common set of parameters, so I may be able to set up the decoders to
> > > handle decoding from two different remote types at once. The HVR boards
> > > can ship with either type of remote AFAIK.
> > >
> > > I wonder if I can flip the keytables on the fly or if I have to create
> > > two different input devices?
> >
> > IMO, the better is, by default, to open just one input device per IR receiver.
> > >From what I understand from our discussions, if the user wants to filter IR
> > commands into several input interfaces, some userspace interface will be
> > provided to allow the creation of other input interfaces for that purpose.
>
> Hmm. That's not what I just thought I read from Dmitry....
>
I am a resonable guy ;) In cases when we can certainly say that there
are 2 separate remotes (and we know characteristics somehow) we need to
create 2 input devices. Otherwise we can't ;)
--
Dmitry
On Tue, Dec 8, 2009 at 11:27 AM, Mauro Carvalho Chehab
<[email protected]> wrote:
> Jon Smirl wrote:
>> On Tue, Dec 8, 2009 at 9:34 AM, Mauro Carvalho Chehab
>> <[email protected]> wrote:
>>> Jon Smirl wrote:
>>>> On Tue, Dec 8, 2009 at 8:59 AM, Mauro Carvalho Chehab
>>>> <[email protected]> wrote:
>>>>> Jon Smirl wrote:
>>>>>> On Tue, Dec 8, 2009 at 8:30 AM, Mauro Carvalho Chehab
>>>>>> <[email protected]> wrote:
>>>>>>> Andy Walls wrote:
>>>>>>>> On Mon, 2009-12-07 at 20:22 -0800, Dmitry Torokhov wrote:
>>>>>>>>> On Mon, Dec 07, 2009 at 09:42:22PM -0500, Andy Walls wrote:
>>>>>>>>>> So I'll whip up an RC-6 Mode 6A decoder for cx23885-input.c before the
>>>>>>>>>> end of the month.
>>>>>>>>>>
>>>>>>>>>> I can setup the CX2388[58] hardware to look for both RC-5 and RC-6 with
>>>>>>>>>> a common set of parameters, so I may be able to set up the decoders to
>>>>>>>>>> handle decoding from two different remote types at once. ?The HVR boards
>>>>>>>>>> can ship with either type of remote AFAIK.
>>>>>>>>>>
>>>>>>>>>> I wonder if I can flip the keytables on the fly or if I have to create
>>>>>>>>>> two different input devices?
>>>>>>>>>>
>>>>>>>>> Can you distinguish between the 2 remotes (not receivers)?
>>>>>>>> Yes. ?RC-6 and RC-5 are different enough to distinguish between the two.
>>>>>>>> (Honestly I could pile on more protocols that have similar pulse time
>>>>>>>> periods, but that's complexity for no good reason and I don't know of a
>>>>>>>> vendor that bundles 3 types of remotes per TV card.)
>>>>>>> You'll be distinguishing the protocol, not the remote. If I understood
>>>>>>> Dmitry's question, he is asking if you can distinguish between two different
>>>>>>> remotes that may, for example, be using both RC-5 or both RC-6 or one RC-5
>>>>>>> and another RC-6.
>>>>>> RC-5 and RC-6 both contain an address field. ?My opinion is that
>>>>>> different addresses represent different devices and in general they
>>>>>> should appear on an input devices per address.
>>>>> The same IR can produce two different addresses. The IR bundled with my satellite
>>>>> STB produces two different codes, depending if you previously pressed <TV> or <SAT>
>>>>> key (in fact, I think it can even produce different protocols for TV, as it can
>>>>> be configured to work with different TV sets).
>>>> You have a multi-function remote.
>>> Yes.
>>>
>>>> That's why those keys don't send codes. When writing code you should
>>>> think of this remote as being two indpendent virtual remotes, not a
>>>> single one.
>>> Not really. I may think on it as a single device and use the two groups
>>> of functions to control two aspects at the same application.
>>>
>>> For example, I may map the <TV> group on kaffeine for DVB reception and the
>>> <SAT> group for DVD (well, probably, in this case, I'll use an IR with
>>> <TV> and <DVD> keys, instead ;) ).
>>>
>>>> By using maps containing the two different addresses for <TV> and
>>>> <SAT> you can split these commands onto two different evdev devices.
>>> True. I can do it, but I can opt to have both mapped as one evdev device as well.
>>> This will basically depend on how I want to mount my environment.
>>>
>>>> This model is complicated by the fact that some remotes that look like
>>>> multi-function remotes aren't really multifunction. The remote bundled
>>>> with the MS MCE receiver is one. That remote is a single function
>>>> device even though it has function buttons for TV, Music, Pictures,
>>>> etc.
>>> It is very common to have such remotes bundled with multimedia devices.
>>>
>>> An unsolved question on my mind is how should we map such IR's? Should we
>>> provide a way for them to emulate a multifunction IR (for example, after pressing
>>> TV key, subsequent keystrokes would be directed to the TV evdev device?), or
>>> should we let this up to some userspace app to handle this case?
>>
>> Splitting them into multiple devices requires remembering state and
>> scripting so it needs to be done in user space.
>
> It shouldn't be hard to do it in kernelspace, since you'll need to have
> one evdev interface associated with the IR anyway, but this will add
> some extra complexity at the scancode->keycode conversion, but I'm wandering
> if we should do it or not.
>
> Maybe the better is to not do it in kernelspace, to avoid adding there an
> extra complexity that can easily be done in userspace.
>
>> If the user wants to
>> control a radio app and a home automation app they need to choose.
>> Keep the bundled remote and do some non-trivial scripting or buy a
>> universal remote.
>
> Ok, but using the shipped IR even without a separate address group for
> different applications, and having it controlling radio app and tv app
> (not simultaneously) should not be hard, but I LIRC already covers such
> usecase, so maybe we don't need to worry about it.
>
>> Universal remotes make it much easier to achieve "just works".
>
> True.
>
>> The IR core can contain default universal profiles for various classes
>> of devices. Say Morotola_DVR and SciAtlanta_DVR. The core would check
>> if the receiver is cable of receiving these profiles before loading
>> them. There would be ten of these default universal profiles at most
>> and you can unload them from RAM if they aren't needed.
>>
>> Now Myth can have a menu with three remote choices:
>> ?Universal Morotola_DVR
>> ?Universal SciAtlanta_DVR
>> ?Bundled
>>
>> The Bundled choice came from the map built into the IR receiver's device driver.
>> The other two choices were loaded by the IR core after ensuring that
>> the hardware could receive from a universal remote.
>>
>> The core would also load a couple of default radio profiles
>> ?Univeral SonyDR112_RADIO
>> ?Univeral OnkyoTX8255_RADIO
>> Same for automation and mouse/keyboard emulation.
>
> Agreed.
>
>> Myth looks in sysfs and builds a menu containing DVR devices and all
>> bundled entries. First app to open the "Bundled" device gets to keep
>> it.
>
> Myth (or other userspace apps) don't need to to that, since we've standardized
> the keycode actions (see the IR chapter of the media DocBook). It just
> needs to support the keycodes already defined, for the common case.
>
>> These apps could take "just works" even farther. When they start up
>> they could listen on all three evdev devices: ?Morotola_DVR,
>> SciAtlanta_DVR, ? Bundled. And then if you find Myth responding to
>> unwanted commands you could disable the unwanted profiles by
>> deselecting them in the Myth UI.
>
> I don't like the idea of automatically loading 3 different keycodes at the
> same time. You may have overlaps between different keycode tables. The
> better is to have some userspace GUI that will allow the user to select
> what keycode table(s) he want to be available, if he decides to not use the
> bundled IR.
Of course there is going to be overlap of the keycodes, but not the
scancodes. There should be almost 100% overlap.
The three maps are there to support a non-technical user, a
sophisticated user will disable two of them. This works because the
non-technical user is only going to use one of the three IR device
profiles. The other two may be loaded, but the user isn't sending any
IR signals that match their maps.
Where this breaks down is if they are using SciAtlanta_DVR to control
MythTV and they also happen to have a physical Motorola DVR in the
same room. The Linux box is going to pick up the commands meant for
the Motorola DVR and both boxes will respond.. In that cause they will
need to figure figure out how to disable the Motorola DVR profile.
But is a non-technical person likely to have two DVRs in the same
room?
>
> The same applies to applications: if you have 3 keymaps loaded, is because you
> want do do different things with the 3 keymaps (like using keymap 1 for kaffeine,
> keymap 2 for mplayer, keymap 3 for mythtv).
>
> So, IR-aware applications should have a setup interface to specify what IR keycodes
> are relevant to that particular application, and how to associate an evdev interface
> to an specific group of functions (for applications that supports several different
> types of media, like MythTV and Kaffeine, where you'll end by having a "TV" keymap/evdev,
> a "Radio" keymap/evdev, a "CD/DVD" Keymap/evdev, etc).
>
> Btw, if we're doing that, IMO, we should have an string sysfs alias attribute,
> to allow associating the userspace application to an specific keymap alias
> (like "radio", "tv", etc.).
>
>> All of this may seem complicated to build, but the purpose is to
>> create an environment where a non-technical user can get an IR remote
>> working without needing detailed knowledge about how IR protocols
>> work.
>
> IMO, this is an important requisite to fulfill.
>
> Cheers,
> Mauro.
>
--
Jon Smirl
[email protected]
Jon Smirl <[email protected]> writes:
> Why do you want to pull the 1KB default mapping table out of the
> device driver __init section and more it to a udev script? Now we will
> have to maintain a parallel udev script for ever receiver's device
> driver.
Of course no. We will need a single program (script etc.) for all
devices. And we will need a database of the known remotes (scan and key
codes).
> You can handle that with __devinit
__devinit is NOP with hot-plug.
Fortunately we don't need the keymaps in the kernel.
For certain uses we may (and may not) need to have one keymap built-in,
perhaps something similar to the embedded initrd.
--
Krzysztof Halasa
Krzysztof Halasa wrote:
> Jon Smirl <[email protected]> writes:
>
>> Why do you want to pull the 1KB default mapping table out of the
>> device driver __init section and more it to a udev script? Now we will
>> have to maintain a parallel udev script for ever receiver's device
>> driver.
>
> Of course no. We will need a single program (script etc.) for all
> devices. And we will need a database of the known remotes (scan and key
> codes).
The keycode database can be easily extracted from kernel drivers by script.
I have it already at V4L/DVB development tree.
>> You can handle that with __devinit
>
> __devinit is NOP with hot-plug.
>
> Fortunately we don't need the keymaps in the kernel.
> For certain uses we may (and may not) need to have one keymap built-in,
> perhaps something similar to the embedded initrd.
I still think the better is to have them in kernel, but compiled only
if selected at Kbuild.
Cheers,
Mauro.
Dmitry Torokhov wrote:
> I am a resonable guy ;) In cases when we can certainly say that there
> are 2 separate remotes (and we know characteristics somehow) we need to
> create 2 input devices. Otherwise we can't ;)
Only on very few specific cases (a few protocols), you can be (almost) sure.
Even on this case, universal remotes can fake another IR.
Cheers,
Mauro.
Jon Smirl wrote:
>> I don't like the idea of automatically loading 3 different keycodes at the
>> same time. You may have overlaps between different keycode tables. The
>> better is to have some userspace GUI that will allow the user to select
>> what keycode table(s) he want to be available, if he decides to not use the
>> bundled IR.
>
> Of course there is going to be overlap of the keycodes, but not the
> scancodes. There should be almost 100% overlap.
What prevents users to create overlaps at scancodes? We might add some
protection, but, providing that different keycode tables can be used by
different applications, why do we need to prevent it?
> The three maps are there to support a non-technical user, a
> sophisticated user will disable two of them. This works because the
> non-technical user is only going to use one of the three IR device
> profiles. The other two may be loaded, but the user isn't sending any
> IR signals that match their maps.
I doubt you can map all cases with just three profiles.
>
> Where this breaks down is if they are using SciAtlanta_DVR to control
> MythTV and they also happen to have a physical Motorola DVR in the
> same room.
> The Linux box is going to pick up the commands meant for
> the Motorola DVR and both boxes will respond.. In that cause they will
> need to figure figure out how to disable the Motorola DVR profile.
I used to have a Set Top Box that has some broken code to decode IR. So,
sometimes, when I used to press a key on my TV IR, the STB were getting
the code, producing a really bad result. That's really bad.
A normal user is able to click on some graphical application and
select his IR model. The app may even have some photos or pictures
representing the most used IR's. This is better than letting him to to
to some forum, asking his friends, etc, trying to figure out why his
PC is doing something wrong when he changes a channel on his TV.
> But is a non-technical person likely to have two DVRs in the same
> room?
Well, I know someone that has an 8 year old children with a setup like this:
a PC monitor that has an IR, and a PC with a TV board also with IR.
Of course, both the monitor and the PC are at the same room.
Cheers,
Mauro.
On Mon, 23 Nov 2009, Krzysztof Halasa wrote:
> Devin Heitmueller <[email protected]> writes:
>
>> There is an argument to be made that since it may be desirable for
>> both IR receivers and transmitters to share the same table of remote
>> control definitions, it might make sense to at least *consider* how
>> the IR transmitter interface is going to work, even if it is decided
>> to not implement such a design in the first revision.
>>
>> Personally, I would hate to see a situation where we find out that we
>> took a bad approach because nobody considered what would be required
>> for IR transmitters to reuse the same remote control definition data.
>
> I briefly though about such possibility, but dismissed it with
> assumption that we won't transmit the same codes (including "key" codes)
> that we receive.
>
> Perhaps I'm wrong.
I could definantly see this happening. the computer receives the 'play'
button from a dvd remote, issues commands to control the audio system, dim
lights, and then sends the 'play' button to the DVD player inside a
cabinet where it can't see the remote directly.
but in any case, it shouldn't be hard to share a table of mappings.
David Lang