[PATCH][RESEND] Make budget-ci use ir-common and make ir-common aware of repeat events

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This message is in MIME format which your mailer apparently does not support.
You either require a newer version of your software which supports MIME, or
a separate MIME decoding utility.  Alternatively, ask the sender of this
message to resend it in a different format.

--92259591--1668213989--329508527
Content-Type: text/plain; charset
Patch attached. It's applicable to current repository content.

I'm interested in knowing which budget cards have remote controls which are
compatible and provide either working output *or* dmesg output when keys are
pressed. If you have a card which is (or can be) driven by the budget-ci
module and for which a remote control interface is reported, you can add the
low half-word of the card's PCI subsystem ID as shown in the following
example (untested, since I only have a Nova-T):

--- a/linux/drivers/media/ttpci/budget-ci.c
+++ b/linux/drivers/media/ttpci/budget-ci.c
@@ -220,6 +220,7
 	/* Select keymap */
 	switch (budget_ci->budget.dev->pci->subsystem_device) {
 	case 0x1011:    /* Hauppauge/TT Nova-T budget (tda10045/Philips tdm13+	case 0x1017:	/* Hauppauge/TT Nova-S/CI budget */
16l(tda6651tt) + TDA9889) */
 		keys = ir_codes_hauppauge_new; /* more keys defined than are physically present */
 		break;
 

If, with that patch (modified, if needed, for your card), you have a
fully-working remote control *or* you're seeing messages like
  budget-ci: received key 04 address 1E
in dmesg output (and, possibly, /var/log/debug) then I'd like to know. In the
case of dmesg output, the range of key values and the range of address values
are both important and should be reported.

-- 
| Darren Salt | d youmustbejoking,demon,co,uk | nr. Ashington,
| Debian,     | s zap,tartarus,org            | Northumberland
| RISC OS     | @                             | Toon Army
|   I don't ask for much, just untold riches...

Do not lend money to a fiend.

--92259591--1668213989--329508527
Content-Type: text/plain; charsetContent-Disposition: attachment; filenameContent-Transfer-Encoding: quoted-printable

budget-ci: make it use ir-common and make ir-common aware of repeat events
From: Darren Salt <linux@xxxxxxxxxxxxxxxxxxxxxxxxxxx>

budget-ci changes:

Allocate enough space for the device name.
Supply a device name (for id by means other than the device node name).

Retype key_map[], and rename it ready for later removal from budget-ci.c.

Use the correct keymap for Nova-T remote controls.

Make the repeat period equal to that of the remote control, i.e. generate a
key event for every received signal - but not the *first* repeated signal
because that could be coming from a Zenith remote control. Also, the initial
repeat delay being longer is generally useful.

The driver now expects two bytes for each button press or repeat.
It must quickly process the first byte, else it risks missing the second.

The second byte contains a partial address; require (byte & 0x1F) == 0x1F,
at least for known Hauppauge devices.

Output debug information concerning unrecognised addresses.


ir-common changes:

Assume that ir->keypressed is always valid, specifically 0, 1 or 2.

Make ir_input_keydown aware of repeat events.


Kconfig:

Cause ir-common to be built if budget-ci is built.


Signed-off-by: Darren Salt <linux@xxxxxxxxxxxxxxxxxxxxxxxxxxx>

diff -r e0b2792a1f00 linux/drivers/media/common/ir-functions.c
--- a/linux/drivers/media/common/ir-functions.c	Mon Feb  6 16:04:08 2006
+++ b/linux/drivers/media/common/ir-functions.c	Mon Feb  6 17:18:51 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 -r e0b2792a1f00 linux/drivers/media/dvb/ttpci/budget-ci.c
--- a/linux/drivers/media/dvb/ttpci/budget-ci.c	Mon Feb  6 16:04:08 2006
+++ b/linux/drivers/media/dvb/ttpci/budget-ci.c	Mon Feb  6 17:18:51 2006
@@ -4,6 +4,7 @@
  * Compiled from various sources by Michael Hunold <michael@xxxxxxx>
  *
  *     msp430 IR support contributed by Jack Thomasson <jkt@xxxxxxxxxx>
+ *     modified to use ir-common by Darren Salt <linux@xxxxxxxxxxxxxxxxxxxxxxxxxxx>
  *     partially based on the Siemens DVB driver by Ralph+Marcus Metzler
  *
  * CI interface support (c) 2004 Andrew de Quincey <adq_dvb@xxxxxxxxxxxxx>
@@ -37,6 +38,8 @@
 #include <linux/interrupt.h>
 #include <linux/input.h>
 #include <linux/spinlock.h>
+#include <linux/version.h>
+#include <media/ir-common.h>
 
 #include "dvb_ca_en50221.h"
 #include "stv0299.h"
@@ -62,23 +65,40 @@
 #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
