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; }