]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/media/dvb/ttpci/budget-ci.c
V4L/DVB (5335): Budget-ci: Use the repeat handling of the input subsystem
[net-next-2.6.git] / drivers / media / dvb / ttpci / budget-ci.c
index 464feaf1a9ad2401afbeeb686b0996b36765aa5d..4ed4599ce816b78be6c5f3527ceb9f84028a2e8e 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);
 }