+
+struct budget_ci_ir {
+	struct input_dev *dev;
+	struct ir_input_state state;
+	char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
+	char phys[32];
+	struct timer_list timeout; /* key-up */
+	u8 keycode;
+	u8 keydown;
+	u8 last_edge;
+};
+#define IR_NO_DATA (u8)(0x80)
+
 struct budget_ci {
 	struct budget budget;
-	struct input_dev *input_dev;
 	struct tasklet_struct msp430_irq_tasklet;
 	struct tasklet_struct ciintf_irq_tasklet;
 	int slot_status;
 	struct dvb_ca_en50221 ca;
-	char ir_dev_name[50];
+	struct budget_ci_ir ir;
 	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] = {
+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,
@@ -129,52 +149,52 @@
 
 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)
 {
 	struct budget_ci *budget_ci = (struct budget_ci *) data;
-	struct input_dev *dev = budget_ci->input_dev;
+	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);
+		budget_ci->ir.keycode = code & 0x3F;
+		return;
+	}
+	else if ((code & 0x1F) == 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 {
+		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;
 	}
 }
 
@@ -182,43 +202,94 @@
 {
 	struct saa7146_dev *saa = budget_ci->budget.dev;
 	struct input_dev *input_dev;
-	int i;
-
-	budget_ci->input_dev = input_dev = input_allocate_device();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+	int error;
+#endif
+	IR_KEYTAB_TYPE *keys;
+
+	budget_ci->ir.dev = input_dev = input_allocate_device();
 	if (!input_dev)
+	{
+		printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
 		return -ENOMEM;
-
-	sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
-
-	input_dev->name = budget_ci->ir_dev_name;
-
-	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);
-
-	input_register_device(budget_ci->input_dev);
-
-	input_dev->timer.function = msp430_ir_debounce;
+	}
+
+	snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name), "Budget-CI dvb ir receiver %s", saa->name);
+	snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys), "pci-%s/ir0", pci_name(saa->pci));
+
+	/* Select keymap */
+	switch (budget_ci->budget.dev->pci->subsystem_device) {
+	case 0x1011:    /* Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889) */
+		keys = ir_codes_hauppauge_new; /* more keys defined than are physically present */
+		break;
+
+	default:	/* unknown or insufficient information - FIXME */
+		keys = ir_codes_budget_ci_old;
+		break;
+	}
+	ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5, keys);
+
+	input_dev->name = budget_ci->ir.name;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	input_dev->phys = budget_ci->ir.phys;   
+	input_dev->id.bustype = BUS_PCI;
+	input_dev->id.version = 1;
+	if (saa->pci->subsystem_vendor) {
+		input_dev->id.vendor = saa->pci->subsystem_vendor;
+		input_dev->id.product = saa->pci->subsystem_device;
+	} else {
+		input_dev->id.vendor = saa->pci->vendor;
+		input_dev->id.product = saa->pci->device;
+	}
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+	input_dev->cdev.dev = &saa->pci->dev;
+# else
+	input_dev->dev = &saa->pci->dev;
+# endif
+#endif
+
+	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);
+	if (error) {
+		input_free_device(input_dev);
+		budget_ci->ir.dev = NULL;
+		printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
+		return error;
+	}
+#else
+	input_register_device(input_dev);
+#endif
 
 	saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
 
+	/* 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 */
+
+	printk("budget_ci: IR interface initialised\n");
 	return 0;
 }
 
 static void msp430_ir_deinit(struct budget_ci *budget_ci)
 {
 	struct saa7146_dev *saa = budget_ci->budget.dev;
-	struct input_dev *dev = budget_ci->input_dev;
 
 	saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
 
-	if (del_timer(&dev->timer))
-		input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
-
-	input_unregister_device(dev);
+	if (budget_ci->ir.dev) {
+		if (del_timer(&budget_ci->ir.timeout))
+			ir_input_nokey(budget_ci->ir.dev, &budget_ci->ir.state);
+		input_unregister_device(budget_ci->ir.dev);
+	}
 }
 
 static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
@@ -1093,7 +1164,7 @@
 	struct budget_ci *budget_ci;
 	int err;
 
-	if (!(budget_ci = kmalloc(sizeof(struct budget_ci), GFP_KERNEL)))
+	if (!(budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL)))
 		return -ENOMEM;
 
 	dprintk(2, "budget_ci: %p\n", budget_ci);
diff -r 3843c1bf83c4 linux/drivers/media/dvb/ttpci/Kconfig
--- a/linux/drivers/media/dvb/ttpci/Kconfig	Wed Feb  8 01:19:25 2006
+++ b/linux/drivers/media/dvb/ttpci/Kconfig	Wed Feb  8 01:19:40 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

--92259591--1668213989--329508527--

_______________________________________________

linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb


[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux