[vdr] Hauppauge LIRC remote, FC3, buttons

Darren Salt linux at youmustbejoking.demon.co.uk
Fri Feb 25 03:10:48 CET 2005


I demand that Simon Baxter may or may not have written...

> I'm having some strange problems with my VDR keymaps on Xine (running FC3
> with a DVB Nova-T). I use the xine keymap editor to 'grab' keystrokes for
> the VDR buttons, but none of the coloured buttons (green, red, blue) are
> recognised?

I can't help with LIRC, but you *can* get this working with the remote plugin
and my patches (attached).

The -kernel patch is applicable to 2.6.x kernel source and the LinuxTV DVB
driver tarballs (1.1.0, 1.1.1 and possibly some older versions); the -linuxtv
patch is for DVB CVS (and *should* still be applicable; I've not checked
recently). For the record, these are based on the IR keymap interface in the
av7110 code.

The third patch is for the DVB utilities - you'll get an extra binary,
budget_ci_loadkeys, which you can use as follows (once you've loaded the
patched budget_ci module):

  # budget_ci_loadkeys hauppauge_grey.rc5 >/proc/budget_ci_ir

For those who are already using these patches: no need to update - the
patches are unchanged.

Debian testing/unstable users: these patches are present in dvb-utils 1.1.0-3
and dvb-driver-source 1.1.1-4 and later versions.

(BTW, you need to switch on text wrapping or to stop using OE.)

-- 
| Darren Salt | nr. Ashington, | d youmustbejoking,demon,co,uk
| Debian,     | Northumberland | s zap,tartarus,org
| RISC OS     | Toon Army      | @
|   Retrocomputing: a PC card in a Risc PC

Anything worth doing is worth overdoing.
-------------- next part --------------
--- linux/drivers/media/dvb/ttpci/budget-ci.c.orig	2003-11-20 10:50:15.000000000 +0000
+++ linux/drivers/media/dvb/ttpci/budget-ci.c	2004-09-27 22:16:19.000000000 +0100
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
+#include <linux/proc_fs.h>
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
 #include "input_fake.h"
@@ -181,10 +182,48 @@
 }
 
 
+static int budget_ci_ir_write_proc (struct file *file,
+				    const char __user *buffer,
+				    unsigned long count, void *data)
+{
+	/* adapted from av7110_ir.c */
+	char *page;
+	int i;
+	struct input_dev *input = (struct input_dev *)data;
+
+	if (count < sizeof (key_map))
+		return -EINVAL;
+	
+	page = (char *)vmalloc(sizeof (key_map));
+	if (!page)
+		return -ENOMEM;
+	
+	if (copy_from_user(page, buffer, sizeof (key_map))) {
+		vfree(page);
+		return -EFAULT;
+	}
+
+	memcpy (&key_map, page, sizeof (key_map));
+	vfree(page);
+
+	memset (input->keybit, 0, sizeof(input->keybit));
+
+	for (i=0; i<sizeof(key_map)/sizeof(key_map[0]); i++) {
+		if (key_map[i] > KEY_MAX)
+			key_map[i] = 0;
+		else if (key_map[i] > KEY_RESERVED)
+			set_bit (key_map[i], input->keybit);
+	}
+
+	return count;
+}
+
+
 static int msp430_ir_init (struct budget_ci *budget_ci)
 {
 	struct saa7146_dev *saa = budget_ci->budget.dev;
 	int i;
+	static struct proc_dir_entry *e;
 
 	memset(&budget_ci->input_dev, 0, sizeof(struct input_dev));
 
@@ -204,6 +243,13 @@
 
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); 
 
+	e = create_proc_entry ("budget_ci_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
+	if (e) {
+		e->write_proc = budget_ci_ir_write_proc;
+		e->data = &budget_ci->input_dev;
+		e->size = sizeof (key_map);
+	}
+
 	return 0;
 }
 
@@ -213,6 +259,8 @@
 	struct saa7146_dev *saa = budget_ci->budget.dev;
 	struct input_dev *dev = &budget_ci->input_dev;
 
+	remove_proc_entry ("budget_ci_ir", NULL);
+
 	saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
 	saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
