[PATCH] Implement repeat key handling in budget-ci IR

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

 



The attached patch contains the last set of changes to the budget-ci IR handling which makes it use the repeat handling of the input subsystem. This allows some code simplification, makes sure that repeat key presses are reported as such and also allows the "debounce" hack to be removed altogether.

In addition a couple of static variables were removed which would have confused the IR code if more than one card is used.

Signed-off-by: David Härdeman <david@xxxxxxxxxxx>

--
David Härdeman
diff -r 5884d8239fe1 linux/drivers/media/dvb/ttpci/budget-ci.c
--- a/linux/drivers/media/dvb/ttpci/budget-ci.c	Sun Feb 18 23:10:14 2007 -0200
+++ b/linux/drivers/media/dvb/ttpci/budget-ci.c	Tue Feb 20 01:39:48 2007 +0100
@@ -73,20 +73,14 @@
 #define SLOTSTATUS_READY	8
 #define SLOTSTATUS_OCCUPIED	(SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
 
-/* Milliseconds during which key presses are regarded as key repeat and during
- * which the debounce logic is active
+/* 
+ * Milliseconds during which a key is regarded as pressed.
+ * If an identical command arrives within this time, the timer will start over.
  */
-#define IR_REPEAT_TIMEOUT	350
+#define IR_KEYPRESS_TIMEOUT	250
 
 /* RC5 device wildcard */
 #define IR_DEVICE_ANY		255
-
-/* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two),
- * this setting allows the superflous sequences to be ignored
- */
-static int debounce = 0;
-module_param(debounce, int, 0644);
-MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)");
 
 static int rc5_device = -1;
 module_param(rc5_device, int, 0644);
@@ -99,11 +93,24 @@ struct budget_ci_ir {
 struct budget_ci_ir {
 	struct input_dev *dev;
 	struct tasklet_struct msp430_irq_tasklet;
+	struct timer_list timer_keyup;
 	char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
 	char phys[32];
 	struct ir_input_state state;
 	int rc5_device;
+	u32 last_raw;
+	u32 ir_key;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+	bool have_command;
 };
+#else
+	int have_command;
+};
+enum {
+	false	= 0,
+	true	= 1
+};
+#endif
 
 struct budget_ci {
 	struct budget budget;
@@ -125,13 +132,8 @@ static void msp430_ir_interrupt(unsigned
 {
 	struct budget_ci *budget_ci = (struct budget_ci *) data;
 	struct input_dev *dev = budget_ci->ir.dev;
-	static int bounces = 0;
-	int device;
-	int toggle;
-	static int prev_toggle = -1;
-	static u32 ir_key;
-	static int state = 0;
 	u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
+	u32 raw;
 
 	/*
 	 * The msp430 chip can generate two different bytes, command and device
@@ -143,7 +145,7 @@ static void msp430_ir_interrupt(unsigned
 	 * bytes and one or more device bytes. For the repeated bytes, the
 	 * highest bit (X) is set. The first command byte is always generated
 	 * before the first device byte. Other than that, no specific order
-	 * seems to apply.
+	 * seems to apply. To make life interesting, bytes can also be lost.
 	 *
 	 * Only when we have a command and device byte, a keypress is
 	 * generated.
@@ -152,53 +154,35 @@ static void msp430_ir_interrupt(unsigned
 	if (ir_debug)
 		printk("budget_ci: received byte 0x%02x\n", command);
 
-	/* Is this a repeated byte? */
-	if (command & 0x80)
-		return;
+	/* Remove repeat bit, we use every command */
+	command = command & 0x7f;
 
 	/* Is this a RC5 command byte? */
 	if (command & 0x40) {
-		state = 1;
-		ir_key = command & 0x3f;
+		budget_ci->ir.have_command = true;
+		budget_ci->ir.ir_key = command & 0x3f;
 		return;
 	}
 
 	/* It's a RC5 device byte */
-	if (!state)
+	if (!budget_ci->ir.have_command)
 		return;
-	state = 0;
-	device = command & 0x1f;
-	toggle = command & 0x20;
-
-	if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device)
+	budget_ci->ir.have_command = false;
+
+	if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
+	    budget_ci->ir.rc5_device != (command & 0x1f))
 		return;
 
-	/* Ignore repeated key sequences if requested */
-	if (toggle == prev_toggle && ir_key == dev->repeat_key &&
-	    bounces > 0 && timer_pending(&dev->timer)) {
-		if (ir_debug)
-			printk("budget_ci: debounce logic ignored IR command\n");
-		bounces--;
-		return;
-	}
-	prev_toggle = toggle;
-
-	/* Are we still waiting for a keyup event? */
-	if (del_timer(&dev->timer))
+	/* Is this a repeated key sequence? (same device, command, toggle) */
+	raw = budget_ci->ir.ir_key | (command << 8);
+	if (budget_ci->ir.last_raw != raw || !timer_pending(&budget_ci->ir.timer_keyup)) {
 		ir_input_nokey(dev, &budget_ci->ir.state);
-
-	/* Generate keypress */
-	if (ir_debug)
-		printk("budget_ci: generating keypress 0x%02x\n", ir_key);
-	ir_input_keydown(dev, &budget_ci->ir.state, ir_key, (ir_key & (command << 8)));
-
-	/* Do we want to delay the keyup event? */
-	if (debounce) {
-		bounces = debounce;
-		mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT));
-	} else {
-		ir_input_nokey(dev, &budget_ci->ir.state);
-	}
+		ir_input_keydown(dev, &budget_ci->ir.state, 
+				 budget_ci->ir.ir_key, raw);
+		budget_ci->ir.last_raw = raw;
+	}
+
+	mod_timer(&budget_ci->ir.timer_keyup, jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT));
 }
 
 static int msp430_ir_init(struct budget_ci *budget_ci)
@@ -277,16 +261,21 @@ static int msp430_ir_init(struct budget_
 		break;
 	}
 
-	/* initialise the key-up debounce timeout handler */
-	input_dev->timer.function = msp430_ir_keyup;
-	input_dev->timer.data = (unsigned long) &budget_ci->ir;
-
+	/* initialise the key-up timeout handler */
+	init_timer(&budget_ci->ir.timer_keyup);
+	budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
+	budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
+	budget_ci->ir.last_raw = 0xffff; /* An impossible value */
 	error = input_register_device(input_dev);
 	if (error) {
 		printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
 		goto out2;
 	}
 
+	/* note: these must be after input_register_device */
+	input_dev->rep[REP_DELAY] = 400;
+	input_dev->rep[REP_PERIOD] = 250;
+
 	tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
 		     (unsigned long) budget_ci);
 
@@ -310,10 +299,8 @@ static void msp430_ir_deinit(struct budg
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
 	tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
 
-	if (del_timer(&dev->timer)) {
-		ir_input_nokey(dev, &budget_ci->ir.state);
-		input_sync(dev);
-	}
+	del_timer_sync(&dev->timer);
+	ir_input_nokey(dev, &budget_ci->ir.state);
 
 	input_unregister_device(dev);
 }
_______________________________________________
linux-dvb mailing list
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