[linux-dvb] [patch 5/8] budget-ci IR: integrate with ir-common

David Härdeman david at hardeman.nu
Tue Oct 3 02:01:55 CEST 2006


This converts the budget-ci driver so that it uses ir-common for some of its
IR processing. In particular, the keymap for the Nova-T (sub 13c2:1011) is
switched to the Hauppauge grey/black keymap, of which the keys on the
supplied R808 remote control form a subset.

The old budget-ci keymap is moved to ir-keymaps.c and is used for other
remotes.

The debounce logic for buggy remotes (i.e. Zenith) is made conditional the
new debounce parameter and defaults to off (so that repeat keypresses aren't
ignored for all working remotes).

Some parts are based on Darren Salt's dvb-ir patchset.

Signed-off-by: David Härdeman <david at hardeman.nu>


Index: v4l-dvb/linux/drivers/media/common/ir-keymaps.c
===================================================================
--- v4l-dvb.orig/linux/drivers/media/common/ir-keymaps.c	2006-10-02 18:48:22.000000000 +0200
+++ v4l-dvb/linux/drivers/media/common/ir-keymaps.c	2006-10-02 18:49:03.000000000 +0200
@@ -1595,3 +1595,58 @@
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_norwood);
+
+/* From reading the following remotes:
+ * Zenith Universal 7 / TV Mode 807 / VCR Mode 837
+ * Hauppauge (from NOVA-CI-s box product)
+ * This is a "middle of the road" approach, differences are noted
+ */
+IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = {
+	[ 0x00 ] = KEY_0,
+	[ 0x01 ] = KEY_1,
+	[ 0x02 ] = KEY_2,
+	[ 0x03 ] = KEY_3,
+	[ 0x04 ] = KEY_4,
+	[ 0x05 ] = KEY_5,
+	[ 0x06 ] = KEY_6,
+	[ 0x07 ] = KEY_7,
+	[ 0x08 ] = KEY_8,
+	[ 0x09 ] = KEY_9,
+	[ 0x0a ] = KEY_ENTER,
+	[ 0x0b ] = KEY_RED,
+	[ 0x0c ] = KEY_POWER,             /* RADIO on Hauppauge */
+	[ 0x0d ] = KEY_MUTE,
+	[ 0x0f ] = KEY_A,                 /* TV on Hauppauge */
+	[ 0x10 ] = KEY_VOLUMEUP,
+	[ 0x11 ] = KEY_VOLUMEDOWN,
+	[ 0x14 ] = KEY_B,
+	[ 0x1c ] = KEY_UP,
+	[ 0x1d ] = KEY_DOWN,
+	[ 0x1e ] = KEY_OPTION,            /* RESERVED on Hauppauge */
+	[ 0x1f ] = KEY_BREAK,
+	[ 0x20 ] = KEY_CHANNELUP,
+	[ 0x21 ] = KEY_CHANNELDOWN,
+	[ 0x22 ] = KEY_PREVIOUS,          /* Prev. Ch on Zenith, SOURCE on Hauppauge */
+	[ 0x24 ] = KEY_RESTART,
+	[ 0x25 ] = KEY_OK,
+	[ 0x26 ] = KEY_CYCLEWINDOWS,      /* MINIMIZE on Hauppauge */
+	[ 0x28 ] = KEY_ENTER,             /* VCR mode on Zenith */
+	[ 0x29 ] = KEY_PAUSE,
+	[ 0x2b ] = KEY_RIGHT,
+	[ 0x2c ] = KEY_LEFT,
+	[ 0x2e ] = KEY_MENU,              /* FULL SCREEN on Hauppauge */
+	[ 0x30 ] = KEY_SLOW,
+	[ 0x31 ] = KEY_PREVIOUS,          /* VCR mode on Zenith */
+	[ 0x32 ] = KEY_REWIND,
+	[ 0x34 ] = KEY_FASTFORWARD,
+	[ 0x35 ] = KEY_PLAY,
+	[ 0x36 ] = KEY_STOP,
+	[ 0x37 ] = KEY_RECORD,
+	[ 0x38 ] = KEY_TUNER,             /* TV/VCR on Zenith */
+	[ 0x3a ] = KEY_C,
+	[ 0x3c ] = KEY_EXIT,
+	[ 0x3d ] = KEY_POWER2,
+	[ 0x3e ] = KEY_TUNER,
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old);
Index: v4l-dvb/linux/drivers/media/dvb/ttpci/Kconfig
===================================================================
--- v4l-dvb.orig/linux/drivers/media/dvb/ttpci/Kconfig	2006-10-02 18:48:22.000000000 +0200
+++ v4l-dvb/linux/drivers/media/dvb/ttpci/Kconfig	2006-10-02 18:49:03.000000000 +0200
@@ -92,6 +92,7 @@
 	select DVB_STV0299 if !DVB_FE_CUSTOMISE
 	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
 	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+	select VIDEO_IR
 	help
 	  Support for simple SAA7146 based DVB cards
 	  (so called Budget- or Nova-PCI cards) without onboard
