[media] em28xx: add debouncing mechanism for GPI-connected buttons
authorFrank Schaefer <fschaefer.oss@googlemail.com>
Sun, 1 Dec 2013 21:06:53 +0000 (18:06 -0300)
committerMauro Carvalho Chehab <m.chehab@samsung.com>
Tue, 10 Dec 2013 18:11:28 +0000 (16:11 -0200)
So far, the driver only supports a snapshot button which is assigned to
register 0x0c bit 5. This special port has a built-in debouncing mechanism.
For buttons connected to ordinary GPI ports, this patch implements a software
debouncing mechanism.

Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/media/usb/em28xx/em28xx-input.c
drivers/media/usb/em28xx/em28xx.h

index 20c6a8ae14621ea8d822736b0f49fe8fd7979be2..ebc538730e07b38d3a39903bf98b03e6de8bf8d0 100644 (file)
@@ -479,7 +479,7 @@ static void em28xx_query_buttons(struct work_struct *work)
                container_of(work, struct em28xx, buttons_query_work.work);
        u8 i, j;
        int regval;
-       bool pressed;
+       bool is_pressed, was_pressed;
 
        /* Poll and evaluate all addresses */
        for (i = 0; i < dev->num_button_polling_addresses; i++) {
@@ -497,12 +497,21 @@ static void em28xx_query_buttons(struct work_struct *work)
                                j++;
                                continue;
                        }
-                       /* Determine if button is pressed */
-                       pressed = regval & button->mask;
-                       if (button->inverted)
-                               pressed = !pressed;
+                       /* Determine if button is and was pressed last time */
+                       is_pressed = regval & button->mask;
+                       was_pressed = dev->button_polling_last_values[i]
+                                      & button->mask;
+                       if (button->inverted) {
+                               is_pressed = !is_pressed;
+                               was_pressed = !was_pressed;
+                       }
+                       /* Clear button state (if needed) */
+                       if (is_pressed && button->reg_clearing)
+                               em28xx_write_reg(dev, button->reg_clearing,
+                                                (~regval & button->mask)
+                                                   | (regval & ~button->mask));
                        /* Handle button state */
-                       if (!pressed) {
+                       if (!is_pressed || was_pressed) {
                                j++;
                                continue;
                        }
@@ -518,14 +527,11 @@ static void em28xx_query_buttons(struct work_struct *work)
                        default:
                                WARN_ONCE(1, "BUG: unhandled button role.");
                        }
-                       /* Clear button state (if needed) */
-                       if (button->reg_clearing)
-                               em28xx_write_reg(dev, button->reg_clearing,
-                                                (~regval & button->mask)
-                                                   | (regval & ~button->mask));
                        /* Next button */
                        j++;
                }
+               /* Save current value for comparison during the next polling */
+               dev->button_polling_last_values[i] = regval;
        }
        /* Schedule next poll */
        schedule_delayed_work(&dev->buttons_query_work,
@@ -611,6 +617,8 @@ static void em28xx_init_buttons(struct em28xx *dev)
 
        /* Start polling */
        if (dev->num_button_polling_addresses) {
+               memset(dev->button_polling_last_values, 0,
+                                              EM28XX_NUM_BUTTON_ADDRESSES_MAX);
                INIT_DELAYED_WORK(&dev->buttons_query_work,
                                                          em28xx_query_buttons);
                schedule_delayed_work(&dev->buttons_query_work,
index e185d00e904484c0a8aaa5d60ede5f417710eeb1..df828c68ef4489f95e81d0011131dcef30ec4f1c 100644 (file)
@@ -669,6 +669,7 @@ struct em28xx {
        /* Button state polling */
        struct delayed_work buttons_query_work;
        u8 button_polling_addresses[EM28XX_NUM_BUTTON_ADDRESSES_MAX];
+       u8 button_polling_last_values[EM28XX_NUM_BUTTON_ADDRESSES_MAX];
        u8 num_button_polling_addresses;
        /* Snapshot button input device */
        char snapshot_button_path[30];  /* path of the input dev */