[linux-dvb] [PATCH] budget-ci: convert to using ir-common, use RC5 addresses etc.

Darren Salt linux at youmustbejoking.demon.co.uk
Sat Apr 1 20:35:46 CEST 2006


Note: this patch depends on the budget-ci patches which I recently posted to
this list.


budget-ci: convert to using ir-common, use RC5 addresses etc.
From: Darren Salt <linux at youmustbejoking.demon.co.uk>

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.

Both bytes from the MSP430 are now required; the interrupt code MUST return
quickly from processing the first byte else it may miss the second byte.
(The first byte has bit 6 set and the key code in bits 5..0; the second has
bit 6 clear and has the RC5 address in bits 4..0 and a flag (edge
signalling) in bit 5.)

The second event from Zenith remote controls should still be ignored. I'm
unable to test this, not having one of these.

Key repeat is properly handled. This requires a small change in ir-common:
it now treats the second and successive calls to ir_input_keydown (for the
same device & key) without an intervening ir_input_nokey() call as repeat
events, and causes input_event to be called with "key repeat" rather than
"key down".

Two module parameters are added. Both are boolean; the described action
occurs when the corresponding value is non-zero.
* ir_debug
    Some unknown keys will be logged. Both code and address are output.
* ir_any_rc5_address
    The RC5 address (if known) will be ignored.

The RC5 address for the R808 remote control for my old Nova-T is 0x1F; this
is the only address configured in this patch, and if any supported card is
recognised as Nova-T, input with any other address (e.g. 0x1E from the A415
remote control for my new Nova-T) will, by default, be rejected.

Signed-off-by: Darren Salt <linux at youmustbejoking.demon.co.uk>

diff --git a/linux/drivers/media/common/ir-functions.c b/linux/drivers/media/common/ir-functions.c
--- a/linux/drivers/media/common/ir-functions.c	Wed Mar 22 16:45:04 2006
+++ b/linux/drivers/media/common/ir-functions.c	Thu Mar 23 02:27:41 2006
@@ -53,7 +53,7 @@
 	}
 	dprintk(1,"%s: key event code=%d down=%d\n",
 		dev->name,ir->keycode,ir->keypressed);
-	input_report_key(dev,ir->keycode,ir->keypressed);
+	input_event(dev, EV_KEY, ir->keycode, ir->keypressed);
 	input_sync(dev);
 }
 
@@ -106,8 +106,10 @@
 		ir->ir_raw  = ir_raw;
 		ir->keycode = keycode;
 		ir->keypressed = 1;
-		ir_input_key_event(dev,ir);
-	}
+	}
+	else
+		ir->keypressed = 2; /* repeat */
+	ir_input_key_event(dev, ir);
 #if 0
 	/* maybe do something like this ??? */
 	input_event(a, EV_IR, ir->ir_type, ir->ir_raw);
diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig
--- a/linux/drivers/media/dvb/ttpci/Kconfig	Wed Mar 22 16:45:04 2006
+++ b/linux/drivers/media/dvb/ttpci/Kconfig	Thu Mar 23 02:27:41 2006
@@ -85,6 +85,7 @@
 	select DVB_STV0297
 	select DVB_STV0299
 	select DVB_TDA1004X
+	select VIDEO_IR
 	help
 	  Support for simple SAA7146 based DVB cards
 	  (so called Budget- or Nova-PCI cards) without onboard
diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c
--- a/linux/drivers/media/dvb/ttpci/budget-ci.c	Wed Mar 22 16:45:04 2006
+++ b/linux/drivers/media/dvb/ttpci/budget-ci.c	Thu Mar 23 02:27:41 2006
@@ -5,6 +5,7 @@
  *
  *     msp430 IR support contributed by Jack Thomasson <jkt at Helius.COM>
  *     partially based on the Siemens DVB driver by Ralph+Marcus Metzler
+ *     modified to use ir-common by Darren Salt <linux at youmustbejoking.demon.co.uk>
  *
  * CI interface support (c) 2004 Andrew de Quincey <adq_dvb at lidskialf.net>
  *
@@ -37,6 +38,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,12 +67,36 @@
 #define SLOTSTATUS_READY	8
 #define SLOTSTATUS_OCCUPIED	(SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
 
+/* We need some appropriate timeout due to the lack of key-up. This has to
+ * be longer than the RC's own repeat rate; we need to allow for occasional
+ * unreceived transmissions.
+ */
+#define IR_REPEAT_TIMEOUT      240
+
+/* RC5 address wildcard */
+#define IR_ADDRESS_ANY		255
+
+static int ir_debug = 0;
+module_param(ir_debug, int, 0644);	/* debug level [IR] */
+MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
+
+static int ir_any_rc5_address = 0;
+module_param(ir_any_rc5_address, int, 0644);
+MODULE_PARM_DESC(ir_any_rc5_address, "allow any RC5 address [IR]");
+
 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 timer_list timeout; /* key-up */