Index: v4l-dvb/linux/include/media/ir-common.h
===================================================================
--- v4l-dvb.orig/linux/include/media/ir-common.h	2006-10-02 18:48:22.000000000 +0200
+++ v4l-dvb/linux/include/media/ir-common.h	2006-10-02 18:49:03.000000000 +0200
@@ -92,6 +92,7 @@
 extern IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE];
 
 #endif
 
Index: v4l-dvb/linux/drivers/media/dvb/ttpci/budget-ci.c
===================================================================
--- v4l-dvb.orig/linux/drivers/media/dvb/ttpci/budget-ci.c	2006-10-02 18:48:56.000000000 +0200
+++ v4l-dvb/linux/drivers/media/dvb/ttpci/budget-ci.c	2006-10-02 18:49:03.000000000 +0200
@@ -37,6 +37,7 @@
 #include <linux/interrupt.h>
 #include <linux/input.h>
 #include <linux/spinlock.h>
+#include <media/ir-common.h>
 
 #include "dvb_ca_en50221.h"
 #include "stv0299.h"
@@ -65,11 +66,24 @@
 #define SLOTSTATUS_READY	8
 #define SLOTSTATUS_OCCUPIED	(SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
 
+/* Milliseconds during which key presses are regarded as key repeat and during
+ * which the debounce logic is active
+ */
+#define IR_REPEAT_TIMEOUT	350
+
+/* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two),
+ * this setting allows the superflous sequences to be ignored
+ */
+static int debounce = 0;
+module_param(debounce, int, 0644);
+MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)");
+
 struct budget_ci_ir {
 	struct input_dev *dev;
 	struct tasklet_struct msp430_irq_tasklet;
 	char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
 	char phys[32];
+	struct ir_input_state state;
 };
 
 struct budget_ci {
@@ -82,108 +96,42 @@
 	u8 tuner_pll_address; /* used for philips_tdm1316l configs */
 };
 
