V4L/DVB (5335): Budget-ci: Use the repeat handling of the input subsystem
authorDavid Härdeman <david@hardeman.nu>
Fri, 27 Apr 2007 15:31:22 +0000 (12:31 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Fri, 27 Apr 2007 18:43:46 +0000 (15:43 -0300)
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 Hardeman <david@hardeman.nu>
Signed-off-by: Oliver Endriss <o.endriss@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/dvb/ttpci/budget-ci.c

index 464feaf..4ed4599 100644 (file)
 #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);
 MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
@@ -99,10 +93,14 @@ MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
 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;
+       bool have_command;
 };
 
 struct budget_ci {
@@ -125,13 +123,8 @@ static void msp430_ir_interrupt(unsigned long data)
 {
        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 +136,7 @@ static void msp430_ir_interrupt(unsigned long data)
         * 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 +145,35 @@ static void msp430_ir_interrupt(unsigned long data)
        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;
+       budget_ci->ir.have_command = false;
 
-       if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device)
+       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))
-               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 {
+       /* 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);
+               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)
@@ -271,16 +246,21 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
                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);
 
@@ -304,10 +284,8 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci)
        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);
 }