+	u8 address;
+	u8 keycode;
+	u8 keydown;
+	u8 last_edge;
 };
+#define IR_NO_DATA (u8)(0x80)
 
 struct budget_ci {
 	struct budget budget;
@@ -86,7 +112,7 @@
    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] = {
+static IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = {
 	/* 0x0X */
 	KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8,
 	KEY_9,
@@ -137,17 +163,10 @@
 
 static void msp430_ir_debounce(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->keycode = IR_NO_DATA;
+	ir->keydown = 0;
+	ir_input_nokey (ir->dev, &ir->state);
 }
 
 static void msp430_ir_interrupt(unsigned long data)
@@ -158,31 +177,41 @@
 		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);
+		budget_ci->ir.keycode = code & 0x3F;
+		return;
+	}
+	else if (ir_any_rc5_address ||
+		 (budget_ci->ir.address == IR_ADDRESS_ANY) ||
+		 (budget_ci->ir.address == (code & 0x1F))) {
+		if (timer_pending(&budget_ci->ir.timeout) &&
+		    ((code & 0x20) != budget_ci->ir.last_edge)) {
+			budget_ci->ir.keydown = 0;
+			del_timer(&budget_ci->ir.timeout);
+			ir_input_nokey(dev, &budget_ci->ir.state);
 		}
 
-		if (!key_map[code]) {
-			printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
-			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);
+		budget_ci->ir.last_edge = code & 0x20;
+
+		code = budget_ci->ir.keycode;
+		budget_ci->ir.keycode = IR_NO_DATA;
+
+		/* Zenith remote always sends 2 sequences: ignore the second.
+		 * Also, if code == IR_NO_DATA, we've missed the first byte;
+		 * if this happens, don't report a keypress.
+		 */
+		budget_ci->ir.keydown = (budget_ci->ir.keydown << 1) | 1;
+		if ((budget_ci->ir.keydown != 3) && (code != IR_NO_DATA))
+			ir_input_keydown(dev, &budget_ci->ir.state, code, code);
+
+		/* (re)start a key-up timeout */
+		mod_timer(&budget_ci->ir.timeout,
+			  jiffies + HZ * IR_REPEAT_TIMEOUT / 1000);
+	}
+	else {
+		if (ir_debug)
+			printk (KERN_DEBUG "budget-ci: received key %02X address %02X\n",
+				budget_ci->ir.keycode & 0x3F, code & 0x1F);
+		budget_ci->ir.keycode = IR_NO_DATA;
 	}
 }
 
@@ -190,7 +219,7 @@
 {
 	struct saa7146_dev *saa = budget_ci->budget.dev;
 	struct input_dev *input_dev;
-	int i;
+	IR_KEYTAB_TYPE *keys;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
 	int error;
 #endif
@@ -226,10 +255,27 @@
 # 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:
+		budget_ci->ir.address = 0x1F;
+		keys = ir_codes_hauppauge_new; /* more keys defined than are physically present */
+		break;
+
+	default:	/* unknown or insufficient information - FIXME */
+		budget_ci->ir.address = IR_ADDRESS_ANY;
+		keys = ir_codes_budget_ci_old;
+		break;
+	}
+	ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5, keys);
+
+	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,7 +289,13 @@
 	input_register_device(input_dev);
 #endif
 
-	input_dev->timer.function = msp430_ir_debounce;
+	/* initialise our key-up timeout handler */
+	init_timer(&budget_ci->ir.timeout);
+	budget_ci->ir.timeout.function = msp430_ir_debounce;
+	budget_ci->ir.timeout.data = (unsigned long) &budget_ci->ir;
+
+	budget_ci->ir.keycode = IR_NO_DATA;
+	budget_ci->ir.last_edge = 255; /* can't happen */
 
 	saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
@@ -261,8 +313,8 @@
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
 
 	if (dev) {
-		if (del_timer(&dev->timer))
-			input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
+		if (del_timer(&budget_ci->ir.timeout))
+			ir_input_nokey(dev, &budget_ci->ir.state);
 		input_unregister_device(dev);
 	}
 }

-- 
| Darren Salt    | linux or ds at              | nr. Ashington, | Toon
| RISC OS, Linux | youmustbejoking,demon,co,uk | Northumberland | Army
|   <URL:http://www.youmustbejoking.demon.co.uk/progs.packages.html>

If you have a video recorder, there'll be three good programmes on at once.



More information about the linux-dvb mailing list