[linux-dvb] [PATCH] Allow budget-ci to only listen to certain IR devices

David Härdeman david at hardeman.nu
Thu Sep 28 00:48:56 CEST 2006


The attached patch changes the IR function in budget-ci so that it reads 
all IR sequences from the MSP430 chip. This allows the code to ignore 
invalid RC5 codes and also allows it to decide which RC5 device code was 
used to send the command (which would fix the problem of using multiple 
RC5 remotes [0]).

Per default the driver still listens to commands from all devices, but 
using the ir_device parameter, it is possible to limit it to a single 
device (which is a good thing if there are other RC5 devices nearby).

Compiled and tested with a programmable remote using a number of 
different RC5 device codes.

This patch needs to be applied on top of the dynamic keymap patch posted 
earlier[1].

Patch included this time :)

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

[0] http://www.linuxtv.org/mailinglists/linux-dvb/2004/03-2004/msg00721.html
[1] http://www.linuxtv.org/pipermail/linux-dvb/2006-September/013100.html

-- 
David Härdeman
-------------- next part --------------
diff -ur linux-old/drivers/media/dvb/ttpci/budget-ci.c linux/drivers/media/dvb/ttpci/budget-ci.c
--- linux-old/drivers/media/dvb/ttpci/budget-ci.c	2006-09-26 17:12:41.000000000 +0200
+++ linux/drivers/media/dvb/ttpci/budget-ci.c	2006-09-27 23:11:25.000000000 +0200
@@ -65,6 +65,17 @@
 #define SLOTSTATUS_READY	8
 #define SLOTSTATUS_OCCUPIED	(SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
 
+#define IR_RECV_NONE		0
+#define IR_RECV_DEVICE		1
+#define IR_RECV_CMD1		2
+#define IR_RECV_CMD2		4
+#define IR_RECV_ALL		(IR_RECV_DEVICE|IR_RECV_CMD1|IR_RECV_CMD2)
+
+static int ir_device = -1;
+module_param(ir_device, int, 0644);
+MODULE_PARM_DESC(ir_device, 
+		 "Listen to IR commands from given device (0 - 31, default: all).");
+
 struct budget_ci {
 	struct budget budget;
 	struct input_dev *input_dev;
@@ -150,36 +161,87 @@
 {
 	struct budget_ci *budget_ci = (struct budget_ci *) data;
 	struct input_dev *dev = budget_ci->input_dev;
-	unsigned int code =
+	static unsigned int code1;
+	static unsigned int code2;
+	static unsigned int device;
+	static int status = IR_RECV_NONE;
+	unsigned int command = 
 		ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
 
-	if (code & 0x40) {
-		code &= 0x3f;
+	/*
+	 * Theory of operation
+	 * ===================
+	 * (from http://home.tiscali.nl/m.majoor/DVBSHardware.pdf)
+	 * 
+	 * The msp430 generates three different sequences, each one byte:
+	 * 0x00 <= data < 0x40 = device and toggle information 
+	 * 0x40 <= data < 0x80 = command 1
+	 * 0x80 <= data < 0xc0 = invalid
+	 * 0xc0 <= data < 0xff = command 2
+	 * 
+	 * The device and toggle information byte has the following bit structure:
+	 * 00TDDDDD, T is the RC5 toggle bit, D are the device code bits (0 - 31)
+	 *
+	 * The command bytes have the following bit structure:
+	 * X1CCCCCC, X signifies command 1 or 2, C are the command code bits (0 - 63)
+	 * 
+	 * The order of the sequences can vary, but a command is only sucessfully
+	 * received once all three have appeared at least once, and when the command 1
+	 * and command 2 commands match.
+	 */
+
+	if (command < 0x40) {
+		/* Device and toggle information */
+		device = command & 0x1f;
+		status |= IR_RECV_DEVICE;
+		dprintk(2, "budget_ci: IR data (device code) - %02x\n", device);
+	} else if (command < 0x80) {
+		/* Command 1 */
+		code1 = command - 0x40;
+		dprintk(2, "budget_ci: IR data (command 1) - %02x\n", code1);
+		status |= IR_RECV_CMD1;
+	} else if (command >= 0xc0 && command <= 0xff) {
+		/* Command 2 */
+		code2 = command - 0xc0;
+		dprintk(2, "budget_ci: IR data (command 2) - %02x\n", code2);
+		status |= IR_RECV_CMD2;
+	} else {
+		/* Invalid */
+		printk("budget_ci: invalid IR data - %02x\n", command);
+	}
 
-		if (timer_pending(&dev->timer)) {
-			if (code == dev->repeat_key) {
-				++dev->rep[0];
-				return;
-			}
-			del_timer(&dev->timer);
-			input_report_key(dev, INPUT_KEYCODE(dev, dev->repeat_key), 0);
-		}
+	if (status != IR_RECV_ALL || code1 != code2)
+		return;
 
-		if (!INPUT_KEYCODE(dev, code)) {
-			printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
+	dprintk(2, "budget_ci: IR key - dev %02x, command %02x\n", device, code1);
+	status = IR_RECV_NONE;
+
+	if (ir_device >= 0 && ir_device != device)
+		return;
+
+	if (timer_pending(&dev->timer)) {
+		if (code1 == dev->repeat_key) {
+			++dev->rep[0];
 			return;
 		}
+		del_timer(&dev->timer);
+		input_report_key(dev, INPUT_KEYCODE(dev, dev->repeat_key), 0);
+	}
 
-		/* 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_report_key(dev, INPUT_KEYCODE(dev, dev->repeat_key), !0);
-		add_timer(&dev->timer);
+	if (!INPUT_KEYCODE(dev, code1)) {
+		printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code1);
+		return;
 	}
+
+	/* initialize debounce and repeat */
+	dev->repeat_key = code1;
+	/* Zenith remote _always_ sends 2 sequences */
+	dev->rep[0] = ~0;
+	/* 350 milliseconds */
+	dev->timer.expires = jiffies + HZ * 350 / 1000;
+	/* MAKE */
+	input_report_key(dev, INPUT_KEYCODE(dev, dev->repeat_key), !0);
+	add_timer(&dev->timer);
 }
 
 static int msp430_ir_init(struct budget_ci *budget_ci)


More information about the linux-dvb mailing list