-/* from reading the following remotes:
-   Zenith Universal 7 / TV Mode 807 / VCR Mode 837
-   Hauppauge (from NOVA-CI-s box product)
-   i've taken a "middle of the road" approach and note the differences
-*/
-static u16 key_map[64] = {
-	/* 0x0X */
-	KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8,
-	KEY_9,
-	KEY_ENTER,
-	KEY_RED,
-	KEY_POWER,		/* RADIO on Hauppauge */
-	KEY_MUTE,
-	0,
-	KEY_A,			/* TV on Hauppauge */
-	/* 0x1X */
-	KEY_VOLUMEUP, KEY_VOLUMEDOWN,
-	0, 0,
-	KEY_B,
-	0, 0, 0, 0, 0, 0, 0,
-	KEY_UP, KEY_DOWN,
-	KEY_OPTION,		/* RESERVED on Hauppauge */
-	KEY_BREAK,
-	/* 0x2X */
-	KEY_CHANNELUP, KEY_CHANNELDOWN,
-	KEY_PREVIOUS,		/* Prev. Ch on Zenith, SOURCE on Hauppauge */
-	0, KEY_RESTART, KEY_OK,
-	KEY_CYCLEWINDOWS,	/* MINIMIZE on Hauppauge */
-	0,
-	KEY_ENTER,		/* VCR mode on Zenith */
-	KEY_PAUSE,
-	0,
-	KEY_RIGHT, KEY_LEFT,
-	0,
-	KEY_MENU,		/* FULL SCREEN on Hauppauge */
-	0,
-	/* 0x3X */
-	KEY_SLOW,
-	KEY_PREVIOUS,		/* VCR mode on Zenith */
-	KEY_REWIND,
-	0,
-	KEY_FASTFORWARD,
-	KEY_PLAY, KEY_STOP,
-	KEY_RECORD,
-	KEY_TUNER,		/* TV/VCR on Zenith */
-	0,
-	KEY_C,
-	0,
-	KEY_EXIT,
-	KEY_POWER2,
-	KEY_TUNER,		/* VCR mode on Zenith */
-	0,
-};
-
-static void msp430_ir_debounce(unsigned long data)
+static void msp430_ir_keyup(unsigned long data)
 {
-	struct input_dev *dev = (struct input_dev *) data;
-
-	if (dev->rep[0] == 0 || dev->rep[0] == ~0) {
-		input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
-		return;
-	}
-
-	dev->rep[0] = 0;
-	dev->timer.expires = jiffies + HZ * 350 / 1000;
-	add_timer(&dev->timer);
-	input_event(dev, EV_KEY, key_map[dev->repeat_key], 2);	/* REPEAT */
+	struct budget_ci_ir *ir = (struct budget_ci_ir *) data;
+	ir_input_nokey(ir->dev, &ir->state);
 }
 
 static void msp430_ir_interrupt(unsigned long data)
 {
 	struct budget_ci *budget_ci = (struct budget_ci *) data;
 	struct input_dev *dev = budget_ci->ir.dev;
-	unsigned int code =
-		ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
-
-	if (code & 0x40) {
-		code &= 0x3f;
-
-		if (timer_pending(&dev->timer)) {
-			if (code == dev->repeat_key) {
-				++dev->rep[0];
-				return;
-			}
-			del_timer(&dev->timer);
-			input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
-		}
-
-		if (!key_map[code]) {
-			printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
+	static int bounces = 0;
+	u32 ir_key;
+	u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
+
+	if (command & 0x40) {
+		ir_key = command & 0x3f;
+
+		if (ir_key != dev->repeat_key && del_timer(&dev->timer))
+			/* We were still waiting for a keyup event but this is a new key */
+			ir_input_nokey(dev, &budget_ci->ir.state);
+
+		if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) {
+			/* Ignore repeated key sequences if requested */
+			bounces--;
 			return;
 		}
 
-		/* initialize debounce and repeat */
-		dev->repeat_key = code;
-		/* Zenith remote _always_ sends 2 sequences */
-		dev->rep[0] = ~0;
-		/* 350 milliseconds */
-		dev->timer.expires = jiffies + HZ * 350 / 1000;
-		/* MAKE */
-		input_event(dev, EV_KEY, key_map[code], !0);
-		add_timer(&dev->timer);
+		if (!timer_pending(&dev->timer))
+			/* New keypress */
+			bounces = debounce;
+
+		/* Prepare a keyup event sometime in the future */
+		mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT));
+
+		/* Generate a new or repeated keypress */
+		ir_input_keydown(dev, &budget_ci->ir.state, ir_key, command);
 	}
 }
 
@@ -191,7 +139,6 @@
 {
 	struct saa7146_dev *saa = budget_ci->budget.dev;
 	struct input_dev *input_dev = budget_ci->ir.dev;
-	int i;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
 	int error;
 #endif
@@ -228,10 +175,30 @@
 # endif
 #endif
 
-	set_bit(EV_KEY, input_dev->evbit);
-	for (i = 0; i < ARRAY_SIZE(key_map); i++)
-		if (key_map[i])
-			set_bit(key_map[i], input_dev->keybit);
+	/* Select keymap */
+	switch (budget_ci->budget.dev->pci->subsystem_device) {
+	case 0x100c:
+	case 0x100f:
+	case 0x1010:
+	case 0x1011:
+	case 0x1012:
+	case 0x1017:
+		/* The hauppauge keymap is a superset of these remotes */
+		ir_input_init(input_dev, &budget_ci->ir.state,
+			      IR_TYPE_RC5, ir_codes_hauppauge_new);
+		break;
+	default:
+		/* unknown remote */
+		ir_input_init(input_dev, &budget_ci->ir.state,
+			      IR_TYPE_RC5, ir_codes_budget_ci_old);
+		break;
+	}
+
+	/* initialise the key-up timeout handler */
+	input_dev->timer.function = msp430_ir_keyup;
+	input_dev->timer.data = (unsigned long) &budget_ci->ir;
+	input_dev->rep[REP_DELAY] = 1;
+	input_dev->rep[REP_PERIOD] = 1;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
 	error = input_register_device(input_dev);
@@ -243,8 +210,6 @@
 	input_register_device(input_dev);
 #endif
 
-	input_dev->timer.function = msp430_ir_debounce;
-
 	tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
 		     (unsigned long) budget_ci);
 
@@ -269,7 +234,7 @@
 	tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
 
 	if (del_timer(&dev->timer))
-		input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
+		ir_input_nokey(dev, &budget_ci->ir.state);
 
 	input_unregister_device(dev);
 }

--
David Härdeman




More information about the linux-dvb mailing list