-------------- next part --------------
--- linux/drivers/media/dvb/ttpci/budget-ci.c.orig	2004-09-20 17:37:46.000000000 +0100
+++ linux/drivers/media/dvb/ttpci/budget-ci.c	2004-10-17 22:02:12.000000000 +0100
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
+#include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 
 #include "dvb_ca_en50221.h"
@@ -234,10 +235,48 @@ static void msp430_ir_interrupt (unsigne
 	}
 }
 
+static int budget_ci_ir_write_proc (struct file *file,
+				    const char __user *buffer,
+				    unsigned long count, void *data)
+{
+	/* adapted from av7110_ir.c */
+	char *page;
+	int i;
+	struct input_dev *input = (struct input_dev *)data;
+
+	if (count < sizeof (key_map))
+		return -EINVAL;
+	
+	page = (char *)vmalloc(sizeof (key_map));
+	if (!page)
+		return -ENOMEM;
+	
+	if (copy_from_user(page, buffer, sizeof (key_map))) {
+		vfree(page);
+		return -EFAULT;
+	}
+
+	memcpy (&key_map, page, sizeof (key_map));
+	vfree(page);
+
+	memset (input->keybit, 0, sizeof(input->keybit));
+
+	for (i=0; i<sizeof(key_map)/sizeof(key_map[0]); i++) {
+		if (key_map[i] > KEY_MAX)
+			key_map[i] = 0;
+		else if (key_map[i] > KEY_RESERVED)
+			set_bit (key_map[i], input->keybit);
+	}
+
+	return count;
+}
+
+
 static int msp430_ir_init (struct budget_ci *budget_ci)
 {
 	struct saa7146_dev *saa = budget_ci->budget.dev;
 	int i;
+	static struct proc_dir_entry *e;
 
 	memset(&budget_ci->input_dev, 0, sizeof(struct input_dev));
 
@@ -258,6 +297,13 @@ static int msp430_ir_init (struct budget
 
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
 
+	e = create_proc_entry ("budget_ci_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
+	if (e) {
+		e->write_proc = budget_ci_ir_write_proc;
+		e->data = &budget_ci->input_dev;
+		e->size = sizeof (key_map);
+	}
+
 	return 0;
 }
 
@@ -266,6 +312,8 @@ static void msp430_ir_deinit (struct bud
 	struct saa7146_dev *saa = budget_ci->budget.dev;
 	struct input_dev *dev = &budget_ci->input_dev;
 
+	remove_proc_entry ("budget_ci_ir", NULL);
+
 	saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
 
-------------- next part --------------
diff -urNad linuxtv-dvb-apps-1.1.0/util/av7110_loadkeys/Makefile linuxtv-dvb-apps-1.1.0/util/av7110_loadkeys/Makefile
--- linuxtv-dvb-apps-1.1.0/util/av7110_loadkeys/Makefile	2004-09-27 20:48:23.000000000 +0100
+++ linuxtv-dvb-apps-1.1.0/util/av7110_loadkeys/Makefile	2004-09-27 20:48:39.000000000 +0100
@@ -1,14 +1,23 @@
 CC = gcc
-CFLAGS = -g -Wall -O2
+CFLAGS = -g -Wall -O2 -D_GNU_SOURCE
 
-all: av7110_loadkeys evtest
+all: av7110_loadkeys budget_ci_loadkeys evtest
 
 av7110_loadkeys: av7110_loadkeys.o
 
+budget_ci_loadkeys: budget_ci_loadkeys.o
+
 evtest: evtest.o
 
+av7110_loadkeys.o: CFLAGS += -UHW_MSP430
 av7110_loadkeys.o: av7110_loadkeys.c input_keynames.h
 
+budget_ci_loadkeys.c: av7110_loadkeys.c
+	ln av7110_loadkeys.c budget_ci_loadkeys.c
+
+budget_ci_loadkeys.o: CFLAGS += -DHW_MSP430
+budget_ci_loadkeys.o: budget_ci_loadkeys.c input_keynames.h
+
 evtest.o: evtest.c input_keynames.h
 
 
@@ -53,5 +62,6 @@
 
 
 clean:
-	$(RM) core* *.o input_keynames.h av7110_loadkeys evtest
+	$(RM) core* *.o input_keynames.h av7110_loadkeys budget_ci_loadkeys \
+		 budget_ci_loadkeys.c evtest
 
diff -urNad linuxtv-dvb-apps-1.1.0/util/av7110_loadkeys/av7110_loadkeys.c linuxtv-dvb-apps-1.1.0/util/av7110_loadkeys/av7110_loadkeys.c
--- linuxtv-dvb-apps-1.1.0/util/av7110_loadkeys/av7110_loadkeys.c	2004-09-27 20:48:23.000000000 +0100
+++ linuxtv-dvb-apps-1.1.0/util/av7110_loadkeys/av7110_loadkeys.c	2004-09-27 20:48:23.000000000 +0100
@@ -1,5 +1,6 @@
 #include <asm/types.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <unistd.h>
 #include <sys/mman.h>
 #include <sys/types.h>
@@ -111,12 +112,20 @@
 
 
 
+#ifdef HW_MSP430
+const char usage [] = "\n\tusage: budget_ci_loadkeys keymap_filename.rc5\n\n";
+#else
 const char usage [] = "\n\tusage: av7110_loadkeys [-i|--invert] [-a|--address <num>] keymap_filename.(rc5|rcmm)\n\n";
-
+#endif
 
 struct ir_setup {
+#ifdef HW_MSP430
+#define KEYTAB_SIZE 64
+#else
+#define KEYTAB_SIZE 256
 	__u32 ir_config;
-	__u16 keytab [256];
+#endif
+	__u16 keytab [KEYTAB_SIZE];
 } __attribute__ ((packed));
 
 
@@ -128,7 +137,10 @@
 	char *buf, *pos, *fname = NULL;
 
 	for (i=1; i<argc; i++) {
+#ifndef HW_MSP430
+		/* AV7110 only; not MSP430 */
 		if (!strcmp("-i", argv[i]) || !strcmp("--invert", argv[i]))
+			
 			setup.ir_config |= 0x8000;
 		else if (!strcmp("-a", argv[i]) || !strcmp("--address", argv[i])) {
 			if (++i < argc) {
@@ -136,6 +148,7 @@
 				setup.ir_config |= 0x4000;
 			}
 		} else
+#endif
 			fname = argv[i];
 	}
 
@@ -144,6 +157,14 @@
 		exit (-1);
 	}
 
+#ifdef HW_MSP430
+	if (strncmp(".rc5", fname + strlen(fname) - 4, 4) != 0) {
+		const char msg [] = "\nERROR: "
+			"input filename must have suffix .rc5\n";
+		write (0, msg, strlen(msg));
+		exit (-1);
+	}
+#else
 	if (strncmp(".rcmm", fname + strlen(fname) - 5, 5) == 0)
 		setup.ir_config |= 0x0001;
 	else if (strncmp(".rc5", fname + strlen(fname) - 4, 4) != 0) {
@@ -152,6 +173,7 @@
 		write (0, msg, strlen(msg));
 		exit (-1);
 	}
+#endif
 
 	if ((fd = open (fname, O_RDONLY)) < 0)
 		print_error ("open", fname);
@@ -173,9 +195,11 @@
 		key = strtol (pos, &pos, 0);
 		keycode = parse_keyname (pos, &pos, buf + len - pos);
 
-		if (key < 0 || key > 0xff) {
-			const char msg [] = 
-				"\nERROR: key must be in range 0 ... 0xff!\n\n";
+		if (key < 0 || key >= KEYTAB_SIZE) {
+			char *msg;
+			asprintf (&msg,
+				"\nERROR: key must be in range 0 ... 0x%02x!\n\n",
+				KEYTAB_SIZE);
 
 			write (0, msg, strlen(msg));
 			exit (-1);
@@ -190,7 +214,7 @@
 	munmap (buf, len);
 	close (fd);
 
-	write (1, &setup, 4 + 256 * sizeof(__u16));
+	write (1, &setup, sizeof (setup));
 
 	return 0;
 }


More information about the vdr mailing list